Developers
Integration Guide
A developer-facing tour of the protocol. Whether you're a project team listing your token, an aggregator routing through Topaz, or a builder reading pool state for an oracle, this is the entry point.
Choose a deployment before integrating
The BNB examples below use that chain's token addresses, wrapped native asset and contracts. A spoke needs its own verified deployment bundle, RPC, factory registry, Voter and reward token. Pool creation, whitelisting, gauges and incentives are local operations; an approval or listing on BNB does not authorize the same action elsewhere.
The interface races Topaz routing, 0x and Relay on every chain pair each one serves. A Topaz winner executes through the Universal Router with Permit2; the Router and Slipstream SwapRouter examples below are direct contract integrations, not a description of every app swap.
xTOPAZ adds vault entry, LayerZero transfers, redemption and local spoke voting. These flows are enabled on the live networks. Read the multichain integration guide for chain and endpoint IDs, contract groups, receipt checks and indexing.
Common integration paths
- ✓Aggregator / router integration — quote Topaz pools and execute swaps through Router (v2) or SwapRouter (Slipstream).
- ✓Token listing as a project — get whitelisted, create your pool, request a gauge, post incentives.
- ✓Oracle consumer — read TWAPs from Slipstream pools for your dapp.
- ✓Vault / strategy builder — automate concentrated-liquidity range management or veTOPAZ voting strategies.
Routing & quoting
For programmatic swaps, three quoter contracts cover all routes:
- ✓
Router— v2-style multihop swaps. UsegetAmountsOutfor quoting. - ✓
QuoterV2— Slipstream-only multihop quotes. Off-chain only (it reverts to return data — the standard Uniswap V3 quoter pattern). - ✓
MixedRouteQuoterV1— quotes that mix v2 and Slipstream pools in a single path. Use this when routing across both pool types.
Encoding a Slipstream path:
// Single hop
bytes memory path = abi.encodePacked(
tokenIn, // 20 bytes
uint24(tickSpacing), // 3 bytes
tokenOut // 20 bytes
);
// Multi-hop via WBNB
bytes memory path = abi.encodePacked(
tokenIn, // 20 bytes
uint24(50), // tickSpacing for first hop (low-vol)
WBNB, // 20 bytes
uint24(200), // tickSpacing for second hop (volatile)
tokenOut // 20 bytes
);See Contracts for all addresses including the mixed-route quoter and Swaps & Routing for end-user routing concepts.
Listing a token / pool (for projects)
The complete checklist for bringing a new token onto Topaz:
- 1Deploy or identify the ERC-20 on the selected live Topaz network; the current examples use BNB. Standard ERC-20 only — fee-on-transfer tokens are partially supported by the v2 router but not by the Slipstream periphery.
- 2Create the pool. For v2:
PoolFactory.createPool(tokenA, tokenB, stable). For Slipstream:CLFactory.createPool(tokenA, tokenB, tickSpacing, sqrtPriceX96). Both are permissionless. - 3Seed initial liquidity. Provide both tokens at a price you're willing to defend. First deposit sets the price; subsequent depositors must match the ratio.
- 4Request whitelisting. Two whitelists matter: (a) token whitelist for use as bribe rewards, and (b) for new tokens, token whitelist on the Voter to allow permissionless gauge creation. Coordinate with governance — reach out via Telegram or governance forum.
- 5Get a gauge created. Once your token is whitelisted (or for a fully-whitelisted pair, by anyone), call
Voter.createGauge(poolFactory, pool). Without a gauge, the pool exists but receives no emissions. - 6Post incentives. Approve and call
BribeVotingReward.notifyRewardAmount(token, amount)on the gauge's bribe contract to attract votes. See Incentives (Bribes).
Reading pool state on-chain
Common reads:
- ✓
PoolFactory.getPool(tokenA, tokenB, stable)— fetch v2 pool address (returns 0x0 if absent). - ✓
CLFactory.getPool(tokenA, tokenB, tickSpacing)— fetch Slipstream pool address. - ✓
Voter.gauges(pool)— fetch a pool's gauge address (0x0 if none). - ✓
Voter.isAlive(gauge)— check whether a gauge is currently active. - ✓
CLPool.slot0()— current sqrtPriceX96, tick, observation index, etc. - ✓
CLPool.observe([secondsAgo1, secondsAgo2])— compute a TWAP from the in-pool oracle. See Oracles & TWAP.
Working with the gauge directly
For programmatic LP integrations:
// v2 LP token staking
ILpToken(lpToken).approve(gauge, amount);
IGauge(gauge).deposit(amount);
// Claim emissions
IGauge(gauge).getReward(msg.sender);
// Withdraw
IGauge(gauge).withdraw(amount);
// Slipstream NFT staking
INonfungiblePositionManager(npm).approve(gauge, tokenId);
ICLGauge(gauge).deposit(tokenId);
ICLGauge(gauge).getReward(tokenId);
ICLGauge(gauge).withdraw(tokenId);Gauges follow the standard notifyRewardAmount /rewardPerToken /earned pattern from MasterChef / Synthetix. Rewards stream linearly across 604,800 seconds after each epoch's emission allocation.
Voting on behalf of a contract
Smart-contract vaults that hold veTOPAZ NFTs can vote and claim like any wallet. Standard flow:
// One-time setup: vault must own (or be approved for) the veNFT
IVoter(voter).vote(
tokenId,
[pool1, pool2, ...],
[weight1, weight2, ...]
);
// Each epoch, after the flip:
IVoter(voter).claimBribes(
[bribeContract1, ...],
[[token1A, token1B], ...],
tokenId
);
IVoter(voter).claimFees(
[feeContract1, ...],
[[token1A, token1B], ...],
tokenId
);Indexing & subgraph
Topaz emits standard events at every state change — pool creates, swaps, mints, burns, votes, gauge distributions, and reward claims. Indexers need each deployment’s RPC logs and start blocks, or a chain-specific subgraph. If you build public indexing infrastructure for the protocol, get in touch via Telegram for cross-linking.
Continue reading
Contracts →
Every deployed contract on all five networks, with explorer links.
Oracles & TWAP →
Read TWAPs from Slipstream pools and grow observation cardinality.
Incentives (Bribes) →
Programmatic incentive deposits for liquidity acquisition.
Gauge Voting →
Voter interface details — vote, reset, poke, claim.