Project: Set Up a Liquidity Pool
A complete, runnable project doing the admin-side setup for a new Uniswap V2 pool on Celo: register both assets, create the pool, fund it, and confirm reserves — the prerequisite for AMM Trading to work. See the Admin API for the endpoint reference.
Celo only
Uniswap V2 pools are a Celo-specific mechanism — there's no chain selector on this page because Stellar's AMM (see Stellar AMM) is a completely separate native protocol-level mechanism with no equivalent create/fund flow.
What you'll build
A setup.js script that registers two assets, creates the pool between them, funds it with real reserves, and confirms it's live — everything AMM Trading needs to actually execute a swap.
Prerequisites
- Node.js 18+ (for global
fetch) - A running comet-engine with a service token — pool creation/funding are platform-wide admin actions, not tenant-scoped, so this uses
X-Service-Tokenrather than a tenant API key/secret
Project setup
mkdir pool-setup && cd pool-setup && npm init -y && npm install dotenv.env:
COMET_BASE_URL=http://localhost:8100
COMET_SERVICE_TOKEN=your-service-tokenCreate setup.js with this shared helper at the top — every step below adds to the same file:
import 'dotenv/config';
const base = process.env.COMET_BASE_URL;
const headers = {
'Content-Type': 'application/json',
'X-Service-Token': process.env.COMET_SERVICE_TOKEN,
};
async function comet(method, path, body) {
const res = await fetch(base + path, { method, headers, body: body ? JSON.stringify(body) : undefined });
const data = await res.json();
if (!res.ok) throw new Error(`${method} ${path} -> ${res.status}: ${JSON.stringify(data)}`);
return data;
}Step 1: Register both assets
🔒 Admin operation — always requires a Service Token, regardless of the panel above.
curl -X POST "http://localhost:8100/api/v1/admin/assets/USDT/register?chain=celo" \
-H "Content-Type: application/json" \
-H "X-Service-Token: YOUR_SERVICE_TOKEN" \
-d '{
"contract": "0x3C8EB6c8DF02B43a7bae71314917aCBdd60edDDF",
"decimals": 6,
"name": "Tether USD"
}'{
"message": "asset USDT registered on celo",
"asset": {
"symbol": "USDT",
"contract": "0x3C8E...DDDF"
}
}🔒 Admin operation — always requires a Service Token, regardless of the panel above.
curl -X POST "http://localhost:8100/api/v1/admin/assets/IMC/register?chain=celo" \
-H "Content-Type: application/json" \
-H "X-Service-Token: YOUR_SERVICE_TOKEN" \
-d '{
"contract": "0x1D1aA006f66A191fc04e7d1cab8D62B0c81d9221",
"decimals": 6,
"name": "ImpalaCoin",
"type": "airtime",
"backing": "airtime"
}'{
"message": "asset IMC registered on celo",
"asset": {
"symbol": "IMC",
"contract": "0xF150...d5A2"
}
}Step 2: Create the pool
🔒 Admin operation — always requires a Service Token, regardless of the panel above.
curl -X POST "http://localhost:8100/api/v1/admin/pools/create" \
-H "Content-Type: application/json" \
-H "X-Service-Token: YOUR_SERVICE_TOKEN" \
-d '{
"tokenA": "USDT",
"tokenB": "IMC",
"chain": "celo"
}'{
"pair": "0xfE6A7492c21DE2C196B465A814A1FAf9B2564082",
"chain": "celo"
}Step 3: Fund it with real reserves
🔒 Admin operation — always requires a Service Token, regardless of the panel above.
curl -X POST "http://localhost:8100/api/v1/admin/pools/fund" \
-H "Content-Type: application/json" \
-H "X-Service-Token: YOUR_SERVICE_TOKEN" \
-d '{
"pair": "0xfE6A7492c21DE2C196B465A814A1FAf9B2564082",
"amountA": 500000000,
"amountB": 1000000000,
"chain": "celo"
}'{
"status": "success",
"txHash": "0x...",
"reserveA": "500000000",
"reserveB": "1000000000"
}Step 4: Confirm it's live
curl -X GET "http://localhost:8100/api/v1/swap/pools" \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-H "X-API-Secret: YOUR_API_SECRET"{
"pools": [
{
"pair": "0xfE6A7492c21DE2C196B465A814A1FAf9B2564082",
"token0": "USDT",
"token1": "IMC",
"reserve0": "500000000",
"reserve1": "1000000000"
}
],
"count": 1
}Step 5: Run the whole setup as one script
Add main() to setup.js:
async function main() {
await comet('POST', '/api/v1/admin/assets/USDT/register?chain=celo', {
contract: '0x3C8EB6c8DF02B43a7bae71314917aCBdd60edDDF', decimals: 6, name: 'Tether USD',
});
await comet('POST', '/api/v1/admin/assets/IMC/register?chain=celo', {
contract: '0x1D1aA006f66A191fc04e7d1cab8D62B0c81d9221', decimals: 6, name: 'ImpalaCoin', type: 'airtime', backing: 'airtime',
});
console.log('assets registered');
const pool = await comet('POST', '/api/v1/admin/pools/create', { tokenA: 'USDT', tokenB: 'IMC', chain: 'celo' });
console.log('pool created:', pool.pair);
const funded = await comet('POST', '/api/v1/admin/pools/fund', {
pair: pool.pair, amountA: 500000000, amountB: 1000000000, chain: 'celo',
});
console.log('pool funded:', funded.txHash);
const pools = await comet('GET', '/api/v1/swap/pools');
console.log('pools now live:', pools.pools);
}
main().catch((e) => { console.error(e); process.exit(1); });node setup.jsWhat you built
- A real, funded Uniswap V2 pool on Celo — not a testnet placeholder, actual reserves an actual swap can draw against.
- The full admin lifecycle: register, create, fund, verify.
Next steps: head to AMM Trading to actually swap against this pool, or repeat Step 1–3 for another asset pair.