bsv-x402 0.6.0 → 0.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 +57 -7
- package/dist/index.d.cts +12 -3
- package/dist/index.d.ts +12 -3
- package/dist/index.js +57 -7
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -544,6 +544,8 @@ async function constructBrc105Proof(challenge, wallet, origin) {
|
|
|
544
544
|
})
|
|
545
545
|
}],
|
|
546
546
|
options: {
|
|
547
|
+
returnTXIDOnly: false,
|
|
548
|
+
noSend: true,
|
|
547
549
|
randomizeOutputs: false
|
|
548
550
|
}
|
|
549
551
|
});
|
|
@@ -555,13 +557,21 @@ async function constructBrc105Proof(challenge, wallet, origin) {
|
|
|
555
557
|
} else {
|
|
556
558
|
throw new Error("Wallet returned no transaction data (neither tx nor rawTx)");
|
|
557
559
|
}
|
|
558
|
-
|
|
560
|
+
const proof = {
|
|
559
561
|
derivationPrefix: challenge.derivationPrefix,
|
|
560
562
|
derivationSuffix,
|
|
561
563
|
transaction: transactionBase64,
|
|
562
564
|
clientIdentityKey,
|
|
563
565
|
txid: result.txid
|
|
564
566
|
};
|
|
567
|
+
const abort = wallet.abortAction ? async () => {
|
|
568
|
+
try {
|
|
569
|
+
await wallet.abortAction({ reference: result.txid });
|
|
570
|
+
} catch (err) {
|
|
571
|
+
console.warn("[x402] abortAction failed:", err);
|
|
572
|
+
}
|
|
573
|
+
} : void 0;
|
|
574
|
+
return { proof, abort };
|
|
565
575
|
}
|
|
566
576
|
|
|
567
577
|
// src/challenge.ts
|
|
@@ -597,6 +607,22 @@ function parseChallenge(header) {
|
|
|
597
607
|
}
|
|
598
608
|
|
|
599
609
|
// src/x402-fetch.ts
|
|
610
|
+
function bytesToBase642(bytes) {
|
|
611
|
+
let binary = "";
|
|
612
|
+
for (const b of bytes) binary += String.fromCharCode(b);
|
|
613
|
+
return btoa(binary);
|
|
614
|
+
}
|
|
615
|
+
function numberArrayToBase642(arr) {
|
|
616
|
+
return bytesToBase642(new Uint8Array(arr));
|
|
617
|
+
}
|
|
618
|
+
function hexToBytes2(hex) {
|
|
619
|
+
if (hex.length % 2 !== 0) throw new Error("Hex string must have even length");
|
|
620
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
621
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
622
|
+
bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
|
|
623
|
+
}
|
|
624
|
+
return bytes;
|
|
625
|
+
}
|
|
600
626
|
var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
601
627
|
function base58DecodeCheck(address) {
|
|
602
628
|
let leadingZeros = 0;
|
|
@@ -660,12 +686,17 @@ async function defaultConstructProof(challenge) {
|
|
|
660
686
|
if (!result || !result.txid) {
|
|
661
687
|
throw new Error("Wallet declined payment or returned invalid result");
|
|
662
688
|
}
|
|
663
|
-
|
|
664
|
-
|
|
689
|
+
let beef;
|
|
690
|
+
if (result.tx && Array.isArray(result.tx) && result.tx.length > 0) {
|
|
691
|
+
beef = numberArrayToBase642(result.tx);
|
|
692
|
+
} else if (result.rawTx && typeof result.rawTx === "string" && result.rawTx.length > 0) {
|
|
693
|
+
beef = bytesToBase642(hexToBytes2(result.rawTx));
|
|
694
|
+
} else {
|
|
695
|
+
throw new Error("Wallet returned no transaction data (neither tx nor rawTx)");
|
|
665
696
|
}
|
|
666
697
|
return {
|
|
667
698
|
txid: result.txid,
|
|
668
|
-
|
|
699
|
+
beef
|
|
669
700
|
};
|
|
670
701
|
}
|
|
671
702
|
function createX402Fetch(config = {}) {
|
|
@@ -706,11 +737,16 @@ function createX402Fetch(config = {}) {
|
|
|
706
737
|
return response;
|
|
707
738
|
}
|
|
708
739
|
let proof;
|
|
740
|
+
let abort;
|
|
709
741
|
try {
|
|
710
742
|
if (brc105ProofConstructor) {
|
|
711
|
-
|
|
743
|
+
const result = await brc105ProofConstructor(brc105Challenge);
|
|
744
|
+
proof = result.proof;
|
|
745
|
+
abort = result.abort;
|
|
712
746
|
} else {
|
|
713
|
-
|
|
747
|
+
const result = await constructBrc105Proof(brc105Challenge, brc105Wallet, origin);
|
|
748
|
+
proof = result.proof;
|
|
749
|
+
abort = result.abort;
|
|
714
750
|
}
|
|
715
751
|
} catch (err) {
|
|
716
752
|
console.error("[x402] Proof construction failed (brc105):", err);
|
|
@@ -720,7 +756,21 @@ function createX402Fetch(config = {}) {
|
|
|
720
756
|
const headers = new Headers(init?.headers);
|
|
721
757
|
headers.set("x-bsv-payment", JSON.stringify(proof));
|
|
722
758
|
headers.set("x-bsv-auth-identity-key", proof.clientIdentityKey);
|
|
723
|
-
|
|
759
|
+
let retryResponse;
|
|
760
|
+
try {
|
|
761
|
+
retryResponse = await fetch(input, { ...init, headers });
|
|
762
|
+
} catch (err) {
|
|
763
|
+
if (abort) {
|
|
764
|
+
await abort();
|
|
765
|
+
console.warn("[x402] BRC-105 retry fetch failed, UTXOs released via abortAction");
|
|
766
|
+
}
|
|
767
|
+
throw err;
|
|
768
|
+
}
|
|
769
|
+
if (!retryResponse.ok && abort) {
|
|
770
|
+
await abort();
|
|
771
|
+
console.warn("[x402] Server rejected BRC-105 payment, UTXOs released via abortAction");
|
|
772
|
+
}
|
|
773
|
+
return retryResponse;
|
|
724
774
|
}
|
|
725
775
|
return response;
|
|
726
776
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -6,7 +6,7 @@ interface Challenge {
|
|
|
6
6
|
}
|
|
7
7
|
interface Proof {
|
|
8
8
|
txid: string;
|
|
9
|
-
|
|
9
|
+
beef: string;
|
|
10
10
|
}
|
|
11
11
|
interface Brc105Challenge {
|
|
12
12
|
version: string;
|
|
@@ -37,6 +37,11 @@ interface Brc105Wallet {
|
|
|
37
37
|
hmac: number[];
|
|
38
38
|
}>;
|
|
39
39
|
createAction(params: CWICreateActionParams): Promise<CWICreateActionResult>;
|
|
40
|
+
abortAction?: (args: {
|
|
41
|
+
reference: string;
|
|
42
|
+
}) => Promise<{
|
|
43
|
+
aborted: boolean;
|
|
44
|
+
}>;
|
|
40
45
|
}
|
|
41
46
|
interface Brc105Proof {
|
|
42
47
|
derivationPrefix: string;
|
|
@@ -45,7 +50,11 @@ interface Brc105Proof {
|
|
|
45
50
|
clientIdentityKey: string;
|
|
46
51
|
txid: string;
|
|
47
52
|
}
|
|
48
|
-
|
|
53
|
+
interface Brc105ProofResult {
|
|
54
|
+
proof: Brc105Proof;
|
|
55
|
+
abort?: () => Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
type Brc105ProofConstructor = (challenge: Brc105Challenge) => Promise<Brc105ProofResult>;
|
|
49
58
|
type PaymentProtocol = 'x402' | 'brc105';
|
|
50
59
|
interface PaymentRequest {
|
|
51
60
|
amount: number;
|
|
@@ -118,7 +127,7 @@ declare function parseBrc105Challenge(response: Response): Brc105Challenge;
|
|
|
118
127
|
* 4. Call wallet.createAction with the locking script and custom instructions
|
|
119
128
|
* 5. Convert transaction to base64
|
|
120
129
|
*/
|
|
121
|
-
declare function constructBrc105Proof(challenge: Brc105Challenge, wallet: Brc105Wallet, origin?: string): Promise<
|
|
130
|
+
declare function constructBrc105Proof(challenge: Brc105Challenge, wallet: Brc105Wallet, origin?: string): Promise<Brc105ProofResult>;
|
|
122
131
|
|
|
123
132
|
/**
|
|
124
133
|
* Autospend balance cap per tier (max sats that can be auto-spent without confirmation).
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ interface Challenge {
|
|
|
6
6
|
}
|
|
7
7
|
interface Proof {
|
|
8
8
|
txid: string;
|
|
9
|
-
|
|
9
|
+
beef: string;
|
|
10
10
|
}
|
|
11
11
|
interface Brc105Challenge {
|
|
12
12
|
version: string;
|
|
@@ -37,6 +37,11 @@ interface Brc105Wallet {
|
|
|
37
37
|
hmac: number[];
|
|
38
38
|
}>;
|
|
39
39
|
createAction(params: CWICreateActionParams): Promise<CWICreateActionResult>;
|
|
40
|
+
abortAction?: (args: {
|
|
41
|
+
reference: string;
|
|
42
|
+
}) => Promise<{
|
|
43
|
+
aborted: boolean;
|
|
44
|
+
}>;
|
|
40
45
|
}
|
|
41
46
|
interface Brc105Proof {
|
|
42
47
|
derivationPrefix: string;
|
|
@@ -45,7 +50,11 @@ interface Brc105Proof {
|
|
|
45
50
|
clientIdentityKey: string;
|
|
46
51
|
txid: string;
|
|
47
52
|
}
|
|
48
|
-
|
|
53
|
+
interface Brc105ProofResult {
|
|
54
|
+
proof: Brc105Proof;
|
|
55
|
+
abort?: () => Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
type Brc105ProofConstructor = (challenge: Brc105Challenge) => Promise<Brc105ProofResult>;
|
|
49
58
|
type PaymentProtocol = 'x402' | 'brc105';
|
|
50
59
|
interface PaymentRequest {
|
|
51
60
|
amount: number;
|
|
@@ -118,7 +127,7 @@ declare function parseBrc105Challenge(response: Response): Brc105Challenge;
|
|
|
118
127
|
* 4. Call wallet.createAction with the locking script and custom instructions
|
|
119
128
|
* 5. Convert transaction to base64
|
|
120
129
|
*/
|
|
121
|
-
declare function constructBrc105Proof(challenge: Brc105Challenge, wallet: Brc105Wallet, origin?: string): Promise<
|
|
130
|
+
declare function constructBrc105Proof(challenge: Brc105Challenge, wallet: Brc105Wallet, origin?: string): Promise<Brc105ProofResult>;
|
|
122
131
|
|
|
123
132
|
/**
|
|
124
133
|
* Autospend balance cap per tier (max sats that can be auto-spent without confirmation).
|
package/dist/index.js
CHANGED
|
@@ -506,6 +506,8 @@ async function constructBrc105Proof(challenge, wallet, origin) {
|
|
|
506
506
|
})
|
|
507
507
|
}],
|
|
508
508
|
options: {
|
|
509
|
+
returnTXIDOnly: false,
|
|
510
|
+
noSend: true,
|
|
509
511
|
randomizeOutputs: false
|
|
510
512
|
}
|
|
511
513
|
});
|
|
@@ -517,13 +519,21 @@ async function constructBrc105Proof(challenge, wallet, origin) {
|
|
|
517
519
|
} else {
|
|
518
520
|
throw new Error("Wallet returned no transaction data (neither tx nor rawTx)");
|
|
519
521
|
}
|
|
520
|
-
|
|
522
|
+
const proof = {
|
|
521
523
|
derivationPrefix: challenge.derivationPrefix,
|
|
522
524
|
derivationSuffix,
|
|
523
525
|
transaction: transactionBase64,
|
|
524
526
|
clientIdentityKey,
|
|
525
527
|
txid: result.txid
|
|
526
528
|
};
|
|
529
|
+
const abort = wallet.abortAction ? async () => {
|
|
530
|
+
try {
|
|
531
|
+
await wallet.abortAction({ reference: result.txid });
|
|
532
|
+
} catch (err) {
|
|
533
|
+
console.warn("[x402] abortAction failed:", err);
|
|
534
|
+
}
|
|
535
|
+
} : void 0;
|
|
536
|
+
return { proof, abort };
|
|
527
537
|
}
|
|
528
538
|
|
|
529
539
|
// src/challenge.ts
|
|
@@ -559,6 +569,22 @@ function parseChallenge(header) {
|
|
|
559
569
|
}
|
|
560
570
|
|
|
561
571
|
// src/x402-fetch.ts
|
|
572
|
+
function bytesToBase642(bytes) {
|
|
573
|
+
let binary = "";
|
|
574
|
+
for (const b of bytes) binary += String.fromCharCode(b);
|
|
575
|
+
return btoa(binary);
|
|
576
|
+
}
|
|
577
|
+
function numberArrayToBase642(arr) {
|
|
578
|
+
return bytesToBase642(new Uint8Array(arr));
|
|
579
|
+
}
|
|
580
|
+
function hexToBytes2(hex) {
|
|
581
|
+
if (hex.length % 2 !== 0) throw new Error("Hex string must have even length");
|
|
582
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
583
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
584
|
+
bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
|
|
585
|
+
}
|
|
586
|
+
return bytes;
|
|
587
|
+
}
|
|
562
588
|
var BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
563
589
|
function base58DecodeCheck(address) {
|
|
564
590
|
let leadingZeros = 0;
|
|
@@ -622,12 +648,17 @@ async function defaultConstructProof(challenge) {
|
|
|
622
648
|
if (!result || !result.txid) {
|
|
623
649
|
throw new Error("Wallet declined payment or returned invalid result");
|
|
624
650
|
}
|
|
625
|
-
|
|
626
|
-
|
|
651
|
+
let beef;
|
|
652
|
+
if (result.tx && Array.isArray(result.tx) && result.tx.length > 0) {
|
|
653
|
+
beef = numberArrayToBase642(result.tx);
|
|
654
|
+
} else if (result.rawTx && typeof result.rawTx === "string" && result.rawTx.length > 0) {
|
|
655
|
+
beef = bytesToBase642(hexToBytes2(result.rawTx));
|
|
656
|
+
} else {
|
|
657
|
+
throw new Error("Wallet returned no transaction data (neither tx nor rawTx)");
|
|
627
658
|
}
|
|
628
659
|
return {
|
|
629
660
|
txid: result.txid,
|
|
630
|
-
|
|
661
|
+
beef
|
|
631
662
|
};
|
|
632
663
|
}
|
|
633
664
|
function createX402Fetch(config = {}) {
|
|
@@ -668,11 +699,16 @@ function createX402Fetch(config = {}) {
|
|
|
668
699
|
return response;
|
|
669
700
|
}
|
|
670
701
|
let proof;
|
|
702
|
+
let abort;
|
|
671
703
|
try {
|
|
672
704
|
if (brc105ProofConstructor) {
|
|
673
|
-
|
|
705
|
+
const result = await brc105ProofConstructor(brc105Challenge);
|
|
706
|
+
proof = result.proof;
|
|
707
|
+
abort = result.abort;
|
|
674
708
|
} else {
|
|
675
|
-
|
|
709
|
+
const result = await constructBrc105Proof(brc105Challenge, brc105Wallet, origin);
|
|
710
|
+
proof = result.proof;
|
|
711
|
+
abort = result.abort;
|
|
676
712
|
}
|
|
677
713
|
} catch (err) {
|
|
678
714
|
console.error("[x402] Proof construction failed (brc105):", err);
|
|
@@ -682,7 +718,21 @@ function createX402Fetch(config = {}) {
|
|
|
682
718
|
const headers = new Headers(init?.headers);
|
|
683
719
|
headers.set("x-bsv-payment", JSON.stringify(proof));
|
|
684
720
|
headers.set("x-bsv-auth-identity-key", proof.clientIdentityKey);
|
|
685
|
-
|
|
721
|
+
let retryResponse;
|
|
722
|
+
try {
|
|
723
|
+
retryResponse = await fetch(input, { ...init, headers });
|
|
724
|
+
} catch (err) {
|
|
725
|
+
if (abort) {
|
|
726
|
+
await abort();
|
|
727
|
+
console.warn("[x402] BRC-105 retry fetch failed, UTXOs released via abortAction");
|
|
728
|
+
}
|
|
729
|
+
throw err;
|
|
730
|
+
}
|
|
731
|
+
if (!retryResponse.ok && abort) {
|
|
732
|
+
await abort();
|
|
733
|
+
console.warn("[x402] Server rejected BRC-105 payment, UTXOs released via abortAction");
|
|
734
|
+
}
|
|
735
|
+
return retryResponse;
|
|
686
736
|
}
|
|
687
737
|
return response;
|
|
688
738
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bsv-x402",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
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",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"url": "git+https://github.com/sgbett/bsv-x402.git"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@bsv/wallet-toolbox-client": "
|
|
37
|
+
"@bsv/wallet-toolbox-client": "npm:@sgbett/wallet-toolbox-client@2.1.19-fix.1",
|
|
38
38
|
"@types/chrome": "^0.1.38",
|
|
39
39
|
"@types/express": "^5.0.6",
|
|
40
40
|
"express": "^5.2.1",
|