@cmdoss/suipay 0.1.1-dev.6 → 0.1.1-dev.8
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.js +71 -4
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1752,6 +1752,33 @@ function decodeSponsorGasPayment(encoded) {
|
|
|
1752
1752
|
return { objectId: bits[0], version: bits[1], digest: bits[2] };
|
|
1753
1753
|
});
|
|
1754
1754
|
}
|
|
1755
|
+
var SPONSOR_GAS_ADDRESS_BALANCE = "address-balance";
|
|
1756
|
+
function decodeSponsorGasPin(encoded) {
|
|
1757
|
+
if (encoded === SPONSOR_GAS_ADDRESS_BALANCE)
|
|
1758
|
+
return [];
|
|
1759
|
+
return decodeSponsorGasPayment(encoded);
|
|
1760
|
+
}
|
|
1761
|
+
var ADDRESS_BALANCE_VALIDITY_EPOCHS = 1n;
|
|
1762
|
+
function addressBalanceGasExpiration(input) {
|
|
1763
|
+
const chain = input.chainIdentifier.trim();
|
|
1764
|
+
if (!chain)
|
|
1765
|
+
throw new Error("address-balance gas needs a chain identifier");
|
|
1766
|
+
if (input.epoch < 0n)
|
|
1767
|
+
throw new Error("address-balance gas needs a non-negative epoch");
|
|
1768
|
+
if (!Number.isInteger(input.nonce) || input.nonce < 0 || input.nonce > 4294967295) {
|
|
1769
|
+
throw new Error("address-balance gas nonce must be a u32");
|
|
1770
|
+
}
|
|
1771
|
+
return {
|
|
1772
|
+
ValidDuring: {
|
|
1773
|
+
minEpoch: String(input.epoch),
|
|
1774
|
+
maxEpoch: String(input.epoch + ADDRESS_BALANCE_VALIDITY_EPOCHS),
|
|
1775
|
+
minTimestamp: null,
|
|
1776
|
+
maxTimestamp: null,
|
|
1777
|
+
chain,
|
|
1778
|
+
nonce: input.nonce
|
|
1779
|
+
}
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1755
1782
|
|
|
1756
1783
|
// ../sdk/dist/protocol/mpp.js
|
|
1757
1784
|
function offerToBase64Url(offer) {
|
|
@@ -4381,7 +4408,7 @@ function readX402GasPin(offer) {
|
|
|
4381
4408
|
owner,
|
|
4382
4409
|
budget,
|
|
4383
4410
|
price,
|
|
4384
|
-
payment:
|
|
4411
|
+
payment: decodeSponsorGasPin(offer.sponsorGasPayment ?? "")
|
|
4385
4412
|
};
|
|
4386
4413
|
} catch {
|
|
4387
4414
|
return null;
|
|
@@ -4395,16 +4422,33 @@ async function buildSpendAccountX402PayTx(input) {
|
|
|
4395
4422
|
tx.setGasBudget(input.gas.budget);
|
|
4396
4423
|
tx.setGasPrice(input.gas.price);
|
|
4397
4424
|
tx.setGasPayment(input.gas.payment);
|
|
4398
|
-
|
|
4425
|
+
if (input.gas.payment.length === 0) {
|
|
4426
|
+
if (!input.chainIdentifier) {
|
|
4427
|
+
throw new Error("address-balance sponsor gas needs a chain identifier");
|
|
4428
|
+
}
|
|
4429
|
+
tx.setExpiration(addressBalanceGasExpiration({
|
|
4430
|
+
epoch: input.currentEpoch,
|
|
4431
|
+
chainIdentifier: input.chainIdentifier,
|
|
4432
|
+
nonce: input.nonce ?? randomU32()
|
|
4433
|
+
}));
|
|
4434
|
+
} else {
|
|
4435
|
+
tx.setExpiration({ Epoch: String(input.currentEpoch + X402_EXPIRATION_EPOCHS) });
|
|
4436
|
+
}
|
|
4399
4437
|
const txBytes = toBase645(await tx.build());
|
|
4400
4438
|
return { txBytes, kindBytes };
|
|
4401
4439
|
}
|
|
4440
|
+
function randomU32() {
|
|
4441
|
+
return globalThis.crypto.getRandomValues(new Uint32Array(1))[0];
|
|
4442
|
+
}
|
|
4402
4443
|
function currentEpochReader(client) {
|
|
4403
4444
|
return async () => {
|
|
4404
4445
|
const { systemState } = await client.core.getCurrentSystemState();
|
|
4405
4446
|
return BigInt(systemState.epoch);
|
|
4406
4447
|
};
|
|
4407
4448
|
}
|
|
4449
|
+
function chainIdentifierReader(client) {
|
|
4450
|
+
return async () => (await client.core.getChainIdentifier()).chainIdentifier;
|
|
4451
|
+
}
|
|
4408
4452
|
function assertPayTransaction(txBytes, expected) {
|
|
4409
4453
|
let data;
|
|
4410
4454
|
try {
|
|
@@ -4865,6 +4909,10 @@ async function payDelegatedSpendAccount(args) {
|
|
|
4865
4909
|
return { status: "ok", paid: false, body: resolution.body };
|
|
4866
4910
|
}
|
|
4867
4911
|
if (resolution.status === "failed") {
|
|
4912
|
+
logInternal(logError, "resolve payment failed", {
|
|
4913
|
+
code: resolution.code,
|
|
4914
|
+
detail: resolution.detail
|
|
4915
|
+
});
|
|
4868
4916
|
const mapped = mapPayOpErrorToDelegated(resolution.code, resolution.detail);
|
|
4869
4917
|
return failed2(mapped.code, mapped.detail, {
|
|
4870
4918
|
paymentId: resolution.paymentId
|
|
@@ -4989,7 +5037,8 @@ async function payDelegatedSpendAccount(args) {
|
|
|
4989
5037
|
buildInput: {
|
|
4990
5038
|
...kindBuildInput,
|
|
4991
5039
|
gas: x402Terms.gas,
|
|
4992
|
-
currentEpoch: x402Terms.currentEpoch
|
|
5040
|
+
currentEpoch: x402Terms.currentEpoch,
|
|
5041
|
+
...x402Terms.chainIdentifier !== void 0 ? { chainIdentifier: x402Terms.chainIdentifier } : {}
|
|
4993
5042
|
},
|
|
4994
5043
|
settlement: {
|
|
4995
5044
|
status: "success",
|
|
@@ -5366,12 +5415,28 @@ async function x402Preflight(dialect, offer, deps, logError) {
|
|
|
5366
5415
|
logInternal(logError, "x402 needs a current-epoch reader");
|
|
5367
5416
|
return null;
|
|
5368
5417
|
}
|
|
5418
|
+
let currentEpoch;
|
|
5369
5419
|
try {
|
|
5370
|
-
|
|
5420
|
+
currentEpoch = BigInt(await deps.getCurrentEpoch());
|
|
5371
5421
|
} catch (err) {
|
|
5372
5422
|
logInternal(logError, "read current epoch failed", err);
|
|
5373
5423
|
return null;
|
|
5374
5424
|
}
|
|
5425
|
+
if (gas.payment.length > 0)
|
|
5426
|
+
return { gas, currentEpoch };
|
|
5427
|
+
if (typeof deps.getChainIdentifier !== "function") {
|
|
5428
|
+
logInternal(logError, "address-balance x402 gas needs a chain-identifier reader");
|
|
5429
|
+
return null;
|
|
5430
|
+
}
|
|
5431
|
+
try {
|
|
5432
|
+
const chainIdentifier = await deps.getChainIdentifier();
|
|
5433
|
+
if (!chainIdentifier.trim())
|
|
5434
|
+
throw new Error("chain identifier is blank");
|
|
5435
|
+
return { gas, currentEpoch, chainIdentifier };
|
|
5436
|
+
} catch (err) {
|
|
5437
|
+
logInternal(logError, "read chain identifier failed", err);
|
|
5438
|
+
return null;
|
|
5439
|
+
}
|
|
5375
5440
|
}
|
|
5376
5441
|
function emitX402Progress(ctx, event) {
|
|
5377
5442
|
if (!ctx.onProgress)
|
|
@@ -6453,6 +6518,8 @@ async function createPayer(options) {
|
|
|
6453
6518
|
// x402 bounds the transaction's expiration by the current epoch, read from
|
|
6454
6519
|
// the same client as every other chain read here.
|
|
6455
6520
|
getCurrentEpoch: currentEpochReader(chain.client),
|
|
6521
|
+
// Address-balance gas (ADR-0055) binds the expiration to the chain.
|
|
6522
|
+
getChainIdentifier: chainIdentifierReader(chain.client),
|
|
6456
6523
|
...options.offerSecret ? { offerSecret: options.offerSecret } : {},
|
|
6457
6524
|
...options.fetchImpl ? { fetchImpl: options.fetchImpl } : {},
|
|
6458
6525
|
...options.logError ? { logError: options.logError } : {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmdoss/suipay",
|
|
3
|
-
"version": "0.1.1-dev.
|
|
3
|
+
"version": "0.1.1-dev.8",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "SuiPay embeddable client — quote and pay a 402 from a spend-account grant.",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"tsup": "^8.0.0",
|
|
33
33
|
"typescript": "^6.0.3",
|
|
34
34
|
"vitest": "^4.1.10",
|
|
35
|
-
"@cmdoss/suipay-
|
|
36
|
-
"@cmdoss/suipay-
|
|
35
|
+
"@cmdoss/suipay-core": "0.1.0",
|
|
36
|
+
"@cmdoss/suipay-sdk": "0.1.0"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "tsup",
|