bsv-x402 0.3.0 → 0.4.1
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 +32 -10
- package/dist/index.d.cts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +32 -10
- package/package.json +7 -3
package/dist/index.cjs
CHANGED
|
@@ -53,12 +53,15 @@ function parseBrc105Challenge(response) {
|
|
|
53
53
|
if (!Number.isFinite(satoshisRequired) || !Number.isInteger(satoshisRequired) || satoshisRequired <= 0) {
|
|
54
54
|
throw new Error("BRC-105: satoshis-required must be a positive integer");
|
|
55
55
|
}
|
|
56
|
-
const
|
|
56
|
+
const authIdentityKey = response.headers.get("x-bsv-auth-identity-key") || null;
|
|
57
|
+
const paymentIdentityKey = response.headers.get("x-bsv-payment-identity-key") || null;
|
|
58
|
+
const authenticated = authIdentityKey !== null && authIdentityKey.length > 0;
|
|
59
|
+
const serverIdentityKey = authIdentityKey || paymentIdentityKey;
|
|
57
60
|
if (serverIdentityKey === null || serverIdentityKey.length === 0) {
|
|
58
|
-
throw new Error("BRC-105: missing
|
|
61
|
+
throw new Error("BRC-105: missing identity key (expected x-bsv-auth-identity-key or x-bsv-payment-identity-key)");
|
|
59
62
|
}
|
|
60
63
|
if (!/^0[23][0-9a-fA-F]{64}$/.test(serverIdentityKey)) {
|
|
61
|
-
throw new Error("BRC-105:
|
|
64
|
+
throw new Error("BRC-105: identity key must be a 33-byte compressed public key (hex)");
|
|
62
65
|
}
|
|
63
66
|
const derivationPrefix = response.headers.get("x-bsv-payment-derivation-prefix");
|
|
64
67
|
if (derivationPrefix === null || derivationPrefix.length === 0) {
|
|
@@ -68,7 +71,8 @@ function parseBrc105Challenge(response) {
|
|
|
68
71
|
version,
|
|
69
72
|
satoshisRequired,
|
|
70
73
|
serverIdentityKey,
|
|
71
|
-
derivationPrefix
|
|
74
|
+
derivationPrefix,
|
|
75
|
+
authenticated
|
|
72
76
|
};
|
|
73
77
|
}
|
|
74
78
|
|
|
@@ -516,7 +520,8 @@ async function createDerivationSuffix(wallet) {
|
|
|
516
520
|
const nonceBytes = [...firstHalf, ...hmac];
|
|
517
521
|
return numberArrayToBase64(nonceBytes);
|
|
518
522
|
}
|
|
519
|
-
async function constructBrc105Proof(challenge, wallet) {
|
|
523
|
+
async function constructBrc105Proof(challenge, wallet, origin) {
|
|
524
|
+
const { publicKey: clientIdentityKey } = await wallet.getPublicKey({ identityKey: true });
|
|
520
525
|
const derivationSuffix = await createDerivationSuffix(wallet);
|
|
521
526
|
const keyID = `${challenge.derivationPrefix} ${derivationSuffix}`;
|
|
522
527
|
const { publicKey: derivedPublicKey } = await wallet.getPublicKey({
|
|
@@ -525,12 +530,13 @@ async function constructBrc105Proof(challenge, wallet) {
|
|
|
525
530
|
counterparty: challenge.serverIdentityKey
|
|
526
531
|
});
|
|
527
532
|
const lockingScript = await pubkeyToP2PKHLockingScript(derivedPublicKey);
|
|
533
|
+
const description = origin ? `Payment for request to ${origin}` : "BRC-105 payment";
|
|
528
534
|
const result = await wallet.createAction({
|
|
529
|
-
description
|
|
535
|
+
description,
|
|
530
536
|
outputs: [{
|
|
531
537
|
satoshis: challenge.satoshisRequired,
|
|
532
538
|
lockingScript,
|
|
533
|
-
|
|
539
|
+
outputDescription: "HTTP request payment",
|
|
534
540
|
customInstructions: JSON.stringify({
|
|
535
541
|
derivationPrefix: challenge.derivationPrefix,
|
|
536
542
|
derivationSuffix,
|
|
@@ -553,6 +559,7 @@ async function constructBrc105Proof(challenge, wallet) {
|
|
|
553
559
|
derivationPrefix: challenge.derivationPrefix,
|
|
554
560
|
derivationSuffix,
|
|
555
561
|
transaction: transactionBase64,
|
|
562
|
+
clientIdentityKey,
|
|
556
563
|
txid: result.txid
|
|
557
564
|
};
|
|
558
565
|
}
|
|
@@ -1165,12 +1172,26 @@ function createX402Fetch(config = {}) {
|
|
|
1165
1172
|
let proof;
|
|
1166
1173
|
try {
|
|
1167
1174
|
proof = await buildProof();
|
|
1168
|
-
} catch {
|
|
1175
|
+
} catch (err) {
|
|
1176
|
+
console.error(`[x402] Proof construction failed (${protocol}):`, err);
|
|
1177
|
+
config.onProofError?.(err, protocol);
|
|
1169
1178
|
return originalResponse;
|
|
1170
1179
|
}
|
|
1171
1180
|
rl.record(makeLedgerEntry(proof));
|
|
1172
1181
|
await persist(rl);
|
|
1173
|
-
|
|
1182
|
+
const maxAttempts = 3;
|
|
1183
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
1184
|
+
try {
|
|
1185
|
+
return await retryWithProof(proof);
|
|
1186
|
+
} catch (err) {
|
|
1187
|
+
if (attempt >= maxAttempts) {
|
|
1188
|
+
console.error(`[x402] Paid request failed after ${maxAttempts} attempts (${protocol}):`, err);
|
|
1189
|
+
return originalResponse;
|
|
1190
|
+
}
|
|
1191
|
+
await new Promise((r) => setTimeout(r, 250 * Math.pow(2, attempt)));
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
return originalResponse;
|
|
1174
1195
|
});
|
|
1175
1196
|
}
|
|
1176
1197
|
const fetchFn = async function x402Fetch2(input, init) {
|
|
@@ -1226,11 +1247,12 @@ function createX402Fetch(config = {}) {
|
|
|
1226
1247
|
if (brc105ProofConstructor) {
|
|
1227
1248
|
return brc105ProofConstructor(brc105Challenge);
|
|
1228
1249
|
}
|
|
1229
|
-
return constructBrc105Proof(brc105Challenge, brc105Wallet);
|
|
1250
|
+
return constructBrc105Proof(brc105Challenge, brc105Wallet, origin);
|
|
1230
1251
|
},
|
|
1231
1252
|
(proof) => {
|
|
1232
1253
|
const headers = new Headers(init?.headers);
|
|
1233
1254
|
headers.set("x-bsv-payment", JSON.stringify(proof));
|
|
1255
|
+
headers.set("x-bsv-auth-identity-key", proof.clientIdentityKey);
|
|
1234
1256
|
return fetch(input, { ...init, headers });
|
|
1235
1257
|
},
|
|
1236
1258
|
(proof) => ({
|
package/dist/index.d.cts
CHANGED
|
@@ -13,6 +13,8 @@ interface Brc105Challenge {
|
|
|
13
13
|
satoshisRequired: number;
|
|
14
14
|
serverIdentityKey: string;
|
|
15
15
|
derivationPrefix: string;
|
|
16
|
+
/** Whether the identity key came from BRC-103 auth (vs standalone x-bsv-payment-identity-key). */
|
|
17
|
+
authenticated: boolean;
|
|
16
18
|
}
|
|
17
19
|
/** Minimal wallet interface for BRC-105 proof construction.
|
|
18
20
|
* Works with both CWIInterface (page context) and WalletInterface (SDK). */
|
|
@@ -21,6 +23,8 @@ interface Brc105Wallet {
|
|
|
21
23
|
protocolID: [number, string];
|
|
22
24
|
keyID: string;
|
|
23
25
|
counterparty: string;
|
|
26
|
+
} | {
|
|
27
|
+
identityKey: true;
|
|
24
28
|
}): Promise<{
|
|
25
29
|
publicKey: string;
|
|
26
30
|
}>;
|
|
@@ -38,6 +42,7 @@ interface Brc105Proof {
|
|
|
38
42
|
derivationPrefix: string;
|
|
39
43
|
derivationSuffix: string;
|
|
40
44
|
transaction: string;
|
|
45
|
+
clientIdentityKey: string;
|
|
41
46
|
txid: string;
|
|
42
47
|
}
|
|
43
48
|
type Brc105ProofConstructor = (challenge: Brc105Challenge) => Promise<Brc105Proof>;
|
|
@@ -93,6 +98,7 @@ interface X402Config {
|
|
|
93
98
|
nightmareConfirmation?: string;
|
|
94
99
|
onLimitReached?: (reason: string) => void;
|
|
95
100
|
onYellowLight?: (detail: YellowLightEvent) => Promise<boolean>;
|
|
101
|
+
onProofError?: (error: unknown, protocol: PaymentProtocol) => void;
|
|
96
102
|
now?: () => number;
|
|
97
103
|
}
|
|
98
104
|
interface YellowLightEvent {
|
|
@@ -135,6 +141,7 @@ interface CWICreateActionOutput {
|
|
|
135
141
|
satoshis: number;
|
|
136
142
|
lockingScript: string;
|
|
137
143
|
description?: string;
|
|
144
|
+
outputDescription?: string;
|
|
138
145
|
customInstructions?: string;
|
|
139
146
|
}
|
|
140
147
|
interface CWICreateActionParams {
|
|
@@ -194,7 +201,7 @@ declare function parseChallenge(header: string): Challenge;
|
|
|
194
201
|
* Expects four headers:
|
|
195
202
|
* - x-bsv-payment-version (must be "1.0")
|
|
196
203
|
* - x-bsv-payment-satoshis-required (positive integer)
|
|
197
|
-
* - x-bsv-auth-identity-key (
|
|
204
|
+
* - x-bsv-auth-identity-key or x-bsv-payment-identity-key (compressed pubkey)
|
|
198
205
|
* - x-bsv-payment-derivation-prefix (non-empty)
|
|
199
206
|
*/
|
|
200
207
|
declare function parseBrc105Challenge(response: Response): Brc105Challenge;
|
|
@@ -209,7 +216,7 @@ declare function parseBrc105Challenge(response: Response): Brc105Challenge;
|
|
|
209
216
|
* 4. Call wallet.createAction with the locking script and custom instructions
|
|
210
217
|
* 5. Convert transaction to base64
|
|
211
218
|
*/
|
|
212
|
-
declare function constructBrc105Proof(challenge: Brc105Challenge, wallet: Brc105Wallet): Promise<Brc105Proof>;
|
|
219
|
+
declare function constructBrc105Proof(challenge: Brc105Challenge, wallet: Brc105Wallet, origin?: string): Promise<Brc105Proof>;
|
|
213
220
|
|
|
214
221
|
/** Anything with a numeric `amount` can be checked against spending limits. */
|
|
215
222
|
type SpendCheckable = Challenge | PaymentRequest;
|
|
@@ -267,4 +274,4 @@ type SitePromptFn = (origin: string) => Promise<SitePolicyAction>;
|
|
|
267
274
|
*/
|
|
268
275
|
declare function resolveSitePolicy(origin: string, limits: SpendLimits, twoFactorProvider?: TwoFactorProvider, promptFn?: SitePromptFn): Promise<SitePolicy>;
|
|
269
276
|
|
|
270
|
-
export { BFG_DAILY_CEILING_SATOSHIS, BFG_PER_TX_CEILING_SATOSHIS, type Brc105Challenge, type Brc105Proof, type Brc105ProofConstructor, type Brc105Wallet, type Challenge, type LedgerEntry, type LimitCheckResult, type LimitState, LocalStorageAdapter, type PaymentProtocol, type PaymentRequest, type Proof, RateLimiter, type SitePolicy, type SitePolicyAction, type SpendCheckable, type SpendLimits, type SpendMode, type StorageAdapter, TIER_PRESETS, type TierName, type TierPreset, type TimeWindow, type TwoFactorAction, type TwoFactorPolicy, type TwoFactorProvider, WalletTwoFactorProvider, type WindowLimit, type X402Config, type X402FetchFn, type YellowLightEvent, constructBrc105Proof, createX402Fetch, parseBrc105Challenge, parseChallenge, resolveSitePolicy, resolveSpendLimits, x402Fetch };
|
|
277
|
+
export { BFG_DAILY_CEILING_SATOSHIS, BFG_PER_TX_CEILING_SATOSHIS, type BlockSeverity, type Brc105Challenge, type Brc105Proof, type Brc105ProofConstructor, type Brc105Wallet, type CWICreateActionOutput, type CWICreateActionParams, type CWICreateActionResult, type Challenge, type KeyDeriver, type LedgerEntry, type LimitCheckResult, type LimitState, LocalStorageAdapter, type PaymentProtocol, type PaymentRequest, type Proof, RateLimiter, type SitePolicy, type SitePolicyAction, type SitePromptFn, type SpendCheckable, type SpendLimits, type SpendMode, type StorageAdapter, TIER_PRESETS, type TierName, type TierPreset, type TimeWindow, type TwoFactorAction, type TwoFactorPolicy, type TwoFactorProvider, WalletTwoFactorProvider, type WindowLimit, type X402Config, type X402FetchFn, type YellowLightEvent, constructBrc105Proof, createX402Fetch, parseBrc105Challenge, parseChallenge, resolveSitePolicy, resolveSpendLimits, x402Fetch };
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ interface Brc105Challenge {
|
|
|
13
13
|
satoshisRequired: number;
|
|
14
14
|
serverIdentityKey: string;
|
|
15
15
|
derivationPrefix: string;
|
|
16
|
+
/** Whether the identity key came from BRC-103 auth (vs standalone x-bsv-payment-identity-key). */
|
|
17
|
+
authenticated: boolean;
|
|
16
18
|
}
|
|
17
19
|
/** Minimal wallet interface for BRC-105 proof construction.
|
|
18
20
|
* Works with both CWIInterface (page context) and WalletInterface (SDK). */
|
|
@@ -21,6 +23,8 @@ interface Brc105Wallet {
|
|
|
21
23
|
protocolID: [number, string];
|
|
22
24
|
keyID: string;
|
|
23
25
|
counterparty: string;
|
|
26
|
+
} | {
|
|
27
|
+
identityKey: true;
|
|
24
28
|
}): Promise<{
|
|
25
29
|
publicKey: string;
|
|
26
30
|
}>;
|
|
@@ -38,6 +42,7 @@ interface Brc105Proof {
|
|
|
38
42
|
derivationPrefix: string;
|
|
39
43
|
derivationSuffix: string;
|
|
40
44
|
transaction: string;
|
|
45
|
+
clientIdentityKey: string;
|
|
41
46
|
txid: string;
|
|
42
47
|
}
|
|
43
48
|
type Brc105ProofConstructor = (challenge: Brc105Challenge) => Promise<Brc105Proof>;
|
|
@@ -93,6 +98,7 @@ interface X402Config {
|
|
|
93
98
|
nightmareConfirmation?: string;
|
|
94
99
|
onLimitReached?: (reason: string) => void;
|
|
95
100
|
onYellowLight?: (detail: YellowLightEvent) => Promise<boolean>;
|
|
101
|
+
onProofError?: (error: unknown, protocol: PaymentProtocol) => void;
|
|
96
102
|
now?: () => number;
|
|
97
103
|
}
|
|
98
104
|
interface YellowLightEvent {
|
|
@@ -135,6 +141,7 @@ interface CWICreateActionOutput {
|
|
|
135
141
|
satoshis: number;
|
|
136
142
|
lockingScript: string;
|
|
137
143
|
description?: string;
|
|
144
|
+
outputDescription?: string;
|
|
138
145
|
customInstructions?: string;
|
|
139
146
|
}
|
|
140
147
|
interface CWICreateActionParams {
|
|
@@ -194,7 +201,7 @@ declare function parseChallenge(header: string): Challenge;
|
|
|
194
201
|
* Expects four headers:
|
|
195
202
|
* - x-bsv-payment-version (must be "1.0")
|
|
196
203
|
* - x-bsv-payment-satoshis-required (positive integer)
|
|
197
|
-
* - x-bsv-auth-identity-key (
|
|
204
|
+
* - x-bsv-auth-identity-key or x-bsv-payment-identity-key (compressed pubkey)
|
|
198
205
|
* - x-bsv-payment-derivation-prefix (non-empty)
|
|
199
206
|
*/
|
|
200
207
|
declare function parseBrc105Challenge(response: Response): Brc105Challenge;
|
|
@@ -209,7 +216,7 @@ declare function parseBrc105Challenge(response: Response): Brc105Challenge;
|
|
|
209
216
|
* 4. Call wallet.createAction with the locking script and custom instructions
|
|
210
217
|
* 5. Convert transaction to base64
|
|
211
218
|
*/
|
|
212
|
-
declare function constructBrc105Proof(challenge: Brc105Challenge, wallet: Brc105Wallet): Promise<Brc105Proof>;
|
|
219
|
+
declare function constructBrc105Proof(challenge: Brc105Challenge, wallet: Brc105Wallet, origin?: string): Promise<Brc105Proof>;
|
|
213
220
|
|
|
214
221
|
/** Anything with a numeric `amount` can be checked against spending limits. */
|
|
215
222
|
type SpendCheckable = Challenge | PaymentRequest;
|
|
@@ -267,4 +274,4 @@ type SitePromptFn = (origin: string) => Promise<SitePolicyAction>;
|
|
|
267
274
|
*/
|
|
268
275
|
declare function resolveSitePolicy(origin: string, limits: SpendLimits, twoFactorProvider?: TwoFactorProvider, promptFn?: SitePromptFn): Promise<SitePolicy>;
|
|
269
276
|
|
|
270
|
-
export { BFG_DAILY_CEILING_SATOSHIS, BFG_PER_TX_CEILING_SATOSHIS, type Brc105Challenge, type Brc105Proof, type Brc105ProofConstructor, type Brc105Wallet, type Challenge, type LedgerEntry, type LimitCheckResult, type LimitState, LocalStorageAdapter, type PaymentProtocol, type PaymentRequest, type Proof, RateLimiter, type SitePolicy, type SitePolicyAction, type SpendCheckable, type SpendLimits, type SpendMode, type StorageAdapter, TIER_PRESETS, type TierName, type TierPreset, type TimeWindow, type TwoFactorAction, type TwoFactorPolicy, type TwoFactorProvider, WalletTwoFactorProvider, type WindowLimit, type X402Config, type X402FetchFn, type YellowLightEvent, constructBrc105Proof, createX402Fetch, parseBrc105Challenge, parseChallenge, resolveSitePolicy, resolveSpendLimits, x402Fetch };
|
|
277
|
+
export { BFG_DAILY_CEILING_SATOSHIS, BFG_PER_TX_CEILING_SATOSHIS, type BlockSeverity, type Brc105Challenge, type Brc105Proof, type Brc105ProofConstructor, type Brc105Wallet, type CWICreateActionOutput, type CWICreateActionParams, type CWICreateActionResult, type Challenge, type KeyDeriver, type LedgerEntry, type LimitCheckResult, type LimitState, LocalStorageAdapter, type PaymentProtocol, type PaymentRequest, type Proof, RateLimiter, type SitePolicy, type SitePolicyAction, type SitePromptFn, type SpendCheckable, type SpendLimits, type SpendMode, type StorageAdapter, TIER_PRESETS, type TierName, type TierPreset, type TimeWindow, type TwoFactorAction, type TwoFactorPolicy, type TwoFactorProvider, WalletTwoFactorProvider, type WindowLimit, type X402Config, type X402FetchFn, type YellowLightEvent, constructBrc105Proof, createX402Fetch, parseBrc105Challenge, parseChallenge, resolveSitePolicy, resolveSpendLimits, x402Fetch };
|
package/dist/index.js
CHANGED
|
@@ -15,12 +15,15 @@ function parseBrc105Challenge(response) {
|
|
|
15
15
|
if (!Number.isFinite(satoshisRequired) || !Number.isInteger(satoshisRequired) || satoshisRequired <= 0) {
|
|
16
16
|
throw new Error("BRC-105: satoshis-required must be a positive integer");
|
|
17
17
|
}
|
|
18
|
-
const
|
|
18
|
+
const authIdentityKey = response.headers.get("x-bsv-auth-identity-key") || null;
|
|
19
|
+
const paymentIdentityKey = response.headers.get("x-bsv-payment-identity-key") || null;
|
|
20
|
+
const authenticated = authIdentityKey !== null && authIdentityKey.length > 0;
|
|
21
|
+
const serverIdentityKey = authIdentityKey || paymentIdentityKey;
|
|
19
22
|
if (serverIdentityKey === null || serverIdentityKey.length === 0) {
|
|
20
|
-
throw new Error("BRC-105: missing
|
|
23
|
+
throw new Error("BRC-105: missing identity key (expected x-bsv-auth-identity-key or x-bsv-payment-identity-key)");
|
|
21
24
|
}
|
|
22
25
|
if (!/^0[23][0-9a-fA-F]{64}$/.test(serverIdentityKey)) {
|
|
23
|
-
throw new Error("BRC-105:
|
|
26
|
+
throw new Error("BRC-105: identity key must be a 33-byte compressed public key (hex)");
|
|
24
27
|
}
|
|
25
28
|
const derivationPrefix = response.headers.get("x-bsv-payment-derivation-prefix");
|
|
26
29
|
if (derivationPrefix === null || derivationPrefix.length === 0) {
|
|
@@ -30,7 +33,8 @@ function parseBrc105Challenge(response) {
|
|
|
30
33
|
version,
|
|
31
34
|
satoshisRequired,
|
|
32
35
|
serverIdentityKey,
|
|
33
|
-
derivationPrefix
|
|
36
|
+
derivationPrefix,
|
|
37
|
+
authenticated
|
|
34
38
|
};
|
|
35
39
|
}
|
|
36
40
|
|
|
@@ -478,7 +482,8 @@ async function createDerivationSuffix(wallet) {
|
|
|
478
482
|
const nonceBytes = [...firstHalf, ...hmac];
|
|
479
483
|
return numberArrayToBase64(nonceBytes);
|
|
480
484
|
}
|
|
481
|
-
async function constructBrc105Proof(challenge, wallet) {
|
|
485
|
+
async function constructBrc105Proof(challenge, wallet, origin) {
|
|
486
|
+
const { publicKey: clientIdentityKey } = await wallet.getPublicKey({ identityKey: true });
|
|
482
487
|
const derivationSuffix = await createDerivationSuffix(wallet);
|
|
483
488
|
const keyID = `${challenge.derivationPrefix} ${derivationSuffix}`;
|
|
484
489
|
const { publicKey: derivedPublicKey } = await wallet.getPublicKey({
|
|
@@ -487,12 +492,13 @@ async function constructBrc105Proof(challenge, wallet) {
|
|
|
487
492
|
counterparty: challenge.serverIdentityKey
|
|
488
493
|
});
|
|
489
494
|
const lockingScript = await pubkeyToP2PKHLockingScript(derivedPublicKey);
|
|
495
|
+
const description = origin ? `Payment for request to ${origin}` : "BRC-105 payment";
|
|
490
496
|
const result = await wallet.createAction({
|
|
491
|
-
description
|
|
497
|
+
description,
|
|
492
498
|
outputs: [{
|
|
493
499
|
satoshis: challenge.satoshisRequired,
|
|
494
500
|
lockingScript,
|
|
495
|
-
|
|
501
|
+
outputDescription: "HTTP request payment",
|
|
496
502
|
customInstructions: JSON.stringify({
|
|
497
503
|
derivationPrefix: challenge.derivationPrefix,
|
|
498
504
|
derivationSuffix,
|
|
@@ -515,6 +521,7 @@ async function constructBrc105Proof(challenge, wallet) {
|
|
|
515
521
|
derivationPrefix: challenge.derivationPrefix,
|
|
516
522
|
derivationSuffix,
|
|
517
523
|
transaction: transactionBase64,
|
|
524
|
+
clientIdentityKey,
|
|
518
525
|
txid: result.txid
|
|
519
526
|
};
|
|
520
527
|
}
|
|
@@ -1127,12 +1134,26 @@ function createX402Fetch(config = {}) {
|
|
|
1127
1134
|
let proof;
|
|
1128
1135
|
try {
|
|
1129
1136
|
proof = await buildProof();
|
|
1130
|
-
} catch {
|
|
1137
|
+
} catch (err) {
|
|
1138
|
+
console.error(`[x402] Proof construction failed (${protocol}):`, err);
|
|
1139
|
+
config.onProofError?.(err, protocol);
|
|
1131
1140
|
return originalResponse;
|
|
1132
1141
|
}
|
|
1133
1142
|
rl.record(makeLedgerEntry(proof));
|
|
1134
1143
|
await persist(rl);
|
|
1135
|
-
|
|
1144
|
+
const maxAttempts = 3;
|
|
1145
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
1146
|
+
try {
|
|
1147
|
+
return await retryWithProof(proof);
|
|
1148
|
+
} catch (err) {
|
|
1149
|
+
if (attempt >= maxAttempts) {
|
|
1150
|
+
console.error(`[x402] Paid request failed after ${maxAttempts} attempts (${protocol}):`, err);
|
|
1151
|
+
return originalResponse;
|
|
1152
|
+
}
|
|
1153
|
+
await new Promise((r) => setTimeout(r, 250 * Math.pow(2, attempt)));
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
return originalResponse;
|
|
1136
1157
|
});
|
|
1137
1158
|
}
|
|
1138
1159
|
const fetchFn = async function x402Fetch2(input, init) {
|
|
@@ -1188,11 +1209,12 @@ function createX402Fetch(config = {}) {
|
|
|
1188
1209
|
if (brc105ProofConstructor) {
|
|
1189
1210
|
return brc105ProofConstructor(brc105Challenge);
|
|
1190
1211
|
}
|
|
1191
|
-
return constructBrc105Proof(brc105Challenge, brc105Wallet);
|
|
1212
|
+
return constructBrc105Proof(brc105Challenge, brc105Wallet, origin);
|
|
1192
1213
|
},
|
|
1193
1214
|
(proof) => {
|
|
1194
1215
|
const headers = new Headers(init?.headers);
|
|
1195
1216
|
headers.set("x-bsv-payment", JSON.stringify(proof));
|
|
1217
|
+
headers.set("x-bsv-auth-identity-key", proof.clientIdentityKey);
|
|
1196
1218
|
return fetch(input, { ...init, headers });
|
|
1197
1219
|
},
|
|
1198
1220
|
(proof) => ({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bsv-x402",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "x402 payment protocol client — a fetch() wrapper that handles 402 payment flows transparently",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -25,19 +25,23 @@
|
|
|
25
25
|
"build:firefox": "tsx plugins/build.ts --target firefox",
|
|
26
26
|
"build:safari": "tsx plugins/build.ts --target safari",
|
|
27
27
|
"build:all": "npm run build && npm run build:plugins",
|
|
28
|
-
"demo": "npm run build && tsx demo/server.ts"
|
|
28
|
+
"demo": "npm run build && tsx demo/server.ts",
|
|
29
|
+
"docs": "typedoc",
|
|
30
|
+
"postinstall": "patch-package"
|
|
29
31
|
},
|
|
30
32
|
"repository": {
|
|
31
33
|
"type": "git",
|
|
32
|
-
"url": "https://github.com/sgbett/bsv-x402.git"
|
|
34
|
+
"url": "git+https://github.com/sgbett/bsv-x402.git"
|
|
33
35
|
},
|
|
34
36
|
"devDependencies": {
|
|
35
37
|
"@bsv/wallet-toolbox-client": "^2.1.17",
|
|
36
38
|
"@types/chrome": "^0.1.38",
|
|
37
39
|
"@types/express": "^5.0.6",
|
|
38
40
|
"express": "^5.2.1",
|
|
41
|
+
"patch-package": "^8.0.1",
|
|
39
42
|
"tsup": "^8.0.0",
|
|
40
43
|
"tsx": "^4.21.0",
|
|
44
|
+
"typedoc": "^0.28.18",
|
|
41
45
|
"typescript": "^5.0.0",
|
|
42
46
|
"vitest": "^3.0.0"
|
|
43
47
|
}
|