@t2000/sdk 9.5.0 → 9.7.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
@@ -1051,6 +1051,7 @@ var KeypairSigner = class {
1051
1051
  constructor(keypair) {
1052
1052
  this.keypair = keypair;
1053
1053
  }
1054
+ kind = "keypair";
1054
1055
  getAddress() {
1055
1056
  return this.keypair.getPublicKey().toSuiAddress();
1056
1057
  }
@@ -1157,6 +1158,13 @@ async function payWithMpp(args) {
1157
1158
  }
1158
1159
  const headerChallenge = await parseMppSuiChallenge(probe);
1159
1160
  if (headerChallenge) {
1161
+ if (signer.kind === "zklogin") {
1162
+ throw new exports.T2000Error(
1163
+ "DIALECT_UNSUPPORTED",
1164
+ "This seller only offers the MPP header dialect, which zkLogin (Passport) wallets cannot safely pay: the seller cannot verify zkLogin signatures, so the payment would settle on-chain without the service delivering. No payment was made. Use an x402-capable service, or pay from a keypair wallet (t2 CLI / MCP).",
1165
+ { dialect: "mpp-header", signerKind: "zklogin" }
1166
+ );
1167
+ }
1160
1168
  const result = await payViaMppHeader({ signer, client, options });
1161
1169
  await reportDirectPayment(result, options.url);
1162
1170
  return result;
@@ -1394,6 +1402,7 @@ var ZkLoginSigner = class {
1394
1402
  this.userAddress = userAddress;
1395
1403
  this.maxEpoch = maxEpoch;
1396
1404
  }
1405
+ kind = "zklogin";
1397
1406
  getAddress() {
1398
1407
  return this.userAddress;
1399
1408
  }
@@ -3122,6 +3131,209 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
3122
3131
 
3123
3132
  // src/index.ts
3124
3133
  init_errors();
3134
+
3135
+ // src/wallet/job.ts
3136
+ init_errors();
3137
+ init_token_registry();
3138
+ init_preflight();
3139
+ init_coinSelection();
3140
+ var A2A_ESCROW_PACKAGE_ID = process.env.A2A_ESCROW_PACKAGE_ID ?? "0x9e67c380fb7079d793d6d15ff916b24d82779d7119bfa4631863102ed485c0a0";
3141
+ var CLOCK_ID2 = "0x6";
3142
+ var MODULE = "escrow";
3143
+ var MAX_JOB_USDC = 50;
3144
+ var JOB_STATES = [
3145
+ "funded",
3146
+ "delivered",
3147
+ "released",
3148
+ "refunded",
3149
+ "rejected"
3150
+ ];
3151
+ function hexToBytes2(hex) {
3152
+ const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
3153
+ if (clean.length === 0 || clean.length % 2 !== 0 || /[^0-9a-fA-F]/.test(clean)) {
3154
+ throw new exports.T2000Error(
3155
+ "INVALID_AMOUNT",
3156
+ `Expected a hex hash (0x\u2026), got "${hex.slice(0, 32)}"`
3157
+ );
3158
+ }
3159
+ const out = [];
3160
+ for (let i = 0; i < clean.length; i += 2) {
3161
+ out.push(Number.parseInt(clean.slice(i, i + 2), 16));
3162
+ }
3163
+ return out;
3164
+ }
3165
+ function bytesToHex2(bytes) {
3166
+ let s = "0x";
3167
+ for (const b of bytes) s += b.toString(16).padStart(2, "0");
3168
+ return s;
3169
+ }
3170
+ function preflightCreateJob(terms) {
3171
+ const addressCheck = checkSuiAddress(terms.seller);
3172
+ if (!addressCheck.valid) return addressCheck;
3173
+ if (!Number.isFinite(terms.amountUsdc) || terms.amountUsdc <= 0) {
3174
+ return preflightFail("INVALID_AMOUNT", `Amount must be positive. Got ${terms.amountUsdc}.`);
3175
+ }
3176
+ if (terms.amountUsdc > MAX_JOB_USDC) {
3177
+ return preflightFail(
3178
+ "INVALID_AMOUNT",
3179
+ `v1 caps escrow jobs at ${MAX_JOB_USDC} USDC (no-arbitration split only stays fair at small sizes). Got ${terms.amountUsdc}.`
3180
+ );
3181
+ }
3182
+ if (terms.deliverByMs <= Date.now()) {
3183
+ return preflightFail("INVALID_AMOUNT", "deliverByMs must be in the future.");
3184
+ }
3185
+ if (terms.reviewWindowMs < 0) {
3186
+ return preflightFail("INVALID_AMOUNT", "reviewWindowMs must be \u2265 0.");
3187
+ }
3188
+ if (!Number.isInteger(terms.rejectSplitBps) || terms.rejectSplitBps < 0 || terms.rejectSplitBps > 1e4) {
3189
+ return preflightFail("INVALID_AMOUNT", "rejectSplitBps must be an integer 0\u201310000.");
3190
+ }
3191
+ try {
3192
+ hexToBytes2(terms.specHash);
3193
+ } catch (e) {
3194
+ return preflightFail("INVALID_AMOUNT", e.message);
3195
+ }
3196
+ return exports.PREFLIGHT_OK;
3197
+ }
3198
+ async function buildCreateJobTx({
3199
+ client,
3200
+ buyer,
3201
+ terms
3202
+ }) {
3203
+ const pf = preflightCreateJob(terms);
3204
+ if (!pf.valid) throw new exports.T2000Error(pf.code, pf.error);
3205
+ const seller = validateAddress(terms.seller);
3206
+ if (seller === validateAddress(buyer)) {
3207
+ throw new exports.T2000Error("INVALID_ADDRESS", "Buyer and seller must be different wallets.");
3208
+ }
3209
+ const rawAmount = BigInt(Math.floor(terms.amountUsdc * 10 ** USDC_DECIMALS));
3210
+ const tx = new transactions.Transaction();
3211
+ const { coin } = await selectAndSplitCoin(tx, client, buyer, exports.USDC_TYPE, rawAmount, {
3212
+ allowSwapAll: false
3213
+ });
3214
+ tx.moveCall({
3215
+ target: `${A2A_ESCROW_PACKAGE_ID}::${MODULE}::create`,
3216
+ typeArguments: [exports.USDC_TYPE],
3217
+ arguments: [
3218
+ tx.pure.address(seller),
3219
+ coin,
3220
+ tx.pure.vector("u8", hexToBytes2(terms.specHash)),
3221
+ tx.pure.u64(terms.deliverByMs),
3222
+ tx.pure.u64(terms.reviewWindowMs),
3223
+ tx.pure.u64(terms.rejectSplitBps),
3224
+ tx.object(CLOCK_ID2)
3225
+ ]
3226
+ });
3227
+ return tx;
3228
+ }
3229
+ function jobCall(jobId, fn) {
3230
+ const tx = new transactions.Transaction();
3231
+ tx.moveCall({
3232
+ target: `${A2A_ESCROW_PACKAGE_ID}::${MODULE}::${fn}`,
3233
+ typeArguments: [exports.USDC_TYPE],
3234
+ arguments: [tx.object(jobId), tx.object(CLOCK_ID2)]
3235
+ });
3236
+ return tx;
3237
+ }
3238
+ function buildDeliverJobTx(jobId, deliveryHash) {
3239
+ const tx = new transactions.Transaction();
3240
+ tx.moveCall({
3241
+ target: `${A2A_ESCROW_PACKAGE_ID}::${MODULE}::deliver`,
3242
+ typeArguments: [exports.USDC_TYPE],
3243
+ arguments: [
3244
+ tx.object(jobId),
3245
+ tx.pure.vector("u8", hexToBytes2(deliveryHash)),
3246
+ tx.object(CLOCK_ID2)
3247
+ ]
3248
+ });
3249
+ return tx;
3250
+ }
3251
+ function buildReleaseJobTx(jobId) {
3252
+ return jobCall(jobId, "release");
3253
+ }
3254
+ function buildRejectJobTx(jobId) {
3255
+ return jobCall(jobId, "reject");
3256
+ }
3257
+ function buildRefundJobTx(jobId) {
3258
+ return jobCall(jobId, "refund");
3259
+ }
3260
+ async function getJob(client, jobId) {
3261
+ const resp = await client.core.getObject({ objectId: jobId, include: { json: true } }).catch((e) => {
3262
+ throw new exports.T2000Error(
3263
+ "RPC_ERROR",
3264
+ `Job ${jobId} not found: ${e instanceof Error ? e.message : String(e)}`
3265
+ );
3266
+ });
3267
+ const objType = resp.object?.type ?? "";
3268
+ const json = resp.object?.json;
3269
+ if (!json || !objType.includes(`::${MODULE}::Job<`)) {
3270
+ throw new exports.T2000Error("RPC_ERROR", `Object ${jobId} is not an a2a_escrow Job.`);
3271
+ }
3272
+ const stateNum = Number(json.state ?? -1);
3273
+ const state = JOB_STATES[stateNum];
3274
+ if (!state) {
3275
+ throw new exports.T2000Error("RPC_ERROR", `Job ${jobId} has unknown state ${stateNum}.`);
3276
+ }
3277
+ const deliveredAtMs = Number(json.delivered_at_ms ?? 0);
3278
+ const deliveryBytes = json.delivery_hash ?? [];
3279
+ const hasDelivery = deliveredAtMs > 0;
3280
+ return {
3281
+ id: jobId,
3282
+ buyer: String(json.buyer),
3283
+ seller: String(json.seller),
3284
+ amountUsdc: Number(json.amount) / 10 ** USDC_DECIMALS,
3285
+ escrowUsdc: Number(json.escrow) / 10 ** USDC_DECIMALS,
3286
+ specHash: bytesToHex2(json.spec_hash ?? []),
3287
+ deliverByMs: Number(json.deliver_by_ms),
3288
+ reviewWindowMs: Number(json.review_window_ms),
3289
+ rejectSplitBps: Number(json.reject_split_bps),
3290
+ state,
3291
+ deliveryHash: hasDelivery ? bytesToHex2(deliveryBytes) : null,
3292
+ deliveredAtMs: hasDelivery ? deliveredAtMs : null,
3293
+ createdAtMs: Number(json.created_at_ms)
3294
+ };
3295
+ }
3296
+ function jobActionsFor(job, caller, nowMs = Date.now()) {
3297
+ const me = validateAddress(caller);
3298
+ const isBuyer = me === job.buyer;
3299
+ const isSeller = me === job.seller;
3300
+ const actions = [];
3301
+ if (job.state === "funded") {
3302
+ if (isSeller && nowMs <= job.deliverByMs) actions.push("deliver");
3303
+ if (isBuyer) actions.push("release");
3304
+ if (nowMs > job.deliverByMs) actions.push("refund");
3305
+ } else if (job.state === "delivered") {
3306
+ const windowClosesMs = (job.deliveredAtMs ?? 0) + job.reviewWindowMs;
3307
+ if (isBuyer && nowMs <= windowClosesMs) actions.push("release", "reject");
3308
+ if (nowMs > windowClosesMs) actions.push("release");
3309
+ }
3310
+ return actions;
3311
+ }
3312
+ async function verifyJobForSeller({
3313
+ client,
3314
+ jobId,
3315
+ seller,
3316
+ minAmountUsdc,
3317
+ minRunwayMs = 6e4
3318
+ }) {
3319
+ const job = await getJob(client, jobId);
3320
+ const problems = [];
3321
+ if (job.state !== "funded") {
3322
+ problems.push(`state is "${job.state}", expected "funded"`);
3323
+ }
3324
+ if (job.seller !== validateAddress(seller)) {
3325
+ problems.push(`job pays ${job.seller}, not this seller`);
3326
+ }
3327
+ if (job.escrowUsdc < minAmountUsdc) {
3328
+ problems.push(`escrow holds ${job.escrowUsdc} USDC, price is ${minAmountUsdc}`);
3329
+ }
3330
+ if (job.deliverByMs - Date.now() < minRunwayMs) {
3331
+ problems.push("deadline too close to accept");
3332
+ }
3333
+ return { ok: problems.length === 0, job, problems };
3334
+ }
3335
+
3336
+ // src/index.ts
3125
3337
  init_coinSelection();
3126
3338
 
3127
3339
  // src/composeTx.ts
@@ -3545,6 +3757,7 @@ function displayHandle(label, parentName = AUDRIC_PARENT_NAME) {
3545
3757
  // src/index.ts
3546
3758
  init_preflight();
3547
3759
 
3760
+ exports.A2A_ESCROW_PACKAGE_ID = A2A_ESCROW_PACKAGE_ID;
3548
3761
  exports.AGENT_ID_PARENT = AGENT_ID_PARENT;
3549
3762
  exports.AGENT_ID_PARENT_NAME = AGENT_ID_PARENT_NAME;
3550
3763
  exports.AGENT_ID_PARENT_NFT_ID = AGENT_ID_PARENT_NFT_ID;
@@ -3560,11 +3773,13 @@ exports.GASLESS_MIN_STABLE_AMOUNT = GASLESS_MIN_STABLE_AMOUNT;
3560
3773
  exports.GASLESS_STABLE_TYPES = GASLESS_STABLE_TYPES;
3561
3774
  exports.GAS_RESERVE_MIN = GAS_RESERVE_MIN;
3562
3775
  exports.InvalidAddressError = InvalidAddressError;
3776
+ exports.JOB_STATES = JOB_STATES;
3563
3777
  exports.KNOWN_TARGETS = KNOWN_TARGETS;
3564
3778
  exports.KeypairSigner = KeypairSigner;
3565
3779
  exports.LABEL_PATTERNS = LABEL_PATTERNS;
3566
3780
  exports.LimitEnforcer = LimitEnforcer;
3567
3781
  exports.LimitExceededError = LimitExceededError;
3782
+ exports.MAX_JOB_USDC = MAX_JOB_USDC;
3568
3783
  exports.MIST_PER_SUI = MIST_PER_SUI;
3569
3784
  exports.OPERATION_ASSETS = OPERATION_ASSETS;
3570
3785
  exports.SENDABLE_ASSETS = SENDABLE_ASSETS;
@@ -3588,6 +3803,11 @@ exports.approxUsdValue = approxUsdValue;
3588
3803
  exports.assertAllowedAsset = assertAllowedAsset;
3589
3804
  exports.assertLimitConfig = assertLimitConfig;
3590
3805
  exports.buildAddLeafTx = buildAddLeafTx;
3806
+ exports.buildCreateJobTx = buildCreateJobTx;
3807
+ exports.buildDeliverJobTx = buildDeliverJobTx;
3808
+ exports.buildRefundJobTx = buildRefundJobTx;
3809
+ exports.buildRejectJobTx = buildRejectJobTx;
3810
+ exports.buildReleaseJobTx = buildReleaseJobTx;
3591
3811
  exports.buildRevokeLeafTx = buildRevokeLeafTx;
3592
3812
  exports.buildSendTx = buildSendTx;
3593
3813
  exports.buildSwapTx = buildSwapTx;
@@ -3622,6 +3842,7 @@ exports.getAddress = getAddress;
3622
3842
  exports.getCoinMeta = getCoinMeta;
3623
3843
  exports.getDecimals = getDecimals;
3624
3844
  exports.getDecimalsForCoinType = getDecimalsForCoinType;
3845
+ exports.getJob = getJob;
3625
3846
  exports.getLimits = getLimits;
3626
3847
  exports.getSponsoredSwapProviders = getSponsoredSwapProviders;
3627
3848
  exports.getSuiClient = getSuiClient;
@@ -3631,6 +3852,7 @@ exports.hasLimits = hasLimits;
3631
3852
  exports.isAllowedAsset = isAllowedAsset;
3632
3853
  exports.isCetusRouteFresh = isCetusRouteFresh;
3633
3854
  exports.isInRegistry = isInRegistry;
3855
+ exports.jobActionsFor = jobActionsFor;
3634
3856
  exports.keypairFromPrivateKey = keypairFromPrivateKey;
3635
3857
  exports.listModels = listModels;
3636
3858
  exports.loadKey = loadKey;
@@ -3644,6 +3866,7 @@ exports.normalizeCoinType = normalizeCoinType;
3644
3866
  exports.parseMppSuiChallenge = parseMppSuiChallenge;
3645
3867
  exports.parseSuiRpcTx = parseSuiRpcTx;
3646
3868
  exports.payWithMpp = payWithMpp;
3869
+ exports.preflightCreateJob = preflightCreateJob;
3647
3870
  exports.preflightFail = preflightFail;
3648
3871
  exports.preflightPay = preflightPay;
3649
3872
  exports.preflightSend = preflightSend;
@@ -3675,6 +3898,7 @@ exports.usdcToRaw = usdcToRaw;
3675
3898
  exports.validateAddress = validateAddress;
3676
3899
  exports.validateLabel = validateLabel;
3677
3900
  exports.verifyCetusRouteCoinMatch = verifyCetusRouteCoinMatch;
3901
+ exports.verifyJobForSeller = verifyJobForSeller;
3678
3902
  exports.verifyReceipt = verifyReceipt;
3679
3903
  exports.walletExists = walletExists;
3680
3904
  exports.writeLimitsFile = writeLimitsFile;