Inventory Management
Quoting both sides of a prediction market requires YES and NO tokens on hand. Three operations govern your token inventory: splitting USDC.e into matched YES/NO pairs, merging pairs back into USDC.e to free capital, and redeeming winning tokens for their payout once a market resolves.
Every operation goes through the Conditional Tokens Framework (CTF) contract on Polygon.
Splitting USDC.e into Tokens
Section titled “Splitting USDC.e into Tokens”A split converts USDC.e into equal quantities of YES and NO tokens, giving you the inventory needed to post quotes on both sides of the book.
use openfish_client_sdk::ctf::Client as CtfClient;use openfish_client_sdk::ctf::types::SplitPositionRequest;use openfish_client_sdk::types::{U256, address};
let ctf_client = CtfClient::new(provider, 137)?;
// Split 1000 USDC.e into 1000 YES + 1000 NO tokenslet request = SplitPositionRequest::builder() .collateral_token(address!("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174")) .condition_id(condition_id) .partition(vec![U256::from(1), U256::from(2)]) .amount(U256::from(1_000_000_000u64)) // 1000 USDC.e (6 decimals) .build();
let result = ctf_client.split_position(&request).await?;println!("Split tx: {:?}", result.transaction_hash);After splitting 1000 USDC.e you hold 1000 YES tokens and 1000 NO tokens. Your USDC.e balance decreases by 1000.
Merging Tokens to USDC.e
Section titled “Merging Tokens to USDC.e”Merging burns equal quantities of YES and NO tokens and returns the equivalent USDC.e. Use it to wind down exposure, exit a market entirely, or reallocate capital elsewhere.
use openfish_client_sdk::ctf::types::MergePositionsRequest;
// Merge 500 YES + 500 NO back to 500 USDC.elet request = MergePositionsRequest::builder() .collateral_token(address!("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174")) .condition_id(condition_id) .partition(vec![U256::from(1), U256::from(2)]) .amount(U256::from(500_000_000u64)) // 500 USDC.e (6 decimals) .build();
let result = ctf_client.merge_positions(&request).await?;Both YES and NO balances decrease by 500, USDC.e increases by 500.
Redeeming After Resolution
Section titled “Redeeming After Resolution”When a market reaches its final outcome, winning tokens can be exchanged 1:1 for USDC.e. Losing tokens yield nothing.
Check Resolution Status
Section titled “Check Resolution Status”let market = clob_client.market(condition_id).await?;if market.closed { if let Some(winner) = market.tokens.iter().find(|t| t.winner) { println!("Winning outcome: {}", winner.outcome); }}Redeem Winning Tokens
Section titled “Redeem Winning Tokens”use openfish_client_sdk::ctf::types::RedeemPositionsRequest;
let request = RedeemPositionsRequest::builder() .collateral_token(address!("0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174")) .condition_id(condition_id) .index_sets(vec![U256::from(1), U256::from(2)]) // pass both; only winners pay out .build();
let result = ctf_client.redeem_positions(&request).await?;Negative Risk Markets
Section titled “Negative Risk Markets”Multi-outcome markets route through different exchange contracts. The split and merge mechanics are identical, but you target the Neg Risk Adapter and Neg Risk CTF Exchange.
const NEG_RISK_ADAPTER: &str = "0x0d8FA66CFe5D5EF96D6be9C4e808BD4279527d6e";const NEG_RISK_EXCHANGE: &str = "0x700eaF3f3FEb1D3f2aE67000e1A4FA41a6E35DF1";See Negative Risk Markets for details on how multi-outcome token mechanics differ from standard binary markets.
Inventory Strategies
Section titled “Inventory Strategies”Before Quoting
Section titled “Before Quoting”- Fetch market metadata via the Gamma API (condition ID, token IDs, tick size).
- Split enough USDC.e to cover your expected quoting size on both sides.
- Verify token approvals are in place (see Getting Started).
During Trading
Section titled “During Trading”- Skew quotes when inventory becomes heavy on one side to attract fills that rebalance you.
- Merge excess pairs to free capital for other markets.
- Split more when inventory on either side runs low.
After Resolution
Section titled “After Resolution”- Cancel all open orders in the resolved market.
- Wait for the resolution transaction to confirm.
- Redeem winning tokens.
- Merge any remaining YES/NO pairs (edge case: partial fills during resolution window).
Batch Operations
Section titled “Batch Operations”Multiple inventory operations can be batched into a single relayer transaction for gas efficiency. This is particularly useful when onboarding to several markets at once.
// Example: split into tokens for two markets in one transactionlet txs = vec![ split_position_tx(condition_id_a, amount), split_position_tx(condition_id_b, amount),];relayer_client.execute(txs, "Batch inventory setup").await?;Next Steps
Section titled “Next Steps”- Trading — Order entry and quoting best practices.
- Liquidity Rewards — Earn rewards for providing two-sided liquidity.
- Contract Addresses — Full list of Openfish smart contracts on Polygon.