@t2000/cli 2.18.0 → 2.19.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.
@@ -17575,6 +17575,130 @@ function extractCommands(txBlock) {
17575
17575
  return result;
17576
17576
  }
17577
17577
  init_token_registry();
17578
+ var SUI_MAINNET_URL = "https://fullnode.mainnet.sui.io:443";
17579
+ var SUI_ADDRESS_REGEX = /^0x[a-fA-F0-9]{1,64}$/i;
17580
+ var SUI_ADDRESS_STRICT_REGEX = /^0x[a-fA-F0-9]{64}$/i;
17581
+ var SUINS_NAME_REGEX = /^[a-z0-9-]+(\.[a-z0-9-]+)*\.sui$/;
17582
+ var InvalidAddressError = class extends Error {
17583
+ constructor(raw) {
17584
+ super(
17585
+ `"${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).`
17586
+ );
17587
+ this.raw = raw;
17588
+ this.name = "InvalidAddressError";
17589
+ }
17590
+ };
17591
+ var SuinsNotRegisteredError = class extends Error {
17592
+ constructor(name_) {
17593
+ super(
17594
+ `"${name_}" isn't a registered SuiNS name. Double-check the spelling, or paste the full Sui address (0x\u2026 64 hex characters).`
17595
+ );
17596
+ this.name_ = name_;
17597
+ this.name = "SuinsNotRegisteredError";
17598
+ }
17599
+ };
17600
+ var SuinsRpcError = class extends Error {
17601
+ constructor(name_, detail) {
17602
+ super(`SuiNS lookup failed for "${name_}" (${detail}). Try again, or paste the full Sui address.`);
17603
+ this.name_ = name_;
17604
+ this.name = "SuinsRpcError";
17605
+ }
17606
+ };
17607
+ function looksLikeSuiNs(value) {
17608
+ if (!value) return false;
17609
+ return SUINS_NAME_REGEX.test(value.trim().toLowerCase());
17610
+ }
17611
+ async function resolveSuinsViaRpc(rawName, ctx = {}) {
17612
+ const name = rawName.trim().toLowerCase();
17613
+ if (!SUINS_NAME_REGEX.test(name)) {
17614
+ throw new InvalidAddressError(rawName);
17615
+ }
17616
+ const url = ctx.suiRpcUrl || SUI_MAINNET_URL;
17617
+ let res;
17618
+ try {
17619
+ res = await fetch(url, {
17620
+ method: "POST",
17621
+ headers: { "Content-Type": "application/json" },
17622
+ body: JSON.stringify({
17623
+ jsonrpc: "2.0",
17624
+ id: 1,
17625
+ method: "suix_resolveNameServiceAddress",
17626
+ params: [name]
17627
+ }),
17628
+ signal: ctx.signal ?? AbortSignal.timeout(8e3)
17629
+ });
17630
+ } catch (err) {
17631
+ const msg = err instanceof Error ? err.message : String(err);
17632
+ throw new SuinsRpcError(name, msg);
17633
+ }
17634
+ if (!res.ok) {
17635
+ throw new SuinsRpcError(name, `HTTP ${res.status}`);
17636
+ }
17637
+ let body;
17638
+ try {
17639
+ body = await res.json();
17640
+ } catch (err) {
17641
+ const msg = err instanceof Error ? err.message : String(err);
17642
+ throw new SuinsRpcError(name, `JSON parse failed: ${msg}`);
17643
+ }
17644
+ if (body.error) {
17645
+ throw new SuinsRpcError(name, body.error.message);
17646
+ }
17647
+ return body.result ?? null;
17648
+ }
17649
+ async function resolveAddressToSuinsViaRpc(rawAddress, ctx = {}) {
17650
+ const address = rawAddress.trim().toLowerCase();
17651
+ if (!SUI_ADDRESS_REGEX.test(address)) {
17652
+ throw new InvalidAddressError(rawAddress);
17653
+ }
17654
+ const url = ctx.suiRpcUrl || SUI_MAINNET_URL;
17655
+ let res;
17656
+ try {
17657
+ res = await fetch(url, {
17658
+ method: "POST",
17659
+ headers: { "Content-Type": "application/json" },
17660
+ body: JSON.stringify({
17661
+ jsonrpc: "2.0",
17662
+ id: 1,
17663
+ method: "suix_resolveNameServiceNames",
17664
+ params: [address]
17665
+ }),
17666
+ signal: ctx.signal ?? AbortSignal.timeout(8e3)
17667
+ });
17668
+ } catch (err) {
17669
+ const msg = err instanceof Error ? err.message : String(err);
17670
+ throw new SuinsRpcError(address, msg);
17671
+ }
17672
+ if (!res.ok) {
17673
+ throw new SuinsRpcError(address, `HTTP ${res.status}`);
17674
+ }
17675
+ let body;
17676
+ try {
17677
+ body = await res.json();
17678
+ } catch (err) {
17679
+ const msg = err instanceof Error ? err.message : String(err);
17680
+ throw new SuinsRpcError(address, `JSON parse failed: ${msg}`);
17681
+ }
17682
+ if (body.error) {
17683
+ throw new SuinsRpcError(address, body.error.message);
17684
+ }
17685
+ return body.result?.data ?? [];
17686
+ }
17687
+ async function normalizeAddressInput(value, ctx = {}) {
17688
+ const trimmed = value.trim();
17689
+ if (SUI_ADDRESS_REGEX.test(trimmed)) {
17690
+ return { address: trimmed.toLowerCase(), suinsName: null, raw: value };
17691
+ }
17692
+ if (looksLikeSuiNs(trimmed)) {
17693
+ const name = trimmed.toLowerCase();
17694
+ const address = await resolveSuinsViaRpc(name, ctx);
17695
+ if (!address) {
17696
+ throw new SuinsNotRegisteredError(name);
17697
+ }
17698
+ return { address: address.toLowerCase(), suinsName: name, raw: value };
17699
+ }
17700
+ throw new InvalidAddressError(value);
17701
+ }
17578
17702
  function ulebEncode(num) {
17579
17703
  let bigNum = BigInt(num);
17580
17704
  const arr = [];
@@ -21999,6 +22123,14 @@ var SafeguardEnforcer = class {
21999
22123
  };
22000
22124
  init_errors();
22001
22125
  var RESERVED_NAMES = /* @__PURE__ */ new Set(["to", "all", "address"]);
22126
+ var deprecationWarned = false;
22127
+ function warnContactsDeprecation() {
22128
+ if (deprecationWarned) return;
22129
+ deprecationWarned = true;
22130
+ console.warn(
22131
+ "[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."
22132
+ );
22133
+ }
22002
22134
  var ContactManager = class {
22003
22135
  contacts = {};
22004
22136
  filePath;
@@ -22052,12 +22184,15 @@ var ContactManager = class {
22052
22184
  }
22053
22185
  const contact = this.contacts[nameOrAddress.toLowerCase()];
22054
22186
  if (contact) {
22187
+ warnContactsDeprecation();
22055
22188
  return { address: contact.address, contactName: contact.name };
22056
22189
  }
22057
22190
  throw new T2000Error(
22058
22191
  "CONTACT_NOT_FOUND",
22059
22192
  `"${nameOrAddress}" is not a valid Sui address or saved contact.
22060
- Add it: t2000 contacts add ${nameOrAddress} 0x...`
22193
+ Use a SuiNS name (e.g. alex.sui \u2014 register at https://suins.io)
22194
+ or paste the full Sui address (0x... 64 hex characters).
22195
+ Legacy contact aliases: \`t2000 contacts add ${nameOrAddress} 0x...\` (deprecated).`
22061
22196
  );
22062
22197
  }
22063
22198
  validateName(name) {
@@ -22427,7 +22562,7 @@ var T2000 = class _T2000 extends import_index.default {
22427
22562
  if (!(asset in SUPPORTED_ASSETS)) {
22428
22563
  throw new T2000Error("ASSET_NOT_SUPPORTED", `Asset ${asset} is not supported`);
22429
22564
  }
22430
- const resolved = this.contacts.resolve(params.to);
22565
+ const resolved = await this.resolveRecipient(params.to);
22431
22566
  const sendAmount = params.amount;
22432
22567
  const sendTo = resolved.address;
22433
22568
  const gasResult = await executeTx(
@@ -22444,11 +22579,55 @@ var T2000 = class _T2000 extends import_index.default {
22444
22579
  amount: sendAmount,
22445
22580
  to: resolved.address,
22446
22581
  contactName: resolved.contactName,
22582
+ suinsName: resolved.suinsName,
22447
22583
  gasCost: gasResult.gasCostSui,
22448
22584
  gasCostUnit: "SUI",
22449
22585
  balance
22450
22586
  };
22451
22587
  }
22588
+ /**
22589
+ * [S.279 / CLI-CONTACTS-CLEANUP — 2026-05-23] Resolve a recipient
22590
+ * string into a canonical 0x address, trying each shape in priority
22591
+ * order:
22592
+ * 1. **hex** — `0x…` is used directly (no RPC round-trip).
22593
+ * 2. **SuiNS** — `alex.sui` resolves via `suix_resolveNameServiceAddress`.
22594
+ * 3. **saved contact** — `ContactManager.resolve()` falls back to the
22595
+ * legacy `~/.t2000/contacts.json` alias map. Deprecated; the
22596
+ * manager surfaces a one-time `console.warn` when this path fires.
22597
+ *
22598
+ * Returns `{ address, suinsName?, contactName? }` so `send()` can stamp
22599
+ * the name source on the receipt without re-resolving.
22600
+ *
22601
+ * Throws `T2000Error('SUINS_NOT_REGISTERED', …)` for well-formed but
22602
+ * unregistered SuiNS names (vs. propagating the engine-style
22603
+ * `SuinsNotRegisteredError` — keeps the SDK's error surface
22604
+ * `T2000Error`-only, consistent with every other write helper).
22605
+ */
22606
+ async resolveRecipient(input) {
22607
+ const trimmed = input.trim();
22608
+ if (SUI_ADDRESS_REGEX.test(trimmed)) {
22609
+ return { address: trimmed.toLowerCase() };
22610
+ }
22611
+ if (looksLikeSuiNs(trimmed)) {
22612
+ try {
22613
+ const name = trimmed.toLowerCase();
22614
+ const address = await resolveSuinsViaRpc(name);
22615
+ if (!address) {
22616
+ throw new SuinsNotRegisteredError(name);
22617
+ }
22618
+ return { address: address.toLowerCase(), suinsName: name };
22619
+ } catch (err) {
22620
+ if (err instanceof SuinsNotRegisteredError) {
22621
+ throw new T2000Error(
22622
+ "SUINS_NOT_REGISTERED",
22623
+ err.message
22624
+ );
22625
+ }
22626
+ throw err;
22627
+ }
22628
+ }
22629
+ return this.contacts.resolve(input);
22630
+ }
22452
22631
  async balance() {
22453
22632
  const bal = await queryBalance(this.client, this._address);
22454
22633
  let chainTotal = bal.available + bal.gasReserve.usdEquiv;
@@ -24196,6 +24375,16 @@ export {
24196
24375
  parseSuiRpcTx,
24197
24376
  extractTxSender,
24198
24377
  extractTxCommands,
24378
+ SUI_ADDRESS_REGEX,
24379
+ SUI_ADDRESS_STRICT_REGEX,
24380
+ SUINS_NAME_REGEX,
24381
+ InvalidAddressError,
24382
+ SuinsNotRegisteredError,
24383
+ SuinsRpcError,
24384
+ looksLikeSuiNs,
24385
+ resolveSuinsViaRpc,
24386
+ resolveAddressToSuinsViaRpc,
24387
+ normalizeAddressInput,
24199
24388
  getRates,
24200
24389
  getPendingRewardsByAddress,
24201
24390
  getPendingRewards,
@@ -24257,4 +24446,4 @@ axios/dist/node/axios.cjs:
24257
24446
  @scure/bip39/index.js:
24258
24447
  (*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
24259
24448
  */
24260
- //# sourceMappingURL=chunk-ZNZ4MOY2.js.map
24449
+ //# sourceMappingURL=chunk-2TOYZOH3.js.map