Skip to content

Merge Tokens

Merging is the inverse of splitting. It destroys equal quantities of both Yes and No tokens and returns the equivalent USDC.e to your wallet. Every 1 Yes + 1 No merged yields $1 USDC.e.

100 Yes tokens + 100 No tokens --> $100 USDC.e
POST https://api.openfish.fun/ctf/merge

Requires L2 authentication (HMAC signature in request headers).

FieldTypeRequiredDescription
conditionIdstringYesThe market’s condition ID (hex, 0x-prefixed)
amountstringYesNumber of full token sets to merge
Terminal window
curl -X POST https://api.openfish.fun/ctf/merge \
-H "Content-Type: application/json" \
-H "OPENFISH-API-KEY: your-api-key" \
-H "OPENFISH-SIGNATURE: ..." \
-H "OPENFISH-TIMESTAMP: ..." \
-H "OPENFISH-PASSPHRASE: ..." \
-d '{
"conditionId": "0xabc123...def456",
"amount": "100"
}'
{
"success": true,
"conditionId": "0xabc123...def456",
"amount": "100",
"txHash": "0x4b2a...c8d1"
}
FieldTypeDescription
successbooleanWhether the operation completed
conditionIdstringThe condition ID that was merged
amountstringNumber of full sets merged (equals USDC.e returned)
txHashstringOn-chain transaction hash (present only in onchain mode)
  1. The server validates your L2 authentication headers.
  2. It confirms you hold at least amount of every outcome token for this condition.
  3. Both outcome token balances are reduced by the requested amount.
  4. Your USDC.e (collateral) balance increases by the same amount.
  5. The operation is logged for the data server.
  6. When running in onchain mode, a mergePositions transaction is sent to the CTF contract.

The merge is atomic within the ledger — if any outcome token balance falls short, the entire request fails with an error and no balances change. If the on-chain transaction fails, ledger changes are rolled back automatically (outcome tokens re-credited, USDC re-debited), and an error is returned.

When the server operates in onchain settlement mode, it submits:

function mergePositions(
address collateralToken, // USDC.e
bytes32 parentCollectionId, // 0x000...000
bytes32 conditionId, // market condition
uint256[] partition, // [1, 2] for binary
uint256 amount // in 6-decimal base units
) external;
use openfish_client_sdk::ClobClient;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let clob = ClobClient::authenticated(
"https://api.openfish.fun",
"your-api-key",
"your-api-secret",
"your-passphrase",
);
let condition_id = "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af";
let result = clob.ctf_merge(condition_id, "50").await?;
println!("Merged {} token sets back to USDC.e", result.amount);
if let Some(tx) = &result.tx_hash {
println!("On-chain tx: https://polygonscan.com/tx/{}", tx);
}
Ok(())
}
  • Reducing exposure — When you hold equal Yes and No positions, merging reclaims collateral more efficiently than selling both sides on the order book.
  • Locking in arbitrage — If you acquired both sides at a combined cost under $1, merging yields a guaranteed profit.
  • Freeing capital — Release USDC.e from positions you no longer want to maintain.
ErrorCause
conditionId and amount requiredMissing or empty fields in the request body
insufficient {token_id} balanceYou do not hold enough of one or more outcome tokens
invalid JSONMalformed request body
401 UnauthorizedInvalid or missing L2 authentication headers