Skip to main contentSkip to FAQSkip to contact
Planned4 min read

SDK Client#

Planned Specification. Both packages are under development. Use the REST API and WebSocket directly until release.

Installation#

Bash
1npm install @tetrafi/sdk
1 linesbash

Python requires 3.10+, httpx, websockets.

Initialization#

TypeScript
1import { TetraFi } from "@tetrafi/sdk";
2
3const tetrafi = new TetraFi({
4 apiKey: process.env.TETRAFI_API_KEY!,
5 environment: "sandbox", // "sandbox" | "production"
6 timeout: 30000, // ms, default 30000
7 retries: 3, // auto-retry on 5xx
8});
8 linestypescript
apiKey / api_keystringrequired
Your API key (tfk_test_* for sandbox, tfk_live_* for production)
environmentstring
'sandbox' | 'production'. Defaults to 'production'.Default: production
timeoutnumber
Request timeout (ms in TS, seconds in Python).Default: 30000 / 30
retriesnumber
Auto-retry count on 5xx errors.Default: 3
baseUrl / base_urlstring
Override the API base URL. Useful for proxies or local development.

Core Methods#

rfq.create(params) Stable#

Submit a new RFQ to competing solvers.

TypeScript
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});
7 linestypescript
Annotated parameters
1const rfq = await tetrafi.rfq.create({
2pair: "USDC/USDT",
3side: "buy",
4amount: "1000000.00",
5corridor: "ethereum-optimism",
6maxSlippage: 0.001,
7});
7 linestypescript
ReturnsRFQ

rfq.getQuotes(rfqId) / rfq.get_quotes(rfq_id) Stable#

Get competing quotes for an active RFQ. Returns list sorted best-price-first.

TypeScript
1const quotes = await tetrafi.rfq.getQuotes("rfq_abc123");
1 linestypescript
ReturnsQuote[]- sorted best-price first

rfq.acceptBest(rfqId) / rfq.accept_best(rfq_id)#

Automatically select and accept the best available quote.

TypeScript
1const settlement = await tetrafi.rfq.acceptBest("rfq_abc123");
1 linestypescript
ReturnsSettlement

quotes.accept(quoteId) / quotes.accept(quote_id)#

Accept a specific quote and trigger escrow creation.

TypeScript
1const settlement = await tetrafi.quotes.accept("qt_xyz789");
1 linestypescript
ReturnsSettlement

settlements.get(id)#

Get the current status of a settlement.

TypeScript
1const settlement = await tetrafi.settlements.get("stl_abc123");
1 linestypescript
ReturnsSettlement

compliance.check(address)#

Check whether an address has a valid compliance attestation.

TypeScript
1const status = await tetrafi.compliance.check("...");
1 linestypescript

events.on(type, callback) Beta#

Subscribe to real-time events via WebSocket. TypeScript uses a callback pattern; Python uses async for.

TypeScript
1const unsubscribe = tetrafi.events.on("settlement.complete", (event) => {
2 console.log("Settled:", event.settlement.id);
3});
4
5// Later: stop receiving events
6unsubscribe();
6 linestypescript
ChannelWhen it fires
rfq.createdYour RFQ has been broadcast to solvers
quote.receivedA solver returned a quote
quote.acceptedYou accepted a quote
settlement.pendingSettlement initiated, escrow locking
settlement.completeBoth legs settled atomically
settlement.failedSettlement reverted, refund issued
rfq.* / settlement.*Wildcard - all events in that namespace

Full Working Example#

TypeScript
1import { TetraFi } from "@tetrafi/sdk";
2
3const tetrafi = new TetraFi({
4 apiKey: process.env.TETRAFI_API_KEY!,
5 environment: "sandbox",
6});
7
8async function executeSwap() {
9 // 1. Create RFQ
10 const rfq = await tetrafi.rfq.create({
11 pair: "USDC/USDT",
12 side: "buy",
13 amount: "1000000.00",
14 });
15
16 // 2. Wait for auction window
17 await new Promise((r) => setTimeout(r, 3000));
18 const quotes = await tetrafi.rfq.getQuotes(rfq.id);
19 if (quotes.length === 0) throw new Error("No quotes");
20
21 // 3. Accept best price
22 const settlement = await tetrafi.rfq.acceptBest(rfq.id);
23
24 // 4. Monitor to completion
25 let status = settlement;
26 while (!["complete", "failed", "refunded"].includes(status.status)) {
27 await new Promise((r) => setTimeout(r, 5000));
28 status = await tetrafi.settlements.get(settlement.id);
29 }
30
31 console.log(status.status === "complete" ? "Success!" : `Failed: ${status.status}`);
32}
33
34executeSwap().catch(console.error);
34 linestypescript

Error Handling#

TypeScript
1import { TetraFiError, RateLimitError, AuthError, ComplianceError } from "@tetrafi/sdk";
2
3try {
4 const rfq = await tetrafi.rfq.create({ pair: "USDC/USDT", side: "buy", amount: "1000000" });
5} catch (e) {
6 if (e instanceof RateLimitError) {
7 await sleep(e.retryAfter * 1000);
8 } else if (e instanceof AuthError) {
9 console.error("Invalid API key");
10 } else if (e instanceof ComplianceError) {
11 console.error("Compliance check failed");
12 } else if (e instanceof TetraFiError) {
13 console.error("API error:", e.code, e.message);
14 } else {
15 throw e;
16 }
17}
17 linestypescript

Type Definitions#

TypeScript
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;
9 expiresAt: string;
10}
11
12interface Quote {
13 id: string;
14 rfqId: string;
15 solverId: string;
16 price: string;
17 ttl: number;
18 confidence: number;
19 createdAt: string;
20}
21
22interface Settlement {
23 id: string;
24 rfqId: string;
25 quoteId: string;
26 status: "pending" | "escrow_locked" | "filling" | "complete" | "failed" | "refunded";
27 originTxHash?: string;
28 destinationTxHash?: string;
29 amount: string;
30 createdAt: string;
31 settledAt?: string;
32}
33
34interface ComplianceStatus {
35 address: string;
36 isCompliant: boolean;
37 attestationHash: string;
38 expiresAt: string;
39}
39 linestypescript

Versioning#

Both packages follow semver. Pin to exact versions for production deploys.

BumpMeaningAction
1.0.x → 1.0.yPatch - bug fixesAuto-update safe
1.0.x → 1.1.xMinor - new methodsRead changelog
1.x → 2.0Major - breakingMigration guide required