@t2000/cli 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/README.md +7 -3
- package/dist/{chunk-ZNZ4MOY2.js → chunk-R7KXQRHQ.js} +201 -3
- package/dist/chunk-R7KXQRHQ.js.map +1 -0
- package/dist/{dist-EFTMN6BY.js → dist-A7D5R6SM.js} +22 -2
- package/dist/{dist-APKOY2VV.js → dist-EUGE6UAA.js} +145 -10
- package/dist/{dist-APKOY2VV.js.map → dist-EUGE6UAA.js.map} +1 -1
- package/dist/index.js +13 -6
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-ZNZ4MOY2.js.map +0 -1
- /package/dist/{dist-EFTMN6BY.js.map → dist-A7D5R6SM.js.map} +0 -0
package/README.md
CHANGED
|
@@ -180,14 +180,18 @@ t2000 init
|
|
|
180
180
|
|---------|-------------|
|
|
181
181
|
| `t2000 earn` | Show all earning opportunities — savings yield |
|
|
182
182
|
|
|
183
|
-
### Contacts
|
|
183
|
+
### Contacts (DEPRECATED — sunset in next major)
|
|
184
|
+
|
|
185
|
+
The local `~/.t2000/contacts.json` alias map is being retired. **Use SuiNS instead**: register `your-name.sui` once at https://suins.io and every Sui app — including `t2000 send` — resolves it automatically. The first time a process resolves or writes a legacy contact alias, the CLI prints a one-shot deprecation warning to stderr.
|
|
184
186
|
|
|
185
187
|
| Command | Description |
|
|
186
188
|
|---------|-------------|
|
|
187
|
-
| `t2000 contacts` | List saved contacts |
|
|
188
|
-
| `t2000 contacts add <name> <address>` | Save a named contact |
|
|
189
|
+
| `t2000 contacts` | List saved contacts (deprecated) |
|
|
190
|
+
| `t2000 contacts add <name> <address>` | Save a named contact (deprecated; warns once) |
|
|
189
191
|
| `t2000 contacts remove <name>` | Remove a contact |
|
|
190
192
|
|
|
193
|
+
`t2000 send` accepts SuiNS names natively — `t2000 send 10 USDC to alex.sui` works with no setup. Priority order for the recipient argument: `0x` address > SuiNS name > saved contact alias.
|
|
194
|
+
|
|
191
195
|
### Safeguards
|
|
192
196
|
|
|
193
197
|
| Command | Description |
|
|
@@ -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;
|
|
@@ -22028,6 +22160,7 @@ var ContactManager = class {
|
|
|
22028
22160
|
const existed = key in this.contacts;
|
|
22029
22161
|
this.contacts[key] = { name, address: normalized };
|
|
22030
22162
|
this.save();
|
|
22163
|
+
warnContactsDeprecation();
|
|
22031
22164
|
return { action: existed ? "updated" : "added" };
|
|
22032
22165
|
}
|
|
22033
22166
|
remove(name) {
|
|
@@ -22052,12 +22185,15 @@ var ContactManager = class {
|
|
|
22052
22185
|
}
|
|
22053
22186
|
const contact = this.contacts[nameOrAddress.toLowerCase()];
|
|
22054
22187
|
if (contact) {
|
|
22188
|
+
warnContactsDeprecation();
|
|
22055
22189
|
return { address: contact.address, contactName: contact.name };
|
|
22056
22190
|
}
|
|
22057
22191
|
throw new T2000Error(
|
|
22058
22192
|
"CONTACT_NOT_FOUND",
|
|
22059
22193
|
`"${nameOrAddress}" is not a valid Sui address or saved contact.
|
|
22060
|
-
|
|
22194
|
+
Use a SuiNS name (e.g. alex.sui \u2014 register at https://suins.io)
|
|
22195
|
+
or paste the full Sui address (0x... 64 hex characters).
|
|
22196
|
+
Legacy contact aliases: \`t2000 contacts add ${nameOrAddress} 0x...\` (deprecated).`
|
|
22061
22197
|
);
|
|
22062
22198
|
}
|
|
22063
22199
|
validateName(name) {
|
|
@@ -22427,7 +22563,7 @@ var T2000 = class _T2000 extends import_index.default {
|
|
|
22427
22563
|
if (!(asset in SUPPORTED_ASSETS)) {
|
|
22428
22564
|
throw new T2000Error("ASSET_NOT_SUPPORTED", `Asset ${asset} is not supported`);
|
|
22429
22565
|
}
|
|
22430
|
-
const resolved = this.
|
|
22566
|
+
const resolved = await this.resolveRecipient(params.to);
|
|
22431
22567
|
const sendAmount = params.amount;
|
|
22432
22568
|
const sendTo = resolved.address;
|
|
22433
22569
|
const gasResult = await executeTx(
|
|
@@ -22444,11 +22580,63 @@ var T2000 = class _T2000 extends import_index.default {
|
|
|
22444
22580
|
amount: sendAmount,
|
|
22445
22581
|
to: resolved.address,
|
|
22446
22582
|
contactName: resolved.contactName,
|
|
22583
|
+
suinsName: resolved.suinsName,
|
|
22447
22584
|
gasCost: gasResult.gasCostSui,
|
|
22448
22585
|
gasCostUnit: "SUI",
|
|
22449
22586
|
balance
|
|
22450
22587
|
};
|
|
22451
22588
|
}
|
|
22589
|
+
/**
|
|
22590
|
+
* [S.279 / CLI-CONTACTS-CLEANUP — 2026-05-23] Resolve a recipient
|
|
22591
|
+
* string into a canonical 0x address, trying each shape in priority
|
|
22592
|
+
* order:
|
|
22593
|
+
* 1. **hex** — `0x…` is used directly (no RPC round-trip).
|
|
22594
|
+
* 2. **SuiNS** — `alex.sui` resolves via `suix_resolveNameServiceAddress`.
|
|
22595
|
+
* 3. **saved contact** — `ContactManager.resolve()` falls back to the
|
|
22596
|
+
* legacy `~/.t2000/contacts.json` alias map. Deprecated; the
|
|
22597
|
+
* manager surfaces a one-time `console.warn` when this path fires.
|
|
22598
|
+
*
|
|
22599
|
+
* Returns `{ address, suinsName?, contactName? }` so `send()` can stamp
|
|
22600
|
+
* the name source on the receipt without re-resolving.
|
|
22601
|
+
*
|
|
22602
|
+
* Throws `T2000Error('SUINS_NOT_REGISTERED', …)` for well-formed but
|
|
22603
|
+
* unregistered SuiNS names (vs. propagating the engine-style
|
|
22604
|
+
* `SuinsNotRegisteredError` — keeps the SDK's error surface
|
|
22605
|
+
* `T2000Error`-only, consistent with every other write helper).
|
|
22606
|
+
*
|
|
22607
|
+
* [S.279.1 / 2026-05-23 — patch v2.19.1] Promoted from `private` to
|
|
22608
|
+
* `public` so MCP's `t2000_send` dryRun preview path can share the
|
|
22609
|
+
* same resolution logic as the live execute path. Pre-2.19.1 the
|
|
22610
|
+
* MCP dryRun called `agent.contacts.resolve(to)` directly, which
|
|
22611
|
+
* rejected SuiNS names — preview-then-execute flows broke for
|
|
22612
|
+
* `alex.sui`-style recipients. SSOT: never let preview and execute
|
|
22613
|
+
* resolve the same input differently.
|
|
22614
|
+
*/
|
|
22615
|
+
async resolveRecipient(input) {
|
|
22616
|
+
const trimmed = input.trim();
|
|
22617
|
+
if (SUI_ADDRESS_REGEX.test(trimmed)) {
|
|
22618
|
+
return { address: trimmed.toLowerCase() };
|
|
22619
|
+
}
|
|
22620
|
+
if (looksLikeSuiNs(trimmed)) {
|
|
22621
|
+
try {
|
|
22622
|
+
const name = trimmed.toLowerCase();
|
|
22623
|
+
const address = await resolveSuinsViaRpc(name);
|
|
22624
|
+
if (!address) {
|
|
22625
|
+
throw new SuinsNotRegisteredError(name);
|
|
22626
|
+
}
|
|
22627
|
+
return { address: address.toLowerCase(), suinsName: name };
|
|
22628
|
+
} catch (err) {
|
|
22629
|
+
if (err instanceof SuinsNotRegisteredError) {
|
|
22630
|
+
throw new T2000Error(
|
|
22631
|
+
"SUINS_NOT_REGISTERED",
|
|
22632
|
+
err.message
|
|
22633
|
+
);
|
|
22634
|
+
}
|
|
22635
|
+
throw err;
|
|
22636
|
+
}
|
|
22637
|
+
}
|
|
22638
|
+
return this.contacts.resolve(input);
|
|
22639
|
+
}
|
|
22452
22640
|
async balance() {
|
|
22453
22641
|
const bal = await queryBalance(this.client, this._address);
|
|
22454
22642
|
let chainTotal = bal.available + bal.gasReserve.usdEquiv;
|
|
@@ -24196,6 +24384,16 @@ export {
|
|
|
24196
24384
|
parseSuiRpcTx,
|
|
24197
24385
|
extractTxSender,
|
|
24198
24386
|
extractTxCommands,
|
|
24387
|
+
SUI_ADDRESS_REGEX,
|
|
24388
|
+
SUI_ADDRESS_STRICT_REGEX,
|
|
24389
|
+
SUINS_NAME_REGEX,
|
|
24390
|
+
InvalidAddressError,
|
|
24391
|
+
SuinsNotRegisteredError,
|
|
24392
|
+
SuinsRpcError,
|
|
24393
|
+
looksLikeSuiNs,
|
|
24394
|
+
resolveSuinsViaRpc,
|
|
24395
|
+
resolveAddressToSuinsViaRpc,
|
|
24396
|
+
normalizeAddressInput,
|
|
24199
24397
|
getRates,
|
|
24200
24398
|
getPendingRewardsByAddress,
|
|
24201
24399
|
getPendingRewards,
|
|
@@ -24257,4 +24455,4 @@ axios/dist/node/axios.cjs:
|
|
|
24257
24455
|
@scure/bip39/index.js:
|
|
24258
24456
|
(*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
|
|
24259
24457
|
*/
|
|
24260
|
-
//# sourceMappingURL=chunk-
|
|
24458
|
+
//# sourceMappingURL=chunk-R7KXQRHQ.js.map
|