@t2000/sdk 2.18.1 → 2.19.1

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,12 +1,12 @@
1
1
  import { EventEmitter } from 'eventemitter3';
2
2
  import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
3
3
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
4
- import { Q as TxMetadata, o as SafeguardConfig, T as T2000Error, H as TransactionSigner, _ as ZkLoginProof, v as SupportedAsset } from './types-C2Va_r0h.cjs';
5
- export { A as ALL_NAVI_ASSETS, B as BORROW_FEE_BPS, a as BPS_DENOMINATOR, ax as CETUS_USDC_SUI_POOL, C as CLOCK_ID, b as COIN_REGISTRY, c as ClassifyBalanceChange, d as ClassifyResult, e as CoinMeta, D as DEFAULT_NETWORK, f as DEFAULT_SAFEGUARD_CONFIG, E as ETH_TYPE, g as ExtractedTransfer, F as FeeOperation, G as GAS_RESERVE_MIN, I as IKA_TYPE, K as KNOWN_TARGETS, h as KeypairSigner, L as LABEL_PATTERNS, i as LOFI_TYPE, M as MANIFEST_TYPE, j as MIST_PER_SUI, N as NAVX_TYPE, ay as OPERATION_ASSETS, O as OUTBOUND_OPS, az as Operation, P as ProtocolFeeInfo, S as SAVE_FEE_BPS, k as STABLE_ASSETS, l as SUI_DECIMALS, m as SUI_TYPE, n as SUPPORTED_ASSETS, p as SafeguardError, q as SafeguardErrorDetails, r as SafeguardRule, s as SimulationResult, t as StableAsset, u as SuiRpcTxBlock, w as T2000ErrorCode, x as T2000ErrorData, y as T2000_OVERLAY_FEE_WALLET, z as TOKEN_MAP, J as TxDirection, U as USDC_DECIMALS, R as USDC_TYPE, V as USDE_TYPE, W as USDSUI_TYPE, X as USDT_TYPE, Y as WAL_TYPE, Z as WBTC_TYPE, $ as ZkLoginSigner, a0 as addFeeTransfer, aA as assertAllowedAsset, a1 as calculateFee, a2 as classifyAction, a3 as classifyLabel, a4 as classifyTransaction, a5 as extractAllUserLegs, a6 as extractTransferDetails, a7 as extractTxCommands, a8 as extractTxSender, a9 as fallbackLabel, aa as formatAssetAmount, ab as formatSui, ac as formatUsd, aB as getCoinMeta, ad as getDecimals, ae as getDecimalsForCoinType, af as getTier, aC as isAllowedAsset, aD as isInRegistry, ag as isSupported, ah as isTier1, ai as isTier2, aj as mapMoveAbortCode, ak as mapWalletError, al as mistToSui, aE as normalizeAsset, aF as normalizeCoinType, am as parseSuiRpcTx, aG as queryHistory, aH as queryTransaction, an as rawToStable, ao as rawToUsdc, ap as refineLendingLabel, aq as resolveSymbol, ar as resolveTokenType, aI as simulateTransaction, as as stableToRaw, at as suiToMist, aJ as throwIfSimulationFailed, au as truncateAddress, av as usdcToRaw, aw as validateAddress } from './types-C2Va_r0h.cjs';
4
+ import { Q as TxMetadata, o as SafeguardConfig, T as T2000Error, H as TransactionSigner, _ as ZkLoginProof, v as SupportedAsset } from './types-DOnXJXL2.cjs';
5
+ export { A as ALL_NAVI_ASSETS, B as BORROW_FEE_BPS, a as BPS_DENOMINATOR, ax as CETUS_USDC_SUI_POOL, C as CLOCK_ID, b as COIN_REGISTRY, c as ClassifyBalanceChange, d as ClassifyResult, e as CoinMeta, D as DEFAULT_NETWORK, f as DEFAULT_SAFEGUARD_CONFIG, E as ETH_TYPE, g as ExtractedTransfer, F as FeeOperation, G as GAS_RESERVE_MIN, I as IKA_TYPE, K as KNOWN_TARGETS, h as KeypairSigner, L as LABEL_PATTERNS, i as LOFI_TYPE, M as MANIFEST_TYPE, j as MIST_PER_SUI, N as NAVX_TYPE, ay as OPERATION_ASSETS, O as OUTBOUND_OPS, az as Operation, P as ProtocolFeeInfo, S as SAVE_FEE_BPS, k as STABLE_ASSETS, l as SUI_DECIMALS, m as SUI_TYPE, n as SUPPORTED_ASSETS, p as SafeguardError, q as SafeguardErrorDetails, r as SafeguardRule, s as SimulationResult, t as StableAsset, u as SuiRpcTxBlock, w as T2000ErrorCode, x as T2000ErrorData, y as T2000_OVERLAY_FEE_WALLET, z as TOKEN_MAP, J as TxDirection, U as USDC_DECIMALS, R as USDC_TYPE, V as USDE_TYPE, W as USDSUI_TYPE, X as USDT_TYPE, Y as WAL_TYPE, Z as WBTC_TYPE, $ as ZkLoginSigner, a0 as addFeeTransfer, aA as assertAllowedAsset, a1 as calculateFee, a2 as classifyAction, a3 as classifyLabel, a4 as classifyTransaction, a5 as extractAllUserLegs, a6 as extractTransferDetails, a7 as extractTxCommands, a8 as extractTxSender, a9 as fallbackLabel, aa as formatAssetAmount, ab as formatSui, ac as formatUsd, aB as getCoinMeta, ad as getDecimals, ae as getDecimalsForCoinType, af as getTier, aC as isAllowedAsset, aD as isInRegistry, ag as isSupported, ah as isTier1, ai as isTier2, aj as mapMoveAbortCode, ak as mapWalletError, al as mistToSui, aE as normalizeAsset, aF as normalizeCoinType, am as parseSuiRpcTx, aG as queryHistory, aH as queryTransaction, an as rawToStable, ao as rawToUsdc, ap as refineLendingLabel, aq as resolveSymbol, ar as resolveTokenType, aI as simulateTransaction, as as stableToRaw, at as suiToMist, aJ as throwIfSimulationFailed, au as truncateAddress, av as usdcToRaw, aw as validateAddress } from './types-DOnXJXL2.cjs';
6
6
  import { L as LendingAdapter, a as LendingRates, P as PendingReward$1 } from './descriptors-DqIb4AnV.cjs';
7
7
  export { A as AdapterCapability, b as AdapterPositions, c as AdapterTxResult, H as HealthInfo, d as ProtocolDescriptor, e as allDescriptors, n as naviDescriptor } from './descriptors-DqIb4AnV.cjs';
8
- import { n as T2000Options, P as PayOptions, d as PayResult, o as StakeVSuiResult, U as UnstakeVSuiResult, p as SwapResult, q as SwapQuoteResult, i as SendResult, B as BalanceResponse, k as TransactionRecord, D as DepositInfo, r as PaymentRequest, S as SaveResult, W as WithdrawResult, b as MaxWithdrawResult, a as BorrowResult, h as RepayResult, M as MaxBorrowResult, H as HealthFactorResult, e as PendingReward, C as ClaimRewardsResult, s as CompoundRewardsResult, g as PositionsResult, R as RatesResult, E as EarningsResult, F as FundStatusResult, c as OverlayFeeConfig, j as SwapRouteResult, t as FinancialSummary } from './types-I7U99DvG.cjs';
9
- export { A as AssetRates, G as GasReserve, u as HFAlertLevel, O as OVERLAY_FEE_RATE, f as PositionEntry, v as SerializedCetusRoute, w as SerializedCetusRoutePath, x as SerializedRouterDataV3, T as TransactionLeg, y as addSwapToTx, l as buildSwapTx, z as deserializeCetusRoute, m as findSwapRoute, I as isCetusRouteFresh, J as serializeCetusRoute, K as verifyCetusRouteCoinMatch } from './types-I7U99DvG.cjs';
8
+ import { n as T2000Options, P as PayOptions, d as PayResult, o as StakeVSuiResult, U as UnstakeVSuiResult, p as SwapResult, q as SwapQuoteResult, i as SendResult, B as BalanceResponse, k as TransactionRecord, D as DepositInfo, r as PaymentRequest, S as SaveResult, W as WithdrawResult, b as MaxWithdrawResult, a as BorrowResult, h as RepayResult, M as MaxBorrowResult, H as HealthFactorResult, e as PendingReward, C as ClaimRewardsResult, s as CompoundRewardsResult, g as PositionsResult, R as RatesResult, E as EarningsResult, F as FundStatusResult, c as OverlayFeeConfig, j as SwapRouteResult, t as FinancialSummary } from './types-Bk7NncQ_.cjs';
9
+ export { A as AssetRates, G as GasReserve, u as HFAlertLevel, O as OVERLAY_FEE_RATE, f as PositionEntry, v as SerializedCetusRoute, w as SerializedCetusRoutePath, x as SerializedRouterDataV3, T as TransactionLeg, y as addSwapToTx, l as buildSwapTx, z as deserializeCetusRoute, m as findSwapRoute, I as isCetusRouteFresh, J as serializeCetusRoute, K as verifyCetusRouteCoinMatch } from './types-Bk7NncQ_.cjs';
10
10
  import { Transaction, TransactionObjectArgument } from '@mysten/sui/transactions';
11
11
  import { SuinsClient } from '@mysten/suins';
12
12
  export { NaviAdapter, ProtocolRegistry } from './adapters/index.cjs';
@@ -136,6 +136,37 @@ declare class T2000 extends EventEmitter<T2000Events> {
136
136
  amount: number;
137
137
  asset?: string;
138
138
  }): Promise<SendResult>;
139
+ /**
140
+ * [S.279 / CLI-CONTACTS-CLEANUP — 2026-05-23] Resolve a recipient
141
+ * string into a canonical 0x address, trying each shape in priority
142
+ * order:
143
+ * 1. **hex** — `0x…` is used directly (no RPC round-trip).
144
+ * 2. **SuiNS** — `alex.sui` resolves via `suix_resolveNameServiceAddress`.
145
+ * 3. **saved contact** — `ContactManager.resolve()` falls back to the
146
+ * legacy `~/.t2000/contacts.json` alias map. Deprecated; the
147
+ * manager surfaces a one-time `console.warn` when this path fires.
148
+ *
149
+ * Returns `{ address, suinsName?, contactName? }` so `send()` can stamp
150
+ * the name source on the receipt without re-resolving.
151
+ *
152
+ * Throws `T2000Error('SUINS_NOT_REGISTERED', …)` for well-formed but
153
+ * unregistered SuiNS names (vs. propagating the engine-style
154
+ * `SuinsNotRegisteredError` — keeps the SDK's error surface
155
+ * `T2000Error`-only, consistent with every other write helper).
156
+ *
157
+ * [S.279.1 / 2026-05-23 — patch v2.19.1] Promoted from `private` to
158
+ * `public` so MCP's `t2000_send` dryRun preview path can share the
159
+ * same resolution logic as the live execute path. Pre-2.19.1 the
160
+ * MCP dryRun called `agent.contacts.resolve(to)` directly, which
161
+ * rejected SuiNS names — preview-then-execute flows broke for
162
+ * `alex.sui`-style recipients. SSOT: never let preview and execute
163
+ * resolve the same input differently.
164
+ */
165
+ resolveRecipient(input: string): Promise<{
166
+ address: string;
167
+ contactName?: string;
168
+ suinsName?: string;
169
+ }>;
139
170
  balance(): Promise<BalanceResponse>;
140
171
  history(params?: {
141
172
  limit?: number;
@@ -223,6 +254,116 @@ declare class T2000 extends EventEmitter<T2000Events> {
223
254
  private emitBalanceChange;
224
255
  }
225
256
 
257
+ /**
258
+ * Canonical 0x-address shape. Loose lower bound (>= 1 hex char) so
259
+ * pre-v1.0 short addresses still validate; tools that need a full 64-hex
260
+ * address can additionally check `length === 66`. Case-insensitive on
261
+ * the `0x` prefix because some upstream callers (and historic tests)
262
+ * uppercase the prefix as part of address normalization tests; the
263
+ * normalizer always returns the lowercased canonical form regardless.
264
+ */
265
+ declare const SUI_ADDRESS_REGEX: RegExp;
266
+ /**
267
+ * Strict canonical 0x-address shape (66 chars total). Used by the
268
+ * resolver's "looks like" check to disambiguate "user pasted an
269
+ * address" vs "user typed a SuiNS name".
270
+ */
271
+ declare const SUI_ADDRESS_STRICT_REGEX: RegExp;
272
+ /**
273
+ * Mirrors the pattern in `audric/apps/web-v2/lib/suins-cache.ts` so the
274
+ * host-side send executor and the engine-side read normalizer agree on
275
+ * what counts as a SuiNS name. SuiNS allows nested labels (`team.alex.sui`)
276
+ * but every label must use only `[a-z0-9-]`.
277
+ */
278
+ declare const SUINS_NAME_REGEX: RegExp;
279
+ declare class InvalidAddressError extends Error {
280
+ readonly raw: string;
281
+ constructor(raw: string);
282
+ }
283
+ declare class SuinsNotRegisteredError extends Error {
284
+ readonly name_: string;
285
+ constructor(name_: string);
286
+ }
287
+ declare class SuinsRpcError extends Error {
288
+ readonly name_: string;
289
+ constructor(name_: string, detail: string);
290
+ }
291
+ /**
292
+ * Returns true if `value` looks like a SuiNS name (case-insensitive).
293
+ * Cheap synchronous check — use to avoid an unnecessary RPC round-trip
294
+ * for inputs that obviously aren't names (0x addresses, contact handles).
295
+ */
296
+ declare function looksLikeSuiNs(value: string): boolean;
297
+ /**
298
+ * Resolve a SuiNS name to its on-chain Sui address via the public
299
+ * `suix_resolveNameServiceAddress` JSON-RPC method. Returns `null` if
300
+ * the name resolves to no address (= not registered or expired). Throws
301
+ * `SuinsRpcError` on RPC/network failure.
302
+ *
303
+ * The host SHOULD pass a `rpcUrl` that includes any vendor key (e.g.
304
+ * audric's BlockVision-keyed URL) so the call benefits from the host's
305
+ * paid retry/cache budget. Falls back to the public mainnet endpoint.
306
+ */
307
+ declare function resolveSuinsViaRpc(rawName: string, ctx?: {
308
+ suiRpcUrl?: string;
309
+ signal?: AbortSignal;
310
+ }): Promise<string | null>;
311
+ /**
312
+ * Reverse-resolve a 0x address to its registered SuiNS names via
313
+ * `suix_resolveNameServiceNames`. Returns the names sorted by the
314
+ * registry (the first entry is conventionally the user's "primary"
315
+ * name on dApps that show one), or `[]` when the address has no
316
+ * SuiNS records. Throws `SuinsRpcError` on RPC/network failure.
317
+ *
318
+ * Why this is its own helper (not folded into `normalizeAddressInput`):
319
+ * a reverse lookup adds a second RPC round-trip per tool call. We don't
320
+ * want every read tool that takes an `address` to silently double its
321
+ * latency. The lookup primitive is opt-in via the `resolve_suins` tool;
322
+ * normalizers stay forward-only.
323
+ */
324
+ declare function resolveAddressToSuinsViaRpc(rawAddress: string, ctx?: {
325
+ suiRpcUrl?: string;
326
+ signal?: AbortSignal;
327
+ }): Promise<string[]>;
328
+ interface NormalizedAddress {
329
+ /**
330
+ * Canonical 0x-prefixed lowercase hex address. Always set on success.
331
+ * Tools should use this for any downstream query (BlockVision, NAVI,
332
+ * positionFetcher, etc.) and for cache keys.
333
+ */
334
+ address: string;
335
+ /**
336
+ * The user-facing name when the input was resolved via SuiNS, otherwise
337
+ * `null`. Tools should stamp this on result data so card titles can
338
+ * render "Balance · obehi.sui" instead of "Balance · 0x1234…abcd".
339
+ */
340
+ suinsName: string | null;
341
+ /**
342
+ * The original input (pre-normalization). Useful for error narration —
343
+ * "I tried to resolve `Obehi.Sui` and …" reads better than the
344
+ * post-trim/lowercase form.
345
+ */
346
+ raw: string;
347
+ }
348
+ /**
349
+ * Canonical normalizer. Accepts a 0x address OR a SuiNS name; returns
350
+ * a structured `NormalizedAddress`. Throws:
351
+ * - `InvalidAddressError` if the input matches neither shape.
352
+ * - `SuinsNotRegisteredError` if the SuiNS name is well-formed but
353
+ * resolves to null (= not registered).
354
+ * - `SuinsRpcError` if the RPC fails.
355
+ *
356
+ * Every read tool (engine) and write helper (SDK `T2000.send()`) that
357
+ * accepts a user-supplied recipient MUST call this helper before any
358
+ * downstream lookup. Doing the check inline (1) duplicates the regex,
359
+ * (2) silently rejects SuiNS names, (3) makes cache keys inconsistent
360
+ * across tools.
361
+ */
362
+ declare function normalizeAddressInput(value: string, ctx?: {
363
+ suiRpcUrl?: string;
364
+ signal?: AbortSignal;
365
+ }): Promise<NormalizedAddress>;
366
+
226
367
  declare function generateKeypair(): Ed25519Keypair;
227
368
  declare function keypairFromPrivateKey(privateKey: string): Ed25519Keypair;
228
369
  declare function saveKey(keypair: Ed25519Keypair, passphrase: string, keyPath?: string): Promise<string>;
@@ -1347,4 +1488,4 @@ declare function fullHandle(label: string): string;
1347
1488
  */
1348
1489
  declare function displayHandle(label: string): string;
1349
1490
 
1350
- export { AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, type AppenderContext, BalanceResponse, type BorrowInput, BorrowResult, type BuildAddLeafParams, type BuildHarvestRewardsTxOptions, type BuildRevokeLeafParams, type ClaimRewardsInput, ClaimRewardsResult, type CoinPage, type ComposeTxFeeHookContext, type ComposeTxFeeHooks, type ComposeTxOptions, type ComposeTxResult, CompoundRewardsResult, ContactManager, DepositInfo, EarningsResult, FinancialSummary, type FinancialSummaryOptions, FundStatusResult, HF_CRITICAL_THRESHOLD, HF_WARN_THRESHOLD, type HarvestPlan, type HarvestSkippedLeg, type HarvestSwapLeg, HealthFactorResult, type LabelValidationResult, LendingAdapter, LendingRates, MaxBorrowResult, MaxWithdrawResult, OverlayFeeConfig, PayOptions, PayResult, PaymentRequest, PendingReward, PositionsResult, RatesResult, type RepayDebtInput, RepayResult, SPONSORED_PYTH_DEPENDENT_PROVIDERS, SafeguardConfig, SafeguardEnforcer, type SaveDepositInput, SaveResult, type SelectAndSplitResult, SendResult, type SendTransferInput, StakeVSuiResult, type StepPreview, SupportedAsset, type SwapExecuteInput, SwapQuoteResult, SwapResult, SwapRouteResult, T2000, T2000Error, T2000Options, TransactionRecord, TransactionSigner, TxMetadata, UnstakeVSuiResult, VOLO_METADATA, VOLO_PKG, VOLO_POOL, VSUI_TYPE, type VoloStakeInput, type VoloStats, type VoloUnstakeInput, WRITE_APPENDER_REGISTRY, type WithdrawInput, WithdrawResult, type WriteStep, type WriteToolName, ZkLoginProof, addClaimRewardsToTx, addSendToTx, addStakeVSuiToTx, addUnstakeVSuiToTx, aggregateClaimableRewards, buildAddLeafTx, buildClaimRewardsTx, buildHarvestRewardsTx, buildRevokeLeafTx, buildSendTx, buildStakeVSuiTx, buildUnstakeVSuiTx, composeTx, deriveAllowedAddressesFromPtb, displayHandle, exportPrivateKey, fetchAllCoins, fullHandle, generateKeypair, getAddress, getFinancialSummary, getPendingRewards, getPendingRewardsByAddress, getRates, getSponsoredSwapProviders, getSwapQuote, getVoloStats, keypairFromPrivateKey, loadKey, saveKey, selectAndSplitCoin, selectSuiCoin, validateLabel, walletExists };
1491
+ export { AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, type AppenderContext, BalanceResponse, type BorrowInput, BorrowResult, type BuildAddLeafParams, type BuildHarvestRewardsTxOptions, type BuildRevokeLeafParams, type ClaimRewardsInput, ClaimRewardsResult, type CoinPage, type ComposeTxFeeHookContext, type ComposeTxFeeHooks, type ComposeTxOptions, type ComposeTxResult, CompoundRewardsResult, ContactManager, DepositInfo, EarningsResult, FinancialSummary, type FinancialSummaryOptions, FundStatusResult, HF_CRITICAL_THRESHOLD, HF_WARN_THRESHOLD, type HarvestPlan, type HarvestSkippedLeg, type HarvestSwapLeg, HealthFactorResult, InvalidAddressError, type LabelValidationResult, LendingAdapter, LendingRates, MaxBorrowResult, MaxWithdrawResult, type NormalizedAddress, OverlayFeeConfig, PayOptions, PayResult, PaymentRequest, PendingReward, PositionsResult, RatesResult, type RepayDebtInput, RepayResult, SPONSORED_PYTH_DEPENDENT_PROVIDERS, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SafeguardConfig, SafeguardEnforcer, type SaveDepositInput, SaveResult, type SelectAndSplitResult, SendResult, type SendTransferInput, StakeVSuiResult, type StepPreview, SuinsNotRegisteredError, SuinsRpcError, SupportedAsset, type SwapExecuteInput, SwapQuoteResult, SwapResult, SwapRouteResult, T2000, T2000Error, T2000Options, TransactionRecord, TransactionSigner, TxMetadata, UnstakeVSuiResult, VOLO_METADATA, VOLO_PKG, VOLO_POOL, VSUI_TYPE, type VoloStakeInput, type VoloStats, type VoloUnstakeInput, WRITE_APPENDER_REGISTRY, type WithdrawInput, WithdrawResult, type WriteStep, type WriteToolName, ZkLoginProof, addClaimRewardsToTx, addSendToTx, addStakeVSuiToTx, addUnstakeVSuiToTx, aggregateClaimableRewards, buildAddLeafTx, buildClaimRewardsTx, buildHarvestRewardsTx, buildRevokeLeafTx, buildSendTx, buildStakeVSuiTx, buildUnstakeVSuiTx, composeTx, deriveAllowedAddressesFromPtb, displayHandle, exportPrivateKey, fetchAllCoins, fullHandle, generateKeypair, getAddress, getFinancialSummary, getPendingRewards, getPendingRewardsByAddress, getRates, getSponsoredSwapProviders, getSwapQuote, getVoloStats, keypairFromPrivateKey, loadKey, looksLikeSuiNs, normalizeAddressInput, resolveAddressToSuinsViaRpc, resolveSuinsViaRpc, saveKey, selectAndSplitCoin, selectSuiCoin, validateLabel, walletExists };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { EventEmitter } from 'eventemitter3';
2
2
  import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
3
3
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
4
- import { Q as TxMetadata, o as SafeguardConfig, T as T2000Error, H as TransactionSigner, _ as ZkLoginProof, v as SupportedAsset } from './types-BMdhu0D7.js';
5
- export { A as ALL_NAVI_ASSETS, B as BORROW_FEE_BPS, a as BPS_DENOMINATOR, ax as CETUS_USDC_SUI_POOL, C as CLOCK_ID, b as COIN_REGISTRY, c as ClassifyBalanceChange, d as ClassifyResult, e as CoinMeta, D as DEFAULT_NETWORK, f as DEFAULT_SAFEGUARD_CONFIG, E as ETH_TYPE, g as ExtractedTransfer, F as FeeOperation, G as GAS_RESERVE_MIN, I as IKA_TYPE, K as KNOWN_TARGETS, h as KeypairSigner, L as LABEL_PATTERNS, i as LOFI_TYPE, M as MANIFEST_TYPE, j as MIST_PER_SUI, N as NAVX_TYPE, ay as OPERATION_ASSETS, O as OUTBOUND_OPS, az as Operation, P as ProtocolFeeInfo, S as SAVE_FEE_BPS, k as STABLE_ASSETS, l as SUI_DECIMALS, m as SUI_TYPE, n as SUPPORTED_ASSETS, p as SafeguardError, q as SafeguardErrorDetails, r as SafeguardRule, s as SimulationResult, t as StableAsset, u as SuiRpcTxBlock, w as T2000ErrorCode, x as T2000ErrorData, y as T2000_OVERLAY_FEE_WALLET, z as TOKEN_MAP, J as TxDirection, U as USDC_DECIMALS, R as USDC_TYPE, V as USDE_TYPE, W as USDSUI_TYPE, X as USDT_TYPE, Y as WAL_TYPE, Z as WBTC_TYPE, $ as ZkLoginSigner, a0 as addFeeTransfer, aA as assertAllowedAsset, a1 as calculateFee, a2 as classifyAction, a3 as classifyLabel, a4 as classifyTransaction, a5 as extractAllUserLegs, a6 as extractTransferDetails, a7 as extractTxCommands, a8 as extractTxSender, a9 as fallbackLabel, aa as formatAssetAmount, ab as formatSui, ac as formatUsd, aB as getCoinMeta, ad as getDecimals, ae as getDecimalsForCoinType, af as getTier, aC as isAllowedAsset, aD as isInRegistry, ag as isSupported, ah as isTier1, ai as isTier2, aj as mapMoveAbortCode, ak as mapWalletError, al as mistToSui, aE as normalizeAsset, aF as normalizeCoinType, am as parseSuiRpcTx, aG as queryHistory, aH as queryTransaction, an as rawToStable, ao as rawToUsdc, ap as refineLendingLabel, aq as resolveSymbol, ar as resolveTokenType, aI as simulateTransaction, as as stableToRaw, at as suiToMist, aJ as throwIfSimulationFailed, au as truncateAddress, av as usdcToRaw, aw as validateAddress } from './types-BMdhu0D7.js';
4
+ import { Q as TxMetadata, o as SafeguardConfig, T as T2000Error, H as TransactionSigner, _ as ZkLoginProof, v as SupportedAsset } from './types-CfBlFLmU.js';
5
+ export { A as ALL_NAVI_ASSETS, B as BORROW_FEE_BPS, a as BPS_DENOMINATOR, ax as CETUS_USDC_SUI_POOL, C as CLOCK_ID, b as COIN_REGISTRY, c as ClassifyBalanceChange, d as ClassifyResult, e as CoinMeta, D as DEFAULT_NETWORK, f as DEFAULT_SAFEGUARD_CONFIG, E as ETH_TYPE, g as ExtractedTransfer, F as FeeOperation, G as GAS_RESERVE_MIN, I as IKA_TYPE, K as KNOWN_TARGETS, h as KeypairSigner, L as LABEL_PATTERNS, i as LOFI_TYPE, M as MANIFEST_TYPE, j as MIST_PER_SUI, N as NAVX_TYPE, ay as OPERATION_ASSETS, O as OUTBOUND_OPS, az as Operation, P as ProtocolFeeInfo, S as SAVE_FEE_BPS, k as STABLE_ASSETS, l as SUI_DECIMALS, m as SUI_TYPE, n as SUPPORTED_ASSETS, p as SafeguardError, q as SafeguardErrorDetails, r as SafeguardRule, s as SimulationResult, t as StableAsset, u as SuiRpcTxBlock, w as T2000ErrorCode, x as T2000ErrorData, y as T2000_OVERLAY_FEE_WALLET, z as TOKEN_MAP, J as TxDirection, U as USDC_DECIMALS, R as USDC_TYPE, V as USDE_TYPE, W as USDSUI_TYPE, X as USDT_TYPE, Y as WAL_TYPE, Z as WBTC_TYPE, $ as ZkLoginSigner, a0 as addFeeTransfer, aA as assertAllowedAsset, a1 as calculateFee, a2 as classifyAction, a3 as classifyLabel, a4 as classifyTransaction, a5 as extractAllUserLegs, a6 as extractTransferDetails, a7 as extractTxCommands, a8 as extractTxSender, a9 as fallbackLabel, aa as formatAssetAmount, ab as formatSui, ac as formatUsd, aB as getCoinMeta, ad as getDecimals, ae as getDecimalsForCoinType, af as getTier, aC as isAllowedAsset, aD as isInRegistry, ag as isSupported, ah as isTier1, ai as isTier2, aj as mapMoveAbortCode, ak as mapWalletError, al as mistToSui, aE as normalizeAsset, aF as normalizeCoinType, am as parseSuiRpcTx, aG as queryHistory, aH as queryTransaction, an as rawToStable, ao as rawToUsdc, ap as refineLendingLabel, aq as resolveSymbol, ar as resolveTokenType, aI as simulateTransaction, as as stableToRaw, at as suiToMist, aJ as throwIfSimulationFailed, au as truncateAddress, av as usdcToRaw, aw as validateAddress } from './types-CfBlFLmU.js';
6
6
  import { L as LendingAdapter, a as LendingRates, P as PendingReward$1 } from './descriptors-DqIb4AnV.js';
7
7
  export { A as AdapterCapability, b as AdapterPositions, c as AdapterTxResult, H as HealthInfo, d as ProtocolDescriptor, e as allDescriptors, n as naviDescriptor } from './descriptors-DqIb4AnV.js';
8
- import { n as T2000Options, P as PayOptions, d as PayResult, o as StakeVSuiResult, U as UnstakeVSuiResult, p as SwapResult, q as SwapQuoteResult, i as SendResult, B as BalanceResponse, k as TransactionRecord, D as DepositInfo, r as PaymentRequest, S as SaveResult, W as WithdrawResult, b as MaxWithdrawResult, a as BorrowResult, h as RepayResult, M as MaxBorrowResult, H as HealthFactorResult, e as PendingReward, C as ClaimRewardsResult, s as CompoundRewardsResult, g as PositionsResult, R as RatesResult, E as EarningsResult, F as FundStatusResult, c as OverlayFeeConfig, j as SwapRouteResult, t as FinancialSummary } from './types-I7U99DvG.js';
9
- export { A as AssetRates, G as GasReserve, u as HFAlertLevel, O as OVERLAY_FEE_RATE, f as PositionEntry, v as SerializedCetusRoute, w as SerializedCetusRoutePath, x as SerializedRouterDataV3, T as TransactionLeg, y as addSwapToTx, l as buildSwapTx, z as deserializeCetusRoute, m as findSwapRoute, I as isCetusRouteFresh, J as serializeCetusRoute, K as verifyCetusRouteCoinMatch } from './types-I7U99DvG.js';
8
+ import { n as T2000Options, P as PayOptions, d as PayResult, o as StakeVSuiResult, U as UnstakeVSuiResult, p as SwapResult, q as SwapQuoteResult, i as SendResult, B as BalanceResponse, k as TransactionRecord, D as DepositInfo, r as PaymentRequest, S as SaveResult, W as WithdrawResult, b as MaxWithdrawResult, a as BorrowResult, h as RepayResult, M as MaxBorrowResult, H as HealthFactorResult, e as PendingReward, C as ClaimRewardsResult, s as CompoundRewardsResult, g as PositionsResult, R as RatesResult, E as EarningsResult, F as FundStatusResult, c as OverlayFeeConfig, j as SwapRouteResult, t as FinancialSummary } from './types-Bk7NncQ_.js';
9
+ export { A as AssetRates, G as GasReserve, u as HFAlertLevel, O as OVERLAY_FEE_RATE, f as PositionEntry, v as SerializedCetusRoute, w as SerializedCetusRoutePath, x as SerializedRouterDataV3, T as TransactionLeg, y as addSwapToTx, l as buildSwapTx, z as deserializeCetusRoute, m as findSwapRoute, I as isCetusRouteFresh, J as serializeCetusRoute, K as verifyCetusRouteCoinMatch } from './types-Bk7NncQ_.js';
10
10
  import { Transaction, TransactionObjectArgument } from '@mysten/sui/transactions';
11
11
  import { SuinsClient } from '@mysten/suins';
12
12
  export { NaviAdapter, ProtocolRegistry } from './adapters/index.js';
@@ -136,6 +136,37 @@ declare class T2000 extends EventEmitter<T2000Events> {
136
136
  amount: number;
137
137
  asset?: string;
138
138
  }): Promise<SendResult>;
139
+ /**
140
+ * [S.279 / CLI-CONTACTS-CLEANUP — 2026-05-23] Resolve a recipient
141
+ * string into a canonical 0x address, trying each shape in priority
142
+ * order:
143
+ * 1. **hex** — `0x…` is used directly (no RPC round-trip).
144
+ * 2. **SuiNS** — `alex.sui` resolves via `suix_resolveNameServiceAddress`.
145
+ * 3. **saved contact** — `ContactManager.resolve()` falls back to the
146
+ * legacy `~/.t2000/contacts.json` alias map. Deprecated; the
147
+ * manager surfaces a one-time `console.warn` when this path fires.
148
+ *
149
+ * Returns `{ address, suinsName?, contactName? }` so `send()` can stamp
150
+ * the name source on the receipt without re-resolving.
151
+ *
152
+ * Throws `T2000Error('SUINS_NOT_REGISTERED', …)` for well-formed but
153
+ * unregistered SuiNS names (vs. propagating the engine-style
154
+ * `SuinsNotRegisteredError` — keeps the SDK's error surface
155
+ * `T2000Error`-only, consistent with every other write helper).
156
+ *
157
+ * [S.279.1 / 2026-05-23 — patch v2.19.1] Promoted from `private` to
158
+ * `public` so MCP's `t2000_send` dryRun preview path can share the
159
+ * same resolution logic as the live execute path. Pre-2.19.1 the
160
+ * MCP dryRun called `agent.contacts.resolve(to)` directly, which
161
+ * rejected SuiNS names — preview-then-execute flows broke for
162
+ * `alex.sui`-style recipients. SSOT: never let preview and execute
163
+ * resolve the same input differently.
164
+ */
165
+ resolveRecipient(input: string): Promise<{
166
+ address: string;
167
+ contactName?: string;
168
+ suinsName?: string;
169
+ }>;
139
170
  balance(): Promise<BalanceResponse>;
140
171
  history(params?: {
141
172
  limit?: number;
@@ -223,6 +254,116 @@ declare class T2000 extends EventEmitter<T2000Events> {
223
254
  private emitBalanceChange;
224
255
  }
225
256
 
257
+ /**
258
+ * Canonical 0x-address shape. Loose lower bound (>= 1 hex char) so
259
+ * pre-v1.0 short addresses still validate; tools that need a full 64-hex
260
+ * address can additionally check `length === 66`. Case-insensitive on
261
+ * the `0x` prefix because some upstream callers (and historic tests)
262
+ * uppercase the prefix as part of address normalization tests; the
263
+ * normalizer always returns the lowercased canonical form regardless.
264
+ */
265
+ declare const SUI_ADDRESS_REGEX: RegExp;
266
+ /**
267
+ * Strict canonical 0x-address shape (66 chars total). Used by the
268
+ * resolver's "looks like" check to disambiguate "user pasted an
269
+ * address" vs "user typed a SuiNS name".
270
+ */
271
+ declare const SUI_ADDRESS_STRICT_REGEX: RegExp;
272
+ /**
273
+ * Mirrors the pattern in `audric/apps/web-v2/lib/suins-cache.ts` so the
274
+ * host-side send executor and the engine-side read normalizer agree on
275
+ * what counts as a SuiNS name. SuiNS allows nested labels (`team.alex.sui`)
276
+ * but every label must use only `[a-z0-9-]`.
277
+ */
278
+ declare const SUINS_NAME_REGEX: RegExp;
279
+ declare class InvalidAddressError extends Error {
280
+ readonly raw: string;
281
+ constructor(raw: string);
282
+ }
283
+ declare class SuinsNotRegisteredError extends Error {
284
+ readonly name_: string;
285
+ constructor(name_: string);
286
+ }
287
+ declare class SuinsRpcError extends Error {
288
+ readonly name_: string;
289
+ constructor(name_: string, detail: string);
290
+ }
291
+ /**
292
+ * Returns true if `value` looks like a SuiNS name (case-insensitive).
293
+ * Cheap synchronous check — use to avoid an unnecessary RPC round-trip
294
+ * for inputs that obviously aren't names (0x addresses, contact handles).
295
+ */
296
+ declare function looksLikeSuiNs(value: string): boolean;
297
+ /**
298
+ * Resolve a SuiNS name to its on-chain Sui address via the public
299
+ * `suix_resolveNameServiceAddress` JSON-RPC method. Returns `null` if
300
+ * the name resolves to no address (= not registered or expired). Throws
301
+ * `SuinsRpcError` on RPC/network failure.
302
+ *
303
+ * The host SHOULD pass a `rpcUrl` that includes any vendor key (e.g.
304
+ * audric's BlockVision-keyed URL) so the call benefits from the host's
305
+ * paid retry/cache budget. Falls back to the public mainnet endpoint.
306
+ */
307
+ declare function resolveSuinsViaRpc(rawName: string, ctx?: {
308
+ suiRpcUrl?: string;
309
+ signal?: AbortSignal;
310
+ }): Promise<string | null>;
311
+ /**
312
+ * Reverse-resolve a 0x address to its registered SuiNS names via
313
+ * `suix_resolveNameServiceNames`. Returns the names sorted by the
314
+ * registry (the first entry is conventionally the user's "primary"
315
+ * name on dApps that show one), or `[]` when the address has no
316
+ * SuiNS records. Throws `SuinsRpcError` on RPC/network failure.
317
+ *
318
+ * Why this is its own helper (not folded into `normalizeAddressInput`):
319
+ * a reverse lookup adds a second RPC round-trip per tool call. We don't
320
+ * want every read tool that takes an `address` to silently double its
321
+ * latency. The lookup primitive is opt-in via the `resolve_suins` tool;
322
+ * normalizers stay forward-only.
323
+ */
324
+ declare function resolveAddressToSuinsViaRpc(rawAddress: string, ctx?: {
325
+ suiRpcUrl?: string;
326
+ signal?: AbortSignal;
327
+ }): Promise<string[]>;
328
+ interface NormalizedAddress {
329
+ /**
330
+ * Canonical 0x-prefixed lowercase hex address. Always set on success.
331
+ * Tools should use this for any downstream query (BlockVision, NAVI,
332
+ * positionFetcher, etc.) and for cache keys.
333
+ */
334
+ address: string;
335
+ /**
336
+ * The user-facing name when the input was resolved via SuiNS, otherwise
337
+ * `null`. Tools should stamp this on result data so card titles can
338
+ * render "Balance · obehi.sui" instead of "Balance · 0x1234…abcd".
339
+ */
340
+ suinsName: string | null;
341
+ /**
342
+ * The original input (pre-normalization). Useful for error narration —
343
+ * "I tried to resolve `Obehi.Sui` and …" reads better than the
344
+ * post-trim/lowercase form.
345
+ */
346
+ raw: string;
347
+ }
348
+ /**
349
+ * Canonical normalizer. Accepts a 0x address OR a SuiNS name; returns
350
+ * a structured `NormalizedAddress`. Throws:
351
+ * - `InvalidAddressError` if the input matches neither shape.
352
+ * - `SuinsNotRegisteredError` if the SuiNS name is well-formed but
353
+ * resolves to null (= not registered).
354
+ * - `SuinsRpcError` if the RPC fails.
355
+ *
356
+ * Every read tool (engine) and write helper (SDK `T2000.send()`) that
357
+ * accepts a user-supplied recipient MUST call this helper before any
358
+ * downstream lookup. Doing the check inline (1) duplicates the regex,
359
+ * (2) silently rejects SuiNS names, (3) makes cache keys inconsistent
360
+ * across tools.
361
+ */
362
+ declare function normalizeAddressInput(value: string, ctx?: {
363
+ suiRpcUrl?: string;
364
+ signal?: AbortSignal;
365
+ }): Promise<NormalizedAddress>;
366
+
226
367
  declare function generateKeypair(): Ed25519Keypair;
227
368
  declare function keypairFromPrivateKey(privateKey: string): Ed25519Keypair;
228
369
  declare function saveKey(keypair: Ed25519Keypair, passphrase: string, keyPath?: string): Promise<string>;
@@ -1347,4 +1488,4 @@ declare function fullHandle(label: string): string;
1347
1488
  */
1348
1489
  declare function displayHandle(label: string): string;
1349
1490
 
1350
- export { AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, type AppenderContext, BalanceResponse, type BorrowInput, BorrowResult, type BuildAddLeafParams, type BuildHarvestRewardsTxOptions, type BuildRevokeLeafParams, type ClaimRewardsInput, ClaimRewardsResult, type CoinPage, type ComposeTxFeeHookContext, type ComposeTxFeeHooks, type ComposeTxOptions, type ComposeTxResult, CompoundRewardsResult, ContactManager, DepositInfo, EarningsResult, FinancialSummary, type FinancialSummaryOptions, FundStatusResult, HF_CRITICAL_THRESHOLD, HF_WARN_THRESHOLD, type HarvestPlan, type HarvestSkippedLeg, type HarvestSwapLeg, HealthFactorResult, type LabelValidationResult, LendingAdapter, LendingRates, MaxBorrowResult, MaxWithdrawResult, OverlayFeeConfig, PayOptions, PayResult, PaymentRequest, PendingReward, PositionsResult, RatesResult, type RepayDebtInput, RepayResult, SPONSORED_PYTH_DEPENDENT_PROVIDERS, SafeguardConfig, SafeguardEnforcer, type SaveDepositInput, SaveResult, type SelectAndSplitResult, SendResult, type SendTransferInput, StakeVSuiResult, type StepPreview, SupportedAsset, type SwapExecuteInput, SwapQuoteResult, SwapResult, SwapRouteResult, T2000, T2000Error, T2000Options, TransactionRecord, TransactionSigner, TxMetadata, UnstakeVSuiResult, VOLO_METADATA, VOLO_PKG, VOLO_POOL, VSUI_TYPE, type VoloStakeInput, type VoloStats, type VoloUnstakeInput, WRITE_APPENDER_REGISTRY, type WithdrawInput, WithdrawResult, type WriteStep, type WriteToolName, ZkLoginProof, addClaimRewardsToTx, addSendToTx, addStakeVSuiToTx, addUnstakeVSuiToTx, aggregateClaimableRewards, buildAddLeafTx, buildClaimRewardsTx, buildHarvestRewardsTx, buildRevokeLeafTx, buildSendTx, buildStakeVSuiTx, buildUnstakeVSuiTx, composeTx, deriveAllowedAddressesFromPtb, displayHandle, exportPrivateKey, fetchAllCoins, fullHandle, generateKeypair, getAddress, getFinancialSummary, getPendingRewards, getPendingRewardsByAddress, getRates, getSponsoredSwapProviders, getSwapQuote, getVoloStats, keypairFromPrivateKey, loadKey, saveKey, selectAndSplitCoin, selectSuiCoin, validateLabel, walletExists };
1491
+ export { AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, type AppenderContext, BalanceResponse, type BorrowInput, BorrowResult, type BuildAddLeafParams, type BuildHarvestRewardsTxOptions, type BuildRevokeLeafParams, type ClaimRewardsInput, ClaimRewardsResult, type CoinPage, type ComposeTxFeeHookContext, type ComposeTxFeeHooks, type ComposeTxOptions, type ComposeTxResult, CompoundRewardsResult, ContactManager, DepositInfo, EarningsResult, FinancialSummary, type FinancialSummaryOptions, FundStatusResult, HF_CRITICAL_THRESHOLD, HF_WARN_THRESHOLD, type HarvestPlan, type HarvestSkippedLeg, type HarvestSwapLeg, HealthFactorResult, InvalidAddressError, type LabelValidationResult, LendingAdapter, LendingRates, MaxBorrowResult, MaxWithdrawResult, type NormalizedAddress, OverlayFeeConfig, PayOptions, PayResult, PaymentRequest, PendingReward, PositionsResult, RatesResult, type RepayDebtInput, RepayResult, SPONSORED_PYTH_DEPENDENT_PROVIDERS, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SafeguardConfig, SafeguardEnforcer, type SaveDepositInput, SaveResult, type SelectAndSplitResult, SendResult, type SendTransferInput, StakeVSuiResult, type StepPreview, SuinsNotRegisteredError, SuinsRpcError, SupportedAsset, type SwapExecuteInput, SwapQuoteResult, SwapResult, SwapRouteResult, T2000, T2000Error, T2000Options, TransactionRecord, TransactionSigner, TxMetadata, UnstakeVSuiResult, VOLO_METADATA, VOLO_PKG, VOLO_POOL, VSUI_TYPE, type VoloStakeInput, type VoloStats, type VoloUnstakeInput, WRITE_APPENDER_REGISTRY, type WithdrawInput, WithdrawResult, type WriteStep, type WriteToolName, ZkLoginProof, addClaimRewardsToTx, addSendToTx, addStakeVSuiToTx, addUnstakeVSuiToTx, aggregateClaimableRewards, buildAddLeafTx, buildClaimRewardsTx, buildHarvestRewardsTx, buildRevokeLeafTx, buildSendTx, buildStakeVSuiTx, buildUnstakeVSuiTx, composeTx, deriveAllowedAddressesFromPtb, displayHandle, exportPrivateKey, fetchAllCoins, fullHandle, generateKeypair, getAddress, getFinancialSummary, getPendingRewards, getPendingRewardsByAddress, getRates, getSponsoredSwapProviders, getSwapQuote, getVoloStats, keypairFromPrivateKey, loadKey, looksLikeSuiNs, normalizeAddressInput, resolveAddressToSuinsViaRpc, resolveSuinsViaRpc, saveKey, selectAndSplitCoin, selectSuiCoin, validateLabel, walletExists };
package/dist/index.js CHANGED
@@ -1799,6 +1799,132 @@ function extractCommands(txBlock) {
1799
1799
  // src/t2000.ts
1800
1800
  init_token_registry();
1801
1801
 
1802
+ // src/utils/suins.ts
1803
+ var SUI_MAINNET_URL = "https://fullnode.mainnet.sui.io:443";
1804
+ var SUI_ADDRESS_REGEX = /^0x[a-fA-F0-9]{1,64}$/i;
1805
+ var SUI_ADDRESS_STRICT_REGEX = /^0x[a-fA-F0-9]{64}$/i;
1806
+ var SUINS_NAME_REGEX = /^[a-z0-9-]+(\.[a-z0-9-]+)*\.sui$/;
1807
+ var InvalidAddressError = class extends Error {
1808
+ constructor(raw) {
1809
+ super(
1810
+ `"${raw}" isn't a valid Sui address or SuiNS name. Pass a 0x-prefixed hex address (e.g. 0x40cd\u20263e62) or a SuiNS name ending in .sui (e.g. alex.sui).`
1811
+ );
1812
+ this.raw = raw;
1813
+ this.name = "InvalidAddressError";
1814
+ }
1815
+ };
1816
+ var SuinsNotRegisteredError = class extends Error {
1817
+ constructor(name_) {
1818
+ super(
1819
+ `"${name_}" isn't a registered SuiNS name. Double-check the spelling, or paste the full Sui address (0x\u2026 64 hex characters).`
1820
+ );
1821
+ this.name_ = name_;
1822
+ this.name = "SuinsNotRegisteredError";
1823
+ }
1824
+ };
1825
+ var SuinsRpcError = class extends Error {
1826
+ constructor(name_, detail) {
1827
+ super(`SuiNS lookup failed for "${name_}" (${detail}). Try again, or paste the full Sui address.`);
1828
+ this.name_ = name_;
1829
+ this.name = "SuinsRpcError";
1830
+ }
1831
+ };
1832
+ function looksLikeSuiNs(value) {
1833
+ if (!value) return false;
1834
+ return SUINS_NAME_REGEX.test(value.trim().toLowerCase());
1835
+ }
1836
+ async function resolveSuinsViaRpc(rawName, ctx = {}) {
1837
+ const name = rawName.trim().toLowerCase();
1838
+ if (!SUINS_NAME_REGEX.test(name)) {
1839
+ throw new InvalidAddressError(rawName);
1840
+ }
1841
+ const url = ctx.suiRpcUrl || SUI_MAINNET_URL;
1842
+ let res;
1843
+ try {
1844
+ res = await fetch(url, {
1845
+ method: "POST",
1846
+ headers: { "Content-Type": "application/json" },
1847
+ body: JSON.stringify({
1848
+ jsonrpc: "2.0",
1849
+ id: 1,
1850
+ method: "suix_resolveNameServiceAddress",
1851
+ params: [name]
1852
+ }),
1853
+ signal: ctx.signal ?? AbortSignal.timeout(8e3)
1854
+ });
1855
+ } catch (err) {
1856
+ const msg = err instanceof Error ? err.message : String(err);
1857
+ throw new SuinsRpcError(name, msg);
1858
+ }
1859
+ if (!res.ok) {
1860
+ throw new SuinsRpcError(name, `HTTP ${res.status}`);
1861
+ }
1862
+ let body;
1863
+ try {
1864
+ body = await res.json();
1865
+ } catch (err) {
1866
+ const msg = err instanceof Error ? err.message : String(err);
1867
+ throw new SuinsRpcError(name, `JSON parse failed: ${msg}`);
1868
+ }
1869
+ if (body.error) {
1870
+ throw new SuinsRpcError(name, body.error.message);
1871
+ }
1872
+ return body.result ?? null;
1873
+ }
1874
+ async function resolveAddressToSuinsViaRpc(rawAddress, ctx = {}) {
1875
+ const address = rawAddress.trim().toLowerCase();
1876
+ if (!SUI_ADDRESS_REGEX.test(address)) {
1877
+ throw new InvalidAddressError(rawAddress);
1878
+ }
1879
+ const url = ctx.suiRpcUrl || SUI_MAINNET_URL;
1880
+ let res;
1881
+ try {
1882
+ res = await fetch(url, {
1883
+ method: "POST",
1884
+ headers: { "Content-Type": "application/json" },
1885
+ body: JSON.stringify({
1886
+ jsonrpc: "2.0",
1887
+ id: 1,
1888
+ method: "suix_resolveNameServiceNames",
1889
+ params: [address]
1890
+ }),
1891
+ signal: ctx.signal ?? AbortSignal.timeout(8e3)
1892
+ });
1893
+ } catch (err) {
1894
+ const msg = err instanceof Error ? err.message : String(err);
1895
+ throw new SuinsRpcError(address, msg);
1896
+ }
1897
+ if (!res.ok) {
1898
+ throw new SuinsRpcError(address, `HTTP ${res.status}`);
1899
+ }
1900
+ let body;
1901
+ try {
1902
+ body = await res.json();
1903
+ } catch (err) {
1904
+ const msg = err instanceof Error ? err.message : String(err);
1905
+ throw new SuinsRpcError(address, `JSON parse failed: ${msg}`);
1906
+ }
1907
+ if (body.error) {
1908
+ throw new SuinsRpcError(address, body.error.message);
1909
+ }
1910
+ return body.result?.data ?? [];
1911
+ }
1912
+ async function normalizeAddressInput(value, ctx = {}) {
1913
+ const trimmed = value.trim();
1914
+ if (SUI_ADDRESS_REGEX.test(trimmed)) {
1915
+ return { address: trimmed.toLowerCase(), suinsName: null, raw: value };
1916
+ }
1917
+ if (looksLikeSuiNs(trimmed)) {
1918
+ const name = trimmed.toLowerCase();
1919
+ const address = await resolveSuinsViaRpc(name, ctx);
1920
+ if (!address) {
1921
+ throw new SuinsNotRegisteredError(name);
1922
+ }
1923
+ return { address: address.toLowerCase(), suinsName: name, raw: value };
1924
+ }
1925
+ throw new InvalidAddressError(value);
1926
+ }
1927
+
1802
1928
  // ../../node_modules/.pnpm/@mysten+bcs@2.0.2/node_modules/@mysten/bcs/dist/uleb.mjs
1803
1929
  function ulebEncode(num) {
1804
1930
  let bigNum = BigInt(num);
@@ -6266,6 +6392,14 @@ var SafeguardEnforcer = class {
6266
6392
  };
6267
6393
  init_errors();
6268
6394
  var RESERVED_NAMES = /* @__PURE__ */ new Set(["to", "all", "address"]);
6395
+ var deprecationWarned = false;
6396
+ function warnContactsDeprecation() {
6397
+ if (deprecationWarned) return;
6398
+ deprecationWarned = true;
6399
+ console.warn(
6400
+ "[t2000] DEPRECATION: ~/.t2000/contacts.json alias resolution is deprecated and will be removed in the next major release. Use SuiNS names instead (e.g. `t2000 send alex.sui 10 USDC`). Register a SuiNS name at https://suins.io if you need a memorable handle."
6401
+ );
6402
+ }
6269
6403
  var ContactManager = class {
6270
6404
  contacts = {};
6271
6405
  filePath;
@@ -6295,6 +6429,7 @@ var ContactManager = class {
6295
6429
  const existed = key in this.contacts;
6296
6430
  this.contacts[key] = { name, address: normalized };
6297
6431
  this.save();
6432
+ warnContactsDeprecation();
6298
6433
  return { action: existed ? "updated" : "added" };
6299
6434
  }
6300
6435
  remove(name) {
@@ -6319,12 +6454,15 @@ var ContactManager = class {
6319
6454
  }
6320
6455
  const contact = this.contacts[nameOrAddress.toLowerCase()];
6321
6456
  if (contact) {
6457
+ warnContactsDeprecation();
6322
6458
  return { address: contact.address, contactName: contact.name };
6323
6459
  }
6324
6460
  throw new T2000Error(
6325
6461
  "CONTACT_NOT_FOUND",
6326
6462
  `"${nameOrAddress}" is not a valid Sui address or saved contact.
6327
- Add it: t2000 contacts add ${nameOrAddress} 0x...`
6463
+ Use a SuiNS name (e.g. alex.sui \u2014 register at https://suins.io)
6464
+ or paste the full Sui address (0x... 64 hex characters).
6465
+ Legacy contact aliases: \`t2000 contacts add ${nameOrAddress} 0x...\` (deprecated).`
6328
6466
  );
6329
6467
  }
6330
6468
  validateName(name) {
@@ -6694,7 +6832,7 @@ var T2000 = class _T2000 extends EventEmitter {
6694
6832
  if (!(asset in SUPPORTED_ASSETS)) {
6695
6833
  throw new T2000Error("ASSET_NOT_SUPPORTED", `Asset ${asset} is not supported`);
6696
6834
  }
6697
- const resolved = this.contacts.resolve(params.to);
6835
+ const resolved = await this.resolveRecipient(params.to);
6698
6836
  const sendAmount = params.amount;
6699
6837
  const sendTo = resolved.address;
6700
6838
  const gasResult = await executeTx(
@@ -6711,11 +6849,63 @@ var T2000 = class _T2000 extends EventEmitter {
6711
6849
  amount: sendAmount,
6712
6850
  to: resolved.address,
6713
6851
  contactName: resolved.contactName,
6852
+ suinsName: resolved.suinsName,
6714
6853
  gasCost: gasResult.gasCostSui,
6715
6854
  gasCostUnit: "SUI",
6716
6855
  balance
6717
6856
  };
6718
6857
  }
6858
+ /**
6859
+ * [S.279 / CLI-CONTACTS-CLEANUP — 2026-05-23] Resolve a recipient
6860
+ * string into a canonical 0x address, trying each shape in priority
6861
+ * order:
6862
+ * 1. **hex** — `0x…` is used directly (no RPC round-trip).
6863
+ * 2. **SuiNS** — `alex.sui` resolves via `suix_resolveNameServiceAddress`.
6864
+ * 3. **saved contact** — `ContactManager.resolve()` falls back to the
6865
+ * legacy `~/.t2000/contacts.json` alias map. Deprecated; the
6866
+ * manager surfaces a one-time `console.warn` when this path fires.
6867
+ *
6868
+ * Returns `{ address, suinsName?, contactName? }` so `send()` can stamp
6869
+ * the name source on the receipt without re-resolving.
6870
+ *
6871
+ * Throws `T2000Error('SUINS_NOT_REGISTERED', …)` for well-formed but
6872
+ * unregistered SuiNS names (vs. propagating the engine-style
6873
+ * `SuinsNotRegisteredError` — keeps the SDK's error surface
6874
+ * `T2000Error`-only, consistent with every other write helper).
6875
+ *
6876
+ * [S.279.1 / 2026-05-23 — patch v2.19.1] Promoted from `private` to
6877
+ * `public` so MCP's `t2000_send` dryRun preview path can share the
6878
+ * same resolution logic as the live execute path. Pre-2.19.1 the
6879
+ * MCP dryRun called `agent.contacts.resolve(to)` directly, which
6880
+ * rejected SuiNS names — preview-then-execute flows broke for
6881
+ * `alex.sui`-style recipients. SSOT: never let preview and execute
6882
+ * resolve the same input differently.
6883
+ */
6884
+ async resolveRecipient(input) {
6885
+ const trimmed = input.trim();
6886
+ if (SUI_ADDRESS_REGEX.test(trimmed)) {
6887
+ return { address: trimmed.toLowerCase() };
6888
+ }
6889
+ if (looksLikeSuiNs(trimmed)) {
6890
+ try {
6891
+ const name = trimmed.toLowerCase();
6892
+ const address = await resolveSuinsViaRpc(name);
6893
+ if (!address) {
6894
+ throw new SuinsNotRegisteredError(name);
6895
+ }
6896
+ return { address: address.toLowerCase(), suinsName: name };
6897
+ } catch (err) {
6898
+ if (err instanceof SuinsNotRegisteredError) {
6899
+ throw new T2000Error(
6900
+ "SUINS_NOT_REGISTERED",
6901
+ err.message
6902
+ );
6903
+ }
6904
+ throw err;
6905
+ }
6906
+ }
6907
+ return this.contacts.resolve(input);
6908
+ }
6719
6909
  async balance() {
6720
6910
  const bal = await queryBalance(this.client, this._address);
6721
6911
  let chainTotal = bal.available + bal.gasReserve.usdEquiv;
@@ -8379,6 +8569,6 @@ function displayHandle(label) {
8379
8569
  (*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
8380
8570
  */
8381
8571
 
8382
- export { ALL_NAVI_ASSETS, AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, BORROW_FEE_BPS, BPS_DENOMINATOR, CETUS_USDC_SUI_POOL, CLOCK_ID, COIN_REGISTRY, ContactManager, DEFAULT_NETWORK, DEFAULT_SAFEGUARD_CONFIG, ETH_TYPE, GAS_RESERVE_MIN, HF_CRITICAL_THRESHOLD, HF_WARN_THRESHOLD, IKA_TYPE, KNOWN_TARGETS, KeypairSigner, LABEL_PATTERNS, LOFI_TYPE, MANIFEST_TYPE, MIST_PER_SUI, NAVX_TYPE, NaviAdapter, OPERATION_ASSETS, OUTBOUND_OPS, OVERLAY_FEE_RATE, ProtocolRegistry, SAVE_FEE_BPS, SPONSORED_PYTH_DEPENDENT_PROVIDERS, STABLE_ASSETS, SUI_DECIMALS, SUI_TYPE, SUPPORTED_ASSETS, SafeguardEnforcer, SafeguardError, T2000, T2000Error, T2000_OVERLAY_FEE_WALLET, TOKEN_MAP, USDC_DECIMALS, USDC_TYPE, USDE_TYPE, USDSUI_TYPE, USDT_TYPE, VOLO_METADATA, VOLO_PKG, VOLO_POOL, VSUI_TYPE, WAL_TYPE, WBTC_TYPE, WRITE_APPENDER_REGISTRY, ZkLoginSigner, addClaimRewardsToTx, addFeeTransfer, addSendToTx, addStakeVSuiToTx, addSwapToTx, addUnstakeVSuiToTx, aggregateClaimableRewards, allDescriptors, assertAllowedAsset, buildAddLeafTx, buildClaimRewardsTx, buildHarvestRewardsTx, buildRevokeLeafTx, buildSendTx, buildStakeVSuiTx, buildSwapTx, buildUnstakeVSuiTx, calculateFee, classifyAction, classifyLabel, classifyTransaction, composeTx, deriveAllowedAddressesFromPtb, deserializeCetusRoute, displayHandle, exportPrivateKey, extractAllUserLegs, extractTransferDetails, extractTxCommands, extractTxSender, fallbackLabel, fetchAllCoins, findSwapRoute, formatAssetAmount, formatSui, formatUsd, fullHandle, generateKeypair, getAddress, getCoinMeta, getDecimals, getDecimalsForCoinType, getFinancialSummary, getPendingRewards, getPendingRewardsByAddress, getRates, getSponsoredSwapProviders, getSwapQuote, getTier, getVoloStats, isAllowedAsset, isCetusRouteFresh, isInRegistry, isSupported, isTier1, isTier2, keypairFromPrivateKey, loadKey, mapMoveAbortCode, mapWalletError, mistToSui, naviDescriptor, normalizeAsset, normalizeCoinType, parseSuiRpcTx, queryHistory, queryTransaction, rawToStable, rawToUsdc, refineLendingLabel, resolveSymbol, resolveTokenType, saveKey, selectAndSplitCoin, selectSuiCoin, serializeCetusRoute, simulateTransaction, stableToRaw, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, validateLabel, verifyCetusRouteCoinMatch, walletExists };
8572
+ export { ALL_NAVI_ASSETS, AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, BORROW_FEE_BPS, BPS_DENOMINATOR, CETUS_USDC_SUI_POOL, CLOCK_ID, COIN_REGISTRY, ContactManager, DEFAULT_NETWORK, DEFAULT_SAFEGUARD_CONFIG, ETH_TYPE, GAS_RESERVE_MIN, HF_CRITICAL_THRESHOLD, HF_WARN_THRESHOLD, IKA_TYPE, InvalidAddressError, KNOWN_TARGETS, KeypairSigner, LABEL_PATTERNS, LOFI_TYPE, MANIFEST_TYPE, MIST_PER_SUI, NAVX_TYPE, NaviAdapter, OPERATION_ASSETS, OUTBOUND_OPS, OVERLAY_FEE_RATE, ProtocolRegistry, SAVE_FEE_BPS, SPONSORED_PYTH_DEPENDENT_PROVIDERS, STABLE_ASSETS, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SUI_DECIMALS, SUI_TYPE, SUPPORTED_ASSETS, SafeguardEnforcer, SafeguardError, SuinsNotRegisteredError, SuinsRpcError, T2000, T2000Error, T2000_OVERLAY_FEE_WALLET, TOKEN_MAP, USDC_DECIMALS, USDC_TYPE, USDE_TYPE, USDSUI_TYPE, USDT_TYPE, VOLO_METADATA, VOLO_PKG, VOLO_POOL, VSUI_TYPE, WAL_TYPE, WBTC_TYPE, WRITE_APPENDER_REGISTRY, ZkLoginSigner, addClaimRewardsToTx, addFeeTransfer, addSendToTx, addStakeVSuiToTx, addSwapToTx, addUnstakeVSuiToTx, aggregateClaimableRewards, allDescriptors, assertAllowedAsset, buildAddLeafTx, buildClaimRewardsTx, buildHarvestRewardsTx, buildRevokeLeafTx, buildSendTx, buildStakeVSuiTx, buildSwapTx, buildUnstakeVSuiTx, calculateFee, classifyAction, classifyLabel, classifyTransaction, composeTx, deriveAllowedAddressesFromPtb, deserializeCetusRoute, displayHandle, exportPrivateKey, extractAllUserLegs, extractTransferDetails, extractTxCommands, extractTxSender, fallbackLabel, fetchAllCoins, findSwapRoute, formatAssetAmount, formatSui, formatUsd, fullHandle, generateKeypair, getAddress, getCoinMeta, getDecimals, getDecimalsForCoinType, getFinancialSummary, getPendingRewards, getPendingRewardsByAddress, getRates, getSponsoredSwapProviders, getSwapQuote, getTier, getVoloStats, isAllowedAsset, isCetusRouteFresh, isInRegistry, isSupported, isTier1, isTier2, keypairFromPrivateKey, loadKey, looksLikeSuiNs, mapMoveAbortCode, mapWalletError, mistToSui, naviDescriptor, normalizeAddressInput, normalizeAsset, normalizeCoinType, parseSuiRpcTx, queryHistory, queryTransaction, rawToStable, rawToUsdc, refineLendingLabel, resolveAddressToSuinsViaRpc, resolveSuinsViaRpc, resolveSymbol, resolveTokenType, saveKey, selectAndSplitCoin, selectSuiCoin, serializeCetusRoute, simulateTransaction, stableToRaw, suiToMist, throwIfSimulationFailed, truncateAddress, usdcToRaw, validateAddress, validateLabel, verifyCetusRouteCoinMatch, walletExists };
8383
8573
  //# sourceMappingURL=index.js.map
8384
8574
  //# sourceMappingURL=index.js.map