@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/browser.cjs +212 -0
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +201 -1
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +215 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +204 -1
- package/dist/index.js.map +1 -1
- package/dist/{send-YAYf0YR3.d.cts → job-CSq0DRsC.d.cts} +107 -1
- package/dist/{send-YAYf0YR3.d.ts → job-CSq0DRsC.d.ts} +107 -1
- package/package.json +1 -1
package/dist/browser.cjs
CHANGED
|
@@ -1314,15 +1314,218 @@ async function buildSendTx({
|
|
|
1314
1314
|
return tx;
|
|
1315
1315
|
}
|
|
1316
1316
|
|
|
1317
|
+
// src/wallet/job.ts
|
|
1318
|
+
init_errors();
|
|
1319
|
+
init_token_registry();
|
|
1320
|
+
init_coinSelection();
|
|
1321
|
+
var A2A_ESCROW_PACKAGE_ID = process.env.A2A_ESCROW_PACKAGE_ID ?? "0x9e67c380fb7079d793d6d15ff916b24d82779d7119bfa4631863102ed485c0a0";
|
|
1322
|
+
var CLOCK_ID2 = "0x6";
|
|
1323
|
+
var MODULE = "escrow";
|
|
1324
|
+
var MAX_JOB_USDC = 50;
|
|
1325
|
+
var JOB_STATES = [
|
|
1326
|
+
"funded",
|
|
1327
|
+
"delivered",
|
|
1328
|
+
"released",
|
|
1329
|
+
"refunded",
|
|
1330
|
+
"rejected"
|
|
1331
|
+
];
|
|
1332
|
+
function hexToBytes(hex) {
|
|
1333
|
+
const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
1334
|
+
if (clean.length === 0 || clean.length % 2 !== 0 || /[^0-9a-fA-F]/.test(clean)) {
|
|
1335
|
+
throw new exports.T2000Error(
|
|
1336
|
+
"INVALID_AMOUNT",
|
|
1337
|
+
`Expected a hex hash (0x\u2026), got "${hex.slice(0, 32)}"`
|
|
1338
|
+
);
|
|
1339
|
+
}
|
|
1340
|
+
const out = [];
|
|
1341
|
+
for (let i = 0; i < clean.length; i += 2) {
|
|
1342
|
+
out.push(Number.parseInt(clean.slice(i, i + 2), 16));
|
|
1343
|
+
}
|
|
1344
|
+
return out;
|
|
1345
|
+
}
|
|
1346
|
+
function bytesToHex(bytes) {
|
|
1347
|
+
let s = "0x";
|
|
1348
|
+
for (const b of bytes) s += b.toString(16).padStart(2, "0");
|
|
1349
|
+
return s;
|
|
1350
|
+
}
|
|
1351
|
+
function preflightCreateJob(terms) {
|
|
1352
|
+
const addressCheck = checkSuiAddress(terms.seller);
|
|
1353
|
+
if (!addressCheck.valid) return addressCheck;
|
|
1354
|
+
if (!Number.isFinite(terms.amountUsdc) || terms.amountUsdc <= 0) {
|
|
1355
|
+
return preflightFail("INVALID_AMOUNT", `Amount must be positive. Got ${terms.amountUsdc}.`);
|
|
1356
|
+
}
|
|
1357
|
+
if (terms.amountUsdc > MAX_JOB_USDC) {
|
|
1358
|
+
return preflightFail(
|
|
1359
|
+
"INVALID_AMOUNT",
|
|
1360
|
+
`v1 caps escrow jobs at ${MAX_JOB_USDC} USDC (no-arbitration split only stays fair at small sizes). Got ${terms.amountUsdc}.`
|
|
1361
|
+
);
|
|
1362
|
+
}
|
|
1363
|
+
if (terms.deliverByMs <= Date.now()) {
|
|
1364
|
+
return preflightFail("INVALID_AMOUNT", "deliverByMs must be in the future.");
|
|
1365
|
+
}
|
|
1366
|
+
if (terms.reviewWindowMs < 0) {
|
|
1367
|
+
return preflightFail("INVALID_AMOUNT", "reviewWindowMs must be \u2265 0.");
|
|
1368
|
+
}
|
|
1369
|
+
if (!Number.isInteger(terms.rejectSplitBps) || terms.rejectSplitBps < 0 || terms.rejectSplitBps > 1e4) {
|
|
1370
|
+
return preflightFail("INVALID_AMOUNT", "rejectSplitBps must be an integer 0\u201310000.");
|
|
1371
|
+
}
|
|
1372
|
+
try {
|
|
1373
|
+
hexToBytes(terms.specHash);
|
|
1374
|
+
} catch (e) {
|
|
1375
|
+
return preflightFail("INVALID_AMOUNT", e.message);
|
|
1376
|
+
}
|
|
1377
|
+
return PREFLIGHT_OK;
|
|
1378
|
+
}
|
|
1379
|
+
async function buildCreateJobTx({
|
|
1380
|
+
client,
|
|
1381
|
+
buyer,
|
|
1382
|
+
terms
|
|
1383
|
+
}) {
|
|
1384
|
+
const pf = preflightCreateJob(terms);
|
|
1385
|
+
if (!pf.valid) throw new exports.T2000Error(pf.code, pf.error);
|
|
1386
|
+
const seller = validateAddress(terms.seller);
|
|
1387
|
+
if (seller === validateAddress(buyer)) {
|
|
1388
|
+
throw new exports.T2000Error("INVALID_ADDRESS", "Buyer and seller must be different wallets.");
|
|
1389
|
+
}
|
|
1390
|
+
const rawAmount = BigInt(Math.floor(terms.amountUsdc * 10 ** USDC_DECIMALS));
|
|
1391
|
+
const tx = new transactions.Transaction();
|
|
1392
|
+
const { coin } = await selectAndSplitCoin(tx, client, buyer, exports.USDC_TYPE, rawAmount, {
|
|
1393
|
+
allowSwapAll: false
|
|
1394
|
+
});
|
|
1395
|
+
tx.moveCall({
|
|
1396
|
+
target: `${A2A_ESCROW_PACKAGE_ID}::${MODULE}::create`,
|
|
1397
|
+
typeArguments: [exports.USDC_TYPE],
|
|
1398
|
+
arguments: [
|
|
1399
|
+
tx.pure.address(seller),
|
|
1400
|
+
coin,
|
|
1401
|
+
tx.pure.vector("u8", hexToBytes(terms.specHash)),
|
|
1402
|
+
tx.pure.u64(terms.deliverByMs),
|
|
1403
|
+
tx.pure.u64(terms.reviewWindowMs),
|
|
1404
|
+
tx.pure.u64(terms.rejectSplitBps),
|
|
1405
|
+
tx.object(CLOCK_ID2)
|
|
1406
|
+
]
|
|
1407
|
+
});
|
|
1408
|
+
return tx;
|
|
1409
|
+
}
|
|
1410
|
+
function jobCall(jobId, fn) {
|
|
1411
|
+
const tx = new transactions.Transaction();
|
|
1412
|
+
tx.moveCall({
|
|
1413
|
+
target: `${A2A_ESCROW_PACKAGE_ID}::${MODULE}::${fn}`,
|
|
1414
|
+
typeArguments: [exports.USDC_TYPE],
|
|
1415
|
+
arguments: [tx.object(jobId), tx.object(CLOCK_ID2)]
|
|
1416
|
+
});
|
|
1417
|
+
return tx;
|
|
1418
|
+
}
|
|
1419
|
+
function buildDeliverJobTx(jobId, deliveryHash) {
|
|
1420
|
+
const tx = new transactions.Transaction();
|
|
1421
|
+
tx.moveCall({
|
|
1422
|
+
target: `${A2A_ESCROW_PACKAGE_ID}::${MODULE}::deliver`,
|
|
1423
|
+
typeArguments: [exports.USDC_TYPE],
|
|
1424
|
+
arguments: [
|
|
1425
|
+
tx.object(jobId),
|
|
1426
|
+
tx.pure.vector("u8", hexToBytes(deliveryHash)),
|
|
1427
|
+
tx.object(CLOCK_ID2)
|
|
1428
|
+
]
|
|
1429
|
+
});
|
|
1430
|
+
return tx;
|
|
1431
|
+
}
|
|
1432
|
+
function buildReleaseJobTx(jobId) {
|
|
1433
|
+
return jobCall(jobId, "release");
|
|
1434
|
+
}
|
|
1435
|
+
function buildRejectJobTx(jobId) {
|
|
1436
|
+
return jobCall(jobId, "reject");
|
|
1437
|
+
}
|
|
1438
|
+
function buildRefundJobTx(jobId) {
|
|
1439
|
+
return jobCall(jobId, "refund");
|
|
1440
|
+
}
|
|
1441
|
+
async function getJob(client, jobId) {
|
|
1442
|
+
const resp = await client.core.getObject({ objectId: jobId, include: { json: true } }).catch((e) => {
|
|
1443
|
+
throw new exports.T2000Error(
|
|
1444
|
+
"RPC_ERROR",
|
|
1445
|
+
`Job ${jobId} not found: ${e instanceof Error ? e.message : String(e)}`
|
|
1446
|
+
);
|
|
1447
|
+
});
|
|
1448
|
+
const objType = resp.object?.type ?? "";
|
|
1449
|
+
const json = resp.object?.json;
|
|
1450
|
+
if (!json || !objType.includes(`::${MODULE}::Job<`)) {
|
|
1451
|
+
throw new exports.T2000Error("RPC_ERROR", `Object ${jobId} is not an a2a_escrow Job.`);
|
|
1452
|
+
}
|
|
1453
|
+
const stateNum = Number(json.state ?? -1);
|
|
1454
|
+
const state = JOB_STATES[stateNum];
|
|
1455
|
+
if (!state) {
|
|
1456
|
+
throw new exports.T2000Error("RPC_ERROR", `Job ${jobId} has unknown state ${stateNum}.`);
|
|
1457
|
+
}
|
|
1458
|
+
const deliveredAtMs = Number(json.delivered_at_ms ?? 0);
|
|
1459
|
+
const deliveryBytes = json.delivery_hash ?? [];
|
|
1460
|
+
const hasDelivery = deliveredAtMs > 0;
|
|
1461
|
+
return {
|
|
1462
|
+
id: jobId,
|
|
1463
|
+
buyer: String(json.buyer),
|
|
1464
|
+
seller: String(json.seller),
|
|
1465
|
+
amountUsdc: Number(json.amount) / 10 ** USDC_DECIMALS,
|
|
1466
|
+
escrowUsdc: Number(json.escrow) / 10 ** USDC_DECIMALS,
|
|
1467
|
+
specHash: bytesToHex(json.spec_hash ?? []),
|
|
1468
|
+
deliverByMs: Number(json.deliver_by_ms),
|
|
1469
|
+
reviewWindowMs: Number(json.review_window_ms),
|
|
1470
|
+
rejectSplitBps: Number(json.reject_split_bps),
|
|
1471
|
+
state,
|
|
1472
|
+
deliveryHash: hasDelivery ? bytesToHex(deliveryBytes) : null,
|
|
1473
|
+
deliveredAtMs: hasDelivery ? deliveredAtMs : null,
|
|
1474
|
+
createdAtMs: Number(json.created_at_ms)
|
|
1475
|
+
};
|
|
1476
|
+
}
|
|
1477
|
+
function jobActionsFor(job, caller, nowMs = Date.now()) {
|
|
1478
|
+
const me = validateAddress(caller);
|
|
1479
|
+
const isBuyer = me === job.buyer;
|
|
1480
|
+
const isSeller = me === job.seller;
|
|
1481
|
+
const actions = [];
|
|
1482
|
+
if (job.state === "funded") {
|
|
1483
|
+
if (isSeller && nowMs <= job.deliverByMs) actions.push("deliver");
|
|
1484
|
+
if (isBuyer) actions.push("release");
|
|
1485
|
+
if (nowMs > job.deliverByMs) actions.push("refund");
|
|
1486
|
+
} else if (job.state === "delivered") {
|
|
1487
|
+
const windowClosesMs = (job.deliveredAtMs ?? 0) + job.reviewWindowMs;
|
|
1488
|
+
if (isBuyer && nowMs <= windowClosesMs) actions.push("release", "reject");
|
|
1489
|
+
if (nowMs > windowClosesMs) actions.push("release");
|
|
1490
|
+
}
|
|
1491
|
+
return actions;
|
|
1492
|
+
}
|
|
1493
|
+
async function verifyJobForSeller({
|
|
1494
|
+
client,
|
|
1495
|
+
jobId,
|
|
1496
|
+
seller,
|
|
1497
|
+
minAmountUsdc,
|
|
1498
|
+
minRunwayMs = 6e4
|
|
1499
|
+
}) {
|
|
1500
|
+
const job = await getJob(client, jobId);
|
|
1501
|
+
const problems = [];
|
|
1502
|
+
if (job.state !== "funded") {
|
|
1503
|
+
problems.push(`state is "${job.state}", expected "funded"`);
|
|
1504
|
+
}
|
|
1505
|
+
if (job.seller !== validateAddress(seller)) {
|
|
1506
|
+
problems.push(`job pays ${job.seller}, not this seller`);
|
|
1507
|
+
}
|
|
1508
|
+
if (job.escrowUsdc < minAmountUsdc) {
|
|
1509
|
+
problems.push(`escrow holds ${job.escrowUsdc} USDC, price is ${minAmountUsdc}`);
|
|
1510
|
+
}
|
|
1511
|
+
if (job.deliverByMs - Date.now() < minRunwayMs) {
|
|
1512
|
+
problems.push("deadline too close to accept");
|
|
1513
|
+
}
|
|
1514
|
+
return { ok: problems.length === 0, job, problems };
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1317
1517
|
// src/browser.ts
|
|
1318
1518
|
init_token_registry();
|
|
1319
1519
|
|
|
1520
|
+
exports.A2A_ESCROW_PACKAGE_ID = A2A_ESCROW_PACKAGE_ID;
|
|
1320
1521
|
exports.CLOCK_ID = CLOCK_ID;
|
|
1321
1522
|
exports.DEFAULT_NETWORK = DEFAULT_NETWORK;
|
|
1322
1523
|
exports.GAS_RESERVE_MIN = GAS_RESERVE_MIN;
|
|
1524
|
+
exports.JOB_STATES = JOB_STATES;
|
|
1323
1525
|
exports.KNOWN_TARGETS = KNOWN_TARGETS;
|
|
1324
1526
|
exports.KeypairSigner = KeypairSigner;
|
|
1325
1527
|
exports.LABEL_PATTERNS = LABEL_PATTERNS;
|
|
1528
|
+
exports.MAX_JOB_USDC = MAX_JOB_USDC;
|
|
1326
1529
|
exports.MIST_PER_SUI = MIST_PER_SUI;
|
|
1327
1530
|
exports.OVERLAY_FEE_RATE = OVERLAY_FEE_RATE;
|
|
1328
1531
|
exports.PREFLIGHT_MAX_AMOUNT = PREFLIGHT_MAX_AMOUNT;
|
|
@@ -1333,6 +1536,11 @@ exports.SUPPORTED_ASSETS = SUPPORTED_ASSETS;
|
|
|
1333
1536
|
exports.T2000_OVERLAY_FEE_WALLET = T2000_OVERLAY_FEE_WALLET;
|
|
1334
1537
|
exports.USDC_DECIMALS = USDC_DECIMALS;
|
|
1335
1538
|
exports.ZkLoginSigner = ZkLoginSigner;
|
|
1539
|
+
exports.buildCreateJobTx = buildCreateJobTx;
|
|
1540
|
+
exports.buildDeliverJobTx = buildDeliverJobTx;
|
|
1541
|
+
exports.buildRefundJobTx = buildRefundJobTx;
|
|
1542
|
+
exports.buildRejectJobTx = buildRejectJobTx;
|
|
1543
|
+
exports.buildReleaseJobTx = buildReleaseJobTx;
|
|
1336
1544
|
exports.buildSendTx = buildSendTx;
|
|
1337
1545
|
exports.buildSwapTx = buildSwapTx;
|
|
1338
1546
|
exports.checkPositiveAmount = checkPositiveAmount;
|
|
@@ -1353,12 +1561,15 @@ exports.formatUsd = formatUsd;
|
|
|
1353
1561
|
exports.fromBase64 = fromBase642;
|
|
1354
1562
|
exports.getDecimals = getDecimals;
|
|
1355
1563
|
exports.getDecimalsForCoinType = getDecimalsForCoinType;
|
|
1564
|
+
exports.getJob = getJob;
|
|
1565
|
+
exports.jobActionsFor = jobActionsFor;
|
|
1356
1566
|
exports.mapMoveAbortCode = mapMoveAbortCode;
|
|
1357
1567
|
exports.mapWalletError = mapWalletError;
|
|
1358
1568
|
exports.mistToSui = mistToSui;
|
|
1359
1569
|
exports.parseMppSuiChallenge = parseMppSuiChallenge;
|
|
1360
1570
|
exports.parseSuiRpcTx = parseSuiRpcTx;
|
|
1361
1571
|
exports.payWithMpp = payWithMpp;
|
|
1572
|
+
exports.preflightCreateJob = preflightCreateJob;
|
|
1362
1573
|
exports.preflightFail = preflightFail;
|
|
1363
1574
|
exports.preflightPay = preflightPay;
|
|
1364
1575
|
exports.preflightSend = preflightSend;
|
|
@@ -1374,5 +1585,6 @@ exports.toBase64 = toBase64;
|
|
|
1374
1585
|
exports.truncateAddress = truncateAddress;
|
|
1375
1586
|
exports.usdcToRaw = usdcToRaw;
|
|
1376
1587
|
exports.validateAddress = validateAddress;
|
|
1588
|
+
exports.verifyJobForSeller = verifyJobForSeller;
|
|
1377
1589
|
//# sourceMappingURL=browser.cjs.map
|
|
1378
1590
|
//# sourceMappingURL=browser.cjs.map
|