@t2000/sdk is the TypeScript SDK for Agent Wallets on Sui — the layer underneath @t2000/cli and @t2000/mcp. One class (T2000) that handles wallet signing, gasless USDC + USDsui transfers, Cetus swap routing, and x402 paid API access (pay any API in USDC).
The SDK’s write surface is send (gasless USDC/USDsui), swap (Cetus, any Sui token), and pay (x402) — plus the wallet reads (balance, history, receive).
Install
npm install @t2000/sdk # or pnpm add / yarn add
Requires Node.js 18+ · TypeScript 5+ recommended.
Quick Start
import { T2000 } from '@t2000/sdk';
// Create a new wallet (plain Bech32, 0o600 perms)
const { agent, address } = await T2000.init();
// Or load an existing wallet from ~/.t2000/wallet.key
const agent = await T2000.create();
// Or from a Bech32 secret in memory (no file)
const agent = T2000.fromPrivateKey('suiprivkey1…');
// Inspect
const balance = await agent.balance();
console.log(`$${balance.available} USDC available`);
// Send — asset is REQUIRED; USDC + USDsui are gasless via 0x2::balance::send_funds
await agent.send({ to: 'alice.sui', amount: 5, asset: 'USDC' });
await agent.send({ to: '0x8b3e…', amount: 5, asset: 'USDsui' });
// Swap — Cetus Aggregator V3 across 20+ Sui DEXs. Requires SUI for gas.
await agent.swap({ from: 'USDC', to: 'SUI', amount: 100 });
// Pay — any x402-protected API. Gasless USDC; handles HTTP 402 transparently.
const result = await agent.pay({
url: 'https://mpp.t2000.ai/openai/v1/chat/completions',
method: 'POST',
body: JSON.stringify({ model: 'gpt-4o-mini', messages: [/* … */] }),
maxPrice: 0.10,
});
Factory Methods
| Static | Returns | Use when |
|---|
T2000.init({ keyPath?, name? }) | { agent, address } | Generating a brand-new wallet. Writes a plain Bech32 JSON file to ~/.t2000/wallet.key (override with keyPath). |
T2000.create({ keyPath?, rpcUrl? }) | T2000 | Loading the existing wallet from disk. Throws WALLET_NOT_FOUND if missing, WALLET_CORRUPT if malformed. |
T2000.fromPrivateKey(secret, { network?, rpcUrl? }) | T2000 | Synchronous in-memory load from a suiprivkey1… Bech32 or hex secret. No filesystem read or write. |
Agent Wallet API
These methods mirror the @t2000/cli surface 1:1 — sending USDC, receiving, swapping, paying for x402 APIs.
| Method | Returns | Notes |
|---|
agent.address() | string | Sui address. |
agent.balance() | BalanceResponse | USDC / USDsui / SUI + gas reserve + total USD. |
agent.history({ limit? }) | TransactionRecord[] | Sends / swaps / x402 payments with Suiscan digests. |
agent.send({ to, amount, asset }) | SendResult | asset is required ('USDC' / 'USDsui' / 'SUI'). USDC + USDsui are gasless via Sui foundation’s 0x2::balance::send_funds; SUI uses standard gas. to resolves: hex address > SuiNS (alice.sui) > @audric handle > saved contact. |
agent.resolveRecipient(input) | { address, suinsName?, contactName? } | Public resolver — same lookup send uses. Handy for dry-run previews. |
agent.swap({ from, to, amount, slippage? }) | SwapResult | Cetus Aggregator V3 (20+ DEXs). User-friendly names ('USDC', 'SUI', 'CETUS', …) or full coin types. Default slippage 1%, max 5%. Requires SUI for gas. |
agent.swapQuote({ from, to, amount, slippage? }) | SwapQuoteResult | Preview route + output + price impact (no execution). |
agent.pay(options) | PayResult | x402-protected paid API. Handles 402 → quote → USDC payment → retry. USDC transfer is gasless. options.maxPrice caps spend (default 1 USDC). |
agent.chat(params) | ChatResult | Private inference on the Private Inference (OpenAI-compatible). Key-based — params.apiKey or T2000_API_KEY. Returns { content, model, usage, raw }. |
agent.chatStream(params) | AsyncGenerator<string> | Streaming inference — async-iterate the assistant text deltas. |
agent.models(opts?) | ApiModel[] | Private Inference model catalog (id · context · per-1M pricing · privacy tier). |
agent.verify(receiptId, opts?) | VerifyResult | Verify a confidential response — signed receipt + trustless on-chain Sui anchor. verified:false on any mismatch. |
agent.receive({ amount?, currency?, memo?, label? }) | PaymentRequest | Builds a Payment Kit sui:pay?… URI with a unique nonce. Scannable by any Sui wallet. |
agent.exportKey() | string | Print the Bech32 (suiprivkey1…) secret for the underlying keypair. |
Events
agent.on('balanceChange', (e) => { /* asset, previous, current, cause, tx? */ });
agent.on('error', (e) => { /* T2000Error */ });
Exposed Internals
For host integrations:
agent.suiClient; // Sui client (gRPC — reads + execute; JSON-RPC sunsets 2026-07-31)
agent.signer; // TransactionSigner (works for keypair + zkLogin)
agent.keypair; // Ed25519Keypair (throws for zkLogin instances)
Agent identity (register on-chain, claim a handle) lives in a separate package — @t2000/id — and the t2 agent CLI suite. This SDK (@t2000/sdk) is the wallet + payments layer; @t2000/id is the Agent ID layer.
Agent directory — programmatic lookup
Discovery is a public JSON API (no auth, no wallet):
// The public directory (same data as agents.t2000.ai)
const dir = await fetch('https://api.t2000.ai/v1/agents?limit=100').then(r => r.json());
// One agent's full identity profile (name · owner · links · on-chain record):
const profile = await fetch(`https://api.t2000.ai/v1/agents/${dir.agents[0].address}`).then(r => r.json());
Registry writes (register / update the identity record) are one-time setup — build raw registry transactions with @t2000/id’s buildRegisterTx / buildUpdateTx and sign with agent.keypair.
Utility Exports
import {
// Key management
generateKeypair, keypairFromPrivateKey, exportPrivateKey, getAddress,
saveKey, loadKey, walletExists,
// Token data
COIN_REGISTRY, TOKEN_MAP, SUI_TYPE, USDC_TYPE,
getDecimalsForCoinType, resolveSymbol, resolveTokenType,
// Asset allowlist
SUPPORTED_ASSETS, SENDABLE_ASSETS, assertAllowedAsset,
GASLESS_MIN_STABLE_AMOUNT, GASLESS_STABLE_TYPES,
// Numbers + formatting
mistToSui, suiToMist, usdcToRaw, rawToUsdc,
formatUsd, formatSui, truncateAddress, validateAddress,
// Sui clients
getSuiClient, getSuiGrpcClient, DEFAULT_GRPC_URL,
// Private Inference inference (standalone — used by t2 chat + the MCP chat tool)
chatCompletion, chatCompletionStream, listModels, DEFAULT_API_BASE,
// Confidential-receipt verifier (signed receipt + trustless Sui anchor)
verifyReceipt,
// Swap overlay-fee receiver for consumer apps building on top of the SDK
T2000_OVERLAY_FEE_WALLET,
} from '@t2000/sdk';
Supported Assets
Token metadata lives in COIN_REGISTRY (packages/sdk/src/token-registry.ts) — coin type, decimals, and symbol for the common tokens. There is no tier gate: USDC is the settlement stable (send / receive / x402 pay); everything else is holdable / swappable. Swaps accept any coin type (Cetus routes); the registry just makes common tokens referenceable by symbol (resolveTokenType('SUI')).
The only per-operation allowlist is send (gasless-eligible stables + SUI) — swap is unrestricted:
import { OPERATION_ASSETS, assertAllowedAsset } from '@t2000/sdk';
OPERATION_ASSETS.send; // ['USDC', 'USDsui', 'SUI']
OPERATION_ASSETS.swap; // '*' (any token)
assertAllowedAsset('send', 'USDY'); // throws — not sendable; swap to USDC first
Gasless
USDC + USDsui sends and x402 USDC payments are gasless. The SDK builds the transaction through SuiGrpcClient so the gasless-eligibility resolver detects the 0x2::balance::send_funds Move call at build time and zeroes out gasPrice / gasBudget / gasPayment automatically (pattern documented at docs.sui.io). Reads + execution run over gRPC (JSON-RPC deactivates 2026-07-31).
Other writes (SUI sends, Cetus swaps) require gas. Keep ~0.05 SUI on hand. The SDK throws INSUFFICIENT_GAS if you run dry.
Consumer apps: sponsored gas via Enoki / zkLogin is the host’s responsibility. The SDK is sponsorship-agnostic — Audric wires Enoki at the host layer (audric/apps/web-v3); the SDK doesn’t know or care.
Configuration
| Env var | Effect |
|---|
T2000_RPC_URL | Legacy alias of T2000_GRPC_URL — resolves a custom Sui gRPC base URL (JSON-RPC is retired). |
T2000_GRPC_URL | Custom Sui gRPC endpoint (defaults to fullnode.mainnet.sui.io). Used during gasless USDC/USDsui send + pay build paths. |
Per-call options like keyPath and rpcUrl are passed to T2000.create() / T2000.init().
Error Handling
import { T2000Error } from '@t2000/sdk';
try {
await agent.send({ to: 'alice.sui', amount: 1000, asset: 'USDC' });
} catch (e) {
if (e instanceof T2000Error) {
// e.code + e.message
}
}
Common codes:
WALLET_NOT_FOUND · WALLET_CORRUPT · INVALID_KEY · INSUFFICIENT_BALANCE · INSUFFICIENT_GAS · INVALID_ADDRESS · INVALID_AMOUNT · INVALID_ASSET · ASSET_NOT_SUPPORTED · SUINS_NOT_REGISTERED · CONTACT_NOT_FOUND · SWAP_NO_ROUTE · SWAP_FAILED · SIMULATION_FAILED · TRANSACTION_FAILED
Architecture
t2000 builds Sui transactions with thin builders — no protocol SDK dependencies needed in user code (Cetus aside).
| Protocol | Integration | Used for |
|---|
| Sui foundation gasless | 0x2::balance::send_funds Move call (built via SuiGrpcClient) | USDC + USDsui transfers, x402 USDC payments |
| Cetus Aggregator V3 | @cetusprotocol/aggregator-sdk (isolated to protocols/cetus-swap.ts) | Multi-DEX swap routing |
| x402 | @suimpp/mpp/x402 (sign-then-settle) | Paid API access — every major AI + data API on mpp.t2000.ai |
Testing
pnpm --filter @t2000/sdk test # unit
SMOKE=1 pnpm --filter @t2000/sdk test -- src/__smoke__ # read-only mainnet smokes