@t2000/sdk 9.12.0 → 9.13.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/README.md CHANGED
@@ -31,6 +31,8 @@ await agent.pay({ url: 'https://mpp.t2000.ai/openai/v1/chat/completions', method
31
31
 
32
32
  USDC + USDsui sends and x402 USDC payments are gasless (Sui foundation's `0x2::balance::send_funds` sponsor). SUI sends and Cetus swaps need gas — keep ~0.05 SUI on hand.
33
33
 
34
+ The SDK also ships the **escrow-job builders** for agent-to-agent deliverable work (`t2000::a2a_escrow` on Sui mainnet): `buildCreateJobTx` / `buildDeliverJobTx` / `buildReleaseJobTx` / `buildRejectJobTx` / `buildRefundJobTx`, plus `getJob`, `jobActionsFor`, and `verifyJobForSeller`. 2.5% protocol fee on the seller payout at settlement; refunds fee-free.
35
+
34
36
  ## Full reference
35
37
 
36
38
  Factory methods, full API surface, supported assets, Cetus swap routing, x402 payments, error handling, architecture →
package/dist/browser.cjs CHANGED
@@ -1310,6 +1310,18 @@ async function buildSendTx({
1310
1310
  required: amount
1311
1311
  });
1312
1312
  }
1313
+ if (asset === "USDC" || asset === "USDsui") {
1314
+ const rawFloor = displayToRaw(GASLESS_MIN_STABLE_AMOUNT, assetInfo.decimals);
1315
+ const remainder = totalBalance - rawAmount;
1316
+ if (remainder > 0n && remainder < rawFloor) {
1317
+ const total = Number(totalBalance) / 10 ** assetInfo.decimals;
1318
+ throw new exports.T2000Error(
1319
+ "INVALID_AMOUNT",
1320
+ `Gasless ${asset} transfers must send the entire balance or leave at least ${GASLESS_MIN_STABLE_AMOUNT} ${asset}. Sending ${amount} of ${total} leaves ${(total - amount).toFixed(assetInfo.decimals)}. Send ${total} (everything) or at most ${(total - GASLESS_MIN_STABLE_AMOUNT).toFixed(assetInfo.decimals)}.`,
1321
+ { available: total, required: amount }
1322
+ );
1323
+ }
1324
+ }
1313
1325
  if (asset === "SUI") {
1314
1326
  const [sendCoin] = tx.splitCoins(tx.gas, [rawAmount]);
1315
1327
  tx.transferObjects([sendCoin], recipient);
@@ -1547,12 +1559,88 @@ async function verifyJobForSeller({
1547
1559
  return { ok: problems.length === 0, job, problems };
1548
1560
  }
1549
1561
 
1562
+ // src/commerce.ts
1563
+ var DEFAULT_COMMERCE_API_BASE = "https://api.t2000.ai/v1";
1564
+ async function commerceFetchJson(url, init) {
1565
+ const res = await fetch(url, {
1566
+ method: init?.method ?? "GET",
1567
+ headers: init?.body ? { "Content-Type": "application/json" } : void 0,
1568
+ body: init?.body ? JSON.stringify(init.body) : void 0
1569
+ });
1570
+ const json = await res.json().catch(() => ({}));
1571
+ if (!res.ok) {
1572
+ const err = json.error;
1573
+ const msg = typeof err === "string" ? err : err?.message ?? `HTTP ${res.status}`;
1574
+ throw new Error(msg);
1575
+ }
1576
+ return json;
1577
+ }
1578
+ async function listOfferings(base, filter = {}) {
1579
+ const params = new URLSearchParams();
1580
+ if (filter.agent) params.set("agent", filter.agent);
1581
+ if (filter.query) params.set("q", filter.query);
1582
+ const qs = params.size > 0 ? `?${params.toString()}` : "";
1583
+ const json = await commerceFetchJson(`${base}/offerings${qs}`);
1584
+ const offerings = json.offerings ?? [];
1585
+ return { total: json.total ?? offerings.length, offerings };
1586
+ }
1587
+ async function fetchOffering(base, agent, slug) {
1588
+ const { offerings: rows } = await listOfferings(base, { agent });
1589
+ const match = rows.find((o) => o.slug === slug.trim().toLowerCase());
1590
+ if (!match) {
1591
+ const live = rows.filter((o) => !o.retired).map((o) => o.slug);
1592
+ throw new Error(
1593
+ `Agent ${truncateAddress(agent)} has no offering "${slug}".` + (live.length > 0 ? ` Live offerings: ${live.join(", ")}` : "")
1594
+ );
1595
+ }
1596
+ if (match.retired) {
1597
+ throw new Error(
1598
+ `Offering "${slug}" is retired \u2014 the seller no longer sells it.`
1599
+ );
1600
+ }
1601
+ return match;
1602
+ }
1603
+ async function sha256Hex(content) {
1604
+ const digest = await crypto.subtle.digest(
1605
+ "SHA-256",
1606
+ new TextEncoder().encode(content)
1607
+ );
1608
+ return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, "0")).join("");
1609
+ }
1610
+ async function putJobSpec(base, content) {
1611
+ const json = await commerceFetchJson(`${base}/job/spec`, {
1612
+ method: "POST",
1613
+ body: { content }
1614
+ });
1615
+ const hash = json.hash;
1616
+ if (!hash) {
1617
+ throw new Error("Failed to store the job spec.");
1618
+ }
1619
+ return hash;
1620
+ }
1621
+ async function getJobSpec(base, hash) {
1622
+ const clean = hash.trim().toLowerCase().replace(/^0x/, "");
1623
+ const json = await commerceFetchJson(`${base}/job/spec/${clean}`);
1624
+ const content = json.content;
1625
+ if (content === void 0) {
1626
+ throw new Error("No spec stored for this hash.");
1627
+ }
1628
+ const actual = await sha256Hex(content);
1629
+ if (actual !== clean) {
1630
+ throw new Error(
1631
+ "Spec content does NOT match its hash \u2014 the store returned tampered data. Do not trust it."
1632
+ );
1633
+ }
1634
+ return content;
1635
+ }
1636
+
1550
1637
  // src/browser.ts
1551
1638
  init_token_registry();
1552
1639
 
1553
1640
  exports.A2A_ESCROW_FEE_CONFIG_ID = A2A_ESCROW_FEE_CONFIG_ID;
1554
1641
  exports.A2A_ESCROW_PACKAGE_ID = A2A_ESCROW_PACKAGE_ID;
1555
1642
  exports.CLOCK_ID = CLOCK_ID;
1643
+ exports.DEFAULT_COMMERCE_API_BASE = DEFAULT_COMMERCE_API_BASE;
1556
1644
  exports.DEFAULT_NETWORK = DEFAULT_NETWORK;
1557
1645
  exports.GAS_RESERVE_MIN = GAS_RESERVE_MIN;
1558
1646
  exports.JOB_STATES = JOB_STATES;
@@ -1590,6 +1678,7 @@ exports.extractTransferDetails = extractTransferDetails;
1590
1678
  exports.extractTxCommands = extractTxCommands;
1591
1679
  exports.extractTxSender = extractTxSender;
1592
1680
  exports.fallbackLabel = fallbackLabel;
1681
+ exports.fetchOffering = fetchOffering;
1593
1682
  exports.findSwapRoute = findSwapRoute;
1594
1683
  exports.formatAssetAmount = formatAssetAmount;
1595
1684
  exports.formatSui = formatSui;
@@ -1598,7 +1687,9 @@ exports.fromBase64 = fromBase642;
1598
1687
  exports.getDecimals = getDecimals;
1599
1688
  exports.getDecimalsForCoinType = getDecimalsForCoinType;
1600
1689
  exports.getJob = getJob;
1690
+ exports.getJobSpec = getJobSpec;
1601
1691
  exports.jobActionsFor = jobActionsFor;
1692
+ exports.listOfferings = listOfferings;
1602
1693
  exports.mapMoveAbortCode = mapMoveAbortCode;
1603
1694
  exports.mapWalletError = mapWalletError;
1604
1695
  exports.mistToSui = mistToSui;
@@ -1610,6 +1701,7 @@ exports.preflightFail = preflightFail;
1610
1701
  exports.preflightPay = preflightPay;
1611
1702
  exports.preflightSend = preflightSend;
1612
1703
  exports.preflightSwap = preflightSwap;
1704
+ exports.putJobSpec = putJobSpec;
1613
1705
  exports.rawToStable = rawToStable;
1614
1706
  exports.rawToUsdc = rawToUsdc;
1615
1707
  exports.refineLendingLabel = refineLendingLabel;