@t2000/sdk 9.6.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
@@ -3131,6 +3131,209 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
3131
3131
 
3132
3132
  // src/index.ts
3133
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
3134
3337
  init_coinSelection();
3135
3338
 
3136
3339
  // src/composeTx.ts
@@ -3554,6 +3757,7 @@ function displayHandle(label, parentName = AUDRIC_PARENT_NAME) {
3554
3757
  // src/index.ts
3555
3758
  init_preflight();
3556
3759
 
3760
+ exports.A2A_ESCROW_PACKAGE_ID = A2A_ESCROW_PACKAGE_ID;
3557
3761
  exports.AGENT_ID_PARENT = AGENT_ID_PARENT;
3558
3762
  exports.AGENT_ID_PARENT_NAME = AGENT_ID_PARENT_NAME;
3559
3763
  exports.AGENT_ID_PARENT_NFT_ID = AGENT_ID_PARENT_NFT_ID;
@@ -3569,11 +3773,13 @@ exports.GASLESS_MIN_STABLE_AMOUNT = GASLESS_MIN_STABLE_AMOUNT;
3569
3773
  exports.GASLESS_STABLE_TYPES = GASLESS_STABLE_TYPES;
3570
3774
  exports.GAS_RESERVE_MIN = GAS_RESERVE_MIN;
3571
3775
  exports.InvalidAddressError = InvalidAddressError;
3776
+ exports.JOB_STATES = JOB_STATES;
3572
3777
  exports.KNOWN_TARGETS = KNOWN_TARGETS;
3573
3778
  exports.KeypairSigner = KeypairSigner;
3574
3779
  exports.LABEL_PATTERNS = LABEL_PATTERNS;
3575
3780
  exports.LimitEnforcer = LimitEnforcer;
3576
3781
  exports.LimitExceededError = LimitExceededError;
3782
+ exports.MAX_JOB_USDC = MAX_JOB_USDC;
3577
3783
  exports.MIST_PER_SUI = MIST_PER_SUI;
3578
3784
  exports.OPERATION_ASSETS = OPERATION_ASSETS;
3579
3785
  exports.SENDABLE_ASSETS = SENDABLE_ASSETS;
@@ -3597,6 +3803,11 @@ exports.approxUsdValue = approxUsdValue;
3597
3803
  exports.assertAllowedAsset = assertAllowedAsset;
3598
3804
  exports.assertLimitConfig = assertLimitConfig;
3599
3805
  exports.buildAddLeafTx = buildAddLeafTx;
3806
+ exports.buildCreateJobTx = buildCreateJobTx;
3807
+ exports.buildDeliverJobTx = buildDeliverJobTx;
3808
+ exports.buildRefundJobTx = buildRefundJobTx;
3809
+ exports.buildRejectJobTx = buildRejectJobTx;
3810
+ exports.buildReleaseJobTx = buildReleaseJobTx;
3600
3811
  exports.buildRevokeLeafTx = buildRevokeLeafTx;
3601
3812
  exports.buildSendTx = buildSendTx;
3602
3813
  exports.buildSwapTx = buildSwapTx;
@@ -3631,6 +3842,7 @@ exports.getAddress = getAddress;
3631
3842
  exports.getCoinMeta = getCoinMeta;
3632
3843
  exports.getDecimals = getDecimals;
3633
3844
  exports.getDecimalsForCoinType = getDecimalsForCoinType;
3845
+ exports.getJob = getJob;
3634
3846
  exports.getLimits = getLimits;
3635
3847
  exports.getSponsoredSwapProviders = getSponsoredSwapProviders;
3636
3848
  exports.getSuiClient = getSuiClient;
@@ -3640,6 +3852,7 @@ exports.hasLimits = hasLimits;
3640
3852
  exports.isAllowedAsset = isAllowedAsset;
3641
3853
  exports.isCetusRouteFresh = isCetusRouteFresh;
3642
3854
  exports.isInRegistry = isInRegistry;
3855
+ exports.jobActionsFor = jobActionsFor;
3643
3856
  exports.keypairFromPrivateKey = keypairFromPrivateKey;
3644
3857
  exports.listModels = listModels;
3645
3858
  exports.loadKey = loadKey;
@@ -3653,6 +3866,7 @@ exports.normalizeCoinType = normalizeCoinType;
3653
3866
  exports.parseMppSuiChallenge = parseMppSuiChallenge;
3654
3867
  exports.parseSuiRpcTx = parseSuiRpcTx;
3655
3868
  exports.payWithMpp = payWithMpp;
3869
+ exports.preflightCreateJob = preflightCreateJob;
3656
3870
  exports.preflightFail = preflightFail;
3657
3871
  exports.preflightPay = preflightPay;
3658
3872
  exports.preflightSend = preflightSend;
@@ -3684,6 +3898,7 @@ exports.usdcToRaw = usdcToRaw;
3684
3898
  exports.validateAddress = validateAddress;
3685
3899
  exports.validateLabel = validateLabel;
3686
3900
  exports.verifyCetusRouteCoinMatch = verifyCetusRouteCoinMatch;
3901
+ exports.verifyJobForSeller = verifyJobForSeller;
3687
3902
  exports.verifyReceipt = verifyReceipt;
3688
3903
  exports.walletExists = walletExists;
3689
3904
  exports.writeLimitsFile = writeLimitsFile;