Backend Server

This is the backend server for Clones. It handles database operations and API endpoints.

Getting Started

First, clone the repository to your local machine:

git clone https://github.com/clones-ai/clones-backend.git
cd backend

Environment Setup

Before running the backend, you need to configure your environment variables.

  1. In the root of the backend project, locate the env.example file.
  2. Create a copy of this file and name it .env.
cp .env.example .env
  1. The .env file is included in .gitignore and should not be committed to version control.
  2. Open the .env file and fill in the required values. At a minimum, you must provide:
  • OPENAI_API_KEY: Your key for OpenAI services.
  • DEPOSIT_KEY_ENCRYPTION_SECRET and DEPOSIT_KEY_ENCRYPTION_SALT: These are critical for securing user funds. For local development, you can generate them with the following commands:
# For the secret key
openssl rand -base64 32

# For the salt
openssl rand -base64 16

The other variables can usually be left with their default values for a standard local setup.

Here is an example of what the top of your .env file should look like:

# --- OpenAI ---
OPENAI_API_KEY=your_openai_api_key_here

# --- Security - See README.md ---
# Generate with: openssl rand -base64 32
DEPOSIT_KEY_ENCRYPTION_SECRET=
# Generate with: openssl rand -base64 16
DEPOSIT_KEY_ENCRYPTION_SALT=

# --- Base Blockchain (EVM) ---
# Use Base Sepolia for development, Base Mainnet for production.
# Sepolia (testnet):
RPC_URL=https://sepolia.base.org
# Mainnet (production):
# RPC_URL=https://mainnet.base.org

# Optional (some tooling may use these)
# BASE_NETWORK=sepolia
# BASE_CHAIN_ID=84532  # Mainnet is 8453
# Block explorers: https://sepolia.basescan.org (testnet), https://basescan.org (mainnet)

# --- Mongodb ----
DB_URI=mongodb://admin:admin@mongodb:27017/dev?authSource=admin

Official Base RPC endpoints and chain IDs: Mainnet 8453 @ https://mainnet.base.org, Sepolia 84532 @ https://sepolia.base.org. ([Base][1])

Security

Critical: Private Key Encryption

To protect user funds, all depositPrivateKey values for training pools are encrypted before being stored in the database. This is a critical security measure to prevent fund theft in the event of a database breach.

The encryption is handled by the src/services/security/crypto.ts module, which uses the AES-256-GCM algorithm.

Environment Variables

The entire security mechanism relies on two critical environment variables, which must be set up as described in the Environment Setup section:

  • DEPOSIT_KEY_ENCRYPTION_SECRET: The Master Encryption Key.
  • DEPOSIT_KEY_ENCRYPTION_SALT: A cryptographic salt used to derive the encryption key from the master key.

Never commit these values to version control.

Running with Docker

The backend runs inside a Docker container. Use docker compose to manage the service from the root of the backend project.

# Start the services in detached mode
docker compose up -d

# View logs for the backend service
docker compose logs -f backend

# Execute a command inside the backend container
docker exec backend npm run <command>

# Stop and remove the services
docker compose down

Creating Development Tokens

To test features involving ERC‑20 tokens on Base, you may need to create your own development tokens on the Base Sepolia testnet. This guide explains how to deploy and mint a token for local development.

1. Prerequisites

Ensure you have:

  • Node.js (LTS) and npm
  • Hardhat toolchain in a local project (we’ll initialize one below)

(You can use Foundry if you prefer; the steps are shown with Hardhat.)

2. Configure Base (Sepolia) access

Create a new folder for a throwaway token project and set up Hardhat:

mkdir erc20-demo && cd erc20-demo
npm init -y
npm install --save-dev hardhat@2.26.3 @nomicfoundation/hardhat-toolbox@6.1.0
npm install dotenv @openzeppelin/contracts
npx hardhat init # choose "Create a JavaScript project"
// Let Hardhat project default root
// Add .gitignore file 

Create a .env in this folder with your deployer EVM private key (use a test key) and your Base Sepolia RPC:

RPC_URL=https://sepolia.base.org
PRIVATE_KEY=0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

You can request Base Sepolia test ETH from official faucets. ([Base][https://docs.base.org/base-chain/tools/network-faucets], [Coinbase][https://www.coinbase.com/fr-fr/developer-platform/products/faucet], [Coinbase Développeur Docs][https://docs.cdp.coinbase.com/faucets/introduction/welcome])

In hardhat.config.js add a baseSepolia network:

require("@nomicfoundation/hardhat-toolbox");
require("dotenv").config();

module.exports = {
  solidity: "0.8.28",
  networks: {
    baseSepolia: {
      url: process.env.RPC_URL,
      accounts: [process.env.PRIVATE_KEY],
      chainId: 84532
    }
  }
};

Chain ID 84532 is Base Sepolia. ([Base][https://docs.base.org/base-chain/quickstart/connecting-to-base])

3. Fund Your Wallet

You'll need Base Sepolia ETH to pay for gas.

# Visit a faucet and send test ETH to your deployer address
# (e.g., Coinbase Developer Platform faucet)

See the Base docs faucet list for options. ([Base][https://docs.base.org/base-chain/tools/network-faucets])

4. Create a New Token

Create contracts/DevToken.sol:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract DevToken is ERC20, Ownable {
    constructor(address initialRecipient, uint256 initialSupply)
        ERC20("DevToken", "DEV")
        Ownable(msg.sender)
    {
        // Mint initial supply to the recipient
        _mint(initialRecipient, initialSupply);
    }

    // Optional: allow the owner to mint more tokens later
    function mint(address to, uint256 amount) external onlyOwner {
        _mint(to, amount);
    }
}

Create scripts/deploy.js:

const hre = require("hardhat");

async function main() {
  const [deployer] = await hre.ethers.getSigners();

  const DevToken = await hre.ethers.getContractFactory("DevToken");
  // Mint 1,000 DEV with 18 decimals to the deployer:
  const initialSupply = hre.ethers.parseUnits("1000", 18);
  const token = await DevToken.deploy(deployer.address, initialSupply);
  await token.waitForDeployment();

  console.log("Token deployed to:", await token.getAddress());
}

main().catch((e) => {
  console.error(e);
  process.exit(1);
});

Deploy to Base Sepolia:

npx hardhat run scripts/deploy.js --network baseSepolia

This will output a Token Contract Address. Copy this address.

5. Mint Tokens

If you added the optional mint() function above, you can mint more tokens to any address.

Create scripts/mint.js:

const hre = require("hardhat");

async function main() {
  const tokenAddress = process.env.TOKEN_ADDRESS;      // 0x...
  const recipient = process.env.RECIPIENT;             // 0x...
  const amount = hre.ethers.parseUnits(process.env.AMOUNT || "100", 18);

  const token = await hre.ethers.getContractAt("DevToken", tokenAddress);
  const tx = await token.mint(recipient, amount);
  await tx.wait();
  console.log(`Minted ${process.env.AMOUNT || "100"} tokens to ${recipient}`);
}

main().catch((e) => {
  console.error(e);
  process.exit(1);
});

Run:

export TOKEN_ADDRESS=0xYourTokenAddress
export RECIPIENT=0xYourWallet
export AMOUNT=1000
npx hardhat run scripts/mint.js --network baseSepolia

7. Update Backend Configuration

To make the backend aware of your new token, add its ERC‑20 contract address to src/services/blockchain/tokens.ts. Find the correct token symbol (e.g., USDC, CLONES) and update the development (Base Sepolia) address accordingly.

8. Add to Wallet (Optional)

You can add the token to MetaMask (or any EVM wallet) to see your balance.

  1. Add the Base network (if not already added):

  2. Import the token: In MetaMask, click Import tokens, paste your Token Contract Address, and confirm. General MetaMask steps are standard; see community guides if needed. ([Revoke.cash][https://revoke.cash/learn/wallets/add-network/base-sepolia])

Note: Your token may appear as “Unknown Token” until metadata (name/symbol) is detected by explorers/wallets. This does not affect functionality for development.