TypeScript SDK#
The @tetrafi/sdk package will provide a typed, ergonomic interface for the TetraFi API. Stripe-inspired design: a single client instance with namespaced methods.
Installation#
Initialization#
1import { TetraFi } from "@tetrafi/sdk";23const tetrafi = new TetraFi({4 apiKey: process.env.TETRAFI_API_KEY!,5 environment: "sandbox", // "sandbox" | "production"6 timeout: 30000, // request timeout (ms), default 300007 retries: 3, // auto-retry on 5xx, default 38});1// Stubbed TetraFi client - drop in the real @tetrafi/sdk once installed.2class TetraFi {3constructor(cfg) { this.cfg = cfg; console.log("TetraFi initialised:", cfg.environment); }4}56const tetrafi = new TetraFi({7apiKey: "tfk_test_example",8environment: "sandbox",9});1011console.log("Ready to submit RFQs.");apiKeystringrequired- Your API key (tfk_test_* for sandbox, tfk_live_* for production)
environmentstring- API environment. Defaults to 'production'.Default:
production timeoutnumber- Request timeout in milliseconds.Default:
30000 retriesnumber- Auto-retry count on 5xx errors.Default:
3 baseUrlstring- Override the API base URL. Useful for proxies or local development.
loggerfunction- Custom logging function. Defaults to console.log in development.
Core Methods#
Method Index
| Method | Returns | Since | Status |
|---|---|---|---|
| rfq.create(params) | RFQ | v2.0 | Stable |
| rfq.getQuotes(rfqId) | Quote[] | v2.0 | Stable |
| rfq.acceptBest(rfqId) | Settlement | v2.0 | |
| quotes.accept(quoteId) | Settlement | v2.0 | |
| settlements.get(id) | Settlement | v2.0 | |
| compliance.check(address) | ComplianceStatus | v2.0 | |
| audit.getTrail(id) | AuditEntry[] | v2.1 | |
| events.on(type, cb) | () => void | v2.1 | Beta |
rfq.create(params) Stable#
Submit a new Request for Quote to competing solvers.
| Parameter | Type | Description |
|---|---|---|
| pairrequired | string | Trading pair in QUOTE/BASE format, e.g. "USDC/USDT" |
| siderequired | "buy" | "sell" | Trade direction from the taker's perspective |
| amountrequired | string | Trade size as a decimal string in source token units |
| corridor | string | Cross-chain path, e.g. "ethereum-optimism". Defaults to same-chain. |
| maxSlippage | number | Maximum acceptable slippage (0.001 = 0.1%). Defaults to 0.005. |
1const rfq = await tetrafi.rfq.create({2 pair: "USDC/USDT",3 side: "buy",4 amount: "1000000.00",5 corridor: "ethereum-optimism",6 maxSlippage: 0.001,7});rfq.getQuotes(rfqId) Stable#
Get competing quotes for an active RFQ.
1const quotes = await tetrafi.rfq.getQuotes("rfq_abc123");rfq.acceptBest(rfqId)#
Automatically select and accept the best available quote.
1const settlement = await tetrafi.rfq.acceptBest("rfq_abc123");quotes.accept(quoteId)#
Accept a specific quote and trigger escrow creation.
1const settlement = await tetrafi.quotes.accept("qt_xyz789");settlements.get(id)#
Get the current status of a settlement.
1const settlement = await tetrafi.settlements.get("stl_abc123");compliance.check(address)#
Check whether an address has a valid compliance attestation.
1const status = await tetrafi.compliance.check("...");audit.getTrail(settlementId)#
Fetch the WORM audit trail for a completed settlement.
1const entries = await tetrafi.audit.getTrail("stl_abc123");events.on(type, callback) Beta#
Subscribe to real-time events via WebSocket.
1const unsubscribe = tetrafi.events.on("settlement.complete", (event) => {2 console.log("Settled:", event.settlement.id);3});45// Later: stop receiving events6unsubscribe();| Parameter | Type | Description |
|---|---|---|
| typerequired | EventType | Event type to subscribe to. Use wildcards: "settlement.*" matches all settlement events. |
| callbackrequired | (event: Event) => void | Function called when a matching event arrives. |
Type Definitions#
1interface RFQ {2 id: string;3 pair: string;4 side: "buy" | "sell";5 amount: string;6 corridor: string;7 status: "pending" | "quoting" | "accepted" | "expired";8 createdAt: string; // ISO 86019 expiresAt: string; // ISO 860110}1112interface Quote {13 id: string;14 rfqId: string;15 solverId: string;16 price: string; // Decimal string, e.g. "0.9995"17 ttl: number; // Seconds until expiry18 confidence: number; // 0-1 fill confidence score19 createdAt: string;20}1interface Settlement {2 id: string;3 rfqId: string;4 quoteId: string;5 status: "pending" | "escrow_locked" | "filling" | "complete" | "failed" | "refunded";6 originTxHash?: string;7 destinationTxHash?: string;8 amount: string;9 createdAt: string;10 settledAt?: string;11}1213interface ComplianceStatus {14 address: string;15 isCompliant: boolean;16 attestationHash: string;17 expiresAt: string;18}1interface AuditEntry {2 tradeId: string;3 type: "rfq_created" | "quote_accepted" | "escrow_locked" | "settlement_complete";4 timestamp: string;5 data: Record<string, unknown>;6 hash: string; // WORM integrity hash7 prevHash: string; // Chain link to previous entry8}910type EventType =11 | "rfq.created"12 | "quote.received"13 | "quote.accepted"14 | "settlement.pending"15 | "settlement.complete"16 | "settlement.failed"17 | "audit.recorded"18 | "rfq.*"19 | "settlement.*";Full Working Example#
1import { TetraFi } from "@tetrafi/sdk";23const tetrafi = new TetraFi({4 apiKey: process.env.TETRAFI_API_KEY!,5 environment: "sandbox",6});78async function executeSwap() {9 // 1. Create RFQ10 const rfq = await tetrafi.rfq.create({11 pair: "USDC/USDT",12 side: "buy",13 amount: "1000000.00",14 });15 console.log("RFQ created:", rfq.id);1617 // 2. Wait for quotes (poll)18 await new Promise((r) => setTimeout(r, 3000));19 const quotes = await tetrafi.rfq.getQuotes(rfq.id);20 console.log("Received quotes:", quotes.length);2122 if (quotes.length === 0) {23 throw new Error("No quotes received");24 }2526 // 3. Accept best price27 const settlement = await tetrafi.rfq.acceptBest(rfq.id);28 console.log("Settlement initiated:", settlement.id);2930 // 4. Monitor to completion31 let status = settlement;32 while (!["complete", "failed", "refunded"].includes(status.status)) {33 await new Promise((r) => setTimeout(r, 5000));34 status = await tetrafi.settlements.get(settlement.id);35 console.log("Status:", status.status);36 }3738 if (status.status === "complete") {39 console.log("Success!");40 console.log("Origin TX:", status.originTxHash);41 console.log("Destination TX:", status.destinationTxHash);42 } else {43 throw new Error(`Settlement failed: {status.status}`);44 }45}4647executeSwap().catch(console.error);Error Handling#
1import { TetraFiError, RateLimitError, AuthError, ComplianceError } from "@tetrafi/sdk";23try {4 const rfq = await tetrafi.rfq.create({5 pair: "USDC/USDT",6 side: "buy",7 amount: "1000000",8 });9} catch (e) {10 if (e instanceof RateLimitError) {11 // Exponential backoff12 await sleep(e.retryAfter * 1000);13 // retry...14 } else if (e instanceof AuthError) {15 console.error("Invalid API key - check TETRAFI_API_KEY");16 } else if (e instanceof ComplianceError) {17 console.error("Compliance check failed - ensure attestation is current");18 } else if (e instanceof TetraFiError) {19 console.error("API error:", e.code, e.message);20 } else {21 throw e; // Unknown error - rethrow22 }23}WebSocket Event Stream#
For real-time updates, the SDK exposes a WebSocket event stream via tetrafi.events. The connection authenticates with your API key and supports wildcard channel subscriptions. Auto-reconnect is on by default.
1import { TetraFi } from "@tetrafi/sdk";23const tetrafi = new TetraFi({4 apiKey: process.env.TETRAFI_API_KEY!,5 environment: "sandbox",6});78// Connect (lazy - happens on first .on() call)9const unsubQuotes = tetrafi.events.on("quote.received", (event) => {10 console.log(`[Quote] {event.quote.solverId}: {event.quote.price}`);11});1213const unsubSettlement = tetrafi.events.on("settlement.*", (event) => {14 switch (event.type) {15 case "settlement.pending":16 console.log("Escrow locked:", event.settlement.id);17 break;18 case "settlement.complete":19 console.log("Complete!", event.settlement.originTxHash);20 break;21 case "settlement.failed":22 console.error("Failed:", event.settlement.error);23 break;24 }25});2627// Connection lifecycle hooks28tetrafi.events.on("connection.opened", () => console.log("WS connected"));29tetrafi.events.on("connection.closed", () => console.log("WS disconnected - auto-reconnecting"));30tetrafi.events.on("connection.error", (e) => console.error("WS error:", e));3132// Cleanup on shutdown33process.on("SIGTERM", () => {34 unsubQuotes();35 unsubSettlement();36 tetrafi.events.disconnect();37});Auto-reconnect: the SDK reconnects automatically on connection loss with exponential backoff (1s → 2s → 4s → 8s, capped at 30s). Active subscriptions are restored after each reconnect - your .on() callbacks keep firing without re-subscribing.
Available Event Channels#
| Channel | When it fires |
|---|---|
rfq.created | Your RFQ has been broadcast to solvers |
quote.received | A solver returned a quote |
quote.accepted | You accepted a quote |
settlement.pending | Settlement initiated, escrow locking |
settlement.complete | Both legs settled atomically |
settlement.failed | Settlement reverted, refund issued |
audit.recorded | New WORM audit entry |
rfq.* | Wildcard - all RFQ events |
settlement.* | Wildcard - all settlement events |
Try It Live#
Event Stream
Subscribe to real-time quote and settlement events.Versioning#
The @tetrafi/sdk package follows semver. Pin your dependency conservatively until you've confirmed compatibility in staging.
| Bump | Meaning | Action required |
|---|---|---|
1.0.x → 1.0.y | Patch - bug fixes, no API changes | Auto-update is safe |
1.0.x → 1.1.x | Minor - additive features, new methods | Read changelog, no migration |
1.x.x → 2.0.0 | Major - breaking changes | Read migration guide |
Deprecation policy. Methods scheduled for removal are marked with a @deprecated JSDoc tag for at least one minor version before removal. Your IDE will surface a strikethrough on the call site, and the SDK logs a one-time warning at runtime:
1[TetraFi] Warning: tetrafi.rfq.create({ slippage }) is deprecated. Use { maxSlippage } instead. This will be removed in 2.0.0.The full changelog lives at github.com/tetrafi/sdk-typescript/releases. Subscribe to the GitHub releases feed to be notified of new versions.
orderType: 'dutch' optioncompliance.check()connect() to init() for consistency with Python SDKPinning tip. For production deployments, pin to an exact version ("@tetrafi/sdk": "1.4.2") rather than a caret range ("^1.4.2"). This prevents an automatic minor update from changing behavior between deploys. Upgrade explicitly after reading the changelog.
Live Playground#
Try the SDK directly in your browser:
How this works. Edit the code below and watch the output update live. The playground runs in a sandboxed iframe using a mock @tetrafi/sdk that returns realistic data with simulated latency - no real API calls are made. Try changing the amount, pair, or side to see how responses change.
Submit an RFQ
Create an RFQ, receive quotes, and accept the best price.