@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
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
HF_CRITICAL_THRESHOLD,
|
|
17
17
|
HF_WARN_THRESHOLD,
|
|
18
18
|
IKA_TYPE,
|
|
19
|
+
InvalidAddressError,
|
|
19
20
|
KNOWN_TARGETS,
|
|
20
21
|
KeypairSigner,
|
|
21
22
|
LABEL_PATTERNS,
|
|
@@ -31,11 +32,16 @@ import {
|
|
|
31
32
|
SAVE_FEE_BPS,
|
|
32
33
|
SPONSORED_PYTH_DEPENDENT_PROVIDERS,
|
|
33
34
|
STABLE_ASSETS,
|
|
35
|
+
SUINS_NAME_REGEX,
|
|
36
|
+
SUI_ADDRESS_REGEX,
|
|
37
|
+
SUI_ADDRESS_STRICT_REGEX,
|
|
34
38
|
SUI_DECIMALS,
|
|
35
39
|
SUI_TYPE,
|
|
36
40
|
SUPPORTED_ASSETS,
|
|
37
41
|
SafeguardEnforcer,
|
|
38
42
|
SafeguardError,
|
|
43
|
+
SuinsNotRegisteredError,
|
|
44
|
+
SuinsRpcError,
|
|
39
45
|
T2000,
|
|
40
46
|
T2000Error,
|
|
41
47
|
T2000_OVERLAY_FEE_WALLET,
|
|
@@ -111,10 +117,12 @@ import {
|
|
|
111
117
|
isTier2,
|
|
112
118
|
keypairFromPrivateKey,
|
|
113
119
|
loadKey,
|
|
120
|
+
looksLikeSuiNs,
|
|
114
121
|
mapMoveAbortCode,
|
|
115
122
|
mapWalletError,
|
|
116
123
|
mistToSui,
|
|
117
124
|
naviDescriptor,
|
|
125
|
+
normalizeAddressInput,
|
|
118
126
|
normalizeAsset,
|
|
119
127
|
normalizeCoinType,
|
|
120
128
|
parseSuiRpcTx,
|
|
@@ -123,6 +131,8 @@ import {
|
|
|
123
131
|
rawToStable,
|
|
124
132
|
rawToUsdc,
|
|
125
133
|
refineLendingLabel,
|
|
134
|
+
resolveAddressToSuinsViaRpc,
|
|
135
|
+
resolveSuinsViaRpc,
|
|
126
136
|
resolveSymbol,
|
|
127
137
|
resolveTokenType,
|
|
128
138
|
saveKey,
|
|
@@ -139,7 +149,7 @@ import {
|
|
|
139
149
|
validateLabel,
|
|
140
150
|
verifyCetusRouteCoinMatch,
|
|
141
151
|
walletExists
|
|
142
|
-
} from "./chunk-
|
|
152
|
+
} from "./chunk-R7KXQRHQ.js";
|
|
143
153
|
import "./chunk-ZRPJE7U5.js";
|
|
144
154
|
import "./chunk-OCLKPYUU.js";
|
|
145
155
|
import "./chunk-SI54PO2N.js";
|
|
@@ -167,6 +177,7 @@ export {
|
|
|
167
177
|
HF_CRITICAL_THRESHOLD,
|
|
168
178
|
HF_WARN_THRESHOLD,
|
|
169
179
|
IKA_TYPE,
|
|
180
|
+
InvalidAddressError,
|
|
170
181
|
KNOWN_TARGETS,
|
|
171
182
|
KeypairSigner,
|
|
172
183
|
LABEL_PATTERNS,
|
|
@@ -182,11 +193,16 @@ export {
|
|
|
182
193
|
SAVE_FEE_BPS,
|
|
183
194
|
SPONSORED_PYTH_DEPENDENT_PROVIDERS,
|
|
184
195
|
STABLE_ASSETS,
|
|
196
|
+
SUINS_NAME_REGEX,
|
|
197
|
+
SUI_ADDRESS_REGEX,
|
|
198
|
+
SUI_ADDRESS_STRICT_REGEX,
|
|
185
199
|
SUI_DECIMALS,
|
|
186
200
|
SUI_TYPE,
|
|
187
201
|
SUPPORTED_ASSETS,
|
|
188
202
|
SafeguardEnforcer,
|
|
189
203
|
SafeguardError,
|
|
204
|
+
SuinsNotRegisteredError,
|
|
205
|
+
SuinsRpcError,
|
|
190
206
|
T2000,
|
|
191
207
|
T2000Error,
|
|
192
208
|
T2000_OVERLAY_FEE_WALLET,
|
|
@@ -262,10 +278,12 @@ export {
|
|
|
262
278
|
isTier2,
|
|
263
279
|
keypairFromPrivateKey,
|
|
264
280
|
loadKey,
|
|
281
|
+
looksLikeSuiNs,
|
|
265
282
|
mapMoveAbortCode,
|
|
266
283
|
mapWalletError,
|
|
267
284
|
mistToSui,
|
|
268
285
|
naviDescriptor,
|
|
286
|
+
normalizeAddressInput,
|
|
269
287
|
normalizeAsset,
|
|
270
288
|
normalizeCoinType,
|
|
271
289
|
parseSuiRpcTx,
|
|
@@ -274,6 +292,8 @@ export {
|
|
|
274
292
|
rawToStable,
|
|
275
293
|
rawToUsdc,
|
|
276
294
|
refineLendingLabel,
|
|
295
|
+
resolveAddressToSuinsViaRpc,
|
|
296
|
+
resolveSuinsViaRpc,
|
|
277
297
|
resolveSymbol,
|
|
278
298
|
resolveTokenType,
|
|
279
299
|
saveKey,
|
|
@@ -291,4 +311,4 @@ export {
|
|
|
291
311
|
verifyCetusRouteCoinMatch,
|
|
292
312
|
walletExists
|
|
293
313
|
};
|
|
294
|
-
//# sourceMappingURL=dist-
|
|
314
|
+
//# sourceMappingURL=dist-A7D5R6SM.js.map
|
|
@@ -134943,6 +134943,76 @@ function extractCommands(txBlock) {
|
|
|
134943
134943
|
return result;
|
|
134944
134944
|
}
|
|
134945
134945
|
init_token_registry();
|
|
134946
|
+
var SUI_MAINNET_URL = "https://fullnode.mainnet.sui.io:443";
|
|
134947
|
+
var SUI_ADDRESS_REGEX = /^0x[a-fA-F0-9]{1,64}$/i;
|
|
134948
|
+
var SUINS_NAME_REGEX = /^[a-z0-9-]+(\.[a-z0-9-]+)*\.sui$/;
|
|
134949
|
+
var InvalidAddressError4 = class extends Error {
|
|
134950
|
+
constructor(raw) {
|
|
134951
|
+
super(
|
|
134952
|
+
`"${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).`
|
|
134953
|
+
);
|
|
134954
|
+
this.raw = raw;
|
|
134955
|
+
this.name = "InvalidAddressError";
|
|
134956
|
+
}
|
|
134957
|
+
};
|
|
134958
|
+
var SuinsNotRegisteredError = class extends Error {
|
|
134959
|
+
constructor(name_) {
|
|
134960
|
+
super(
|
|
134961
|
+
`"${name_}" isn't a registered SuiNS name. Double-check the spelling, or paste the full Sui address (0x\u2026 64 hex characters).`
|
|
134962
|
+
);
|
|
134963
|
+
this.name_ = name_;
|
|
134964
|
+
this.name = "SuinsNotRegisteredError";
|
|
134965
|
+
}
|
|
134966
|
+
};
|
|
134967
|
+
var SuinsRpcError = class extends Error {
|
|
134968
|
+
constructor(name_, detail) {
|
|
134969
|
+
super(`SuiNS lookup failed for "${name_}" (${detail}). Try again, or paste the full Sui address.`);
|
|
134970
|
+
this.name_ = name_;
|
|
134971
|
+
this.name = "SuinsRpcError";
|
|
134972
|
+
}
|
|
134973
|
+
};
|
|
134974
|
+
function looksLikeSuiNs(value) {
|
|
134975
|
+
if (!value) return false;
|
|
134976
|
+
return SUINS_NAME_REGEX.test(value.trim().toLowerCase());
|
|
134977
|
+
}
|
|
134978
|
+
async function resolveSuinsViaRpc(rawName, ctx = {}) {
|
|
134979
|
+
const name = rawName.trim().toLowerCase();
|
|
134980
|
+
if (!SUINS_NAME_REGEX.test(name)) {
|
|
134981
|
+
throw new InvalidAddressError4(rawName);
|
|
134982
|
+
}
|
|
134983
|
+
const url3 = ctx.suiRpcUrl || SUI_MAINNET_URL;
|
|
134984
|
+
let res;
|
|
134985
|
+
try {
|
|
134986
|
+
res = await fetch(url3, {
|
|
134987
|
+
method: "POST",
|
|
134988
|
+
headers: { "Content-Type": "application/json" },
|
|
134989
|
+
body: JSON.stringify({
|
|
134990
|
+
jsonrpc: "2.0",
|
|
134991
|
+
id: 1,
|
|
134992
|
+
method: "suix_resolveNameServiceAddress",
|
|
134993
|
+
params: [name]
|
|
134994
|
+
}),
|
|
134995
|
+
signal: ctx.signal ?? AbortSignal.timeout(8e3)
|
|
134996
|
+
});
|
|
134997
|
+
} catch (err) {
|
|
134998
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
134999
|
+
throw new SuinsRpcError(name, msg);
|
|
135000
|
+
}
|
|
135001
|
+
if (!res.ok) {
|
|
135002
|
+
throw new SuinsRpcError(name, `HTTP ${res.status}`);
|
|
135003
|
+
}
|
|
135004
|
+
let body;
|
|
135005
|
+
try {
|
|
135006
|
+
body = await res.json();
|
|
135007
|
+
} catch (err) {
|
|
135008
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
135009
|
+
throw new SuinsRpcError(name, `JSON parse failed: ${msg}`);
|
|
135010
|
+
}
|
|
135011
|
+
if (body.error) {
|
|
135012
|
+
throw new SuinsRpcError(name, body.error.message);
|
|
135013
|
+
}
|
|
135014
|
+
return body.result ?? null;
|
|
135015
|
+
}
|
|
134946
135016
|
function ulebEncode2(num2) {
|
|
134947
135017
|
let bigNum = BigInt(num2);
|
|
134948
135018
|
const arr = [];
|
|
@@ -139313,6 +139383,14 @@ var SafeguardEnforcer = class {
|
|
|
139313
139383
|
};
|
|
139314
139384
|
init_errors9();
|
|
139315
139385
|
var RESERVED_NAMES = /* @__PURE__ */ new Set(["to", "all", "address"]);
|
|
139386
|
+
var deprecationWarned = false;
|
|
139387
|
+
function warnContactsDeprecation() {
|
|
139388
|
+
if (deprecationWarned) return;
|
|
139389
|
+
deprecationWarned = true;
|
|
139390
|
+
console.warn(
|
|
139391
|
+
"[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."
|
|
139392
|
+
);
|
|
139393
|
+
}
|
|
139316
139394
|
var ContactManager = class {
|
|
139317
139395
|
contacts = {};
|
|
139318
139396
|
filePath;
|
|
@@ -139342,6 +139420,7 @@ var ContactManager = class {
|
|
|
139342
139420
|
const existed = key in this.contacts;
|
|
139343
139421
|
this.contacts[key] = { name, address: normalized };
|
|
139344
139422
|
this.save();
|
|
139423
|
+
warnContactsDeprecation();
|
|
139345
139424
|
return { action: existed ? "updated" : "added" };
|
|
139346
139425
|
}
|
|
139347
139426
|
remove(name) {
|
|
@@ -139366,12 +139445,15 @@ var ContactManager = class {
|
|
|
139366
139445
|
}
|
|
139367
139446
|
const contact = this.contacts[nameOrAddress.toLowerCase()];
|
|
139368
139447
|
if (contact) {
|
|
139448
|
+
warnContactsDeprecation();
|
|
139369
139449
|
return { address: contact.address, contactName: contact.name };
|
|
139370
139450
|
}
|
|
139371
139451
|
throw new T2000Error(
|
|
139372
139452
|
"CONTACT_NOT_FOUND",
|
|
139373
139453
|
`"${nameOrAddress}" is not a valid Sui address or saved contact.
|
|
139374
|
-
|
|
139454
|
+
Use a SuiNS name (e.g. alex.sui \u2014 register at https://suins.io)
|
|
139455
|
+
or paste the full Sui address (0x... 64 hex characters).
|
|
139456
|
+
Legacy contact aliases: \`t2000 contacts add ${nameOrAddress} 0x...\` (deprecated).`
|
|
139375
139457
|
);
|
|
139376
139458
|
}
|
|
139377
139459
|
validateName(name) {
|
|
@@ -139741,7 +139823,7 @@ var T2000 = class _T2000 extends import_index2.default {
|
|
|
139741
139823
|
if (!(asset in SUPPORTED_ASSETS)) {
|
|
139742
139824
|
throw new T2000Error("ASSET_NOT_SUPPORTED", `Asset ${asset} is not supported`);
|
|
139743
139825
|
}
|
|
139744
|
-
const resolved = this.
|
|
139826
|
+
const resolved = await this.resolveRecipient(params.to);
|
|
139745
139827
|
const sendAmount = params.amount;
|
|
139746
139828
|
const sendTo = resolved.address;
|
|
139747
139829
|
const gasResult = await executeTx(
|
|
@@ -139758,11 +139840,63 @@ var T2000 = class _T2000 extends import_index2.default {
|
|
|
139758
139840
|
amount: sendAmount,
|
|
139759
139841
|
to: resolved.address,
|
|
139760
139842
|
contactName: resolved.contactName,
|
|
139843
|
+
suinsName: resolved.suinsName,
|
|
139761
139844
|
gasCost: gasResult.gasCostSui,
|
|
139762
139845
|
gasCostUnit: "SUI",
|
|
139763
139846
|
balance
|
|
139764
139847
|
};
|
|
139765
139848
|
}
|
|
139849
|
+
/**
|
|
139850
|
+
* [S.279 / CLI-CONTACTS-CLEANUP — 2026-05-23] Resolve a recipient
|
|
139851
|
+
* string into a canonical 0x address, trying each shape in priority
|
|
139852
|
+
* order:
|
|
139853
|
+
* 1. **hex** — `0x…` is used directly (no RPC round-trip).
|
|
139854
|
+
* 2. **SuiNS** — `alex.sui` resolves via `suix_resolveNameServiceAddress`.
|
|
139855
|
+
* 3. **saved contact** — `ContactManager.resolve()` falls back to the
|
|
139856
|
+
* legacy `~/.t2000/contacts.json` alias map. Deprecated; the
|
|
139857
|
+
* manager surfaces a one-time `console.warn` when this path fires.
|
|
139858
|
+
*
|
|
139859
|
+
* Returns `{ address, suinsName?, contactName? }` so `send()` can stamp
|
|
139860
|
+
* the name source on the receipt without re-resolving.
|
|
139861
|
+
*
|
|
139862
|
+
* Throws `T2000Error('SUINS_NOT_REGISTERED', …)` for well-formed but
|
|
139863
|
+
* unregistered SuiNS names (vs. propagating the engine-style
|
|
139864
|
+
* `SuinsNotRegisteredError` — keeps the SDK's error surface
|
|
139865
|
+
* `T2000Error`-only, consistent with every other write helper).
|
|
139866
|
+
*
|
|
139867
|
+
* [S.279.1 / 2026-05-23 — patch v2.19.1] Promoted from `private` to
|
|
139868
|
+
* `public` so MCP's `t2000_send` dryRun preview path can share the
|
|
139869
|
+
* same resolution logic as the live execute path. Pre-2.19.1 the
|
|
139870
|
+
* MCP dryRun called `agent.contacts.resolve(to)` directly, which
|
|
139871
|
+
* rejected SuiNS names — preview-then-execute flows broke for
|
|
139872
|
+
* `alex.sui`-style recipients. SSOT: never let preview and execute
|
|
139873
|
+
* resolve the same input differently.
|
|
139874
|
+
*/
|
|
139875
|
+
async resolveRecipient(input) {
|
|
139876
|
+
const trimmed = input.trim();
|
|
139877
|
+
if (SUI_ADDRESS_REGEX.test(trimmed)) {
|
|
139878
|
+
return { address: trimmed.toLowerCase() };
|
|
139879
|
+
}
|
|
139880
|
+
if (looksLikeSuiNs(trimmed)) {
|
|
139881
|
+
try {
|
|
139882
|
+
const name = trimmed.toLowerCase();
|
|
139883
|
+
const address2 = await resolveSuinsViaRpc(name);
|
|
139884
|
+
if (!address2) {
|
|
139885
|
+
throw new SuinsNotRegisteredError(name);
|
|
139886
|
+
}
|
|
139887
|
+
return { address: address2.toLowerCase(), suinsName: name };
|
|
139888
|
+
} catch (err) {
|
|
139889
|
+
if (err instanceof SuinsNotRegisteredError) {
|
|
139890
|
+
throw new T2000Error(
|
|
139891
|
+
"SUINS_NOT_REGISTERED",
|
|
139892
|
+
err.message
|
|
139893
|
+
);
|
|
139894
|
+
}
|
|
139895
|
+
throw err;
|
|
139896
|
+
}
|
|
139897
|
+
}
|
|
139898
|
+
return this.contacts.resolve(input);
|
|
139899
|
+
}
|
|
139766
139900
|
async balance() {
|
|
139767
139901
|
const bal = await queryBalance(this.client, this._address);
|
|
139768
139902
|
let chainTotal = bal.available + bal.gasReserve.usdEquiv;
|
|
@@ -140862,7 +140996,7 @@ Call t2000_services first to discover the right endpoint, then t2000_pay to exec
|
|
|
140862
140996
|
);
|
|
140863
140997
|
server.tool(
|
|
140864
140998
|
"t2000_contacts",
|
|
140865
|
-
"List saved contacts (name \u2192 address mappings).
|
|
140999
|
+
"DEPRECATED \u2014 List saved local contacts (~/.t2000/contacts.json name \u2192 address mappings). The local contact map is being sunset; the canonical name system is SuiNS (e.g. alex.sui \u2014 resolved by t2000_send automatically). This tool will be removed in the next major SDK release. Prefer pasting 0x addresses or using SuiNS names directly with t2000_send.",
|
|
140866
141000
|
{},
|
|
140867
141001
|
async () => {
|
|
140868
141002
|
try {
|
|
@@ -140911,16 +141045,16 @@ function registerWriteTools(server, agent) {
|
|
|
140911
141045
|
const mutex = new TxMutex();
|
|
140912
141046
|
server.tool(
|
|
140913
141047
|
"t2000_send",
|
|
140914
|
-
"Send USDC to a Sui address or contact
|
|
141048
|
+
"Send USDC (or another supported asset) to a 0x Sui address, a SuiNS name (e.g. alex.sui), or a saved contact alias. Amount is in dollars. Subject to per-transaction and daily send limits. Set dryRun: true to preview without signing. SuiNS is the preferred name path; saved contacts (~/.t2000/contacts.json) are deprecated and will be removed in the next major SDK release.",
|
|
140915
141049
|
{
|
|
140916
|
-
to: external_exports.string().describe("Recipient Sui address
|
|
141050
|
+
to: external_exports.string().describe("Recipient: 0x Sui address, SuiNS name like 'alex.sui', or saved contact name. SuiNS preferred; contact aliases are deprecated."),
|
|
140917
141051
|
amount: external_exports.number().describe("Amount in dollars to send"),
|
|
140918
141052
|
asset: external_exports.string().optional().describe("Asset to send (default: USDC)"),
|
|
140919
141053
|
dryRun: external_exports.boolean().optional().describe("Preview without signing (default: false)")
|
|
140920
141054
|
},
|
|
140921
141055
|
async ({ to: to2, amount: amount2, asset, dryRun }) => {
|
|
140922
141056
|
try {
|
|
140923
|
-
const resolved = agent.
|
|
141057
|
+
const resolved = await agent.resolveRecipient(to2);
|
|
140924
141058
|
if (dryRun) {
|
|
140925
141059
|
agent.enforcer.check({ operation: "send", amount: amount2 });
|
|
140926
141060
|
const balance = await agent.balance();
|
|
@@ -140934,6 +141068,7 @@ function registerWriteTools(server, agent) {
|
|
|
140934
141068
|
amount: amount2,
|
|
140935
141069
|
to: resolved.address,
|
|
140936
141070
|
contactName: resolved.contactName,
|
|
141071
|
+
suinsName: resolved.suinsName,
|
|
140937
141072
|
asset: asset ?? "USDC",
|
|
140938
141073
|
currentBalance: balance.available,
|
|
140939
141074
|
balanceAfter: balance.available - amount2,
|
|
@@ -141224,7 +141359,7 @@ ${text}`;
|
|
|
141224
141359
|
);
|
|
141225
141360
|
server.tool(
|
|
141226
141361
|
"t2000_contact_add",
|
|
141227
|
-
|
|
141362
|
+
"DEPRECATED \u2014 Save a contact name \u2192 Sui address mapping to ~/.t2000/contacts.json. The local-file contact map is being sunset; the canonical name system is SuiNS (register your-name.sui at https://suins.io once and every Sui app resolves it). Use this tool only if the recipient has no SuiNS name AND you need a memorable local alias. Will be removed in the next major SDK release.",
|
|
141228
141363
|
{
|
|
141229
141364
|
name: external_exports.string().describe('Contact name (e.g. "Tom", "Alice")'),
|
|
141230
141365
|
address: external_exports.string().describe("Sui wallet address (0x...)")
|
|
@@ -141240,7 +141375,7 @@ ${text}`;
|
|
|
141240
141375
|
);
|
|
141241
141376
|
server.tool(
|
|
141242
141377
|
"t2000_contact_remove",
|
|
141243
|
-
"Remove a saved contact by name.",
|
|
141378
|
+
"DEPRECATED \u2014 Remove a saved local contact by name. The local-file contact map is being sunset; will be removed entirely in the next major SDK release.",
|
|
141244
141379
|
{
|
|
141245
141380
|
name: external_exports.string().describe("Contact name to remove")
|
|
141246
141381
|
},
|
|
@@ -142008,7 +142143,7 @@ ${context}
|
|
|
142008
142143
|
})
|
|
142009
142144
|
);
|
|
142010
142145
|
}
|
|
142011
|
-
var PKG_VERSION = "2.
|
|
142146
|
+
var PKG_VERSION = "2.19.1";
|
|
142012
142147
|
console.log = (...args) => console.error("[log]", ...args);
|
|
142013
142148
|
console.warn = (...args) => console.error("[warn]", ...args);
|
|
142014
142149
|
async function startMcpServer(opts) {
|
|
@@ -142099,4 +142234,4 @@ axios/dist/node/axios.cjs:
|
|
|
142099
142234
|
@scure/bip39/index.js:
|
|
142100
142235
|
(*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
|
|
142101
142236
|
*/
|
|
142102
|
-
//# sourceMappingURL=dist-
|
|
142237
|
+
//# sourceMappingURL=dist-EUGE6UAA.js.map
|