Developer quickstart
Read a market, obtain an execution-matching quote and construct a bounded transaction.
On this page
Start with the network and manifest
Robinhood Chain mainnet uses chain ID 4663. Use the manifest belonging to the deployment you are integrating with. The Contracts page reads the same public manifest as this app and offers a JSON download; do not substitute addresses from an earlier test deployment.
Examples below use the source package @sinjoh/sdk with viem. They assume that package is available in your workspace; this guide does not assert that an npm release has been published. Read examples need no private key.
import { createPublicClient, http } from 'viem';
import { Manifest, tokenMarket, market, quoteTrade } from '@sinjoh/sdk';
const manifest = Manifest.parse(await fetch(
new URL('/resources/manifest.json', APP_ORIGIN)
).then(response => response.json()));
const client = createPublicClient({ transport: http(RPC_URL) });
if (await client.getChainId() !== manifest.chainId) throw new Error('Wrong chain');Read contracts without the SDK
The manifest and interface downloads also work with plain viem, so read integrations need not wait for an SDK package release. This alternative example reads the configured path count; it makes no signing request.
import { createPublicClient, http, type Abi } from 'viem';
const reader = createPublicClient({ transport: http(RPC_URL) });
const deployment = await fetch(new URL('/resources/manifest.json', APP_ORIGIN))
.then(response => response.json());
const settingsInterface = await fetch(new URL('/resources/abi/settings', APP_ORIGIN))
.then(response => response.json()) as Abi;
if (await reader.getChainId() !== deployment.chainId) throw new Error('Wrong chain');
const pathCount = await reader.readContract({
address: deployment.contracts.settings,
abi: settingsInterface,
functionName: 'swapPathCount',
});Resolve a token and quote a trade
TOKEN_ADDRESS, APP_ORIGIN and RPC_URL are supplied by your application. Treat (hook, poolId) as the identity throughout. Amounts are raw integers; use the input token’s actual decimals rather than assuming 18.
const id = await tokenMarket(client, manifest, TOKEN_ADDRESS);
if (!id) throw new Error('No canonical Sinjoh market');
const m = await market(client, manifest, id);
const q = await quoteTrade(client, manifest, m, 'buy', 'in', backingAmount);
console.log({ input: q.amountIn, output: q.amountOut, unused: q.unused });A quote simulates the real hook path through SinjohQuoter. It needs no account balance or allowance. The transaction’s eventual state can differ, so a quote must be paired with minimum output, maximum input and a deadline.
Construct a transaction without signing
import { approvals, limits, robinhoodChain, tradeTx } from '@sinjoh/sdk';
const deadline = (await client.getBlock()).timestamp + 300n;
const slippageBps = 50;
const missingApprovals = await approvals(
client, robinhoodChain, walletAddress, q.payAsset,
limits(q, slippageBps).maxIn, Number(deadline)
);
const transaction = tradeTx(robinhoodChain, q, slippageBps, deadline);
// 50 bps = 0.50% slippage. Have the user's wallet review/sign approvals
// and the transaction. These builders do not send anything.Before using an integration with funds
- Read contract addresses and compatible hooks from the current manifest.
- Resolve both hook and pool ID, and preserve raw integer precision.
- Quote the actual size; inspect unused input and every conversion hop.
- Keep approval spender, chain, account and transaction bound to the same quote.
- Observe receipts and decoded events; a submitted hash is not successful execution.
- Keep current-state, indexed-state and finalized-state observations separate.
Skip to documentation