@t2000/cli 5.16.0 → 5.17.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.
- package/dist/{dist-UPUBYGXT.js → dist-7QRKMV5A.js} +144 -4
- package/dist/dist-7QRKMV5A.js.map +1 -0
- package/dist/index.js +209 -16
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/dist-UPUBYGXT.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -27783,10 +27783,10 @@ async function finalize(response, opts) {
|
|
|
27783
27783
|
return { status: response.status, body: body2, paid: opts.paid };
|
|
27784
27784
|
}
|
|
27785
27785
|
async function makeGrpcBuildClient(client) {
|
|
27786
|
-
const { SuiGrpcClient:
|
|
27786
|
+
const { SuiGrpcClient: SuiGrpcClient3 } = await import("./grpc-OLWNGPHN.js");
|
|
27787
27787
|
const network = client.network === "testnet" ? "testnet" : "mainnet";
|
|
27788
27788
|
const baseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
|
|
27789
|
-
return new
|
|
27789
|
+
return new SuiGrpcClient3({ baseUrl, network });
|
|
27790
27790
|
}
|
|
27791
27791
|
function atomicToHuman(raw, decimals) {
|
|
27792
27792
|
return Number(raw) / 10 ** decimals;
|
|
@@ -28436,6 +28436,124 @@ async function listModels(opts) {
|
|
|
28436
28436
|
privacy: m.privacy ?? m.privacy_tier
|
|
28437
28437
|
}));
|
|
28438
28438
|
}
|
|
28439
|
+
var RECEIPT_ANCHORED_SUFFIX = "::anchor::ReceiptAnchored";
|
|
28440
|
+
function fullnodeUrl(network) {
|
|
28441
|
+
return network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
|
|
28442
|
+
}
|
|
28443
|
+
async function verifyReceipt(receiptId, opts = {}) {
|
|
28444
|
+
const base = opts.apiBase ?? DEFAULT_API_BASE;
|
|
28445
|
+
const network = opts.network ?? "mainnet";
|
|
28446
|
+
const checks = [];
|
|
28447
|
+
let receipt = null;
|
|
28448
|
+
try {
|
|
28449
|
+
const res = await fetch(`${base}/aci/receipts/${encodeURIComponent(receiptId)}`);
|
|
28450
|
+
if (res.ok) {
|
|
28451
|
+
receipt = await res.json();
|
|
28452
|
+
}
|
|
28453
|
+
} catch {
|
|
28454
|
+
}
|
|
28455
|
+
if (!receipt?.event_log) {
|
|
28456
|
+
checks.push({
|
|
28457
|
+
name: "Receipt",
|
|
28458
|
+
status: "fail",
|
|
28459
|
+
detail: "receipt not found or malformed",
|
|
28460
|
+
trust: "receipt-asserted"
|
|
28461
|
+
});
|
|
28462
|
+
return { receiptId, verified: false, anchorVerified: false, checks };
|
|
28463
|
+
}
|
|
28464
|
+
const wireHash = receipt.event_log.find((e) => e.type === "response.returned")?.wire_hash;
|
|
28465
|
+
const workloadId = receipt.workload_id;
|
|
28466
|
+
checks.push({
|
|
28467
|
+
name: "Receipt",
|
|
28468
|
+
status: wireHash && workloadId ? "pass" : "fail",
|
|
28469
|
+
detail: wireHash ? `well-formed (${receipt.event_log.length} log entries, workload ${workloadId})` : "missing response wire_hash / workload_id",
|
|
28470
|
+
trust: "receipt-asserted"
|
|
28471
|
+
});
|
|
28472
|
+
const upstreamEv = receipt.event_log.find((e) => e.type === "upstream.verified");
|
|
28473
|
+
const upstreamOk = upstreamEv?.result === "verified";
|
|
28474
|
+
checks.push({
|
|
28475
|
+
name: "Confidential upstream",
|
|
28476
|
+
status: upstreamEv ? upstreamOk ? "pass" : "fail" : "skip",
|
|
28477
|
+
detail: upstreamEv ? `${upstreamEv.provider ?? upstreamEv.upstream_name ?? "upstream"}: ${upstreamEv.result ?? "unknown"}${upstreamEv.tcb_status ? ` (TCB ${upstreamEv.tcb_status})` : ""}` : "no upstream.verified event (routed/non-confidential?)",
|
|
28478
|
+
trust: "receipt-asserted"
|
|
28479
|
+
});
|
|
28480
|
+
let anchorVerified = false;
|
|
28481
|
+
let anchor;
|
|
28482
|
+
let digest;
|
|
28483
|
+
try {
|
|
28484
|
+
const res = await fetch(`${base}/aci/anchor/${encodeURIComponent(receiptId)}`);
|
|
28485
|
+
if (res.ok) {
|
|
28486
|
+
const j = await res.json();
|
|
28487
|
+
digest = j.txDigest;
|
|
28488
|
+
}
|
|
28489
|
+
} catch {
|
|
28490
|
+
}
|
|
28491
|
+
if (!digest) {
|
|
28492
|
+
checks.push({
|
|
28493
|
+
name: "Sui anchor",
|
|
28494
|
+
status: "fail",
|
|
28495
|
+
detail: `no anchor on record \u2014 POST ${base}/aci/anchor/${receiptId} to create one`,
|
|
28496
|
+
trust: "trustless"
|
|
28497
|
+
});
|
|
28498
|
+
} else {
|
|
28499
|
+
try {
|
|
28500
|
+
const client = new SuiGrpcClient({ baseUrl: fullnodeUrl(network), network });
|
|
28501
|
+
const tx = await client.core.getTransaction({
|
|
28502
|
+
digest,
|
|
28503
|
+
include: { events: true }
|
|
28504
|
+
});
|
|
28505
|
+
const txn = tx.$kind === "Transaction" ? tx.Transaction : tx.FailedTransaction;
|
|
28506
|
+
const ev = (txn.events ?? []).find(
|
|
28507
|
+
(e) => e.eventType.endsWith(RECEIPT_ANCHORED_SUFFIX)
|
|
28508
|
+
);
|
|
28509
|
+
const data = ev?.json ?? {};
|
|
28510
|
+
const onChainReceipt = String(data.receipt_id ?? "");
|
|
28511
|
+
const onChainWire = String(data.wire_hash ?? "");
|
|
28512
|
+
const onChainWorkload = String(data.workload_id ?? "");
|
|
28513
|
+
const matches = onChainReceipt === receiptId && onChainWire === wireHash && onChainWorkload === workloadId;
|
|
28514
|
+
anchorVerified = matches;
|
|
28515
|
+
anchor = {
|
|
28516
|
+
txDigest: digest,
|
|
28517
|
+
anchoredAtMs: data.anchored_at_ms ? String(data.anchored_at_ms) : void 0,
|
|
28518
|
+
anchoredBy: data.anchored_by ? String(data.anchored_by) : void 0,
|
|
28519
|
+
explorer: `https://suiscan.xyz/${network}/tx/${digest}`
|
|
28520
|
+
};
|
|
28521
|
+
checks.push({
|
|
28522
|
+
name: "Sui anchor",
|
|
28523
|
+
status: matches ? "pass" : "fail",
|
|
28524
|
+
detail: matches ? `on-chain ReceiptAnchored matches (wire_hash + workload_id), tx ${digest}` : `on-chain event does NOT match the receipt (wire ${onChainWire || "absent"})`,
|
|
28525
|
+
trust: "trustless"
|
|
28526
|
+
});
|
|
28527
|
+
} catch (e) {
|
|
28528
|
+
checks.push({
|
|
28529
|
+
name: "Sui anchor",
|
|
28530
|
+
status: "fail",
|
|
28531
|
+
detail: `could not read anchor tx ${digest}: ${e instanceof Error ? e.message : "error"}`,
|
|
28532
|
+
trust: "trustless"
|
|
28533
|
+
});
|
|
28534
|
+
}
|
|
28535
|
+
}
|
|
28536
|
+
checks.push({
|
|
28537
|
+
name: "Receipt signature",
|
|
28538
|
+
status: "skip",
|
|
28539
|
+
detail: receipt.signature ? "present (local recompute via RedPill keyset canonicalization = roadmap)" : "no signature on receipt",
|
|
28540
|
+
trust: "roadmap"
|
|
28541
|
+
});
|
|
28542
|
+
return {
|
|
28543
|
+
receiptId,
|
|
28544
|
+
verified: Boolean(wireHash && workloadId) && anchorVerified,
|
|
28545
|
+
anchorVerified,
|
|
28546
|
+
checks,
|
|
28547
|
+
wireHash,
|
|
28548
|
+
workloadId,
|
|
28549
|
+
upstream: upstreamEv ? {
|
|
28550
|
+
provider: upstreamEv.provider ?? upstreamEv.upstream_name,
|
|
28551
|
+
result: upstreamEv.result,
|
|
28552
|
+
tcbStatus: upstreamEv.tcb_status
|
|
28553
|
+
} : void 0,
|
|
28554
|
+
anchor
|
|
28555
|
+
};
|
|
28556
|
+
}
|
|
28439
28557
|
var DEFAULT_CONFIG_DIR = join2(homedir(), ".t2000");
|
|
28440
28558
|
function resolveConfigPath(configDir) {
|
|
28441
28559
|
return join2(configDir ?? DEFAULT_CONFIG_DIR, "config.json");
|
|
@@ -28717,6 +28835,11 @@ var T2000 = class _T2000 extends import_index2.default {
|
|
|
28717
28835
|
async models(opts) {
|
|
28718
28836
|
return listModels(opts);
|
|
28719
28837
|
}
|
|
28838
|
+
/** Verify a confidential response by receipt id — checks the signed receipt
|
|
28839
|
+
* + its trustless on-chain Sui anchor. Fails closed on any mismatch. */
|
|
28840
|
+
async verify(receiptId, opts) {
|
|
28841
|
+
return verifyReceipt(receiptId, opts);
|
|
28842
|
+
}
|
|
28720
28843
|
// -- Swap --
|
|
28721
28844
|
async swap(params) {
|
|
28722
28845
|
this.limits.assert({
|
|
@@ -32473,8 +32596,77 @@ function registerChat(program3) {
|
|
|
32473
32596
|
});
|
|
32474
32597
|
}
|
|
32475
32598
|
|
|
32476
|
-
// src/commands/
|
|
32599
|
+
// src/commands/verify.ts
|
|
32477
32600
|
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
32601
|
+
function mark(check2) {
|
|
32602
|
+
if (check2.status === "pass") {
|
|
32603
|
+
return import_picocolors10.default.green("\u2713");
|
|
32604
|
+
}
|
|
32605
|
+
if (check2.status === "fail") {
|
|
32606
|
+
return import_picocolors10.default.red("\u2717");
|
|
32607
|
+
}
|
|
32608
|
+
return import_picocolors10.default.dim("\u2022");
|
|
32609
|
+
}
|
|
32610
|
+
function trustTag(check2) {
|
|
32611
|
+
if (check2.trust === "trustless") {
|
|
32612
|
+
return import_picocolors10.default.green(" (trustless \xB7 read from Sui)");
|
|
32613
|
+
}
|
|
32614
|
+
if (check2.trust === "roadmap") {
|
|
32615
|
+
return import_picocolors10.default.dim(" (roadmap)");
|
|
32616
|
+
}
|
|
32617
|
+
return import_picocolors10.default.dim(" (in signed receipt)");
|
|
32618
|
+
}
|
|
32619
|
+
function registerVerify(program3) {
|
|
32620
|
+
program3.command("verify").argument("<receipt-id>", "A confidential receipt id (rcpt-\u2026)").description(
|
|
32621
|
+
"Verify a confidential response by receipt id \u2014 checks the signed receipt + its trustless on-chain Sui anchor. Fails closed on any mismatch."
|
|
32622
|
+
).option("--api <url>", "API base URL (default https://api.t2000.ai/v1)").option("--testnet", "Read the anchor from Sui testnet (default mainnet)").action(async (receiptId, opts) => {
|
|
32623
|
+
try {
|
|
32624
|
+
const result = await verifyReceipt(receiptId, {
|
|
32625
|
+
apiBase: opts.api,
|
|
32626
|
+
network: opts.testnet ? "testnet" : "mainnet"
|
|
32627
|
+
});
|
|
32628
|
+
if (isJsonMode()) {
|
|
32629
|
+
printJson(result);
|
|
32630
|
+
if (!result.verified) {
|
|
32631
|
+
process.exitCode = 1;
|
|
32632
|
+
}
|
|
32633
|
+
return;
|
|
32634
|
+
}
|
|
32635
|
+
printBlank();
|
|
32636
|
+
printLine(import_picocolors10.default.bold(`Verifying ${receiptId}`));
|
|
32637
|
+
printBlank();
|
|
32638
|
+
for (const check2 of result.checks) {
|
|
32639
|
+
printLine(` ${mark(check2)} ${import_picocolors10.default.bold(check2.name)}${trustTag(check2)}`);
|
|
32640
|
+
printLine(` ${import_picocolors10.default.dim(check2.detail)}`);
|
|
32641
|
+
}
|
|
32642
|
+
printBlank();
|
|
32643
|
+
if (result.anchor) {
|
|
32644
|
+
printLine(import_picocolors10.default.dim(` anchor: ${result.anchor.explorer}`));
|
|
32645
|
+
}
|
|
32646
|
+
if (result.verified) {
|
|
32647
|
+
printLine(
|
|
32648
|
+
import_picocolors10.default.green(
|
|
32649
|
+
" RESULT: \u2713 anchor-verified on Sui (tamper-evident, Sui-native)."
|
|
32650
|
+
)
|
|
32651
|
+
);
|
|
32652
|
+
printLine(
|
|
32653
|
+
import_picocolors10.default.dim(
|
|
32654
|
+
" Local DCAP-quote + receipt-signature recompute = roadmap (full no-trust)."
|
|
32655
|
+
)
|
|
32656
|
+
);
|
|
32657
|
+
} else {
|
|
32658
|
+
printLine(import_picocolors10.default.red(" RESULT: \u2717 NOT verified \u2014 see the failed check above."));
|
|
32659
|
+
process.exitCode = 1;
|
|
32660
|
+
}
|
|
32661
|
+
printBlank();
|
|
32662
|
+
} catch (error) {
|
|
32663
|
+
handleError(error);
|
|
32664
|
+
}
|
|
32665
|
+
});
|
|
32666
|
+
}
|
|
32667
|
+
|
|
32668
|
+
// src/commands/services/search.ts
|
|
32669
|
+
var import_picocolors11 = __toESM(require_picocolors(), 1);
|
|
32478
32670
|
|
|
32479
32671
|
// src/commands/services/catalog.ts
|
|
32480
32672
|
var DEFAULT_GATEWAY_URL = "https://mpp.t2000.ai";
|
|
@@ -32576,9 +32768,9 @@ Examples:
|
|
|
32576
32768
|
}
|
|
32577
32769
|
function renderServiceLine(svc) {
|
|
32578
32770
|
const minPrice = cheapestEndpointPrice(svc);
|
|
32579
|
-
const priceTag = minPrice !== null ?
|
|
32580
|
-
const catTag = svc.categories.length > 0 ?
|
|
32581
|
-
printKeyValue(
|
|
32771
|
+
const priceTag = minPrice !== null ? import_picocolors11.default.green(`from $${minPrice}`) : import_picocolors11.default.dim("no pricing");
|
|
32772
|
+
const catTag = svc.categories.length > 0 ? import_picocolors11.default.dim(`[${svc.categories.join(", ")}]`) : "";
|
|
32773
|
+
printKeyValue(import_picocolors11.default.bold(svc.name), `${priceTag} ${catTag}`);
|
|
32582
32774
|
printKeyValue(" url", svc.serviceUrl);
|
|
32583
32775
|
printKeyValue(" about", svc.description);
|
|
32584
32776
|
printBlank();
|
|
@@ -32592,7 +32784,7 @@ function cheapestEndpointPrice(svc) {
|
|
|
32592
32784
|
}
|
|
32593
32785
|
|
|
32594
32786
|
// src/commands/services/inspect.ts
|
|
32595
|
-
var
|
|
32787
|
+
var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
32596
32788
|
function registerServicesInspect(parent) {
|
|
32597
32789
|
parent.command("inspect").description("Show pricing + endpoints for an MPP service or endpoint URL").argument("<url>", "Service base URL or endpoint URL").option("--gateway <url>", "Override gateway base URL (default: https://mpp.t2000.ai)").addHelpText(
|
|
32598
32790
|
"after",
|
|
@@ -32629,7 +32821,7 @@ Examples:
|
|
|
32629
32821
|
return;
|
|
32630
32822
|
}
|
|
32631
32823
|
printBlank();
|
|
32632
|
-
printKeyValue("Service",
|
|
32824
|
+
printKeyValue("Service", import_picocolors12.default.bold(service.name));
|
|
32633
32825
|
printKeyValue("URL", service.serviceUrl);
|
|
32634
32826
|
printKeyValue("About", service.description);
|
|
32635
32827
|
if (service.categories.length > 0) {
|
|
@@ -32659,7 +32851,7 @@ Examples:
|
|
|
32659
32851
|
function renderEndpoint(ep, serviceUrl) {
|
|
32660
32852
|
const price = `$${ep.price}`;
|
|
32661
32853
|
const label = `${ep.method} ${ep.path}`.padEnd(40);
|
|
32662
|
-
printKeyValue(label, `${
|
|
32854
|
+
printKeyValue(label, `${import_picocolors12.default.green(price)} ${import_picocolors12.default.dim(ep.description)}`);
|
|
32663
32855
|
printKeyValue(" url", `${serviceUrl}${ep.path}`);
|
|
32664
32856
|
printBlank();
|
|
32665
32857
|
}
|
|
@@ -32682,7 +32874,7 @@ T2000_GATEWAY_URL or --gateway <url> for local development.
|
|
|
32682
32874
|
}
|
|
32683
32875
|
|
|
32684
32876
|
// src/commands/limit/show.ts
|
|
32685
|
-
var
|
|
32877
|
+
var import_picocolors13 = __toESM(require_picocolors(), 1);
|
|
32686
32878
|
function registerLimitShow(parent) {
|
|
32687
32879
|
parent.command("show").description("Show current spending limits").action(async (opts) => {
|
|
32688
32880
|
try {
|
|
@@ -32705,10 +32897,10 @@ function registerLimitShow(parent) {
|
|
|
32705
32897
|
}
|
|
32706
32898
|
printBlank();
|
|
32707
32899
|
if (limits.perTxUsd !== void 0) {
|
|
32708
|
-
printKeyValue("Per-transaction",
|
|
32900
|
+
printKeyValue("Per-transaction", import_picocolors13.default.green(`$${limits.perTxUsd}`));
|
|
32709
32901
|
}
|
|
32710
32902
|
if (limits.dailyUsd !== void 0) {
|
|
32711
|
-
printKeyValue("Daily (cumulative)",
|
|
32903
|
+
printKeyValue("Daily (cumulative)", import_picocolors13.default.green(`$${limits.dailyUsd}`));
|
|
32712
32904
|
}
|
|
32713
32905
|
printBlank();
|
|
32714
32906
|
printInfo("Use `--force` on `t2 send` / `t2 swap` / `t2 pay` to override per-call.");
|
|
@@ -32720,7 +32912,7 @@ function registerLimitShow(parent) {
|
|
|
32720
32912
|
}
|
|
32721
32913
|
|
|
32722
32914
|
// src/commands/limit/set.ts
|
|
32723
|
-
var
|
|
32915
|
+
var import_picocolors14 = __toESM(require_picocolors(), 1);
|
|
32724
32916
|
function parseLimitSetArgs(opts) {
|
|
32725
32917
|
const perTx = opts.perTx !== void 0 ? parseUsdFlag("--per-tx", opts.perTx) : void 0;
|
|
32726
32918
|
const daily = opts.daily !== void 0 ? parseUsdFlag("--daily", opts.daily) : void 0;
|
|
@@ -32762,10 +32954,10 @@ Examples:
|
|
|
32762
32954
|
printBlank();
|
|
32763
32955
|
printSuccess("Spending limits updated.");
|
|
32764
32956
|
if (next?.perTxUsd !== void 0) {
|
|
32765
|
-
printKeyValue("Per-transaction",
|
|
32957
|
+
printKeyValue("Per-transaction", import_picocolors14.default.green(`$${next.perTxUsd}`));
|
|
32766
32958
|
}
|
|
32767
32959
|
if (next?.dailyUsd !== void 0) {
|
|
32768
|
-
printKeyValue("Daily (cumulative)",
|
|
32960
|
+
printKeyValue("Daily (cumulative)", import_picocolors14.default.green(`$${next.dailyUsd}`));
|
|
32769
32961
|
}
|
|
32770
32962
|
printBlank();
|
|
32771
32963
|
printInfo("Use `t2 limit show` to view; `t2 limit reset` to clear.");
|
|
@@ -32827,7 +33019,7 @@ function registerMcpStart(parent) {
|
|
|
32827
33019
|
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) => {
|
|
32828
33020
|
let mod2;
|
|
32829
33021
|
try {
|
|
32830
|
-
mod2 = await import("./dist-
|
|
33022
|
+
mod2 = await import("./dist-7QRKMV5A.js");
|
|
32831
33023
|
} catch {
|
|
32832
33024
|
console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
|
|
32833
33025
|
process.exit(1);
|
|
@@ -33790,6 +33982,7 @@ Examples:
|
|
|
33790
33982
|
registerSwap(program3);
|
|
33791
33983
|
registerPay(program3);
|
|
33792
33984
|
registerChat(program3);
|
|
33985
|
+
registerVerify(program3);
|
|
33793
33986
|
registerServices(program3);
|
|
33794
33987
|
registerLimit(program3);
|
|
33795
33988
|
registerMcp(program3);
|