SDK Examples
Worked examples against @tokenbot-org/sdk. Every method used here exists on the shipped SDK — see
the reference.
All examples assume this setup:
import { SignedHttpClient, unlockIdentity } from '@tokenbot-org/cli-core';import { TokenbotSdk } from '@tokenbot-org/sdk';
const privateKey = unlockIdentity(encryptedKey, salt, passphrase);
const sdk = new TokenbotSdk({ http: new SignedHttpClient({ apiUrl: 'https://api.tokenbot.com', publicKey, privateKey }), graphqlUrl: 'https://gql-api.tokenbot.com/graphql', wsUrl: 'wss://gql-api.tokenbot.com/graphql',});1. Confirm the identity works
Section titled “1. Confirm the identity works”const me = await sdk.identity.whoami();console.log(me);Fails with SdkAuthError if the key isn’t registered — the cheapest way to check wiring before
anything else.
2. Pull full trade history
Section titled “2. Pull full trade history”The trap here is the default window:
// ❌ Silently returns only the last monthconst partial = await sdk.trades.list();
// ✅ Full historyconst all = await sdk.trades.list({ filter: { dateRange: 'ALL', limit: 500 } });graphql-api defaults dateRange to MONTH when it isn’t supplied, so omitting it looks like “all
trades” and isn’t.
3. Total realised PnL
Section titled “3. Total realised PnL”const trades = await sdk.trades.list({ filter: { dateRange: 'ALL', limit: 500 } });
const pnl = trades.reduce((sum, t) => sum + Number(t.profitLoss ?? 0), 0);console.log(`realised pnl: ${pnl.toFixed(2)}`);Page with limit + page if you have more than one page of history.
4. Filter by symbol — and why it needs a big limit
Section titled “4. Filter by symbol — and why it needs a big limit”const btc = await sdk.trades.list({ filter: { symbol: 'BTC/USDT', dateRange: 'ALL', limit: 500 },});symbol is applied client-side, because graphql-api has no symbol filter. It narrows the page
the server already returned. With a small limit you can get an empty result even when matching
trades exist further back.
5. Stand up copy trading end to end
Section titled “5. Stand up copy trading end to end”// 1. Register the exchange account the copier trades on.// This uploads credentials to the SERVER so the platform can act for you.const account = await sdk.exchanges.createAccount({ exchangeName: 'binance', accountName: 'main', tradingType: 'spot', apiKey: process.env.BINANCE_KEY!, apiSecret: process.env.BINANCE_SECRET!,});
// 2. Pick a strategy to followconst strategies = await sdk.strategies.list();const leader = strategies[0];
// 3. Create the copierconst copier = await sdk.copiers.create({ strategyId: leader.id, exchangeAccountId: account.id, name: 'btc follow', allocationPercentage: 25,});
// 4. Bind them — note POSITIONAL args, unlike the CLI's flagsawait sdk.copiers.link(leader.id, copier.id);To detach:
await sdk.copiers.unlink(leader.id, copier.id);6. Adjust a copier’s allocation
Section titled “6. Adjust a copier’s allocation”await sdk.copiers.update(copierId, { allocationPercentage: 10 });update is a partial — send only what changes.
7. Register a webhook and prove it works
Section titled “7. Register a webhook and prove it works”const hook = await sdk.webhooks.create({ url: 'https://example.com/hooks/tokenbot', events: ['trade.filled'],});
await sdk.webhooks.test(hook.id);test sends a real test event, so you can confirm the endpoint before depending on it.
8. Stream the market-maker order book
Section titled “8. Stream the market-maker order book”for await (const snap of sdk.mm.orderBookWatch({ exchangeId: 'mexc', symbol: 'TBOT/USDT' })) { console.log('best bid', snap.bids[0], 'best ask', snap.asks[0]); break; // tears the socket down cleanly}Requires wsUrl on the constructor. Without it this throws SdkError immediately rather than
failing later at the socket.
9. Typed error handling
Section titled “9. Typed error handling”import { SdkAuthError, SdkNotFoundError, SdkPermissionError, SdkValidationError, SdkNetworkError,} from '@tokenbot-org/sdk';
async function safeGetStrategy(id: string) { try { return await sdk.strategies.get(id); } catch (err) { if (err instanceof SdkNotFoundError) return null; if (err instanceof SdkPermissionError) throw new Error('not your strategy'); if (err instanceof SdkAuthError) throw new Error('identity rejected — re-run tokenbot init'); if (err instanceof SdkValidationError) throw new Error('unexpected API shape — SDK may be stale'); if (err instanceof SdkNetworkError) throw new Error('could not reach TokenBot'); throw err; }}SdkValidationError is the interesting one: responses are schema-validated, so a server-side shape
change surfaces at the boundary instead of as an undefined field deep in your code.
10. A small reporting script
Section titled “10. A small reporting script”const [me, strategies, copiers] = await Promise.all([ sdk.identity.whoami(), sdk.strategies.list(), sdk.copiers.list(),]);
console.log(`account: ${me.id}`);console.log(`strategies: ${strategies.length}`);console.log(`copiers: ${copiers.length} (${copiers.filter((c) => c.isActive).length} active)`);See also
Section titled “See also”- SDK Reference
- Overview
- CLI Examples — the same workflows from the terminal

