TypeScript SDK

Typed all the way down.

Every method, argument and return type is derived from the same contract the API itself is built from. There is no codegen step to run and nothing to regenerate — a wrong chain slug is a compile error, not a 400 you discover in production.

86 methodsZero codegenNode · Bun · Deno · browser · edge
MCP
Claude, ChatGPT, Cursor
SDK
TypeScript
CLI
Terminal & CI
REST API
Any language
Install

Install

npm i foxd-sdk
quick start
import { FoxD } from "foxd-sdk";

const foxd = new FoxD({ apiKey: process.env.FOXD_API_KEY });

const { tokens } = await foxd.market.trending({ chain: "base", limit: 10 });
Types

What 'typed' actually buys you

The chain parameter is a union, not a string. Autocomplete lists the six real chains, and anything else fails to compile:

foxd.market.trending({ chain: "base" });      // fine
foxd.market.trending({ chain: "dogecoin" });  // Type '"dogecoin"' is not assignable
foxd.market.trending({ nonsense: 1 });        // Object literal may only specify known properties
foxd.market.doesNotExist({});                 // Property 'doesNotExist' does not exist

Responses are shaped too — tokens[0].priceUsd is number | null, so the nullability that actually exists in market data is visible at the call site rather than discovered by a crash.

Safety

Two behaviours worth knowing

Mutating calls are never retried

Read calls retry transient failures with exponential backoff and jitter. Anything that moves money does not — a timeout does not mean the write failed, and replaying a trade to be helpful would be far worse than surfacing the ambiguity.

Errors are structured

import { FoxD, FoxDError } from "foxd-sdk";

try {
  await foxd.trade.execute({ /* … */ });
} catch (e) {
  if (e instanceof FoxDError) {
    e.code;       // "spend_cap_exceeded" — stable, matchable
    e.status;     // 403
    e.retryable;  // false
  }
}
Example

A real safety check

const { tokens } = await foxd.market.trending({ chain: "base", limit: 5 });
const t = tokens[0];

const [provider, sim] = await Promise.all([
  foxd.analytics.security({ chain: "base", address: t.address }),
  foxd.analytics.simulateHoneypot({ chain: "base", address: t.address }),
]);

// simulated:false is NOT a pass — it means no conclusion was reached.
const sellable = sim.simulated && sim.canSell === true;
if (provider.isHoneypot || !sellable) throw new Error("not sellable");

const quote = await foxd.trade.quote({
  chain: "base",
  tokenIn: "0x0000000000000000000000000000000000000000",
  tokenOut: t.address,
  amountIn: "10000000000000000",   // base units, as a string
  side: "buy",
});
console.log(quote.venue, quote.estimatedUsd, quote.priceImpactBps);

Amounts are base-unit strings — wei on EVM, lamports on Solana. An 18-decimal amount does not survive a float, so the SDK will not accept one.

Get an API key

Public market data needs no key. Everything account-, wallet- or trade-related does. Keys are free, scoped, and revocable in one click.

Create an API keyFull documentation
SniperTradeLaunchAI
TypeScript SDK — Typed FoxD client for bots and apps | FoxD