{"version":3,"sources":["../src/errors.ts","../src/preflight.ts","../src/token-registry.ts","../src/wallet/coinSelection.ts","../src/protocols/cetus-swap.ts","../src/swap-quote.ts","../src/constants.ts","../src/utils/sui.ts","../src/wallet/keyManager.ts","../src/wallet/keypairSigner.ts","../src/wallet/executeTx.ts","../src/wallet/pay.ts","../src/wallet/zkLoginSigner.ts","../src/wallet/send.ts","../src/utils/format.ts","../src/wallet/balance.ts","../src/wallet/classify.ts","../src/wallet/history.ts","../src/t2000.ts","../src/utils/suins.ts","../src/limits/config.ts","../src/limits/errors.ts","../src/limits/enforce.ts","../src/index.ts","../src/composeTx.ts","../src/utils/simulate.ts","../src/protocols/suins-leaf.ts"],"names":["T2000Error","PREFLIGHT_MAX_AMOUNT","PREFLIGHT_OK","isValidSuiAddress","normalizeSuiAddress","COIN_REGISTRY","ETH_TYPE","IKA_TYPE","LOFI_TYPE","MANIFEST_TYPE","NAVX_TYPE","SUI_TYPE","TOKEN_MAP","USDC_TYPE","USDE_TYPE","USDSUI_TYPE","USDT_TYPE","WAL_TYPE","WBTC_TYPE","coinWithBalance","requested","swapAll","effectiveAmount","coin","Transaction","OVERLAY_FEE_RATE","BN","AggregatorClient","Env","selectSuiCoin","selectAndSplitCoin","findSwapRoute","resolveTokenType","serializeCetusRoute","SuiGrpcClient","SuiGraphQLClient","resolve","homedir","Ed25519Keypair","decodeSuiPrivateKey","access","mkdir","dirname","writeFile","readFile","fromBase64","buildCoinToAddressBalanceMigration","getDecimalsForCoinType","normalizeStructTag","join","readFileSync","path","existsSync","writeFileSync","DEFAULT_CONFIG_DIR","EventEmitter","buildSwapTx","preflightSwap","getSwapQuote","createPaymentTransactionUri","SuinsTransaction"],"mappings":"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","file":"index.cjs","sourcesContent":["export type T2000ErrorCode =\n  | 'INSUFFICIENT_BALANCE'\n  | 'ADDRESS_BALANCE_UNSPONSORABLE'\n  | 'INSUFFICIENT_GAS'\n  | 'INVALID_ADDRESS'\n  | 'INVALID_AMOUNT'\n  | 'WALLET_NOT_FOUND'\n  | 'WALLET_LOCKED'\n  | 'WALLET_EXISTS'\n  | 'WALLET_CORRUPT'\n  | 'INVALID_KEY'\n  | 'SIMULATION_FAILED'\n  | 'TRANSACTION_FAILED'\n  | 'ASSET_NOT_SUPPORTED'\n  | 'INVALID_ASSET'\n  | 'PROTOCOL_UNAVAILABLE'\n  | 'RPC_ERROR'\n  | 'RPC_UNREACHABLE'\n  | 'PRICE_EXCEEDS_LIMIT'\n  | 'UNSUPPORTED_NETWORK'\n  | 'PAYMENT_EXPIRED'\n  | 'DUPLICATE_PAYMENT'\n  | 'FACILITATOR_REJECTION'\n  | 'CONTACT_NOT_FOUND'\n  | 'INVALID_CONTACT_NAME'\n  | 'SUINS_NOT_REGISTERED'\n  | 'FACILITATOR_TIMEOUT'\n  | 'SAFEGUARD_BLOCKED'\n  | 'SWAP_NO_ROUTE'\n  | 'SWAP_FAILED'\n  | 'CHAIN_MODE_INVALID'\n  | 'UNKNOWN';\n\nexport interface T2000ErrorData {\n  reason?: string;\n  [key: string]: unknown;\n}\n\nexport class T2000Error extends Error {\n  readonly code: T2000ErrorCode;\n  readonly data?: T2000ErrorData;\n  readonly retryable: boolean;\n\n  constructor(code: T2000ErrorCode, message: string, data?: T2000ErrorData, retryable = false) {\n    super(message);\n    this.name = 'T2000Error';\n    this.code = code;\n    this.data = data;\n    this.retryable = retryable;\n  }\n\n  toJSON() {\n    return {\n      error: this.code,\n      message: this.message,\n      ...(this.data && { data: this.data }),\n      retryable: this.retryable,\n    };\n  }\n}\n\nexport function mapWalletError(error: unknown): T2000Error {\n  const msg = error instanceof Error ? error.message : String(error);\n\n  if (msg.includes('rejected') || msg.includes('cancelled')) {\n    return new T2000Error('TRANSACTION_FAILED', 'Transaction cancelled');\n  }\n  if (msg.includes('Insufficient') || msg.includes('insufficient')) {\n    return new T2000Error('INSUFFICIENT_BALANCE', 'Insufficient balance');\n  }\n\n  return new T2000Error('UNKNOWN', msg, undefined, true);\n}\n\nexport function mapMoveAbortCode(code: number): string {\n  const abortMessages: Record<number, string> = {\n    1: 'Protocol is temporarily paused',\n    2: 'Amount must be greater than zero',\n    3: 'Invalid operation type',\n    4: 'Fee rate exceeds maximum',\n    5: 'Insufficient treasury balance',\n    6: 'Not authorized',\n    7: 'Package version mismatch — upgrade required',\n    8: 'Timelock is active — wait for expiry',\n    9: 'No pending change to execute',\n    10: 'Already at current version',\n    // NAVI Protocol abort codes\n    1502: 'Oracle price is stale — try again in a moment',\n    1503: 'Withdrawal amount is invalid (zero or dust) — try a specific amount instead of \"all\"',\n    1600: 'Health factor too low — withdrawal would risk liquidation',\n    1605: 'Asset borrowing is disabled or at capacity on this protocol',\n    // NAVI utils abort codes\n    46000: 'Insufficient balance to repay — withdraw some savings first to get cash',\n  };\n  return abortMessages[code] ?? `Move abort code: ${code}`;\n}\n\n/**\n * Check if an error message contains a MoveAbort — these are on-chain\n * failures that will fail no matter how many times you retry.\n */\nexport function isMoveAbort(msg: string): boolean {\n  return msg.includes('MoveAbort') || msg.includes('MovePrimitiveRuntimeError');\n}\n\nexport function parseMoveAbortMessage(msg: string): string {\n  const abortMatch = msg.match(/abort code:\\s*(\\d+)/i) ?? msg.match(/MoveAbort[^,]*,\\s*(\\d+)/);\n  if (abortMatch) {\n    const code = parseInt(abortMatch[1], 10);\n\n    const moduleMatch = msg.match(/Identifier\\(\"([^\"]+)\"\\)/) ?? msg.match(/in '([^']+)'/);\n    const fnMatch = msg.match(/function_name:\\s*Some\\(\"([^\"]+)\"\\)/);\n    const context = `${moduleMatch?.[1] ?? ''}${fnMatch ? `::${fnMatch[1]}` : ''}`.toLowerCase();\n    const suffix = moduleMatch\n      ? ` [${moduleMatch[1]}${fnMatch ? `::${fnMatch[1]}` : ''}]`\n      : '';\n\n    if (context.includes('slippage')) {\n      return `Slippage too high — price moved during execution${suffix}`;\n    }\n    if (context.includes('balance::split') || context.includes('balance::ENotEnough')) {\n      return `Insufficient on-chain balance${suffix}`;\n    }\n\n    const mapped = mapMoveAbortCode(code);\n    return `${mapped}${suffix}`;\n  }\n  return msg;\n}\n","// Builder-appropriate safety, layer 2 (SPEC_AUDRIC_V3 §7 / safeguards-defense-\n// in-depth.mdc). `preflight()` is CHEAP, PURE, SYNCHRONOUS input validation —\n// no network, no I/O, no context lookup. It runs BEFORE the LLM round-trip /\n// before the tap-to-confirm card, so a malformed intent is rejected without\n// the user ever seeing a confirm for it.\n//\n// Each write builder co-locates its own `preflight*` validator (send.ts →\n// `preflightSend`, pay.ts → `preflightPay`, cetus-swap.ts → `preflightSwap`).\n// This module owns ONLY the shared result type + the two pure primitives those\n// validators compose (amount sanity + sync address validity). The agent-loop\n// guards that read conversation/session state stay in the v3 HOST (they are\n// NOT builder-appropriate, S.442/S.443).\n\nimport { isValidSuiAddress, normalizeSuiAddress } from '@mysten/sui/utils';\nimport type { T2000ErrorCode } from './errors.js';\n\n/**\n * The result of a synchronous preflight check. `valid: false` carries a\n * `T2000ErrorCode` + human message so the host can surface a precise reason\n * (and the builder can rethrow it as a `T2000Error` verbatim).\n */\nexport type PreflightResult =\n  | { valid: true }\n  | { valid: false; code: T2000ErrorCode; error: string };\n\n/**\n * Fat-finger / overflow ceiling for an asset amount. NOT a spending policy\n * (that's the `@t2000/sdk/limits` module — USD-denominated, opt-in, stateful);\n * this is the \"obviously wrong number\" guard the safeguards rule prescribes\n * (`amount > 1_000_000` → unreasonable).\n */\nexport const PREFLIGHT_MAX_AMOUNT = 1_000_000;\n\nexport const PREFLIGHT_OK: PreflightResult = { valid: true };\n\nexport function preflightFail(code: T2000ErrorCode, error: string): PreflightResult {\n  return { valid: false, code, error };\n}\n\n/**\n * Pure positive-finite-amount sanity check (no network). Rejects NaN/Infinity\n * and non-positive values. The absurd-value ceiling defaults to\n * {@link PREFLIGHT_MAX_AMOUNT} but callers can raise it — pass\n * `max: Number.POSITIVE_INFINITY` for swaps of low-unit-value tokens\n * (memecoins legitimately trade in millions/billions of units), where a fixed\n * display-amount ceiling would be a false positive.\n */\nexport function checkPositiveAmount(\n  amount: number,\n  label = 'Amount',\n  max: number = PREFLIGHT_MAX_AMOUNT,\n): PreflightResult {\n  if (typeof amount !== 'number' || !Number.isFinite(amount)) {\n    return preflightFail('INVALID_AMOUNT', `${label} must be a finite number`);\n  }\n  if (amount <= 0) {\n    return preflightFail('INVALID_AMOUNT', `${label} must be greater than zero`);\n  }\n  if (amount > max) {\n    return preflightFail('INVALID_AMOUNT', `${label} ${amount} exceeds the sane maximum (${max})`);\n  }\n  return PREFLIGHT_OK;\n}\n\n/**\n * Pure, synchronous Sui-address validity (no throw, no network) — the\n * non-throwing sibling of `validateAddress`. Use in preflight; use\n * `validateAddress` when you need the normalized form.\n */\nexport function checkSuiAddress(address: string, label = 'recipient'): PreflightResult {\n  try {\n    // `normalizeSuiAddress('')` pads to the zero address (which is \"valid\"), so\n    // guard empty / whitespace-only input before normalizing.\n    if (typeof address === 'string' && address.trim() !== '' &&\n        isValidSuiAddress(normalizeSuiAddress(address))) {\n      return PREFLIGHT_OK;\n    }\n  } catch {\n    // normalizeSuiAddress throws on malformed input → fall through to the fail.\n  }\n  return preflightFail('INVALID_ADDRESS', `Invalid ${label} address: ${address}`);\n}\n","/**\n * Unified token registry — single source of truth for coin types, decimals,\n * and symbols. ZERO heavy dependencies; safe to import anywhere (server,\n * browser, Edge).\n *\n * Used for swap-by-symbol resolution, amount formatting (decimals), and\n * history/balance display. USDC is the settlement stable (send / receive /\n * x402 pay); everything else is holdable / swappable. There is no curated\n * \"tier\" gate — swaps accept any coin type (Cetus routes); the registry just\n * makes the common tokens ergonomic to reference by symbol.\n *\n * To add a token: add ONE entry to COIN_REGISTRY below — everything derives\n * from it.\n */\n\nexport interface CoinMeta {\n  type: string;\n  decimals: number;\n  symbol: string;\n}\n\n/**\n * Canonical coin registry.\n * Key = user-friendly name (used in swap, CLI, prompts).\n */\nexport const COIN_REGISTRY: Record<string, CoinMeta> = {\n  // ── Settlement stable ─────────────────────────────────────────────────\n  USDC:     { type: '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC', decimals: 6, symbol: 'USDC' },\n\n  // ── Common swap assets (symbol ergonomics — any coin type still swaps) ─\n  SUI:      { type: '0x2::sui::SUI', decimals: 9, symbol: 'SUI' },\n  wBTC:     { type: '0x0041f9f9344cac094454cd574e333c4fdb132d7bcc9379bcd4aab485b2a63942::wbtc::WBTC', decimals: 8, symbol: 'wBTC' },\n  ETH:      { type: '0xd0e89b2af5e4910726fbcd8b8dd37bb79b29e5f83f7491bca830e94f7f226d29::eth::ETH', decimals: 8, symbol: 'ETH' },\n  GOLD:     { type: '0x9d297676e7a4b771ab023291377b2adfaa4938fb9080b8d12430e4b108b836a9::xaum::XAUM', decimals: 9, symbol: 'GOLD' },\n  DEEP:     { type: '0xdeeb7a4662eec9f2f3def03fb937a663dddaa2e215b8078a284d026b7946c270::deep::DEEP', decimals: 6, symbol: 'DEEP' },\n  WAL:      { type: '0x356a26eb9e012a68958082340d4c4116e7f55615cf27affcff209cf0ae544f59::wal::WAL', decimals: 9, symbol: 'WAL' },\n  NS:       { type: '0x5145494a5f5100e645e4b0aa950fa6b68f614e8c59e17bc5ded3495123a79178::ns::NS', decimals: 6, symbol: 'NS' },\n  IKA:      { type: '0x7262fb2f7a3a14c888c438a3cd9b912469a58cf60f367352c46584262e8299aa::ika::IKA', decimals: 9, symbol: 'IKA' },\n  CETUS:    { type: '0x06864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS', decimals: 9, symbol: 'CETUS' },\n  NAVX:     { type: '0xa99b8952d4f7d947ea77fe0ecdcc9e5fc0bcab2841d6e2a5aa00c3044e5544b5::navx::NAVX', decimals: 9, symbol: 'NAVX' },\n  vSUI:     { type: '0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT', decimals: 9, symbol: 'vSUI' },\n  haSUI:    { type: '0xbde4ba4c2e274a60ce15c1cfff9e5c42e41654ac8b6d906a57efa4bd3c29f47d::hasui::HASUI', decimals: 9, symbol: 'haSUI' },\n  afSUI:    { type: '0xf325ce1300e8dac124071d3152c5c5ee6174914f8bc2161e88329cf579246efc::afsui::AFSUI', decimals: 9, symbol: 'afSUI' },\n  LOFI:     { type: '0xf22da9a24ad027cccb5f2d496cbe91de953d363513db08a3a734d361c7c17503::LOFI::LOFI', decimals: 9, symbol: 'LOFI' },\n  MANIFEST: { type: '0xc466c28d87b3d5cd34f3d5c088751532d71a38d93a8aae4551dd56272cfb4355::manifest::MANIFEST', decimals: 9, symbol: 'MANIFEST' },\n\n  // ── Other stables (display / classification) ──────────────────────────\n  USDT:     { type: '0x375f70cf2ae4c00bf37117d0c85a2c71545e6ee05c4a5c7d282cd66a4504b068::usdt::USDT', decimals: 6, symbol: 'USDT' },\n  USDe:     { type: '0x41d587e5336f1c86cad50d38a7136db99333bb9bda91cea4ba69115defeb1402::sui_usde::SUI_USDE', decimals: 6, symbol: 'USDe' },\n  USDSUI:   { type: '0x44f838219cf67b058f3b37907b655f226153c18e33dfcd0da559a844fea9b1c1::usdsui::USDSUI', decimals: 6, symbol: 'USDsui' },\n};\n\n/** Reverse lookup: coin type → CoinMeta. Built once at import time. */\nconst BY_TYPE = new Map<string, CoinMeta>();\nfor (const meta of Object.values(COIN_REGISTRY)) {\n  BY_TYPE.set(meta.type, meta);\n}\n\n// ── Lookup helpers ───────────────────────────────────────────────────────\n\n/**\n * Returns the registry metadata for a coin type, or `undefined` if the coin\n * is not in the registry. Used for canonical-symbol + decimal resolution.\n */\nexport function getCoinMeta(coinType: string): CoinMeta | undefined {\n  return BY_TYPE.get(coinType);\n}\n\n/**\n * Returns true if the coin type appears in COIN_REGISTRY. Useful as a\n * canonical-symbol gate — e.g. so the registry's mixed-case `USDsui` wins\n * over a vendor feed's uppercase `USDSUI`.\n */\nexport function isInRegistry(coinType: string): boolean {\n  return BY_TYPE.has(coinType);\n}\n\n// ── Lookup helpers ───────────────────────────────────────────────────────\n\n/**\n * Get decimals for any coin type. Checks full type match, then suffix match,\n * then defaults to 9. Works for any token, registered or not.\n */\nexport function getDecimalsForCoinType(coinType: string): number {\n  const direct = BY_TYPE.get(coinType);\n  if (direct) return direct.decimals;\n\n  const suffix = coinType.split('::').slice(1).join('::').toUpperCase();\n  if (suffix) {\n    for (const meta of BY_TYPE.values()) {\n      const metaSuffix = meta.type.split('::').slice(1).join('::').toUpperCase();\n      if (metaSuffix === suffix) return meta.decimals;\n    }\n  }\n\n  return 9;\n}\n\n/** Minimal structural client — just the coin-metadata read this needs. */\ninterface CoinMetadataClient {\n  core: { getCoinMetadata: (opts: { coinType: string }) => Promise<unknown> };\n}\n\n/**\n * [2.11] Decimals for any coin type, resolved correctly for arbitrary tokens.\n * Registry tokens return their known decimals (no network). A coin type NOT in\n * the registry is read ON-CHAIN via coin metadata — never the 9-default guess,\n * because a wrong `from` decimal would corrupt a swap's input amount\n * (financial-amounts rule). Falls back to the registry heuristic only if the\n * on-chain read fails or returns no usable decimals.\n */\nexport async function resolveCoinDecimals(\n  client: CoinMetadataClient,\n  coinType: string,\n): Promise<number> {\n  if (isInRegistry(coinType)) return getDecimalsForCoinType(coinType);\n  try {\n    const res = (await client.core.getCoinMetadata({ coinType })) as {\n      metadata?: { decimals?: number };\n      decimals?: number;\n    };\n    const d = res?.metadata?.decimals ?? res?.decimals;\n    if (typeof d === 'number' && Number.isFinite(d)) return d;\n  } catch {\n    /* on-chain read failed — fall through to the registry heuristic */\n  }\n  return getDecimalsForCoinType(coinType);\n}\n\n/**\n * Resolve a full coin type to a user-friendly symbol.\n * Returns the last `::` segment if not in the registry.\n */\nexport function resolveSymbol(coinType: string): string {\n  const direct = BY_TYPE.get(coinType);\n  if (direct) return direct.symbol;\n\n  const suffix = coinType.split('::').slice(1).join('::').toUpperCase();\n  if (suffix) {\n    for (const meta of BY_TYPE.values()) {\n      const metaSuffix = meta.type.split('::').slice(1).join('::').toUpperCase();\n      if (metaSuffix === suffix) return meta.symbol;\n    }\n  }\n\n  return coinType.split('::').pop() ?? coinType;\n}\n\n/**\n * Name → type map for swap resolution. Derived from COIN_REGISTRY.\n * Contains BOTH original-case and UPPERCASE keys for case-insensitive lookup.\n */\nexport const TOKEN_MAP: Record<string, string> = (() => {\n  const map: Record<string, string> = {};\n  for (const [name, meta] of Object.entries(COIN_REGISTRY)) {\n    map[name] = meta.type;\n    map[name.toUpperCase()] = meta.type;\n  }\n  return map;\n})();\n\n/**\n * Resolve a user-friendly token name to its full coin type.\n * Returns the input unchanged if already a full coin type (contains \"::\").\n * Case-insensitive: 'usde', 'USDe', 'USDE' all resolve correctly.\n */\nexport function resolveTokenType(nameOrType: string): string | null {\n  if (nameOrType.includes('::')) return nameOrType;\n  return TOKEN_MAP[nameOrType] ?? TOKEN_MAP[nameOrType.toUpperCase()] ?? null;\n}\n\n/** Common type constants for direct import. */\nexport const SUI_TYPE = COIN_REGISTRY.SUI.type;\nexport const USDC_TYPE = COIN_REGISTRY.USDC.type;\nexport const USDT_TYPE = COIN_REGISTRY.USDT.type;\nexport const USDSUI_TYPE = COIN_REGISTRY.USDSUI.type;\nexport const USDE_TYPE = COIN_REGISTRY.USDe.type;\nexport const ETH_TYPE = COIN_REGISTRY.ETH.type;\nexport const WBTC_TYPE = COIN_REGISTRY.wBTC.type;\nexport const WAL_TYPE = COIN_REGISTRY.WAL.type;\nexport const NAVX_TYPE = COIN_REGISTRY.NAVX.type;\nexport const IKA_TYPE = COIN_REGISTRY.IKA.type;\nexport const LOFI_TYPE = COIN_REGISTRY.LOFI.type;\nexport const MANIFEST_TYPE = COIN_REGISTRY.MANIFEST.type;\n","/**\n * Wallet-side coin selection helpers — single source of truth for the\n * \"produce a `Coin<T>` argument holding `amount` raw units of `coinType`,\n * owned by `address`\" pattern. Used by every wallet-mode appender that\n * needs a coin input (save, send, swap, repay, stake, etc.).\n *\n * **2026-05-22 — address-balance migration.** Sui mainnet's address-balance\n * feature ships funds account-style instead of as discrete `Coin<T>` objects.\n * After a payment via `0x2::balance::send_funds`, the leftover lands in the\n * sender's address balance with a synthetic \"coin reservation\" representing\n * the deposit. `client.getCoins()` correctly filters those reservations out\n * (they aren't real owned objects), so the old fetch+merge+split pattern\n * threw `INSUFFICIENT_BALANCE` for users whose stables had drifted into\n * address balance — even when `getBalance().totalBalance` showed plenty.\n *\n * The fix is structural: hand the work to `coinWithBalance({ type, balance })`\n * from `@mysten/sui/transactions`. Its build-time resolver inspects coins +\n * address balance together (`getBalance` + `listCoins`), then emits the\n * right shape — direct `redeem_funds` from address balance when AB ≥\n * required, or merge-and-split across coins + AB withdrawal when not. Multi\n * intents per coin type get batched into a single merge in one PTB, so the\n * old per-PTB merge cache is no longer needed.\n *\n * Pre-flight uses `client.getBalance().totalBalance` (sums coins + AB)\n * instead of summing the paginated `getCoins` page. That's the OTHER half\n * of the migration — the legacy path could see `0` from `getCoins` and\n * mistakenly throw before `coinWithBalance` ever ran.\n */\nimport {\n  Transaction,\n  coinWithBalance,\n  type TransactionObjectArgument,\n} from '@mysten/sui/transactions';\nimport type { SuiCoreClient } from '../utils/sui.js';\nimport { T2000Error } from '../errors.js';\n\nexport interface CoinPage {\n  ids: string[];\n  totalBalance: bigint;\n}\n\n/**\n * Sum every coin of `coinType` owned by `owner`, INCLUDING address balance.\n * Returns the IDs of any discrete coin objects that exist (callers\n * occasionally need this for non-`coinWithBalance` paths, e.g. SUIns name\n * registration which expects raw object IDs).\n *\n * Pre-2026-05-22 this function paginated `client.getCoins` and summed\n * the page balances. That misses address-balance funds (the SDK filters\n * them out of `getCoins` for back-compat). The new implementation calls\n * `getBalance` for the canonical total and `getCoins` for the optional\n * ID list — both round-trips, but they happen in parallel.\n */\nexport async function fetchAllCoins(\n  client: SuiCoreClient,\n  owner: string,\n  coinType: string,\n): Promise<CoinPage> {\n  const [balance, ids] = await Promise.all([\n    client.core.getBalance({ owner, coinType }),\n    (async () => {\n      const out: string[] = [];\n      let cursor: string | null | undefined;\n      let hasNext = true;\n      while (hasNext) {\n        const page = await client.core.listCoins({ owner, coinType, cursor: cursor ?? undefined });\n        for (const c of page.objects) out.push(c.objectId);\n        cursor = page.cursor;\n        hasNext = page.hasNextPage;\n      }\n      return out;\n    })(),\n  ]);\n  return { ids, totalBalance: BigInt(balance.balance.balance) };\n}\n\nexport interface SelectAndSplitResult {\n  /** TransactionObjectArgument for a coin holding `effectiveAmount` raw units. */\n  coin: TransactionObjectArgument;\n  /** Actual raw amount the returned coin holds. May be < requested if `swapAll` is true. */\n  effectiveAmount: bigint;\n  /** True iff the request consumed the entire wallet balance (no split needed). */\n  swapAll: boolean;\n}\n\n/**\n * Wallet-mode coin selection prelude. Pre-flights against\n * `getBalance().totalBalance` (coins + address balance combined), then\n * returns a `coinWithBalance({ type, balance })` argument that the\n * `@mysten/sui` resolver fulfills at build time.\n *\n * Throws `T2000Error` (`INSUFFICIENT_BALANCE`) when:\n * - `amount` is bigger than the total balance AND the caller did NOT\n *   opt into `swapAll: true` clipping.\n * - `amount === 'all'` AND total balance is zero.\n *\n * @param tx — PTB to register the `coinWithBalance` intent against.\n * @param client — Sui RPC client for the pre-flight `getBalance` lookup.\n * @param owner — wallet address whose coins to source from.\n * @param coinType — fully-qualified Sui coin type (e.g. `\"0x...::usdc::USDC\"`).\n * @param amount — raw amount to source (in MIST / smallest unit). Pass\n *   `'all'` to consume the entire balance.\n * @param options.allowSwapAll — if true (default), `amount` >= totalBalance\n *   auto-clips to total. If false, throws when the request would over-consume.\n * @param options.sponsoredContext — when true, source ONLY from discrete coin\n *   objects (never the address balance). See the long note below — this exists\n *   because Enoki's gas station can't yet deserialize a `TransactionData` that\n *   contains the address-balance `FundsWithdrawal` reservation that\n *   `coinWithBalance` emits. Self-funded callers leave this false: the fullnode\n *   handles `FundsWithdrawal` fine, so the address-balance path is preferred\n *   (it can reach funds that aren't held as coin objects).\n *\n * @returns\n *   - `coin` — `TransactionObjectArgument` ready for downstream consumption.\n *   - `effectiveAmount` — the raw amount the returned coin holds (handles\n *     swapAll clipping).\n *   - `swapAll` — true iff the entire balance was consumed.\n */\nexport async function selectAndSplitCoin(\n  tx: Transaction,\n  client: SuiCoreClient,\n  owner: string,\n  coinType: string,\n  amount: bigint | 'all',\n  options: {\n    allowSwapAll?: boolean;\n    sponsoredContext?: boolean;\n    mergeCache?: SponsoredCoinMergeCache;\n  } = {},\n): Promise<SelectAndSplitResult> {\n  // [2026-05-30] Sponsored Enoki path — coin objects only. `coinWithBalance`\n  // reaches into the address balance (mysten Address Balances feature) when\n  // `addressBalance >= required`, emitting `0x2::coin::redeem_funds` + a\n  // `FundsWithdrawal` reservation input. That input is a newer `TransactionData`\n  // field; Enoki's sponsor endpoint accepts the kind bytes (200) but its gas\n  // station rejects the assembled `TransactionData` at execute with\n  // \"Invalid bcs bytes for TransactionData\". The fullnode parses it fine — only\n  // Enoki can't (yet). So under sponsorship we source from discrete coin objects\n  // and surface a clear error when the user's funds are address-balance-only.\n  // See github.com/mission69b/t2000 issue #93.\n  if (options.sponsoredContext) {\n    return selectCoinObjectsOnly(\n      tx,\n      client,\n      owner,\n      coinType,\n      amount,\n      options.allowSwapAll ?? true,\n      options.mergeCache,\n    );\n  }\n\n  const balanceResp = await client.core.getBalance({ owner, coinType });\n  const totalBalance = BigInt(balanceResp.balance.balance);\n\n  if (totalBalance === 0n) {\n    throw new T2000Error('INSUFFICIENT_BALANCE', `No balance found for ${coinType}`);\n  }\n\n  const allowSwapAll = options.allowSwapAll ?? true;\n\n  if (amount !== 'all' && amount > totalBalance && !allowSwapAll) {\n    throw new T2000Error('INSUFFICIENT_BALANCE', `Insufficient balance for ${coinType}`, {\n      available: totalBalance.toString(),\n      required: amount.toString(),\n    });\n  }\n\n  const requested = amount === 'all' ? totalBalance : amount;\n  const swapAll = amount === 'all' || requested >= totalBalance;\n  const effectiveAmount = swapAll ? totalBalance : requested;\n\n  const coin = coinWithBalance({ type: coinType, balance: effectiveAmount })(tx);\n\n  return { coin, effectiveAmount, swapAll };\n}\n\n/**\n * Coin-object-only selection for sponsored (Enoki) transactions. Fetches the\n * owner's discrete `Coin<T>` objects (NOT the address balance — `getCoins`\n * excludes it), merges them, and splits the requested amount. Never emits a\n * `FundsWithdrawal` reservation, so the resulting `TransactionData` stays on\n * the shape Enoki's gas station can serialize.\n *\n * Throws `ADDRESS_BALANCE_UNSPONSORABLE` when the coin objects don't cover the\n * request — which, for a user whose `getBalance().totalBalance` shows funds,\n * means those funds live in the address balance (e.g. received via a gasless\n * stablecoin transfer) and can't be moved through a sponsored transaction yet.\n */\n/**\n * Per-PTB cache of merged sponsored coin-object primaries, keyed by coin\n * type. The FIRST `selectCoinObjectsOnly` call for a given coin type in a\n * PTB fetches the owner's discrete `Coin<T>` objects, merges them into one\n * `primary`, and records it here alongside the remaining (unspent) balance.\n * EVERY subsequent leg sourcing the same coin type splits from that cached\n * `primary` instead of re-fetching + re-merging.\n *\n * Why this exists (S.xxx, 2026-06-02): a sponsored bundle with 2+ legs\n * sourcing the same coin (e.g. `SUI→WAL` + `SUI→DEEP`, or `swap USDC` +\n * `save USDC`) called `selectCoinObjectsOnly` once per leg. Each call\n * emitted its own `mergeCoins` over the SAME coin objects, so the second\n * leg's merge referenced coins the first leg already consumed → Enoki\n * dry-run failed with `CommandArgumentError { ArgumentWithoutValue }`.\n *\n * This is NOT SUI-specific. Under sponsorship, `selectAndSplitCoin` routes\n * EVERY asset through `selectCoinObjectsOnly` (the `coinWithBalance`\n * batching that would otherwise dedup these merges only runs for\n * non-sponsored CLI/direct flows — its address-balance `FundsWithdrawal`\n * reservation is what Enoki can't deserialize, issue #93). So the cache is\n * the dedup layer for ALL coin types in a sponsored multi-leg PTB, keyed\n * by coin type. SUI was simply the first asset observed failing in the\n * wild because it's the most common swap source.\n */\nexport type SponsoredCoinMergeCache = Map<\n  string,\n  { primary: TransactionObjectArgument; remaining: bigint }\n>;\n\nasync function selectCoinObjectsOnly(\n  tx: Transaction,\n  client: SuiCoreClient,\n  owner: string,\n  coinType: string,\n  amount: bigint | 'all',\n  allowSwapAll: boolean,\n  mergeCache?: SponsoredCoinMergeCache,\n): Promise<SelectAndSplitResult> {\n  // Cache hit — a prior leg in THIS PTB already merged this coin type's\n  // objects into `cached.primary`. Re-running the fetch+merge below would\n  // emit a second `mergeCoins` over already-consumed coins → dry-run\n  // `ArgumentWithoutValue`. Split from the cached primary instead.\n  const cached = mergeCache?.get(coinType);\n  if (cached) {\n    const requested = amount === 'all' ? cached.remaining : amount;\n    if (cached.remaining === 0n || requested > cached.remaining) {\n      throw new T2000Error(\n        'ADDRESS_BALANCE_UNSPONSORABLE',\n        `Not enough ${coinType} in coin objects to cover all legs of this ` +\n          `sponsored bundle. The remaining funds are in your address balance, ` +\n          `which sponsored transactions can't access yet.`,\n        { remaining: cached.remaining.toString(), requested: requested.toString(), coinType },\n      );\n    }\n    const swapAll = amount === 'all' || requested >= cached.remaining;\n    const effectiveAmount = swapAll ? cached.remaining : requested;\n    const coin = swapAll\n      ? cached.primary\n      : tx.splitCoins(cached.primary, [effectiveAmount])[0];\n    cached.remaining -= effectiveAmount;\n    return { coin, effectiveAmount, swapAll };\n  }\n\n  const objects: { objectId: string; balance: bigint }[] = [];\n  let coinObjectTotal = 0n;\n  let cursor: string | null | undefined;\n  let hasNext = true;\n  while (hasNext) {\n    const page = await client.core.listCoins({ owner, coinType, cursor: cursor ?? undefined });\n    for (const c of page.objects) {\n      objects.push({ objectId: c.objectId, balance: BigInt(c.balance) });\n      coinObjectTotal += BigInt(c.balance);\n    }\n    cursor = page.cursor;\n    hasNext = page.hasNextPage;\n  }\n\n  const unsponsorable = (): T2000Error =>\n    new T2000Error(\n      'ADDRESS_BALANCE_UNSPONSORABLE',\n      `These funds are in your address balance, which sponsored transactions ` +\n        `can't access yet. (Funds received via gasless transfers land there.) ` +\n        `This will work once the gas sponsor adds address-balance support.`,\n      { coinObjectTotal: coinObjectTotal.toString(), coinType },\n    );\n\n  if (coinObjectTotal === 0n) {\n    throw unsponsorable();\n  }\n\n  const requested = amount === 'all' ? coinObjectTotal : amount;\n  if (requested > coinObjectTotal) {\n    // Not enough in coin objects. If the caller allows clipping to the\n    // available coin-object total (\"swap all\"), do so; otherwise the shortfall\n    // is sitting in the address balance → unsponsorable.\n    if (allowSwapAll && amount === 'all') {\n      // unreachable (requested === coinObjectTotal here) — kept for clarity.\n    } else {\n      throw unsponsorable();\n    }\n  }\n\n  const swapAll = amount === 'all' || requested >= coinObjectTotal;\n  const effectiveAmount = swapAll ? coinObjectTotal : requested;\n\n  const [first, ...rest] = objects;\n  const primary = tx.object(first.objectId);\n  if (rest.length > 0) {\n    tx.mergeCoins(\n      primary,\n      rest.map((o) => tx.object(o.objectId)),\n    );\n  }\n\n  // Consume the whole merged coin when taking everything; otherwise split the\n  // exact amount and leave the remainder on the (sender-owned) primary coin.\n  const coin = swapAll ? primary : tx.splitCoins(primary, [effectiveAmount])[0];\n\n  // Record the merged primary so later legs in the same PTB reuse it\n  // rather than re-fetching + re-merging the same (now-consumed) coins.\n  // When `swapAll`, the primary was consumed (remaining 0) — a later leg\n  // hitting the cache then throws the unsponsorable shortfall above.\n  mergeCache?.set(coinType, {\n    primary,\n    remaining: coinObjectTotal - effectiveAmount,\n  });\n\n  return { coin, effectiveAmount, swapAll };\n}\n\n/**\n * Build a GASLESS coin→address-balance migration.\n *\n * Sends WHOLE `Coin<T>` objects to `owner`'s OWN SIP-58 address balance via\n * `0x2::coin::send_funds(coin, owner)` — one allowlisted framework MoveCall\n * per coin, with NO native `SplitCoins` / `MergeCoins` commands. That shape is\n * what makes it gasless: the gRPC build resolver only zeros gas for PTBs whose\n * every command is a MoveCall into the `0x2` gasless allowlist (`send_funds` /\n * `redeem_funds` / `withdrawal_split` / `into_balance`). The same eligibility\n * the gasless `balance::send_funds` send + the x402 `redeem_funds`+`send_funds`\n * withdrawal rely on. (The old migration merged+split first → native commands →\n * fell outside the allowlist → needed SUI. See `pay.ts ensureAddressBalanceCovers`.)\n *\n * Selects the FEWEST coins (largest first) whose combined balance covers\n * `minAmount`, minimizing the MoveCall count. Over-migration is harmless — the\n * surplus just lands in the address balance. Pure / network-free: callers pass\n * coins they've already fetched, so this is unit-testable offline.\n *\n * Throws `INSUFFICIENT_BALANCE` when the supplied coin objects can't cover\n * `minAmount`.\n */\nexport function buildCoinToAddressBalanceMigration(args: {\n  coins: { objectId: string; balance: bigint }[];\n  coinType: string;\n  owner: string;\n  minAmount: bigint;\n}): { tx: Transaction; migratedRaw: bigint } {\n  const { coins, coinType, owner, minAmount } = args;\n\n  // Largest first → fewest whole-coin sends to cover the shortfall.\n  const sorted = [...coins]\n    .filter((c) => c.balance > 0n)\n    .sort((a, b) => (b.balance > a.balance ? 1 : b.balance < a.balance ? -1 : 0));\n\n  const selected: { objectId: string; balance: bigint }[] = [];\n  let migratedRaw = 0n;\n  for (const c of sorted) {\n    if (migratedRaw >= minAmount) break;\n    selected.push(c);\n    migratedRaw += c.balance;\n  }\n\n  if (migratedRaw < minAmount) {\n    throw new T2000Error('INSUFFICIENT_BALANCE', `Insufficient ${coinType} coin objects to migrate`, {\n      available: migratedRaw.toString(),\n      required: minAmount.toString(),\n    });\n  }\n\n  const tx = new Transaction();\n  for (const c of selected) {\n    tx.moveCall({\n      target: '0x2::coin::send_funds',\n      typeArguments: [coinType],\n      arguments: [tx.object(c.objectId), tx.pure.address(owner)],\n    });\n  }\n  return { tx, migratedRaw };\n}\n\n/**\n * SUI-specific coin selection. Branches on sponsorship context:\n *\n * - **Self-funded (`sponsoredContext: false`)** — splits from `tx.gas`\n *   directly (the user's gas coin IS their SUI). More efficient — no\n *   `getBalance` RTT.\n *\n * - **Sponsored (`sponsoredContext: true`)** — sources from the user's\n *   discrete SUI coin objects (`selectCoinObjectsOnly`). This both (a) avoids\n *   `tx.gas`, which belongs to the Enoki sponsor — NOT the user — under\n *   sponsored flows (the original S.260 reason for `useGasCoin: false`), AND\n *   (b) avoids `coinWithBalance`'s address-balance `FundsWithdrawal`, which\n *   Enoki's gas station can't deserialize (issue #93). If the user's SUI is\n *   address-balance-only, it raises `ADDRESS_BALANCE_UNSPONSORABLE`.\n */\nexport async function selectSuiCoin(\n  tx: Transaction,\n  client: SuiCoreClient,\n  owner: string,\n  amountMist: bigint,\n  sponsoredContext: boolean,\n  mergeCache?: SponsoredCoinMergeCache,\n): Promise<SelectAndSplitResult> {\n  if (sponsoredContext) {\n    const { SUI_TYPE } = await import('../token-registry.js');\n    return selectCoinObjectsOnly(tx, client, owner, SUI_TYPE, amountMist, false, mergeCache);\n  }\n\n  const [coin] = tx.splitCoins(tx.gas, [amountMist]);\n  return { coin, effectiveAmount: amountMist, swapAll: false };\n}\n","/**\n * Cetus Aggregator V3 SDK wrapper — the ONLY file that imports @cetusprotocol/aggregator-sdk.\n * Documented CLAUDE.md exception: multi-DEX routing cannot be feasibly replaced by thin tx builders.\n *\n * [B5 v2 / @t2000/sdk@1.1.0 / 2026-04-30]\n * Overlay fee config is now per-call instead of a module-level singleton. CLI / direct\n * SDK callers (`T2000.swap()`) DON'T pass `overlayFee` → fee-free swap. Audric's\n * prepare/route.ts ALWAYS passes `overlayFee = { rate: OVERLAY_FEE_RATE, receiver:\n * T2000_OVERLAY_FEE_WALLET }` → fee charged. Structural inclusion (Audric's code can't\n * forget to pass it because it IS the code), not a toggle that defaults to safe.\n *\n * Pre-1.1.0: a module-level `OVERLAY_FEE_RECEIVER` constant defaulted to a Move object\n * ID. USDC sent there became OwnedObjects keyed to the object and was inaccessible.\n * Fixed by making the receiver a regular wallet address (T2000_OVERLAY_FEE_WALLET) AND\n * by removing the singleton pattern that hid the misconfig.\n */\nimport { AggregatorClient, Env, type FindRouterParams, type RouterDataV3 } from '@cetusprotocol/aggregator-sdk';\nimport { Transaction, type TransactionObjectArgument } from '@mysten/sui/transactions';\nimport BN from 'bn.js';\nimport { resolveTokenType, getDecimalsForCoinType } from '../token-registry.js';\nimport type { SuiCoreClient } from '../utils/sui.js';\nimport type { SponsoredCoinMergeCache } from '../wallet/coinSelection.js';\nimport {\n  type PreflightResult,\n  PREFLIGHT_OK,\n  preflightFail,\n  checkPositiveAmount,\n} from '../preflight.js';\n\n/**\n * Synchronous, network-free preflight for `swap`. Validates the from/to token\n * args + amount sanity, and rejects an identity swap — the cheap checks the\n * host runs before routing. Returns a `PreflightResult`; never throws.\n * Route-finding, liquidity, slippage + decimals resolution stay in the async\n * path (`findSwapRoute`/`buildSwapTx`/`getSwapQuote`).\n *\n * v3 drops the swap *tool*, but `swap` survives as an SDK/CLI builder (§8) so\n * it gets the same builder-appropriate preflight as send/pay.\n */\nexport function preflightSwap(input: {\n  from: string;\n  to: string;\n  amount: number;\n}): PreflightResult {\n  if (typeof input.from !== 'string' || input.from.trim() === '') {\n    return preflightFail('INVALID_ASSET', 'A `from` token is required to swap');\n  }\n  if (typeof input.to !== 'string' || input.to.trim() === '') {\n    return preflightFail('INVALID_ASSET', 'A `to` token is required to swap');\n  }\n\n  // No upper ceiling — swaps route arbitrary tokens, and low-unit-value tokens\n  // legitimately trade in millions/billions of units.\n  const amountCheck = checkPositiveAmount(input.amount, 'Amount', Number.POSITIVE_INFINITY);\n  if (!amountCheck.valid) return amountCheck;\n\n  // Identity swap is a no-op the router can't route — catch it cheaply.\n  // Resolve symbol → coin type so \"USDC\" and the USDC coin type compare equal.\n  // Guard the null===null case (two unknown symbols both resolve to null) by\n  // also requiring the resolved value to be non-null, falling back to a raw\n  // string compare.\n  const resolvedFrom = resolveTokenType(input.from);\n  const resolvedTo = resolveTokenType(input.to);\n  const sameToken =\n    input.from.trim() === input.to.trim() ||\n    (resolvedFrom !== null && resolvedFrom === resolvedTo);\n  if (sameToken) {\n    return preflightFail('INVALID_ASSET', `Cannot swap ${input.from} to itself`);\n  }\n\n  return PREFLIGHT_OK;\n}\n\nexport interface OverlayFeeConfig {\n  /** Fee rate as a fraction (e.g. 0.001 = 0.1%). Pass 0 to disable. */\n  rate: number;\n  /** Wallet address that receives the overlay fee. */\n  receiver: string;\n}\n\nexport interface SwapRouteResult {\n  routerData: RouterDataV3;\n  amountIn: string;\n  amountOut: string;\n  byAmountIn: boolean;\n  priceImpact: number;\n  insufficientLiquidity: boolean;\n}\n\n// [SPEC 20.2 / D-1 (a)] Typed JSON-friendly representation of a Cetus\n// `RouterDataV3` for cross-process / cross-network transport. The native\n// shape contains `BN` instances (`bn.js`) and a `Map<string, string>`\n// (`packages`) that don't survive JSON.stringify / JSON.parse cleanly:\n// - `BN.toJSON()` returns the internal `{negative,words,length,red}` blob\n// - `Map.toJSON()` returns `{}`\n// Round-tripping via `serializeCetusRoute` + `deserializeCetusRoute`\n// converts BN ↔ decimal string and Map ↔ Record. Engine + audric both\n// reference fields by path (`route.routerData.paths[i].provider`) without\n// needing to know about the underlying BN/Map types.\nexport interface SerializedCetusRoutePath {\n  id: string;\n  direction: boolean;\n  provider: string;\n  from: string;\n  target: string;\n  feeRate: number;\n  amountIn: string;\n  amountOut: string;\n  version?: string;\n  publishedAt?: string;\n  extendedDetails?: Record<string, unknown>;\n}\n\nexport interface SerializedRouterDataV3 {\n  quoteID?: string;\n  /** RouterDataV3.amountIn (BN) → decimal string */\n  amountIn: string;\n  /** RouterDataV3.amountOut (BN) → decimal string */\n  amountOut: string;\n  byAmountIn: boolean;\n  paths: SerializedCetusRoutePath[];\n  insufficientLiquidity: boolean;\n  deviationRatio: number;\n  /** RouterDataV3.packages (Map) → Record */\n  packages?: Record<string, string>;\n  totalDeepFee?: number;\n  error?: { code: number; msg: string };\n  overlayFee?: number;\n}\n\nexport interface SerializedCetusRoute {\n  routerData: SerializedRouterDataV3;\n  amountIn: string;\n  amountOut: string;\n  byAmountIn: boolean;\n  priceImpact: number;\n  insufficientLiquidity: boolean;\n  /**\n   * Wall-clock timestamp (ms since epoch) at which the route was discovered.\n   * Used by audric's prepare-route for SPEC 20.2 D-3 TTL re-validation: if\n   * the route is older than the threshold AND price impact has shifted\n   * beyond tolerance, fall back to a fresh `findSwapRoute()` call.\n   */\n  discoveredAt: number;\n  /**\n   * Snapshot of the input/output coin types the route was discovered for.\n   * SPEC 20.2 D-2 (b) structural verification: prepare-route asserts\n   * input/output coins match before using the fast-path; mismatch falls\n   * back to fresh discovery (defense against client-side tampering and\n   * against legitimate token-type drift in the request).\n   */\n  fromCoinType: string;\n  toCoinType: string;\n}\n\nexport function serializeCetusRoute(\n  route: SwapRouteResult,\n  context: { fromCoinType: string; toCoinType: string },\n): SerializedCetusRoute {\n  return {\n    routerData: serializeRouterDataV3(route.routerData),\n    amountIn: route.amountIn,\n    amountOut: route.amountOut,\n    byAmountIn: route.byAmountIn,\n    priceImpact: route.priceImpact,\n    insufficientLiquidity: route.insufficientLiquidity,\n    discoveredAt: Date.now(),\n    fromCoinType: context.fromCoinType,\n    toCoinType: context.toCoinType,\n  };\n}\n\nexport function deserializeCetusRoute(serialized: SerializedCetusRoute): SwapRouteResult {\n  return {\n    routerData: deserializeRouterDataV3(serialized.routerData),\n    amountIn: serialized.amountIn,\n    amountOut: serialized.amountOut,\n    byAmountIn: serialized.byAmountIn,\n    priceImpact: serialized.priceImpact,\n    insufficientLiquidity: serialized.insufficientLiquidity,\n  };\n}\n\nfunction serializeRouterDataV3(rd: RouterDataV3): SerializedRouterDataV3 {\n  const out: SerializedRouterDataV3 = {\n    amountIn: rd.amountIn.toString(),\n    amountOut: rd.amountOut.toString(),\n    byAmountIn: rd.byAmountIn,\n    paths: rd.paths.map(serializeCetusRoutePath),\n    insufficientLiquidity: rd.insufficientLiquidity,\n    deviationRatio: rd.deviationRatio,\n  };\n  if (rd.quoteID !== undefined) out.quoteID = rd.quoteID;\n  if (rd.packages) {\n    const obj: Record<string, string> = {};\n    for (const [k, v] of rd.packages) obj[k] = v;\n    out.packages = obj;\n  }\n  if (rd.totalDeepFee !== undefined) out.totalDeepFee = rd.totalDeepFee;\n  if (rd.error) out.error = { code: rd.error.code, msg: rd.error.msg };\n  if (rd.overlayFee !== undefined) out.overlayFee = rd.overlayFee;\n  return out;\n}\n\nfunction deserializeRouterDataV3(s: SerializedRouterDataV3): RouterDataV3 {\n  const out: RouterDataV3 = {\n    amountIn: new BN(s.amountIn),\n    amountOut: new BN(s.amountOut),\n    byAmountIn: s.byAmountIn,\n    paths: s.paths.map(deserializeCetusRoutePath),\n    insufficientLiquidity: s.insufficientLiquidity,\n    deviationRatio: s.deviationRatio,\n  };\n  if (s.quoteID !== undefined) out.quoteID = s.quoteID;\n  if (s.packages) out.packages = new Map(Object.entries(s.packages));\n  if (s.totalDeepFee !== undefined) out.totalDeepFee = s.totalDeepFee;\n  if (s.error) out.error = { code: s.error.code, msg: s.error.msg };\n  if (s.overlayFee !== undefined) out.overlayFee = s.overlayFee;\n  return out;\n}\n\nfunction serializeCetusRoutePath(p: RouterDataV3['paths'][number]): SerializedCetusRoutePath {\n  const out: SerializedCetusRoutePath = {\n    id: p.id,\n    direction: p.direction,\n    provider: p.provider,\n    from: p.from,\n    target: p.target,\n    feeRate: p.feeRate,\n    amountIn: p.amountIn,\n    amountOut: p.amountOut,\n  };\n  if (p.version !== undefined) out.version = p.version;\n  if (p.publishedAt !== undefined) out.publishedAt = p.publishedAt;\n  if (p.extendedDetails) out.extendedDetails = { ...p.extendedDetails };\n  return out;\n}\n\nfunction deserializeCetusRoutePath(p: SerializedCetusRoutePath): RouterDataV3['paths'][number] {\n  const out: RouterDataV3['paths'][number] = {\n    id: p.id,\n    direction: p.direction,\n    provider: p.provider,\n    from: p.from,\n    target: p.target,\n    feeRate: p.feeRate,\n    amountIn: p.amountIn,\n    amountOut: p.amountOut,\n  };\n  if (p.version !== undefined) out.version = p.version;\n  if (p.publishedAt !== undefined) out.publishedAt = p.publishedAt;\n  if (p.extendedDetails) out.extendedDetails = { ...p.extendedDetails };\n  return out;\n}\n\n/**\n * SPEC 20.2 D-2 (b) structural verification helper. Returns true when the\n * serialized route matches the requested coin types (i.e. it's safe to use\n * as the prepare-route fast-path), false otherwise (tampered, or input\n * mismatch from a legitimate but stale pending action). Caller falls back\n * to a fresh `findSwapRoute()` call when verification fails.\n */\nexport function verifyCetusRouteCoinMatch(\n  serialized: SerializedCetusRoute,\n  expected: { fromCoinType: string; toCoinType: string },\n): boolean {\n  return serialized.fromCoinType === expected.fromCoinType && serialized.toCoinType === expected.toCoinType;\n}\n\n/**\n * SPEC 20.2 D-3 (b) TTL helper. Returns true when the serialized route is\n * fresh enough to use as the fast-path (< `maxAgeMs` old). Returns false\n * for stale routes — caller falls back to fresh `findSwapRoute()` to pick\n * up any pool-price drift since route discovery.\n *\n * Default 30s aligns with the existing quote-freshness contract surfaced\n * to users via `pending_action.quoteAge` (the PermissionCard \"QUOTE Ns OLD\"\n * badge starts warning the user past 30s).\n */\nexport function isCetusRouteFresh(serialized: SerializedCetusRoute, maxAgeMs: number = 30_000): boolean {\n  return Date.now() - serialized.discoveredAt < maxAgeMs;\n}\n\n/**\n * Default Audric swap overlay fee — 0.1%. Exported for consumers that want to use\n * the canonical Audric rate (the Audric prepare-route does this). Changing this\n * rate requires a coordinated SDK + audric release.\n */\nexport const OVERLAY_FEE_RATE = 0.001;\n\n/**\n * Cache `AggregatorClient` instances by `(signer + overlay rate + overlay receiver)`.\n * Per-call instantiation is cheap (the client is mostly config), but caching avoids\n * pointless re-allocation when the same caller swaps multiple times in a loop.\n */\nconst clientCache = new Map<string, AggregatorClient>();\n\nfunction getClient(walletAddress: string, overlayFee?: OverlayFeeConfig): AggregatorClient {\n  const rate = overlayFee?.rate ?? 0;\n  const receiver = overlayFee?.receiver ?? '';\n  const key = `${walletAddress}|${rate}|${receiver}`;\n\n  const cached = clientCache.get(key);\n  if (cached) return cached;\n\n  const client = new AggregatorClient({\n    signer: walletAddress,\n    env: Env.Mainnet,\n    ...(rate > 0 && receiver\n      ? { overlayFeeRate: rate, overlayFeeReceiver: receiver }\n      : {}),\n  });\n  clientCache.set(key, client);\n  return client;\n}\n\n/**\n * [Bug A defense-in-depth / 2026-05-10] Returns true when every path\n * provider in `route.routerData.paths` is present in the active\n * `providers` allow-list. Cetus's `getProvidersExcluding(...)` returns\n * an inclusion list (the complement of the exclusion), so when a caller\n * passes `providers`, every walked provider must be IN that list to be\n * compatible.\n *\n * When `providers` is undefined (non-sponsored caller, e.g. CLI) every\n * route is compatible — same semantics as `findSwapRoute` itself.\n *\n * Why per-path: a Cetus aggregator route can split across multiple DEXes\n * (e.g. 60% Cetus + 40% Bluefin). A single excluded provider in any path\n * triggers `tx.gas` usage in `routerSwap`. Reject the whole route if any\n * leg is excluded.\n */\nexport function isPrecomputedRouteCompatibleWithProviders(\n  route: SwapRouteResult,\n  providers: string[] | undefined,\n): boolean {\n  if (!providers || providers.length === 0) return true;\n  const allowed = new Set(providers);\n  for (const path of route.routerData.paths) {\n    if (!allowed.has(path.provider)) return false;\n  }\n  return true;\n}\n\n/**\n * Find the optimal swap route via Cetus Aggregator REST API.\n *\n * Pass `overlayFee` to charge an overlay fee on the output (Audric's pattern).\n * Omit it for a fee-free swap (CLI / direct SDK pattern).\n */\nexport async function findSwapRoute(params: {\n  walletAddress: string;\n  from: string;\n  to: string;\n  amount: bigint;\n  byAmountIn: boolean;\n  overlayFee?: OverlayFeeConfig;\n  /**\n   * Optional Cetus provider allow-list. When omitted, all 30+ DEXes\n   * are eligible. Sponsored flows (Enoki) MUST pass an exclusion list\n   * computed via `getProvidersExcluding([...])` from the Cetus SDK to\n   * remove Pyth-dependent providers (HAEDALPMM, METASTABLE, OBRIC,\n   * STEAMM_OMM, STEAMM_OMM_V2, SEVENK, HAEDALHMMV2) — those reference\n   * `tx.gas` for oracle fees, which Enoki rejects in sponsored txs.\n   * Non-sponsored callers (CLI, direct SDK) leave this undefined.\n   */\n  providers?: string[];\n}): Promise<SwapRouteResult | null> {\n  const client = getClient(params.walletAddress, params.overlayFee);\n\n  const findParams: FindRouterParams = {\n    from: params.from,\n    target: params.to,\n    amount: params.amount.toString(),\n    byAmountIn: params.byAmountIn,\n    ...(params.providers ? { providers: params.providers } : {}),\n  };\n\n  const routerData = await client.findRouters(findParams);\n  if (!routerData) return null;\n\n  if (routerData.insufficientLiquidity) {\n    return {\n      routerData,\n      amountIn: routerData.amountIn.toString(),\n      amountOut: routerData.amountOut.toString(),\n      byAmountIn: params.byAmountIn,\n      priceImpact: normalizePriceImpact(routerData.deviationRatio),\n      insufficientLiquidity: true,\n    };\n  }\n\n  if (routerData.error) {\n    const { T2000Error } = await import('../errors.js');\n    throw new T2000Error('SWAP_FAILED', `Cetus routing error: ${routerData.error.msg} (code ${routerData.error.code})`);\n  }\n\n  return {\n    routerData,\n    amountIn: routerData.amountIn.toString(),\n    amountOut: routerData.amountOut.toString(),\n    byAmountIn: params.byAmountIn,\n    priceImpact: normalizePriceImpact(routerData.deviationRatio),\n    insufficientLiquidity: false,\n  };\n}\n\n/**\n * Cetus' aggregator types `deviationRatio` as `number`, but in some routes\n * the router actually returns a string (\"0.001234\"). The SDK type lies, so we\n * always coerce to a finite number here (NaN/null/undefined → 0). Without\n * this every downstream consumer that calls `priceImpact.toFixed(...)` will\n * crash at runtime — including the Audric SwapQuoteCard, which takes the\n * whole chat UI down through its error boundary.\n */\nfunction normalizePriceImpact(value: unknown): number {\n  const n = typeof value === 'number' ? value : Number(value);\n  return Number.isFinite(n) ? n : 0;\n}\n\n/**\n * Build a swap PTB from a route result. The caller must provide an input coin\n * obtained by splitting/merging wallet coins.\n *\n * **Important:** Cetus's `routerSwap` reads the overlay-fee config from the\n * AggregatorClient instance. The `overlayFee` param here MUST match the one\n * passed to `findSwapRoute` for the same swap (otherwise you'll hit the cache\n * boundary and get a different client with different overlay config).\n */\nexport async function buildSwapTx(params: {\n  walletAddress: string;\n  route: SwapRouteResult;\n  tx: Transaction;\n  inputCoin: TransactionObjectArgument;\n  slippage: number;\n  overlayFee?: OverlayFeeConfig;\n}): Promise<TransactionObjectArgument> {\n  const client = getClient(params.walletAddress, params.overlayFee);\n  const clampedSlippage = Math.max(0.001, Math.min(params.slippage, 0.05));\n\n  const outputCoin = await client.routerSwap({\n    router: params.route.routerData,\n    inputCoin: params.inputCoin,\n    slippage: clampedSlippage,\n    txb: params.tx,\n  });\n\n  return outputCoin;\n}\n\n/**\n * Append a swap fragment to an existing PTB. SPEC 7 § \"Layer 1\" Cetus\n * appender. Two modes, dispatched by the presence of `input.inputCoin`:\n *\n * - **Wallet mode** (`inputCoin` omitted) — sources `from`-asset funds\n *   via `coinWithBalance({ type, balance })` (resolves coin objects +\n *   address balance at build time), runs the swap. Mirrors the audric\n *   host's `transactions/prepare/route.ts` swap branch (P2.2c will\n *   retire that branch in favor of this appender via `composeTx`).\n *\n * - **Chain mode** (`inputCoin` provided) — consumes the passed-in coin\n *   reference (typically produced by an upstream appender like\n *   `addWithdrawToTx`) directly, no wallet fetch / no merge / no\n *   split. This is the SPEC 7 multi-write enabler (\"withdraw → swap →\n *   save\" without intermediate wallet materialization).\n *\n * **SUI in wallet mode:** ALWAYS sources through `selectSuiCoin` (which\n * routes via `coinWithBalance({ type: SUI, useGasCoin: false })` under\n * sponsored flows, OR `tx.splitCoins(tx.gas, ...)` under self-funded\n * flows). The caller MUST set `sponsoredContext` correctly — otherwise\n * sponsored swaps with SUI source fail with `Cannot use GasCoin as a\n * transaction argument` (Enoki owns `tx.gas`, the PTB body referencing\n * it as an argument is invalid for sponsorship). 2.14.0 shipped without\n * this branch and broke audric/web-v2 SUI→USDC swaps; restored in 2.14.1\n * (S.260). For non-sponsored flows (CLI), `T2000.swap()` pre-builds the\n * inputCoin via `tx.splitCoins(tx.gas, [rawAmount])[0]` and uses chain\n * mode, sidestepping wallet-mode entirely — this branch is a defensive\n * safety net for future direct SDK users who pass SUI in wallet mode.\n *\n * **`swapAll` semantics (wallet mode):** if the requested raw amount\n * is >= the wallet's total `from` balance, the appender consumes the\n * entire merged primary coin (not a split), matching audric's host\n * route's `swapAll` clipping. The returned `effectiveAmountIn` reflects\n * the actual consumed amount in display units.\n *\n * **Slippage:** clamped to [0.001, 0.05] (0.1% – 5%). Defaults to 0.01.\n *\n * @returns\n * - `coin` — output coin reference, ready for downstream consumption\n *   (e.g. `addSaveToTx`) or wallet transfer (`tx.transferObjects`).\n * - `effectiveAmountIn` — display-units input amount the swap actually\n *   consumes (handles `swapAll` clipping in wallet mode; in chain mode\n *   echoes the requested `input.amount`).\n * - `expectedAmountOut` — display-units output amount per the route\n *   quote. Actual on-chain output may differ within slippage.\n * - `route` — raw `SwapRouteResult` for downstream telemetry / logging.\n */\nexport async function addSwapToTx(\n  tx: Transaction,\n  client: SuiCoreClient,\n  address: string,\n  input: {\n    from: string;\n    to: string;\n    amount: number;\n    slippage?: number;\n    byAmountIn?: boolean;\n    overlayFee?: OverlayFeeConfig;\n    inputCoin?: TransactionObjectArgument;\n    /**\n     * Optional Cetus provider allow-list. Forwarded to `findSwapRoute`.\n     * Sponsored flows (Enoki) MUST pass `getProvidersExcluding([...])`\n     * to remove Pyth-dependent providers — see `findSwapRoute`'s JSDoc\n     * for the exclusion list. Non-sponsored callers omit this.\n     */\n    providers?: string[];\n    /**\n     * [SPEC 20.2 D-3 (b)] Precomputed route from a prior `findSwapRoute()`\n     * call (typically captured by `swap_quote` and threaded through\n     * `pending_action.cetusRoute`). When present AND not stale (per\n     * `isCetusRouteFresh`) AND the input/output coins match, this skips\n     * the ~400-500ms `findSwapRoute()` discovery call. Stale routes are\n     * silently ignored (caller falls back to fresh discovery).\n     *\n     * Caller responsibility: pass the SAME `overlayFee` / `providers` /\n     * `byAmountIn` that produced the precomputed route. Mismatch will\n     * still produce a working swap but may use the wrong overlay-fee\n     * config (the route data already encodes the chosen DEX path).\n     */\n    precomputedRoute?: SwapRouteResult;\n    /**\n     * Whether this swap is being built inside a sponsored-tx flow (Enoki)\n     * vs self-funded (CLI / direct sign). Load-bearing for SUI-source\n     * swaps in wallet mode: under sponsored flows, `tx.gas` belongs to\n     * the sponsor and CANNOT be referenced as a transaction argument\n     * (Sui protocol rejects with `Cannot use GasCoin as a transaction\n     * argument`). When `true`, SUI source routes through `selectSuiCoin`\n     * with `useGasCoin: false` so the resolver sources from the user's\n     * SUI coin objects + address balance instead. Defaults to `false`\n     * (back-compat — pre-2.14.1 behavior). Audric/web-v2's compose path\n     * threads this through via `composeTx({ sponsoredContext: true })`.\n     */\n    sponsoredContext?: boolean;\n    /**\n     * Per-PTB merge cache for sponsored coin-object sourcing (any coin\n     * type — SUI in the dedicated branch, USDC/USDsui/etc. in the wallet\n     * branch). Provided by `composeTx`'s orchestration loop so multiple\n     * legs sourcing the same coin in one bundle share a single merged\n     * primary coin instead of each emitting its own `mergeCoins` (the\n     * second of which references already-consumed coins → Enoki dry-run\n     * `ArgumentWithoutValue`). Single swaps don't need it; omit. See\n     * `SponsoredCoinMergeCache` JSDoc.\n     */\n    coinMergeCache?: SponsoredCoinMergeCache;\n  },\n): Promise<{\n  coin: TransactionObjectArgument;\n  effectiveAmountIn: number;\n  expectedAmountOut: number;\n  route: SwapRouteResult;\n  /** True when `precomputedRoute` was used (no `findSwapRoute()` call). */\n  usedPrecomputedRoute: boolean;\n}> {\n  const { T2000Error } = await import('../errors.js');\n\n  const fromType = resolveTokenType(input.from);\n  const toType = resolveTokenType(input.to);\n  if (!fromType) throw new T2000Error('ASSET_NOT_SUPPORTED', `Unknown token: ${input.from}. Provide the symbol (USDC, SUI, ...) or full coin type.`);\n  if (!toType) throw new T2000Error('ASSET_NOT_SUPPORTED', `Unknown token: ${input.to}. Provide the symbol (USDC, SUI, ...) or full coin type.`);\n  if (fromType === toType) throw new T2000Error('SWAP_FAILED', 'Cannot swap a token to itself');\n  if (!Number.isFinite(input.amount) || input.amount <= 0) {\n    throw new T2000Error('INVALID_AMOUNT', 'Amount must be greater than zero');\n  }\n\n  const fromDecimals = getDecimalsForCoinType(fromType);\n  const toDecimals = getDecimalsForCoinType(toType);\n  const requestedRaw = BigInt(Math.floor(input.amount * 10 ** fromDecimals));\n\n  const slippage = Math.max(0.001, Math.min(input.slippage ?? 0.01, 0.05));\n  const byAmountIn = input.byAmountIn ?? true;\n\n  let inputCoin: TransactionObjectArgument;\n  let effectiveRaw: bigint;\n\n  if (input.inputCoin) {\n    inputCoin = input.inputCoin;\n    effectiveRaw = requestedRaw;\n  } else if (fromType === '0x2::sui::SUI') {\n    // SUI source needs special handling: under sponsored flows (Enoki),\n    // referencing `tx.gas` as a transaction argument is forbidden (sponsor\n    // owns the gas coin). `selectSuiCoin` does the right thing for both\n    // sponsored (uses `coinWithBalance({ useGasCoin: false })`) and\n    // self-funded (splits from `tx.gas` directly). The 2.14.0 release\n    // shipped without this branch and broke audric/web-v2 SUI→USDC swaps\n    // (\"Cannot use GasCoin as a transaction argument\" from Enoki); fixed\n    // in 2.14.1 (S.260).\n    const { selectSuiCoin } = await import('../wallet/coinSelection.js');\n    const result = await selectSuiCoin(\n      tx,\n      client,\n      address,\n      requestedRaw,\n      input.sponsoredContext ?? false,\n      input.coinMergeCache,\n    );\n    inputCoin = result.coin;\n    effectiveRaw = result.effectiveAmount;\n  } else {\n    // Non-SUI wallet-mode source — delegate to the canonical prelude.\n    // NON-sponsored: pre-flights against `getBalance().totalBalance` and\n    // returns a `coinWithBalance({ type, balance })` arg, whose `@mysten/sui`\n    // resolver batches all intents for a coin type into a single build-time\n    // merge — so same-asset multi-leg bundles dedup automatically.\n    //\n    // SPONSORED: routes through `selectCoinObjectsOnly` instead (coinWithBalance's\n    // address-balance `FundsWithdrawal` reservation is what Enoki can't\n    // deserialize, issue #93). That manual path has NO build-time batching, so\n    // two legs sourcing the same coin would each emit their own `mergeCoins`\n    // over the SAME objects → second merge references consumed coins → Enoki\n    // dry-run `ArgumentWithoutValue`. The `coinMergeCache` supplies the dedup:\n    // first leg merges once + caches the primary, later legs split from it.\n    const { selectAndSplitCoin } = await import('../wallet/coinSelection.js');\n    const result = await selectAndSplitCoin(tx, client, address, fromType, requestedRaw, {\n      sponsoredContext: input.sponsoredContext ?? false,\n      mergeCache: input.coinMergeCache,\n    });\n    inputCoin = result.coin;\n    effectiveRaw = result.effectiveAmount;\n  }\n\n  // [SPEC 20.2 D-3 (b)] Use the precomputed route when available + valid.\n  // Validity = same input/output coin types AND the requested raw amount\n  // matches what the route was discovered for (mismatch indicates the user\n  // edited the amount post-quote, in which case we must re-discover at the\n  // new amount because price impact is amount-dependent). The caller\n  // (`audric prepare-route`) owns the staleness check (`isCetusRouteFresh`)\n  // and only forwards `precomputedRoute` when fresh.\n  //\n  // [Bug A defense-in-depth / 2026-05-10] Even with the engine fix that\n  // makes `swap_quote` discover sponsor-safe routes, this layer also\n  // validates the precomputed route against the active providers\n  // allow-list. If the route walks any excluded provider (e.g. a stale\n  // `pending_action.cetusRoute` from before the engine fix shipped, or a\n  // provider list that drifted between quote and execute), fall back to\n  // fresh discovery. Better to eat 400ms than to let a Pyth-dependent\n  // route reach Enoki and revert with HTTP 400.\n  let route: SwapRouteResult | null;\n  let usedPrecomputedRoute = false;\n  if (\n    input.precomputedRoute &&\n    input.precomputedRoute.amountIn === effectiveRaw.toString() &&\n    input.precomputedRoute.byAmountIn === byAmountIn &&\n    isPrecomputedRouteCompatibleWithProviders(input.precomputedRoute, input.providers)\n  ) {\n    route = input.precomputedRoute;\n    usedPrecomputedRoute = true;\n  } else {\n    route = await findSwapRoute({\n      walletAddress: address,\n      from: fromType,\n      to: toType,\n      amount: effectiveRaw,\n      byAmountIn,\n      overlayFee: input.overlayFee,\n      providers: input.providers,\n    });\n  }\n\n  if (!route) {\n    throw new T2000Error('SWAP_NO_ROUTE', `No swap route found for ${input.from} → ${input.to}`);\n  }\n  if (route.insufficientLiquidity) {\n    throw new T2000Error('SWAP_NO_ROUTE', `Insufficient liquidity for ${input.from} → ${input.to}`);\n  }\n\n  const outputCoin = await buildSwapTx({\n    walletAddress: address,\n    route,\n    tx,\n    inputCoin,\n    slippage,\n    overlayFee: input.overlayFee,\n  });\n\n  return {\n    coin: outputCoin,\n    effectiveAmountIn: Number(effectiveRaw) / 10 ** fromDecimals,\n    expectedAmountOut: Number(route.amountOut) / 10 ** toDecimals,\n    route,\n    usedPrecomputedRoute,\n  };\n}\n\n// Re-export from the canonical token registry for backward-compat.\nexport { TOKEN_MAP, resolveTokenType } from '../token-registry.js';\n","/**\n * Standalone swap quote — no T2000 agent instance required.\n * Only needs a wallet address for Cetus Aggregator routing.\n */\nimport { T2000Error } from './errors.js';\nimport { getDecimalsForCoinType } from './token-registry.js';\nimport type { SwapQuoteResult } from './types.js';\n\nexport async function getSwapQuote(params: {\n  walletAddress: string;\n  from: string;\n  to: string;\n  amount: number;\n  byAmountIn?: boolean;\n  /**\n   * [Bug A fix / 2026-05-10] Optional Cetus provider allow-list, forwarded to\n   * `findSwapRoute`. Sponsored callers (Enoki) MUST pass\n   * `getSponsoredSwapProviders()` to remove Pyth-dependent providers\n   * (HAEDALPMM, METASTABLE, OBRIC, STEAMM_OMM/_V2, SEVENK, HAEDALHMMV2).\n   * Those providers cause the Cetus aggregator's internal `routerSwap` to\n   * insert a `tx.splitCoins(tx.gas, ...)` call for the Pyth update fee,\n   * which Enoki rejects with HTTP 400 \"Cannot use GasCoin as a transaction\n   * argument\" (3-step bundle smoke 2026-05-10).\n   *\n   * Pre-fix: `getSwapQuote` discovered routes against the FULL provider set,\n   * stashed Pyth-dependent routes onto `pending_action.cetusRoute` (SPEC\n   * 20.2 fast-path), and the audric `prepare` route's `swap_execute`\n   * appender used the precomputed route AS-IS — bypassing the providers\n   * filter that `composeTx` correctly applied. Result: every swap whose\n   * best route happened to include a Pyth-dependent provider failed at\n   * Enoki sponsorship.\n   *\n   * Non-sponsored callers (e.g. CLI direct swap) leave this undefined to\n   * keep access to the full provider set including Pyth-dependent pools.\n   */\n  providers?: string[];\n  /**\n   * [2.11] On-chain-resolved decimals for `from` / `to`, supplied by callers\n   * that hold a client (e.g. `T2000.swapQuote`). When omitted (standalone /\n   * sponsored callers), falls back to the registry — correct for registry\n   * tokens, a 9-decimal guess for an unknown coin type.\n   */\n  fromDecimals?: number;\n  toDecimals?: number;\n}): Promise<SwapQuoteResult> {\n  const { findSwapRoute, resolveTokenType } = await import('./protocols/cetus-swap.js');\n\n  const fromType = resolveTokenType(params.from);\n  const toType = resolveTokenType(params.to);\n  // [S.123 v1.24.7] Use T2000Error('ASSET_NOT_SUPPORTED') consistently with the\n  // other 4 throw sites in t2000.ts / cetus-swap.ts. Allows tools to branch\n  // on `err.code === 'ASSET_NOT_SUPPORTED'` and return a structured recovery\n  // hint to the LLM instead of re-throwing a generic error string.\n  if (!fromType) {\n    throw new T2000Error(\n      'ASSET_NOT_SUPPORTED',\n      `Unknown token: ${params.from}. Provide the symbol (USDC, SUI, ...) or full coin type.`,\n    );\n  }\n  if (!toType) {\n    throw new T2000Error(\n      'ASSET_NOT_SUPPORTED',\n      `Unknown token: ${params.to}. Provide the symbol (USDC, SUI, ...) or full coin type.`,\n    );\n  }\n\n  const byAmountIn = params.byAmountIn ?? true;\n\n  const fromDecimals = params.fromDecimals ?? getDecimalsForCoinType(fromType);\n  const rawAmount = BigInt(Math.floor(params.amount * 10 ** fromDecimals));\n\n  const route = await findSwapRoute({\n    walletAddress: params.walletAddress,\n    from: fromType,\n    to: toType,\n    amount: rawAmount,\n    byAmountIn,\n    providers: params.providers,\n  });\n\n  if (!route) throw new T2000Error('SWAP_FAILED', `No swap route found for ${params.from} -> ${params.to}.`);\n  if (route.insufficientLiquidity) {\n    throw new T2000Error('SWAP_FAILED', `Insufficient liquidity for ${params.from} -> ${params.to}.`);\n  }\n\n  const toDecimals = params.toDecimals ?? getDecimalsForCoinType(toType);\n  const fromAmount = Number(route.amountIn) / 10 ** fromDecimals;\n  const toAmount = Number(route.amountOut) / 10 ** toDecimals;\n\n  const routeDesc = route.routerData.paths\n    ?.map((p: { provider?: string }) => p.provider)\n    .filter(Boolean)\n    .slice(0, 3)\n    .join(' + ') ?? 'Cetus Aggregator';\n\n  // [SPEC 20.2 / D-1 (a)] Serialize the Cetus route at quote time so the\n  // engine can attach it to `pending_action.cetusRoute`. The serialized\n  // form survives the SSE → client → POST → prepare-route hop without losing\n  // BN/Map fidelity (raw RouterDataV3 doesn't JSON-stringify cleanly).\n  const { serializeCetusRoute } = await import('./protocols/cetus-swap.js');\n  const serializedRoute = serializeCetusRoute(route, { fromCoinType: fromType, toCoinType: toType });\n\n  return {\n    fromToken: params.from,\n    toToken: params.to,\n    fromAmount,\n    toAmount,\n    priceImpact: route.priceImpact,\n    route: routeDesc,\n    serializedRoute,\n  };\n}\n","import { T2000Error } from './errors.js';\n\nexport const MIST_PER_SUI = 1_000_000_000n;\nexport const SUI_DECIMALS = 9;\nexport const USDC_DECIMALS = 6;\n\nexport const PRECISION = 1_000_000_000_000_000_000n;\n\nexport const MIN_DEPOSIT = 1_000_000n; // 1 USDC (6 decimals)\n\nexport const CLOCK_ID = '0x6';\n\nexport const SUPPORTED_ASSETS = {\n  USDC: {\n    type: '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC',\n    decimals: 6,\n    symbol: 'USDC',\n    displayName: 'USDC',\n  },\n  USDT: {\n    type: '0x375f70cf2ae4c00bf37117d0c85a2c71545e6ee05c4a5c7d282cd66a4504b068::usdt::USDT',\n    decimals: 6,\n    symbol: 'USDT',\n    displayName: 'suiUSDT',\n  },\n  USDe: {\n    type: '0x41d587e5336f1c86cad50d38a7136db99333bb9bda91cea4ba69115defeb1402::sui_usde::SUI_USDE',\n    decimals: 6,\n    symbol: 'USDe',\n    displayName: 'suiUSDe',\n  },\n  USDsui: {\n    type: '0x44f838219cf67b058f3b37907b655f226153c18e33dfcd0da559a844fea9b1c1::usdsui::USDSUI',\n    decimals: 6,\n    symbol: 'USDsui',\n    displayName: 'USDsui',\n  },\n  SUI: {\n    type: '0x2::sui::SUI',\n    decimals: 9,\n    symbol: 'SUI',\n    displayName: 'SUI',\n  },\n  WAL: {\n    type: '0x356a26eb9e012a68958082340d4c4116e7f55615cf27affcff209cf0ae544f59::wal::WAL',\n    decimals: 9,\n    symbol: 'WAL',\n    displayName: 'WAL',\n  },\n  ETH: {\n    type: '0xd0e89b2af5e4910726fbcd8b8dd37bb79b29e5f83f7491bca830e94f7f226d29::eth::ETH',\n    decimals: 8,\n    symbol: 'ETH',\n    displayName: 'suiETH',\n  },\n  NAVX: {\n    type: '0xa99b8952d4f7d947ea77fe0ecdcc9e5fc0bcab2841d6e2a5aa00c3044e5544b5::navx::NAVX',\n    decimals: 9,\n    symbol: 'NAVX',\n    displayName: 'NAVX',\n  },\n  GOLD: {\n    type: '0x9d297676e7a4b771ab023291377b2adfaa4938fb9080b8d12430e4b108b836a9::xaum::XAUM',\n    decimals: 6,\n    symbol: 'GOLD',\n    displayName: 'XAUM',\n  },\n} as const;\n\nexport type SupportedAsset = keyof typeof SUPPORTED_ASSETS;\n\n// [SPEC_AGENTIC_STACK P1 / SDK F3 — 2026-05-25]\n// `StableAsset` = \"what we treat as worth $1 for wallet pricing and balance roll-up\".\n// Pre-Phase 1: USDC only — left USDsui wallet holdings invisible to balance.ts.\n// Phase 1: widened to USDC + USDsui (both are NAVI-native stables with $1 peg).\n// USDT / USDe stay OUT of this set deliberately — they are stables, but the\n// codebase has never priced them at $1, and adding them here would require\n// auditing balance.ts callers downstream. Keep the carve minimal.\nexport type StableAsset = 'USDC' | 'USDsui';\nexport const STABLE_ASSETS: readonly StableAsset[] = ['USDC', 'USDsui'] as const;\n\n// ---------------------------------------------------------------------------\n// Operation → allowed asset rules (single source of truth)\n// ---------------------------------------------------------------------------\n\n// [v4.0 Phase A Day 2 — 2026-05-26] `send` is constrained to\n// `['USDC', 'USDsui', 'SUI']`. Rationale (SPEC_AGENT_WALLET_GREENFIELD §A):\n// - USDC + USDsui are gasless via `0x2::balance::send_funds` (Sui mainnet\n//   protocol allowlist) — the two foundation stables.\n// - SUI is the only non-stable kept on the allowlist so users with no\n//   stablecoin balance can still pay gas-native SUI transfers.\n// - USDT, USDe, WAL, ETH, NAVX, GOLD are NOT sendable — users must swap to\n//   USDC/USDsui first (one-step) or hold SUI and use a manual Move call.\n// `swap` is unrestricted (Cetus routes any pair). The DeFi operations\n// (save/borrow/withdraw/repay) were removed with NAVI.\nexport const OPERATION_ASSETS = {\n  send: ['USDC', 'USDsui', 'SUI'],\n  swap: '*',\n} as const;\n\nexport type Operation = keyof typeof OPERATION_ASSETS;\n\nexport function isAllowedAsset(op: Operation, asset: string): boolean {\n  const allowed = OPERATION_ASSETS[op];\n  if (allowed === '*') return true;\n  // [v0.51.0] Mixed-case canonical keys (USDsui, suiUSDT) need case-insensitive\n  // membership. Pre-v0.51 we only had USDC ↔ USDC (uppercase identity), so\n  // a one-sided uppercase compare looked correct. Now that USDsui is in the\n  // set, normalize both sides.\n  const target = asset.toLowerCase();\n  return (allowed as readonly string[]).some((a) => a.toLowerCase() === target);\n}\n\n/**\n * Throws if the asset is not permitted for the given operation.\n *\n * [v4.0 Phase A Day 2] Pre-v4 this allowed `undefined` as a silent default\n * to USDC. Removed because every write path now requires explicit asset\n * (see `T2000.send` + `buildSendTx` + `composeTx.send_transfer`). The\n * `undefined → no-op` branch is kept defensively; the `send_transfer` flow\n * validates non-undefined.\n */\nexport function assertAllowedAsset(op: Operation, asset: string | undefined): void {\n  if (!asset) return;\n  if (!isAllowedAsset(op, asset)) {\n    const allowed = OPERATION_ASSETS[op];\n    const list = Array.isArray(allowed) ? allowed.join(', ') : 'any';\n    const swapHint =\n      op === 'send' ? ' Swap to USDC or USDsui first, or send SUI.' : '';\n    throw new T2000Error(\n      'INVALID_ASSET',\n      `${op} only supports ${list}. Cannot use ${asset}.${swapHint}`,\n    );\n  }\n}\n\n/**\n * [v4.0 Phase A Day 2] Narrow type alias for assets sendable through the\n * Agent Wallet. Matches `OPERATION_ASSETS.send` exactly. Exported so the\n * CLI / SDK / composeTx can share one type without re-declaring it.\n */\nexport type SendableAsset = 'USDC' | 'USDsui' | 'SUI';\nexport const SENDABLE_ASSETS: readonly SendableAsset[] = ['USDC', 'USDsui', 'SUI'] as const;\n\n/**\n * [v4.0 Phase A Day 2] Coin types for the two gasless-allowlisted stables.\n * Used by `wallet/send.ts` + `composeTx.send_transfer` to construct the\n * `0x2::balance::send_funds` Move call's `typeArguments`. SUI is excluded\n * because SUI transfers are NOT gasless (gas-native, uses `tx.gas` split +\n * `transferObjects` per the existing path).\n */\nexport const GASLESS_STABLE_TYPES: Record<'USDC' | 'USDsui', string> = {\n  USDC: SUPPORTED_ASSETS.USDC.type,\n  USDsui: SUPPORTED_ASSETS.USDsui.type,\n};\n\n// Swap overlay fees route here. Audric's prepare/route.ts passes\n// `overlayFee.receiver = T2000_OVERLAY_FEE_WALLET` to the Cetus aggregator. The\n// CLI/SDK never charge fees — this constant is exported for consumer apps only.\n//\n// Address corresponds to the treasury admin wallet. Override via env for local dev /\n// testnet only — production must use the canonical mainnet address below.\nexport const T2000_OVERLAY_FEE_WALLET = process.env.T2000_OVERLAY_FEE_WALLET\n  ?? '0x5366efbf2b4fe5767fe2e78eb197aa5f5d138d88ac3333fbf3f80a1927da473a';\n\nexport const DEFAULT_NETWORK = 'mainnet' as const;\n// gRPC fullnode endpoint. Post-flip this is the canonical transport for the\n// whole SDK: `getSuiClient()` (reads + execution) AND `getSuiGrpcClient()`\n// (gasless stablecoin build detection) both target it. Override the read/exec\n// client with T2000_RPC_URL and the build client with T2000_GRPC_URL.\nexport const DEFAULT_RPC_URL = 'https://fullnode.mainnet.sui.io:443';\nexport const DEFAULT_GRPC_URL = 'https://fullnode.mainnet.sui.io:443';\n// [gRPC migration] GraphQL endpoint for the query surface that has NO gRPC\n// `core` equivalent — `transactionBlocks` (history). Used by\n// `getSuiGraphQLClient()`. The canonical mainnet host is `graphql.mainnet.sui.io`\n// (parallel to the gRPC fullnode); the older `sui-mainnet.mystenlabs.com/graphql`\n// host was dropped 2026-06-15 after it began resetting TLS connections (live\n// smoke). Public endpoint is rate-limited — production hosts override with\n// T2000_GRAPHQL_URL to a dedicated provider.\nexport const DEFAULT_GRAPHQL_URL = 'https://graphql.mainnet.sui.io/graphql';\nexport const DEFAULT_KEY_PATH = '~/.t2000/wallet.key';\nexport const DEFAULT_CONFIG_PATH = '~/.t2000/config.json';\n\n// [v4.0 Phase A Day 2] Minimum stablecoin amount for protocol-level gasless\n// transfers via `0x2::balance::send_funds`. The Sui mainnet allowlist enforces\n// this floor at the protocol level to prevent dust spam; we surface a clear\n// error before signing rather than letting the tx revert on-chain.\nexport const GASLESS_MIN_STABLE_AMOUNT = 0.01;\n\n// Cetus USDC/SUI pool — read-only for SUI price oracle (no SDK dependency)\nexport const CETUS_USDC_SUI_POOL = '0x51e883ba7c0b566a26cbc8a94cd33eb0abd418a77cc1e60ad22fd9b1f29cd2ab';\n\nexport const GAS_RESERVE_MIN = 0.05; // minimum SUI to keep for gas\n","import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';\nimport { SuiGrpcClient } from '@mysten/sui/grpc';\nimport { SuiGraphQLClient } from '@mysten/sui/graphql';\nimport { isValidSuiAddress, normalizeSuiAddress } from '@mysten/sui/utils';\nimport { DEFAULT_GRAPHQL_URL, DEFAULT_GRPC_URL, DEFAULT_RPC_URL } from '../constants.js';\nimport { T2000Error } from '../errors.js';\n\n/**\n * [gRPC migration / S.438] Transport-agnostic client type for the migration.\n *\n * Both `SuiJsonRpcClient` and `SuiGrpcClient` extend `BaseClient` and expose\n * an identical `.core.*` API. During the migration, call sites are rewritten\n * from legacy methods (`getBalance`, `getObject`, `executeTransactionBlock`)\n * to the unified `client.core.*` API and typed against this union — so the\n * rewrite is behavior-preserving while still on JSON-RPC, and the final\n * transport flip (gRPC) is a one-line change in `getSuiClient()`.\n *\n * The query surface that has no gRPC `core` equivalent (`queryTransactionBlocks`\n * / `queryEvents`, Stage 0 finding A) uses `getSuiGraphQLClient()` instead.\n */\nexport type SuiCoreClient = SuiJsonRpcClient | SuiGrpcClient;\n\n/**\n * Resolve the effective JSON-RPC URL: explicit arg > env var > default.\n * `T2000_RPC_URL` is an OPTIONAL override per the Greenfield SPEC's env\n * contract — no required vars, so we read inline (allowed by\n * `env-validation-gate.mdc` carve-out for packages with zero required\n * env vars).\n */\nfunction resolveRpcUrl(rpcUrl?: string): string {\n  if (rpcUrl) return rpcUrl;\n  const envUrl = process.env.T2000_RPC_URL?.trim();\n  if (envUrl) return envUrl;\n  return DEFAULT_RPC_URL;\n}\n\n/**\n * Same shape as `resolveRpcUrl` for the gRPC endpoint.\n */\nfunction resolveGrpcUrl(grpcUrl?: string): string {\n  if (grpcUrl) return grpcUrl;\n  const envUrl = process.env.T2000_GRPC_URL?.trim();\n  if (envUrl) return envUrl;\n  return DEFAULT_GRPC_URL;\n}\n\n/**\n * Same shape as `resolveRpcUrl` for the GraphQL endpoint.\n */\nfunction resolveGraphqlUrl(graphqlUrl?: string): string {\n  if (graphqlUrl) return graphqlUrl;\n  const envUrl = process.env.T2000_GRAPHQL_URL?.trim();\n  if (envUrl) return envUrl;\n  return DEFAULT_GRAPHQL_URL;\n}\n\n/**\n * Canonical agent client cache, keyed by URL. The earlier impl cached\n * unconditionally and ignored URL changes after the first call —\n * brittle for testnet smokes and custom-RPC test setups.\n */\nconst rpcClientCache = new Map<string, SuiGrpcClient>();\n\n/**\n * [gRPC cutover] The canonical agent client is now gRPC. Mysten deactivates\n * the JSON-RPC fullnode interface on 2026-07-31, so reads (`.core.*`) and\n * execution route over gRPC — transaction *builds* already do\n * (`getSuiGrpcClient`). The whole SDK was first refactored onto the unified\n * `.core` API (behavior-preserving on JSON-RPC), then flipped here. The\n * `rpcUrl` arg / `T2000_RPC_URL` override now resolve a gRPC `baseUrl`\n * (`DEFAULT_RPC_URL` is the same host as `DEFAULT_GRPC_URL`). The historical\n * query surface stays on `getSuiGraphQLClient()`.\n */\nexport function getSuiClient(rpcUrl?: string): SuiGrpcClient {\n  const url = resolveRpcUrl(rpcUrl);\n  const cached = rpcClientCache.get(url);\n  if (cached) return cached;\n  const client = new SuiGrpcClient({ baseUrl: url, network: 'mainnet' });\n  rpcClientCache.set(url, client);\n  return client;\n}\n\n/**\n * gRPC client cache, keyed by URL. Same rationale as the JSON-RPC cache:\n * different URLs must produce different clients.\n */\nconst grpcClientCache = new Map<string, SuiGrpcClient>();\n\n/**\n * Cached `SuiGrpcClient` for gasless stablecoin transfer builds.\n *\n * [v4.0 Phase A Day 2 — SPEC_AGENT_WALLET_GREENFIELD §A]\n *\n * Why this exists: Sui mainnet's protocol-level gasless stablecoin transfers\n * (`0x2::balance::send_funds` on the USDC + USDsui allowlist) are detected\n * ONLY when the transaction is built through a `SuiGrpcClient`. The gRPC\n * client's build resolver inspects the PTB at `tx.build()` time and, if it\n * matches the gasless pattern, sets `gasPrice=0` + `gasBudget=0` automatically.\n * Building the SAME PTB through `SuiJsonRpcClient` produces the same bytes\n * but with non-zero gas — the tx still works, but the user pays SUI gas.\n *\n * Execution stays on JSON-RPC (`SuiJsonRpcClient.executeTransactionBlock`)\n * because (a) the rest of the SDK expects JSON-RPC and (b) Sui's docs\n * explicitly support a \"build via gRPC, execute via JSON-RPC\" hybrid:\n * https://docs.sui.io/develop/transaction-payment/gasless-stablecoin-transfers\n *\n * Override the endpoint with the `T2000_GRPC_URL` env var or the\n * `grpcUrl` arg. Cache is keyed by URL so multiple endpoints can\n * co-exist (e.g., the rare testnet smoke + production usage from the\n * same process).\n */\nexport function getSuiGrpcClient(grpcUrl?: string): SuiGrpcClient {\n  const baseUrl = resolveGrpcUrl(grpcUrl);\n  const cached = grpcClientCache.get(baseUrl);\n  if (cached) return cached;\n  const client = new SuiGrpcClient({ baseUrl, network: 'mainnet' });\n  grpcClientCache.set(baseUrl, client);\n  return client;\n}\n\n/**\n * GraphQL client cache, keyed by URL. Same rationale as the other caches.\n */\nconst graphqlClientCache = new Map<string, SuiGraphQLClient>();\n\n/**\n * Cached `SuiGraphQLClient` for the query surface that has NO gRPC `core`\n * equivalent: `queryTransactionBlocks` + `queryEvents` (Stage 0 finding A —\n * `SPEC_FULL_GRPC_MIGRATION.md`). Mysten's gRPC successor doesn't cover the\n * historical query/event API; GraphQL is its documented home. Consumers:\n * `wallet/history.ts` + the swap-event read in `protocols/cetus-swap.ts`.\n *\n * Override the endpoint with `T2000_GRAPHQL_URL` or the `graphqlUrl` arg.\n */\nexport function getSuiGraphQLClient(graphqlUrl?: string): SuiGraphQLClient {\n  const url = resolveGraphqlUrl(graphqlUrl);\n  const cached = graphqlClientCache.get(url);\n  if (cached) return cached;\n  const client = new SuiGraphQLClient({ url, network: 'mainnet' });\n  graphqlClientCache.set(url, client);\n  return client;\n}\n\nexport function validateAddress(address: string): string {\n  const normalized = normalizeSuiAddress(address);\n  if (!isValidSuiAddress(normalized)) {\n    throw new T2000Error('INVALID_ADDRESS', `Invalid Sui address: ${address}`);\n  }\n  return normalized;\n}\n\nexport function truncateAddress(address: string): string {\n  if (address.length <= 10) return address;\n  return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\n/**\n * Normalize a Sui coin type to its canonical long-form 64-hex address.\n * `0x2::sui::SUI` → `0x0000…0002::sui::SUI`. Idempotent on already-long\n * forms. Returns the input unchanged if it doesn't look like a coin type\n * (`<address>::<module>::<name>`) so callers can pass arbitrary strings\n * without crashing.\n *\n * Why this exists: BlockVision's `/v2/sui/coin/price/list` endpoint\n * silently returns an empty `prices` map for short-form coin types\n * (notably `0x2::sui::SUI` — the native gas coin). Internal callers must\n * pass the long form, but external callers (LLM tool args, cached\n * coin-type strings, audit logs) commonly use the short form. Normalize\n * before the network call, denormalize back to the caller's input shape\n * after, and short/long become interchangeable.\n */\nexport function normalizeCoinType(coinType: string): string {\n  const parts = coinType.split('::');\n  if (parts.length !== 3) return coinType;\n  const [addr, mod, name] = parts;\n  if (!addr.startsWith('0x')) return coinType;\n  return `${normalizeSuiAddress(addr)}::${mod}::${name}`;\n}\n","// v4.0 wallet auth model: plain Bech32 secret in a versioned JSON file,\n// 0o600 perms. Matches the Sui CLI convention. No AES, no PIN, no scrypt.\n// Anything that isn't `{ version: 2, secret: \"suiprivkey1...\" }` throws\n// `WALLET_CORRUPT` — the user moves/deletes the file and runs `t2 init`.\n\nimport { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';\nimport { decodeSuiPrivateKey } from '@mysten/sui/cryptography';\nimport { readFile, writeFile, mkdir, access } from 'node:fs/promises';\nimport { dirname, resolve } from 'node:path';\nimport { homedir } from 'node:os';\nimport { T2000Error } from '../errors.js';\nimport { DEFAULT_KEY_PATH } from '../constants.js';\n\ninterface PlainKey {\n  version: 2;\n  secret: string;\n}\n\nfunction expandPath(p: string): string {\n  if (p.startsWith('~')) return resolve(homedir(), p.slice(2));\n  return resolve(p);\n}\n\nexport function generateKeypair(): Ed25519Keypair {\n  return Ed25519Keypair.generate();\n}\n\nexport function keypairFromPrivateKey(privateKey: string): Ed25519Keypair {\n  if (privateKey.startsWith('suiprivkey')) {\n    const decoded = decodeSuiPrivateKey(privateKey);\n    return Ed25519Keypair.fromSecretKey(decoded.secretKey);\n  }\n  const bytes = Buffer.from(privateKey.replace(/^0x/, ''), 'hex');\n  return Ed25519Keypair.fromSecretKey(bytes);\n}\n\n/**\n * Save a keypair as a v2 plain Bech32 JSON file with `0o600` perms.\n *\n * `_passphrase` is accepted but IGNORED — kept in the signature for\n * back-compat with v3.x callers. Will be removed when all callers\n * are off PIN (Phase A Day 5+).\n */\nexport async function saveKey(\n  keypair: Ed25519Keypair,\n  _passphrase: string | undefined,\n  keyPath?: string,\n): Promise<string> {\n  const filePath = expandPath(keyPath ?? DEFAULT_KEY_PATH);\n\n  try {\n    await access(filePath);\n    throw new T2000Error('WALLET_EXISTS', `Wallet already exists at ${filePath}`);\n  } catch (error) {\n    if (error instanceof T2000Error) throw error;\n  }\n\n  await mkdir(dirname(filePath), { recursive: true });\n\n  const payload: PlainKey = {\n    version: 2,\n    secret: keypair.getSecretKey(),\n  };\n\n  await writeFile(filePath, JSON.stringify(payload, null, 2), { mode: 0o600 });\n\n  return filePath;\n}\n\n/**\n * Save a Bech32 secret directly as a v2 plain wallet file. Used by any\n * path where the secret is supplied externally rather than freshly\n * generated. Kept exported because external tooling may still want it\n * even though the CLI no longer ships an `--import` flag.\n */\nexport async function saveBech32(secret: string, keyPath?: string): Promise<string> {\n  if (!secret.startsWith('suiprivkey')) {\n    throw new T2000Error(\n      'INVALID_KEY',\n      `Secret must be a Bech32 suiprivkey1... string. Got: ${secret.slice(0, 12)}...`,\n    );\n  }\n  decodeSuiPrivateKey(secret);\n\n  const filePath = expandPath(keyPath ?? DEFAULT_KEY_PATH);\n\n  try {\n    await access(filePath);\n    throw new T2000Error('WALLET_EXISTS', `Wallet already exists at ${filePath}`);\n  } catch (error) {\n    if (error instanceof T2000Error) throw error;\n  }\n\n  await mkdir(dirname(filePath), { recursive: true });\n\n  const payload: PlainKey = { version: 2, secret };\n\n  await writeFile(filePath, JSON.stringify(payload, null, 2), { mode: 0o600 });\n\n  return filePath;\n}\n\n/**\n * Load a keypair from disk.\n *\n * `_passphrase` is accepted but IGNORED — kept for back-compat. The\n * actual file format determines the load path:\n *\n * - **v2 plain JSON** (`{ version: 2, secret: \"suiprivkey1...\" }`) →\n *   decode + return keypair.\n * - **Anything else** → throw `WALLET_CORRUPT`. The user moves or\n *   deletes the file and runs `t2 init` to create a fresh wallet.\n */\nexport async function loadKey(\n  _passphrase?: string,\n  keyPath?: string,\n): Promise<Ed25519Keypair> {\n  const filePath = expandPath(keyPath ?? DEFAULT_KEY_PATH);\n\n  let content: string;\n  try {\n    content = await readFile(filePath, 'utf-8');\n  } catch {\n    throw new T2000Error('WALLET_NOT_FOUND', `No wallet found at ${filePath}`);\n  }\n\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(content);\n  } catch {\n    throw new T2000Error(\n      'WALLET_CORRUPT',\n      `Wallet file at ${filePath} is not a valid v4 wallet. Move or delete the file, then run \\`t2 init\\`.`,\n    );\n  }\n\n  if (!isPlainKey(parsed)) {\n    throw new T2000Error(\n      'WALLET_CORRUPT',\n      `Wallet file at ${filePath} is not a valid v4 wallet. Expected { version: 2, secret: \"suiprivkey1...\" }. Move or delete the file, then run \\`t2 init\\`.`,\n    );\n  }\n\n  const decoded = decodeSuiPrivateKey(parsed.secret);\n  return Ed25519Keypair.fromSecretKey(decoded.secretKey);\n}\n\nexport async function walletExists(keyPath?: string): Promise<boolean> {\n  const filePath = expandPath(keyPath ?? DEFAULT_KEY_PATH);\n  try {\n    await access(filePath);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\nexport function exportPrivateKey(keypair: Ed25519Keypair): string {\n  return keypair.getSecretKey();\n}\n\nexport function getAddress(keypair: Ed25519Keypair): string {\n  return keypair.getPublicKey().toSuiAddress();\n}\n\nfunction isPlainKey(value: unknown): value is PlainKey {\n  return (\n    typeof value === 'object' &&\n    value !== null &&\n    (value as { version?: unknown }).version === 2 &&\n    typeof (value as { secret?: unknown }).secret === 'string'\n  );\n}\n","import type { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';\nimport type { TransactionSigner } from '../signer.js';\n\nexport class KeypairSigner implements TransactionSigner {\n  constructor(private readonly keypair: Ed25519Keypair) {}\n\n  getAddress(): string {\n    return this.keypair.getPublicKey().toSuiAddress();\n  }\n\n  async signTransaction(txBytes: Uint8Array): Promise<{ signature: string }> {\n    return this.keypair.signTransaction(txBytes);\n  }\n\n  async signPersonalMessage(messageBytes: Uint8Array): Promise<{ signature: string; bytes: string }> {\n    return this.keypair.signPersonalMessage(messageBytes);\n  }\n\n  /** Access the underlying keypair for APIs that still require it directly. */\n  getKeypair(): Ed25519Keypair {\n    return this.keypair;\n  }\n}\n","import type { SuiClientTypes } from '@mysten/sui/client';\nimport type { Transaction } from '@mysten/sui/transactions';\nimport type { TransactionSigner } from '../signer.js';\nimport type { SuiCoreClient } from '../utils/sui.js';\n\n// ---------------------------------------------------------------------------\n// executeTx — build + sign + submit + wait, the SDK's one tx-execution helper.\n//\n// Browser-safe (no fs / keyManager imports) so it can back\n// both the Node-side `T2000` methods AND the browser-side `payWithMpp`\n// (gasless MPP runs client-side on the zkLogin session key). Moved out of\n// `t2000.ts` so `wallet/pay.ts` can share it without pulling the Node-only\n// `T2000` module graph into the browser bundle.\n//\n// [gRPC migration] Submit + wait go through the unified `client.core.*`\n// API (`executeTransaction` + `waitForTransaction`), which is transport-\n// agnostic across the JSON-RPC and gRPC clients.\n// ---------------------------------------------------------------------------\n\nexport type SuiTransactionEffects = SuiClientTypes.TransactionEffects;\nexport type BuildClient = NonNullable<Parameters<Transaction['build']>[0]>['client'];\n\nexport async function executeTx(\n  client: SuiCoreClient,\n  signer: TransactionSigner,\n  buildTx: () => Promise<Transaction> | Transaction,\n  options: { buildClient?: BuildClient } = {},\n): Promise<{ digest: string; gasCostSui: number; effects: SuiTransactionEffects | undefined }> {\n  const tx = await buildTx();\n  tx.setSender(signer.getAddress());\n  // [2026-05-22] Optional buildClient. When set, `tx.build()` uses it to\n  // resolve the PTB — relevant for gasless stablecoin transfers where the\n  // SuiGrpcClient build path auto-detects allowlisted ops and zeros out\n  // gasPrice/gasBudget/gasPayment. See `payWithMpp`.\n  const txBytes = await tx.build({ client: options.buildClient ?? client });\n  const { signature } = await signer.signTransaction(txBytes);\n  const result = await client.core.executeTransaction({\n    transaction: txBytes,\n    signatures: [signature],\n    include: { effects: true },\n  });\n  const txn = result.$kind === 'Transaction' ? result.Transaction : result.FailedTransaction;\n  await client.core.waitForTransaction({ digest: txn.digest });\n  const effects = txn.effects ?? undefined;\n  const gasUsed = effects?.gasUsed;\n  let gasCostSui = 0;\n  if (gasUsed) {\n    const total = BigInt(gasUsed.computationCost) + BigInt(gasUsed.storageCost) - BigInt(gasUsed.storageRebate);\n    gasCostSui = Number(total) / 1e9;\n  }\n  return { digest: txn.digest, gasCostSui, effects };\n}\n","import type { SuiGrpcClient } from '@mysten/sui/grpc';\nimport { fromBase64 } from '@mysten/sui/utils';\nimport type { X402Requirements } from '@suimpp/mpp/x402';\nimport type { TransactionSigner } from '../signer.js';\nimport type { PayOptions, PayResult } from '../types.js';\nimport { T2000Error } from '../errors.js';\nimport { executeTx } from './executeTx.js';\nimport {\n  type PreflightResult,\n  PREFLIGHT_OK,\n  preflightFail,\n  checkPositiveAmount,\n} from '../preflight.js';\n\n/**\n * Synchronous, network-free preflight for `pay` (x402 Service call). Validates\n * the target URL shape and the `maxPrice` ceiling when present — the cheap\n * checks the v3 host runs before dispatching the paid tool / showing the\n * tap-to-confirm card. Returns a `PreflightResult`; never throws. The probe +\n * 402 handshake + balance migration stay in `payWithMpp` (network).\n */\nexport function preflightPay(input: { url: string; maxPrice?: number }): PreflightResult {\n  if (typeof input.url !== 'string' || input.url.trim() === '') {\n    return preflightFail('FACILITATOR_REJECTION', 'A target URL is required to pay');\n  }\n  let parsed: URL;\n  try {\n    parsed = new URL(input.url);\n  } catch {\n    return preflightFail('FACILITATOR_REJECTION', `Invalid URL: ${input.url}`);\n  }\n  if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n    return preflightFail(\n      'FACILITATOR_REJECTION',\n      `URL must be http(s): got ${parsed.protocol}//`,\n    );\n  }\n  // `maxPrice` is optional (no ceiling = pay whatever the 402 asks). Validate\n  // only when the caller set one — a malformed ceiling is a fat-finger.\n  if (input.maxPrice !== undefined) {\n    const priceCheck = checkPositiveAmount(input.maxPrice, 'maxPrice');\n    if (!priceCheck.valid) return priceCheck;\n  }\n  return PREFLIGHT_OK;\n}\n\n// ---------------------------------------------------------------------------\n// payWithMpp — the SDK's single source of truth for the pay loop. Browser-safe\n// (no fs / keyManager / SafeguardEnforcer), so the Audric client can run it\n// in-browser on the zkLogin session key. `T2000.pay()` delegates here.\n//\n// x402 `sui-exact`, ONE path (SPEC_AGENT_PAYMENTS_X402 1.2; scheme =\n// SUIMPP_X402_SCHEME.md v0.3). The flow: sign an authorization, the gateway\n// settles. The legacy MPP \"digest dialect\" (client broadcasts, retries with\n// the tx digest) was retired from the SDK — the gateway dual-serves both for\n// installed pre-x402 CLIs, so the SDK client doesn't need a fallback. Both\n// dialects always rode the SAME gasless `send_funds<USDC>` rail; the only\n// difference was who submits, and x402 is now the only one we speak.\n//\n// Settlement: the withdrawal form draws from the SIP-58 address balance (the\n// canonical stateless, offline-signable shape), so coin-object funds are\n// migrated in first when needed (S.414 finding). The client only SIGNS — the\n// gateway submits (settle-then-serve), so a failed upstream is never charged.\n// ---------------------------------------------------------------------------\n\nexport async function payWithMpp(args: {\n  signer: TransactionSigner;\n  client: SuiGrpcClient;\n  options: PayOptions;\n}): Promise<PayResult> {\n  const { signer, client, options } = args;\n\n  // Layer 2 — cheap synchronous preflight (URL shape + maxPrice sanity) before\n  // any network round-trip. Rethrow the precise code+message verbatim.\n  const pf = preflightPay({ url: options.url, maxPrice: options.maxPrice });\n  if (!pf.valid) throw new T2000Error(pf.code, pf.error);\n\n  const method = (options.method ?? 'GET').toUpperCase();\n  const canHaveBody = method !== 'GET' && method !== 'HEAD';\n  const reqInit: RequestInit = {\n    method,\n    headers: options.headers,\n    body: canHaveBody ? options.body : undefined,\n  };\n\n  // Probe (no payment). A paid endpoint answers 402; a free/cached one serves.\n  const probe = await fetch(options.url, reqInit);\n  if (probe.status !== 402) {\n    return finalize(probe, { paid: false });\n  }\n\n  const requirements = await pickSuiExactRequirements(probe, client.network);\n  if (!requirements) {\n    throw new T2000Error(\n      'FACILITATOR_REJECTION',\n      `Endpoint returned 402 without an x402 'exact' / sui:${client.network} payment requirement. ` +\n        `This SDK only speaks the x402 dialect.`,\n    );\n  }\n\n  return payViaX402({ signer, client, options, reqInit, requirements });\n}\n\n// ---------------------------------------------------------------------------\n// x402 `sui-exact` — sign-then-settle\n// ---------------------------------------------------------------------------\n\nasync function pickSuiExactRequirements(\n  response: Response,\n  network: string,\n): Promise<X402Requirements | undefined> {\n  try {\n    const body = (await response.clone().json()) as { accepts?: X402Requirements[] };\n    const want = `sui:${network === 'testnet' ? 'testnet' : 'mainnet'}`;\n    return body.accepts?.find((a) => a.scheme === 'exact' && a.network === want);\n  } catch {\n    return undefined;\n  }\n}\n\nasync function payViaX402(args: {\n  signer: TransactionSigner;\n  client: SuiGrpcClient;\n  options: PayOptions;\n  reqInit: RequestInit;\n  requirements: X402Requirements;\n}): Promise<PayResult> {\n  const { signer, client, options, reqInit, requirements } = args;\n  const { buildX402SignedPayment, X402_PAYMENT_HEADER, X402_PAYMENT_RESPONSE_HEADER } = await import(\n    '@suimpp/mpp/x402'\n  );\n\n  const amountRaw = BigInt(requirements.maxAmountRequired);\n\n  // The x402 withdrawal form spends ONLY the SIP-58 address balance. A wallet\n  // funded by ordinary coin transfers (or swap output) holds Coin<USDC>\n  // objects → migrate enough in first (S.414 finding; SUIMPP_X402_SCHEME §4).\n  const migrationGasSui = await ensureAddressBalanceCovers({\n    signer,\n    client,\n    asset: requirements.asset,\n    amountRaw,\n  });\n\n  // Build + sign — NEVER submitted client-side; the gateway settles. The\n  // builder only reads toSuiAddress() + signTransaction(), both of which every\n  // TransactionSigner (keypair AND zkLogin) provides.\n  const signerAdapter = {\n    toSuiAddress: () => signer.getAddress(),\n    signTransaction: (bytes: Uint8Array) => signer.signTransaction(bytes),\n  } as unknown as Parameters<typeof buildX402SignedPayment>[0]['signer'];\n\n  const { header } = await buildX402SignedPayment({ requirements, signer: signerAdapter });\n\n  const res = await fetch(options.url, {\n    ...reqInit,\n    headers: { ...(options.headers ?? {}), [X402_PAYMENT_HEADER]: header },\n  });\n\n  // Settled iff the gateway returned the x402 receipt header.\n  const settleHeader = res.headers.get(X402_PAYMENT_RESPONSE_HEADER);\n  const paid = !!settleHeader;\n  let digest: string | undefined;\n  if (settleHeader) {\n    try {\n      digest = (JSON.parse(new TextDecoder().decode(fromBase64(settleHeader))) as { transaction?: string })\n        .transaction;\n    } catch {\n      digest = undefined;\n    }\n  }\n\n  const result = await finalize(res, { paid });\n  if (!paid) return { ...result, dialect: 'x402' };\n  return {\n    ...result,\n    dialect: 'x402',\n    cost: atomicToHuman(amountRaw, await assetDecimals(requirements.asset)),\n    gasCostSui: migrationGasSui,\n    receipt: digest\n      ? { reference: digest, timestamp: new Date().toISOString() }\n      : result.receipt,\n  };\n}\n\n/**\n * Ensure the sender's SIP-58 address balance covers `amountRaw` of `asset`.\n * Returns the SUI gas spent migrating (0 when no migration was needed or the\n * migration was gasless). Throws `INSUFFICIENT_BALANCE` when the wallet\n * doesn't hold enough of the asset at all (coins + address balance combined).\n */\nasync function ensureAddressBalanceCovers(args: {\n  signer: TransactionSigner;\n  client: SuiGrpcClient;\n  asset: string;\n  amountRaw: bigint;\n}): Promise<number> {\n  const { signer, client, asset, amountRaw } = args;\n  const owner = signer.getAddress();\n\n  // total = coins + address balance (the canonical combined read)\n  const balanceResp = await client.core.getBalance({ owner, coinType: asset });\n  const total = BigInt(balanceResp.balance.balance);\n  if (total < amountRaw) {\n    throw new T2000Error('INSUFFICIENT_BALANCE', `Insufficient ${asset} to pay`, {\n      available: total.toString(),\n      required: amountRaw.toString(),\n    });\n  }\n\n  // address balance = total − discrete coin-object sum (listCoins excludes AB).\n  // Collect the coin objects too — we reuse them to build the migration.\n  const coins: { objectId: string; balance: bigint }[] = [];\n  let coinSum = 0n;\n  let cursor: string | null | undefined;\n  let hasNext = true;\n  while (hasNext) {\n    const page = await client.core.listCoins({ owner, coinType: asset, cursor: cursor ?? undefined });\n    for (const c of page.objects) {\n      coins.push({ objectId: c.objectId, balance: BigInt(c.balance) });\n      coinSum += BigInt(c.balance);\n    }\n    cursor = page.cursor;\n    hasNext = page.hasNextPage;\n  }\n  const addressBalance = total - coinSum;\n  if (addressBalance >= amountRaw) return 0; // address balance already covers it\n\n  // Move the shortfall from coin objects into the address balance by sending\n  // WHOLE coin objects to self via `0x2::coin::send_funds` — one allowlisted\n  // framework MoveCall per coin, NO native merge/split. Built on the gRPC\n  // client so its resolver detects the all-allowlisted-MoveCall shape and zeros\n  // gas: the migration itself is gasless (the same eligibility the x402\n  // withdrawal + the gasless send rely on). The old merge+split+send shape had\n  // native `SplitCoins`/`MergeCoins` commands → fell outside the allowlist →\n  // forced SUI gas, breaking coin-object holders with 0 SUI.\n  const shortfall = amountRaw - addressBalance;\n  const { buildCoinToAddressBalanceMigration } = await import('./coinSelection.js');\n  const grpcClient = await makeGrpcBuildClient(client);\n  const { tx } = buildCoinToAddressBalanceMigration({ coins, coinType: asset, owner, minAmount: shortfall });\n  const migration = await executeTx(client, signer, () => tx, { buildClient: grpcClient });\n  return migration.gasCostSui;\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\n/** Read the response body (json or text) and assemble the base PayResult. */\nasync function finalize(response: Response, opts: { paid: boolean }): Promise<PayResult> {\n  const contentType = response.headers.get('content-type') ?? '';\n  let body: unknown;\n  try {\n    body = contentType.includes('application/json') ? await response.json() : await response.text();\n  } catch {\n    body = null;\n  }\n  return { status: response.status, body, paid: opts.paid };\n}\n\n/** A gRPC client for tx BUILD — its resolver auto-detects the gasless\n * stablecoin shape (gasPrice/gasBudget/gasPayment zeroed). */\nasync function makeGrpcBuildClient(client: SuiGrpcClient): Promise<SuiGrpcClient> {\n  const { SuiGrpcClient } = await import('@mysten/sui/grpc');\n  const network: 'mainnet' | 'testnet' = client.network === 'testnet' ? 'testnet' : 'mainnet';\n  const baseUrl =\n    network === 'testnet' ? 'https://fullnode.testnet.sui.io' : 'https://fullnode.mainnet.sui.io';\n  return new SuiGrpcClient({ baseUrl, network });\n}\n\nfunction atomicToHuman(raw: bigint, decimals: number): number {\n  return Number(raw) / 10 ** decimals;\n}\n\nasync function assetDecimals(coinType: string): Promise<number> {\n  try {\n    const { getDecimalsForCoinType } = await import('../token-registry.js');\n    const d = getDecimalsForCoinType(coinType);\n    return typeof d === 'number' ? d : 6;\n  } catch {\n    return 6;\n  }\n}\n","import type { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';\nimport type { TransactionSigner } from '../signer.js';\n\nexport interface ZkLoginProof {\n  proofPoints: {\n    a: string[];\n    b: string[][];\n    c: string[];\n  };\n  issBase64Details: {\n    indexMod4: number;\n    value: string;\n  };\n  headerBase64: string;\n  addressSeed: string;\n}\n\nexport class ZkLoginSigner implements TransactionSigner {\n  constructor(\n    private readonly ephemeralKeypair: Ed25519Keypair,\n    private readonly zkProof: ZkLoginProof,\n    private readonly userAddress: string,\n    private readonly maxEpoch: number,\n  ) {}\n\n  getAddress(): string {\n    return this.userAddress;\n  }\n\n  async signTransaction(txBytes: Uint8Array): Promise<{ signature: string }> {\n    const { getZkLoginSignature } = await import('@mysten/zklogin');\n    const ephSig = await this.ephemeralKeypair.signTransaction(txBytes);\n    return {\n      signature: getZkLoginSignature({\n        inputs: this.zkProof,\n        maxEpoch: this.maxEpoch,\n        userSignature: ephSig.signature,\n      }),\n    };\n  }\n\n  async signPersonalMessage(messageBytes: Uint8Array): Promise<{ signature: string; bytes: string }> {\n    const { getZkLoginSignature } = await import('@mysten/zklogin');\n    const { signature: ephSig, bytes } = await this.ephemeralKeypair.signPersonalMessage(messageBytes);\n    return {\n      signature: getZkLoginSignature({\n        inputs: this.zkProof,\n        maxEpoch: this.maxEpoch,\n        userSignature: ephSig,\n      }),\n      bytes,\n    };\n  }\n\n  isExpired(currentEpoch: number): boolean {\n    return currentEpoch >= this.maxEpoch;\n  }\n}\n","import {\n  Transaction,\n  type TransactionObjectArgument,\n} from '@mysten/sui/transactions';\nimport {\n  GASLESS_MIN_STABLE_AMOUNT,\n  GASLESS_STABLE_TYPES,\n  SUPPORTED_ASSETS,\n  assertAllowedAsset,\n  type SendableAsset,\n} from '../constants.js';\nimport { T2000Error } from '../errors.js';\nimport { validateAddress, type SuiCoreClient } from '../utils/sui.js';\nimport { displayToRaw } from '../utils/format.js';\nimport {\n  type PreflightResult,\n  PREFLIGHT_OK,\n  preflightFail,\n  checkPositiveAmount,\n  checkSuiAddress,\n} from '../preflight.js';\n\n/**\n * Synchronous, network-free preflight for `send`. Validates asset membership,\n * amount sanity, the gasless stable floor, and recipient address shape — the\n * cheap checks the v3 host runs before the LLM round-trip / tap-to-confirm.\n * Returns a `PreflightResult`; never throws. `buildSendTx` calls this first,\n * then layers the network balance read on top.\n */\nexport function preflightSend(input: {\n  to: string;\n  amount: number;\n  asset: string;\n}): PreflightResult {\n  // Asset membership — reuse the canonical message (single source of truth).\n  try {\n    assertAllowedAsset('send', input.asset);\n  } catch (e) {\n    return preflightFail('INVALID_ASSET', (e as T2000Error).message);\n  }\n\n  const amountCheck = checkPositiveAmount(input.amount);\n  if (!amountCheck.valid) return amountCheck;\n\n  // Gasless protocol allowlist enforces a 0.01 minimum on the stables.\n  if (\n    (input.asset === 'USDC' || input.asset === 'USDsui') &&\n    input.amount < GASLESS_MIN_STABLE_AMOUNT\n  ) {\n    return preflightFail(\n      'INVALID_AMOUNT',\n      `Minimum gasless transfer is ${GASLESS_MIN_STABLE_AMOUNT} ${input.asset}. Got ${input.amount}.`,\n    );\n  }\n\n  const addressCheck = checkSuiAddress(input.to);\n  if (!addressCheck.valid) return addressCheck;\n\n  return PREFLIGHT_OK;\n}\n\n/**\n * Build a PTB that sends `amount` of `asset` from `address` to `to`.\n *\n * [v4.0 Phase A Day 2 — SPEC_AGENT_WALLET_GREENFIELD §A]\n *\n * Asset constraint: `'USDC' | 'USDsui' | 'SUI'` only. Other assets throw\n * `INVALID_ASSET` via `assertAllowedAsset('send', asset)`. The constrained\n * set matches Sui mainnet's gasless allowlist (USDC + USDsui) plus SUI\n * for users who want a gas-native transfer.\n *\n * Build paths:\n * - **USDC / USDsui** — `0x2::balance::send_funds` Move call with a\n *   `tx.balance({ type, balance })` input. When built via `SuiGrpcClient`,\n *   the gRPC resolver auto-detects gasless eligibility and zeros gas.\n *   When built via `SuiJsonRpcClient`, the same PTB still executes but\n *   the caller pays normal gas. Minimum 0.01 (protocol allowlist floor).\n * - **SUI** — `tx.splitCoins(tx.gas, [amount]) → tx.transferObjects()`.\n *   Standard gas-native transfer. No minimum.\n *\n * Pre-flight balance check stays on JSON-RPC (`client.getBalance`) — it\n * sums coin objects + address balance so the legacy `getCoins` page miss\n * doesn't break for users whose stables landed via gasless deposits.\n *\n * `asset` is REQUIRED (no implicit USDC default — pre-v4 hid LLM intent\n * errors). Callers passing the wrong asset get an explicit error rather\n * than a silent currency substitution.\n */\nexport async function buildSendTx({\n  client,\n  address,\n  to,\n  amount,\n  asset,\n}: {\n  client: SuiCoreClient;\n  address: string;\n  to: string;\n  amount: number;\n  asset: SendableAsset;\n}): Promise<Transaction> {\n  // Layer 2 — cheap synchronous preflight (asset / amount / gasless floor /\n  // recipient shape). Rethrow the precise code+message verbatim.\n  const pf = preflightSend({ to, amount, asset });\n  if (!pf.valid) throw new T2000Error(pf.code, pf.error);\n\n  const recipient = validateAddress(to);\n  const assetInfo = SUPPORTED_ASSETS[asset];\n  if (!assetInfo) throw new T2000Error('ASSET_NOT_SUPPORTED', `Asset ${asset} is not supported`);\n\n  const rawAmount = displayToRaw(amount, assetInfo.decimals);\n  const tx = new Transaction();\n  tx.setSender(address);\n\n  // Balance pre-flight against `core.getBalance().balance.balance` (sums\n  // coins + address balance). The legacy `getCoins` page miss broke for\n  // users whose stables had drifted into address balance via @suimpp/mpp 0.7+.\n  const balanceResp = await client.core.getBalance({ owner: address, coinType: assetInfo.type });\n  const totalBalance = BigInt(balanceResp.balance.balance);\n  if (totalBalance < rawAmount) {\n    throw new T2000Error('INSUFFICIENT_BALANCE', `Insufficient ${asset} balance`, {\n      available: Number(totalBalance) / 10 ** assetInfo.decimals,\n      required: amount,\n    });\n  }\n\n  if (asset === 'SUI') {\n    // Standard gas-native transfer — split from the gas coin, transfer\n    // the resulting object. NOT gasless (SUI is not on the protocol\n    // allowlist for `balance::send_funds`).\n    const [sendCoin] = tx.splitCoins(tx.gas, [rawAmount]);\n    tx.transferObjects([sendCoin], recipient);\n    return tx;\n  }\n\n  // USDC / USDsui — gasless via `0x2::balance::send_funds`. The gRPC\n  // build resolver inspects this PTB shape at `tx.build()` time and,\n  // when it matches the protocol allowlist, sets gasPrice=0/gasBudget=0\n  // automatically. The Move signature is:\n  //   public fun send_funds<T>(balance: Balance<T>, recipient: address)\n  // `tx.balance({ type, balance })` produces a Balance<T> input sourced\n  // from the sender's address balance + coin objects (auto-merged).\n  const coinType = GASLESS_STABLE_TYPES[asset];\n  tx.moveCall({\n    target: '0x2::balance::send_funds',\n    typeArguments: [coinType],\n    arguments: [\n      tx.balance({ type: coinType, balance: rawAmount }),\n      tx.pure.address(recipient),\n    ],\n  });\n  return tx;\n}\n\n/**\n * Fragment-appender for the chain-mode send leg of SPEC 7 multi-write\n * Payment Intents. Consumes a coin reference produced by a previous\n * appender (e.g. `addWithdrawToTx`, `addSwapToTx`) and transfers it to\n * `recipient` within the same Payment Intent — no intermediate wallet\n * materialization.\n *\n * Codifies the hand-built send leg from\n * `scripts/smoke-spec7-withdraw-then-send.ts` (P2.1) into a typed\n * appender. SPEC 7 § \"Layer 1\" — P2.2b will register this in the\n * `WRITE_APPENDER_REGISTRY` under `send_transfer` for chain-mode\n * dispatch; the registry adapter will handle the wallet-fetch fallback\n * by delegating to `buildSendTx` when no upstream coin is available.\n *\n * For single-step send_transfer flows (no chained predecessor), use\n * `buildSendTx` directly — it builds a complete tx including the\n * wallet-coin selection / merge / split prelude.\n *\n * [v4.0 Phase A Day 2] Stays on the legacy `transferObjects` path\n * because chain-mode bundles are NEVER gasless — by definition they\n * combine multiple Move calls (`withdraw → send`, `swap → send`) which\n * fail the protocol allowlist check (only `balance::send_funds` and\n * a few related helpers are eligible). The bundled flow still works,\n * the user just pays gas (or has it sponsored by audric via Enoki).\n *\n * @returns void — the coin is consumed by `tx.transferObjects`. Callers\n *   that need the post-transfer \"effective amount\" should rely on the\n *   upstream appender's `effectiveAmount` (e.g. `addWithdrawToTx`'s\n *   return), not on this appender.\n */\nexport function addSendToTx(\n  tx: Transaction,\n  coin: TransactionObjectArgument,\n  recipient: string,\n): void {\n  const validRecipient = validateAddress(recipient);\n  tx.transferObjects([coin], validRecipient);\n}\n","import { MIST_PER_SUI, USDC_DECIMALS, SUPPORTED_ASSETS } from '../constants.js';\nimport type { SupportedAsset } from '../constants.js';\n\nexport function mistToSui(mist: bigint): number {\n  return Number(mist) / Number(MIST_PER_SUI);\n}\n\nexport function suiToMist(sui: number): bigint {\n  return BigInt(Math.round(sui * Number(MIST_PER_SUI)));\n}\n\nexport function usdcToRaw(amount: number): bigint {\n  return BigInt(Math.round(amount * 10 ** USDC_DECIMALS));\n}\n\nexport function rawToUsdc(raw: bigint): number {\n  return Number(raw) / 10 ** USDC_DECIMALS;\n}\n\nexport function stableToRaw(amount: number, decimals: number): bigint {\n  return BigInt(Math.round(amount * 10 ** decimals));\n}\n\nexport function rawToStable(raw: bigint, decimals: number): number {\n  return Number(raw) / 10 ** decimals;\n}\n\nexport function getDecimals(asset: SupportedAsset): number {\n  return SUPPORTED_ASSETS[asset].decimals;\n}\n\nexport function rawToDisplay(raw: bigint, decimals: number): number {\n  return Number(raw) / 10 ** decimals;\n}\n\nexport function displayToRaw(amount: number, decimals: number): bigint {\n  return BigInt(Math.round(amount * 10 ** decimals));\n}\n\nexport function formatUsd(amount: number): string {\n  return `$${amount.toFixed(2)}`;\n}\n\nexport function formatSui(amount: number): string {\n  if (amount < 0.001) return `${amount.toFixed(6)} SUI`;\n  return `${amount.toFixed(3)} SUI`;\n}\n\nexport function formatLargeNumber(n: number): string {\n  if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n  if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;\n  return n.toFixed(2);\n}\n\nexport function formatAssetAmount(amount: number, asset: string): string {\n  if (asset === 'BTC') return amount.toFixed(8);\n  if (asset === 'GOLD') return amount.toFixed(6);\n  if (asset === 'ETH') return amount.toFixed(6);\n  return amount.toFixed(4);\n}\n\nconst ASSET_LOOKUP: Map<string, string> = new Map();\nfor (const [key, info] of Object.entries(SUPPORTED_ASSETS)) {\n  ASSET_LOOKUP.set(key.toUpperCase(), key);\n  if (info.displayName && info.displayName.toUpperCase() !== key.toUpperCase()) {\n    ASSET_LOOKUP.set(info.displayName.toUpperCase(), key);\n  }\n}\n\n/**\n * Case-insensitive lookup against SUPPORTED_ASSETS keys AND display names.\n * 'usde' → 'USDe', 'suiusde' → 'USDe', 'suiusdt' → 'USDT', 'usdsui' → 'USDsui'.\n * Returns the original input if not found so downstream validation can reject it.\n */\nexport function normalizeAsset(input: string): string {\n  return ASSET_LOOKUP.get(input.toUpperCase()) ?? input;\n}\n","import { normalizeStructTag } from '@mysten/sui/utils';\nimport { SUPPORTED_ASSETS, STABLE_ASSETS, MIST_PER_SUI, CETUS_USDC_SUI_POOL } from '../constants.js';\nimport type { StableAsset } from '../constants.js';\nimport { resolveSymbol, resolveCoinDecimals } from '../token-registry.js';\nimport type { SuiCoreClient } from '../utils/sui.js';\nimport type { BalanceResponse, TokenHolding } from '../types.js';\n\nconst SUI_PRICE_FALLBACK = 1.0;\nlet _cachedSuiPrice = 0;\nlet _priceLastFetched = 0;\nconst PRICE_CACHE_TTL_MS = 60_000;\n\n/**\n * Fetch SUI price in USD from the Cetus USDC/SUI pool's sqrt_price.\n *\n * Pool is Pool<USDC, SUI> so coin_a = USDC (6 dec), coin_b = SUI (9 dec).\n * current_sqrt_price (Q64 fixed-point) encodes sqrt(raw_price) where\n * raw_price = SUI_raw / USDC_raw.\n *\n * USDC per SUI = 10^(decimals_a - decimals_b) / raw_price\n *              = 10^(6-9) / raw_price\n *              = 1 / (raw_price * 1000)\n *\n * Equivalently: 1000 / raw_price\n */\nasync function fetchSuiPrice(client: SuiCoreClient): Promise<number> {\n  const now = Date.now();\n  if (_cachedSuiPrice > 0 && now - _priceLastFetched < PRICE_CACHE_TTL_MS) {\n    return _cachedSuiPrice;\n  }\n\n  try {\n    // [gRPC migration] `core.getObject` returns BCS content; request `json`\n    // to read parsed Move fields (the legacy `content.fields` path is gone).\n    const pool = await client.core.getObject({\n      objectId: CETUS_USDC_SUI_POOL,\n      include: { json: true },\n    });\n\n    const fields = pool.object?.json as Record<string, unknown> | null | undefined;\n    if (fields) {\n      const currentSqrtPrice = BigInt(String(fields.current_sqrt_price ?? '0'));\n\n      if (currentSqrtPrice > 0n) {\n        const Q64 = 2n ** 64n;\n        const sqrtPriceFloat = Number(currentSqrtPrice) / Number(Q64);\n        const rawPrice = sqrtPriceFloat * sqrtPriceFloat;\n        const price = 1000 / rawPrice;\n        if (price > 0.01 && price < 1000) {\n          _cachedSuiPrice = price;\n          _priceLastFetched = now;\n        }\n      }\n    }\n  } catch {\n    // Use cached/fallback price\n  }\n\n  return _cachedSuiPrice || SUI_PRICE_FALLBACK;\n}\n\nfunction safeNorm(coinType: string): string {\n  try {\n    return normalizeStructTag(coinType);\n  } catch {\n    return coinType;\n  }\n}\n\nconst SUI_TYPE_NORM = safeNorm(SUPPORTED_ASSETS.SUI.type);\nconst STABLE_BY_NORM: Record<string, StableAsset> = (() => {\n  const m: Record<string, StableAsset> = {};\n  for (const asset of STABLE_ASSETS) m[safeNorm(SUPPORTED_ASSETS[asset].type)] = asset;\n  return m;\n})();\n\n/**\n * Full wallet balance: **every** held coin, not just the curated stables + SUI.\n *\n * Uses one `listBalances` (paginated) instead of N `getBalance` calls, then\n * partitions: stables → priced $1, SUI → Cetus-oracle priced, **everything else\n * → `tokens[]` amount-only** (`usdValue: null` — no price oracle for arbitrary\n * tokens; we don't guess). Decimals for non-registry tokens are read on-chain\n * (the only added call, and only for tokens you actually hold — necessary for a\n * correct amount). `totalUsd` sums **priced holdings only** so it never\n * overstates; `tokens` surfaces the rest honestly.\n */\nexport async function queryBalance(\n  client: SuiCoreClient,\n  address: string,\n): Promise<BalanceResponse> {\n  const held: Array<{ coinType: string; raw: bigint }> = [];\n  let cursor: string | null | undefined;\n  do {\n    const page = await client.core.listBalances({ owner: address, cursor: cursor ?? undefined });\n    for (const b of page.balances) {\n      const raw = BigInt(b.balance);\n      if (raw > 0n) held.push({ coinType: b.coinType, raw });\n    }\n    cursor = page.hasNextPage ? page.cursor : null;\n  } while (cursor);\n\n  const suiPriceUsd = await fetchSuiPrice(client);\n\n  const stables = {} as Record<StableAsset, number>;\n  for (const asset of STABLE_ASSETS) stables[asset] = 0;\n  let totalStables = 0;\n  let suiAmount = 0;\n  const otherCoins: Array<{ coinType: string; raw: bigint }> = [];\n\n  for (const { coinType, raw } of held) {\n    const norm = safeNorm(coinType);\n    if (norm === SUI_TYPE_NORM) {\n      suiAmount = Number(raw) / Number(MIST_PER_SUI);\n    } else if (STABLE_BY_NORM[norm]) {\n      const asset = STABLE_BY_NORM[norm];\n      const amount = Number(raw) / 10 ** SUPPORTED_ASSETS[asset].decimals;\n      stables[asset] = amount;\n      totalStables += amount;\n    } else {\n      otherCoins.push({ coinType, raw });\n    }\n  }\n\n  // Non-stable, non-SUI holdings — amount-only (no price oracle). Decimals come\n  // from the registry (no call) or on-chain coin metadata (unknown tokens only).\n  const tokens: TokenHolding[] = await Promise.all(\n    otherCoins.map(async ({ coinType, raw }) => {\n      const decimals = await resolveCoinDecimals(client, coinType);\n      return {\n        coinType,\n        symbol: resolveSymbol(coinType),\n        amount: Number(raw) / 10 ** decimals,\n        usdValue: null,\n      };\n    }),\n  );\n  tokens.sort((a, b) => a.symbol.localeCompare(b.symbol));\n\n  const suiUsdValue = suiAmount * suiPriceUsd;\n\n  return {\n    stables,\n    available: totalStables,\n    sui: { amount: suiAmount, usdValue: suiUsdValue },\n    tokens,\n    totalUsd: totalStables + suiUsdValue,\n  };\n}\n","/**\n * Shared transaction classifier.\n *\n * Consumed by both the SDK's `parseTxRecord` (production agent path) and\n * the engine's `transaction_history` tool (cold-start RPC path). Keeping\n * a single source of truth here prevents the two paths from drifting —\n * see v1.5.3 regression where the SDK path was emitting `action:\n * 'transaction'` (rendered as \"On-chain\") while the engine path was\n * already producing fine-grained labels.\n */\n\nimport { getDecimalsForCoinType, resolveSymbol, SUI_TYPE } from '../token-registry.js';\n\n/**\n * Coarse action bucket — one of `'send' | 'lending' | 'swap' |\n * 'transaction'`. Used by the ACI `action` filter on the\n * `transaction_history` tool. STABLE: downstream queries depend on\n * exactly these values.\n *\n * Order matters: more specific buckets first. Lending patterns precede\n * swap patterns so a NAVI `::swap` helper (if one ever existed) would\n * still bucket as lending.\n */\nexport const KNOWN_TARGETS: readonly [RegExp, string][] = [\n  [/::suilend|::obligation/, 'lending'],\n  [/::navi|::lending_core|::incentive_v\\d+|::oracle_pro/, 'lending'],\n  /**\n   * DEX modules — both direct calls and aggregator legs. The Cetus\n   * aggregator dispatches through a per-DEX module (e.g.\n   * `cetus::swap`, `flowx_amm::swap`, `aftermath::swap`, …) plus\n   * router glue functions. We list every DEX module the aggregator\n   * supports today so a single-DEX call still classifies cleanly.\n   */\n  [/::cetus(?:_dlmm)?::|::pool::|::deepbook|::flowx_(?:amm|clmm)::|::kriya_(?:amm|clmm)::|::turbos::|::aftermath::|::afsui::|::bluefin::|::bluemove::|::ferra_(?:clmm|dlmm)::|::haedal_hmm::|::hasui::|::hawal::|::magma::|::momentum::|::obric::|::springsui::|::steamm_cpmm::|::fullsail::|::alphafi::|::volo_swap::/, 'swap'],\n  /**\n   * Cetus aggregator router glue. These are the swap-context and\n   * balance-handling helpers the aggregator emits around per-DEX\n   * legs. Without this entry a tx that ONLY had router calls\n   * (theoretically possible for setup/cleanup) would slip through;\n   * in practice these always coexist with a DEX leg, but the entry\n   * is cheap insurance.\n   */\n  [/::router::(?:new_swap_context(?:_v)?|confirm_swap|transfer_balance|take_balance|transfer_or_destroy_coin)/, 'swap'],\n  [/::transfer::public_transfer/, 'send'],\n];\n\n/**\n * Finer-grained display labels — derived from MoveCall function names.\n * The card renders `label ?? action`, so when this map matches we get\n * \"Deposit\" / \"Withdraw\" / \"Borrow\" / \"Repay\" / \"Payment link\" instead\n * of the generic \"Lending\" or \"Transaction\".\n *\n * Order matters: more specific patterns first. Each entry is\n * (regex, label) where the regex is matched against the\n * fully-qualified MoveCall target `pkg::module::function`.\n */\nexport const LABEL_PATTERNS: readonly [RegExp, string][] = [\n  [/::pay(?:ment_kit|_kit)?::|::create_payment_link|::pay_link/, 'payment_link'],\n  [/::create_invoice|::invoice::/, 'invoice'],\n  [/::deposit|::supply|::mint_ctokens/, 'deposit'],\n  [/::withdraw|::redeem|::redeem_ctokens/, 'withdraw'],\n  [/::borrow/, 'borrow'],\n  [/::repay/, 'repay'],\n  [/::claim_reward|::claim::|::claim_incentive/, 'claim'],\n  [/::stake/, 'stake'],\n  [/::unstake|::burn::/, 'unstake'],\n  [/::liquidate/, 'liquidate'],\n];\n\nexport interface ClassifyBalanceChange {\n  owner: { AddressOwner?: string } | string;\n  coinType: string;\n  amount: string;\n}\n\nfunction resolveOwner(owner: ClassifyBalanceChange['owner']): string | null {\n  if (typeof owner === 'object' && owner.AddressOwner) return owner.AddressOwner;\n  if (typeof owner === 'string') return owner;\n  return null;\n}\n\nexport function classifyAction(targets: string[], commandTypes: string[]): string {\n  for (const target of targets) {\n    for (const [pattern, label] of KNOWN_TARGETS) {\n      if (pattern.test(target)) return label;\n    }\n  }\n  if (commandTypes.includes('TransferObjects') && !commandTypes.includes('MoveCall')) return 'send';\n  return 'transaction';\n}\n\n/**\n * Last-resort fallback when neither `LABEL_PATTERNS` nor the action\n * bucket produces something useful.\n *\n * Returns the first MoveCall's *module* name (e.g. \"navi\", \"spam\") so\n * the card shows something better than the literal word \"transaction\".\n * When no MoveCall exists, returns 'on-chain'.\n *\n * Note: callers should prefer `classifyLabel` which now layers\n * pattern-match → coarse action → module name (see commentary there).\n */\nexport function fallbackLabel(targets: string[]): string {\n  if (!targets.length) return 'on-chain';\n  const first = targets[0];\n  const parts = first.split('::');\n  if (parts.length >= 2 && parts[1]) return parts[1].toLowerCase();\n  return 'on-chain';\n}\n\n/**\n * Three-tier label resolution for the transaction history card:\n *   1. Specific keyword match in `LABEL_PATTERNS` (\"deposit\",\n *      \"payment_link\", …).\n *   2. Coarse action bucket from `classifyAction` (\"swap\", \"send\",\n *      \"lending\") — prevents leaking opaque internal module names like\n *      \"router\" (Cetus aggregator) or \"cross_swap\" (third-party DEX\n *      aggregators) for txs that we already classified as a swap.\n *   3. Module name from the first MoveCall (`fallbackLabel`) — only\n *      used when the action bucket itself is the generic \"transaction\".\n *\n * Pre-v0.46.2 we skipped tier 2, so swaps showed labels like \"router\",\n * \"cross_swap\", \"scallop_router\", etc. instead of the clean \"swap\".\n */\nexport function classifyLabel(targets: string[], commandTypes: string[]): string {\n  for (const target of targets) {\n    for (const [pattern, label] of LABEL_PATTERNS) {\n      if (pattern.test(target)) return label;\n    }\n  }\n  if (commandTypes.includes('TransferObjects') && !commandTypes.includes('MoveCall')) return 'send';\n  const action = classifyAction(targets, commandTypes);\n  if (action !== 'transaction') return action;\n  return fallbackLabel(targets);\n}\n\n/**\n * Balance-direction tiebreaker for ambiguous lending calls.\n *\n * Many lending modules expose generic entry points (NAVI's bundled\n * flash actions, `lending_core::*::entry_*`, etc.) that don't carry\n * a `deposit`/`withdraw`/`borrow`/`repay` keyword in the function\n * name. When `classifyLabel` falls back to a bare module name like\n * `\"lending\"` for a known lending tx, infer direction from the user's\n * non-SUI balance change:\n *   - net outflow of the supplied asset → deposit (also covers repay,\n *     but repay-without-keyword is essentially never emitted).\n *   - net inflow of the supplied asset → withdraw (also covers borrow).\n * SUI is excluded so gas-only transactions don't get mislabeled.\n *\n * If `LABEL_PATTERNS` matched a specific keyword, the existing label is\n * returned unchanged.\n */\nexport function refineLendingLabel(\n  currentAction: string,\n  currentLabel: string,\n  moveCallTargets: string[],\n  changes: ClassifyBalanceChange[],\n  address: string,\n): string {\n  if (currentAction !== 'lending') return currentLabel;\n  const labelMatchedSpecific = LABEL_PATTERNS.some(([p]) =>\n    moveCallTargets.some((t) => p.test(t)),\n  );\n  if (labelMatchedSpecific) return currentLabel;\n\n  const userNonSuiOutflow = changes.find(\n    (c) => resolveOwner(c.owner) === address && c.coinType !== SUI_TYPE && BigInt(c.amount) < 0n,\n  );\n  if (userNonSuiOutflow) return 'deposit';\n\n  const userNonSuiInflow = changes.find(\n    (c) => resolveOwner(c.owner) === address && c.coinType !== SUI_TYPE && BigInt(c.amount) > 0n,\n  );\n  if (userNonSuiInflow) return 'withdraw';\n\n  return currentLabel;\n}\n\nexport interface ClassifyResult {\n  action: string;\n  label: string;\n}\n\nexport function classifyTransaction(\n  moveCallTargets: string[],\n  commandTypes: string[],\n  balanceChanges: ClassifyBalanceChange[],\n  address: string,\n): ClassifyResult {\n  const action = classifyAction(moveCallTargets, commandTypes);\n  const baseLabel = classifyLabel(moveCallTargets, commandTypes);\n  const label = refineLendingLabel(action, baseLabel, moveCallTargets, balanceChanges, address);\n  return { action, label };\n}\n\n/**\n * Direction of the user's net non-gas movement for this transaction.\n *\n *   - `'out'` — the user spent the asset (sends, deposits, repays,\n *     swap-in, payment-link payouts).\n *   - `'in'`  — the user received the asset (withdraws, borrows,\n *     swap-out, claims, deposits credited from another wallet).\n *\n * Used by the `TransactionHistoryCard` to choose the `+`/`−` sign and\n * color. Direction is computed from the actual on-chain balance change\n * — never from the textual label — so opaque action types (`'router'`,\n * `'cross_swap'`, …) still render the correct sign.\n */\nexport type TxDirection = 'in' | 'out';\n\nexport interface ExtractedTransfer {\n  amount?: number;\n  asset?: string;\n  recipient?: string;\n  direction?: TxDirection;\n}\n\n/**\n * Extracts the principal amount/asset/direction for a transaction\n * from its `balanceChanges`.\n *\n * Algorithm:\n *   1. Restrict to the user's *own* balance changes.\n *   2. Prefer non-SUI changes (gas-only SUI deltas are noise).\n *   3. Pick the change with the largest absolute value — the \"principal\".\n *   4. If no non-SUI change exists, fall back to the largest SUI change\n *      so pure-SUI transfers (stake/unstake/native send) still render.\n *   5. Direction follows the sign of the principal.\n *   6. Recipient is set only on outflows, by finding a matching inflow\n *      on a *non-user* address with the same coinType.\n *\n * Pre-v0.46.2 this function only inspected outflows, so withdraws,\n * borrows, claims, swap-receives and payment-link receives all\n * rendered with no amount on the rich card (and with a wrong sign,\n * because the card guessed direction from the label string).\n */\nexport function extractTransferDetails(\n  changes: ClassifyBalanceChange[] | undefined,\n  sender: string,\n): ExtractedTransfer {\n  if (!changes || changes.length === 0) return {};\n\n  const userChanges = changes.filter((c) => resolveOwner(c.owner) === sender);\n  if (userChanges.length === 0) return {};\n\n  const userNonSui = userChanges.filter((c) => c.coinType !== SUI_TYPE);\n  const pool = userNonSui.length > 0 ? userNonSui : userChanges;\n\n  let primary = pool[0];\n  let primaryAbs = bigintAbs(BigInt(primary.amount));\n  for (let i = 1; i < pool.length; i++) {\n    const abs = bigintAbs(BigInt(pool[i].amount));\n    if (abs > primaryAbs) {\n      primary = pool[i];\n      primaryAbs = abs;\n    }\n  }\n\n  const raw = BigInt(primary.amount);\n  if (raw === 0n) return {};\n\n  const decimals = getDecimalsForCoinType(primary.coinType);\n  const amount = Number(primaryAbs) / 10 ** decimals;\n  const asset = resolveSymbol(primary.coinType);\n  const direction: TxDirection = raw < 0n ? 'out' : 'in';\n\n  let recipient: string | undefined;\n  if (direction === 'out') {\n    const recipientChange = changes.find(\n      (c) =>\n        resolveOwner(c.owner) !== sender &&\n        c.coinType === primary.coinType &&\n        BigInt(c.amount) > 0n,\n    );\n    recipient = recipientChange ? resolveOwner(recipientChange.owner) ?? undefined : undefined;\n  }\n\n  return { amount, asset, recipient, direction };\n}\n\nfunction bigintAbs(n: bigint): bigint {\n  return n < 0n ? -n : n;\n}\n\n/**\n * Extract every non-zero user balance leg for a transaction — not\n * just the largest one. Order is RPC order; callers responsible for\n * any sorting (e.g. audric sorts by USD value once it's priced).\n *\n * Sui collapses balance changes by coin type, so a 3-step bundle\n * touching USDC three times surfaces as ONE leg of net USDC delta.\n * Distinguishing per-step legs would require parsing the PTB's\n * commands; this helper deliberately stops at the balance-change\n * granularity because that's what's reliably available across all\n * Sui RPC versions.\n *\n * Pre-v1.27.2 the only public API was `extractTransferDetails`,\n * which returned a single \"primary\" leg and made swap rows\n * unrenderable (showed `Swapped 987.60 MANIFEST` because MANIFEST\n * was the largest raw delta even though USDC was the value side).\n */\nexport function extractAllUserLegs(\n  changes: ClassifyBalanceChange[] | undefined,\n  sender: string,\n): import('../types.js').TransactionLeg[] {\n  if (!changes || changes.length === 0) return [];\n\n  const legs: import('../types.js').TransactionLeg[] = [];\n  for (const c of changes) {\n    if (resolveOwner(c.owner) !== sender) continue;\n    const raw = BigInt(c.amount);\n    if (raw === 0n) continue;\n    const decimals = getDecimalsForCoinType(c.coinType);\n    const absAmount = bigintAbs(raw);\n    legs.push({\n      coinType: c.coinType,\n      asset: resolveSymbol(c.coinType),\n      decimals,\n      amount: Number(absAmount) / 10 ** decimals,\n      rawAmount: raw.toString(),\n      direction: raw < 0n ? 'out' : 'in',\n    });\n  }\n\n  return legs;\n}\n","import type { TransactionRecord } from '../types.js';\nimport { getSuiGraphQLClient } from '../utils/sui.js';\nimport {\n  classifyTransaction,\n  extractAllUserLegs,\n  extractTransferDetails,\n  type ClassifyBalanceChange,\n} from './classify.js';\n\n// ---------------------------------------------------------------------------\n// [gRPC migration / S.447 + S.450] Transaction history is the one surface with\n// NO gRPC `core.*` equivalent (Stage 0 finding A): list-by-affected-address +\n// per-tx-by-digest live in the GraphQL RPC, not gRPC. Both go through the\n// Sui GraphQL endpoint (`getSuiGraphQLClient()`), share one node fragment +\n// one mapper, and feed the existing (tested) classifier in `classify.ts`.\n//\n// LIVE-VERIFIED 2026-06-15 (S.450) against `graphql.mainnet.sui.io` with a\n// real sender (send + Cetus swap digests). The live schema differs from the\n// older `transactionBlocks` one: the query is `transactions` / `transaction`\n// (filter `affectedAddress` — sender, sponsor, or recipient), the programmable kind is `ProgrammableTransaction`\n// (was `ProgrammableTransactionBlock`) with `commands { nodes }` (was\n// `transactions`), and a move call is `MoveCallCommand` with a nested\n// `function { name module { name package { address } } }` (was a flat\n// `MoveCallTransaction { package module functionName }`). GraphQL errors are\n// now SURFACED, not swallowed (the old `?? []` hid this schema drift as an\n// empty history for a whole session). Schema ref: https://docs.sui.io/references/sui-graphql\n// ---------------------------------------------------------------------------\n\nconst TX_NODE_FRAGMENT = `\n  digest\n  effects {\n    timestamp\n    gasEffects { gasSummary { computationCost storageCost storageRebate } }\n    balanceChanges { nodes { amount coinType { repr } owner { address } } }\n  }\n  kind {\n    __typename\n    ... on ProgrammableTransaction {\n      commands {\n        nodes {\n          __typename\n          ... on MoveCallCommand { function { name module { name package { address } } } }\n        }\n      }\n    }\n  }\n`;\n\n// `affectedAddress` (not `sentAddress`) so history includes INCOMING transactions\n// — received payments, x402/MPP refunds, airdrops — not just ones the agent\n// signed. Per the Sui GraphQL schema: \"transactions that interacted with the\n// given address … as a sender, sponsor, or recipient.\" The shared classifier\n// already labels each leg's direction ('in' / 'out'), so inbound txns render\n// correctly downstream.\nconst HISTORY_QUERY = `query History($address: SuiAddress!, $last: Int!) {\n  transactions(last: $last, filter: { affectedAddress: $address }) {\n    nodes {${TX_NODE_FRAGMENT}}\n  }\n}`;\n\nconst TX_BY_DIGEST_QUERY = `query TxByDigest($digest: String!) {\n  transaction(digest: $digest) {${TX_NODE_FRAGMENT}}\n}`;\n\n/** Minimal shape of a Sui GraphQL transaction node we consume. */\ninterface GqlTxNode {\n  digest?: string;\n  effects?: {\n    timestamp?: string;\n    // Live schema returns gas as numbers; `Number()` in the mapper tolerates both.\n    gasEffects?: { gasSummary?: { computationCost?: string | number; storageCost?: string | number; storageRebate?: string | number } };\n    balanceChanges?: { nodes?: Array<{ amount?: string; coinType?: { repr?: string }; owner?: { address?: string } }> };\n  };\n  kind?: {\n    __typename?: string;\n    commands?: {\n      nodes?: Array<{\n        __typename?: string;\n        function?: { name?: string; module?: { name?: string; package?: { address?: string } } };\n      }>;\n    };\n  };\n}\n\n/** GraphQL transport result with the optional `errors` array surfaced. */\ninterface GqlResult<T> {\n  data?: T;\n  errors?: Array<{ message?: string }>;\n}\n\nfunction assertNoGqlErrors(res: GqlResult<unknown>, what: string): void {\n  if (res.errors?.length) {\n    throw new Error(\n      `Sui GraphQL ${what} failed: ${res.errors.map((e) => e.message ?? 'unknown error').join('; ')}`,\n    );\n  }\n}\n\nexport async function queryHistory(\n  address: string,\n  limit = 20,\n): Promise<TransactionRecord[]> {\n  const gql = getSuiGraphQLClient();\n  const res = (await gql.query({ query: HISTORY_QUERY, variables: { address, last: limit } })) as GqlResult<{\n    transactions?: { nodes?: GqlTxNode[] };\n  }>;\n  assertNoGqlErrors(res, 'history query');\n  const nodes = res.data?.transactions?.nodes ?? [];\n  // GraphQL `last` returns ascending; the legacy JSON-RPC path returned\n  // descending (newest first) — reverse to preserve caller expectations.\n  return nodes.map((n) => recordFromGqlNode(n, address)).reverse();\n}\n\nexport async function queryTransaction(\n  digest: string,\n  senderAddress: string,\n): Promise<TransactionRecord | null> {\n  const gql = getSuiGraphQLClient();\n  const res = (await gql.query({ query: TX_BY_DIGEST_QUERY, variables: { digest } })) as GqlResult<{\n    transaction?: GqlTxNode | null;\n  }>;\n  assertNoGqlErrors(res, 'transaction query');\n  const node = res.data?.transaction;\n  if (!node) return null; // genuine not-found (distinct from a query error, which throws above)\n  return recordFromGqlNode(node, senderAddress);\n}\n\n/**\n * Map a Sui GraphQL transactionBlock node → the primitives the shared\n * classifier consumes, then build the record. Isolated so the legacy\n * JSON-RPC `parseTxRecord` (back-compat, below) and this GraphQL path\n * converge on one classification routine.\n */\nfunction recordFromGqlNode(node: GqlTxNode, address: string): TransactionRecord {\n  const gs = node.effects?.gasEffects?.gasSummary;\n  const gasCost = gs\n    ? (Number(gs.computationCost ?? 0) + Number(gs.storageCost ?? 0) - Number(gs.storageRebate ?? 0)) / 1e9\n    : undefined;\n\n  const balanceChanges: ClassifyBalanceChange[] = (node.effects?.balanceChanges?.nodes ?? [])\n    .filter((b) => b.coinType?.repr && b.amount != null)\n    .map((b) => ({ coinType: b.coinType!.repr!, amount: String(b.amount), owner: b.owner?.address ?? '' }));\n\n  const moveCallTargets: string[] = [];\n  const commandTypes: string[] = [];\n  if (node.kind?.__typename === 'ProgrammableTransaction') {\n    for (const cmd of node.kind.commands?.nodes ?? []) {\n      if (cmd.__typename === 'MoveCallCommand') {\n        commandTypes.push('MoveCall');\n        const fn = cmd.function;\n        const pkg = fn?.module?.package?.address;\n        const mod = fn?.module?.name;\n        const name = fn?.name;\n        if (pkg && mod && name) {\n          moveCallTargets.push(`${pkg}::${mod}::${name}`);\n        }\n      } else if (cmd.__typename === 'TransferObjectsCommand') {\n        commandTypes.push('TransferObjects');\n      }\n    }\n  }\n\n  // GraphQL effects.timestamp is an ISO datetime; the record wants ms.\n  const ts = node.effects?.timestamp ? Date.parse(node.effects.timestamp) : 0;\n\n  return buildRecord({\n    digest: node.digest ?? '',\n    moveCallTargets,\n    commandTypes,\n    balanceChanges,\n    timestampMs: Number.isFinite(ts) ? ts : 0,\n    gasCost,\n    address,\n  });\n}\n\n/** Shared record builder — classification + leg/transfer extraction. */\nfunction buildRecord(args: {\n  digest: string;\n  moveCallTargets: string[];\n  commandTypes: string[];\n  balanceChanges: ClassifyBalanceChange[];\n  timestampMs: number;\n  gasCost: number | undefined;\n  address: string;\n}): TransactionRecord {\n  const { digest, moveCallTargets, commandTypes, balanceChanges, timestampMs, gasCost, address } = args;\n  const legs = extractAllUserLegs(balanceChanges, address);\n  const { amount, asset, recipient, direction } = extractTransferDetails(balanceChanges, address);\n  const { action, label } = classifyTransaction(moveCallTargets, commandTypes, balanceChanges, address);\n  return { digest, action, label, legs, amount, asset, recipient, direction, timestamp: timestampMs, gasCost };\n}\n\n/**\n * Shape of a transaction block as returned by `suix_queryTransactionBlocks`\n * with `showEffects | showInput | showBalanceChanges` enabled. Exported so\n * downstream consumers (audric dashboard `/api/history`, `/api/activity`,\n * etc.) can type their RPC calls without redeclaring the structure.\n */\nexport interface SuiRpcTxBlock {\n  digest: string;\n  timestampMs?: string;\n  transaction?: unknown;\n  effects?: { gasUsed?: { computationCost: string; storageCost: string; storageRebate: string } };\n  balanceChanges?: ClassifyBalanceChange[];\n}\n\n/**\n * Convert a single Sui RPC transaction block to a {@link TransactionRecord}\n * using the canonical (shared) classifier and balance-change extractor.\n *\n * This is the single source of truth for transaction parsing across the\n * agent-tool path AND the dashboard-API path. Use it instead of writing\n * a bespoke parser per surface.\n *\n * @param tx      Raw RPC tx block (must include `effects`, `input`, `balanceChanges`).\n * @param address Wallet address whose perspective we're parsing from.\n */\nexport function parseSuiRpcTx(tx: SuiRpcTxBlock, address: string): TransactionRecord {\n  return parseTxRecord(tx, address);\n}\n\n/**\n * Extract the sender (signer) address from a raw RPC tx block.\n * Returns `null` if the block shape is unexpected.\n */\nexport function extractTxSender(txBlock: unknown): string | null {\n  try {\n    if (!txBlock || typeof txBlock !== 'object') return null;\n    const data = 'data' in txBlock ? (txBlock as Record<string, unknown>).data : undefined;\n    if (!data || typeof data !== 'object') return null;\n    return ((data as Record<string, unknown>).sender as string) ?? null;\n  } catch {\n    return null;\n  }\n}\n\n/**\n * Extract MoveCall targets (`<pkg>::<module>::<function>`) and the\n * sequence of programmable-transaction command types (e.g. `MoveCall`,\n * `TransferObjects`) from a raw RPC tx block. Tolerates both the\n * legacy `inner.transactions` field and the newer `inner.commands`\n * field.\n */\nexport function extractTxCommands(txBlock: unknown): {\n  moveCallTargets: string[];\n  commandTypes: string[];\n} {\n  return extractCommands(txBlock);\n}\n\n// [back-compat] Legacy JSON-RPC-shape parser. The live history path is now\n// GraphQL (above); this stays for external consumers that already hold a\n// JSON-RPC tx block (e.g. via `parseSuiRpcTx`). Routes through `buildRecord`\n// so classification is identical to the GraphQL path.\nfunction parseTxRecord(tx: SuiRpcTxBlock, address: string): TransactionRecord {\n  const gasUsed = tx.effects?.gasUsed;\n  const gasCost = gasUsed\n    ? (Number(gasUsed.computationCost) +\n        Number(gasUsed.storageCost) -\n        Number(gasUsed.storageRebate)) /\n      1e9\n    : undefined;\n\n  const { moveCallTargets, commandTypes } = extractCommands(tx.transaction);\n  return buildRecord({\n    digest: tx.digest,\n    moveCallTargets,\n    commandTypes,\n    balanceChanges: tx.balanceChanges ?? [],\n    timestampMs: Number(tx.timestampMs ?? 0),\n    gasCost,\n    address,\n  });\n}\n\ninterface CommandInfo {\n  moveCallTargets: string[];\n  commandTypes: string[];\n}\n\nfunction extractCommands(txBlock: unknown): CommandInfo {\n  const result: CommandInfo = { moveCallTargets: [], commandTypes: [] };\n  try {\n    if (!txBlock || typeof txBlock !== 'object') return result;\n    const data = 'data' in txBlock ? (txBlock as Record<string, unknown>).data : undefined;\n    if (!data || typeof data !== 'object') return result;\n    const inner = 'transaction' in (data as Record<string, unknown>)\n      ? (data as Record<string, unknown>).transaction\n      : undefined;\n    if (!inner || typeof inner !== 'object') return result;\n    const commands = 'commands' in (inner as Record<string, unknown>)\n      ? (inner as Record<string, unknown>).commands\n      : 'transactions' in (inner as Record<string, unknown>)\n        ? (inner as Record<string, unknown>).transactions\n        : undefined;\n    if (!Array.isArray(commands)) return result;\n\n    for (const cmd of commands as Record<string, unknown>[]) {\n      if (cmd.MoveCall) {\n        const mc = cmd.MoveCall as { package: string; module: string; function: string };\n        result.moveCallTargets.push(`${mc.package}::${mc.module}::${mc.function}`);\n        result.commandTypes.push('MoveCall');\n      } else if (cmd.TransferObjects) {\n        result.commandTypes.push('TransferObjects');\n      }\n    }\n  } catch { /* best effort */ }\n  return result;\n}\n","import { EventEmitter } from 'eventemitter3';\nimport type { SuiGrpcClient } from '@mysten/sui/grpc';\nimport type { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';\nimport { Transaction, coinWithBalance, type TransactionObjectArgument } from '@mysten/sui/transactions';\nimport { createPaymentTransactionUri } from '@mysten/payment-kit';\nimport { getSuiClient, getSuiGrpcClient } from './utils/sui.js';\nimport {\n  generateKeypair,\n  keypairFromPrivateKey,\n  saveKey,\n  loadKey,\n  walletExists,\n  exportPrivateKey,\n  getAddress,\n} from './wallet/keyManager.js';\nimport type { TransactionSigner } from './signer.js';\nimport { KeypairSigner } from './wallet/keypairSigner.js';\nimport { executeTx } from './wallet/executeTx.js';\nimport { payWithMpp } from './wallet/pay.js';\nimport { ZkLoginSigner, type ZkLoginProof } from './wallet/zkLoginSigner.js';\nimport { buildSendTx } from './wallet/send.js';\nimport { queryBalance } from './wallet/balance.js';\nimport { queryHistory, queryTransaction } from './wallet/history.js';\nimport { resolveSymbol, resolveCoinDecimals } from './token-registry.js';\nimport {\n  SUI_ADDRESS_REGEX,\n  SuinsNotRegisteredError,\n  looksLikeSuiNs,\n  resolveSuinsViaRpc,\n} from './utils/suins.js';\n// [B5 v2 / 2026-04-30] No fee imports — CLI / direct SDK is fee-free. Consumer\n// apps (Audric) own fee policy (Cetus `overlayFee` on swaps → T2000_OVERLAY_FEE_WALLET).\nimport type {\n  T2000Options,\n  BalanceResponse,\n  SendResult,\n  TransactionRecord,\n  DepositInfo,\n  PaymentRequest,\n  PayOptions,\n  PayResult,\n  SwapResult,\n  SwapQuoteResult,\n} from './types.js';\nimport { T2000Error } from './errors.js';\nimport { SUPPORTED_ASSETS, assertAllowedAsset, type SendableAsset, type SupportedAsset } from './constants.js';\n\nimport { truncateAddress } from './utils/sui.js';\nimport { LimitEnforcer, approxUsdValue } from './limits/index.js';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\nconst DEFAULT_CONFIG_DIR = join(homedir(), '.t2000');\n\ninterface T2000Events {\n  balanceChange: (event: { asset: string; previous: number; current: number; cause: string; tx?: string }) => void;\n  healthWarning: (event: { healthFactor: number; threshold: number; severity: 'warning' }) => void;\n  healthCritical: (event: { healthFactor: number; threshold: number; severity: 'critical' }) => void;\n  yield: (event: { earned: number; total: number; apy: number; timestamp: number }) => void;\n  error: (error: T2000Error) => void;\n}\n\n// Sign + execute a transaction with the agent's signer. Replaces the pre-v2 gas\n// manager — every transaction is now self-funded by the agent's wallet.\nexport class T2000 extends EventEmitter<T2000Events> {\n  private readonly _signer: TransactionSigner;\n  private readonly _keypair?: Ed25519Keypair;\n  private readonly client: SuiGrpcClient;\n  private readonly _address: string;\n  /** Unified spending-limit gate (per-tx + cumulative daily, USD). Shared by\n   *  CLI + MCP + programmatic writes — one gate, no bypass (R-0 Finding 1). */\n  readonly limits: LimitEnforcer;\n\n  private constructor(keypair: Ed25519Keypair, client: SuiGrpcClient, configDir?: string);\n  private constructor(signer: TransactionSigner, client: SuiGrpcClient, configDir: string | undefined, isSignerMode: true);\n  private constructor(\n    keypairOrSigner: Ed25519Keypair | TransactionSigner,\n    client: SuiGrpcClient,\n    configDir?: string,\n    isSignerMode?: boolean,\n  ) {\n    super();\n    if (isSignerMode) {\n      this._signer = keypairOrSigner as TransactionSigner;\n      this._keypair = undefined;\n      this._address = this._signer.getAddress();\n    } else {\n      const kp = keypairOrSigner as Ed25519Keypair;\n      this._keypair = kp;\n      this._signer = new KeypairSigner(kp);\n      this._address = getAddress(kp);\n    }\n    this.client = client;\n    this.limits = new LimitEnforcer(configDir);\n  }\n\n  static async create(options: T2000Options = {}): Promise<T2000> {\n    const { keyPath, rpcUrl } = options;\n\n    const client = getSuiClient(rpcUrl);\n\n    const exists = await walletExists(keyPath);\n    if (!exists) {\n      throw new T2000Error(\n        'WALLET_NOT_FOUND',\n        'No wallet found. Run `t2 init` to create one.',\n      );\n    }\n\n    // [v4.0] loadKey reads v2 plain Bech32 JSON. Anything else throws\n    // WALLET_CORRUPT. PIN/passphrase fields on T2000Options are accepted\n    // for back-compat but IGNORED.\n    const keypair = await loadKey(undefined, keyPath);\n    return new T2000(keypair, client, DEFAULT_CONFIG_DIR);\n  }\n\n  static fromPrivateKey(privateKey: string, options: { network?: 'mainnet' | 'testnet'; rpcUrl?: string } = {}): T2000 {\n    const keypair = keypairFromPrivateKey(privateKey);\n    const client = getSuiClient(options.rpcUrl);\n    return new T2000(keypair, client);\n  }\n\n  static async init(options: { pin?: string; passphrase?: string; keyPath?: string; name?: string } = {}): Promise<{ agent: T2000; address: string }> {\n    // [v4.0] pin/passphrase accepted for back-compat but IGNORED.\n    const keypair = generateKeypair();\n    await saveKey(keypair, undefined, options.keyPath);\n\n    const client = getSuiClient();\n    const agent = new T2000(keypair, client, DEFAULT_CONFIG_DIR);\n    const address = agent.address();\n\n    return { agent, address };\n  }\n\n  // -- Gas --\n\n  /** SuiGrpcClient used by this agent — exposed for integrations. */\n  get suiClient(): SuiGrpcClient {\n    return this.client;\n  }\n\n  /** Ed25519Keypair used by this agent — exposed for CLI/MCP integrations. */\n  get keypair(): Ed25519Keypair {\n    if (!this._keypair) {\n      throw new T2000Error('WALLET_NOT_FOUND', 'Keypair not available — this instance uses zkLogin');\n    }\n    return this._keypair;\n  }\n\n  /** Transaction signer (works for both keypair and zkLogin). */\n  get signer(): TransactionSigner {\n    return this._signer;\n  }\n\n  // -- MPP Payments --\n\n  async pay(options: PayOptions): Promise<PayResult> {\n    // Gate on the maxPrice ceiling pre-flight (USD); record the ACTUAL cost\n    // post-settle. `force` bypasses (caller owns consent).\n    this.limits.assert({ operation: 'pay', amountUsd: options.maxPrice ?? 0, force: options.force });\n\n    // Canonical gasless MPP pay loop lives in `wallet/pay.ts` (browser-safe,\n    // shared with the Audric client's unified gasless write path). T2000\n    // owns only the limit book-ends; the server budget ledger is the cap on\n    // the browser side, so the browser caller skips the SDK limit gate.\n    const result = await payWithMpp({ signer: this._signer, client: this.client, options });\n\n    if (result.paid) {\n      this.limits.record(result.cost ?? options.maxPrice ?? 0);\n    }\n\n    return result;\n  }\n\n  // [S.323 / 2026-05-25] VOLO vSUI staking surfaces removed (full cut).\n  // Engine cut Volo in S.277; SDK + CLI + MCP followed in S.323 because the\n  // product surface (five products: Passport / Intelligence / Finance / Pay\n  // / Store) doesn't include a staking primitive. vSUI still appears in the\n  // codebase as a passive token (NAVI reward rewards, Cetus swap routing),\n  // but there is no longer any way to MINT or REDEEM vSUI through t2000.\n  // History: see spec/archive/v07e/AUDIT_V07E_EARNS_ITS_KEEP_2026-05-23.md\n  // and the S.323 build-tracker entry.\n\n  // -- Swap --\n\n  async swap(params: {\n    from: string;\n    to: string;\n    amount: number;\n    byAmountIn?: boolean;\n    slippage?: number;\n    force?: boolean;\n  }): Promise<SwapResult> {\n    // Gate on the input-side USD value (stables 1:1; SUI/other → ungated).\n    this.limits.assert({\n      operation: 'swap',\n      amountUsd: approxUsdValue(params.from, params.amount) ?? 0,\n      force: params.force,\n    });\n\n    const { findSwapRoute, buildSwapTx, resolveTokenType, preflightSwap } = await import('./protocols/cetus-swap.js');\n\n    // Layer 2 — cheap synchronous preflight (from/to/amount sanity, identity\n    // swap). Runs before any route-finding network call.\n    const pf = preflightSwap({ from: params.from, to: params.to, amount: params.amount });\n    if (!pf.valid) throw new T2000Error(pf.code, pf.error);\n\n    const fromType = resolveTokenType(params.from);\n    const toType = resolveTokenType(params.to);\n    if (!fromType) throw new T2000Error('ASSET_NOT_SUPPORTED', `Unknown token: ${params.from}. Provide the full coin type.`);\n    if (!toType) throw new T2000Error('ASSET_NOT_SUPPORTED', `Unknown token: ${params.to}. Provide the full coin type.`);\n\n    const byAmountIn = params.byAmountIn ?? true;\n    const slippage = Math.min(params.slippage ?? 0.01, 0.05);\n\n    const fromDecimals = await resolveCoinDecimals(this.client, fromType);\n    const rawAmount = BigInt(Math.floor(params.amount * 10 ** fromDecimals));\n\n    const route = await findSwapRoute({\n      walletAddress: this._address,\n      from: fromType,\n      to: toType,\n      amount: rawAmount,\n      byAmountIn,\n    });\n\n    if (!route) throw new T2000Error('SWAP_NO_ROUTE', `No swap route found for ${params.from} -> ${params.to}.`);\n    if (route.insufficientLiquidity) throw new T2000Error('SWAP_NO_ROUTE', `Insufficient liquidity for ${params.from} -> ${params.to}.`);\n    if (route.priceImpact > 0.05) {\n      console.warn(`[swap] High price impact: ${(route.priceImpact * 100).toFixed(2)}%`);\n    }\n\n    const toDecimals = await resolveCoinDecimals(this.client, toType);\n\n    // Snapshot pre-swap balance for fallback diff calculation\n    let preBalRaw = 0n;\n    try {\n      const preBal = await this.client.core.getBalance({ owner: this._address, coinType: toType });\n      preBalRaw = BigInt(preBal.balance.balance);\n    } catch { /* first time holding this token — balance is 0 */ }\n\n    const gasResult = await executeTx(this.client, this._signer, async () => {\n      const tx = new Transaction();\n      tx.setSender(this._address);\n\n      let inputCoin: TransactionObjectArgument;\n      if (fromType === '0x2::sui::SUI') {\n        [inputCoin] = tx.splitCoins(tx.gas, [rawAmount]);\n      } else {\n        const bal = await this.client.core.getBalance({ owner: this._address, coinType: fromType });\n        if (BigInt(bal.balance.balance) < rawAmount) {\n          throw new T2000Error('INSUFFICIENT_BALANCE', `Insufficient ${params.from} balance.`, {\n            available: Number(bal.balance.balance) / 10 ** fromDecimals,\n            required: params.amount,\n          });\n        }\n        inputCoin = coinWithBalance({ type: fromType, balance: rawAmount })(tx);\n      }\n\n      const outputCoin = await buildSwapTx({\n        walletAddress: this._address,\n        route,\n        tx,\n        inputCoin,\n        slippage,\n      });\n\n      tx.transferObjects([outputCoin], this._address);\n      return tx;\n    });\n\n    const fromAmount = Number(route.amountIn) / 10 ** fromDecimals;\n    let toAmount = Number(route.amountOut) / 10 ** toDecimals;\n\n    // --- Primary: parse balance changes from the finalized transaction ---\n    const toTypeSuffix = toType.split('::').slice(1).join('::');\n    try {\n      // [gRPC migration] core.waitForTransaction returns a discriminated union;\n      // balanceChanges are `{ coinType, address, amount }` (signed string),\n      // not the legacy `{ owner: { AddressOwner } }` shape.\n      const fullTx = await this.client.core.waitForTransaction({\n        digest: gasResult.digest,\n        include: { balanceChanges: true },\n        timeout: 8_000,\n      });\n      const txn = fullTx.$kind === 'Transaction' ? fullTx.Transaction : fullTx.FailedTransaction;\n      const changes = txn.balanceChanges ?? [];\n      const received = changes.find((c) => {\n        if (BigInt(c.amount) <= 0n) return false;\n        if (!c.address || c.address.toLowerCase() !== this._address.toLowerCase()) return false;\n        if (c.coinType === toType) return true;\n        return c.coinType.endsWith(toTypeSuffix);\n      });\n      if (received) {\n        const actual = Number(BigInt(received.amount)) / 10 ** toDecimals;\n        if (actual > 0) toAmount = actual;\n      }\n    } catch {\n      // waitForTransaction timeout — fall through to balance diff\n    }\n\n    // --- Fallback: pre/post getBalance diff ---\n    const cetusEstimate = Number(route.amountOut) / 10 ** toDecimals;\n    if (Math.abs(toAmount - cetusEstimate) < 0.001) {\n      try {\n        await new Promise((r) => setTimeout(r, 2000));\n        const postBal = await this.client.core.getBalance({ owner: this._address, coinType: toType });\n        const postRaw = BigInt(postBal.balance.balance);\n        const delta = Number(postRaw - preBalRaw) / 10 ** toDecimals;\n        if (delta > 0) toAmount = delta;\n      } catch {\n        // Balance diff fallback failed — use Cetus estimate\n      }\n    }\n\n    // Resolve full coin types to user-friendly token names\n    const fromName = resolveSymbol(fromType);\n    const toName = resolveSymbol(toType);\n\n    const routeDesc = route.routerData.paths\n      ?.map((p) => p.provider)\n      .filter(Boolean)\n      .slice(0, 3)\n      .join(' + ') ?? 'Cetus Aggregator';\n\n    // Record the settled input-side USD against the cumulative daily total.\n    this.limits.record(approxUsdValue(params.from, params.amount) ?? 0);\n\n    return {\n      success: true,\n      tx: gasResult.digest,\n      fromToken: fromName,\n      toToken: toName,\n      fromAmount,\n      toAmount,\n      priceImpact: route.priceImpact,\n      route: routeDesc,\n      gasCost: gasResult.gasCostSui,\n    };\n  }\n\n  /**\n   * [SPEC_AGENTIC_STACK P1 / SDK F2 — 2026-05-25]\n   * Thin wrapper around the standalone `getSwapQuote()`. Pre-Phase 1 this method\n   * was ~50 LoC duplicating `swap-quote.ts` — missing `serializedRoute` (SPEC 20.2\n   * fast-path) and the `providers` allow-list (Bug A fix / Pyth-dependent\n   * provider filter for sponsored callers). Routing both API surfaces through\n   * one implementation ensures fixes land for both.\n   */\n  async swapQuote(params: {\n    from: string;\n    to: string;\n    amount: number;\n    byAmountIn?: boolean;\n    providers?: string[];\n  }): Promise<SwapQuoteResult> {\n    const { getSwapQuote } = await import('./swap-quote.js');\n    const { resolveTokenType } = await import('./protocols/cetus-swap.js');\n    // [2.11] Resolve decimals on-chain for non-registry coin types so the quote\n    // matches what a real swap would compute (the standalone getSwapQuote can't\n    // — it has no client). Falls back to its registry default if unresolved.\n    const fromType = resolveTokenType(params.from);\n    const toType = resolveTokenType(params.to);\n    return getSwapQuote({\n      walletAddress: this._address,\n      from: params.from,\n      to: params.to,\n      amount: params.amount,\n      byAmountIn: params.byAmountIn,\n      providers: params.providers,\n      fromDecimals: fromType ? await resolveCoinDecimals(this.client, fromType) : undefined,\n      toDecimals: toType ? await resolveCoinDecimals(this.client, toType) : undefined,\n    });\n  }\n\n  // -- Wallet --\n\n  address(): string {\n    return this._address;\n  }\n\n  /**\n   * Send `amount` of `asset` to `to` (hex address or SuiNS name).\n   *\n   * [v4.0 Phase A Day 2 — SPEC_AGENT_WALLET_GREENFIELD §A]\n   *\n   * **Breaking changes from v3.x:**\n   * - `asset` is now REQUIRED (no implicit `?? 'USDC'` default). Callers\n   *   must specify `'USDC' | 'USDsui' | 'SUI'`. Sending `'USDT'` /\n   *   `'USDe'` / `'WAL'` / `'ETH'` / `'NAVX'` / `'GOLD'` now errors\n   *   with `INVALID_ASSET` — swap to a stable first.\n   * - USDC + USDsui builds go through `SuiGrpcClient` so the gRPC build\n   *   resolver auto-detects `0x2::balance::send_funds` eligibility and\n   *   zeros gas at simulate time. Result: **gasless USDC / USDsui sends\n   *   from a zero-SUI wallet.** SUI sends stay on the standard gas-paid\n   *   path.\n   *\n   * Submission stays on the JSON-RPC client (the rest of the SDK\n   * expects JSON-RPC for read paths, and Sui's docs explicitly support\n   * the \"build via gRPC, execute via JSON-RPC\" hybrid).\n   */\n  async send(params: { to: string; amount: number; asset: SupportedAsset; force?: boolean }): Promise<SendResult> {\n    // [v4.0 Phase A Day 2] Asset is REQUIRED at runtime (no more silent\n    // USDC default). The parameter type is `SupportedAsset` (the wider\n    // SDK surface) rather than `SendableAsset` so callers that still\n    // hand a wide-typed asset through — primarily the engine LLM tool\n    // surface — compile without modification. Runtime narrowing happens\n    // via `assertAllowedAsset('send', asset)`, which throws\n    // `INVALID_ASSET` for anything outside `['USDC', 'USDsui', 'SUI']`.\n    // This matches the SPEC verification gate `asset: 'USDY'` →\n    // `INVALID_ASSET` (runtime check, not compile check).\n    const asset = params.asset;\n    if (!asset) {\n      throw new T2000Error(\n        'INVALID_ASSET',\n        \"send() requires an explicit asset. Use one of: USDC, USDsui, SUI.\",\n      );\n    }\n    assertAllowedAsset('send', asset);\n    // `assertAllowedAsset('send', asset)` narrows the runtime value to\n    // one of `SendableAsset` (USDC / USDsui / SUI). Cast statically.\n    const sendableAsset = asset as SendableAsset;\n\n    // Spending-limit gate (USD; stables 1:1, SUI ungated). `force` bypasses.\n    this.limits.assert({\n      operation: 'send',\n      amountUsd: approxUsdValue(sendableAsset, params.amount) ?? 0,\n      force: params.force,\n    });\n\n    const resolved = await this.resolveRecipient(params.to);\n    const sendAmount = params.amount;\n    const sendTo = resolved.address;\n\n    // Gasless-eligible stables (USDC / USDsui) build via the dedicated gRPC\n    // client so the resolver can zero gas at simulate. SUI is not on the\n    // `balance::send_funds` allowlist, so it builds via the default client\n    // (also gRPC post-cutover) with normal gas — no separate build client.\n    const useGrpc = sendableAsset === 'USDC' || sendableAsset === 'USDsui';\n    const buildClient = useGrpc ? getSuiGrpcClient() : undefined;\n\n    const gasResult = await executeTx(\n      this.client,\n      this._signer,\n      () => buildSendTx({ client: this.client, address: this._address, to: sendTo, amount: sendAmount, asset: sendableAsset }),\n      { buildClient },\n    );\n\n    this.limits.record(approxUsdValue(sendableAsset, sendAmount) ?? 0);\n    const balance = await this.balance();\n\n    this.emitBalanceChange(sendableAsset, sendAmount, 'send', gasResult.digest);\n\n    return {\n      success: true,\n      tx: gasResult.digest,\n      amount: sendAmount,\n      to: resolved.address,\n      suinsName: resolved.suinsName,\n      gasCost: gasResult.gasCostSui,\n      gasCostUnit: 'SUI',\n      balance,\n    };\n  }\n\n  /**\n   * Resolve a recipient string into a canonical 0x address:\n   *   1. **hex** — `0x…` is used directly (no RPC round-trip).\n   *   2. **SuiNS** — `alex.sui` resolves via `suix_resolveNameServiceAddress`.\n   *\n   * Anything else is rejected. (The legacy `contacts.json` alias map was\n   * removed — SuiNS supersedes local contacts.)\n   *\n   * Returns `{ address, suinsName? }` so `send()` can stamp the name source\n   * on the receipt without re-resolving. Throws\n   * `T2000Error('SUINS_NOT_REGISTERED', …)` for well-formed but unregistered\n   * SuiNS names, keeping the SDK error surface `T2000Error`-only.\n   *\n   * Public so MCP's `t2000_send` dryRun preview shares one resolution path\n   * with the live execute path (never resolve the same input two ways).\n   */\n  async resolveRecipient(\n    input: string,\n  ): Promise<{ address: string; suinsName?: string }> {\n    const trimmed = input.trim();\n    if (SUI_ADDRESS_REGEX.test(trimmed)) {\n      return { address: trimmed.toLowerCase() };\n    }\n    if (looksLikeSuiNs(trimmed)) {\n      try {\n        const name = trimmed.toLowerCase();\n        const address = await resolveSuinsViaRpc(name);\n        if (!address) {\n          throw new SuinsNotRegisteredError(name);\n        }\n        return { address: address.toLowerCase(), suinsName: name };\n      } catch (err) {\n        if (err instanceof SuinsNotRegisteredError) {\n          throw new T2000Error(\n            'SUINS_NOT_REGISTERED',\n            err.message,\n          );\n        }\n        throw err;\n      }\n    }\n    throw new T2000Error(\n      'INVALID_ADDRESS',\n      `Cannot resolve recipient \"${input}\". Provide a 0x address or a .sui name.`,\n    );\n  }\n\n  async balance(): Promise<BalanceResponse> {\n    // [NAVI removed] Wallet-only balance: spendable stables + SUI gas reserve.\n    return queryBalance(this.client, this._address);\n  }\n\n  async history(params?: { limit?: number }): Promise<TransactionRecord[]> {\n    return queryHistory(this._address, params?.limit);\n  }\n\n  async transactionDetail(digest: string): Promise<TransactionRecord | null> {\n    return queryTransaction(digest, this._address);\n  }\n\n  async deposit(): Promise<DepositInfo> {\n    return {\n      address: this._address,\n      network: 'mainnet',\n      supportedAssets: ['USDC', 'USDT', 'SUI'],\n      instructions: [\n        `Send USDC to: ${this._address}`,\n        `Network: Sui Mainnet`,\n        `Or buy USDC on an exchange and withdraw to this address.`,\n        `USDC contract: ${SUPPORTED_ASSETS.USDC.type}`,\n      ].join('\\n'),\n    };\n  }\n\n  /**\n   * [SPEC_AGENTIC_STACK P1 / SDK F2 — 2026-05-25; refreshed S.342 / 2026-05-26]\n   * Preferred alias of `deposit()`. Was introduced to mirror the v3 `t2000 fund`\n   * CLI command; the v4 CLI surface is `t2 fund` (renamed back from the\n   * interim `t2 receive` in S.464). `deposit()` stays as the canonical method name for\n   * back-compat; `fund()` stays as a programmatic alias for audric + other\n   * SDK consumers that prefer the verb.\n   */\n  async fund(): Promise<DepositInfo> {\n    return this.deposit();\n  }\n\n  receive(params?: { amount?: number; currency?: string; memo?: string; label?: string }): PaymentRequest {\n    const amount = params?.amount ?? null;\n    const currency = params?.currency ?? 'USDC';\n    const memo = params?.memo ?? null;\n    const label = params?.label ?? null;\n    const nonce = crypto.randomUUID();\n\n    let qrUri: string;\n    if (amount != null && amount > 0) {\n      const decimals = currency === 'SUI' ? 9 : 6;\n      const coinType = currency === 'SUI'\n        ? '0x2::sui::SUI'\n        : SUPPORTED_ASSETS.USDC.type;\n      const rawAmount = BigInt(Math.floor(amount * 10 ** decimals));\n      qrUri = createPaymentTransactionUri({\n        receiverAddress: this._address,\n        amount: rawAmount,\n        coinType,\n        nonce,\n        ...(label ? { label } : {}),\n        ...(memo ? { message: memo } : {}),\n      });\n    } else {\n      const qrParts = [`sui:${this._address}`];\n      const queryParams: string[] = [];\n      if (currency !== 'SUI') queryParams.push(`currency=${currency}`);\n      if (memo) queryParams.push(`memo=${encodeURIComponent(memo)}`);\n      if (label) queryParams.push(`label=${encodeURIComponent(label)}`);\n      qrUri = queryParams.length > 0 ? `${qrParts[0]}?${queryParams.join('&')}` : qrParts[0];\n    }\n\n    const amountStr = amount != null ? `$${amount.toFixed(2)} ` : '';\n    const displayParts = [`Send ${amountStr}${currency} to ${truncateAddress(this._address)}`];\n    if (memo) displayParts.push(`Memo: ${memo}`);\n\n    return {\n      address: this._address,\n      network: 'mainnet',\n      amount,\n      currency,\n      memo,\n      label,\n      nonce,\n      qrUri,\n      displayText: displayParts.join('\\n'),\n    };\n  }\n\n  exportKey(): string {\n    return exportPrivateKey(this.keypair);\n  }\n\n  static fromZkLogin(opts: {\n    ephemeralKeypair: Ed25519Keypair;\n    zkProof: ZkLoginProof;\n    userAddress: string;\n    maxEpoch: number;\n    rpcUrl?: string;\n  }): T2000 {\n    const signer = new ZkLoginSigner(opts.ephemeralKeypair, opts.zkProof, opts.userAddress, opts.maxEpoch);\n    const client = getSuiClient(opts.rpcUrl);\n    return new T2000(signer, client, undefined, true);\n  }\n\n  private emitBalanceChange(asset: string, amount: number, cause: string, tx?: string): void {\n    this.emit('balanceChange', { asset, previous: 0, current: 0, cause, tx });\n  }\n}\n\n","// ---------------------------------------------------------------------------\n// Sui address + SuiNS normalization — single source of truth.\n//\n// [S.279 / CLI-CONTACTS-CLEANUP — 2026-05-23] Promoted from the deleted\n// `@t2000/engine` package to the SDK so the CLI's `T2000.send()` can accept\n// SuiNS names (`alex.sui`) alongside hex addresses — one canonical resolver.\n//\n// Background. Host read tools accept an optional `address` parameter so the\n// LLM can inspect any public Sui wallet. Each calls `normalizeAddressInput()`\n// to accept either `0x...` or `alex.sui` and returns a structured\n// `{ address, suinsName, raw }` triple. The SDK's `T2000.send()` uses the\n// same primitive, so a CLI user can run\n// `t2000 send alex.sui 10 USDC` without looking up the hex address first.\n//\n// Single source of truth — see `.cursor/rules/single-source-of-truth.mdc`\n// and `.cursor/rules/engineering-principles.mdc` Principle 2.\n// ---------------------------------------------------------------------------\n\nimport { getSuiGraphQLClient } from './sui.js';\n\n// [gRPC migration] SuiNS resolution moved off JSON-RPC\n// (`suix_resolveNameServiceAddress` / `suix_resolveNameServiceNames`) onto the\n// Sui GraphQL endpoint — the last JSON-RPC caller in the SDK. Both directions\n// use the unified `address(...)` query: `address(name:)` for forward\n// (name → address) and `address(address:){ defaultNameRecord { domain } }` for\n// reverse (address → primary name).\nconst RESOLVE_NAME_QUERY = `query ResolveSuins($name: String!) {\n  address(name: $name) { address }\n}`;\n\nconst REVERSE_NAME_QUERY = `query ReverseSuins($address: SuiAddress!) {\n  address(address: $address) { defaultNameRecord { domain } }\n}`;\n\ninterface GqlResult<T> {\n  data?: T;\n  errors?: Array<{ message?: string }>;\n}\n\n/**\n * Canonical 0x-address shape. Loose lower bound (>= 1 hex char) so\n * pre-v1.0 short addresses still validate; tools that need a full 64-hex\n * address can additionally check `length === 66`. Case-insensitive on\n * the `0x` prefix because some upstream callers (and historic tests)\n * uppercase the prefix as part of address normalization tests; the\n * normalizer always returns the lowercased canonical form regardless.\n */\nexport const SUI_ADDRESS_REGEX = /^0x[a-fA-F0-9]{1,64}$/i;\n\n/**\n * Strict canonical 0x-address shape (66 chars total). Used by the\n * resolver's \"looks like\" check to disambiguate \"user pasted an\n * address\" vs \"user typed a SuiNS name\".\n */\nexport const SUI_ADDRESS_STRICT_REGEX = /^0x[a-fA-F0-9]{64}$/i;\n\n/**\n * Mirrors the pattern in `audric/apps/web-v2/lib/suins-cache.ts` so the\n * host-side send executor and the engine-side read normalizer agree on\n * what counts as a SuiNS name. SuiNS allows nested labels (`team.alex.sui`)\n * but every label must use only `[a-z0-9-]`.\n */\nexport const SUINS_NAME_REGEX = /^[a-z0-9-]+(\\.[a-z0-9-]+)*\\.sui$/;\n\nexport class InvalidAddressError extends Error {\n  constructor(public readonly raw: string) {\n    super(\n      `\"${raw}\" isn't a valid Sui address or SuiNS name. ` +\n        `Pass a 0x-prefixed hex address (e.g. 0x40cd…3e62) or a SuiNS name ending in .sui (e.g. alex.sui).`,\n    );\n    this.name = 'InvalidAddressError';\n  }\n}\n\nexport class SuinsNotRegisteredError extends Error {\n  constructor(public readonly name_: string) {\n    super(\n      `\"${name_}\" isn't a registered SuiNS name. Double-check the spelling, ` +\n        `or paste the full Sui address (0x… 64 hex characters).`,\n    );\n    this.name = 'SuinsNotRegisteredError';\n  }\n}\n\nexport class SuinsRpcError extends Error {\n  constructor(public readonly name_: string, detail: string) {\n    super(`SuiNS lookup failed for \"${name_}\" (${detail}). Try again, or paste the full Sui address.`);\n    this.name = 'SuinsRpcError';\n  }\n}\n\n/**\n * Returns true if `value` looks like a SuiNS name (case-insensitive).\n * Cheap synchronous check — use to avoid an unnecessary RPC round-trip\n * for inputs that obviously aren't names (0x addresses, contact handles).\n */\nexport function looksLikeSuiNs(value: string): boolean {\n  if (!value) return false;\n  return SUINS_NAME_REGEX.test(value.trim().toLowerCase());\n}\n\n/**\n * Resolve a SuiNS name to its on-chain Sui address via the Sui GraphQL\n * `address(name:)` query. Returns `null` if the name resolves to no address\n * (= not registered or expired). Throws `SuinsRpcError` on transport failure.\n *\n * `ctx.signal` is honored for cancellation. (`ctx.suiRpcUrl` is retained for\n * call-site back-compat but no longer used — resolution runs against the\n * canonical GraphQL endpoint via `getSuiGraphQLClient()`.)\n */\nexport async function resolveSuinsViaRpc(\n  rawName: string,\n  ctx: { suiRpcUrl?: string; signal?: AbortSignal } = {},\n): Promise<string | null> {\n  const name = rawName.trim().toLowerCase();\n  if (!SUINS_NAME_REGEX.test(name)) {\n    throw new InvalidAddressError(rawName);\n  }\n\n  const gql = getSuiGraphQLClient();\n  let res: GqlResult<{ address?: { address?: string } | null }>;\n  try {\n    res = (await gql.query({\n      query: RESOLVE_NAME_QUERY,\n      variables: { name },\n      signal: ctx.signal,\n    })) as typeof res;\n  } catch (err) {\n    const msg = err instanceof Error ? err.message : String(err);\n    throw new SuinsRpcError(name, msg);\n  }\n\n  if (res.errors?.length) {\n    throw new SuinsRpcError(name, res.errors.map((e) => e.message ?? 'unknown error').join('; '));\n  }\n\n  // `address(name:)` returns the Address the name points to, or null when the\n  // name has never been registered (or has expired and the record was reaped).\n  return res.data?.address?.address ?? null;\n}\n\n/**\n * Reverse-resolve a 0x address to its SuiNS name via the Sui GraphQL\n * `address(address:){ defaultNameRecord { domain } }` query. Returns a\n * single-element array with the address's **default (primary)** name, or\n * `[]` when it has none. Throws `SuinsRpcError` on transport failure.\n *\n * Behavior note: the legacy JSON-RPC path returned *all* names for the\n * address; GraphQL exposes the explicitly-configured default record, which is\n * the one every consumer here actually uses (the LLM `resolve_suins` tool +\n * card titles only ever render the primary). Returning `[primary]` keeps the\n * `string[]` contract intact.\n *\n * Why this is its own helper (not folded into `normalizeAddressInput`): a\n * reverse lookup adds a second round-trip per tool call. We don't want every\n * read tool that takes an `address` to silently double its latency. The lookup\n * primitive is opt-in via the `resolve_suins` tool; normalizers stay\n * forward-only.\n */\nexport async function resolveAddressToSuinsViaRpc(\n  rawAddress: string,\n  ctx: { suiRpcUrl?: string; signal?: AbortSignal } = {},\n): Promise<string[]> {\n  const address = rawAddress.trim().toLowerCase();\n  if (!SUI_ADDRESS_REGEX.test(address)) {\n    throw new InvalidAddressError(rawAddress);\n  }\n\n  const gql = getSuiGraphQLClient();\n  let res: GqlResult<{ address?: { defaultNameRecord?: { domain?: string } | null } | null }>;\n  try {\n    res = (await gql.query({\n      query: REVERSE_NAME_QUERY,\n      variables: { address },\n      signal: ctx.signal,\n    })) as typeof res;\n  } catch (err) {\n    const msg = err instanceof Error ? err.message : String(err);\n    throw new SuinsRpcError(address, msg);\n  }\n\n  if (res.errors?.length) {\n    throw new SuinsRpcError(address, res.errors.map((e) => e.message ?? 'unknown error').join('; '));\n  }\n\n  const domain = res.data?.address?.defaultNameRecord?.domain;\n  return domain ? [domain] : [];\n}\n\nexport interface NormalizedAddress {\n  /**\n   * Canonical 0x-prefixed lowercase hex address. Always set on success.\n   * Tools should use this for any downstream query (BlockVision, NAVI,\n   * positionFetcher, etc.) and for cache keys.\n   */\n  address: string;\n  /**\n   * The user-facing name when the input was resolved via SuiNS, otherwise\n   * `null`. Tools should stamp this on result data so card titles can\n   * render \"Balance · obehi.sui\" instead of \"Balance · 0x1234…abcd\".\n   */\n  suinsName: string | null;\n  /**\n   * The original input (pre-normalization). Useful for error narration —\n   * \"I tried to resolve `Obehi.Sui` and …\" reads better than the\n   * post-trim/lowercase form.\n   */\n  raw: string;\n}\n\n/**\n * Canonical normalizer. Accepts a 0x address OR a SuiNS name; returns\n * a structured `NormalizedAddress`. Throws:\n *   - `InvalidAddressError` if the input matches neither shape.\n *   - `SuinsNotRegisteredError` if the SuiNS name is well-formed but\n *     resolves to null (= not registered).\n *   - `SuinsRpcError` if the RPC fails.\n *\n * Every read tool (engine) and write helper (SDK `T2000.send()`) that\n * accepts a user-supplied recipient MUST call this helper before any\n * downstream lookup. Doing the check inline (1) duplicates the regex,\n * (2) silently rejects SuiNS names, (3) makes cache keys inconsistent\n * across tools.\n */\nexport async function normalizeAddressInput(\n  value: string,\n  ctx: { suiRpcUrl?: string; signal?: AbortSignal } = {},\n): Promise<NormalizedAddress> {\n  const trimmed = value.trim();\n  if (SUI_ADDRESS_REGEX.test(trimmed)) {\n    return { address: trimmed.toLowerCase(), suinsName: null, raw: value };\n  }\n  if (looksLikeSuiNs(trimmed)) {\n    const name = trimmed.toLowerCase();\n    const address = await resolveSuinsViaRpc(name, ctx);\n    if (!address) {\n      throw new SuinsNotRegisteredError(name);\n    }\n    return { address: address.toLowerCase(), suinsName: name, raw: value };\n  }\n  throw new InvalidAddressError(value);\n}\n","// Unified spending-limit config store (`~/.t2000/config.json`). Moved here from\n// the CLI (`lib/config-store.ts`) + the SDK `SafeguardEnforcer` so ONE gate\n// serves CLI + MCP + programmatic writes (closes the H5 gap — R-0 Finding 1).\n//\n// Node-only (uses `node:fs`) — NOT re-exported from `browser.ts`. The browser\n// (Audric) write path skips client-side limits entirely; the server budget\n// ledger is the cap there.\n//\n// Schema (`~/.t2000/config.json`):\n//   { \"limits\": { \"perTxUsd\": 25, \"dailyUsd\": 100 },\n//     \"dailySpend\": { \"date\": \"2026-06-15\", \"usd\": 12.5 } }\n//\n// `daily` is CUMULATIVE across all outbound writes (send + swap + pay) since\n// midnight UTC — matches the engine's `autonomousDailyLimit` + the user mental\n// model (\"$100/day total\", not \"$100 per send\"). Locked S.424.\n\nimport { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { homedir } from 'node:os';\n\nexport interface LimitsConfig {\n  /** Caps any single outbound write (send | swap | pay) by USD value. */\n  perTxUsd?: number;\n  /** Caps CUMULATIVE outbound spend (all writes) per UTC day, by USD value. */\n  dailyUsd?: number;\n}\n\nexport interface DailySpend {\n  /** UTC date `YYYY-MM-DD` the running total applies to. */\n  date: string;\n  /** USD spent so far on `date`. */\n  usd: number;\n}\n\nexport interface LimitsFile {\n  limits?: LimitsConfig;\n  dailySpend?: DailySpend;\n}\n\nconst DEFAULT_CONFIG_DIR = join(homedir(), '.t2000');\n\nexport function resolveConfigPath(configDir?: string): string {\n  return join(configDir ?? DEFAULT_CONFIG_DIR, 'config.json');\n}\n\n/** UTC date `YYYY-MM-DD`. */\nexport function todayUtc(): string {\n  return new Date().toISOString().slice(0, 10);\n}\n\nexport function readLimitsFile(configDir?: string): LimitsFile {\n  const path = resolveConfigPath(configDir);\n  try {\n    return sanitize(JSON.parse(readFileSync(path, 'utf-8')));\n  } catch {\n    return {};\n  }\n}\n\n/**\n * Write the limits + dailySpend keys, PRESERVING any other keys already on\n * disk (a config file may carry unrelated data). Mode 0600.\n */\nexport function writeLimitsFile(file: LimitsFile, configDir?: string): string {\n  const path = resolveConfigPath(configDir);\n  let existing: Record<string, unknown> = {};\n  try {\n    existing = JSON.parse(readFileSync(path, 'utf-8'));\n  } catch {\n    existing = {};\n  }\n  // Drop the dead v3 SafeguardEnforcer keys if present (maxPerTx/maxDailySend/\n  // dailyUsed/dailyResetDate/locked) — they were never read by v4 and are\n  // replaced by `limits` + `dailySpend`.\n  for (const dead of ['maxPerTx', 'maxDailySend', 'dailyUsed', 'dailyResetDate', 'locked']) {\n    delete existing[dead];\n  }\n  const merged: Record<string, unknown> = { ...existing };\n  if (file.limits && (file.limits.perTxUsd !== undefined || file.limits.dailyUsd !== undefined)) {\n    merged.limits = file.limits;\n  } else {\n    delete merged.limits;\n  }\n  if (file.dailySpend) merged.dailySpend = file.dailySpend;\n  else delete merged.dailySpend;\n\n  const dir = dirname(path);\n  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n  writeFileSync(path, JSON.stringify(merged, null, 2) + '\\n', { mode: 0o600 });\n  return path;\n}\n\nexport function getLimits(configDir?: string): LimitsConfig | undefined {\n  return readLimitsFile(configDir).limits;\n}\n\nexport function hasLimits(configDir?: string): boolean {\n  const l = readLimitsFile(configDir).limits;\n  return !!l && (l.perTxUsd !== undefined || l.dailyUsd !== undefined);\n}\n\n/** Merge-set limits (only provided fields change). Returns the written path. */\nexport function setLimits(limits: LimitsConfig, configDir?: string): string {\n  const file = readLimitsFile(configDir);\n  const merged: LimitsConfig = { ...file.limits };\n  if (limits.perTxUsd !== undefined) merged.perTxUsd = limits.perTxUsd;\n  if (limits.dailyUsd !== undefined) merged.dailyUsd = limits.dailyUsd;\n  return writeLimitsFile({ ...file, limits: merged }, configDir);\n}\n\n/** Remove all limits (keeps the dailySpend ledger). Returns the written path. */\nexport function clearLimits(configDir?: string): string {\n  const file = readLimitsFile(configDir);\n  return writeLimitsFile({ ...file, limits: undefined }, configDir);\n}\n\n/** Cumulative USD spent so far today (0 when the ledger is from a prior day). */\nexport function dailySpentToday(configDir?: string): number {\n  const { dailySpend } = readLimitsFile(configDir);\n  if (!dailySpend || dailySpend.date !== todayUtc()) return 0;\n  return dailySpend.usd;\n}\n\n/** Add `usd` to today's running total (resets on UTC date rollover). */\nexport function recordDailySpend(usd: number, configDir?: string): void {\n  if (!Number.isFinite(usd) || usd <= 0) return;\n  const file = readLimitsFile(configDir);\n  const today = todayUtc();\n  const prior = file.dailySpend && file.dailySpend.date === today ? file.dailySpend.usd : 0;\n  writeLimitsFile({ ...file, dailySpend: { date: today, usd: prior + usd } }, configDir);\n}\n\nfunction sanitize(raw: unknown): LimitsFile {\n  if (typeof raw !== 'object' || raw === null) return {};\n  const r = raw as Record<string, unknown>;\n  const out: LimitsFile = {};\n\n  if (typeof r.limits === 'object' && r.limits !== null) {\n    const l = r.limits as Record<string, unknown>;\n    const limits: LimitsConfig = {};\n    if (typeof l.perTxUsd === 'number' && l.perTxUsd > 0) limits.perTxUsd = l.perTxUsd;\n    // Migrate the legacy `dailySendUsd` (v4 CLI, per-send sub-cap) → `dailyUsd`\n    // (cumulative all-writes). New canonical key wins if both are present.\n    if (typeof l.dailyUsd === 'number' && l.dailyUsd > 0) limits.dailyUsd = l.dailyUsd;\n    else if (typeof l.dailySendUsd === 'number' && l.dailySendUsd > 0) limits.dailyUsd = l.dailySendUsd;\n    if (limits.perTxUsd !== undefined || limits.dailyUsd !== undefined) out.limits = limits;\n  }\n\n  if (typeof r.dailySpend === 'object' && r.dailySpend !== null) {\n    const d = r.dailySpend as Record<string, unknown>;\n    if (typeof d.date === 'string' && typeof d.usd === 'number' && d.usd >= 0) {\n      out.dailySpend = { date: d.date, usd: d.usd };\n    }\n  }\n\n  return out;\n}\n","// Spending-limit error — thrown by the unified limits gate (`@t2000/sdk/limits`)\n// when an outbound write exceeds an opted-in cap. Shared by CLI + MCP +\n// programmatic callers (the gate lives in the SDK write paths). Carries a\n// structured shape so the CLI can render `--json` output and the MCP can\n// surface a typed failure.\n\nexport type LimitKind = 'perTxUsd' | 'dailyUsd';\nexport type LimitOperation = 'send' | 'swap' | 'pay';\n\nexport class LimitExceededError extends Error {\n  readonly code = 'LIMIT_EXCEEDED';\n  readonly operation: LimitOperation;\n  readonly limitKind: LimitKind;\n  readonly limit: number;\n  readonly attempted: number;\n\n  constructor(params: {\n    operation: LimitOperation;\n    limitKind: LimitKind;\n    limit: number;\n    attempted: number;\n  }) {\n    const label = params.limitKind === 'perTxUsd' ? 'per-transaction limit' : 'daily spend limit';\n    super(\n      `Exceeds ${label} ($${params.limit}). Attempted $${params.attempted.toFixed(2)}. Use --force / force:true to override.`,\n    );\n    this.name = 'LimitExceededError';\n    this.operation = params.operation;\n    this.limitKind = params.limitKind;\n    this.limit = params.limit;\n    this.attempted = params.attempted;\n  }\n\n  toJSON(): unknown {\n    return {\n      error: this.code,\n      message: this.message,\n      operation: this.operation,\n      limitKind: this.limitKind,\n      limit: this.limit,\n      attempted: this.attempted,\n    };\n  }\n}\n","// The unified spending-limit gate. ONE enforcer for CLI + MCP + programmatic\n// writes — wired into the T2000 write paths (send / swap / pay), so every\n// surface that calls those methods inherits the same cap (closes H5).\n//\n// USD-denominated. `perTxUsd` caps any single write; `dailyUsd` caps the\n// CUMULATIVE spend across all writes since UTC midnight (the running total\n// lives in the `dailySpend` ledger). `force` bypasses both — the caller owns\n// the prompt/consent.\n\nimport {\n  type LimitsConfig,\n  getLimits,\n  setLimits,\n  clearLimits,\n  hasLimits,\n  dailySpentToday,\n  recordDailySpend,\n} from './config.js';\nimport { LimitExceededError, type LimitOperation } from './errors.js';\n\n/**\n * Best-effort USD value for an asset+amount pair, for the limit gate. Stables\n * are 1:1; SUI (and anything else) returns `null` — \"unknown, don't gate\".\n * The limits are USD-denominated; SUI-USD gating would need a price lookup and\n * is intentionally out of scope (matches the prior CLI behavior).\n */\nexport function approxUsdValue(asset: string, amount: number): number | null {\n  const symbol = asset.toUpperCase();\n  if (symbol === 'USDC' || symbol === 'USDSUI') return amount;\n  return null;\n}\n\n/**\n * Pure gate — no I/O. Returns silently when allowed; throws\n * `LimitExceededError` when blocked.\n */\nexport function assertLimitConfig(input: {\n  limits: LimitsConfig | undefined;\n  spentTodayUsd: number;\n  operation: LimitOperation;\n  amountUsd: number;\n  force?: boolean;\n}): void {\n  if (input.force) return;\n  if (!Number.isFinite(input.amountUsd) || input.amountUsd <= 0) return;\n  const { limits } = input;\n  if (!limits) return;\n\n  if (limits.perTxUsd !== undefined && input.amountUsd > limits.perTxUsd) {\n    throw new LimitExceededError({\n      operation: input.operation,\n      limitKind: 'perTxUsd',\n      limit: limits.perTxUsd,\n      attempted: input.amountUsd,\n    });\n  }\n\n  if (limits.dailyUsd !== undefined && input.spentTodayUsd + input.amountUsd > limits.dailyUsd) {\n    throw new LimitExceededError({\n      operation: input.operation,\n      limitKind: 'dailyUsd',\n      // The cap is total/day; report the cap (attempted is THIS write's USD).\n      limit: limits.dailyUsd,\n      attempted: input.spentTodayUsd + input.amountUsd,\n    });\n  }\n}\n\nexport interface LimitAssertInput {\n  operation: LimitOperation;\n  /** This write's USD value. Pass 0 / non-positive to skip (e.g. SUI sends). */\n  amountUsd: number;\n  /** When true, skip the gate. */\n  force?: boolean;\n}\n\n/**\n * The spending-limit enforcer — reads/writes `~/.t2000/config.json` (or a\n * `configDir` override for tests). Constructed once by the T2000 agent and\n * called around every outbound write; also drives the CLI `t2 limit` commands.\n */\nexport class LimitEnforcer {\n  constructor(private readonly configDir?: string) {}\n\n  /** Throws `LimitExceededError` when the write exceeds an opted-in cap. */\n  assert(input: LimitAssertInput): void {\n    assertLimitConfig({\n      limits: getLimits(this.configDir),\n      spentTodayUsd: dailySpentToday(this.configDir),\n      operation: input.operation,\n      amountUsd: input.amountUsd,\n      force: input.force,\n    });\n  }\n\n  /** Add a settled write's USD value to today's cumulative total. */\n  record(amountUsd: number): void {\n    recordDailySpend(amountUsd, this.configDir);\n  }\n\n  getLimits(): LimitsConfig | undefined {\n    return getLimits(this.configDir);\n  }\n\n  hasLimits(): boolean {\n    return hasLimits(this.configDir);\n  }\n\n  setLimits(limits: LimitsConfig): void {\n    setLimits(limits, this.configDir);\n  }\n\n  clearLimits(): void {\n    clearLimits(this.configDir);\n  }\n\n  dailySpentToday(): number {\n    return dailySpentToday(this.configDir);\n  }\n}\n","export { T2000 } from './t2000.js';\nexport type { TransactionSigner } from './signer.js';\nexport { KeypairSigner } from './wallet/keypairSigner.js';\nexport { ZkLoginSigner, type ZkLoginProof } from './wallet/zkLoginSigner.js';\nexport { payWithMpp, preflightPay } from './wallet/pay.js';\nexport { executeTx } from './wallet/executeTx.js';\nexport { T2000Error, mapWalletError, mapMoveAbortCode } from './errors.js';\nexport type { T2000ErrorCode, T2000ErrorData } from './errors.js';\nexport type {\n  T2000Options,\n  BalanceResponse,\n  SuiHolding,\n  SendResult,\n  DepositInfo,\n  PaymentRequest,\n  TransactionRecord,\n  TransactionLeg,\n  PayOptions,\n  PayResult,\n  SwapResult,\n  SwapQuoteResult,\n} from './types.js';\nexport {\n  MIST_PER_SUI,\n  SUI_DECIMALS,\n  USDC_DECIMALS,\n  T2000_OVERLAY_FEE_WALLET,\n  SUPPORTED_ASSETS,\n  CLOCK_ID,\n  DEFAULT_NETWORK,\n} from './constants.js';\nexport type { SupportedAsset, StableAsset, SendableAsset } from './constants.js';\nexport {\n  STABLE_ASSETS,\n  SENDABLE_ASSETS,\n  GASLESS_MIN_STABLE_AMOUNT,\n  GASLESS_STABLE_TYPES,\n  DEFAULT_GRPC_URL,\n  GAS_RESERVE_MIN,\n  CETUS_USDC_SUI_POOL,\n  OPERATION_ASSETS,\n  isAllowedAsset,\n  assertAllowedAsset,\n} from './constants.js';\nexport type { Operation } from './constants.js';\nexport {\n  validateAddress,\n  truncateAddress,\n  normalizeCoinType,\n  getSuiClient,\n  getSuiGrpcClient,\n} from './utils/sui.js';\nexport {\n  SUI_ADDRESS_REGEX,\n  SUI_ADDRESS_STRICT_REGEX,\n  SUINS_NAME_REGEX,\n  InvalidAddressError,\n  SuinsNotRegisteredError,\n  SuinsRpcError,\n  looksLikeSuiNs,\n  resolveSuinsViaRpc,\n  resolveAddressToSuinsViaRpc,\n  normalizeAddressInput,\n} from './utils/suins.js';\nexport type { NormalizedAddress } from './utils/suins.js';\nexport {\n  KNOWN_TARGETS,\n  LABEL_PATTERNS,\n  classifyAction,\n  classifyLabel,\n  fallbackLabel,\n  refineLendingLabel,\n  classifyTransaction,\n  extractTransferDetails,\n  extractAllUserLegs,\n} from './wallet/classify.js';\nexport type {\n  ClassifyBalanceChange,\n  ClassifyResult,\n  ExtractedTransfer,\n  TxDirection,\n} from './wallet/classify.js';\nexport {\n  parseSuiRpcTx,\n  extractTxSender,\n  extractTxCommands,\n  queryHistory,\n  queryTransaction,\n} from './wallet/history.js';\nexport type { SuiRpcTxBlock } from './wallet/history.js';\nexport { queryBalance } from './wallet/balance.js';\nexport {\n  mistToSui,\n  suiToMist,\n  usdcToRaw,\n  rawToUsdc,\n  stableToRaw,\n  rawToStable,\n  getDecimals,\n  formatUsd,\n  formatSui,\n  formatAssetAmount,\n  normalizeAsset,\n} from './utils/format.js';\nexport {\n  generateKeypair,\n  keypairFromPrivateKey,\n  saveKey,\n  saveBech32,\n  loadKey,\n  walletExists,\n  exportPrivateKey,\n  getAddress,\n} from './wallet/keyManager.js';\nexport { buildSendTx, addSendToTx, preflightSend } from './wallet/send.js';\nexport {\n  fetchAllCoins,\n  selectAndSplitCoin,\n  selectSuiCoin,\n} from './wallet/coinSelection.js';\nexport type { CoinPage, SelectAndSplitResult } from './wallet/coinSelection.js';\nexport {\n  composeTx,\n  deriveAllowedAddressesFromPtb,\n  WRITE_APPENDER_REGISTRY,\n  SPONSORED_PYTH_DEPENDENT_PROVIDERS,\n  getSponsoredSwapProviders,\n} from './composeTx.js';\nexport type {\n  WriteToolName,\n  WriteStep,\n  ComposeTxOptions,\n  ComposeTxResult,\n  AppenderContext,\n  StepPreview,\n  SendTransferInput,\n  SwapExecuteInput,\n} from './composeTx.js';\nexport { simulateTransaction, throwIfSimulationFailed } from './utils/simulate.js';\nexport type { SimulationResult } from './utils/simulate.js';\nexport { getSwapQuote } from './swap-quote.js';\nexport {\n  findSwapRoute,\n  buildSwapTx,\n  addSwapToTx,\n  preflightSwap,\n  OVERLAY_FEE_RATE,\n  serializeCetusRoute,\n  deserializeCetusRoute,\n  verifyCetusRouteCoinMatch,\n  isCetusRouteFresh,\n} from './protocols/cetus-swap.js';\nexport type {\n  SwapRouteResult,\n  OverlayFeeConfig,\n  SerializedCetusRoute,\n  SerializedRouterDataV3,\n  SerializedCetusRoutePath,\n} from './protocols/cetus-swap.js';\nexport {\n  COIN_REGISTRY,\n  TOKEN_MAP,\n  resolveTokenType,\n  resolveSymbol,\n  getDecimalsForCoinType,\n  getCoinMeta,\n  isInRegistry,\n  SUI_TYPE,\n  USDC_TYPE,\n  USDT_TYPE,\n  USDSUI_TYPE,\n  USDE_TYPE,\n  ETH_TYPE,\n  WBTC_TYPE,\n  WAL_TYPE,\n  NAVX_TYPE,\n  IKA_TYPE,\n  LOFI_TYPE,\n  MANIFEST_TYPE,\n} from './token-registry.js';\nexport type { CoinMeta } from './token-registry.js';\n// [S.323 / 2026-05-25] VOLO vSUI staking re-exports removed (full cut).\n// vSUI still exists in the codebase as a passive token (NAVI reward type\n// + Cetus swap target), but t2000 no longer exposes mint/redeem surfaces.\nexport {\n  AUDRIC_PARENT_NAME,\n  AUDRIC_PARENT_NFT_ID,\n  buildAddLeafTx,\n  buildRevokeLeafTx,\n  displayHandle,\n  fullHandle,\n  validateLabel,\n} from './protocols/suins-leaf.js';\nexport type {\n  BuildAddLeafParams,\n  BuildRevokeLeafParams,\n  LabelValidationResult,\n} from './protocols/suins-leaf.js';\n// Unified spending limits (per-tx + cumulative daily, USD) — one gate for\n// CLI + MCP + programmatic writes (R-0 Finding 1; closes H5). Node-only.\nexport {\n  LimitEnforcer,\n  LimitExceededError,\n  approxUsdValue,\n  assertLimitConfig,\n  getLimits,\n  hasLimits,\n  setLimits,\n  clearLimits,\n  dailySpentToday,\n  recordDailySpend,\n  readLimitsFile,\n  writeLimitsFile,\n} from './limits/index.js';\nexport type { LimitsConfig, DailySpend, LimitsFile, LimitKind, LimitOperation, LimitAssertInput } from './limits/index.js';\n// Synchronous, network-free preflight (layer 2) — pure input validation the\n// v3 host runs before the LLM round-trip / tap-to-confirm. Per-builder\n// validators (`preflightSend`/`preflightPay`/`preflightSwap`) are exported\n// alongside their builders above; these are the shared primitives.\nexport {\n  type PreflightResult,\n  PREFLIGHT_MAX_AMOUNT,\n  PREFLIGHT_OK,\n  preflightFail,\n  checkPositiveAmount,\n  checkSuiAddress,\n} from './preflight.js';\n","/**\n * SPEC 7 v0.4 § Layer 0 — Canonical Write Architecture.\n *\n * `composeTx({ steps })` is the single canonical entry-point for every\n * Audric Enoki-sponsored write. The fragment-appender pattern (Layer 1)\n * is the implementation; this primitive dispatches each step to its\n * registered appender from the typed `WRITE_APPENDER_REGISTRY`.\n *\n * Single-write and multi-write go through the same code path. A 1-step\n * `composeTx([{ toolName: 'send_transfer', input: {...} }])` produces\n * the same shape of result as a 3-step bundle.\n *\n * **Why this exists**\n *\n * Pre-Layer-0, four parallel write stacks lived across the audric host:\n * `transactions/prepare` (fat ~600-line route), `services/prepare`\n * (hand-rolled), `debug-swap` (diagnostic), and PayButton (dapp-kit).\n * Each one re-implemented merge/split/transfer + hand-maintained the\n * `allowedAddresses` array Enoki requires. Two production bugs in the\n * past 60 days came from drift between them — PR-H1 (claim-rewards\n * self-transfer missing from allowedAddresses) and PR-H4 (borrow/\n * withdraw self-transfer same bug).\n *\n * Layer 0 collapses 3 of those stacks into one canonical primitive.\n * PayButton stays out by design (different signer, different trust\n * model — see `audric-canonical-write.mdc` for the rationale and the\n * `// CANONICAL-BYPASS:` escape-hatch contract).\n *\n * **What composeTx owns**\n *\n * - PTB assembly via per-tool wallet-mode appenders (the\n *   `WRITE_APPENDER_REGISTRY`).\n * - Pre-built `txKindBytes` (`tx.build({ onlyTransactionKind: true })`)\n *   ready for Enoki's `createSponsoredTransaction`.\n * - Auto-derived `derivedAllowedAddresses` from the assembled PTB's\n *   top-level `transferObjects` calls — eliminates the PR-H1/H4 bug\n *   class permanently. Hand-maintained arrays are now unreachable.\n * - S.38 Pyth flag plumbing — `sponsoredContext: true` automatically\n *   applies `skipPythUpdate` (borrow/withdraw) and `skipOracle` (repay)\n *   to NAVI appenders so Enoki doesn't reject `tx.gas`-as-argument.\n *\n * **What composeTx does NOT own**\n *\n * - **Fees** — Audric concern, not @t2000/sdk concern (CLAUDE.md\n *   rule #9). The SDK is fee-free by design as of @t2000/sdk@1.1.0\n *   (B5 v2). Audric host wraps composeTx with fee insertion in P2.2c.\n * - **Sponsorship** — caller's job. composeTx returns `txKindBytes`\n *   pre-built for Enoki; the caller calls `createSponsoredTransaction`\n *   with their JWT.\n * - **Chain-mode coin handoff between steps** — Layer 2 (engine\n *   bundling) ships this. P2.2b is wallet-mode-only: each step fetches\n *   coins independently. Layer 2 will extend by introducing\n *   `inputCoinFromStep: number` to thread upstream output coins.\n *\n * **Cross-references**\n *\n * - Spec → `spec/SPEC_7_MULTI_WRITE_PTB.md` § \"Layer 0: Canonical\n *   Write Architecture\"\n * - Read-side companion → `t2000/.cursor/rules/single-source-of-truth.mdc`\n *   + `audric/.cursor/rules/audric-canonical-portfolio.mdc`\n * - Write-side rule → `audric/.cursor/rules/audric-canonical-write.mdc`\n */\n\nimport type { SuiCoreClient } from './utils/sui.js';\nimport {\n  Transaction,\n  type TransactionObjectArgument,\n} from '@mysten/sui/transactions';\nimport type { OverlayFeeConfig } from './protocols/cetus-swap.js';\nimport { addSwapToTx, type SwapRouteResult } from './protocols/cetus-swap.js';\nimport { addSendToTx } from './wallet/send.js';\nimport {\n  selectSuiCoin,\n  type SponsoredCoinMergeCache,\n} from './wallet/coinSelection.js';\nimport { resolveTokenType, getDecimalsForCoinType, SUI_TYPE } from './token-registry.js';\nimport {\n  GASLESS_MIN_STABLE_AMOUNT,\n  GASLESS_STABLE_TYPES,\n  SUPPORTED_ASSETS,\n  assertAllowedAsset,\n  type SendableAsset,\n  type SupportedAsset,\n} from './constants.js';\nimport { T2000Error } from './errors.js';\nimport { validateAddress } from './utils/sui.js';\n\n/**\n * Canonical write tools. The 8 tools that can be composed into a PTB.\n *\n * History:\n * - 2026-05-08 (Track B): added `harvest_rewards` (compound macro).\n * - 2026-05-25 (S.323): removed `volo_stake` / `volo_unstake` — full Volo\n *   cut across SDK/CLI/MCP after the engine cut Volo in S.277. vSUI\n *   remains as a passive token (NAVI reward, Cetus swap target).\n *\n * Excluded by design:\n * - `save_contact` — no on-chain leg (Prisma-only).\n */\n// [S.444 — NAVI/DeFi removed] Canonical write tools narrowed to the two\n// surviving on-chain verbs: gasless send + Cetus swap. save/withdraw/borrow/\n// repay/claim/harvest were deleted with NAVI (v2 keeps them on @t2000/sdk@4.x).\nexport type WriteToolName =\n  | 'send_transfer'\n  | 'swap_execute';\n\n// Per-tool input contracts. Match the engine tool input schemas, not the\n// audric host's loosely-typed `params` blob — the registry is the typed\n// surface that lets the host shed the `any`-typed switch statement.\n\n/**\n * [v4.0 Phase A Day 2 — SPEC_AGENT_WALLET_GREENFIELD §A]\n * `asset` is now REQUIRED (no more silent USDC default). The parameter\n * type is the wider `SupportedAsset` rather than the narrower\n * `SendableAsset` so callers that thread a wide-typed asset through\n * (primarily the engine LLM tool surface) compile without modification.\n * Runtime narrowing happens via `assertAllowedAsset('send', asset)`,\n * which throws `INVALID_ASSET` for anything outside the\n * `['USDC', 'USDsui', 'SUI']` whitelist. USDC + USDsui route through\n * the gasless `0x2::balance::send_funds` Move call; SUI uses the\n * standard `transferObjects` path.\n *\n * Audric hosts: the audric chat client (`audric-chat-client.tsx`)\n * already defaults asset to `'USDC'` at the marker layer before\n * calling `sponsoredTx({ type: 'send' })`, so this signature change\n * doesn't break the LLM flow. LLM intents like \"send 5 WAL\" now\n * surface a clear error instead of silently building a non-gasless\n * tx.\n */\nexport interface SendTransferInput {\n  to: string;\n  amount: number;\n  asset: SupportedAsset;\n}\n\nexport interface SwapExecuteInput {\n  from: string;\n  to: string;\n  amount: number;\n  slippage?: number;\n  byAmountIn?: boolean;\n  /** Cetus provider allow-list. Sponsored callers MUST pass an exclusion list\n   *  to remove Pyth-dependent providers — see addSwapToTx JSDoc. composeTx\n   *  derives this automatically from `sponsoredContext` if omitted. */\n  providers?: string[];\n  /**\n   * [SPEC 20.2 / D-1 (a)] Optional precomputed Cetus route discovered at\n   * `swap_quote` time. Bypasses `findSwapRoute()` (-400-500ms) inside\n   * `addSwapToTx`. Caller (audric prepare-route) is responsible for\n   * coin-type verification (D-2) + freshness check (D-3) before passing.\n   * `addSwapToTx` performs an additional sanity check on `amountIn` +\n   * `byAmountIn` and falls back to fresh discovery on mismatch.\n   */\n  precomputedRoute?: SwapRouteResult;\n}\n\n/**\n * Discriminated union mapping `toolName` → `input`. Used to type\n * `WriteStep` so consumers get autocomplete + compile-time validation\n * that the input matches the tool.\n *\n * **[SPEC 13 Phase 1] `inputCoinFromStep`** — consumer steps may\n * reference an earlier step's output coin handle by index. When set,\n * `composeTx`'s orchestration loop threads the producer's\n * `outputCoin` into this step's appender as the `inputCoin` arg,\n * bypassing the wallet pre-fetch path. The producer's terminal\n * `tx.transferObjects([coin], sender)` is suppressed automatically so\n * the same handle isn't double-consumed.\n */\nexport type WriteStep =\n  | { toolName: 'send_transfer'; input: SendTransferInput; inputCoinFromStep?: number }\n  | { toolName: 'swap_execute'; input: SwapExecuteInput; inputCoinFromStep?: number };\n\nexport interface ComposeTxOptions {\n  sender: string;\n  steps: WriteStep[];\n  client: SuiCoreClient;\n  /**\n   * S.38 Pyth flag (sponsorship-critical). When true:\n   * - NAVI borrow/withdraw appenders apply `skipPythUpdate: true`\n   *   (preserves on-chain price-feed updates, skips the tx.gas-using\n   *   Pyth fee payment that Enoki rejects).\n   * - NAVI repay appender applies `skipOracle: true` (debt reduction\n   *   has no health-factor risk, full oracle bypass is safe).\n   * - Cetus swap appender applies `getProvidersExcluding([HAEDALPMM,\n   *   METASTABLE, OBRIC, STEAMM_OMM, STEAMM_OMM_V2, SEVENK,\n   *   HAEDALHMMV2])` — Pyth-dependent providers reference `tx.gas` for\n   *   oracle fees, also rejected by Enoki.\n   * - SUI sends fetch coins via `getCoins` (tx.gas belongs to sponsor,\n   *   not user) instead of splitting from `tx.gas`.\n   *\n   * Self-funded callers (CLI, MCP, server tasks) leave this `false` /\n   * omit — they pay all oracle/Pyth fees from their own SUI gas.\n   */\n  sponsoredContext?: boolean;\n  /**\n   * Per-call overlay fee config for Cetus swaps. Audric host passes\n   * `{ rate: 0.001, receiver: T2000_OVERLAY_FEE_WALLET }` to charge the\n   * 0.1% swap overlay. CLI / direct SDK callers omit. Forwarded to\n   * `addSwapToTx`'s `input.overlayFee`.\n   */\n  overlayFee?: OverlayFeeConfig;\n}\n\n/** Per-step preview returned by each registry appender. Tool-specific shape. */\nexport type StepPreview =\n  | { toolName: 'send_transfer'; effectiveAmount: number; recipient: string; asset: SendableAsset }\n  | { toolName: 'swap_execute'; effectiveAmountIn: number; expectedAmountOut: number; route: SwapRouteResult };\n\nexport interface ComposeTxResult {\n  tx: Transaction;\n  /**\n   * Pre-built bytes for Enoki's `createSponsoredTransaction`. Built\n   * with `onlyTransactionKind: true` so the gas coin can be supplied\n   * by the sponsor.\n   */\n  txKindBytes: Uint8Array;\n  /**\n   * Auto-derived from the assembled PTB's top-level `transferObjects`\n   * commands. Replaces hand-maintained `allowedAddresses` arrays in\n   * audric host's `transactions/prepare` + `services/prepare` —\n   * eliminates the PR-H1/H4 bug class permanently.\n   */\n  derivedAllowedAddresses: string[];\n  perStepPreviews: StepPreview[];\n}\n\n/**\n * Per-appender context passed into every registry entry. Carries the\n * RPC client, sender, sponsorship flag, optional per-call overlay\n * fee config (Cetus swaps), and SPEC 13 Phase 1 chain-mode fields.\n */\nexport interface AppenderContext {\n  client: SuiCoreClient;\n  sender: string;\n  sponsoredContext: boolean;\n  overlayFee?: OverlayFeeConfig;\n  /**\n   * [SPEC 13 Phase 1] When set, the consumer appender consumes this\n   * coin handle directly instead of pre-fetching from the wallet via\n   * `selectAndSplitCoin` / `selectSuiCoin`. Provided by the\n   * orchestration loop when the step has `inputCoinFromStep` set; the\n   * loop looks up `priorOutputs[step.inputCoinFromStep]` and threads\n   * it through here.\n   *\n   * In chain mode, the consumer consumes the handle IN FULL — the\n   * `input.amount` field is treated as informational (used for preview\n   * math). This matches Cetus's `routerSwap`, NAVI's `deposit`/`repay`,\n   * and the Sui `transferObjects` semantics: each takes a coin object\n   * and consumes its entire balance.\n   */\n  chainedCoin?: TransactionObjectArgument;\n  /**\n   * [SPEC 13 Phase 1] True when this step's output coin will be\n   * consumed by a downstream step (some later step has\n   * `inputCoinFromStep === currentStepIndex`). Producer appenders MUST\n   * skip their terminal `tx.transferObjects([coin], ctx.sender)` call\n   * when this is true — otherwise the same `TransactionObjectArgument`\n   * gets used twice (once by the consumer, once by the transfer) and\n   * the PTB build fails or the on-chain leg reverts.\n   */\n  isOutputConsumed?: boolean;\n  /**\n   * Per-PTB merge cache for sponsored coin-object sourcing, shared across\n   * every appender in a single `composeTx` run. Lets multiple legs that\n   * source the same coin type (two SUI swaps, swap USDC + save USDC, etc.)\n   * reuse a single merged primary coin instead of each re-fetching +\n   * re-merging the same coin objects (the second merge of which references\n   * already-consumed coins → Enoki dry-run `ArgumentWithoutValue`). Applies\n   * to ALL coin types, not just SUI. See `SponsoredCoinMergeCache` JSDoc.\n   */\n  coinMergeCache?: SponsoredCoinMergeCache;\n}\n\n/**\n * [SPEC 13 Phase 1] Appender return shape. Producers populate\n * `outputCoin` so the orchestration loop can thread it into a\n * downstream consumer's `chainedCoin`. The terminal consumer\n * (`send_transfer`) omits it.\n *\n * `swap_execute` is the only dual-mode tool — it accepts `chainedCoin`\n * AND populates `outputCoin`. (Pre-S.444 the DeFi tools\n * save/withdraw/borrow/repay were also producers/consumers; removed with NAVI.)\n */\nexport interface AppenderResult<TPreview extends StepPreview> {\n  preview: TPreview;\n  outputCoin?: TransactionObjectArgument;\n}\n\ntype AppenderFn<TInput, TPreview extends StepPreview> = (\n  tx: Transaction,\n  input: TInput,\n  ctx: AppenderContext,\n) => Promise<AppenderResult<TPreview>>;\n\n/**\n * Cetus provider exclusion list for sponsored flows. Mirrors the\n * audric host's `SPONSORED_TX_PROVIDERS` constant — these 7 providers\n * reference `tx.gas` for Pyth oracle fee payments, which Enoki rejects.\n *\n * NOTE: keeping this hardcoded means `findSwapRoute` doesn't need a\n * dependency on `@cetusprotocol/aggregator-sdk`'s `getProvidersExcluding`\n * helper — composeTx forwards the literal list to Cetus, Cetus does the\n * inverse lookup. Result is identical.\n */\nexport const SPONSORED_PYTH_DEPENDENT_PROVIDERS = [\n  'HAEDALPMM',\n  'METASTABLE',\n  'OBRIC',\n  'STEAMM_OMM',\n  'STEAMM_OMM_V2',\n  'SEVENK',\n  'HAEDALHMMV2',\n] as const;\n\n/**\n * Get all eligible Cetus provider names except the Pyth-dependent ones,\n * for sponsored swap context. Computed from the Cetus SDK's\n * `getAllProviders()` minus the exclusion list.\n *\n * [Bug A fix / 2026-05-10] Exported so the engine's `swap_quote` tool can\n * call this when discovering routes for sponsored hosts. Previously the\n * engine only exclude these providers at COMPOSE time; now it excludes\n * at QUOTE time too, so the precomputed route stashed on\n * `pending_action.cetusRoute` is always sponsor-safe.\n */\nexport async function getSponsoredSwapProviders(): Promise<string[]> {\n  const { getProvidersExcluding } = await import('@cetusprotocol/aggregator-sdk');\n  return getProvidersExcluding([...SPONSORED_PYTH_DEPENDENT_PROVIDERS]);\n}\n\n/**\n * The typed registry. Each entry is a wallet-mode dispatcher that takes\n * (tx, input, ctx) and returns a per-step preview. Compile-time check\n * that all `WriteToolName` values have an entry — TypeScript will\n * fail the build if a tool is missing.\n *\n * [S.444] Narrowed to send_transfer + swap_execute after the NAVI/DeFi cut.\n */\nexport const WRITE_APPENDER_REGISTRY: {\n  send_transfer: AppenderFn<SendTransferInput, Extract<StepPreview, { toolName: 'send_transfer' }>>;\n  swap_execute: AppenderFn<SwapExecuteInput, Extract<StepPreview, { toolName: 'swap_execute' }>>;\n} = {\n  send_transfer: async (tx, input, ctx) => {\n    const recipient = validateAddress(input.to);\n    // [v4.0 Phase A Day 2] Asset is required (no `?? 'USDC'` default).\n    // assertAllowedAsset narrows the runtime value to\n    // `'USDC' | 'USDsui' | 'SUI'` and throws INVALID_ASSET otherwise.\n    // The TypeScript shape is `SupportedAsset` (wider, accommodates\n    // engine LLM tool callers that pass wide-typed assets through);\n    // the runtime assertion is the canonical gate.\n    if (!input.asset) {\n      throw new T2000Error(\n        'INVALID_ASSET',\n        \"send_transfer requires an explicit asset. Use one of: USDC, USDsui, SUI.\",\n      );\n    }\n    assertAllowedAsset('send', input.asset);\n    const asset: SendableAsset = input.asset as SendableAsset;\n    const assetInfo = SUPPORTED_ASSETS[asset];\n    if (input.amount <= 0) {\n      throw new T2000Error('INVALID_AMOUNT', 'Send amount must be greater than zero');\n    }\n\n    const rawAmount = BigInt(Math.floor(input.amount * 10 ** assetInfo.decimals));\n\n    // [v4.0 Phase A Day 2] Chain-mode (`chainedCoin` from a previous\n    // appender) ALWAYS uses the legacy `transferObjects` path —\n    // bundles never qualify for gasless because the protocol allowlist\n    // only accepts PTBs whose ops are `balance::send_funds` /\n    // `balance::redeem_funds` / `coin::send_funds` etc. A withdraw →\n    // send bundle has the withdraw Move call, so the whole tx pays gas.\n    if (ctx.chainedCoin) {\n      addSendToTx(tx, ctx.chainedCoin, recipient);\n      return {\n        preview: {\n          toolName: 'send_transfer',\n          effectiveAmount: Number(rawAmount) / 10 ** assetInfo.decimals,\n          recipient,\n          asset,\n        },\n      };\n    }\n\n    if (asset === 'SUI') {\n      // Standard gas-native SUI transfer — NOT gasless (SUI is not on\n      // the protocol `balance::send_funds` allowlist).\n      const result = await selectSuiCoin(\n        tx,\n        ctx.client,\n        ctx.sender,\n        rawAmount,\n        ctx.sponsoredContext,\n        ctx.coinMergeCache,\n      );\n      addSendToTx(tx, result.coin, recipient);\n      return {\n        preview: {\n          toolName: 'send_transfer',\n          effectiveAmount: Number(result.effectiveAmount) / 10 ** assetInfo.decimals,\n          recipient,\n          asset,\n        },\n      };\n    }\n\n    // USDC / USDsui — gasless single-step send via `0x2::balance::send_funds`.\n    // Surfaces the protocol's 0.01 minimum BEFORE building so we don't\n    // burn a sponsorship slot on a tx that will revert on-chain.\n    if (input.amount < GASLESS_MIN_STABLE_AMOUNT) {\n      throw new T2000Error(\n        'INVALID_AMOUNT',\n        `Minimum gasless transfer is ${GASLESS_MIN_STABLE_AMOUNT} ${asset}. Got ${input.amount}.`,\n      );\n    }\n    // Pre-flight balance check (composeTx's selectAndSplitCoin used to\n    // do this; we lose the coin-selection but keep the balance gate so\n    // build-time errors stay actionable for audric's prepare route).\n    const balanceResp = await ctx.client.core.getBalance({ owner: ctx.sender, coinType: assetInfo.type });\n    if (BigInt(balanceResp.balance.balance) < rawAmount) {\n      throw new T2000Error('INSUFFICIENT_BALANCE', `Insufficient ${asset} balance`, {\n        available: Number(balanceResp.balance.balance) / 10 ** assetInfo.decimals,\n        required: input.amount,\n      });\n    }\n    const coinType = GASLESS_STABLE_TYPES[asset];\n    tx.moveCall({\n      target: '0x2::balance::send_funds',\n      typeArguments: [coinType],\n      arguments: [\n        tx.balance({ type: coinType, balance: rawAmount }),\n        tx.pure.address(recipient),\n      ],\n    });\n    return {\n      preview: {\n        toolName: 'send_transfer',\n        effectiveAmount: Number(rawAmount) / 10 ** assetInfo.decimals,\n        recipient,\n        asset,\n      },\n    };\n  },\n\n  swap_execute: async (tx, input, ctx) => {\n    const fromType = resolveTokenType(input.from);\n    const toType = resolveTokenType(input.to);\n    if (!fromType || !toType) {\n      throw new T2000Error(\n        'ASSET_NOT_SUPPORTED',\n        `Unknown token in swap: from=${input.from}, to=${input.to}`,\n      );\n    }\n\n    const providers = input.providers\n      ?? (ctx.sponsoredContext ? await getSponsoredSwapProviders() : undefined);\n\n    const result = await addSwapToTx(tx, ctx.client, ctx.sender, {\n      from: input.from,\n      to: input.to,\n      amount: input.amount,\n      slippage: input.slippage,\n      byAmountIn: input.byAmountIn,\n      overlayFee: ctx.overlayFee,\n      providers,\n      inputCoin: ctx.chainedCoin,\n      precomputedRoute: input.precomputedRoute,\n      sponsoredContext: ctx.sponsoredContext,\n      coinMergeCache: ctx.coinMergeCache,\n    });\n    if (!ctx.isOutputConsumed) {\n      tx.transferObjects([result.coin], ctx.sender);\n    }\n    return {\n      preview: {\n        toolName: 'swap_execute',\n        effectiveAmountIn: result.effectiveAmountIn,\n        expectedAmountOut: result.expectedAmountOut,\n        route: result.route,\n      },\n      outputCoin: result.coin,\n    };\n  },\n\n  // [S.444] claim_rewards / harvest_rewards appenders removed with NAVI.\n  // [S.323] volo_stake / volo_unstake appenders removed earlier.\n};\n\n// Reference unused import to suppress noUnusedLocals; SUI_TYPE is used\n// by selectSuiCoin internally and re-export from index.ts.\nvoid SUI_TYPE;\nvoid getDecimalsForCoinType;\n\n/**\n * Walks the assembled PTB's command list and extracts every recipient\n * address from top-level `TransferObjects` commands. Top-level only —\n * recipients inside nested Move calls are NOT inspected (Enoki only\n * cross-checks top-level commands).\n *\n * Replaces hand-maintained `allowedAddresses` arrays. Two production\n * bugs in 60 days came from drift between the array and the actual\n * PTB recipients (PR-H1 + PR-H4). Computing this from the PTB makes\n * drift impossible by construction.\n */\nexport function deriveAllowedAddressesFromPtb(tx: Transaction): string[] {\n  const addresses = new Set<string>();\n  const data = tx.getData();\n\n  const addAddressFromInput = (inputIndex: number | undefined): void => {\n    if (inputIndex === undefined) return;\n    const input = data.inputs[inputIndex];\n    if (!input) return;\n    const pureBytes = (input as { Pure?: { bytes?: string } }).Pure?.bytes;\n    if (!pureBytes) return;\n    // Pure bytes are base64-encoded BCS for Sui addresses (32 bytes →\n    // 44-char base64). Decode + format as 0x-prefixed hex.\n    try {\n      const bytes = base64ToBytes(pureBytes);\n      if (bytes.length !== 32) return; // not an address\n      const hex = '0x' + Array.from(bytes).map((b) => b.toString(16).padStart(2, '0')).join('');\n      addresses.add(hex);\n    } catch {\n      // not a parseable address — skip\n    }\n  };\n\n  for (const cmd of data.commands) {\n    // Path 1 — `TransferObjects.address` (the legacy send/withdraw/\n    // claim/fee-transfer recipient surface). The Sui transaction-builder\n    // stores each top-level command as a tagged object:\n    //   { TransferObjects: { objects, address: { Input: <index> } } }.\n    const transferCmd = (cmd as { TransferObjects?: unknown }).TransferObjects;\n    if (transferCmd) {\n      const addressArg = (transferCmd as { address?: unknown }).address;\n      const addressInputIndex = (addressArg as { Input?: number } | undefined)?.Input;\n      addAddressFromInput(addressInputIndex);\n      continue;\n    }\n\n    // Path 2 — `0x2::balance::send_funds(balance, recipient)` (gasless\n    // stablecoin transfer, v4.0 Phase A Day 2). Recipient is arg[1],\n    // not a TransferObjects.address. The Move call shape:\n    //   { MoveCall: { package, module, function, arguments: [...] } }\n    //   target = `0x2::balance::send_funds`, arguments[1] = recipient.\n    const moveCall = (cmd as { MoveCall?: unknown }).MoveCall;\n    if (moveCall) {\n      const mc = moveCall as {\n        package?: string;\n        module?: string;\n        function?: string;\n        arguments?: Array<{ Input?: number } | unknown>;\n      };\n      // The `package` field is the normalized framework address. For\n      // `0x2::balance::send_funds` it's `0x0000…0002` (`SUI_FRAMEWORK_ADDRESS`).\n      // Match on module + function defensively; the recipient extraction\n      // only fires when the signature matches.\n      const isBalanceSendFunds =\n        mc.module === 'balance' && mc.function === 'send_funds';\n      const isCoinSendFunds =\n        mc.module === 'coin' && mc.function === 'send_funds';\n      if (isBalanceSendFunds || isCoinSendFunds) {\n        const args = mc.arguments ?? [];\n        const recipientArg = args[1] as { Input?: number } | undefined;\n        addAddressFromInput(recipientArg?.Input);\n      }\n      continue;\n    }\n  }\n\n  return Array.from(addresses);\n}\n\nfunction base64ToBytes(b64: string): Uint8Array {\n  if (typeof Buffer !== 'undefined') {\n    return Uint8Array.from(Buffer.from(b64, 'base64'));\n  }\n  // Browser fallback (in case this ever runs in a worker)\n  const binary = atob(b64);\n  const bytes = new Uint8Array(binary.length);\n  for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n  return bytes;\n}\n\n/**\n * Compose a PTB from a list of canonical write steps. Each step\n * dispatches to its registered fragment-appender; the assembled PTB is\n * returned alongside pre-built `txKindBytes` ready for Enoki sponsorship\n * + auto-derived `derivedAllowedAddresses`.\n *\n * Single-step: `composeTx({ steps: [{ toolName: 'send_transfer', input: {...} }], ... })`\n * Multi-step (Layer 2): `composeTx({ steps: [{...}, {...}, {...}], ... })`\n *\n * Throws:\n * - `T2000Error('NO_APPENDER')` — unknown `toolName`\n * - Any error thrown by the per-step appender (insufficient balance,\n *   asset not supported, route not found, etc.) — propagates as-is.\n */\nexport async function composeTx(opts: ComposeTxOptions): Promise<ComposeTxResult> {\n  const tx = new Transaction();\n  tx.setSender(opts.sender);\n\n  const baseCtx = {\n    client: opts.client,\n    sender: opts.sender,\n    sponsoredContext: opts.sponsoredContext ?? false,\n    overlayFee: opts.overlayFee,\n    // One cache per compose run — shared across all legs (any coin type)\n    // so multi-leg sponsored bundles that source the same coin (two SUI\n    // swaps, swap USDC + save USDC, ...) merge that coin's objects once.\n    coinMergeCache: new Map() as SponsoredCoinMergeCache,\n  };\n\n  // [SPEC 13 Phase 1] First pass: validate every `inputCoinFromStep`\n  // reference and build the `consumedSteps` set. Forward-only\n  // references; producer-only tools can't be consumers.\n  const consumedSteps = new Set<number>();\n  for (let i = 0; i < opts.steps.length; i++) {\n    const step = opts.steps[i];\n    const stepWithChain = step as { inputCoinFromStep?: number };\n    const idx = stepWithChain.inputCoinFromStep;\n    if (idx === undefined) continue;\n\n    if (!Number.isInteger(idx) || idx < 0 || idx >= i) {\n      throw new T2000Error(\n        'CHAIN_MODE_INVALID',\n        `Step ${i} (${step.toolName}) has inputCoinFromStep=${idx}, ` +\n        `which must be a non-negative integer < ${i} (forward-only references).`,\n      );\n    }\n\n    const producer = opts.steps[idx];\n    if (producer.toolName === 'send_transfer') {\n      throw new T2000Error(\n        'CHAIN_MODE_INVALID',\n        `Step ${i} (${step.toolName}) references step ${idx} (${producer.toolName}) as ` +\n        `producer, but 'send_transfer' is a terminal consumer that does not ` +\n        `produce a chainable coin handle. Allowed producers: swap_execute.`,\n      );\n    }\n\n    consumedSteps.add(idx);\n  }\n\n  // [SPEC 13 Phase 1] Second pass: dispatch each step in order,\n  // capturing producers' output handles in `priorOutputs` and threading\n  // them into consumers' `chainedCoin`.\n  const priorOutputs: (TransactionObjectArgument | null)[] = [];\n  const previews: StepPreview[] = [];\n  for (let i = 0; i < opts.steps.length; i++) {\n    const step = opts.steps[i];\n    const appender = (WRITE_APPENDER_REGISTRY as Record<string, AppenderFn<unknown, StepPreview>>)[step.toolName];\n    if (!appender) {\n      throw new T2000Error(\n        'UNKNOWN',\n        `No fragment appender registered for tool '${step.toolName}'. ` +\n        `Allowed: ${(Object.keys(WRITE_APPENDER_REGISTRY) as WriteToolName[]).join(', ')}`,\n      );\n    }\n\n    const stepWithChain = step as { inputCoinFromStep?: number };\n    let chainedCoin: TransactionObjectArgument | undefined;\n    if (stepWithChain.inputCoinFromStep !== undefined) {\n      const upstream = priorOutputs[stepWithChain.inputCoinFromStep];\n      if (!upstream) {\n        // Producer didn't return an outputCoin (shouldn't happen given the\n        // first-pass guard, but defends against future appender bugs).\n        throw new T2000Error(\n          'CHAIN_MODE_INVALID',\n          `Step ${i} (${step.toolName}) expected a coin handle from step ` +\n          `${stepWithChain.inputCoinFromStep}, but the producer did not return one.`,\n        );\n      }\n      chainedCoin = upstream;\n    }\n\n    const stepCtx: AppenderContext = {\n      ...baseCtx,\n      chainedCoin,\n      isOutputConsumed: consumedSteps.has(i),\n    };\n\n    const result = await appender(tx, step.input, stepCtx);\n    priorOutputs.push(result.outputCoin ?? null);\n    previews.push(result.preview);\n  }\n\n  const txKindBytes = await tx.build({ client: opts.client, onlyTransactionKind: true });\n  const derivedAllowedAddresses = deriveAllowedAddressesFromPtb(tx);\n\n  return {\n    tx,\n    txKindBytes,\n    derivedAllowedAddresses,\n    perStepPreviews: previews,\n  };\n}\n","import { Transaction } from '@mysten/sui/transactions';\nimport { T2000Error } from '../errors.js';\nimport { mapMoveAbortCode } from '../errors.js';\nimport type { SuiCoreClient } from './sui.js';\n\nexport interface SimulationResult {\n  success: boolean;\n  gasEstimateSui: number;\n  error?: {\n    moveAbortCode?: number;\n    moveModule?: string;\n    reason: string;\n    rawError: string;\n  };\n}\n\nexport async function simulateTransaction(\n  client: SuiCoreClient,\n  tx: Transaction,\n  sender: string,\n): Promise<SimulationResult> {\n  tx.setSender(sender);\n\n  try {\n    // [gRPC migration] `core.simulateTransaction` replaces `dryRunTransactionBlock`.\n    // It returns a discriminated union; effects.status is `{ success, error }`\n    // where `error` is a structured `ExecutionError` (not the legacy raw string).\n    const txBytes = await tx.build({ client });\n    const sim = await client.core.simulateTransaction({\n      transaction: txBytes,\n      include: { effects: true },\n    });\n    const txn = sim.$kind === 'Transaction' ? sim.Transaction : sim.FailedTransaction;\n    const effects = txn.effects;\n    const gasUsed = effects?.gasUsed;\n\n    const gasEstimateSui = gasUsed\n      ? (Number(gasUsed.computationCost) +\n          Number(gasUsed.storageCost) -\n          Number(gasUsed.storageRebate)) / 1e9\n      : 0;\n\n    const errObj = effects && !effects.status.success ? effects.status.error : undefined;\n    if (sim.$kind === 'FailedTransaction' || errObj) {\n      const rawError = errObj?.message ?? 'Unknown simulation error';\n      // Prefer the structured MoveAbort code; fall back to regex-parsing the\n      // message for non-abort errors / pre-structured formats.\n      const structuredAbort =\n        errObj?.$kind === 'MoveAbort' ? Number(errObj.MoveAbort.abortCode) : undefined;\n      const parsed = parseMoveAbort(rawError);\n      const abortCode = structuredAbort ?? parsed.abortCode;\n\n      return {\n        success: false,\n        gasEstimateSui,\n        error: {\n          moveAbortCode: abortCode,\n          moveModule: parsed.module,\n          reason: abortCode != null ? mapMoveAbortCode(abortCode) : parsed.reason,\n          rawError,\n        },\n      };\n    }\n\n    return { success: true, gasEstimateSui };\n  } catch (err) {\n    const rawError = err instanceof Error ? err.message : String(err);\n    return {\n      success: false,\n      gasEstimateSui: 0,\n      error: {\n        reason: 'Simulation failed: ' + rawError,\n        rawError,\n      },\n    };\n  }\n}\n\nexport function throwIfSimulationFailed(sim: SimulationResult): void {\n  if (sim.success) return;\n\n  throw new T2000Error(\n    'SIMULATION_FAILED',\n    sim.error?.reason ?? 'Transaction simulation failed',\n    {\n      moveAbortCode: sim.error?.moveAbortCode,\n      moveModule: sim.error?.moveModule,\n      reason: sim.error?.reason,\n      rawError: sim.error?.rawError,\n    },\n  );\n}\n\nfunction parseMoveAbort(errorStr: string): {\n  abortCode?: number;\n  module?: string;\n  reason: string;\n} {\n  // Pattern: MoveAbort(MoveLocation { module: ModuleId { ... name: \"module\" }, ... }, code)\n  const abortMatch = errorStr.match(/MoveAbort\\([^,]*,\\s*(\\d+)\\)/);\n  const moduleMatch = errorStr.match(/name:\\s*Identifier\\(\"([^\"]+)\"\\)/);\n\n  if (abortMatch) {\n    const code = parseInt(abortMatch[1], 10);\n    const module = moduleMatch?.[1];\n    const reason = mapMoveAbortCode(code);\n    return { abortCode: code, module, reason };\n  }\n\n  // Pattern: MovePrimitiveRuntimeError\n  if (errorStr.includes('MovePrimitiveRuntimeError')) {\n    const module = moduleMatch?.[1];\n    return {\n      module,\n      reason: `Move runtime error in ${module ?? 'unknown'} module`,\n    };\n  }\n\n  return { reason: errorStr };\n}\n","/**\n * SuiNS leaf-subname builders for the `audric.sui` parent NFT.\n *\n * Used by SPEC 10 v0.2.1 Phase A.1 — Audric Passport Identity. Lets the audric host\n * mint and revoke `username.audric.sui` leaves under the parent NFT held by the\n * dedicated custody address (`0xaca29165…23d11`).\n *\n * **Why a dedicated SDK module (not inline in the audric route):**\n *  - Consumers (audric/web's `/api/identity/{reserve,change,release}` routes) can import\n *    the canonical builder shape without re-discovering the `SuinsTransaction` API.\n *  - Single source of truth for the parent NFT ID + parent name.\n *  - Single source of truth for label validation (length / charset / hyphen rules).\n *\n * **Signer model — read this before wiring into a route:**\n *  These builders are signed by the **service account** (the parent NFT custody address),\n *  NOT by the user's zkLogin key. Per `audric/.cursor/rules/audric-canonical-write.mdc`,\n *  the SPEC 10 leaf-mint API routes are explicitly documented as a CANONICAL-BYPASS of\n *  the `composeTx` write contract — they are server-to-server, the user's key is never\n *  in the loop, and Enoki sponsors the gas. PTB atomicity requires single-signer, so\n *  leaf mints cannot be bundled with chat-agent writes via composeTx.\n *\n * **Reference:** `spec/runbooks/RUNBOOK_audric_sui_parent.md` §1 (parent NFT ID) +\n *  §3 (validated SDK reference shape) + §4 (mainnet smoke test 2026-05-01).\n */\n\nimport { Transaction } from '@mysten/sui/transactions';\nimport { isValidSuiAddress, normalizeSuiAddress } from '@mysten/sui/utils';\nimport { SuinsTransaction, type SuinsClient } from '@mysten/suins';\n\n/**\n * Parent name registered on SuiNS mainnet. Audric's identity namespace anchor.\n *\n * Every leaf created via `buildAddLeafTx` becomes `<label>.audric.sui` and resolves\n * via the standard SuiNS resolver (`suix_resolveNameServiceAddress`).\n */\nexport const AUDRIC_PARENT_NAME = 'audric.sui';\n\n/**\n * On-chain object ID of the `audric.sui` parent NFT (a `SuinsRegistration`).\n *\n * Owned by the dedicated custody address `0xaca29165188f10136073788f648e1186dd25100100146186ebecedaf94b23d11`\n * (per `RUNBOOK_audric_sui_parent.md` §1). Every leaf mint / revoke MUST be signed\n * by the address that owns this NFT. Mainnet only.\n */\nexport const AUDRIC_PARENT_NFT_ID =\n  '0x070456e283ec988b6302bdd6cc5172bbdcb709998cf116586fb98d19b0870198';\n\nexport interface BuildAddLeafParams {\n  /** Bare label, e.g. `'alice'` — NOT the full `'alice.audric.sui'` path. */\n  label: string;\n  /** Sui address the leaf will resolve to (typically the user's zkLogin wallet). */\n  targetAddress: string;\n}\n\nexport interface BuildRevokeLeafParams {\n  /** Bare label of the leaf to revoke. */\n  label: string;\n}\n\nexport type LabelValidationResult = { valid: true } | { valid: false; reason: string };\n\n/**\n * SuiNS labels accept lowercase ASCII letters, digits, and hyphens. Hyphens cannot\n * lead or trail. The 3–63 char window matches SuiNS protocol rules and the SuiNS\n * dashboard's own `Register` form.\n *\n * The regex permits a single character only when it is alphanumeric (rejected by\n * the length check below for being < 3, but the pattern itself stays internally\n * consistent with DNS conventions).\n *\n * SUINS-LABEL-RULE — paired with `audric/apps/web/lib/identity/validate-label.ts`.\n * The audric host duplicates these rules inline to avoid pulling the full SDK\n * (and its server-side transitive deps) into the client bundle. If SuiNS ever\n * label rules, BOTH this file and the audric copy need updating.\n */\nconst LABEL_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;\n\n/**\n * Validate a leaf label against SuiNS protocol rules. Pure function; no I/O.\n *\n * Pre-call this before `buildAddLeafTx` / `buildRevokeLeafTx` if you want a\n * structured error (the builder functions throw on invalid labels). The audric\n * `/api/identity/check` endpoint uses this to drive the picker's real-time\n * availability indicator.\n *\n * Reserved-name policy (specific Audric handles like `support`, `admin`,\n * `official`) is NOT enforced here — that's a UI / route-level concern owned\n * by the audric host, not a protocol-level rule. See SPEC 10 D3.\n */\nexport function validateLabel(label: unknown): LabelValidationResult {\n  if (typeof label !== 'string') {\n    return { valid: false, reason: 'label must be a string' };\n  }\n  if (label.length < 3) {\n    return { valid: false, reason: 'label must be at least 3 characters' };\n  }\n  if (label.length > 63) {\n    return { valid: false, reason: 'label must be at most 63 characters' };\n  }\n  if (!LABEL_PATTERN.test(label)) {\n    return {\n      valid: false,\n      reason:\n        'label may only contain lowercase letters, digits, and hyphens, and may not start or end with a hyphen',\n    };\n  }\n  if (label.includes('--')) {\n    return { valid: false, reason: 'label may not contain consecutive hyphens' };\n  }\n  return { valid: true };\n}\n\n/**\n * Build an unsigned PTB that creates a `<label>.audric.sui` leaf subname pointing\n * to `targetAddress`.\n *\n * The returned `Transaction` has neither sender nor gas configured — the caller\n * (audric's `/api/identity/reserve` route) sets the sender to the parent NFT\n * custody address and submits via Enoki sponsorship. See `audric-transaction-flow.mdc`\n * for the sponsored-tx wrapper pattern; note SPEC 10 leaf-mint is a documented\n * CANONICAL-BYPASS of `composeTx` because the signer is the service account, not\n * the user's zkLogin key.\n *\n * Throws synchronously if `label` violates protocol rules or `targetAddress` is\n * not a valid Sui address — fail-closed before bytes are built.\n */\nexport function buildAddLeafTx(\n  suinsClient: SuinsClient,\n  { label, targetAddress }: BuildAddLeafParams,\n): Transaction {\n  const labelCheck = validateLabel(label);\n  if (!labelCheck.valid) {\n    throw new Error(`buildAddLeafTx: invalid label \"${label}\" — ${labelCheck.reason}`);\n  }\n  if (typeof targetAddress !== 'string' || !isValidSuiAddress(normalizeSuiAddress(targetAddress))) {\n    throw new Error(`buildAddLeafTx: invalid targetAddress \"${targetAddress}\"`);\n  }\n\n  const tx = new Transaction();\n  const suinsTx = new SuinsTransaction(suinsClient, tx);\n  suinsTx.createLeafSubName({\n    parentNft: AUDRIC_PARENT_NFT_ID,\n    name: `${label}.${AUDRIC_PARENT_NAME}`,\n    targetAddress: normalizeSuiAddress(targetAddress),\n  });\n  return tx;\n}\n\n/**\n * Build an unsigned PTB that revokes a `<label>.audric.sui` leaf subname.\n *\n * Used by:\n *   1. The change-username flow (`/api/identity/change`): revoke old leaf inside\n *      the same PTB as the new leaf creation, atomically.\n *   2. The release-username flow (`/api/admin/identity/release`): admin recovery\n *      of squatted / impersonating handles.\n *   3. Account-deletion flow (future): revoke leaf when user deletes their account.\n *\n * The mainnet smoke test (2026-05-01) confirmed revocation gas cost is roughly\n * negative net (storage rebate exceeds computation) — see RUNBOOK §4.\n */\nexport function buildRevokeLeafTx(\n  suinsClient: SuinsClient,\n  { label }: BuildRevokeLeafParams,\n): Transaction {\n  const labelCheck = validateLabel(label);\n  if (!labelCheck.valid) {\n    throw new Error(`buildRevokeLeafTx: invalid label \"${label}\" — ${labelCheck.reason}`);\n  }\n\n  const tx = new Transaction();\n  const suinsTx = new SuinsTransaction(suinsClient, tx);\n  suinsTx.removeLeafSubName({\n    parentNft: AUDRIC_PARENT_NFT_ID,\n    name: `${label}.${AUDRIC_PARENT_NAME}`,\n  });\n  return tx;\n}\n\n/**\n * Convenience: turn a bare label into the full `<label>.audric.sui` path.\n *\n * **Use this for ON-CHAIN operations** — SuiNS leaf NFT `name` field, the\n * `createLeafSubName` / `removeLeafSubName` move calls, and any RPC call\n * that returns/expects the canonical name string. The `<label>.audric.sui`\n * form is what the SuiNS protocol writes into the NFT `name` field.\n *\n * **Do NOT use this for UI rendering** — that's `displayHandle()`'s job\n * (S.118 reversal of SPEC 10 D10, see audric-build-tracker). Pre-S.118\n * we surfaced the full `.sui` form everywhere; we now use the SuiNS V2\n * `@` form (`alice@audric`) for display because it's shorter, fits the\n * agent harness mono aesthetic, and matches SuiNS's own V2 standard.\n *\n * Both forms resolve to the same address via SuiNS RPC (verified\n * mainnet 2026-05-08 PF1) — `displayHandle()` is purely a render-layer\n * choice, not a backend storage change.\n */\nexport function fullHandle(label: string): string {\n  return `${label}.${AUDRIC_PARENT_NAME}`;\n}\n\n/**\n * SuiNS V2 short-form display alias. `displayHandle('alice')` →\n * `'alice@audric'`. Use for chat narration, permission cards, receipts,\n * profile pages, share-to-X copy, OG metadata, and lookup_user output.\n *\n * **Why a separate function from `fullHandle`:**\n *  - `fullHandle('alice')` → `'alice.audric.sui'` is the **on-chain**\n *    NFT name field; SuiNS's `createLeafSubName` writes exactly this\n *    string and `suix_resolveNameServiceAddress` accepts it.\n *  - `displayHandle('alice')` → `'alice@audric'` is the **UI** form\n *    that users see and share. SuiNS RPC also accepts this form\n *    (verified mainnet 2026-05-08 PF1 — both forms return the same\n *    address), so we have one storage form (`<label>.audric.sui`) and\n *    two interchangeable input forms (the user can paste either).\n *\n * Reverses SPEC 10 D10 (\"full handle ALWAYS\"). See audric-build-tracker\n * S.118 for the rationale; see also `audric/apps/web/lib/identity/`\n * for canonicalization in the input parser (which is a no-op since\n * SuiNS RPC accepts both — kept available for future-proofing).\n */\nexport function displayHandle(label: string): string {\n  // Strip trailing `.sui` from the parent for the display form.\n  // Today AUDRIC_PARENT_NAME is `'audric.sui'` → `'audric'`. If the\n  // parent ever changes (e.g. `audric.app.sui` becomes the parent),\n  // this still produces a sensible display form by removing only the\n  // top-level TLD.\n  const parentDisplay = AUDRIC_PARENT_NAME.replace(/\\.sui$/, '');\n  return `${label}@${parentDisplay}`;\n}\n"]}