@t2000/cli 5.4.0 → 5.5.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.js
CHANGED
|
@@ -27808,6 +27808,7 @@ async function buildSendTx({
|
|
|
27808
27808
|
});
|
|
27809
27809
|
return tx;
|
|
27810
27810
|
}
|
|
27811
|
+
init_token_registry();
|
|
27811
27812
|
var SUI_PRICE_FALLBACK = 1;
|
|
27812
27813
|
var _cachedSuiPrice = 0;
|
|
27813
27814
|
var _priceLastFetched = 0;
|
|
@@ -27840,30 +27841,67 @@ async function fetchSuiPrice(client) {
|
|
|
27840
27841
|
}
|
|
27841
27842
|
return _cachedSuiPrice || SUI_PRICE_FALLBACK;
|
|
27842
27843
|
}
|
|
27844
|
+
function safeNorm(coinType) {
|
|
27845
|
+
try {
|
|
27846
|
+
return normalizeStructTag(coinType);
|
|
27847
|
+
} catch {
|
|
27848
|
+
return coinType;
|
|
27849
|
+
}
|
|
27850
|
+
}
|
|
27851
|
+
var SUI_TYPE_NORM = safeNorm(SUPPORTED_ASSETS.SUI.type);
|
|
27852
|
+
var STABLE_BY_NORM = (() => {
|
|
27853
|
+
const m = {};
|
|
27854
|
+
for (const asset of STABLE_ASSETS) m[safeNorm(SUPPORTED_ASSETS[asset].type)] = asset;
|
|
27855
|
+
return m;
|
|
27856
|
+
})();
|
|
27843
27857
|
async function queryBalance(client, address) {
|
|
27844
|
-
const
|
|
27845
|
-
|
|
27846
|
-
|
|
27847
|
-
|
|
27848
|
-
|
|
27849
|
-
|
|
27850
|
-
|
|
27851
|
-
|
|
27858
|
+
const held = [];
|
|
27859
|
+
let cursor;
|
|
27860
|
+
do {
|
|
27861
|
+
const page = await client.core.listBalances({ owner: address, cursor: cursor ?? void 0 });
|
|
27862
|
+
for (const b of page.balances) {
|
|
27863
|
+
const raw = BigInt(b.balance);
|
|
27864
|
+
if (raw > 0n) held.push({ coinType: b.coinType, raw });
|
|
27865
|
+
}
|
|
27866
|
+
cursor = page.hasNextPage ? page.cursor : null;
|
|
27867
|
+
} while (cursor);
|
|
27868
|
+
const suiPriceUsd = await fetchSuiPrice(client);
|
|
27852
27869
|
const stables = {};
|
|
27870
|
+
for (const asset of STABLE_ASSETS) stables[asset] = 0;
|
|
27853
27871
|
let totalStables = 0;
|
|
27854
|
-
|
|
27855
|
-
|
|
27856
|
-
|
|
27872
|
+
let suiAmount = 0;
|
|
27873
|
+
const otherCoins = [];
|
|
27874
|
+
for (const { coinType, raw } of held) {
|
|
27875
|
+
const norm = safeNorm(coinType);
|
|
27876
|
+
if (norm === SUI_TYPE_NORM) {
|
|
27877
|
+
suiAmount = Number(raw) / Number(MIST_PER_SUI);
|
|
27878
|
+
} else if (STABLE_BY_NORM[norm]) {
|
|
27879
|
+
const asset = STABLE_BY_NORM[norm];
|
|
27880
|
+
const amount = Number(raw) / 10 ** SUPPORTED_ASSETS[asset].decimals;
|
|
27881
|
+
stables[asset] = amount;
|
|
27882
|
+
totalStables += amount;
|
|
27883
|
+
} else {
|
|
27884
|
+
otherCoins.push({ coinType, raw });
|
|
27885
|
+
}
|
|
27857
27886
|
}
|
|
27858
|
-
const
|
|
27887
|
+
const tokens = await Promise.all(
|
|
27888
|
+
otherCoins.map(async ({ coinType, raw }) => {
|
|
27889
|
+
const decimals = await resolveCoinDecimals(client, coinType);
|
|
27890
|
+
return {
|
|
27891
|
+
coinType,
|
|
27892
|
+
symbol: resolveSymbol(coinType),
|
|
27893
|
+
amount: Number(raw) / 10 ** decimals,
|
|
27894
|
+
usdValue: null
|
|
27895
|
+
};
|
|
27896
|
+
})
|
|
27897
|
+
);
|
|
27898
|
+
tokens.sort((a, b) => a.symbol.localeCompare(b.symbol));
|
|
27859
27899
|
const suiUsdValue = suiAmount * suiPriceUsd;
|
|
27860
27900
|
return {
|
|
27861
27901
|
stables,
|
|
27862
27902
|
available: totalStables,
|
|
27863
|
-
sui: {
|
|
27864
|
-
|
|
27865
|
-
usdValue: suiUsdValue
|
|
27866
|
-
},
|
|
27903
|
+
sui: { amount: suiAmount, usdValue: suiUsdValue },
|
|
27904
|
+
tokens,
|
|
27867
27905
|
totalUsd: totalStables + suiUsdValue
|
|
27868
27906
|
};
|
|
27869
27907
|
}
|
|
@@ -28029,7 +28067,7 @@ var TX_NODE_FRAGMENT = `
|
|
|
28029
28067
|
}
|
|
28030
28068
|
`;
|
|
28031
28069
|
var HISTORY_QUERY = `query History($address: SuiAddress!, $last: Int!) {
|
|
28032
|
-
transactions(last: $last, filter: {
|
|
28070
|
+
transactions(last: $last, filter: { affectedAddress: $address }) {
|
|
28033
28071
|
nodes {${TX_NODE_FRAGMENT}}
|
|
28034
28072
|
}
|
|
28035
28073
|
}`;
|
|
@@ -28099,7 +28137,9 @@ function buildRecord(args) {
|
|
|
28099
28137
|
return { digest, action, label, legs, amount, asset, recipient, direction, timestamp: timestampMs, gasCost };
|
|
28100
28138
|
}
|
|
28101
28139
|
init_token_registry();
|
|
28102
|
-
var
|
|
28140
|
+
var RESOLVE_NAME_QUERY = `query ResolveSuins($name: String!) {
|
|
28141
|
+
address(name: $name) { address }
|
|
28142
|
+
}`;
|
|
28103
28143
|
var SUI_ADDRESS_REGEX = /^0x[a-fA-F0-9]{1,64}$/i;
|
|
28104
28144
|
var SUINS_NAME_REGEX = /^[a-z0-9-]+(\.[a-z0-9-]+)*\.sui$/;
|
|
28105
28145
|
var InvalidAddressError = class extends Error {
|
|
@@ -28136,38 +28176,22 @@ async function resolveSuinsViaRpc(rawName, ctx = {}) {
|
|
|
28136
28176
|
if (!SUINS_NAME_REGEX.test(name)) {
|
|
28137
28177
|
throw new InvalidAddressError(rawName);
|
|
28138
28178
|
}
|
|
28139
|
-
const
|
|
28179
|
+
const gql = getSuiGraphQLClient();
|
|
28140
28180
|
let res;
|
|
28141
28181
|
try {
|
|
28142
|
-
res = await
|
|
28143
|
-
|
|
28144
|
-
|
|
28145
|
-
|
|
28146
|
-
jsonrpc: "2.0",
|
|
28147
|
-
id: 1,
|
|
28148
|
-
method: "suix_resolveNameServiceAddress",
|
|
28149
|
-
params: [name]
|
|
28150
|
-
}),
|
|
28151
|
-
signal: ctx.signal ?? AbortSignal.timeout(8e3)
|
|
28182
|
+
res = await gql.query({
|
|
28183
|
+
query: RESOLVE_NAME_QUERY,
|
|
28184
|
+
variables: { name },
|
|
28185
|
+
signal: ctx.signal
|
|
28152
28186
|
});
|
|
28153
28187
|
} catch (err) {
|
|
28154
28188
|
const msg = err instanceof Error ? err.message : String(err);
|
|
28155
28189
|
throw new SuinsRpcError(name, msg);
|
|
28156
28190
|
}
|
|
28157
|
-
if (
|
|
28158
|
-
throw new SuinsRpcError(name,
|
|
28159
|
-
}
|
|
28160
|
-
let body;
|
|
28161
|
-
try {
|
|
28162
|
-
body = await res.json();
|
|
28163
|
-
} catch (err) {
|
|
28164
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
28165
|
-
throw new SuinsRpcError(name, `JSON parse failed: ${msg}`);
|
|
28166
|
-
}
|
|
28167
|
-
if (body.error) {
|
|
28168
|
-
throw new SuinsRpcError(name, body.error.message);
|
|
28191
|
+
if (res.errors?.length) {
|
|
28192
|
+
throw new SuinsRpcError(name, res.errors.map((e) => e.message ?? "unknown error").join("; "));
|
|
28169
28193
|
}
|
|
28170
|
-
return
|
|
28194
|
+
return res.data?.address?.address ?? null;
|
|
28171
28195
|
}
|
|
28172
28196
|
init_errors();
|
|
28173
28197
|
var DEFAULT_CONFIG_DIR = join2(homedir(), ".t2000");
|
|
@@ -31333,8 +31357,11 @@ function registerFund(program3) {
|
|
|
31333
31357
|
|
|
31334
31358
|
// src/commands/balance.ts
|
|
31335
31359
|
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
31360
|
+
function formatTokenAmount(n) {
|
|
31361
|
+
return n.toLocaleString("en-US", { maximumFractionDigits: 6, useGrouping: false });
|
|
31362
|
+
}
|
|
31336
31363
|
function registerBalance(program3) {
|
|
31337
|
-
program3.command("balance").description("Show
|
|
31364
|
+
program3.command("balance").description("Show all wallet holdings \u2014 USDC / USDsui / SUI (USD-priced) + any other tokens (amount-only)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(async (opts) => {
|
|
31338
31365
|
try {
|
|
31339
31366
|
const agent = await withAgent({ keyPath: opts.key });
|
|
31340
31367
|
const bal = await agent.balance();
|
|
@@ -31343,6 +31370,7 @@ function registerBalance(program3) {
|
|
|
31343
31370
|
available: bal.available,
|
|
31344
31371
|
stables: bal.stables,
|
|
31345
31372
|
sui: bal.sui,
|
|
31373
|
+
tokens: bal.tokens,
|
|
31346
31374
|
totalUsd: bal.totalUsd
|
|
31347
31375
|
});
|
|
31348
31376
|
return;
|
|
@@ -31358,14 +31386,25 @@ function registerBalance(program3) {
|
|
|
31358
31386
|
printKeyValue(label, formatUsd(amount));
|
|
31359
31387
|
}
|
|
31360
31388
|
}
|
|
31361
|
-
if (bal.sui && bal.sui.
|
|
31389
|
+
if (bal.sui && bal.sui.amount > 0) {
|
|
31362
31390
|
printKeyValue(
|
|
31363
31391
|
"SUI",
|
|
31364
|
-
`${formatUsd(bal.sui.usdValue)} ${import_picocolors3.default.dim(`(${bal.sui.amount.toFixed(4)} SUI \
|
|
31392
|
+
`${formatUsd(bal.sui.usdValue)} ${import_picocolors3.default.dim(`(${bal.sui.amount.toFixed(4)} SUI \xB7 gas)`)}`
|
|
31365
31393
|
);
|
|
31366
31394
|
}
|
|
31395
|
+
const tokens = bal.tokens ?? [];
|
|
31396
|
+
for (const t of tokens) {
|
|
31397
|
+
printKeyValue(t.symbol.padEnd(8), import_picocolors3.default.dim(formatTokenAmount(t.amount)));
|
|
31398
|
+
}
|
|
31367
31399
|
printSeparator();
|
|
31368
|
-
printKeyValue("Wallet total", formatUsd(bal.totalUsd));
|
|
31400
|
+
printKeyValue("Wallet total", `${formatUsd(bal.totalUsd)} ${import_picocolors3.default.dim("(priced holdings)")}`);
|
|
31401
|
+
if (tokens.length > 0) {
|
|
31402
|
+
printLine(
|
|
31403
|
+
import_picocolors3.default.dim(
|
|
31404
|
+
` + ${tokens.length} token${tokens.length === 1 ? "" : "s"} above with no USD price \u2014 not counted in the total`
|
|
31405
|
+
)
|
|
31406
|
+
);
|
|
31407
|
+
}
|
|
31369
31408
|
printBlank();
|
|
31370
31409
|
} catch (error) {
|
|
31371
31410
|
handleError(error);
|
|
@@ -31399,9 +31438,9 @@ function printTxSummary(tx) {
|
|
|
31399
31438
|
const label = ACTION_LABELS[tx.action] ?? `\u{1F4E6} ${tx.action}`;
|
|
31400
31439
|
const time = tx.timestamp ? relativeTime(tx.timestamp) : "";
|
|
31401
31440
|
const amount = formatAmount(tx);
|
|
31402
|
-
const
|
|
31441
|
+
const direction = tx.direction === "in" ? import_picocolors4.default.green("\u2190 received") : tx.recipient ? import_picocolors4.default.dim(`\u2192 ${truncateAddress(tx.recipient)}`) : "";
|
|
31403
31442
|
const link = import_picocolors4.default.dim(explorerUrl(tx.digest));
|
|
31404
|
-
printLine(`${label} ${amount} ${
|
|
31443
|
+
printLine(`${label} ${amount} ${direction}`);
|
|
31405
31444
|
printLine(` ${import_picocolors4.default.dim(truncateAddress(tx.digest))} ${import_picocolors4.default.dim(time)}`);
|
|
31406
31445
|
printLine(` ${link}`);
|
|
31407
31446
|
}
|
|
@@ -31411,6 +31450,7 @@ function printTxDetail(tx) {
|
|
|
31411
31450
|
printKeyValue("Type", label);
|
|
31412
31451
|
printKeyValue("Digest", tx.digest);
|
|
31413
31452
|
if (tx.amount) printKeyValue("Amount", `${tx.amount.toFixed(tx.amount < 0.01 ? 6 : 4)} ${tx.asset ?? ""}`);
|
|
31453
|
+
if (tx.direction) printKeyValue("Direction", tx.direction === "in" ? "Received" : "Sent");
|
|
31414
31454
|
if (tx.recipient) printKeyValue("Recipient", tx.recipient);
|
|
31415
31455
|
if (tx.timestamp) {
|
|
31416
31456
|
printKeyValue("Time", `${new Date(tx.timestamp).toLocaleString()} (${relativeTime(tx.timestamp)})`);
|
|
@@ -32350,7 +32390,7 @@ function registerMcpStart(parent) {
|
|
|
32350
32390
|
parent.command("start", { isDefault: true }).description("Start MCP server (stdio transport \u2014 for AI client integration)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(async (opts) => {
|
|
32351
32391
|
let mod2;
|
|
32352
32392
|
try {
|
|
32353
|
-
mod2 = await import("./dist-
|
|
32393
|
+
mod2 = await import("./dist-OMYCTHXH.js");
|
|
32354
32394
|
} catch {
|
|
32355
32395
|
console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
|
|
32356
32396
|
process.exit(1);
|