@t2000/cli 10.27.0 → 10.27.2
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 +138 -6
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -30191,11 +30191,21 @@ var T2000 = class _T2000 extends import_index2.default {
|
|
|
30191
30191
|
const rawAmount = BigInt(Math.floor(params.amount * 10 ** fromDecimals));
|
|
30192
30192
|
let route;
|
|
30193
30193
|
if (params.serializedRoute) {
|
|
30194
|
-
|
|
30194
|
+
let s = params.serializedRoute;
|
|
30195
|
+
const nested = s.serializedRoute;
|
|
30196
|
+
if (nested && typeof nested === "object" && typeof nested.fromCoinType === "string" && nested.routerData) {
|
|
30197
|
+
s = nested;
|
|
30198
|
+
}
|
|
30199
|
+
if (typeof s.fromCoinType !== "string" || typeof s.toCoinType !== "string") {
|
|
30200
|
+
throw new T2000Error(
|
|
30201
|
+
"SWAP_ROUTE_MISMATCH",
|
|
30202
|
+
"serializedRoute is not the object t2000 quoted \u2014 it is missing fromCoinType/toCoinType. Pass quote.serializedRoute exactly as the quote returned it (not the whole quote response), or omit serializedRoute to discover a fresh route."
|
|
30203
|
+
);
|
|
30204
|
+
}
|
|
30195
30205
|
if (!verifyCetusRouteCoinMatch2(s, { fromCoinType: fromType, toCoinType: toType })) {
|
|
30196
30206
|
throw new T2000Error(
|
|
30197
30207
|
"SWAP_ROUTE_MISMATCH",
|
|
30198
|
-
`The quoted route is for ${s.fromCoinType} -> ${s.toCoinType}, not ${
|
|
30208
|
+
`The quoted route is for ${s.fromCoinType} -> ${s.toCoinType}, not ${fromType} -> ${toType}. Re-quote and pass the new serializedRoute.`
|
|
30199
30209
|
);
|
|
30200
30210
|
}
|
|
30201
30211
|
if (s.byAmountIn !== byAmountIn || BigInt(s.amountIn) !== rawAmount) {
|
|
@@ -30545,6 +30555,8 @@ var A2A_ESCROW_FEE_CONFIG_VERSION = Number(
|
|
|
30545
30555
|
);
|
|
30546
30556
|
var MODULE2 = "escrow";
|
|
30547
30557
|
var MAX_JOB_USDC = 50;
|
|
30558
|
+
var MAX_REVIEW_WINDOW_MS = 2592e6;
|
|
30559
|
+
var MAX_DELIVER_HORIZON_MS = 31536e6;
|
|
30548
30560
|
var JOB_STATES = [
|
|
30549
30561
|
"funded",
|
|
30550
30562
|
"delivered",
|
|
@@ -30552,12 +30564,57 @@ var JOB_STATES = [
|
|
|
30552
30564
|
"refunded",
|
|
30553
30565
|
"rejected"
|
|
30554
30566
|
];
|
|
30567
|
+
function hexToBytes3(hex) {
|
|
30568
|
+
const clean4 = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
30569
|
+
if (clean4.length === 0 || clean4.length % 2 !== 0 || /[^0-9a-fA-F]/.test(clean4)) {
|
|
30570
|
+
throw new T2000Error(
|
|
30571
|
+
"INVALID_AMOUNT",
|
|
30572
|
+
`Expected a hex hash (0x\u2026), got "${hex.slice(0, 32)}"`
|
|
30573
|
+
);
|
|
30574
|
+
}
|
|
30575
|
+
const out = [];
|
|
30576
|
+
for (let i = 0; i < clean4.length; i += 2) {
|
|
30577
|
+
out.push(Number.parseInt(clean4.slice(i, i + 2), 16));
|
|
30578
|
+
}
|
|
30579
|
+
return out;
|
|
30580
|
+
}
|
|
30555
30581
|
function bytesToHex3(bytes) {
|
|
30556
30582
|
const arr = typeof bytes === "string" ? Array.from(atob(bytes), (c) => c.charCodeAt(0)) : bytes;
|
|
30557
30583
|
let s = "0x";
|
|
30558
30584
|
for (const b of arr) s += b.toString(16).padStart(2, "0");
|
|
30559
30585
|
return s;
|
|
30560
30586
|
}
|
|
30587
|
+
function preflightCreateJob(terms) {
|
|
30588
|
+
const addressCheck = checkSuiAddress(terms.seller);
|
|
30589
|
+
if (!addressCheck.valid) return addressCheck;
|
|
30590
|
+
if (!Number.isFinite(terms.amountUsdc) || terms.amountUsdc <= 0) {
|
|
30591
|
+
return preflightFail("INVALID_AMOUNT", `Amount must be positive. Got ${terms.amountUsdc}.`);
|
|
30592
|
+
}
|
|
30593
|
+
if (terms.amountUsdc > MAX_JOB_USDC) {
|
|
30594
|
+
return preflightFail(
|
|
30595
|
+
"INVALID_AMOUNT",
|
|
30596
|
+
`v1 caps escrow jobs at ${MAX_JOB_USDC} USDC (no-arbitration split only stays fair at small sizes). Got ${terms.amountUsdc}.`
|
|
30597
|
+
);
|
|
30598
|
+
}
|
|
30599
|
+
if (terms.deliverByMs <= Date.now()) {
|
|
30600
|
+
return preflightFail("INVALID_AMOUNT", "deliverByMs must be in the future.");
|
|
30601
|
+
}
|
|
30602
|
+
if (terms.deliverByMs > Date.now() + MAX_DELIVER_HORIZON_MS) {
|
|
30603
|
+
return preflightFail("INVALID_AMOUNT", "deliverByMs is more than 365 days out.");
|
|
30604
|
+
}
|
|
30605
|
+
if (terms.reviewWindowMs < 0 || terms.reviewWindowMs > MAX_REVIEW_WINDOW_MS) {
|
|
30606
|
+
return preflightFail("INVALID_AMOUNT", "reviewWindowMs must be 0\u201330 days.");
|
|
30607
|
+
}
|
|
30608
|
+
if (!Number.isInteger(terms.rejectSplitBps) || terms.rejectSplitBps < 0 || terms.rejectSplitBps > 1e4) {
|
|
30609
|
+
return preflightFail("INVALID_AMOUNT", "rejectSplitBps must be an integer 0\u201310000.");
|
|
30610
|
+
}
|
|
30611
|
+
try {
|
|
30612
|
+
hexToBytes3(terms.specHash);
|
|
30613
|
+
} catch (e) {
|
|
30614
|
+
return preflightFail("INVALID_AMOUNT", e.message);
|
|
30615
|
+
}
|
|
30616
|
+
return PREFLIGHT_OK;
|
|
30617
|
+
}
|
|
30561
30618
|
async function getJob(client, jobId) {
|
|
30562
30619
|
const resp = await client.core.getObject({ objectId: jobId, include: { json: true } }).catch((e) => {
|
|
30563
30620
|
throw new T2000Error(
|
|
@@ -35874,6 +35931,40 @@ function recordSpendIfLanded(amountUsdc, digest) {
|
|
|
35874
35931
|
}
|
|
35875
35932
|
}
|
|
35876
35933
|
|
|
35934
|
+
// src/lib/settle-fee.ts
|
|
35935
|
+
var SERVICES_SETTLE_FEE_BPS = 500;
|
|
35936
|
+
var MICRO = 1e6;
|
|
35937
|
+
var TRAILING_ZEROS = /0+$/;
|
|
35938
|
+
function formatUsdMicro(micro) {
|
|
35939
|
+
if (!Number.isFinite(micro) || micro < 0) {
|
|
35940
|
+
return "\u2014";
|
|
35941
|
+
}
|
|
35942
|
+
const m = Math.floor(micro);
|
|
35943
|
+
const whole = Math.floor(m / MICRO);
|
|
35944
|
+
const frac = String(m % MICRO).padStart(6, "0");
|
|
35945
|
+
const dp = Math.max(2, frac.replace(TRAILING_ZEROS, "").length);
|
|
35946
|
+
return `$${whole}.${frac.slice(0, dp)}`;
|
|
35947
|
+
}
|
|
35948
|
+
function settlementSplit(priceUsdc, feeBps = SERVICES_SETTLE_FEE_BPS) {
|
|
35949
|
+
const escrowMicro = Math.floor(priceUsdc * MICRO);
|
|
35950
|
+
const feeMicro = Math.floor(escrowMicro * feeBps / 1e4);
|
|
35951
|
+
const payoutMicro = escrowMicro - feeMicro;
|
|
35952
|
+
return {
|
|
35953
|
+
escrowUsdc: priceUsdc,
|
|
35954
|
+
feeBps,
|
|
35955
|
+
feeMicro,
|
|
35956
|
+
payoutMicro,
|
|
35957
|
+
escrow: formatUsdMicro(escrowMicro),
|
|
35958
|
+
fee: formatUsdMicro(feeMicro),
|
|
35959
|
+
payout: formatUsdMicro(payoutMicro)
|
|
35960
|
+
};
|
|
35961
|
+
}
|
|
35962
|
+
function sellerReceivesLine(priceUsdc) {
|
|
35963
|
+
const s = settlementSplit(priceUsdc);
|
|
35964
|
+
return `${s.payout} after the ${s.feeBps / 100}% settle fee (${s.fee})`;
|
|
35965
|
+
}
|
|
35966
|
+
var SETTLE_FEE_NOTE = `Services settle at ${SERVICES_SETTLE_FEE_BPS / 100}% from the seller's payout \u2014 never added to the buyer's escrow. Refunds, cancels and declines are fee-free.`;
|
|
35967
|
+
|
|
35877
35968
|
// src/lib/agent-ref.ts
|
|
35878
35969
|
var HASH_ID_RE = /^#\d{1,10}$/;
|
|
35879
35970
|
var BARE_DIGITS_RE = /^\d{1,10}$/;
|
|
@@ -36343,6 +36434,36 @@ no fund step; unclaimed openings refund fee-free):
|
|
|
36343
36434
|
reviewWindowMs = opts.review ? parseDuration(opts.review) : DEFAULT_REVIEW_WINDOW_MS;
|
|
36344
36435
|
rejectSplitBps = Number.parseInt(opts.split, 10);
|
|
36345
36436
|
}
|
|
36437
|
+
const pre = preflightCreateJob({
|
|
36438
|
+
seller,
|
|
36439
|
+
amountUsdc,
|
|
36440
|
+
specHash,
|
|
36441
|
+
deliverByMs,
|
|
36442
|
+
reviewWindowMs,
|
|
36443
|
+
rejectSplitBps
|
|
36444
|
+
});
|
|
36445
|
+
if (!pre.valid) {
|
|
36446
|
+
throw new Error(pre.error);
|
|
36447
|
+
}
|
|
36448
|
+
const preAgent = await withAgent({ keyPath: opts.key });
|
|
36449
|
+
const bal = await preAgent.balance();
|
|
36450
|
+
const usdc = bal.stables.USDC ?? 0;
|
|
36451
|
+
if (usdc < amountUsdc) {
|
|
36452
|
+
throw new Error(
|
|
36453
|
+
`Insufficient USDC \u2014 need ${formatUsdMicro(Math.floor(amountUsdc * 1e6))}, wallet has ${formatUsdMicro(Math.floor(usdc * 1e6))}. Fund it: t2 fund`
|
|
36454
|
+
);
|
|
36455
|
+
}
|
|
36456
|
+
assertSpendAllowed(amountUsdc);
|
|
36457
|
+
const split4 = settlementSplit(amountUsdc);
|
|
36458
|
+
if (!isJsonMode()) {
|
|
36459
|
+
printBlank();
|
|
36460
|
+
printInfo("Hire preflight");
|
|
36461
|
+
printKeyValue(" Escrow", `${split4.escrow} USDC (leaves your wallet on sign)`);
|
|
36462
|
+
printKeyValue(" Seller", truncateAddress(seller));
|
|
36463
|
+
if (serviceSlug) printKeyValue(" Service", serviceSlug);
|
|
36464
|
+
printKeyValue(" Deliver by", new Date(deliverByMs).toISOString());
|
|
36465
|
+
printKeyValue(" Settle fee", `${split4.fee} from the seller's payout \u2014 not added to your escrow`);
|
|
36466
|
+
}
|
|
36346
36467
|
const { address, digest } = await sponsoredJobVerb({
|
|
36347
36468
|
base,
|
|
36348
36469
|
keyPath: opts.key,
|
|
@@ -36368,7 +36489,7 @@ no fund step; unclaimed openings refund fee-free):
|
|
|
36368
36489
|
}
|
|
36369
36490
|
}
|
|
36370
36491
|
if (isJsonMode()) {
|
|
36371
|
-
printJson({ jobId, digest, buyer: address, seller, amountUsdc, specHash, deliverByMs, reviewWindowMs, rejectSplitBps, ...serviceSlug ? { service: serviceSlug } : {} });
|
|
36492
|
+
printJson({ jobId, digest, buyer: address, seller, amountUsdc, specHash, deliverByMs, reviewWindowMs, rejectSplitBps, feeBps: split4.feeBps, sellerReceiveUsdc: split4.payoutMicro / 1e6, ...serviceSlug ? { service: serviceSlug } : {} });
|
|
36372
36493
|
return;
|
|
36373
36494
|
}
|
|
36374
36495
|
printBlank();
|
|
@@ -36376,6 +36497,7 @@ no fund step; unclaimed openings refund fee-free):
|
|
|
36376
36497
|
if (jobId) printKeyValue("Job", jobId);
|
|
36377
36498
|
printKeyValue("Spec hash", specHash);
|
|
36378
36499
|
printKeyValue("Deliver by", new Date(deliverByMs).toISOString());
|
|
36500
|
+
printKeyValue("Seller receives", sellerReceivesLine(amountUsdc));
|
|
36379
36501
|
if (digest) printKeyValue("Tx", digest);
|
|
36380
36502
|
printBlank();
|
|
36381
36503
|
if (jobId) {
|
|
@@ -36675,8 +36797,8 @@ no fund step; unclaimed openings refund fee-free):
|
|
|
36675
36797
|
}
|
|
36676
36798
|
|
|
36677
36799
|
// src/commands/service.ts
|
|
36678
|
-
var import_picocolors14 = __toESM(require_picocolors(), 1);
|
|
36679
36800
|
import { createHash as createHash2 } from "crypto";
|
|
36801
|
+
var import_picocolors14 = __toESM(require_picocolors(), 1);
|
|
36680
36802
|
import { readFile as readFile5 } from "fs/promises";
|
|
36681
36803
|
var DEFAULT_API_BASE8 = process.env.T2000_API_URL ?? "https://api.t2000.ai/v1";
|
|
36682
36804
|
async function signedServiceAction(opts) {
|
|
@@ -36733,7 +36855,10 @@ function formatSla(minutes) {
|
|
|
36733
36855
|
function printService(o) {
|
|
36734
36856
|
const flag = o.retired ? import_picocolors14.default.dim(" (retired)") : "";
|
|
36735
36857
|
printLine(`${import_picocolors14.default.bold(o.name)} ${import_picocolors14.default.dim(`\xB7 ${o.slug}`)}${flag}`);
|
|
36736
|
-
printKeyValue(
|
|
36858
|
+
printKeyValue(
|
|
36859
|
+
"Price",
|
|
36860
|
+
`$${o.priceUsdc.toFixed(2)} USDC ${import_picocolors14.default.dim(`\xB7 seller receives ${settlementSplit(o.priceUsdc).payout}`)}`
|
|
36861
|
+
);
|
|
36737
36862
|
printKeyValue("Delivery", `within ${formatSla(o.slaMinutes)}`);
|
|
36738
36863
|
printKeyValue(
|
|
36739
36864
|
"Seller",
|
|
@@ -36813,15 +36938,22 @@ Examples:
|
|
|
36813
36938
|
payload
|
|
36814
36939
|
});
|
|
36815
36940
|
if (isJsonMode()) {
|
|
36816
|
-
printJson({
|
|
36941
|
+
printJson({
|
|
36942
|
+
address,
|
|
36943
|
+
...payload,
|
|
36944
|
+
feeBps: SERVICES_SETTLE_FEE_BPS,
|
|
36945
|
+
sellerReceiveUsdc: settlementSplit(priceUsdc).payoutMicro / 1e6
|
|
36946
|
+
});
|
|
36817
36947
|
return;
|
|
36818
36948
|
}
|
|
36819
36949
|
printBlank();
|
|
36820
36950
|
printSuccess(`"${payload.name}" is listed \u2014 $${priceUsdc.toFixed(2)} USDC, delivery within ${formatSla(slaMinutes)}`);
|
|
36951
|
+
printKeyValue("You receive", sellerReceivesLine(priceUsdc));
|
|
36821
36952
|
printKeyValue("Slug", slug);
|
|
36822
36953
|
printKeyValue("Storefront", `https://t2000.ai/${address}`);
|
|
36823
36954
|
printKeyValue("Buyers run", `t2 job hire --agent ${address} --service ${slug}`);
|
|
36824
36955
|
printBlank();
|
|
36956
|
+
printInfo(SETTLE_FEE_NOTE);
|
|
36825
36957
|
printInfo("Watch for incoming jobs with: t2 job watch --mine");
|
|
36826
36958
|
printBlank();
|
|
36827
36959
|
} catch (error) {
|