@t2000/sdk 10.36.0 → 10.37.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/index.cjs CHANGED
@@ -13,10 +13,6 @@ var cryptography = require('@mysten/sui/cryptography');
13
13
  var promises = require('fs/promises');
14
14
  var path = require('path');
15
15
  var os = require('os');
16
- var ed25519$1 = require('@noble/curves/ed25519');
17
- var secp256k1 = require('@noble/curves/secp256k1');
18
- var sha256 = require('@noble/hashes/sha256');
19
- var utils$1 = require('@noble/hashes/utils');
20
16
  var fs = require('fs');
21
17
  var bcs = require('@mysten/sui/bcs');
22
18
  var suins = require('@mysten/suins');
@@ -1427,10 +1423,10 @@ async function finalize(response, opts) {
1427
1423
  return { status: response.status, body: body2, paid: opts.paid };
1428
1424
  }
1429
1425
  async function makeGrpcBuildClient(client) {
1430
- const { SuiGrpcClient: SuiGrpcClient3 } = await import('@mysten/sui/grpc');
1426
+ const { SuiGrpcClient: SuiGrpcClient2 } = await import('@mysten/sui/grpc');
1431
1427
  const network = client.network === "testnet" ? "testnet" : "mainnet";
1432
1428
  const baseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
1433
- return new SuiGrpcClient3({ baseUrl, network });
1429
+ return new SuiGrpcClient2({ baseUrl, network });
1434
1430
  }
1435
1431
  function atomicToHuman(raw, decimals) {
1436
1432
  return Number(raw) / 10 ** decimals;
@@ -2182,8 +2178,7 @@ function body(params, stream) {
2182
2178
  return JSON.stringify({
2183
2179
  model: params.model,
2184
2180
  messages: params.messages,
2185
- // include_usage → the final stream chunk carries usage + x_receipt_id
2186
- // (the confidential attestation receipt) so we can surface it after a stream.
2181
+ // include_usage → the final stream chunk carries usage.
2187
2182
  ...stream ? { stream: true, stream_options: { include_usage: true } } : {},
2188
2183
  ...params.maxTokens != null ? { max_tokens: params.maxTokens } : {},
2189
2184
  ...params.temperature != null ? { temperature: params.temperature } : {}
@@ -2200,14 +2195,12 @@ async function chatCompletion(params) {
2200
2195
  if (!res.ok) {
2201
2196
  await failBody(res);
2202
2197
  }
2203
- const receiptId = res.headers.get("x-receipt-id") ?? void 0;
2204
2198
  const raw = await res.json();
2205
2199
  const content = raw?.choices?.[0]?.message?.content ?? "";
2206
2200
  return {
2207
2201
  content,
2208
2202
  model: raw?.model ?? params.model,
2209
2203
  usage: usageOf(raw),
2210
- receiptId,
2211
2204
  raw
2212
2205
  };
2213
2206
  }
@@ -2221,12 +2214,11 @@ async function* chatCompletionStream(params) {
2221
2214
  });
2222
2215
  if (!(res.ok && res.body)) {
2223
2216
  await failBody(res);
2224
- return {};
2217
+ return;
2225
2218
  }
2226
2219
  const reader = res.body.getReader();
2227
2220
  const decoder = new TextDecoder();
2228
2221
  let buffer = "";
2229
- let receiptId;
2230
2222
  while (true) {
2231
2223
  const { done, value } = await reader.read();
2232
2224
  if (done) {
@@ -2242,13 +2234,10 @@ async function* chatCompletionStream(params) {
2242
2234
  }
2243
2235
  const data = trimmed.slice(5).trim();
2244
2236
  if (data === "[DONE]") {
2245
- return { receiptId };
2237
+ return;
2246
2238
  }
2247
2239
  try {
2248
2240
  const json = JSON.parse(data);
2249
- if (json.x_receipt_id) {
2250
- receiptId = json.x_receipt_id;
2251
- }
2252
2241
  const delta = json.choices?.[0]?.delta?.content;
2253
2242
  if (typeof delta === "string" && delta) {
2254
2243
  yield delta;
@@ -2257,7 +2246,6 @@ async function* chatCompletionStream(params) {
2257
2246
  }
2258
2247
  }
2259
2248
  }
2260
- return { receiptId };
2261
2249
  }
2262
2250
  async function listModels(opts) {
2263
2251
  const base = opts?.apiBase ?? DEFAULT_API_BASE;
@@ -2279,330 +2267,6 @@ async function listModels(opts) {
2279
2267
  reasoning: m.reasoning
2280
2268
  }));
2281
2269
  }
2282
- var RECEIPT_ANCHORED_SUFFIX = "::anchor::ReceiptAnchored";
2283
- function normalizeClaims(claims) {
2284
- if (!claims) {
2285
- return [];
2286
- }
2287
- if (Array.isArray(claims)) {
2288
- return claims.filter((c) => c.name).map((c) => ({
2289
- name: c.name,
2290
- status: c.status ?? "unknown",
2291
- source: c.source
2292
- }));
2293
- }
2294
- return Object.entries(claims).map(([name, v]) => ({
2295
- name,
2296
- status: v?.status ?? "unknown",
2297
- source: v?.source
2298
- }));
2299
- }
2300
- function fullnodeUrl(network) {
2301
- return network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
2302
- }
2303
- function jcs(value) {
2304
- if (value === null) {
2305
- return "null";
2306
- }
2307
- if (typeof value === "boolean") {
2308
- return value ? "true" : "false";
2309
- }
2310
- if (typeof value === "number") {
2311
- if (!Number.isInteger(value)) {
2312
- throw new Error("JCS: non-integer number");
2313
- }
2314
- return String(value);
2315
- }
2316
- if (typeof value === "string") {
2317
- return JSON.stringify(value);
2318
- }
2319
- if (Array.isArray(value)) {
2320
- return `[${value.map(jcs).join(",")}]`;
2321
- }
2322
- const keys = Object.keys(value).sort();
2323
- return `{${keys.map((k) => `${JSON.stringify(k)}:${jcs(value[k])}`).join(",")}}`;
2324
- }
2325
- function verifyReceiptSignature(receipt, signingKeyHex) {
2326
- try {
2327
- const sig = receipt.signature;
2328
- if (!sig?.value) {
2329
- return false;
2330
- }
2331
- const endorsed = utils$1.hexToBytes(signingKeyHex.replace(/^0x/, ""));
2332
- const sigBytes = utils$1.hexToBytes(sig.value);
2333
- if (sig.algo === "ed25519") {
2334
- if (sigBytes.length !== 64 || endorsed.length !== 32) {
2335
- return false;
2336
- }
2337
- const { value: _omitted, ...sigRest } = sig;
2338
- const canonical2 = {
2339
- ...receipt,
2340
- signature: sigRest
2341
- };
2342
- const msg = new TextEncoder().encode(jcs(canonical2));
2343
- return ed25519$1.ed25519.verify(sigBytes, msg, endorsed);
2344
- }
2345
- if (sig.algo !== "ecdsa-secp256k1") {
2346
- return false;
2347
- }
2348
- const canonical = {
2349
- api_version: receipt.api_version ?? "",
2350
- receipt_id: receipt.receipt_id ?? "",
2351
- chat_id: receipt.chat_id ?? null,
2352
- workload_id: receipt.workload_id ?? "",
2353
- workload_keyset_digest: receipt.workload_keyset_digest ?? "",
2354
- endpoint: receipt.endpoint ?? "",
2355
- method: receipt.method ?? "",
2356
- served_at: receipt.served_at ?? 0,
2357
- event_log: receipt.event_log ?? [],
2358
- signature: { algo: sig.algo, key_id: sig.key_id ?? "" }
2359
- };
2360
- const prehash = sha256.sha256(new TextEncoder().encode(jcs(canonical)));
2361
- if (sigBytes.length !== 65) {
2362
- return false;
2363
- }
2364
- let v = sigBytes[64];
2365
- if (v >= 27 && v <= 30) {
2366
- v -= 27;
2367
- }
2368
- if (v > 3) {
2369
- return false;
2370
- }
2371
- const recovered = secp256k1.secp256k1.Signature.fromCompact(sigBytes.slice(0, 64)).addRecoveryBit(v).recoverPublicKey(prehash).toHex(false);
2372
- return recovered.toLowerCase() === utils$1.bytesToHex(endorsed).toLowerCase();
2373
- } catch {
2374
- return false;
2375
- }
2376
- }
2377
- async function verifyTdxQuote(base, model, receiptWorkloadId) {
2378
- let nonce;
2379
- try {
2380
- nonce = utils$1.bytesToHex(globalThis.crypto.getRandomValues(new Uint8Array(32)));
2381
- } catch {
2382
- return { status: "skip", detail: "no secure RNG available", forged: false };
2383
- }
2384
- let report;
2385
- try {
2386
- const res = await fetch(
2387
- `${base}/aci/attestation?model=${encodeURIComponent(model)}&nonce=${nonce}`
2388
- );
2389
- if (res.ok) {
2390
- report = (await res.json()).report;
2391
- }
2392
- } catch {
2393
- }
2394
- const quoteHex = report?.attestation?.evidence?.quote;
2395
- if (!quoteHex) {
2396
- return {
2397
- status: "skip",
2398
- detail: "attestation report (with quote) unavailable \u2014 pass --model?",
2399
- forged: false
2400
- };
2401
- }
2402
- try {
2403
- const dcap = await import('@phala/dcap-qvl');
2404
- const getCollateralAndVerify = dcap.getCollateralAndVerify ?? dcap.default?.getCollateralAndVerify;
2405
- if (typeof getCollateralAndVerify !== "function") {
2406
- return {
2407
- status: "fail",
2408
- forged: false,
2409
- detail: "DCAP verifier unavailable in this build"
2410
- };
2411
- }
2412
- const quoteBytes = utils$1.hexToBytes(quoteHex.replace(/^0x/, ""));
2413
- const vr = await getCollateralAndVerify(quoteBytes);
2414
- const td = vr.report.asTd10() ?? vr.report.asTd15()?.base ?? null;
2415
- const reportData = td?.reportData;
2416
- const signingAddr = report?.signing_address?.replace(/^0x/, "").toLowerCase();
2417
- const addrBound = Boolean(
2418
- reportData && signingAddr && utils$1.bytesToHex(reportData.slice(0, 20)) === signingAddr
2419
- );
2420
- const workloadMatch = report?.workload_id === receiptWorkloadId;
2421
- const tcb = vr.status;
2422
- const tcbBad = tcb === "Revoked" || tcb === "Unknown";
2423
- const forged = !(addrBound && workloadMatch) || tcbBad;
2424
- let detail;
2425
- if (forged && tcbBad) {
2426
- detail = `genuine TDX but TCB ${tcb}`;
2427
- } else if (!addrBound) {
2428
- detail = "report_data does NOT commit the report's signing address";
2429
- } else if (!workloadMatch) {
2430
- detail = "quote workload_id does not match the receipt's";
2431
- } else {
2432
- detail = `genuine Intel TDX (verified vs Intel collateral), TCB ${tcb}; report_data commits the attested signing address`;
2433
- }
2434
- return { status: forged ? "fail" : "pass", forged, tcbStatus: tcb, detail };
2435
- } catch (e) {
2436
- return {
2437
- status: "fail",
2438
- forged: false,
2439
- detail: `could not verify the quote: ${e instanceof Error ? e.message : "error"}`
2440
- };
2441
- }
2442
- }
2443
- async function verifyReceipt(receiptId, opts = {}) {
2444
- const base = opts.apiBase ?? DEFAULT_API_BASE;
2445
- const network = opts.network ?? "mainnet";
2446
- const checks = [];
2447
- let receipt = null;
2448
- try {
2449
- const res = await fetch(`${base}/aci/receipts/${encodeURIComponent(receiptId)}`);
2450
- if (res.ok) {
2451
- receipt = await res.json();
2452
- }
2453
- } catch {
2454
- }
2455
- if (!receipt?.event_log) {
2456
- checks.push({
2457
- name: "Receipt",
2458
- status: "fail",
2459
- detail: "receipt not found or malformed",
2460
- trust: "receipt-asserted"
2461
- });
2462
- return { receiptId, verified: false, anchorVerified: false, checks };
2463
- }
2464
- const wireHash = receipt.event_log.find((e) => e.type === "response.returned")?.wire_hash;
2465
- const workloadId = receipt.workload_id;
2466
- checks.push({
2467
- name: "Receipt",
2468
- status: wireHash && workloadId ? "pass" : "fail",
2469
- detail: wireHash ? `well-formed (${receipt.event_log.length} log entries, workload ${workloadId})` : "missing response wire_hash / workload_id",
2470
- trust: "receipt-asserted"
2471
- });
2472
- const upstreamEv = receipt.event_log.find((e) => e.type === "upstream.verified");
2473
- const upstreamOk = upstreamEv?.result === "verified";
2474
- const claims = normalizeClaims(upstreamEv?.claims);
2475
- checks.push({
2476
- name: "Confidential upstream",
2477
- status: upstreamEv ? upstreamOk ? "pass" : "fail" : "skip",
2478
- 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?)",
2479
- trust: "receipt-asserted"
2480
- });
2481
- let anchorVerified = false;
2482
- let anchor;
2483
- let digest;
2484
- try {
2485
- const res = await fetch(`${base}/aci/anchor/${encodeURIComponent(receiptId)}`);
2486
- if (res.ok) {
2487
- const j = await res.json();
2488
- digest = j.txDigest;
2489
- }
2490
- } catch {
2491
- }
2492
- if (!digest) {
2493
- checks.push({
2494
- name: "Sui anchor",
2495
- status: "fail",
2496
- detail: `no anchor on record \u2014 POST ${base}/aci/anchor/${receiptId} to create one`,
2497
- trust: "trustless"
2498
- });
2499
- } else {
2500
- try {
2501
- const client = new grpc.SuiGrpcClient({ baseUrl: fullnodeUrl(network), network });
2502
- const tx = await client.core.getTransaction({
2503
- digest,
2504
- include: { events: true }
2505
- });
2506
- const txn = tx.$kind === "Transaction" ? tx.Transaction : tx.FailedTransaction;
2507
- const ev = (txn.events ?? []).find(
2508
- (e) => e.eventType.endsWith(RECEIPT_ANCHORED_SUFFIX)
2509
- );
2510
- const data = ev?.json ?? {};
2511
- const onChainReceipt = String(data.receipt_id ?? "");
2512
- const onChainWire = String(data.wire_hash ?? "");
2513
- const onChainWorkload = String(data.workload_id ?? "");
2514
- const matches = onChainReceipt === receiptId && onChainWire === wireHash && onChainWorkload === workloadId;
2515
- anchorVerified = matches;
2516
- anchor = {
2517
- txDigest: digest,
2518
- anchoredAtMs: data.anchored_at_ms ? String(data.anchored_at_ms) : void 0,
2519
- anchoredBy: data.anchored_by ? String(data.anchored_by) : void 0,
2520
- explorer: `https://suiscan.xyz/${network}/tx/${digest}`
2521
- };
2522
- checks.push({
2523
- name: "Sui anchor",
2524
- status: matches ? "pass" : "fail",
2525
- detail: matches ? `on-chain ReceiptAnchored matches (wire_hash + workload_id), tx ${digest}` : `on-chain event does NOT match the receipt (wire ${onChainWire || "absent"})`,
2526
- trust: "trustless"
2527
- });
2528
- } catch (e) {
2529
- checks.push({
2530
- name: "Sui anchor",
2531
- status: "fail",
2532
- detail: `could not read anchor tx ${digest}: ${e instanceof Error ? e.message : "error"}`,
2533
- trust: "trustless"
2534
- });
2535
- }
2536
- }
2537
- let sigStatus = "skip";
2538
- let sigDetail = "no signature on receipt";
2539
- if (receipt.signature?.value) {
2540
- try {
2541
- const model = opts.model ?? "phala/glm-5.2";
2542
- const res = await fetch(
2543
- `${base}/aci/attestation?model=${encodeURIComponent(model)}`
2544
- );
2545
- const att = res.ok ? await res.json() : null;
2546
- if (!att?.signingKey) {
2547
- sigDetail = "could not fetch the attested keyset to check the signature";
2548
- } else if (att.workloadId && att.workloadId !== workloadId) {
2549
- sigDetail = `attested keyset is for a different workload \u2014 pass --model for ${workloadId}`;
2550
- } else {
2551
- const ok = verifyReceiptSignature(receipt, att.signingKey);
2552
- sigStatus = ok ? "pass" : "fail";
2553
- sigDetail = ok ? `signed by the attested receipt key (${receipt.signature.key_id ?? "key"})` : "signature does NOT recover the attested receipt key \u2014 forged/altered";
2554
- }
2555
- } catch {
2556
- sigDetail = "signature check errored";
2557
- }
2558
- }
2559
- checks.push({
2560
- name: "Receipt signature",
2561
- status: sigStatus,
2562
- detail: sigDetail,
2563
- trust: sigStatus === "skip" ? "roadmap" : "trustless"
2564
- });
2565
- if (opts.skipQuote) {
2566
- checks.push({
2567
- name: "TDX quote (DCAP)",
2568
- status: "skip",
2569
- detail: "skipped (--quick)",
2570
- trust: "trustless"
2571
- });
2572
- } else {
2573
- const q = await verifyTdxQuote(
2574
- base,
2575
- opts.model ?? "phala/glm-5.2",
2576
- workloadId ?? ""
2577
- );
2578
- checks.push({
2579
- name: "TDX quote (DCAP)",
2580
- status: q.status,
2581
- detail: q.detail,
2582
- trust: "trustless"
2583
- });
2584
- }
2585
- const trustlessFailed = checks.some(
2586
- (c) => c.trust === "trustless" && c.status === "fail"
2587
- );
2588
- return {
2589
- receiptId,
2590
- verified: Boolean(wireHash && workloadId) && !trustlessFailed,
2591
- anchorVerified,
2592
- checks,
2593
- wireHash,
2594
- workloadId,
2595
- upstream: upstreamEv ? {
2596
- provider: upstreamEv.provider ?? upstreamEv.upstream_name,
2597
- modelId: upstreamEv.model_id,
2598
- result: upstreamEv.result,
2599
- tcbStatus: upstreamEv.tcb_status,
2600
- sessionId: upstreamEv.session_id,
2601
- claims: claims.length > 0 ? claims : void 0
2602
- } : void 0,
2603
- anchor
2604
- };
2605
- }
2606
2270
  var DEFAULT_CONFIG_DIR = path.join(os.homedir(), ".t2000");
2607
2271
  function resolveConfigPath(configDir) {
2608
2272
  return path.join(configDir ?? DEFAULT_CONFIG_DIR, "config.json");
@@ -2926,8 +2590,7 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
2926
2590
  async chat(params) {
2927
2591
  return chatCompletion(params);
2928
2592
  }
2929
- /** Streaming chat completion — async-iterate the assistant text deltas;
2930
- * the generator returns `{ receiptId }` (confidential attestation) at the end. */
2593
+ /** Streaming chat completion — async-iterate the assistant text deltas. */
2931
2594
  chatStream(params) {
2932
2595
  return chatCompletionStream(params);
2933
2596
  }
@@ -2935,11 +2598,6 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
2935
2598
  async models(opts) {
2936
2599
  return listModels(opts);
2937
2600
  }
2938
- /** Verify a confidential response by receipt id — checks the signed receipt
2939
- * + its trustless on-chain Sui anchor. Fails closed on any mismatch. */
2940
- async verify(receiptId, opts) {
2941
- return verifyReceipt(receiptId, opts);
2942
- }
2943
2601
  // -- Swap --
2944
2602
  async swap(params) {
2945
2603
  this.limits.assert({
@@ -3351,7 +3009,7 @@ function feeConfigArg(tx) {
3351
3009
  mutable: false
3352
3010
  });
3353
3011
  }
3354
- function hexToBytes2(hex) {
3012
+ function hexToBytes(hex) {
3355
3013
  const clean = hex.replace(/^0x/, "");
3356
3014
  const bytes = [];
3357
3015
  for (let i = 0; i < clean.length; i += 2) {
@@ -3430,7 +3088,7 @@ async function buildCreateOpeningTx({
3430
3088
  typeArguments: [exports.USDC_TYPE],
3431
3089
  arguments: [
3432
3090
  coin,
3433
- tx.pure.vector("u8", hexToBytes2(terms.specHash)),
3091
+ tx.pure.vector("u8", hexToBytes(terms.specHash)),
3434
3092
  tx.pure.u64(terms.openUntilMs),
3435
3093
  tx.pure.u64(terms.slaMs),
3436
3094
  tx.pure.u64(terms.reviewWindowMs),
@@ -3481,7 +3139,7 @@ function buildCancelOpeningTx(openingId) {
3481
3139
  function buildRefundUnclaimedTx(openingId) {
3482
3140
  return openingCall(openingId, "refund_unclaimed");
3483
3141
  }
3484
- function bytesToHex2(bytes) {
3142
+ function bytesToHex(bytes) {
3485
3143
  return `0x${Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("")}`;
3486
3144
  }
3487
3145
  async function getOpening(client, openingId) {
@@ -3496,7 +3154,7 @@ async function getOpening(client, openingId) {
3496
3154
  buyer: String(json.buyer),
3497
3155
  amountUsdc: Number(json.amount) / 10 ** USDC_DECIMALS,
3498
3156
  feeBps: Number(json.fee_bps ?? 0),
3499
- specHash: bytesToHex2(json.spec_hash ?? []),
3157
+ specHash: bytesToHex(json.spec_hash ?? []),
3500
3158
  openUntilMs: Number(json.open_until_ms),
3501
3159
  slaMs: Number(json.sla_ms),
3502
3160
  reviewWindowMs: Number(json.review_window_ms),
@@ -3533,7 +3191,7 @@ var JOB_STATES = [
3533
3191
  "refunded",
3534
3192
  "rejected"
3535
3193
  ];
3536
- function hexToBytes3(hex) {
3194
+ function hexToBytes2(hex) {
3537
3195
  const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
3538
3196
  if (clean.length === 0 || clean.length % 2 !== 0 || /[^0-9a-fA-F]/.test(clean)) {
3539
3197
  throw new exports.T2000Error(
@@ -3547,7 +3205,7 @@ function hexToBytes3(hex) {
3547
3205
  }
3548
3206
  return out;
3549
3207
  }
3550
- function bytesToHex3(bytes) {
3208
+ function bytesToHex2(bytes) {
3551
3209
  const arr = typeof bytes === "string" ? Array.from(atob(bytes), (c) => c.charCodeAt(0)) : bytes;
3552
3210
  let s = "0x";
3553
3211
  for (const b of arr) s += b.toString(16).padStart(2, "0");
@@ -3584,7 +3242,7 @@ function preflightCreateJob(terms) {
3584
3242
  return preflightFail("INVALID_AMOUNT", "rejectSplitBps must be an integer 0\u201310000.");
3585
3243
  }
3586
3244
  try {
3587
- hexToBytes3(terms.specHash);
3245
+ hexToBytes2(terms.specHash);
3588
3246
  } catch (e) {
3589
3247
  return preflightFail("INVALID_AMOUNT", e.message);
3590
3248
  }
@@ -3612,7 +3270,7 @@ async function buildCreateJobTx({
3612
3270
  arguments: [
3613
3271
  tx.pure.address(seller),
3614
3272
  coin,
3615
- tx.pure.vector("u8", hexToBytes3(terms.specHash)),
3273
+ tx.pure.vector("u8", hexToBytes2(terms.specHash)),
3616
3274
  tx.pure.u64(terms.deliverByMs),
3617
3275
  tx.pure.u64(terms.reviewWindowMs),
3618
3276
  tx.pure.u64(terms.rejectSplitBps),
@@ -3683,7 +3341,7 @@ function buildDeliverJobTx(jobId, deliveryHash) {
3683
3341
  typeArguments: [exports.USDC_TYPE],
3684
3342
  arguments: [
3685
3343
  tx.object(jobId),
3686
- tx.pure.vector("u8", hexToBytes3(deliveryHash)),
3344
+ tx.pure.vector("u8", hexToBytes2(deliveryHash)),
3687
3345
  feeConfigArg2(tx),
3688
3346
  tx.object(CLOCK_ID3)
3689
3347
  ]
@@ -3720,12 +3378,12 @@ async function getJob(client, jobId) {
3720
3378
  amountUsdc: Number(json.amount) / 10 ** USDC_DECIMALS,
3721
3379
  escrowUsdc: Number(json.escrow) / 10 ** USDC_DECIMALS,
3722
3380
  feeBps: Number(json.fee_bps ?? 0),
3723
- specHash: bytesToHex3(json.spec_hash ?? []),
3381
+ specHash: bytesToHex2(json.spec_hash ?? []),
3724
3382
  deliverByMs: Number(json.deliver_by_ms),
3725
3383
  reviewWindowMs: Number(json.review_window_ms),
3726
3384
  rejectSplitBps: Number(json.reject_split_bps),
3727
3385
  state,
3728
- deliveryHash: hasDelivery ? bytesToHex3(deliveryBytes) : null,
3386
+ deliveryHash: hasDelivery ? bytesToHex2(deliveryBytes) : null,
3729
3387
  deliveredAtMs: hasDelivery ? deliveredAtMs : null,
3730
3388
  createdAtMs: Number(json.created_at_ms)
3731
3389
  };
@@ -4104,6 +3762,17 @@ function isCustomHireEnvelope(text) {
4104
3762
  return false;
4105
3763
  }
4106
3764
  }
3765
+
3766
+ // src/sponsored-guard.ts
3767
+ var sponsoredTxGuard = null;
3768
+ function setSponsoredTxGuard(guard) {
3769
+ sponsoredTxGuard = guard;
3770
+ }
3771
+ function runSponsoredTxGuard(ctx) {
3772
+ sponsoredTxGuard?.(ctx);
3773
+ }
3774
+
3775
+ // src/open-jobs.ts
4107
3776
  async function fetchJson(url, init) {
4108
3777
  const res = await fetch(url, {
4109
3778
  method: init?.method ?? "GET",
@@ -4118,19 +3787,28 @@ async function fetchJson(url, init) {
4118
3787
  }
4119
3788
  return json;
4120
3789
  }
4121
- var sponsoredTxGuard = null;
4122
- function setSponsoredTxGuard(guard) {
4123
- sponsoredTxGuard = guard;
4124
- }
4125
3790
  async function listOpenJobs(base, filter = {}) {
4126
3791
  const params = new URLSearchParams();
4127
3792
  if (filter.status) params.set("status", filter.status);
4128
3793
  if (filter.query) params.set("q", filter.query);
4129
3794
  if (filter.buyer) params.set("buyer", filter.buyer);
4130
3795
  if (filter.limit) params.set("limit", String(filter.limit));
3796
+ if (filter.offset) params.set("offset", String(filter.offset));
4131
3797
  const qs = params.size > 0 ? `?${params.toString()}` : "";
4132
3798
  const json = await fetchJson(`${base}/open-jobs${qs}`);
4133
- return json.openJobs ?? [];
3799
+ const openJobs = Array.isArray(json.openJobs) ? json.openJobs : [];
3800
+ const returned = openJobs.length;
3801
+ const total = typeof json.total === "number" && json.total >= returned ? json.total : returned;
3802
+ const startAt = filter.offset ?? 0;
3803
+ const truncated = typeof json.truncated === "boolean" ? json.truncated : startAt + returned < total;
3804
+ const nextOffset = typeof json.nextOffset === "number" ? json.nextOffset : truncated ? startAt + returned : void 0;
3805
+ return {
3806
+ total,
3807
+ returned,
3808
+ truncated,
3809
+ ...nextOffset === void 0 ? {} : { nextOffset },
3810
+ openJobs
3811
+ };
4134
3812
  }
4135
3813
  async function getOpenJob(base, id) {
4136
3814
  const json = await fetchJson(
@@ -4140,7 +3818,7 @@ async function getOpenJob(base, id) {
4140
3818
  }
4141
3819
  async function sponsoredOpeningVerb(base, signer, action, params) {
4142
3820
  const address = signer.getAddress();
4143
- sponsoredTxGuard?.({ base, action });
3821
+ runSponsoredTxGuard({ base, action });
4144
3822
  const prep = await fetchJson(`${base}/job/prepare`, {
4145
3823
  method: "POST",
4146
3824
  body: { address, action, params }
@@ -4150,7 +3828,7 @@ async function sponsoredOpeningVerb(base, signer, action, params) {
4150
3828
  if (!(nonce && txBytes)) {
4151
3829
  throw new Error("Failed to prepare the transaction.");
4152
3830
  }
4153
- sponsoredTxGuard?.({ base, action, txBytes });
3831
+ runSponsoredTxGuard({ base, action, txBytes });
4154
3832
  const { signature } = await signer.signTransaction(utils.fromBase64(txBytes));
4155
3833
  const json = await fetchJson(`${base}/job/submit`, {
4156
3834
  method: "POST",
@@ -4187,6 +3865,495 @@ function refundOpenJob(base, signer, openingId) {
4187
3865
  });
4188
3866
  }
4189
3867
 
3868
+ // src/commerce/endpoint.ts
3869
+ init_errors();
3870
+
3871
+ // src/commerce/http.ts
3872
+ init_errors();
3873
+ var DEFAULT_COMMERCE_API_BASE2 = "https://api.t2000.ai/v1";
3874
+ function codeForStatus(status) {
3875
+ if (status === 400 || status === 409 || status === 422) {
3876
+ return "INVALID_INPUT";
3877
+ }
3878
+ if (status === 429 || status >= 500) {
3879
+ return "RPC_ERROR";
3880
+ }
3881
+ return "UNKNOWN";
3882
+ }
3883
+ function apiErrorMessage(json, status) {
3884
+ const err = json.error;
3885
+ if (typeof err === "string") {
3886
+ return err;
3887
+ }
3888
+ const msg = err?.message;
3889
+ return typeof msg === "string" ? msg : `HTTP ${status}`;
3890
+ }
3891
+ async function apiRequest(url, init) {
3892
+ const res = await fetch(url, {
3893
+ method: init?.method ?? (init?.body === void 0 ? "GET" : "POST"),
3894
+ headers: {
3895
+ accept: "application/json",
3896
+ ...init?.body === void 0 ? {} : { "Content-Type": "application/json" }
3897
+ },
3898
+ body: init?.body === void 0 ? void 0 : JSON.stringify(init.body)
3899
+ });
3900
+ const json = await res.json().catch(() => ({}));
3901
+ return { ok: res.ok, status: res.status, json };
3902
+ }
3903
+ async function apiJson(url, init) {
3904
+ const res = await apiRequest(url, init);
3905
+ if (!res.ok) {
3906
+ throw new exports.T2000Error(codeForStatus(res.status), apiErrorMessage(res.json, res.status), {
3907
+ status: res.status,
3908
+ ...res.json.error && typeof res.json.error === "object" ? { api: res.json.error } : {}
3909
+ });
3910
+ }
3911
+ return res.json;
3912
+ }
3913
+ function invalidInput(message) {
3914
+ return new exports.T2000Error("INVALID_INPUT", message);
3915
+ }
3916
+ async function signPreparedTx(base, action, signer, txBytes) {
3917
+ runSponsoredTxGuard({ base, action, txBytes });
3918
+ const { signature } = await signer.signTransaction(utils.fromBase64(txBytes));
3919
+ return signature;
3920
+ }
3921
+
3922
+ // src/commerce/endpoint.ts
3923
+ function endpointIssueLines(prep) {
3924
+ const lines = (prep.probe?.issues ?? []).map(
3925
+ (i) => ` \u2717 ${i.message ?? i.code}`
3926
+ );
3927
+ for (const r of prep.routes ?? []) {
3928
+ if (r.probeOk === false) {
3929
+ lines.push(` \u2717 ${r.method ?? "POST"} ${r.path}`);
3930
+ for (const i of r.issues ?? []) {
3931
+ lines.push(` ${i.message ?? i.code}`);
3932
+ }
3933
+ }
3934
+ }
3935
+ return lines;
3936
+ }
3937
+ async function setEndpoint(apiBase, signer, endpoint, primary) {
3938
+ const address = signer.getAddress();
3939
+ runSponsoredTxGuard({ base: apiBase, action: "update" });
3940
+ const res = await apiRequest(`${apiBase}/agent/endpoint/prepare`, {
3941
+ method: "POST",
3942
+ body: { address, endpoint, ...primary ? { primary } : {} }
3943
+ });
3944
+ const prep = res.json;
3945
+ if (!res.ok) {
3946
+ const msg = apiErrorMessage(prep, res.status);
3947
+ const detail = endpointIssueLines(prep).join("\n");
3948
+ throw new exports.T2000Error(
3949
+ "INVALID_INPUT",
3950
+ detail ? `${msg}
3951
+ ${detail}` : msg,
3952
+ { status: res.status, probe: prep.probe ?? null, routes: prep.routes ?? [] }
3953
+ );
3954
+ }
3955
+ if (!(typeof prep.nonce === "string" && typeof prep.txBytes === "string")) {
3956
+ throw invalidInput("Failed to prepare the listing.");
3957
+ }
3958
+ const signature = await signPreparedTx(apiBase, "update", signer, prep.txBytes);
3959
+ const sub = await apiJson(`${apiBase}/agent/endpoint/submit`, {
3960
+ method: "POST",
3961
+ body: { nonce: prep.nonce, address, signature }
3962
+ });
3963
+ const listed = endpoint !== "";
3964
+ return {
3965
+ address,
3966
+ endpoint: listed ? prep.primary?.url ?? endpoint : null,
3967
+ listed,
3968
+ probe: prep.probe ?? null,
3969
+ origin: prep.origin ?? null,
3970
+ primary: prep.primary ?? null,
3971
+ routes: prep.routes ?? [],
3972
+ ...typeof sub.digest === "string" ? { digest: sub.digest } : {}
3973
+ };
3974
+ }
3975
+ function listEndpoint(apiBase, signer, endpoint, opts = {}) {
3976
+ const target = endpoint.trim();
3977
+ if (!target) {
3978
+ throw invalidInput("Provide your x402 endpoint URL.");
3979
+ }
3980
+ return setEndpoint(apiBase, signer, target, opts.primary);
3981
+ }
3982
+ function removeEndpoint(apiBase, signer) {
3983
+ return setEndpoint(apiBase, signer, "");
3984
+ }
3985
+
3986
+ // src/commerce/types.ts
3987
+ var AGENT_CATEGORIES = [
3988
+ "ai-models",
3989
+ "data-feeds",
3990
+ "finance",
3991
+ "research",
3992
+ "dev-tools",
3993
+ "creative",
3994
+ "travel",
3995
+ "comms",
3996
+ "other"
3997
+ ];
3998
+ var SERVICE_TIERS = ["basic", "standard", "premium"];
3999
+
4000
+ // src/commerce/package-slug.ts
4001
+ var SERVICE_SLUG_RE = /^[a-z0-9][a-z0-9-]{1,47}$/;
4002
+ function trimDashes(s) {
4003
+ let start = 0;
4004
+ let end = s.length;
4005
+ while (start < end && s.charCodeAt(start) === 45) start += 1;
4006
+ while (end > start && s.charCodeAt(end - 1) === 45) end -= 1;
4007
+ return s.slice(start, end);
4008
+ }
4009
+ function slugify(name) {
4010
+ return trimDashes(name.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-")).slice(0, 48);
4011
+ }
4012
+ var TIER_SLUG_RE = /^(.+)-(basic|standard|premium)$/;
4013
+ var MAX_TIER_BASE_LENGTH = 48 - "-standard".length;
4014
+ function parseServiceTierSlug(slug) {
4015
+ const m = TIER_SLUG_RE.exec(slug);
4016
+ if (!m) {
4017
+ return null;
4018
+ }
4019
+ return { base: m[1], tier: m[2] };
4020
+ }
4021
+ function packageBaseSlug(slugified) {
4022
+ const cut = slugified.slice(0, MAX_TIER_BASE_LENGTH);
4023
+ let end = cut.length;
4024
+ while (end > 0 && cut.charCodeAt(end - 1) === 45) end -= 1;
4025
+ return cut.slice(0, end);
4026
+ }
4027
+ function packageTierSlugs(base) {
4028
+ return SERVICE_TIERS.map((tier) => ({ tier, slug: `${base}-${tier}` }));
4029
+ }
4030
+
4031
+ // src/commerce/challenge.ts
4032
+ async function sha256Hex2(content) {
4033
+ const digest = await crypto.subtle.digest(
4034
+ "SHA-256",
4035
+ new TextEncoder().encode(content)
4036
+ );
4037
+ return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, "0")).join("");
4038
+ }
4039
+ function servicePayloadSha256(payload) {
4040
+ return sha256Hex2(JSON.stringify(payload));
4041
+ }
4042
+ function profileChallengeMessage(nonce) {
4043
+ return `t2000-agent-profile:${nonce}`;
4044
+ }
4045
+ function serviceChallengeMessage(nonce, payloadHash) {
4046
+ return `t2000-agent-service:${nonce}:${payloadHash}`;
4047
+ }
4048
+ async function fetchChallengeNonce(apiBase, address) {
4049
+ const challenge = await apiJson(`${apiBase}/agent/challenge`, {
4050
+ method: "POST",
4051
+ body: { address }
4052
+ });
4053
+ const nonce = challenge.nonce;
4054
+ if (typeof nonce !== "string" || !nonce) {
4055
+ throw invalidInput("Failed to get a challenge nonce.");
4056
+ }
4057
+ return nonce;
4058
+ }
4059
+ async function signChallenge(apiBase, signer, message) {
4060
+ const nonce = await fetchChallengeNonce(apiBase, signer.getAddress());
4061
+ const text = await message(nonce);
4062
+ const { signature } = await signer.signPersonalMessage(
4063
+ new TextEncoder().encode(text)
4064
+ );
4065
+ return { nonce, signature };
4066
+ }
4067
+
4068
+ // src/commerce/service.ts
4069
+ function serviceUpsertPayload(input) {
4070
+ const slug = input.slug.trim().toLowerCase();
4071
+ if (!SERVICE_SLUG_RE.test(slug)) {
4072
+ throw invalidInput(
4073
+ "slug must be 2-48 chars of [a-z0-9-], starting alphanumeric."
4074
+ );
4075
+ }
4076
+ return {
4077
+ ...input.mode ? { mode: input.mode } : {},
4078
+ slug,
4079
+ name: input.name.trim(),
4080
+ description: input.description.trim(),
4081
+ priceUsdc: input.priceUsdc,
4082
+ slaMinutes: input.slaMinutes,
4083
+ reviewWindowMinutes: input.reviewWindowMinutes ?? 1440,
4084
+ rejectSplitBps: input.rejectSplitBps ?? 8e3,
4085
+ requirements: input.requirements,
4086
+ deliverable: input.deliverable.trim(),
4087
+ ...input.examples === void 0 ? {} : { examples: input.examples }
4088
+ };
4089
+ }
4090
+ async function signedServiceAction(apiBase, signer, action, payload) {
4091
+ const address = signer.getAddress();
4092
+ const { nonce, signature } = await signChallenge(
4093
+ apiBase,
4094
+ signer,
4095
+ async (n) => serviceChallengeMessage(n, await servicePayloadSha256(payload))
4096
+ );
4097
+ return apiJson(`${apiBase}/agent/service`, {
4098
+ method: "POST",
4099
+ body: { address, nonce, signature, action, payload }
4100
+ });
4101
+ }
4102
+ async function upsertService(apiBase, signer, input) {
4103
+ const payload = serviceUpsertPayload(input);
4104
+ const response = await signedServiceAction(apiBase, signer, "upsert", payload);
4105
+ return { address: signer.getAddress(), slug: payload.slug, response };
4106
+ }
4107
+ async function retireService(apiBase, signer, slug) {
4108
+ const clean = slug.trim().toLowerCase();
4109
+ if (!SERVICE_SLUG_RE.test(clean)) {
4110
+ throw invalidInput("slug must be 2-48 chars of [a-z0-9-], starting alphanumeric.");
4111
+ }
4112
+ const response = await signedServiceAction(apiBase, signer, "retire", {
4113
+ slug: clean
4114
+ });
4115
+ return { address: signer.getAddress(), slug: clean, response };
4116
+ }
4117
+
4118
+ // src/commerce/package.ts
4119
+ function planPackage(input) {
4120
+ const name = input.name.trim();
4121
+ if (!name) {
4122
+ throw invalidInput("name is required.");
4123
+ }
4124
+ const base = packageBaseSlug((input.baseSlug ?? slugify(name)).trim().toLowerCase());
4125
+ if (!base || !SERVICE_SLUG_RE.test(`${base}-basic`)) {
4126
+ throw invalidInput(
4127
+ "Could not derive a package slug from the name \u2014 pass baseSlug (a-z, 0-9, dashes)."
4128
+ );
4129
+ }
4130
+ const byTier = /* @__PURE__ */ new Map();
4131
+ for (const t of input.tiers) {
4132
+ if (!SERVICE_TIERS.includes(t.tier)) {
4133
+ throw invalidInput(`Unknown tier "${t.tier}" \u2014 use basic, standard, premium.`);
4134
+ }
4135
+ if (byTier.has(t.tier)) {
4136
+ throw invalidInput(`Tier "${t.tier}" given twice.`);
4137
+ }
4138
+ byTier.set(t.tier, t);
4139
+ }
4140
+ const missing = SERVICE_TIERS.filter((t) => !byTier.has(t));
4141
+ if (missing.length > 0) {
4142
+ throw invalidInput(
4143
+ `A package needs all three tiers \u2014 missing: ${missing.join(", ")}.`
4144
+ );
4145
+ }
4146
+ return {
4147
+ base,
4148
+ tiers: packageTierSlugs(base).map(({ tier, slug }) => {
4149
+ const t = byTier.get(tier);
4150
+ return {
4151
+ tier,
4152
+ slug,
4153
+ input: {
4154
+ mode: "create",
4155
+ slug,
4156
+ name,
4157
+ description: (t.description ?? input.description).trim(),
4158
+ priceUsdc: t.priceUsdc,
4159
+ slaMinutes: t.slaMinutes ?? input.slaMinutes,
4160
+ deliverable: t.deliverable,
4161
+ requirements: input.requirements,
4162
+ reviewWindowMinutes: t.reviewWindowMinutes ?? input.reviewWindowMinutes,
4163
+ rejectSplitBps: t.rejectSplitBps ?? input.rejectSplitBps
4164
+ }
4165
+ };
4166
+ })
4167
+ };
4168
+ }
4169
+ async function createPackage(apiBase, signer, input) {
4170
+ const plan = planPackage(input);
4171
+ const tiers = [];
4172
+ for (const t of plan.tiers) {
4173
+ await upsertService(apiBase, signer, t.input);
4174
+ tiers.push({ tier: t.tier, slug: t.slug, priceUsdc: t.input.priceUsdc });
4175
+ }
4176
+ return { address: signer.getAddress(), base: plan.base, tiers };
4177
+ }
4178
+
4179
+ // src/commerce/resolve.ts
4180
+ init_errors();
4181
+ var FALLBACK_MISS = "Use an Agent ID (#93), @handle, or full 0x\u2026 address.";
4182
+ function agentResolveUrl(q, apiBase = DEFAULT_COMMERCE_API_BASE2) {
4183
+ return `${apiBase}/agents/resolve?q=${encodeURIComponent(q.trim())}`;
4184
+ }
4185
+ async function resolveAgentRef(q, apiBase = DEFAULT_COMMERCE_API_BASE2) {
4186
+ const res = await apiRequest(agentResolveUrl(q, apiBase));
4187
+ const json = res.json;
4188
+ if (!(res.ok && typeof json.address === "string")) {
4189
+ throw new exports.T2000Error(
4190
+ "CONTACT_NOT_FOUND",
4191
+ typeof json.error === "string" ? json.error : FALLBACK_MISS,
4192
+ { ref: q }
4193
+ );
4194
+ }
4195
+ return {
4196
+ address: json.address,
4197
+ ...typeof json.numericId === "number" || json.numericId === null ? { numericId: json.numericId } : {},
4198
+ ...typeof json.name === "string" ? { name: json.name } : {}
4199
+ };
4200
+ }
4201
+ async function getAgentProfile(address, apiBase = DEFAULT_COMMERCE_API_BASE2) {
4202
+ const res = await apiRequest(`${apiBase}/agents/${encodeURIComponent(address)}`);
4203
+ if (!res.ok) {
4204
+ return null;
4205
+ }
4206
+ return { ...res.json, address };
4207
+ }
4208
+
4209
+ // src/commerce/profile.ts
4210
+ function parseAgentCategory(raw) {
4211
+ const c = raw.trim().toLowerCase();
4212
+ if (!AGENT_CATEGORIES.includes(c)) {
4213
+ throw invalidInput(
4214
+ `category must be one of: ${AGENT_CATEGORIES.join(", ")} (got "${raw}").`
4215
+ );
4216
+ }
4217
+ return c;
4218
+ }
4219
+ async function updateProfile(apiBase, signer, input) {
4220
+ const hasField = input.name !== void 0 || input.imageUrl !== void 0 || input.description !== void 0 || input.category !== void 0 || input.website !== void 0 || input.twitter !== void 0 || input.github !== void 0;
4221
+ if (!hasField) {
4222
+ throw invalidInput(
4223
+ "Provide at least one of name, imageUrl, description, category, website, twitter, github."
4224
+ );
4225
+ }
4226
+ const category = input.category === void 0 ? void 0 : parseAgentCategory(input.category);
4227
+ const address = signer.getAddress();
4228
+ const { nonce, signature } = await signChallenge(
4229
+ apiBase,
4230
+ signer,
4231
+ profileChallengeMessage
4232
+ );
4233
+ await apiJson(`${apiBase}/agent/profile`, {
4234
+ method: "POST",
4235
+ body: {
4236
+ address,
4237
+ nonce,
4238
+ signature,
4239
+ displayName: input.name,
4240
+ imageUrl: input.imageUrl,
4241
+ description: input.description,
4242
+ category,
4243
+ website: input.website,
4244
+ twitter: input.twitter,
4245
+ github: input.github
4246
+ }
4247
+ });
4248
+ return { address };
4249
+ }
4250
+ async function ensureCategory(apiBase, signer, category) {
4251
+ if (category !== void 0) {
4252
+ const parsed = parseAgentCategory(category);
4253
+ await updateProfile(apiBase, signer, { category: parsed });
4254
+ return parsed;
4255
+ }
4256
+ const profile = await getAgentProfile(signer.getAddress(), apiBase).catch(
4257
+ () => null
4258
+ );
4259
+ const existing = typeof profile?.category === "string" && profile.category ? profile.category : null;
4260
+ if (!existing) {
4261
+ throw invalidInput(
4262
+ `Pick a directory category first \u2014 buyers browse listings by category. Set one of ${AGENT_CATEGORIES.join(" | ")} (updateProfile({ category }) / t2 agent profile --category).`
4263
+ );
4264
+ }
4265
+ return existing;
4266
+ }
4267
+
4268
+ // src/commerce/register.ts
4269
+ async function registerAgent(apiBase, signer) {
4270
+ const address = signer.getAddress();
4271
+ runSponsoredTxGuard({ base: apiBase, action: "register" });
4272
+ const prep = await apiJson(`${apiBase}/agent/register/prepare`, {
4273
+ method: "POST",
4274
+ body: { address }
4275
+ });
4276
+ if (prep.alreadyRegistered === true) {
4277
+ return { address, alreadyRegistered: true };
4278
+ }
4279
+ const regNonce = prep.regNonce;
4280
+ const txBytes = prep.txBytes;
4281
+ if (!(typeof regNonce === "string" && typeof txBytes === "string")) {
4282
+ throw invalidInput("Failed to prepare registration.");
4283
+ }
4284
+ const signature = await signPreparedTx(apiBase, "register", signer, txBytes);
4285
+ const res = await apiJson(`${apiBase}/agent/register/submit`, {
4286
+ method: "POST",
4287
+ body: { regNonce, address, agentSignature: signature }
4288
+ });
4289
+ return {
4290
+ address,
4291
+ alreadyRegistered: res.alreadyRegistered === true,
4292
+ ...typeof res.digest === "string" ? { digest: res.digest } : {}
4293
+ };
4294
+ }
4295
+
4296
+ // src/commerce/client.ts
4297
+ var CommerceClient = class {
4298
+ signer;
4299
+ apiBase;
4300
+ constructor(options) {
4301
+ this.signer = options.signer;
4302
+ let base = options.apiBase ?? DEFAULT_COMMERCE_API_BASE2;
4303
+ while (base.endsWith("/")) base = base.slice(0, -1);
4304
+ this.apiBase = base;
4305
+ }
4306
+ /** This signer's wallet address. */
4307
+ get address() {
4308
+ return this.signer.getAddress();
4309
+ }
4310
+ /** Register the wallet as an on-chain Agent ID (sponsored; idempotent). */
4311
+ register() {
4312
+ return registerAgent(this.apiBase, this.signer);
4313
+ }
4314
+ /** Set public profile fields (signed, no gas). */
4315
+ updateProfile(input) {
4316
+ return updateProfile(this.apiBase, this.signer, input);
4317
+ }
4318
+ /** The sell gate — set `category` or confirm the live one; throws when
4319
+ * neither exists. Returns the category in force. */
4320
+ ensureCategory(category) {
4321
+ return ensureCategory(this.apiBase, this.signer, category);
4322
+ }
4323
+ /** This seller's public profile (null when unregistered). */
4324
+ profile() {
4325
+ return getAgentProfile(this.address, this.apiBase);
4326
+ }
4327
+ /** List (or fully re-write) one service — `mode: "create"` refuses a live slug. */
4328
+ upsertService(input) {
4329
+ return upsertService(this.apiBase, this.signer, input);
4330
+ }
4331
+ /** Take a service off the board (funded jobs keep settling on-chain). */
4332
+ retireService(input) {
4333
+ return retireService(
4334
+ this.apiBase,
4335
+ this.signer,
4336
+ typeof input === "string" ? input : input.slug
4337
+ );
4338
+ }
4339
+ /** Three tiers under one name — `{base}-basic|standard|premium`. */
4340
+ createPackage(input) {
4341
+ return createPackage(this.apiBase, this.signer, input);
4342
+ }
4343
+ /** Sell an x402 API (origin or one 402 URL) — live-probed, sponsored. */
4344
+ listEndpoint(endpoint, opts = {}) {
4345
+ return listEndpoint(this.apiBase, this.signer, endpoint, opts);
4346
+ }
4347
+ /** Clear the x402 listing. */
4348
+ removeEndpoint() {
4349
+ return removeEndpoint(this.apiBase, this.signer);
4350
+ }
4351
+ /** `#93` · `@handle` · `name.sui` · `0x…` → wallet (marketplace refs only). */
4352
+ resolveRef(q) {
4353
+ return resolveAgentRef(q, this.apiBase);
4354
+ }
4355
+ };
4356
+
4190
4357
  // src/utils/resolve-created.ts
4191
4358
  var OPENING_TYPE_MARKER = "::opening::Opening<";
4192
4359
  var ESCROW_JOB_TYPE_MARKER = "::escrow::Job<";
@@ -4638,11 +4805,13 @@ exports.A2A_ESCROW_PACKAGE_V6_ID = A2A_ESCROW_PACKAGE_V6_ID;
4638
4805
  exports.A2A_ESCROW_PACKAGE_V7_ID = A2A_ESCROW_PACKAGE_V7_ID;
4639
4806
  exports.A2A_ESCROW_PACKAGE_V8_ID = A2A_ESCROW_PACKAGE_V8_ID;
4640
4807
  exports.A2A_SCORE_BOARD_ID = A2A_SCORE_BOARD_ID;
4808
+ exports.AGENT_CATEGORIES = AGENT_CATEGORIES;
4641
4809
  exports.AUDRIC_PARENT = AUDRIC_PARENT;
4642
4810
  exports.AUDRIC_PARENT_NAME = AUDRIC_PARENT_NAME;
4643
4811
  exports.AUDRIC_PARENT_NFT_ID = AUDRIC_PARENT_NFT_ID;
4644
4812
  exports.CETUS_USDC_SUI_POOL = CETUS_USDC_SUI_POOL;
4645
4813
  exports.CLOCK_ID = CLOCK_ID;
4814
+ exports.CommerceClient = CommerceClient;
4646
4815
  exports.DEFAULT_ACTIVITY_REPORT_URL = DEFAULT_ACTIVITY_REPORT_URL;
4647
4816
  exports.DEFAULT_API_BASE = DEFAULT_API_BASE;
4648
4817
  exports.DEFAULT_COMMERCE_API_BASE = DEFAULT_COMMERCE_API_BASE;
@@ -4667,6 +4836,7 @@ exports.MAX_DELIVER_HORIZON_MS = MAX_DELIVER_HORIZON_MS;
4667
4836
  exports.MAX_JOB_USDC = MAX_JOB_USDC;
4668
4837
  exports.MAX_OPEN_WINDOW_MS = MAX_OPEN_WINDOW_MS;
4669
4838
  exports.MAX_REVIEW_WINDOW_MS = MAX_REVIEW_WINDOW_MS;
4839
+ exports.MAX_TIER_BASE_LENGTH = MAX_TIER_BASE_LENGTH;
4670
4840
  exports.MIN_JOB_USDC = MIN_JOB_USDC;
4671
4841
  exports.MIST_PER_SUI = MIST_PER_SUI;
4672
4842
  exports.OPENING_CLAIM_POLICIES = OPENING_CLAIM_POLICIES;
@@ -4680,6 +4850,8 @@ exports.PROVEN_MIN_REVIEWS = PROVEN_MIN_REVIEWS;
4680
4850
  exports.REVIEW_MAX_STARS = REVIEW_MAX_STARS;
4681
4851
  exports.REVIEW_MIN_STARS = REVIEW_MIN_STARS;
4682
4852
  exports.SENDABLE_ASSETS = SENDABLE_ASSETS;
4853
+ exports.SERVICE_SLUG_RE = SERVICE_SLUG_RE;
4854
+ exports.SERVICE_TIERS = SERVICE_TIERS;
4683
4855
  exports.SPONSORED_PYTH_DEPENDENT_PROVIDERS = SPONSORED_PYTH_DEPENDENT_PROVIDERS;
4684
4856
  exports.STABLE_ASSETS = STABLE_ASSETS;
4685
4857
  exports.SUINS_NAME_REGEX = SUINS_NAME_REGEX;
@@ -4696,6 +4868,7 @@ exports.WRITE_APPENDER_REGISTRY = WRITE_APPENDER_REGISTRY;
4696
4868
  exports.ZkLoginSigner = ZkLoginSigner;
4697
4869
  exports.addSendToTx = addSendToTx;
4698
4870
  exports.addSwapToTx = addSwapToTx;
4871
+ exports.agentResolveUrl = agentResolveUrl;
4699
4872
  exports.approxUsdValue = approxUsdValue;
4700
4873
  exports.assertAllowedAsset = assertAllowedAsset;
4701
4874
  exports.assertBuyerRequirements = assertBuyerRequirements;
@@ -4732,12 +4905,15 @@ exports.classifySendAsset = classifySendAsset;
4732
4905
  exports.classifyTransaction = classifyTransaction;
4733
4906
  exports.clearLimits = clearLimits;
4734
4907
  exports.composeTx = composeTx;
4908
+ exports.createPackage = createPackage;
4735
4909
  exports.customHireEnvelope = customHireEnvelope;
4736
4910
  exports.dailySpentToday = dailySpentToday;
4737
4911
  exports.deriveAgentScoreId = deriveAgentScoreId;
4738
4912
  exports.deriveAllowedAddressesFromPtb = deriveAllowedAddressesFromPtb;
4739
4913
  exports.deserializeCetusRoute = deserializeCetusRoute;
4740
4914
  exports.displayHandle = displayHandle;
4915
+ exports.endpointIssueLines = endpointIssueLines;
4916
+ exports.ensureCategory = ensureCategory;
4741
4917
  exports.executeTx = executeTx;
4742
4918
  exports.exportPrivateKey = exportPrivateKey;
4743
4919
  exports.extractAllUserLegs = extractAllUserLegs;
@@ -4746,6 +4922,7 @@ exports.extractTxCommands = extractTxCommands;
4746
4922
  exports.extractTxSender = extractTxSender;
4747
4923
  exports.fallbackLabel = fallbackLabel;
4748
4924
  exports.fetchAllCoins = fetchAllCoins;
4925
+ exports.fetchChallengeNonce = fetchChallengeNonce;
4749
4926
  exports.fetchService = fetchService;
4750
4927
  exports.findSwapRoute = findSwapRoute;
4751
4928
  exports.formatAssetAmount = formatAssetAmount;
@@ -4754,6 +4931,7 @@ exports.formatUsd = formatUsd;
4754
4931
  exports.fullHandle = fullHandle;
4755
4932
  exports.generateKeypair = generateKeypair;
4756
4933
  exports.getAddress = getAddress;
4934
+ exports.getAgentProfile = getAgentProfile;
4757
4935
  exports.getAgentScore = getAgentScore;
4758
4936
  exports.getCoinMeta = getCoinMeta;
4759
4937
  exports.getDecimals = getDecimals;
@@ -4775,6 +4953,7 @@ exports.isCustomHireEnvelope = isCustomHireEnvelope;
4775
4953
  exports.isInRegistry = isInRegistry;
4776
4954
  exports.jobActionsFor = jobActionsFor;
4777
4955
  exports.keypairFromPrivateKey = keypairFromPrivateKey;
4956
+ exports.listEndpoint = listEndpoint;
4778
4957
  exports.listModels = listModels;
4779
4958
  exports.listOpenJobs = listOpenJobs;
4780
4959
  exports.listServices = listServices;
@@ -4787,8 +4966,13 @@ exports.mistToSui = mistToSui;
4787
4966
  exports.normalizeAddressInput = normalizeAddressInput;
4788
4967
  exports.normalizeAsset = normalizeAsset;
4789
4968
  exports.normalizeCoinType = normalizeCoinType;
4969
+ exports.packageBaseSlug = packageBaseSlug;
4970
+ exports.packageTierSlugs = packageTierSlugs;
4971
+ exports.parseAgentCategory = parseAgentCategory;
4972
+ exports.parseServiceTierSlug = parseServiceTierSlug;
4790
4973
  exports.parseSuiRpcTx = parseSuiRpcTx;
4791
4974
  exports.payWithX402 = payWithX402;
4975
+ exports.planPackage = planPackage;
4792
4976
  exports.postOpenJob = postOpenJob;
4793
4977
  exports.preflightCreateJob = preflightCreateJob;
4794
4978
  exports.preflightCreateOpening = preflightCreateOpening;
@@ -4797,6 +4981,7 @@ exports.preflightPay = preflightPay;
4797
4981
  exports.preflightSend = preflightSend;
4798
4982
  exports.preflightSwap = preflightSwap;
4799
4983
  exports.probeX402 = probeX402;
4984
+ exports.profileChallengeMessage = profileChallengeMessage;
4800
4985
  exports.putJobSpec = putJobSpec;
4801
4986
  exports.queryBalance = queryBalance;
4802
4987
  exports.queryHistory = queryHistory;
@@ -4807,30 +4992,41 @@ exports.readLimitsFile = readLimitsFile;
4807
4992
  exports.recordDailySpend = recordDailySpend;
4808
4993
  exports.refineLendingLabel = refineLendingLabel;
4809
4994
  exports.refundOpenJob = refundOpenJob;
4995
+ exports.registerAgent = registerAgent;
4996
+ exports.removeEndpoint = removeEndpoint;
4810
4997
  exports.reportX402Activity = reportX402Activity;
4811
4998
  exports.resolveAddressToSuinsViaRpc = resolveAddressToSuinsViaRpc;
4999
+ exports.resolveAgentRef = resolveAgentRef;
4812
5000
  exports.resolveCreatedObjectId = resolveCreatedObjectId;
4813
5001
  exports.resolveSuinsViaRpc = resolveSuinsViaRpc;
4814
5002
  exports.resolveSymbol = resolveSymbol;
4815
5003
  exports.resolveTokenType = resolveTokenType;
5004
+ exports.retireService = retireService;
4816
5005
  exports.saveBech32 = saveBech32;
4817
5006
  exports.saveKey = saveKey;
4818
5007
  exports.selectAndSplitCoin = selectAndSplitCoin;
4819
5008
  exports.selectSuiCoin = selectSuiCoin;
4820
5009
  exports.serializeCetusRoute = serializeCetusRoute;
5010
+ exports.serviceChallengeMessage = serviceChallengeMessage;
5011
+ exports.servicePayloadSha256 = servicePayloadSha256;
5012
+ exports.serviceUpsertPayload = serviceUpsertPayload;
4821
5013
  exports.setLimits = setLimits;
4822
5014
  exports.setSponsoredTxGuard = setSponsoredTxGuard;
5015
+ exports.signChallenge = signChallenge;
4823
5016
  exports.simulateTransaction = simulateTransaction;
5017
+ exports.slugify = slugify;
4824
5018
  exports.stableToRaw = stableToRaw;
4825
5019
  exports.submitJobReview = submitJobReview;
4826
5020
  exports.suiToMist = suiToMist;
4827
5021
  exports.throwIfSimulationFailed = throwIfSimulationFailed;
5022
+ exports.trimDashes = trimDashes;
4828
5023
  exports.truncateAddress = truncateAddress;
5024
+ exports.updateProfile = updateProfile;
5025
+ exports.upsertService = upsertService;
4829
5026
  exports.usdcToRaw = usdcToRaw;
4830
5027
  exports.validateAddress = validateAddress;
4831
5028
  exports.validateLabel = validateLabel;
4832
5029
  exports.verifyCetusRouteCoinMatch = verifyCetusRouteCoinMatch;
4833
5030
  exports.verifyJobForSeller = verifyJobForSeller;
4834
- exports.verifyReceipt = verifyReceipt;
4835
5031
  exports.walletExists = walletExists;
4836
5032
  exports.writeLimitsFile = writeLimitsFile;