@bsv/sdk 2.1.5 → 2.1.6
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/cjs/package.json +1 -1
- package/dist/cjs/src/compat/Utxo.js +1 -1
- package/dist/cjs/src/compat/Utxo.js.map +1 -1
- package/dist/cjs/src/primitives/Hash.js +4 -2
- package/dist/cjs/src/primitives/Hash.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/compat/Utxo.js +1 -1
- package/dist/esm/src/compat/Utxo.js.map +1 -1
- package/dist/esm/src/primitives/Hash.js +4 -2
- package/dist/esm/src/primitives/Hash.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/primitives/Hash.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +1 -1
- package/package.json +1 -1
- package/src/compat/Utxo.ts +1 -1
- package/src/compat/__tests/Mnemonic.additional.test.ts +1 -1
- package/src/compat/__tests/Mnemonic.test.ts +1 -1
- package/src/overlay-tools/__tests/Historian.test.ts +1 -1
- package/src/overlay-tools/__tests/HostReputationTracker.additional.test.ts +1 -1
- package/src/primitives/Hash.ts +4 -2
- package/src/primitives/__tests/BigNumber.constructor.test.ts +1 -1
- package/src/primitives/__tests/DRBG.test.ts +4 -12
- package/src/primitives/__tests/Point.additional.test.ts +2 -2
- package/src/primitives/__tests/Point.test.ts +1 -1
- package/src/primitives/__tests/SymmetricKeyCompatibility.test.ts +4 -4
- package/src/registry/__tests/RegistryClient.additional.test.ts +4 -4
- package/src/registry/__tests/RegistryClient.test.ts +2 -2
- package/src/storage/__tests/StorageUploader.test.ts +7 -7
- package/src/transaction/__tests/Transaction.test.ts +3 -3
package/package.json
CHANGED
package/src/compat/Utxo.ts
CHANGED
|
@@ -44,7 +44,7 @@ export default function fromUtxo (
|
|
|
44
44
|
}
|
|
45
45
|
): TransactionInput {
|
|
46
46
|
const sourceTransaction = new Transaction(0, [], [], 0)
|
|
47
|
-
sourceTransaction.outputs = Array(utxo.vout + 1).fill(null)
|
|
47
|
+
sourceTransaction.outputs = new Array(utxo.vout + 1).fill(null)
|
|
48
48
|
sourceTransaction.outputs[utxo.vout] = {
|
|
49
49
|
satoshis: utxo.satoshis,
|
|
50
50
|
lockingScript: LockingScript.fromHex(utxo.script)
|
|
@@ -15,7 +15,7 @@ describe('Mnemonic – additional coverage', () => {
|
|
|
15
15
|
})
|
|
16
16
|
|
|
17
17
|
it('uses 128 bits when bits is NaN', () => {
|
|
18
|
-
const m = new Mnemonic().fromRandom(NaN)
|
|
18
|
+
const m = new Mnemonic().fromRandom(Number.NaN)
|
|
19
19
|
expect(m.mnemonic.split(' ')).toHaveLength(12)
|
|
20
20
|
})
|
|
21
21
|
|
|
@@ -41,7 +41,7 @@ describe('Mnemonic', function () {
|
|
|
41
41
|
m = new Mnemonic().fromRandom(128)
|
|
42
42
|
expect(m.check()).toEqual(true)
|
|
43
43
|
|
|
44
|
-
const entropy = Array(32)
|
|
44
|
+
const entropy = new Array(32)
|
|
45
45
|
entropy.fill(0)
|
|
46
46
|
m = new Mnemonic().fromEntropy(entropy)
|
|
47
47
|
expect(m.check()).toEqual(true)
|
|
@@ -34,7 +34,7 @@ function makeMockTx(txid: string, outputs: any[] = [], inputs: any[] = []): MTx
|
|
|
34
34
|
|
|
35
35
|
function makeMockOutput(scriptHex?: string): TransactionOutput {
|
|
36
36
|
const hex = scriptHex || '76a914' // Default to P2PKH prefix if no script provided
|
|
37
|
-
const scriptArray = hex.match(/.{2}/g)?.map(byte => parseInt(byte, 16)) || [0x76, 0xa9, 0x14]
|
|
37
|
+
const scriptArray = hex.match(/.{2}/g)?.map(byte => Number.parseInt(byte, 16)) || [0x76, 0xa9, 0x14]
|
|
38
38
|
|
|
39
39
|
return {
|
|
40
40
|
satoshis: 1,
|
|
@@ -93,7 +93,7 @@ describe('HostReputationTracker – additional coverage', () => {
|
|
|
93
93
|
|
|
94
94
|
it('treats NaN latency as DEFAULT_LATENCY_MS (1500)', () => {
|
|
95
95
|
const t = new HostReputationTracker()
|
|
96
|
-
t.recordSuccess('https://host.com', NaN)
|
|
96
|
+
t.recordSuccess('https://host.com', Number.NaN)
|
|
97
97
|
const snap = t.snapshot('https://host.com')!
|
|
98
98
|
expect(snap.avgLatencyMs).toBe(1500)
|
|
99
99
|
})
|
package/src/primitives/Hash.ts
CHANGED
|
@@ -261,8 +261,10 @@ function appendUtf8CodeUnit (msg: string, i: number, out: number[]): number {
|
|
|
261
261
|
|
|
262
262
|
function utf8StringToArray (msg: string): number[] {
|
|
263
263
|
const res: number[] = []
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
let i = 0
|
|
265
|
+
while (i < msg.length) {
|
|
266
|
+
const lastConsumed = appendUtf8CodeUnit(msg, i, res)
|
|
267
|
+
i = lastConsumed + 1
|
|
266
268
|
}
|
|
267
269
|
return res
|
|
268
270
|
}
|
|
@@ -34,36 +34,28 @@ describe('DRBG', () => {
|
|
|
34
34
|
const entropy = new Array(31).fill(0x01)
|
|
35
35
|
const nonce = new Array(32).fill(0x02)
|
|
36
36
|
|
|
37
|
-
expect(() =>
|
|
38
|
-
new DRBG(entropy, nonce)
|
|
39
|
-
}).toThrow('Entropy must be exactly 32 bytes (256 bits)')
|
|
37
|
+
expect(() => new DRBG(entropy, nonce)).toThrow('Entropy must be exactly 32 bytes (256 bits)')
|
|
40
38
|
})
|
|
41
39
|
|
|
42
40
|
it('throws if entropy is longer than 32 bytes', () => {
|
|
43
41
|
const entropy = new Array(33).fill(0x01)
|
|
44
42
|
const nonce = new Array(32).fill(0x02)
|
|
45
43
|
|
|
46
|
-
expect(() =>
|
|
47
|
-
new DRBG(entropy, nonce)
|
|
48
|
-
}).toThrow('Entropy must be exactly 32 bytes (256 bits)')
|
|
44
|
+
expect(() => new DRBG(entropy, nonce)).toThrow('Entropy must be exactly 32 bytes (256 bits)')
|
|
49
45
|
})
|
|
50
46
|
|
|
51
47
|
it('throws if nonce is shorter than 32 bytes', () => {
|
|
52
48
|
const entropy = new Array(32).fill(0x01)
|
|
53
49
|
const nonce = new Array(31).fill(0x02)
|
|
54
50
|
|
|
55
|
-
expect(() =>
|
|
56
|
-
new DRBG(entropy, nonce)
|
|
57
|
-
}).toThrow('Nonce must be exactly 32 bytes (256 bits)')
|
|
51
|
+
expect(() => new DRBG(entropy, nonce)).toThrow('Nonce must be exactly 32 bytes (256 bits)')
|
|
58
52
|
})
|
|
59
53
|
|
|
60
54
|
it('throws if nonce is longer than 32 bytes', () => {
|
|
61
55
|
const entropy = new Array(32).fill(0x01)
|
|
62
56
|
const nonce = new Array(33).fill(0x02)
|
|
63
57
|
|
|
64
|
-
expect(() =>
|
|
65
|
-
new DRBG(entropy, nonce)
|
|
66
|
-
}).toThrow('Nonce must be exactly 32 bytes (256 bits)')
|
|
58
|
+
expect(() => new DRBG(entropy, nonce)).toThrow('Nonce must be exactly 32 bytes (256 bits)')
|
|
67
59
|
})
|
|
68
60
|
|
|
69
61
|
it('accepts both hex strings and number[] inputs equivalently', () => {
|
|
@@ -118,7 +118,7 @@ describe('Point – additional coverage', () => {
|
|
|
118
118
|
})
|
|
119
119
|
|
|
120
120
|
it('throws for unknown format', () => {
|
|
121
|
-
const der = [0x05, ...Array(32).fill(0x01)]
|
|
121
|
+
const der = [0x05, ...new Array(32).fill(0x01)]
|
|
122
122
|
expect(() => Point.fromDER(der)).toThrow('Unknown point format')
|
|
123
123
|
})
|
|
124
124
|
})
|
|
@@ -147,7 +147,7 @@ describe('Point – additional coverage', () => {
|
|
|
147
147
|
it('fromX accepts number', () => {
|
|
148
148
|
// Use a valid x value that has a square root mod p
|
|
149
149
|
const g = G.mul(new BigNumber(7))
|
|
150
|
-
const xNum = parseInt(g.getX().toString(16).slice(-4), 16)
|
|
150
|
+
const xNum = Number.parseInt(g.getX().toString(16).slice(-4), 16)
|
|
151
151
|
// fromX with a number, may produce a point
|
|
152
152
|
const p = Point.fromX(g.getX(), true)
|
|
153
153
|
expect(p.validate()).toBe(true)
|
|
@@ -40,7 +40,7 @@ describe('Point.fromJSON / fromDER / fromX curve validation (TOB-24)', () => {
|
|
|
40
40
|
it('rejects invalid compressed points in fromDER', () => {
|
|
41
41
|
// 0x02 is a valid compressed prefix, but x = 0 gives y^2 = 7,
|
|
42
42
|
// which has no square root mod p on secp256k1 → invalid point.
|
|
43
|
-
const der = [0x02, ...Array(32).fill(0x00)]
|
|
43
|
+
const der = [0x02, ...new Array(32).fill(0x00)]
|
|
44
44
|
expect(() => Point.fromDER(der)).toThrow(/Invalid point/)
|
|
45
45
|
})
|
|
46
46
|
|
|
@@ -37,7 +37,7 @@ describe('Cross-SDK Compatibility Tests', () => {
|
|
|
37
37
|
// Convert hex to byte array
|
|
38
38
|
const ciphertext: number[] = []
|
|
39
39
|
for (let i = 0; i < ciphertextHex.length; i += 2) {
|
|
40
|
-
ciphertext.push(parseInt(ciphertextHex.slice(i, i + 2), 16))
|
|
40
|
+
ciphertext.push(Number.parseInt(ciphertextHex.slice(i, i + 2), 16))
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// Decrypt using TypeScript SDK
|
|
@@ -83,7 +83,7 @@ describe('Cross-SDK Compatibility Tests', () => {
|
|
|
83
83
|
// Convert hex to byte array
|
|
84
84
|
const ciphertext: number[] = []
|
|
85
85
|
for (let i = 0; i < ciphertextHex.length; i += 2) {
|
|
86
|
-
ciphertext.push(parseInt(ciphertextHex.slice(i, i + 2), 16))
|
|
86
|
+
ciphertext.push(Number.parseInt(ciphertextHex.slice(i, i + 2), 16))
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// Decrypt using TypeScript SDK
|
|
@@ -127,7 +127,7 @@ describe('Cross-SDK Compatibility Tests', () => {
|
|
|
127
127
|
// Test TypeScript decrypting Go ciphertext
|
|
128
128
|
const goCiphertextBytes: number[] = []
|
|
129
129
|
for (let i = 0; i < goCiphertext.length; i += 2) {
|
|
130
|
-
goCiphertextBytes.push(parseInt(goCiphertext.substr(i, 2), 16))
|
|
130
|
+
goCiphertextBytes.push(Number.parseInt(goCiphertext.substr(i, 2), 16))
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
const goDecrypted = symKey.decrypt(goCiphertextBytes, 'utf8')
|
|
@@ -136,7 +136,7 @@ describe('Cross-SDK Compatibility Tests', () => {
|
|
|
136
136
|
// Test TypeScript decrypting TypeScript ciphertext (sanity check)
|
|
137
137
|
const tsCiphertextBytes: number[] = []
|
|
138
138
|
for (let i = 0; i < tsCiphertext.length; i += 2) {
|
|
139
|
-
tsCiphertextBytes.push(parseInt(tsCiphertext.substr(i, 2), 16))
|
|
139
|
+
tsCiphertextBytes.push(Number.parseInt(tsCiphertext.substr(i, 2), 16))
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
const tsDecrypted = symKey.decrypt(tsCiphertextBytes, 'utf8')
|
|
@@ -77,10 +77,10 @@ jest.mock('../../transaction/index.js', () => ({
|
|
|
77
77
|
jest.mock('../../primitives/index.js', () => ({
|
|
78
78
|
Utils: {
|
|
79
79
|
toArray: jest.fn().mockImplementation((str: string) =>
|
|
80
|
-
Array.from(str).map((c) => c.
|
|
80
|
+
Array.from(str).map((c) => c.codePointAt(0))
|
|
81
81
|
),
|
|
82
82
|
toUTF8: jest.fn().mockImplementation((arr: number[] | string) => {
|
|
83
|
-
if (Array.isArray(arr)) return arr.map((n) => String.
|
|
83
|
+
if (Array.isArray(arr)) return arr.map((n) => String.fromCodePoint(n)).join('')
|
|
84
84
|
return arr
|
|
85
85
|
})
|
|
86
86
|
}
|
|
@@ -628,7 +628,7 @@ describe('RegistryClient.resolve – protocol and certificate parsing', () => {
|
|
|
628
628
|
// protocol has 7 fields: protocolID, name, iconURL, description, docURL, operator, sig
|
|
629
629
|
;(PushDrop.decode as jest.Mock).mockReturnValueOnce({
|
|
630
630
|
fields: [
|
|
631
|
-
Array.from('[1,"proto"]').map((c) => c.
|
|
631
|
+
Array.from('[1,"proto"]').map((c) => c.codePointAt(0)), // protocolID JSON
|
|
632
632
|
[110, 97, 109, 101], // 'name'
|
|
633
633
|
[105, 99, 111, 110], // 'icon'
|
|
634
634
|
[100, 101, 115, 99], // 'desc'
|
|
@@ -658,7 +658,7 @@ describe('RegistryClient.resolve – protocol and certificate parsing', () => {
|
|
|
658
658
|
[105, 99, 111, 110], // 'icon'
|
|
659
659
|
[100, 101, 115, 99], // 'desc'
|
|
660
660
|
[100, 111, 99], // 'doc'
|
|
661
|
-
Array.from(fieldsJSON).map((c) => c.
|
|
661
|
+
Array.from(fieldsJSON).map((c) => c.codePointAt(0)), // fieldsJSON
|
|
662
662
|
[111, 112], // 'op' - operator
|
|
663
663
|
[115, 105, 103] // signature
|
|
664
664
|
]
|
|
@@ -82,11 +82,11 @@ jest.mock('../../primitives/index.js', () => {
|
|
|
82
82
|
return {
|
|
83
83
|
Utils: {
|
|
84
84
|
toArray: jest.fn().mockImplementation((str: string) =>
|
|
85
|
-
Array.from(str).map((c) => c.
|
|
85
|
+
Array.from(str).map((c) => c.codePointAt(0))
|
|
86
86
|
),
|
|
87
87
|
toUTF8: jest.fn().mockImplementation((arr: number[] | string) => {
|
|
88
88
|
if (Array.isArray(arr)) {
|
|
89
|
-
return arr.map((n) => String.
|
|
89
|
+
return arr.map((n) => String.fromCodePoint(n)).join('')
|
|
90
90
|
}
|
|
91
91
|
return arr
|
|
92
92
|
})
|
|
@@ -376,7 +376,7 @@ describe('StorageUploader — multi-provider behavior', () => {
|
|
|
376
376
|
})
|
|
377
377
|
|
|
378
378
|
// All three quotes requested (up to 2 * resilienceLevel = 4 allowed, but we only have 3 hosts).
|
|
379
|
-
expect(quoteCalls.sort()).toEqual([
|
|
379
|
+
expect(quoteCalls.sort((a, b) => a.localeCompare(b))).toEqual([
|
|
380
380
|
'https://a.example/quote',
|
|
381
381
|
'https://b.example/quote',
|
|
382
382
|
'https://c.example/quote'
|
|
@@ -611,7 +611,7 @@ describe('StorageUploader — multi-provider behavior', () => {
|
|
|
611
611
|
})
|
|
612
612
|
|
|
613
613
|
// Only the first batch of 4 quote requests should have been issued.
|
|
614
|
-
expect(quoteCalls.sort()).toEqual([
|
|
614
|
+
expect(quoteCalls.sort((a, b) => a.localeCompare(b))).toEqual([
|
|
615
615
|
'https://h1.example/quote',
|
|
616
616
|
'https://h2.example/quote',
|
|
617
617
|
'https://h3.example/quote',
|
|
@@ -649,7 +649,7 @@ describe('StorageUploader — multi-provider behavior', () => {
|
|
|
649
649
|
retentionPeriod: 60
|
|
650
650
|
})
|
|
651
651
|
|
|
652
|
-
expect(quoteCalls.sort()).toEqual([
|
|
652
|
+
expect(quoteCalls.sort((a, b) => a.localeCompare(b))).toEqual([
|
|
653
653
|
'https://h1.example/quote',
|
|
654
654
|
'https://h2.example/quote',
|
|
655
655
|
'https://h3.example/quote',
|
|
@@ -696,7 +696,7 @@ describe('StorageUploader — multi-provider behavior', () => {
|
|
|
696
696
|
|
|
697
697
|
// First batch queried h1-h4 (4 hosts), second batch queried only h5
|
|
698
698
|
// (1 host, the exact remainder). Hosts h6-h8 are never contacted.
|
|
699
|
-
expect(quoteCalls.sort()).toEqual([
|
|
699
|
+
expect(quoteCalls.sort((a, b) => a.localeCompare(b))).toEqual([
|
|
700
700
|
'https://h1.example/quote',
|
|
701
701
|
'https://h2.example/quote',
|
|
702
702
|
'https://h3.example/quote',
|
|
@@ -763,7 +763,7 @@ describe('StorageUploader — multi-host findFile / listUploads / renewFile', ()
|
|
|
763
763
|
|
|
764
764
|
const result = await uploader.findFile('uhrp://x')
|
|
765
765
|
|
|
766
|
-
expect(calls.sort()).toEqual([
|
|
766
|
+
expect(calls.sort((a, b) => a.localeCompare(b))).toEqual([
|
|
767
767
|
'https://a.example/find?uhrpUrl=uhrp%3A%2F%2Fx',
|
|
768
768
|
'https://b.example/find?uhrpUrl=uhrp%3A%2F%2Fx',
|
|
769
769
|
'https://c.example/find?uhrpUrl=uhrp%3A%2F%2Fx'
|
|
@@ -843,7 +843,7 @@ describe('StorageUploader — multi-host findFile / listUploads / renewFile', ()
|
|
|
843
843
|
const listing = await uploader.listUploads()
|
|
844
844
|
const byUrl = Object.fromEntries(listing.map((e: any) => [e.uhrpUrl, e]))
|
|
845
845
|
|
|
846
|
-
expect(Object.keys(byUrl).sort()).toEqual(['uhrp://one', 'uhrp://shared', 'uhrp://two'])
|
|
846
|
+
expect(Object.keys(byUrl).sort((a, b) => a.localeCompare(b))).toEqual(['uhrp://one', 'uhrp://shared', 'uhrp://two'])
|
|
847
847
|
expect(byUrl['uhrp://shared'].expiryTime).toBe(300) // longest wins
|
|
848
848
|
expect(byUrl['uhrp://shared'].hostedBy.sort()).toEqual(['https://a.example', 'https://b.example'])
|
|
849
849
|
expect(byUrl['uhrp://one'].hostedBy).toEqual(['https://a.example'])
|
|
@@ -1026,7 +1026,7 @@ describe('StorageUploader — multi-host findFile / listUploads / renewFile', ()
|
|
|
1026
1026
|
hostedBy: ['https://a.example', 'https://c.example']
|
|
1027
1027
|
})
|
|
1028
1028
|
|
|
1029
|
-
expect(calls.sort()).toEqual([
|
|
1029
|
+
expect(calls.sort((a, b) => a.localeCompare(b))).toEqual([
|
|
1030
1030
|
'https://a.example/renew',
|
|
1031
1031
|
'https://c.example/renew'
|
|
1032
1032
|
])
|
|
@@ -703,7 +703,7 @@ describe('Transaction', () => {
|
|
|
703
703
|
sequence: 0xffffffff
|
|
704
704
|
}
|
|
705
705
|
],
|
|
706
|
-
Array(21)
|
|
706
|
+
new Array(21)
|
|
707
707
|
.fill(null)
|
|
708
708
|
.map(() => ({
|
|
709
709
|
lockingScript: p2pkh.lock(publicKeyHash),
|
|
@@ -1508,7 +1508,7 @@ describe('Transaction', () => {
|
|
|
1508
1508
|
|
|
1509
1509
|
tx.addInput({
|
|
1510
1510
|
sourceTXID: txid,
|
|
1511
|
-
sourceOutputIndex: parseInt(voutStr),
|
|
1511
|
+
sourceOutputIndex: Number.parseInt(voutStr),
|
|
1512
1512
|
unlockingScript
|
|
1513
1513
|
})
|
|
1514
1514
|
}
|
|
@@ -1553,7 +1553,7 @@ describe('Transaction', () => {
|
|
|
1553
1553
|
for (const [index, spend] of Object.entries(args.spends)) {
|
|
1554
1554
|
tx.addInput({
|
|
1555
1555
|
sourceTXID: '00'.repeat(32),
|
|
1556
|
-
sourceOutputIndex: parseInt(index),
|
|
1556
|
+
sourceOutputIndex: Number.parseInt(index),
|
|
1557
1557
|
unlockingScript: Script.fromHex((spend as any).unlockingScript)
|
|
1558
1558
|
})
|
|
1559
1559
|
}
|