TypeScript SDK
@inkle/sdk is a zero-dependency typed client for Node 18+ and the browser. It unwraps the response envelope, classifies errors, times out slow calls, and retries transient failures with backoff.
Install
bash
npm install @inkle/sdkCreate a client
ts
import { InkleClient } from "@inkle/sdk"; // Read-only const inkle = new InkleClient(); // With trading and private reads const bot = new InkleClient({ apiKey: process.env.INKLE_API_KEY, timeoutMs: 30000, // per-request timeout (default 30s) maxRetries: 2, // transient failures, exponential backoff (default 2) });
Read markets
ts
const { items, count } = await inkle.markets.list({ status: "open" }); const market = await inkle.markets.get(items[0].id); const { ticks } = await inkle.markets.priceTicks(market.id, { limit: 200 }); // A 10 $USDI buy on outcome 0 const quote = await inkle.markets.quote(market.id, 0, 10); console.log(quote.shares, quote.avgPrice, quote.priceAfter);
Paginate large lists without holding everything in memory using the async iterator:
ts
for await (const m of inkle.markets.listAll({ status: "open" })) { console.log(m.question); }
Trade
ts
const market = await bot.usdi.createLmsr({ question: "Will it rain in Seoul tomorrow?", outcomeLabels: ["Yes", "No"], closesAt: new Date(Date.now() + 86400000).toISOString(), seed: 50, }); await bot.usdi.bet(market.id, { outcomeIndex: 0, stake: 10 }); await bot.usdi.sell(market.id, { outcomeIndex: 0, shares: 4 }); const positions = await bot.usdi.myBets(market.id);
Handle errors
Every failure throws InkleApiError with a stable type (see the error codes). Branch on it:
ts
import { InkleApiError } from "@inkle/sdk"; try { await bot.usdi.bet(id, { outcomeIndex: 0, stake: 999999 }); } catch (e) { if (e instanceof InkleApiError) { switch (e.type) { case "invalid_request_error": console.error("Rejected:", e.message); // "insufficient $USDI balance" break; case "authentication_error": console.error("Bad or revoked key"); break; case "rate_limit_error": console.error("Slow down"); // already retried by the SDK break; default: console.error(e.type, e.status, e.message); } } }
Transient failures (429, 5xx, network, timeout) are retried automatically with exponential backoff and jitter, honoring a Retry-After header when the server sends one. Set maxRetries: 0 to opt out.
Cancel a request
ts
const controller = new AbortController(); setTimeout(() => controller.abort(), 2000); await inkle.markets.list({ status: "open" }, { signal: controller.signal });
Portfolio & discovery
ts
// Your portfolio (read scope). Rows span both rails, so split // them by tokenSymbol before totalling anything: USDC and $USDI // are different currencies. const positions = await bot.account.positions(); const onChain = positions.filter((p) => p.tokenSymbol !== "USDI"); const ledger = positions.filter((p) => p.tokenSymbol === "USDI"); const history = await bot.account.bets(); const created = await bot.account.markets(); // Public discovery (no key) const results = await inkle.discover.search("bitcoin"); const trending = await inkle.discover.trending(); const board = await inkle.discover.leaderboard({ limit: 50 });
Namespaces
inkle.markets: public reads (list, listAll, get, priceTicks, publicBets, quote, sellQuote)inkle.usdi: trading (createLmsr, createDirect, createFlash, bet, sell, myBets)inkle.flash: on-chain flash pools (list, get, quote, price, bets)inkle.discover: search, trending, leaderboardinkle.account: me, positions, bets, markets