@piprail/sdk 2.13.0 → 2.14.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/CHANGELOG.md +96 -0
- package/dist/{algorand-AA3WXKW4.js → algorand-6J3IABVF.js} +12 -11
- package/dist/{algorand-FCEECDG6.cjs → algorand-QU6G2DQZ.cjs} +43 -42
- package/dist/{aptos-LY67Q6QF.js → aptos-DHOMTBLZ.js} +11 -10
- package/dist/{aptos-GHJPO6JJ.cjs → aptos-LFTQGBBK.cjs} +41 -40
- package/dist/{chunk-MWBT7MCE.cjs → chunk-GYM46G5L.cjs} +22 -4
- package/dist/{chunk-SC2ZYDHD.js → chunk-PAMKCWVW.js} +22 -4
- package/dist/index.cjs +505 -234
- package/dist/index.d.cts +281 -12
- package/dist/index.d.ts +281 -12
- package/dist/index.js +302 -31
- package/dist/{ledger-mF_SoiDB.d.ts → ledger-uFtXlIHY.d.cts} +31 -1
- package/dist/{ledger-mF_SoiDB.d.cts → ledger-uFtXlIHY.d.ts} +31 -1
- package/dist/{near-FZBUICCS.js → near-5PXTVQ47.js} +14 -5
- package/dist/{near-6KAQVVG2.cjs → near-YNNK7RW7.cjs} +39 -30
- package/dist/node.d.cts +2 -2
- package/dist/node.d.ts +2 -2
- package/dist/{solana-ELUWO6N5.js → solana-HITVI3HF.js} +22 -7
- package/dist/{solana-MYF4HBO4.cjs → solana-N3UCNCYE.cjs} +54 -39
- package/dist/{stellar-ASP2THL2.js → stellar-2QT6YYKN.js} +4 -4
- package/dist/{stellar-CRWBSX4E.cjs → stellar-Y3SQN7S5.cjs} +23 -23
- package/dist/{sui-Y4RLKKE2.cjs → sui-4AL4E6XU.cjs} +35 -27
- package/dist/{sui-FZIKZNVI.js → sui-FV5L6WF5.js} +20 -12
- package/dist/{ton-7GKCTC5H.js → ton-5FWDQ4QR.js} +18 -7
- package/dist/{ton-AOR3EURW.cjs → ton-5HDVOTMR.cjs} +33 -22
- package/dist/{tron-BMCWN5SS.js → tron-AZDY7BMQ.js} +10 -10
- package/dist/{tron-OMXB6EW2.cjs → tron-TX2B4N2A.cjs} +39 -39
- package/dist/{xrpl-Y6SQNYLC.cjs → xrpl-5TYDLQFS.cjs} +31 -31
- package/dist/{xrpl-DD7TJL5L.js → xrpl-UJL5J7CY.js} +13 -13
- package/package.json +1 -1
|
@@ -210,6 +210,13 @@ interface X402PaymentSignature {
|
|
|
210
210
|
nonce: string;
|
|
211
211
|
txHash: string;
|
|
212
212
|
};
|
|
213
|
+
/**
|
|
214
|
+
* Optional v2 extensions the client attaches to its payload — e.g. the
|
|
215
|
+
* `payment-identifier` idempotency id at `extensions['payment-identifier'].info.id`
|
|
216
|
+
* (read by the gate via {@link readPaymentIdentifier}). A standard reader ignores it,
|
|
217
|
+
* and omitting it keeps the payload byte-identical.
|
|
218
|
+
*/
|
|
219
|
+
extensions?: Record<string, unknown>;
|
|
213
220
|
}
|
|
214
221
|
/**
|
|
215
222
|
* The EIP-3009 authorization a payer signs for a standard `exact` rail. All
|
|
@@ -590,6 +597,29 @@ declare function buildReceiptExtension(bundle: {
|
|
|
590
597
|
decimals?: number;
|
|
591
598
|
attestation?: SignedReceipt;
|
|
592
599
|
}): Record<string, unknown>;
|
|
600
|
+
/** The x402 extension key for the optional idempotency identifier (the official
|
|
601
|
+
* `payment-identifier` extension). A client MAY attach a stable `id` so the server dedupes
|
|
602
|
+
* retries and rejects a reused id bound to a DIFFERENT payment. */
|
|
603
|
+
declare const EXT_PAYMENT_IDENTIFIER = "payment-identifier";
|
|
604
|
+
/**
|
|
605
|
+
* Advertise the `payment-identifier` extension on a 402 challenge — PURE JSON, viem-free. The
|
|
606
|
+
* v2 `{ info, schema }` shape: `info.required:false` (PipRail never MANDATES an id) plus a
|
|
607
|
+
* JSON-Schema bound of {@link PAYMENT_ID_MIN}–{@link PAYMENT_ID_MAX} chars. A client reads this
|
|
608
|
+
* from the challenge and MAY echo an `id` back on its payload; the gate dedupes it on its
|
|
609
|
+
* existing used-proof set. The gate merges this into the challenge `extensions` (a sibling key,
|
|
610
|
+
* never inside `extensions.piprail`).
|
|
611
|
+
*/
|
|
612
|
+
declare function buildPaymentIdentifierAdvertisement(): Record<string, unknown>;
|
|
613
|
+
/**
|
|
614
|
+
* Read + validate an inbound `payment-identifier` id from a decoded payment-payload object
|
|
615
|
+
* (`payload.extensions['payment-identifier'].info.id`). PURE, NEVER throws. Returns:
|
|
616
|
+
* - the `id` string when present + valid (16–128 chars, `[A-Za-z0-9_-]`),
|
|
617
|
+
* - `null` when ABSENT (the id is OPTIONAL — the gate proceeds exactly as without the feature),
|
|
618
|
+
* - `{ invalid }` when PRESENT but malformed (the gate re-challenges so the buyer can fix it).
|
|
619
|
+
*/
|
|
620
|
+
declare function readPaymentIdentifier(payload: unknown): string | null | {
|
|
621
|
+
invalid: string;
|
|
622
|
+
};
|
|
593
623
|
declare function buildSignatureHeader(signature: X402PaymentSignature): string;
|
|
594
624
|
/**
|
|
595
625
|
* Build the v2 PAYMENT-SIGNATURE header value for a standard x402 `exact` payment:
|
|
@@ -928,4 +958,4 @@ declare class SpendLedger {
|
|
|
928
958
|
summary(): SpendSummary;
|
|
929
959
|
}
|
|
930
960
|
|
|
931
|
-
export {
|
|
961
|
+
export { parseSettleResponse as $, type AddressId as A, type X402ExactAcceptEntry as B, type Caip2 as C, type X402PaymentSignature as D, EXT_OFFER_RECEIPT as E, type X402Receipt as F, type X402ResourceObject as G, HEADER_REQUIRED as H, type X402UptoAcceptEntry as I, buildChallengeHeader as J, buildExactSignatureHeader as K, buildPaymentIdentifierAdvertisement as L, buildReceiptExtension as M, buildReceiptHeader as N, buildSignatureHeader as O, type PaidReceipt as P, buildUptoSignatureHeader as Q, decodeBase64Json as R, type SettleOutcome as S, memorySpendStore as T, parseChallenge as U, type VerifyErrorCode as V, parseExactObject as W, type X402AcceptEntry as X, parseExactPaymentHeader as Y, parseReceipt as Z, parseReceiptExtension as _, type AssetId as a, parseSignatureHeader as a0, parseSignatureObject as a1, parseUptoObject as a2, parseUptoPaymentHeader as a3, pickAccept as a4, readPaymentIdentifier as a5, EXT_PAYMENT_IDENTIFIER as b, type ExactAuthorizationWire as c, type ExactPaymentPayload as d, type ExactPaymentPayloadAny as e, HEADER_RESPONSE as f, HEADER_RESPONSE_V1 as g, HEADER_SIGNATURE as h, HEADER_SIGNATURE_V1 as i, type ParsedExactPayment as j, type ParsedUptoPayment as k, type Permit2Authorization as l, type Permit2PaymentPayload as m, type Permit2UptoAuthorization as n, type Permit2UptoPaymentPayload as o, type PipRailReceipt as p, type SignedReceipt as q, type SpendAssetTotal as r, type SpendDenomTotal as s, SpendLedger as t, type SpendRecord as u, type SpendStore as v, type SpendSummary as w, type VerifyResult as x, type X402AnyAccept as y, type X402Challenge as z };
|
|
@@ -210,6 +210,13 @@ interface X402PaymentSignature {
|
|
|
210
210
|
nonce: string;
|
|
211
211
|
txHash: string;
|
|
212
212
|
};
|
|
213
|
+
/**
|
|
214
|
+
* Optional v2 extensions the client attaches to its payload — e.g. the
|
|
215
|
+
* `payment-identifier` idempotency id at `extensions['payment-identifier'].info.id`
|
|
216
|
+
* (read by the gate via {@link readPaymentIdentifier}). A standard reader ignores it,
|
|
217
|
+
* and omitting it keeps the payload byte-identical.
|
|
218
|
+
*/
|
|
219
|
+
extensions?: Record<string, unknown>;
|
|
213
220
|
}
|
|
214
221
|
/**
|
|
215
222
|
* The EIP-3009 authorization a payer signs for a standard `exact` rail. All
|
|
@@ -590,6 +597,29 @@ declare function buildReceiptExtension(bundle: {
|
|
|
590
597
|
decimals?: number;
|
|
591
598
|
attestation?: SignedReceipt;
|
|
592
599
|
}): Record<string, unknown>;
|
|
600
|
+
/** The x402 extension key for the optional idempotency identifier (the official
|
|
601
|
+
* `payment-identifier` extension). A client MAY attach a stable `id` so the server dedupes
|
|
602
|
+
* retries and rejects a reused id bound to a DIFFERENT payment. */
|
|
603
|
+
declare const EXT_PAYMENT_IDENTIFIER = "payment-identifier";
|
|
604
|
+
/**
|
|
605
|
+
* Advertise the `payment-identifier` extension on a 402 challenge — PURE JSON, viem-free. The
|
|
606
|
+
* v2 `{ info, schema }` shape: `info.required:false` (PipRail never MANDATES an id) plus a
|
|
607
|
+
* JSON-Schema bound of {@link PAYMENT_ID_MIN}–{@link PAYMENT_ID_MAX} chars. A client reads this
|
|
608
|
+
* from the challenge and MAY echo an `id` back on its payload; the gate dedupes it on its
|
|
609
|
+
* existing used-proof set. The gate merges this into the challenge `extensions` (a sibling key,
|
|
610
|
+
* never inside `extensions.piprail`).
|
|
611
|
+
*/
|
|
612
|
+
declare function buildPaymentIdentifierAdvertisement(): Record<string, unknown>;
|
|
613
|
+
/**
|
|
614
|
+
* Read + validate an inbound `payment-identifier` id from a decoded payment-payload object
|
|
615
|
+
* (`payload.extensions['payment-identifier'].info.id`). PURE, NEVER throws. Returns:
|
|
616
|
+
* - the `id` string when present + valid (16–128 chars, `[A-Za-z0-9_-]`),
|
|
617
|
+
* - `null` when ABSENT (the id is OPTIONAL — the gate proceeds exactly as without the feature),
|
|
618
|
+
* - `{ invalid }` when PRESENT but malformed (the gate re-challenges so the buyer can fix it).
|
|
619
|
+
*/
|
|
620
|
+
declare function readPaymentIdentifier(payload: unknown): string | null | {
|
|
621
|
+
invalid: string;
|
|
622
|
+
};
|
|
593
623
|
declare function buildSignatureHeader(signature: X402PaymentSignature): string;
|
|
594
624
|
/**
|
|
595
625
|
* Build the v2 PAYMENT-SIGNATURE header value for a standard x402 `exact` payment:
|
|
@@ -928,4 +958,4 @@ declare class SpendLedger {
|
|
|
928
958
|
summary(): SpendSummary;
|
|
929
959
|
}
|
|
930
960
|
|
|
931
|
-
export {
|
|
961
|
+
export { parseSettleResponse as $, type AddressId as A, type X402ExactAcceptEntry as B, type Caip2 as C, type X402PaymentSignature as D, EXT_OFFER_RECEIPT as E, type X402Receipt as F, type X402ResourceObject as G, HEADER_REQUIRED as H, type X402UptoAcceptEntry as I, buildChallengeHeader as J, buildExactSignatureHeader as K, buildPaymentIdentifierAdvertisement as L, buildReceiptExtension as M, buildReceiptHeader as N, buildSignatureHeader as O, type PaidReceipt as P, buildUptoSignatureHeader as Q, decodeBase64Json as R, type SettleOutcome as S, memorySpendStore as T, parseChallenge as U, type VerifyErrorCode as V, parseExactObject as W, type X402AcceptEntry as X, parseExactPaymentHeader as Y, parseReceipt as Z, parseReceiptExtension as _, type AssetId as a, parseSignatureHeader as a0, parseSignatureObject as a1, parseUptoObject as a2, parseUptoPaymentHeader as a3, pickAccept as a4, readPaymentIdentifier as a5, EXT_PAYMENT_IDENTIFIER as b, type ExactAuthorizationWire as c, type ExactPaymentPayload as d, type ExactPaymentPayloadAny as e, HEADER_RESPONSE as f, HEADER_RESPONSE_V1 as g, HEADER_SIGNATURE as h, HEADER_SIGNATURE_V1 as i, type ParsedExactPayment as j, type ParsedUptoPayment as k, type Permit2Authorization as l, type Permit2PaymentPayload as m, type Permit2UptoAuthorization as n, type Permit2UptoPaymentPayload as o, type PipRailReceipt as p, type SignedReceipt as q, type SpendAssetTotal as r, type SpendDenomTotal as s, SpendLedger as t, type SpendRecord as u, type SpendStore as v, type SpendSummary as w, type VerifyResult as x, type X402AnyAccept as y, type X402Challenge as z };
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
nativeCost,
|
|
11
11
|
rejectForeignToken,
|
|
12
12
|
toInsufficientFundsError
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-PAMKCWVW.js";
|
|
14
14
|
|
|
15
15
|
// src/drivers/near/index.ts
|
|
16
16
|
import { JsonRpcProvider, Account, actions as actions2 } from "near-api-js";
|
|
@@ -312,11 +312,11 @@ async function verifyNear(params) {
|
|
|
312
312
|
return { ok: false, error: "tx_reverted", detail: `NEAR tx ${hash} failed on-chain.` };
|
|
313
313
|
}
|
|
314
314
|
if (accept.asset === "native") {
|
|
315
|
-
if (
|
|
316
|
-
return { ok: false, error: "payment_expired", detail: `Cannot bound the age of native NEAR tx ${hash} (no block time) \u2014 failing closed.` };
|
|
315
|
+
if (!Number.isFinite(tx.timestampMs)) {
|
|
316
|
+
return { ok: false, error: "payment_expired", detail: `Cannot bound the age of native NEAR tx ${hash} (no/invalid block time) \u2014 failing closed.` };
|
|
317
317
|
}
|
|
318
318
|
const ageSeconds = Math.floor(Date.now() / 1e3) - Math.floor(tx.timestampMs / 1e3);
|
|
319
|
-
if (ageSeconds > accept.maxTimeoutSeconds) {
|
|
319
|
+
if (!Number.isFinite(ageSeconds) || ageSeconds > accept.maxTimeoutSeconds) {
|
|
320
320
|
return { ok: false, error: "payment_expired", detail: `Payment is ${ageSeconds}s old; max allowed is ${accept.maxTimeoutSeconds}s.` };
|
|
321
321
|
}
|
|
322
322
|
if (tx.receiverId !== accept.payTo) {
|
|
@@ -569,7 +569,16 @@ function makeNearNetwork(preset, rpcUrl) {
|
|
|
569
569
|
}
|
|
570
570
|
throw new ConfirmationTimeoutError(`NEAR tx ${hash} not confirmed in time.`);
|
|
571
571
|
},
|
|
572
|
-
async estimateCost() {
|
|
572
|
+
async estimateCost(accept) {
|
|
573
|
+
if (accept.scheme === "exact") {
|
|
574
|
+
return nativeCost({
|
|
575
|
+
symbol: "NEAR",
|
|
576
|
+
decimals: NEAR_DECIMALS,
|
|
577
|
+
fee: 0n,
|
|
578
|
+
basis: "estimated",
|
|
579
|
+
detail: "gasless \u2014 the relayer prepays gas + the 1 yocto; the buyer pays 0 NEAR"
|
|
580
|
+
});
|
|
581
|
+
}
|
|
573
582
|
return nativeCost({
|
|
574
583
|
symbol: "NEAR",
|
|
575
584
|
decimals: NEAR_DECIMALS,
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
var
|
|
13
|
+
var _chunkGYM46G5Lcjs = require('./chunk-GYM46G5L.cjs');
|
|
14
14
|
|
|
15
15
|
// src/drivers/near/index.ts
|
|
16
16
|
var _nearapijs = require('near-api-js');
|
|
@@ -61,18 +61,18 @@ async function payNear(params) {
|
|
|
61
61
|
return res.hash;
|
|
62
62
|
} catch (err) {
|
|
63
63
|
if (isNearRegistrationError(err)) {
|
|
64
|
-
throw new (0,
|
|
64
|
+
throw new (0, _chunkGYM46G5Lcjs.RecipientNotReadyError)(
|
|
65
65
|
`NEAR recipient ${accept.payTo} isn't registered on token ${accept.asset} (NEP-145 storage_deposit) \u2014 register it once (\u22480.00125 NEAR) before it can receive. (NEAR: not registered)`,
|
|
66
66
|
{ cause: err }
|
|
67
67
|
);
|
|
68
68
|
}
|
|
69
69
|
if (isNearAffordability(err)) {
|
|
70
|
-
throw new (0,
|
|
70
|
+
throw new (0, _chunkGYM46G5Lcjs.InsufficientFundsError)(
|
|
71
71
|
err instanceof Error ? err.message : "Insufficient NEAR balance for the payment.",
|
|
72
72
|
{ cause: err }
|
|
73
73
|
);
|
|
74
74
|
}
|
|
75
|
-
throw _nullishCoalesce(
|
|
75
|
+
throw _nullishCoalesce(_chunkGYM46G5Lcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
async function payNearNative(params) {
|
|
@@ -82,12 +82,12 @@ async function payNearNative(params) {
|
|
|
82
82
|
return res.hash;
|
|
83
83
|
} catch (err) {
|
|
84
84
|
if (isNearAffordability(err)) {
|
|
85
|
-
throw new (0,
|
|
85
|
+
throw new (0, _chunkGYM46G5Lcjs.InsufficientFundsError)(
|
|
86
86
|
err instanceof Error ? err.message : "Insufficient NEAR balance for the payment.",
|
|
87
87
|
{ cause: err }
|
|
88
88
|
);
|
|
89
89
|
}
|
|
90
|
-
throw _nullishCoalesce(
|
|
90
|
+
throw _nullishCoalesce(_chunkGYM46G5Lcjs.toInsufficientFundsError.call(void 0, err), () => ( err));
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
function isNearRegistrationError(err) {
|
|
@@ -109,28 +109,28 @@ var NONCE_BLOCK_MULTIPLIER = 1000000n;
|
|
|
109
109
|
async function payExactNear(input) {
|
|
110
110
|
const { signer, senderId, blockHeight, accessKeyNonce, accept } = input;
|
|
111
111
|
if (accept.asset === "native") {
|
|
112
|
-
throw new (0,
|
|
112
|
+
throw new (0, _chunkGYM46G5Lcjs.UnsupportedSchemeError)(
|
|
113
113
|
"NEAR exact is NEP-141-only (an ft_transfer); native NEAR is not exact-payable. Pay via onchain-proof."
|
|
114
114
|
);
|
|
115
115
|
}
|
|
116
116
|
if (!isValidNearAccountId(accept.asset)) {
|
|
117
|
-
throw new (0,
|
|
117
|
+
throw new (0, _chunkGYM46G5Lcjs.UnsupportedSchemeError)(`NEAR exact: asset "${accept.asset}" must be a NEP-141 contract account id.`);
|
|
118
118
|
}
|
|
119
119
|
if (!isValidNearAccountId(accept.payTo)) {
|
|
120
|
-
throw new (0,
|
|
120
|
+
throw new (0, _chunkGYM46G5Lcjs.UnsupportedSchemeError)(`NEAR exact: payTo "${accept.payTo}" is not a valid NEAR account id.`);
|
|
121
121
|
}
|
|
122
122
|
if (!isValidNearAccountId(senderId)) {
|
|
123
|
-
throw new (0,
|
|
123
|
+
throw new (0, _chunkGYM46G5Lcjs.UnsupportedSchemeError)(`NEAR exact: sender "${senderId}" is not a valid NEAR account id.`);
|
|
124
124
|
}
|
|
125
125
|
const t = accept.maxTimeoutSeconds;
|
|
126
126
|
if (!Number.isInteger(t) || t <= 0) {
|
|
127
|
-
throw new (0,
|
|
127
|
+
throw new (0, _chunkGYM46G5Lcjs.UnsupportedSchemeError)("NEAR exact: maxTimeoutSeconds must be a positive integer.");
|
|
128
128
|
}
|
|
129
129
|
const timeoutBlocks = BigInt(Math.max(1, Math.ceil(t / ESTIMATED_BLOCK_SECONDS)));
|
|
130
130
|
const maxBlockHeight = blockHeight + timeoutBlocks;
|
|
131
131
|
const nonce = accessKeyNonce + 1n;
|
|
132
132
|
if (nonce >= blockHeight * NONCE_BLOCK_MULTIPLIER) {
|
|
133
|
-
throw new (0,
|
|
133
|
+
throw new (0, _chunkGYM46G5Lcjs.UnsupportedSchemeError)(
|
|
134
134
|
"NEAR exact: the access-key nonce is at the protocol ceiling for this block height; cannot build a delegate action."
|
|
135
135
|
);
|
|
136
136
|
}
|
|
@@ -259,7 +259,7 @@ async function verifyAndSettleExactNear(input) {
|
|
|
259
259
|
if (/not enough|insufficient|exceeded the prepaid gas|NotEnoughBalance|doesn't have enough|is not registered/i.test(m)) {
|
|
260
260
|
return fail("tx_reverted", `the ft_transfer would fail on chain: ${shorten(m)}.`);
|
|
261
261
|
}
|
|
262
|
-
throw new (0,
|
|
262
|
+
throw new (0, _chunkGYM46G5Lcjs.SettlementError)(
|
|
263
263
|
`NEAR exact settle: the relayer could not submit the delegate (${shorten(m)}). The buyer's signed delegate is still valid \u2014 fund/fix the relayer and the buyer can re-present it.`,
|
|
264
264
|
{ cause: err }
|
|
265
265
|
);
|
|
@@ -312,11 +312,11 @@ async function verifyNear(params) {
|
|
|
312
312
|
return { ok: false, error: "tx_reverted", detail: `NEAR tx ${hash} failed on-chain.` };
|
|
313
313
|
}
|
|
314
314
|
if (accept.asset === "native") {
|
|
315
|
-
if (
|
|
316
|
-
return { ok: false, error: "payment_expired", detail: `Cannot bound the age of native NEAR tx ${hash} (no block time) \u2014 failing closed.` };
|
|
315
|
+
if (!Number.isFinite(tx.timestampMs)) {
|
|
316
|
+
return { ok: false, error: "payment_expired", detail: `Cannot bound the age of native NEAR tx ${hash} (no/invalid block time) \u2014 failing closed.` };
|
|
317
317
|
}
|
|
318
318
|
const ageSeconds = Math.floor(Date.now() / 1e3) - Math.floor(tx.timestampMs / 1e3);
|
|
319
|
-
if (ageSeconds > accept.maxTimeoutSeconds) {
|
|
319
|
+
if (!Number.isFinite(ageSeconds) || ageSeconds > accept.maxTimeoutSeconds) {
|
|
320
320
|
return { ok: false, error: "payment_expired", detail: `Payment is ${ageSeconds}s old; max allowed is ${accept.maxTimeoutSeconds}s.` };
|
|
321
321
|
}
|
|
322
322
|
if (tx.receiverId !== accept.payTo) {
|
|
@@ -408,13 +408,13 @@ function txNotFound(hash) {
|
|
|
408
408
|
|
|
409
409
|
function assertNearWallet(wallet, network) {
|
|
410
410
|
if (typeof wallet !== "object" || wallet === null) {
|
|
411
|
-
throw new (0,
|
|
411
|
+
throw new (0, _chunkGYM46G5Lcjs.WrongFamilyError)(
|
|
412
412
|
`chain ${network} is NEAR; wallet must be { accountId, key } (key = ed25519:\u2026).`
|
|
413
413
|
);
|
|
414
414
|
}
|
|
415
|
-
|
|
415
|
+
_chunkGYM46G5Lcjs.assertNoLegacyWalletKey.call(void 0, wallet, "NEAR");
|
|
416
416
|
if (!("accountId" in wallet) || !("key" in wallet)) {
|
|
417
|
-
throw new (0,
|
|
417
|
+
throw new (0, _chunkGYM46G5Lcjs.WrongFamilyError)(
|
|
418
418
|
`chain ${network} is NEAR; wallet must be { accountId, key } (key = ed25519:\u2026).`
|
|
419
419
|
);
|
|
420
420
|
}
|
|
@@ -422,13 +422,13 @@ function assertNearWallet(wallet, network) {
|
|
|
422
422
|
}
|
|
423
423
|
function resolveNearWallet(config) {
|
|
424
424
|
if (!config.accountId || !config.key) {
|
|
425
|
-
throw new (0,
|
|
425
|
+
throw new (0, _chunkGYM46G5Lcjs.WrongFamilyError)("NEAR wallet needs { accountId, key } (key = ed25519:\u2026).");
|
|
426
426
|
}
|
|
427
427
|
let signer;
|
|
428
428
|
try {
|
|
429
429
|
signer = _nearapijs.KeyPairSigner.fromSecretKey(config.key);
|
|
430
430
|
} catch (cause) {
|
|
431
|
-
throw new (0,
|
|
431
|
+
throw new (0, _chunkGYM46G5Lcjs.WrongFamilyError)("NEAR wallet { key } is not a valid ed25519:\u2026 secret key.", {
|
|
432
432
|
cause
|
|
433
433
|
});
|
|
434
434
|
}
|
|
@@ -490,16 +490,16 @@ function makeNearNetwork(preset, rpcUrl) {
|
|
|
490
490
|
const info = preset.tokens[token.toUpperCase()];
|
|
491
491
|
if (!info) {
|
|
492
492
|
const known = Object.keys(preset.tokens).join(", ") || "(none built in)";
|
|
493
|
-
throw new (0,
|
|
493
|
+
throw new (0, _chunkGYM46G5Lcjs.UnknownTokenError)(
|
|
494
494
|
`token "${token}" isn't built in for NEAR (known: ${known}). Pass { contractId, decimals } for a custom NEP-141.`
|
|
495
495
|
);
|
|
496
496
|
}
|
|
497
497
|
return { asset: info.contractId, decimals: info.decimals, symbol: info.symbol };
|
|
498
498
|
}
|
|
499
|
-
|
|
499
|
+
_chunkGYM46G5Lcjs.rejectForeignToken.call(void 0, token, "near", network);
|
|
500
500
|
const t = token;
|
|
501
501
|
if (!t.contractId || typeof t.decimals !== "number") {
|
|
502
|
-
throw new (0,
|
|
502
|
+
throw new (0, _chunkGYM46G5Lcjs.WrongFamilyError)(
|
|
503
503
|
`chain ${network} is NEAR; a custom token must be { contractId, decimals }.`
|
|
504
504
|
);
|
|
505
505
|
}
|
|
@@ -518,12 +518,12 @@ function makeNearNetwork(preset, rpcUrl) {
|
|
|
518
518
|
},
|
|
519
519
|
assertValidPayTo(payTo) {
|
|
520
520
|
if (payTo.startsWith("0x")) {
|
|
521
|
-
throw new (0,
|
|
521
|
+
throw new (0, _chunkGYM46G5Lcjs.WrongFamilyError)(
|
|
522
522
|
`chain ${network} is NEAR, but payTo "${payTo}" looks like an EVM/Sui 0x address.`
|
|
523
523
|
);
|
|
524
524
|
}
|
|
525
525
|
if (!isValidNearAccountId(payTo)) {
|
|
526
|
-
throw new (0,
|
|
526
|
+
throw new (0, _chunkGYM46G5Lcjs.WrongFamilyError)(
|
|
527
527
|
`chain ${network} is NEAR, but payTo "${payTo}" is not a valid NEAR account id.`
|
|
528
528
|
);
|
|
529
529
|
}
|
|
@@ -567,10 +567,19 @@ function makeNearNetwork(preset, rpcUrl) {
|
|
|
567
567
|
if (tx && tx.success) return { height: "0" };
|
|
568
568
|
} catch (e11) {
|
|
569
569
|
}
|
|
570
|
-
throw new (0,
|
|
570
|
+
throw new (0, _chunkGYM46G5Lcjs.ConfirmationTimeoutError)(`NEAR tx ${hash} not confirmed in time.`);
|
|
571
571
|
},
|
|
572
|
-
async estimateCost() {
|
|
573
|
-
|
|
572
|
+
async estimateCost(accept) {
|
|
573
|
+
if (accept.scheme === "exact") {
|
|
574
|
+
return _chunkGYM46G5Lcjs.nativeCost.call(void 0, {
|
|
575
|
+
symbol: "NEAR",
|
|
576
|
+
decimals: NEAR_DECIMALS,
|
|
577
|
+
fee: 0n,
|
|
578
|
+
basis: "estimated",
|
|
579
|
+
detail: "gasless \u2014 the relayer prepays gas + the 1 yocto; the buyer pays 0 NEAR"
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
return _chunkGYM46G5Lcjs.nativeCost.call(void 0, {
|
|
574
583
|
symbol: "NEAR",
|
|
575
584
|
decimals: NEAR_DECIMALS,
|
|
576
585
|
fee: 1500000000000000000000n,
|
|
@@ -692,7 +701,7 @@ function makeNearNetwork(preset, rpcUrl) {
|
|
|
692
701
|
try {
|
|
693
702
|
relayerWallet = resolveNearWallet(relayer._native);
|
|
694
703
|
} catch (err) {
|
|
695
|
-
throw new (0,
|
|
704
|
+
throw new (0, _chunkGYM46G5Lcjs.SettlementError)(
|
|
696
705
|
`NEAR exact settle: the relayer wallet is invalid (${err instanceof Error ? err.message : String(err)}).`,
|
|
697
706
|
{ cause: err }
|
|
698
707
|
);
|
package/dist/node.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { v as SpendStore } from './ledger-uFtXlIHY.cjs';
|
|
2
|
+
export { T as memorySpendStore } from './ledger-uFtXlIHY.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A durable {@link SpendStore} backed by a local JSONL file (one settled payment per
|
package/dist/node.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { v as SpendStore } from './ledger-uFtXlIHY.js';
|
|
2
|
+
export { T as memorySpendStore } from './ledger-uFtXlIHY.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* A durable {@link SpendStore} backed by a local JSONL file (one settled payment per
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
nativeCost,
|
|
9
9
|
rejectForeignToken,
|
|
10
10
|
toInsufficientFundsError
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-PAMKCWVW.js";
|
|
12
12
|
|
|
13
13
|
// src/drivers/solana/index.ts
|
|
14
14
|
import { Connection, PublicKey as PublicKey3 } from "@solana/web3.js";
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
getAccount,
|
|
17
17
|
getAssociatedTokenAddressSync as getAssociatedTokenAddressSync3,
|
|
18
18
|
TOKEN_2022_PROGRAM_ID as TOKEN_2022_PROGRAM_ID2,
|
|
19
|
+
TOKEN_PROGRAM_ID as TOKEN_PROGRAM_ID2,
|
|
19
20
|
TokenAccountNotFoundError
|
|
20
21
|
} from "@solana/spl-token";
|
|
21
22
|
|
|
@@ -126,15 +127,15 @@ async function verifySolana(params) {
|
|
|
126
127
|
detail: `Transaction ${signature} failed on-chain.`
|
|
127
128
|
};
|
|
128
129
|
}
|
|
129
|
-
if (
|
|
130
|
+
if (!Number.isFinite(tx.blockTime)) {
|
|
130
131
|
return {
|
|
131
132
|
ok: false,
|
|
132
133
|
error: "payment_expired",
|
|
133
|
-
detail: `Cannot determine the age of ${signature} (no blockTime).`
|
|
134
|
+
detail: `Cannot determine the age of ${signature} (no/invalid blockTime).`
|
|
134
135
|
};
|
|
135
136
|
}
|
|
136
137
|
const ageSeconds = Math.floor(Date.now() / 1e3) - tx.blockTime;
|
|
137
|
-
if (ageSeconds > accept.maxTimeoutSeconds) {
|
|
138
|
+
if (!Number.isFinite(ageSeconds) || ageSeconds > accept.maxTimeoutSeconds) {
|
|
138
139
|
return {
|
|
139
140
|
ok: false,
|
|
140
141
|
error: "payment_expired",
|
|
@@ -429,6 +430,8 @@ async function verifyAndSettleExactSolana(input) {
|
|
|
429
430
|
if (price > MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS) {
|
|
430
431
|
return fail("signature_invalid", `Compute-unit price ${price} \xB5lamports exceeds the ${MAX_COMPUTE_UNIT_PRICE_MICROLAMPORTS} cap (fee-payer drain guard).`);
|
|
431
432
|
}
|
|
433
|
+
} else {
|
|
434
|
+
return fail("signature_invalid", `Unexpected ComputeBudget instruction (discriminator ${data[0]}) \u2014 only set-unit-limit/price are allowed (fee-payer drain guard).`);
|
|
432
435
|
}
|
|
433
436
|
}
|
|
434
437
|
const isSignedSigner = (pubkey) => {
|
|
@@ -717,14 +720,26 @@ function makeSolanaNetwork(preset, rpcUrl) {
|
|
|
717
720
|
if (asset === "native") return { token: native, native };
|
|
718
721
|
let token;
|
|
719
722
|
try {
|
|
720
|
-
const
|
|
721
|
-
|
|
723
|
+
const mint = new PublicKey3(asset);
|
|
724
|
+
const info = await connection.getAccountInfo(mint);
|
|
725
|
+
const programId = info?.owner.equals(TOKEN_2022_PROGRAM_ID2) ? TOKEN_2022_PROGRAM_ID2 : TOKEN_PROGRAM_ID2;
|
|
726
|
+
const ata = getAssociatedTokenAddressSync3(mint, owner, false, programId);
|
|
727
|
+
token = (await getAccount(connection, ata, "confirmed", programId)).amount;
|
|
722
728
|
} catch (e) {
|
|
723
729
|
token = e instanceof TokenAccountNotFoundError ? 0n : null;
|
|
724
730
|
}
|
|
725
731
|
return { token, native };
|
|
726
732
|
},
|
|
727
|
-
// No receive prerequisite
|
|
733
|
+
// No receive prerequisite for the DEFAULT onchain-proof rail — the payer's tx idempotently
|
|
734
|
+
// creates the recipient's ATA (pay.ts). KNOWN LIMITATION (documented, not a bug): on the opt-in
|
|
735
|
+
// `exact` rail the buyer cannot create the ATA (payExactSolana throws if payTo's token account
|
|
736
|
+
// is missing), so `planPayment`/`canAfford` can be OPTIMISTIC for an exact payment to a
|
|
737
|
+
// brand-new recipient whose ATA doesn't yet exist — marked payable, and `autoRoute` would pick
|
|
738
|
+
// it then refuse (pre-broadcast, recoverable) at pay time. Mitigations in practice: onchain-proof
|
|
739
|
+
// is always co-offered (and DOES create the ATA), `exact` + `autoRoute` are both off by default,
|
|
740
|
+
// and most merchant receive accounts already exist. 'n/a' is correct for onchain-proof; an
|
|
741
|
+
// exact-aware probe needs the token-program-correct ATA derivation (an extra mint-owner read)
|
|
742
|
+
// and is deferred as disproportionate to this opt-in edge.
|
|
728
743
|
async recipientReady() {
|
|
729
744
|
return { ready: "n/a" };
|
|
730
745
|
},
|