@t2000/sdk 5.3.0 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { EventEmitter } from 'eventemitter3';
2
2
  import { SuiGrpcClient } from '@mysten/sui/grpc';
3
3
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
4
- import { T as T2000Error, at as T2000Options, F as TransactionSigner, P as PayOptions, k as PayResult, au as SwapResult, av as SwapQuoteResult, t as SupportedAsset, o as SendResult, B as BalanceResponse, A as TransactionRecord, e as DepositInfo, aw as PaymentRequest, Z as ZkLoginProof, ax as SuiCoreClient, ay as SendableAsset, j as OverlayFeeConfig, az as SponsoredCoinMergeCache, u as SwapRouteResult } from './simulate-BTIIpnXc.cjs';
5
- export { aA as CETUS_USDC_SUI_POOL, C as CLOCK_ID, a as COIN_REGISTRY, b as ClassifyBalanceChange, c as ClassifyResult, d as CoinMeta, aB as CoinPage, aC as DEFAULT_GRPC_URL, D as DEFAULT_NETWORK, E as ETH_TYPE, f as ExtractedTransfer, aD as GASLESS_MIN_STABLE_AMOUNT, aE as GASLESS_STABLE_TYPES, G as GAS_RESERVE_MIN, I as IKA_TYPE, K as KNOWN_TARGETS, g as KeypairSigner, L as LABEL_PATTERNS, h as LOFI_TYPE, M as MANIFEST_TYPE, i as MIST_PER_SUI, N as NAVX_TYPE, aF as OPERATION_ASSETS, O as OVERLAY_FEE_RATE, aG as Operation, aH as SENDABLE_ASSETS, S as STABLE_ASSETS, l as SUI_DECIMALS, m as SUI_TYPE, n as SUPPORTED_ASSETS, aI as SelectAndSplitResult, aJ as SerializedCetusRoute, aK as SerializedCetusRoutePath, aL as SerializedRouterDataV3, p as SimulationResult, q as StableAsset, r as SuiHolding, s as SuiRpcTxBlock, v as T2000ErrorCode, w as T2000ErrorData, x as T2000_OVERLAY_FEE_WALLET, y as TOKEN_MAP, z as TransactionLeg, H as TxDirection, U as USDC_DECIMALS, J as USDC_TYPE, Q as USDE_TYPE, R as USDSUI_TYPE, V as USDT_TYPE, W as WAL_TYPE, X as WBTC_TYPE, Y as ZkLoginSigner, aM as addSwapToTx, aN as assertAllowedAsset, _ as buildSwapTx, $ as classifyAction, a0 as classifyLabel, a1 as classifyTransaction, aO as deserializeCetusRoute, a2 as executeTx, a3 as extractAllUserLegs, a4 as extractTransferDetails, a5 as extractTxCommands, a6 as extractTxSender, a7 as fallbackLabel, aP as fetchAllCoins, a8 as findSwapRoute, a9 as formatAssetAmount, aa as formatSui, ab as formatUsd, aQ as getCoinMeta, ac as getDecimals, ad as getDecimalsForCoinType, aR as getSuiClient, aS as getSuiGrpcClient, aT as isAllowedAsset, aU as isCetusRouteFresh, aV as isInRegistry, ae as mapMoveAbortCode, af as mapWalletError, ag as mistToSui, aW as normalizeAsset, aX as normalizeCoinType, ah as parseSuiRpcTx, ai as payWithMpp, aY as queryHistory, aZ as queryTransaction, aj as rawToStable, ak as rawToUsdc, al as refineLendingLabel, am as resolveSymbol, an as resolveTokenType, a_ as selectAndSplitCoin, a$ as selectSuiCoin, b0 as serializeCetusRoute, b1 as simulateTransaction, ao as stableToRaw, ap as suiToMist, b2 as throwIfSimulationFailed, aq as truncateAddress, ar as usdcToRaw, as as validateAddress, b3 as verifyCetusRouteCoinMatch } from './simulate-BTIIpnXc.cjs';
4
+ import { T as T2000Error, at as T2000Options, F as TransactionSigner, P as PayOptions, k as PayResult, au as SwapResult, av as SwapQuoteResult, t as SupportedAsset, o as SendResult, B as BalanceResponse, A as TransactionRecord, e as DepositInfo, aw as PaymentRequest, Z as ZkLoginProof, ax as SuiCoreClient, ay as SendableAsset, j as OverlayFeeConfig, az as SponsoredCoinMergeCache, u as SwapRouteResult } from './simulate-KETPmlDo.cjs';
5
+ export { aA as CETUS_USDC_SUI_POOL, C as CLOCK_ID, a as COIN_REGISTRY, b as ClassifyBalanceChange, c as ClassifyResult, d as CoinMeta, aB as CoinPage, aC as DEFAULT_GRPC_URL, D as DEFAULT_NETWORK, E as ETH_TYPE, f as ExtractedTransfer, aD as GASLESS_MIN_STABLE_AMOUNT, aE as GASLESS_STABLE_TYPES, G as GAS_RESERVE_MIN, I as IKA_TYPE, K as KNOWN_TARGETS, g as KeypairSigner, L as LABEL_PATTERNS, h as LOFI_TYPE, M as MANIFEST_TYPE, i as MIST_PER_SUI, N as NAVX_TYPE, aF as OPERATION_ASSETS, O as OVERLAY_FEE_RATE, aG as Operation, aH as SENDABLE_ASSETS, S as STABLE_ASSETS, l as SUI_DECIMALS, m as SUI_TYPE, n as SUPPORTED_ASSETS, aI as SelectAndSplitResult, aJ as SerializedCetusRoute, aK as SerializedCetusRoutePath, aL as SerializedRouterDataV3, p as SimulationResult, q as StableAsset, r as SuiHolding, s as SuiRpcTxBlock, v as T2000ErrorCode, w as T2000ErrorData, x as T2000_OVERLAY_FEE_WALLET, y as TOKEN_MAP, z as TransactionLeg, H as TxDirection, U as USDC_DECIMALS, J as USDC_TYPE, Q as USDE_TYPE, R as USDSUI_TYPE, V as USDT_TYPE, W as WAL_TYPE, X as WBTC_TYPE, Y as ZkLoginSigner, aM as addSwapToTx, aN as assertAllowedAsset, _ as buildSwapTx, $ as classifyAction, a0 as classifyLabel, a1 as classifyTransaction, aO as deserializeCetusRoute, a2 as executeTx, a3 as extractAllUserLegs, a4 as extractTransferDetails, a5 as extractTxCommands, a6 as extractTxSender, a7 as fallbackLabel, aP as fetchAllCoins, a8 as findSwapRoute, a9 as formatAssetAmount, aa as formatSui, ab as formatUsd, aQ as getCoinMeta, ac as getDecimals, ad as getDecimalsForCoinType, aR as getSuiClient, aS as getSuiGrpcClient, aT as isAllowedAsset, aU as isCetusRouteFresh, aV as isInRegistry, ae as mapMoveAbortCode, af as mapWalletError, ag as mistToSui, aW as normalizeAsset, aX as normalizeCoinType, ah as parseSuiRpcTx, ai as payWithMpp, aY as queryHistory, aZ as queryTransaction, aj as rawToStable, ak as rawToUsdc, al as refineLendingLabel, am as resolveSymbol, an as resolveTokenType, a_ as selectAndSplitCoin, a$ as selectSuiCoin, b0 as serializeCetusRoute, b1 as simulateTransaction, ao as stableToRaw, ap as suiToMist, b2 as throwIfSimulationFailed, aq as truncateAddress, ar as usdcToRaw, as as validateAddress, b3 as verifyCetusRouteCoinMatch } from './simulate-KETPmlDo.cjs';
6
6
  import { Transaction, TransactionObjectArgument } from '@mysten/sui/transactions';
7
7
  import { SuinsClient } from '@mysten/suins';
8
8
  import '@mysten/sui/client';
@@ -239,8 +239,8 @@ declare class T2000 extends EventEmitter<T2000Events> {
239
239
  /**
240
240
  * [SPEC_AGENTIC_STACK P1 / SDK F2 — 2026-05-25; refreshed S.342 / 2026-05-26]
241
241
  * Preferred alias of `deposit()`. Was introduced to mirror the v3 `t2000 fund`
242
- * CLI command; the v4 CLI surface is `t2 receive` (deleted `fund` in the
243
- * S.332 bulk cut). `deposit()` stays as the canonical method name for
242
+ * CLI command; the v4 CLI surface is `t2 fund` (renamed back from the
243
+ * interim `t2 receive` in S.464). `deposit()` stays as the canonical method name for
244
244
  * back-compat; `fund()` stays as a programmatic alias for audric + other
245
245
  * SDK consumers that prefer the verb.
246
246
  */
@@ -828,6 +828,14 @@ declare function getSwapQuote(params: {
828
828
  * keep access to the full provider set including Pyth-dependent pools.
829
829
  */
830
830
  providers?: string[];
831
+ /**
832
+ * [2.11] On-chain-resolved decimals for `from` / `to`, supplied by callers
833
+ * that hold a client (e.g. `T2000.swapQuote`). When omitted (standalone /
834
+ * sponsored callers), falls back to the registry — correct for registry
835
+ * tokens, a 9-decimal guess for an unknown coin type.
836
+ */
837
+ fromDecimals?: number;
838
+ toDecimals?: number;
831
839
  }): Promise<SwapQuoteResult>;
832
840
 
833
841
  /**
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { EventEmitter } from 'eventemitter3';
2
2
  import { SuiGrpcClient } from '@mysten/sui/grpc';
3
3
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
4
- import { T as T2000Error, at as T2000Options, F as TransactionSigner, P as PayOptions, k as PayResult, au as SwapResult, av as SwapQuoteResult, t as SupportedAsset, o as SendResult, B as BalanceResponse, A as TransactionRecord, e as DepositInfo, aw as PaymentRequest, Z as ZkLoginProof, ax as SuiCoreClient, ay as SendableAsset, j as OverlayFeeConfig, az as SponsoredCoinMergeCache, u as SwapRouteResult } from './simulate-BTIIpnXc.js';
5
- export { aA as CETUS_USDC_SUI_POOL, C as CLOCK_ID, a as COIN_REGISTRY, b as ClassifyBalanceChange, c as ClassifyResult, d as CoinMeta, aB as CoinPage, aC as DEFAULT_GRPC_URL, D as DEFAULT_NETWORK, E as ETH_TYPE, f as ExtractedTransfer, aD as GASLESS_MIN_STABLE_AMOUNT, aE as GASLESS_STABLE_TYPES, G as GAS_RESERVE_MIN, I as IKA_TYPE, K as KNOWN_TARGETS, g as KeypairSigner, L as LABEL_PATTERNS, h as LOFI_TYPE, M as MANIFEST_TYPE, i as MIST_PER_SUI, N as NAVX_TYPE, aF as OPERATION_ASSETS, O as OVERLAY_FEE_RATE, aG as Operation, aH as SENDABLE_ASSETS, S as STABLE_ASSETS, l as SUI_DECIMALS, m as SUI_TYPE, n as SUPPORTED_ASSETS, aI as SelectAndSplitResult, aJ as SerializedCetusRoute, aK as SerializedCetusRoutePath, aL as SerializedRouterDataV3, p as SimulationResult, q as StableAsset, r as SuiHolding, s as SuiRpcTxBlock, v as T2000ErrorCode, w as T2000ErrorData, x as T2000_OVERLAY_FEE_WALLET, y as TOKEN_MAP, z as TransactionLeg, H as TxDirection, U as USDC_DECIMALS, J as USDC_TYPE, Q as USDE_TYPE, R as USDSUI_TYPE, V as USDT_TYPE, W as WAL_TYPE, X as WBTC_TYPE, Y as ZkLoginSigner, aM as addSwapToTx, aN as assertAllowedAsset, _ as buildSwapTx, $ as classifyAction, a0 as classifyLabel, a1 as classifyTransaction, aO as deserializeCetusRoute, a2 as executeTx, a3 as extractAllUserLegs, a4 as extractTransferDetails, a5 as extractTxCommands, a6 as extractTxSender, a7 as fallbackLabel, aP as fetchAllCoins, a8 as findSwapRoute, a9 as formatAssetAmount, aa as formatSui, ab as formatUsd, aQ as getCoinMeta, ac as getDecimals, ad as getDecimalsForCoinType, aR as getSuiClient, aS as getSuiGrpcClient, aT as isAllowedAsset, aU as isCetusRouteFresh, aV as isInRegistry, ae as mapMoveAbortCode, af as mapWalletError, ag as mistToSui, aW as normalizeAsset, aX as normalizeCoinType, ah as parseSuiRpcTx, ai as payWithMpp, aY as queryHistory, aZ as queryTransaction, aj as rawToStable, ak as rawToUsdc, al as refineLendingLabel, am as resolveSymbol, an as resolveTokenType, a_ as selectAndSplitCoin, a$ as selectSuiCoin, b0 as serializeCetusRoute, b1 as simulateTransaction, ao as stableToRaw, ap as suiToMist, b2 as throwIfSimulationFailed, aq as truncateAddress, ar as usdcToRaw, as as validateAddress, b3 as verifyCetusRouteCoinMatch } from './simulate-BTIIpnXc.js';
4
+ import { T as T2000Error, at as T2000Options, F as TransactionSigner, P as PayOptions, k as PayResult, au as SwapResult, av as SwapQuoteResult, t as SupportedAsset, o as SendResult, B as BalanceResponse, A as TransactionRecord, e as DepositInfo, aw as PaymentRequest, Z as ZkLoginProof, ax as SuiCoreClient, ay as SendableAsset, j as OverlayFeeConfig, az as SponsoredCoinMergeCache, u as SwapRouteResult } from './simulate-KETPmlDo.js';
5
+ export { aA as CETUS_USDC_SUI_POOL, C as CLOCK_ID, a as COIN_REGISTRY, b as ClassifyBalanceChange, c as ClassifyResult, d as CoinMeta, aB as CoinPage, aC as DEFAULT_GRPC_URL, D as DEFAULT_NETWORK, E as ETH_TYPE, f as ExtractedTransfer, aD as GASLESS_MIN_STABLE_AMOUNT, aE as GASLESS_STABLE_TYPES, G as GAS_RESERVE_MIN, I as IKA_TYPE, K as KNOWN_TARGETS, g as KeypairSigner, L as LABEL_PATTERNS, h as LOFI_TYPE, M as MANIFEST_TYPE, i as MIST_PER_SUI, N as NAVX_TYPE, aF as OPERATION_ASSETS, O as OVERLAY_FEE_RATE, aG as Operation, aH as SENDABLE_ASSETS, S as STABLE_ASSETS, l as SUI_DECIMALS, m as SUI_TYPE, n as SUPPORTED_ASSETS, aI as SelectAndSplitResult, aJ as SerializedCetusRoute, aK as SerializedCetusRoutePath, aL as SerializedRouterDataV3, p as SimulationResult, q as StableAsset, r as SuiHolding, s as SuiRpcTxBlock, v as T2000ErrorCode, w as T2000ErrorData, x as T2000_OVERLAY_FEE_WALLET, y as TOKEN_MAP, z as TransactionLeg, H as TxDirection, U as USDC_DECIMALS, J as USDC_TYPE, Q as USDE_TYPE, R as USDSUI_TYPE, V as USDT_TYPE, W as WAL_TYPE, X as WBTC_TYPE, Y as ZkLoginSigner, aM as addSwapToTx, aN as assertAllowedAsset, _ as buildSwapTx, $ as classifyAction, a0 as classifyLabel, a1 as classifyTransaction, aO as deserializeCetusRoute, a2 as executeTx, a3 as extractAllUserLegs, a4 as extractTransferDetails, a5 as extractTxCommands, a6 as extractTxSender, a7 as fallbackLabel, aP as fetchAllCoins, a8 as findSwapRoute, a9 as formatAssetAmount, aa as formatSui, ab as formatUsd, aQ as getCoinMeta, ac as getDecimals, ad as getDecimalsForCoinType, aR as getSuiClient, aS as getSuiGrpcClient, aT as isAllowedAsset, aU as isCetusRouteFresh, aV as isInRegistry, ae as mapMoveAbortCode, af as mapWalletError, ag as mistToSui, aW as normalizeAsset, aX as normalizeCoinType, ah as parseSuiRpcTx, ai as payWithMpp, aY as queryHistory, aZ as queryTransaction, aj as rawToStable, ak as rawToUsdc, al as refineLendingLabel, am as resolveSymbol, an as resolveTokenType, a_ as selectAndSplitCoin, a$ as selectSuiCoin, b0 as serializeCetusRoute, b1 as simulateTransaction, ao as stableToRaw, ap as suiToMist, b2 as throwIfSimulationFailed, aq as truncateAddress, ar as usdcToRaw, as as validateAddress, b3 as verifyCetusRouteCoinMatch } from './simulate-KETPmlDo.js';
6
6
  import { Transaction, TransactionObjectArgument } from '@mysten/sui/transactions';
7
7
  import { SuinsClient } from '@mysten/suins';
8
8
  import '@mysten/sui/client';
@@ -239,8 +239,8 @@ declare class T2000 extends EventEmitter<T2000Events> {
239
239
  /**
240
240
  * [SPEC_AGENTIC_STACK P1 / SDK F2 — 2026-05-25; refreshed S.342 / 2026-05-26]
241
241
  * Preferred alias of `deposit()`. Was introduced to mirror the v3 `t2000 fund`
242
- * CLI command; the v4 CLI surface is `t2 receive` (deleted `fund` in the
243
- * S.332 bulk cut). `deposit()` stays as the canonical method name for
242
+ * CLI command; the v4 CLI surface is `t2 fund` (renamed back from the
243
+ * interim `t2 receive` in S.464). `deposit()` stays as the canonical method name for
244
244
  * back-compat; `fund()` stays as a programmatic alias for audric + other
245
245
  * SDK consumers that prefer the verb.
246
246
  */
@@ -828,6 +828,14 @@ declare function getSwapQuote(params: {
828
828
  * keep access to the full provider set including Pyth-dependent pools.
829
829
  */
830
830
  providers?: string[];
831
+ /**
832
+ * [2.11] On-chain-resolved decimals for `from` / `to`, supplied by callers
833
+ * that hold a client (e.g. `T2000.swapQuote`). When omitted (standalone /
834
+ * sponsored callers), falls back to the registry — correct for registry
835
+ * tokens, a 9-decimal guess for an unknown coin type.
836
+ */
837
+ fromDecimals?: number;
838
+ toDecimals?: number;
831
839
  }): Promise<SwapQuoteResult>;
832
840
 
833
841
  /**
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { EventEmitter } from 'eventemitter3';
5
5
  import { createPaymentTransactionUri } from '@mysten/payment-kit';
6
6
  import { SuiGrpcClient } from '@mysten/sui/grpc';
7
7
  import { SuiGraphQLClient } from '@mysten/sui/graphql';
8
- import { normalizeSuiAddress, isValidSuiAddress, fromBase64 } from '@mysten/sui/utils';
8
+ import { normalizeStructTag, normalizeSuiAddress, isValidSuiAddress, fromBase64 } from '@mysten/sui/utils';
9
9
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
10
10
  import { decodeSuiPrivateKey } from '@mysten/sui/cryptography';
11
11
  import { access, mkdir, writeFile, readFile } from 'fs/promises';
@@ -133,6 +133,7 @@ __export(token_registry_exports, {
133
133
  getCoinMeta: () => getCoinMeta,
134
134
  getDecimalsForCoinType: () => getDecimalsForCoinType,
135
135
  isInRegistry: () => isInRegistry,
136
+ resolveCoinDecimals: () => resolveCoinDecimals,
136
137
  resolveSymbol: () => resolveSymbol,
137
138
  resolveTokenType: () => resolveTokenType
138
139
  });
@@ -154,6 +155,16 @@ function getDecimalsForCoinType(coinType) {
154
155
  }
155
156
  return 9;
156
157
  }
158
+ async function resolveCoinDecimals(client, coinType) {
159
+ if (isInRegistry(coinType)) return getDecimalsForCoinType(coinType);
160
+ try {
161
+ const res = await client.core.getCoinMetadata({ coinType });
162
+ const d = res?.metadata?.decimals ?? res?.decimals;
163
+ if (typeof d === "number" && Number.isFinite(d)) return d;
164
+ } catch {
165
+ }
166
+ return getDecimalsForCoinType(coinType);
167
+ }
157
168
  function resolveSymbol(coinType) {
158
169
  const direct = BY_TYPE.get(coinType);
159
170
  if (direct) return direct.symbol;
@@ -648,7 +659,7 @@ async function getSwapQuote(params) {
648
659
  );
649
660
  }
650
661
  const byAmountIn = params.byAmountIn ?? true;
651
- const fromDecimals = getDecimalsForCoinType(fromType);
662
+ const fromDecimals = params.fromDecimals ?? getDecimalsForCoinType(fromType);
652
663
  const rawAmount = BigInt(Math.floor(params.amount * 10 ** fromDecimals));
653
664
  const route = await findSwapRoute2({
654
665
  walletAddress: params.walletAddress,
@@ -662,7 +673,7 @@ async function getSwapQuote(params) {
662
673
  if (route.insufficientLiquidity) {
663
674
  throw new T2000Error("SWAP_FAILED", `Insufficient liquidity for ${params.from} -> ${params.to}.`);
664
675
  }
665
- const toDecimals = getDecimalsForCoinType(toType);
676
+ const toDecimals = params.toDecimals ?? getDecimalsForCoinType(toType);
666
677
  const fromAmount = Number(route.amountIn) / 10 ** fromDecimals;
667
678
  const toAmount = Number(route.amountOut) / 10 ** toDecimals;
668
679
  const routeDesc = route.routerData.paths?.map((p) => p.provider).filter(Boolean).slice(0, 3).join(" + ") ?? "Cetus Aggregator";
@@ -1278,8 +1289,7 @@ function addSendToTx(tx, coin, recipient) {
1278
1289
  const validRecipient = validateAddress(recipient);
1279
1290
  tx.transferObjects([coin], validRecipient);
1280
1291
  }
1281
-
1282
- // src/wallet/balance.ts
1292
+ init_token_registry();
1283
1293
  var SUI_PRICE_FALLBACK = 1;
1284
1294
  var _cachedSuiPrice = 0;
1285
1295
  var _priceLastFetched = 0;
@@ -1312,30 +1322,67 @@ async function fetchSuiPrice(client) {
1312
1322
  }
1313
1323
  return _cachedSuiPrice || SUI_PRICE_FALLBACK;
1314
1324
  }
1325
+ function safeNorm(coinType) {
1326
+ try {
1327
+ return normalizeStructTag(coinType);
1328
+ } catch {
1329
+ return coinType;
1330
+ }
1331
+ }
1332
+ var SUI_TYPE_NORM = safeNorm(SUPPORTED_ASSETS.SUI.type);
1333
+ var STABLE_BY_NORM = (() => {
1334
+ const m = {};
1335
+ for (const asset of STABLE_ASSETS) m[safeNorm(SUPPORTED_ASSETS[asset].type)] = asset;
1336
+ return m;
1337
+ })();
1315
1338
  async function queryBalance(client, address) {
1316
- const stableBalancePromises = STABLE_ASSETS.map(
1317
- (asset) => client.core.getBalance({ owner: address, coinType: SUPPORTED_ASSETS[asset].type }).then((b) => ({ asset, amount: Number(b.balance.balance) / 10 ** SUPPORTED_ASSETS[asset].decimals })).catch(() => ({ asset, amount: 0 }))
1318
- );
1319
- const [suiBalance, suiPriceUsd, ...stableResults] = await Promise.all([
1320
- client.core.getBalance({ owner: address, coinType: SUPPORTED_ASSETS.SUI.type }),
1321
- fetchSuiPrice(client),
1322
- ...stableBalancePromises
1323
- ]);
1339
+ const held = [];
1340
+ let cursor;
1341
+ do {
1342
+ const page = await client.core.listBalances({ owner: address, cursor: cursor ?? void 0 });
1343
+ for (const b of page.balances) {
1344
+ const raw = BigInt(b.balance);
1345
+ if (raw > 0n) held.push({ coinType: b.coinType, raw });
1346
+ }
1347
+ cursor = page.hasNextPage ? page.cursor : null;
1348
+ } while (cursor);
1349
+ const suiPriceUsd = await fetchSuiPrice(client);
1324
1350
  const stables = {};
1351
+ for (const asset of STABLE_ASSETS) stables[asset] = 0;
1325
1352
  let totalStables = 0;
1326
- for (const { asset, amount } of stableResults) {
1327
- stables[asset] = amount;
1328
- totalStables += amount;
1353
+ let suiAmount = 0;
1354
+ const otherCoins = [];
1355
+ for (const { coinType, raw } of held) {
1356
+ const norm = safeNorm(coinType);
1357
+ if (norm === SUI_TYPE_NORM) {
1358
+ suiAmount = Number(raw) / Number(MIST_PER_SUI);
1359
+ } else if (STABLE_BY_NORM[norm]) {
1360
+ const asset = STABLE_BY_NORM[norm];
1361
+ const amount = Number(raw) / 10 ** SUPPORTED_ASSETS[asset].decimals;
1362
+ stables[asset] = amount;
1363
+ totalStables += amount;
1364
+ } else {
1365
+ otherCoins.push({ coinType, raw });
1366
+ }
1329
1367
  }
1330
- const suiAmount = Number(suiBalance.balance.balance) / Number(MIST_PER_SUI);
1368
+ const tokens = await Promise.all(
1369
+ otherCoins.map(async ({ coinType, raw }) => {
1370
+ const decimals = await resolveCoinDecimals(client, coinType);
1371
+ return {
1372
+ coinType,
1373
+ symbol: resolveSymbol(coinType),
1374
+ amount: Number(raw) / 10 ** decimals,
1375
+ usdValue: null
1376
+ };
1377
+ })
1378
+ );
1379
+ tokens.sort((a, b) => a.symbol.localeCompare(b.symbol));
1331
1380
  const suiUsdValue = suiAmount * suiPriceUsd;
1332
1381
  return {
1333
1382
  stables,
1334
1383
  available: totalStables,
1335
- sui: {
1336
- amount: suiAmount,
1337
- usdValue: suiUsdValue
1338
- },
1384
+ sui: { amount: suiAmount, usdValue: suiUsdValue },
1385
+ tokens,
1339
1386
  totalUsd: totalStables + suiUsdValue
1340
1387
  };
1341
1388
  }
@@ -2039,7 +2086,7 @@ var T2000 = class _T2000 extends EventEmitter {
2039
2086
  if (!toType) throw new T2000Error("ASSET_NOT_SUPPORTED", `Unknown token: ${params.to}. Provide the full coin type.`);
2040
2087
  const byAmountIn = params.byAmountIn ?? true;
2041
2088
  const slippage = Math.min(params.slippage ?? 0.01, 0.05);
2042
- const fromDecimals = getDecimalsForCoinType(fromType);
2089
+ const fromDecimals = await resolveCoinDecimals(this.client, fromType);
2043
2090
  const rawAmount = BigInt(Math.floor(params.amount * 10 ** fromDecimals));
2044
2091
  const route = await findSwapRoute2({
2045
2092
  walletAddress: this._address,
@@ -2053,7 +2100,7 @@ var T2000 = class _T2000 extends EventEmitter {
2053
2100
  if (route.priceImpact > 0.05) {
2054
2101
  console.warn(`[swap] High price impact: ${(route.priceImpact * 100).toFixed(2)}%`);
2055
2102
  }
2056
- const toDecimals = getDecimalsForCoinType(toType);
2103
+ const toDecimals = await resolveCoinDecimals(this.client, toType);
2057
2104
  let preBalRaw = 0n;
2058
2105
  try {
2059
2106
  const preBal = await this.client.core.getBalance({ owner: this._address, coinType: toType });
@@ -2146,13 +2193,18 @@ var T2000 = class _T2000 extends EventEmitter {
2146
2193
  */
2147
2194
  async swapQuote(params) {
2148
2195
  const { getSwapQuote: getSwapQuote2 } = await Promise.resolve().then(() => (init_swap_quote(), swap_quote_exports));
2196
+ const { resolveTokenType: resolveTokenType2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
2197
+ const fromType = resolveTokenType2(params.from);
2198
+ const toType = resolveTokenType2(params.to);
2149
2199
  return getSwapQuote2({
2150
2200
  walletAddress: this._address,
2151
2201
  from: params.from,
2152
2202
  to: params.to,
2153
2203
  amount: params.amount,
2154
2204
  byAmountIn: params.byAmountIn,
2155
- providers: params.providers
2205
+ providers: params.providers,
2206
+ fromDecimals: fromType ? await resolveCoinDecimals(this.client, fromType) : void 0,
2207
+ toDecimals: toType ? await resolveCoinDecimals(this.client, toType) : void 0
2156
2208
  });
2157
2209
  }
2158
2210
  // -- Wallet --
@@ -2288,8 +2340,8 @@ var T2000 = class _T2000 extends EventEmitter {
2288
2340
  /**
2289
2341
  * [SPEC_AGENTIC_STACK P1 / SDK F2 — 2026-05-25; refreshed S.342 / 2026-05-26]
2290
2342
  * Preferred alias of `deposit()`. Was introduced to mirror the v3 `t2000 fund`
2291
- * CLI command; the v4 CLI surface is `t2 receive` (deleted `fund` in the
2292
- * S.332 bulk cut). `deposit()` stays as the canonical method name for
2343
+ * CLI command; the v4 CLI surface is `t2 fund` (renamed back from the
2344
+ * interim `t2 receive` in S.464). `deposit()` stays as the canonical method name for
2293
2345
  * back-compat; `fund()` stays as a programmatic alias for audric + other
2294
2346
  * SDK consumers that prefer the verb.
2295
2347
  */