@btc-vision/transaction 1.6.18 → 1.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.
Files changed (141) hide show
  1. package/browser/index.js +1 -1
  2. package/browser/index.js.LICENSE.txt +2 -0
  3. package/browser/src/_version.d.ts +1 -0
  4. package/browser/{epoch → src/epoch}/interfaces/IChallengeSolution.d.ts +2 -0
  5. package/browser/{keypair → src/keypair}/Address.d.ts +7 -4
  6. package/browser/{keypair → src/keypair}/AddressVerificator.d.ts +3 -0
  7. package/browser/{keypair → src/keypair}/EcKeyPair.d.ts +3 -2
  8. package/browser/{keypair → src/keypair}/MessageSigner.d.ts +9 -0
  9. package/browser/src/keypair/Wallet.d.ts +47 -0
  10. package/browser/{keypair → src/keypair}/interfaces/IWallet.d.ts +2 -0
  11. package/browser/src/mnemonic/Mnemonic.d.ts +29 -0
  12. package/browser/src/mnemonic/MnemonicStrength.d.ts +7 -0
  13. package/browser/{opnet.d.ts → src/opnet.d.ts} +4 -0
  14. package/browser/src/transaction/browser/types/OPWallet.d.ts +14 -0
  15. package/browser/test/address.test.d.ts +1 -0
  16. package/browser/test/addressverificator-mldsa.test.d.ts +1 -0
  17. package/browser/test/derivePath.test.d.ts +1 -0
  18. package/browser/test/messagesigner-mldsa.test.d.ts +1 -0
  19. package/browser/test/messagesigner-schnorr.test.d.ts +1 -0
  20. package/browser/test/network-awareness.test.d.ts +1 -0
  21. package/build/_version.d.ts +1 -1
  22. package/build/_version.js +1 -1
  23. package/build/crypto/crypto-browser.d.ts +11 -0
  24. package/build/crypto/crypto-browser.js +56 -0
  25. package/build/epoch/ChallengeSolution.js +3 -2
  26. package/build/epoch/interfaces/IChallengeSolution.d.ts +2 -0
  27. package/build/keypair/Address.d.ts +7 -4
  28. package/build/keypair/Address.js +88 -37
  29. package/build/keypair/AddressVerificator.d.ts +3 -0
  30. package/build/keypair/AddressVerificator.js +49 -1
  31. package/build/keypair/EcKeyPair.d.ts +3 -2
  32. package/build/keypair/EcKeyPair.js +17 -3
  33. package/build/keypair/MessageSigner.d.ts +9 -0
  34. package/build/keypair/MessageSigner.js +23 -0
  35. package/build/keypair/Wallet.d.ts +20 -3
  36. package/build/keypair/Wallet.js +108 -9
  37. package/build/keypair/interfaces/IWallet.d.ts +2 -0
  38. package/build/mnemonic/Mnemonic.d.ts +29 -0
  39. package/build/mnemonic/Mnemonic.js +98 -0
  40. package/build/mnemonic/MnemonicStrength.d.ts +7 -0
  41. package/build/mnemonic/MnemonicStrength.js +8 -0
  42. package/build/opnet.d.ts +4 -0
  43. package/build/opnet.js +4 -0
  44. package/build/transaction/browser/types/OPWallet.d.ts +14 -0
  45. package/build/transaction/browser/types/OPWallet.js +6 -0
  46. package/gulpfile.js +2 -2
  47. package/package.json +28 -20
  48. package/src/_version.ts +1 -1
  49. package/src/epoch/ChallengeSolution.ts +3 -2
  50. package/src/epoch/interfaces/IChallengeSolution.ts +2 -0
  51. package/src/keypair/Address.ts +145 -43
  52. package/src/keypair/AddressVerificator.ts +87 -2
  53. package/src/keypair/EcKeyPair.ts +58 -6
  54. package/src/keypair/MessageSigner.ts +58 -0
  55. package/src/keypair/Wallet.ts +339 -57
  56. package/src/keypair/interfaces/IWallet.ts +13 -3
  57. package/src/mnemonic/Mnemonic.ts +340 -0
  58. package/src/mnemonic/MnemonicStrength.ts +12 -0
  59. package/src/network/ChainId.ts +1 -4
  60. package/src/opnet.ts +16 -0
  61. package/src/transaction/browser/types/OPWallet.ts +73 -0
  62. package/test/address.test.ts +1068 -0
  63. package/test/addressverificator-mldsa.test.ts +473 -0
  64. package/test/derivePath.test.ts +234 -0
  65. package/test/messagesigner-mldsa.test.ts +1060 -0
  66. package/test/messagesigner-schnorr.test.ts +1011 -0
  67. package/test/network-awareness.test.ts +163 -0
  68. package/tsconfig.json +1 -1
  69. package/vitest.config.ts +21 -0
  70. package/browser/_version.d.ts +0 -1
  71. package/browser/keypair/Wallet.d.ts +0 -30
  72. /package/browser/{abi → src/abi}/ABICoder.d.ts +0 -0
  73. /package/browser/{buffer → src/buffer}/BinaryReader.d.ts +0 -0
  74. /package/browser/{buffer → src/buffer}/BinaryWriter.d.ts +0 -0
  75. /package/browser/{bytecode → src/bytecode}/Compressor.d.ts +0 -0
  76. /package/browser/{consensus → src/consensus}/Consensus.d.ts +0 -0
  77. /package/browser/{consensus → src/consensus}/ConsensusConfig.d.ts +0 -0
  78. /package/browser/{consensus → src/consensus}/metadata/RoswellConsensus.d.ts +0 -0
  79. /package/browser/{crypto → src/crypto}/crypto-browser.d.ts +0 -0
  80. /package/browser/{crypto → src/crypto}/crypto.d.ts +0 -0
  81. /package/browser/{deterministic → src/deterministic}/AddressMap.d.ts +0 -0
  82. /package/browser/{deterministic → src/deterministic}/AddressSet.d.ts +0 -0
  83. /package/browser/{deterministic → src/deterministic}/DeterministicMap.d.ts +0 -0
  84. /package/browser/{deterministic → src/deterministic}/DeterministicSet.d.ts +0 -0
  85. /package/browser/{deterministic → src/deterministic}/Map.d.ts +0 -0
  86. /package/browser/{epoch → src/epoch}/ChallengeSolution.d.ts +0 -0
  87. /package/browser/{epoch → src/epoch}/validator/EpochValidator.d.ts +0 -0
  88. /package/browser/{event → src/event}/NetEvent.d.ts +0 -0
  89. /package/browser/{generators → src/generators}/AddressGenerator.d.ts +0 -0
  90. /package/browser/{generators → src/generators}/Features.d.ts +0 -0
  91. /package/browser/{generators → src/generators}/Generator.d.ts +0 -0
  92. /package/browser/{generators → src/generators}/builders/CalldataGenerator.d.ts +0 -0
  93. /package/browser/{generators → src/generators}/builders/CustomGenerator.d.ts +0 -0
  94. /package/browser/{generators → src/generators}/builders/DeploymentGenerator.d.ts +0 -0
  95. /package/browser/{generators → src/generators}/builders/LegacyCalldataGenerator.d.ts +0 -0
  96. /package/browser/{generators → src/generators}/builders/MultiSignGenerator.d.ts +0 -0
  97. /package/browser/{generators → src/generators}/builders/P2WDAGenerator.d.ts +0 -0
  98. /package/browser/{index.d.ts → src/index.d.ts} +0 -0
  99. /package/browser/{keypair → src/keypair}/Secp256k1PointDeriver.d.ts +0 -0
  100. /package/browser/{metadata → src/metadata}/ContractBaseMetadata.d.ts +0 -0
  101. /package/browser/{metadata → src/metadata}/tokens.d.ts +0 -0
  102. /package/browser/{network → src/network}/ChainId.d.ts +0 -0
  103. /package/browser/{p2wda → src/p2wda}/P2WDADetector.d.ts +0 -0
  104. /package/browser/{signer → src/signer}/SignerUtils.d.ts +0 -0
  105. /package/browser/{signer → src/signer}/TweakedSigner.d.ts +0 -0
  106. /package/browser/{transaction → src/transaction}/ContractAddress.d.ts +0 -0
  107. /package/browser/{transaction → src/transaction}/TransactionFactory.d.ts +0 -0
  108. /package/browser/{transaction → src/transaction}/browser/BrowserSignerBase.d.ts +0 -0
  109. /package/browser/{transaction → src/transaction}/browser/Web3Provider.d.ts +0 -0
  110. /package/browser/{transaction → src/transaction}/browser/extensions/UnisatSigner.d.ts +0 -0
  111. /package/browser/{transaction → src/transaction}/browser/extensions/XverseSigner.d.ts +0 -0
  112. /package/browser/{transaction → src/transaction}/browser/types/Unisat.d.ts +0 -0
  113. /package/browser/{transaction → src/transaction}/browser/types/Xverse.d.ts +0 -0
  114. /package/browser/{transaction → src/transaction}/builders/CancelTransaction.d.ts +0 -0
  115. /package/browser/{transaction → src/transaction}/builders/ChallengeSolutionTransaction.d.ts +0 -0
  116. /package/browser/{transaction → src/transaction}/builders/CustomScriptTransaction.d.ts +0 -0
  117. /package/browser/{transaction → src/transaction}/builders/DeploymentTransaction.d.ts +0 -0
  118. /package/browser/{transaction → src/transaction}/builders/FundingTransaction.d.ts +0 -0
  119. /package/browser/{transaction → src/transaction}/builders/InteractionTransaction.d.ts +0 -0
  120. /package/browser/{transaction → src/transaction}/builders/InteractionTransactionP2WDA.d.ts +0 -0
  121. /package/browser/{transaction → src/transaction}/builders/MultiSignTransaction.d.ts +0 -0
  122. /package/browser/{transaction → src/transaction}/builders/SharedInteractionTransaction.d.ts +0 -0
  123. /package/browser/{transaction → src/transaction}/builders/TransactionBuilder.d.ts +0 -0
  124. /package/browser/{transaction → src/transaction}/enums/TransactionType.d.ts +0 -0
  125. /package/browser/{transaction → src/transaction}/interfaces/ITransactionParameters.d.ts +0 -0
  126. /package/browser/{transaction → src/transaction}/interfaces/Tap.d.ts +0 -0
  127. /package/browser/{transaction → src/transaction}/mineable/IP2WSHAddress.d.ts +0 -0
  128. /package/browser/{transaction → src/transaction}/mineable/TimelockGenerator.d.ts +0 -0
  129. /package/browser/{transaction → src/transaction}/processor/PsbtTransaction.d.ts +0 -0
  130. /package/browser/{transaction → src/transaction}/psbt/PSBTTypes.d.ts +0 -0
  131. /package/browser/{transaction → src/transaction}/shared/P2TR_MS.d.ts +0 -0
  132. /package/browser/{transaction → src/transaction}/shared/TweakedTransaction.d.ts +0 -0
  133. /package/browser/{utils → src/utils}/BitcoinUtils.d.ts +0 -0
  134. /package/browser/{utils → src/utils}/BufferHelper.d.ts +0 -0
  135. /package/browser/{utils → src/utils}/StringToBuffer.d.ts +0 -0
  136. /package/browser/{utils → src/utils}/lengths.d.ts +0 -0
  137. /package/browser/{utils → src/utils}/types.d.ts +0 -0
  138. /package/browser/{utxo → src/utxo}/OPNetLimitedProvider.d.ts +0 -0
  139. /package/browser/{utxo → src/utxo}/interfaces/BroadcastResponse.d.ts +0 -0
  140. /package/browser/{utxo → src/utxo}/interfaces/IUTXO.d.ts +0 -0
  141. /package/browser/{verification → src/verification}/TapscriptVerificator.d.ts +0 -0
@@ -0,0 +1,1068 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { Address, MLDSASecurityLevel, Mnemonic } from '../build/opnet.js';
3
+ import { networks } from '@btc-vision/bitcoin';
4
+
5
+ describe('Address - Comprehensive Tests', () => {
6
+ const testMnemonic =
7
+ 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
8
+
9
+ // Helper to get a valid address with both keys
10
+ const getValidAddress = (securityLevel = MLDSASecurityLevel.LEVEL2) => {
11
+ const mnemonic = new Mnemonic(testMnemonic, '', networks.bitcoin, securityLevel);
12
+ const wallet = mnemonic.derive(0);
13
+ return wallet.address;
14
+ };
15
+
16
+ describe('Constructor', () => {
17
+ it('should create an empty address with no parameters', () => {
18
+ const address = new Address();
19
+ expect(address.length).toBe(32); // ADDRESS_BYTE_LENGTH
20
+ });
21
+
22
+ it('should create an address with ML-DSA public key only (32 bytes)', () => {
23
+ const mldsaHash = Buffer.alloc(32);
24
+ mldsaHash.fill(0x01);
25
+ const address = new Address(mldsaHash);
26
+
27
+ expect(address.length).toBe(32);
28
+ expect(address.toHex()).toBe('0x' + mldsaHash.toString('hex'));
29
+ });
30
+
31
+ it('should create an address with ML-DSA public key (1312 bytes - LEVEL2)', () => {
32
+ const mldsaPubKey = Buffer.alloc(1312);
33
+ mldsaPubKey.fill(0x02);
34
+ const address = new Address(mldsaPubKey);
35
+
36
+ expect(address.length).toBe(32);
37
+ expect(address.mldsaPublicKey).toBeDefined();
38
+ expect(address.mldsaPublicKey?.length).toBe(1312);
39
+ });
40
+
41
+ it('should create an address with ML-DSA public key (1952 bytes - LEVEL3)', () => {
42
+ const mldsaPubKey = Buffer.alloc(1952);
43
+ mldsaPubKey.fill(0x03);
44
+ const address = new Address(mldsaPubKey);
45
+
46
+ expect(address.mldsaPublicKey?.length).toBe(1952);
47
+ });
48
+
49
+ it('should create an address with ML-DSA public key (2592 bytes - LEVEL5)', () => {
50
+ const mldsaPubKey = Buffer.alloc(2592);
51
+ mldsaPubKey.fill(0x04);
52
+ const address = new Address(mldsaPubKey);
53
+
54
+ expect(address.mldsaPublicKey?.length).toBe(2592);
55
+ });
56
+
57
+ it('should create an address with both ML-DSA and classical public key (compressed)', () => {
58
+ const mnemonic = new Mnemonic(
59
+ testMnemonic,
60
+ '',
61
+ networks.bitcoin,
62
+ MLDSASecurityLevel.LEVEL2,
63
+ );
64
+ const wallet = mnemonic.derive(0);
65
+
66
+ expect(wallet.address.mldsaPublicKey).toBeDefined();
67
+ expect(wallet.address.originalPublicKey).toBeDefined();
68
+ });
69
+
70
+ it('should create an address with ML-DSA hash and 32-byte classical key hash', () => {
71
+ const mldsaHash = Buffer.alloc(32, 0x01);
72
+ const classicHash = Buffer.alloc(32, 0x02);
73
+ const address = new Address(mldsaHash, classicHash);
74
+
75
+ expect(address.length).toBe(32);
76
+ });
77
+
78
+ it('should create an address with Uint8Array inputs', () => {
79
+ const mldsaHash = new Uint8Array(32);
80
+ mldsaHash.fill(0x05);
81
+ const address = new Address(mldsaHash);
82
+
83
+ expect(address.toHex()).toContain('05050505');
84
+ });
85
+ });
86
+
87
+ describe('Static Methods - dead()', () => {
88
+ it('should return a dead address', () => {
89
+ const deadAddr = Address.dead();
90
+
91
+ expect(deadAddr).toBeInstanceOf(Address);
92
+ expect(deadAddr.toHex()).toBe(
93
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
94
+ );
95
+ });
96
+
97
+ it('should return same dead address instance properties', () => {
98
+ const dead1 = Address.dead();
99
+ const dead2 = Address.dead();
100
+
101
+ expect(dead1.toHex()).toBe(dead2.toHex());
102
+ });
103
+ });
104
+
105
+ describe('Static Methods - fromString()', () => {
106
+ it('should create address from 32-byte hex string', () => {
107
+ const hex = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
108
+ const address = Address.fromString(hex);
109
+
110
+ expect(address.toHex()).toBe('0x' + hex);
111
+ });
112
+
113
+ it('should create address from hex string with 0x prefix', () => {
114
+ const hex = '0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
115
+ const address = Address.fromString(hex);
116
+
117
+ expect(address.toHex()).toBe(hex);
118
+ });
119
+
120
+ it('should create address from hex string without 0x prefix', () => {
121
+ const hex = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
122
+ const address = Address.fromString(hex);
123
+
124
+ expect(address.toHex()).toBe('0x' + hex);
125
+ });
126
+
127
+ it('should create address with classical public key', () => {
128
+ const mnemonic = new Mnemonic(
129
+ testMnemonic,
130
+ '',
131
+ networks.bitcoin,
132
+ MLDSASecurityLevel.LEVEL2,
133
+ );
134
+ const wallet = mnemonic.derive(0);
135
+
136
+ const mldsaHex = wallet.quantumPublicKeyHex;
137
+ const classicHex = wallet.toPublicKeyHex();
138
+ const address = Address.fromString(mldsaHex, classicHex);
139
+
140
+ expect(address).toBeInstanceOf(Address);
141
+ expect(address.originalPublicKey).toBeDefined();
142
+ });
143
+
144
+ it('should create address with classical public key with 0x prefix', () => {
145
+ const mnemonic = new Mnemonic(
146
+ testMnemonic,
147
+ '',
148
+ networks.bitcoin,
149
+ MLDSASecurityLevel.LEVEL2,
150
+ );
151
+ const wallet = mnemonic.derive(0);
152
+
153
+ const mldsaHex = '0x' + wallet.quantumPublicKeyHex;
154
+ const classicHex = '0x' + wallet.toPublicKeyHex();
155
+ const address = Address.fromString(mldsaHex, classicHex);
156
+
157
+ expect(address).toBeInstanceOf(Address);
158
+ });
159
+
160
+ it('should throw error for empty string', () => {
161
+ expect(() => Address.fromString('')).toThrow('Invalid public key');
162
+ });
163
+
164
+ it('should throw error for invalid hex', () => {
165
+ expect(() => Address.fromString('not_hex')).toThrow('hexadecimal format');
166
+ });
167
+
168
+ it('should throw error for invalid classical public key hex', () => {
169
+ const mldsaHex = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
170
+ expect(() => Address.fromString(mldsaHex, 'not_hex')).toThrow('hexadecimal format');
171
+ });
172
+ });
173
+
174
+ describe('Static Methods - wrap()', () => {
175
+ it('should wrap bytes into an Address', () => {
176
+ const bytes = Buffer.alloc(32, 0x42);
177
+ const address = Address.wrap(bytes);
178
+
179
+ expect(address).toBeInstanceOf(Address);
180
+ expect(address.toHex()).toContain('42424242');
181
+ });
182
+
183
+ it('should wrap Uint8Array into an Address', () => {
184
+ const bytes = new Uint8Array(32);
185
+ bytes.fill(0x77);
186
+ const address = Address.wrap(bytes);
187
+
188
+ expect(address.toHex()).toContain('77777777');
189
+ });
190
+ });
191
+
192
+ describe('Static Methods - uncompressedToCompressed()', () => {
193
+ it('should compress an uncompressed public key (even y-coordinate)', () => {
194
+ const uncompressed = Buffer.alloc(65);
195
+ uncompressed[0] = 0x04;
196
+ // Fill x-coordinate
197
+ for (let i = 1; i <= 32; i++) uncompressed[i] = 0x01;
198
+ // Fill y-coordinate with even last byte
199
+ for (let i = 33; i < 65; i++) uncompressed[i] = 0x02;
200
+ uncompressed[64] = 0x00; // Even
201
+
202
+ const compressed = Address.uncompressedToCompressed(uncompressed);
203
+
204
+ expect(compressed.length).toBe(33);
205
+ expect(compressed[0]).toBe(0x02); // Even y-coordinate
206
+ });
207
+
208
+ it('should compress an uncompressed public key (odd y-coordinate)', () => {
209
+ const uncompressed = Buffer.alloc(65);
210
+ uncompressed[0] = 0x04;
211
+ // Fill x-coordinate
212
+ for (let i = 1; i <= 32; i++) uncompressed[i] = 0x01;
213
+ // Fill y-coordinate with odd last byte
214
+ for (let i = 33; i < 65; i++) uncompressed[i] = 0x02;
215
+ uncompressed[64] = 0x01; // Odd
216
+
217
+ const compressed = Address.uncompressedToCompressed(uncompressed);
218
+
219
+ expect(compressed.length).toBe(33);
220
+ expect(compressed[0]).toBe(0x03); // Odd y-coordinate
221
+ });
222
+
223
+ it('should compress from Uint8Array', () => {
224
+ const uncompressed = new Uint8Array(65);
225
+ uncompressed[0] = 0x04;
226
+ for (let i = 1; i < 65; i++) uncompressed[i] = i % 256;
227
+
228
+ const compressed = Address.uncompressedToCompressed(uncompressed);
229
+
230
+ expect(compressed.length).toBe(33);
231
+ expect(compressed[0] === 0x02 || compressed[0] === 0x03).toBe(true);
232
+ });
233
+ });
234
+
235
+ describe('Getters', () => {
236
+ it('should return undefined originalPublicKey for address without classical key', () => {
237
+ const mldsaHash = Buffer.alloc(32, 0x01);
238
+ const address = new Address(mldsaHash);
239
+
240
+ expect(address.originalPublicKey).toBeUndefined();
241
+ });
242
+
243
+ it('should return originalPublicKey when set', () => {
244
+ const addr = getValidAddress();
245
+ expect(addr.originalPublicKey).toBeDefined();
246
+ expect(addr.originalPublicKey?.length).toBe(33);
247
+ });
248
+
249
+ it('should return mldsaPublicKey when full key is provided', () => {
250
+ const mldsaPubKey = Buffer.alloc(1312, 0xab);
251
+ const address = new Address(mldsaPubKey);
252
+
253
+ expect(address.mldsaPublicKey).toBeDefined();
254
+ expect(address.mldsaPublicKey?.length).toBe(1312);
255
+
256
+ if (!address.mldsaPublicKey) {
257
+ throw new Error('mldsaPublicKey is undefined');
258
+ }
259
+
260
+ expect(Buffer.from(address.mldsaPublicKey).toString('hex')).toContain('abab');
261
+ });
262
+
263
+ it('should return undefined mldsaPublicKey when only hash is provided', () => {
264
+ const mldsaHash = Buffer.alloc(32, 0x01);
265
+ const address = new Address(mldsaHash);
266
+
267
+ expect(address.mldsaPublicKey).toBeUndefined();
268
+ });
269
+ });
270
+
271
+ describe('Conversion Methods - toHex/toBuffer', () => {
272
+ it('should convert to hex with 0x prefix', () => {
273
+ const bytes = Buffer.alloc(32, 0xff);
274
+ const address = new Address(bytes);
275
+
276
+ const hex = address.toHex();
277
+ expect(hex).toMatch(/^0x[0-9a-f]{64}$/);
278
+ expect(hex).toContain('ffffff');
279
+ });
280
+
281
+ it('should convert to buffer', () => {
282
+ const bytes = Buffer.alloc(32, 0xaa);
283
+ const address = new Address(bytes);
284
+
285
+ const buffer = address.toBuffer();
286
+ expect(buffer).toBeInstanceOf(Buffer);
287
+ expect(buffer.length).toBe(32);
288
+ expect(buffer.toString('hex')).toContain('aaaa');
289
+ });
290
+
291
+ it('should toString return same as toHex', () => {
292
+ const addr = getValidAddress();
293
+ expect(addr.toString()).toBe(addr.toHex());
294
+ });
295
+
296
+ it('should toJSON return same as toHex', () => {
297
+ const addr = getValidAddress();
298
+ expect(addr.toJSON()).toBe(addr.toHex());
299
+ });
300
+ });
301
+
302
+ describe('Conversion Methods - tweaked', () => {
303
+ it('should convert tweaked to hex', () => {
304
+ const addr = getValidAddress();
305
+ const tweakedHex = addr.tweakedToHex();
306
+
307
+ expect(tweakedHex).toMatch(/^0x[0-9a-f]{64}$/);
308
+ });
309
+
310
+ it('should throw error for tweakedToHex without classical key', () => {
311
+ const mldsaHash = Buffer.alloc(32, 0x01);
312
+ const address = new Address(mldsaHash);
313
+
314
+ expect(() => address.tweakedToHex()).toThrow('Classical public key not set');
315
+ });
316
+
317
+ it('should convert tweaked public key to buffer', () => {
318
+ const addr = getValidAddress();
319
+ const buffer = addr.tweakedPublicKeyToBuffer();
320
+
321
+ expect(buffer).toBeInstanceOf(Buffer);
322
+ expect(buffer.length).toBe(32);
323
+ });
324
+
325
+ it('should throw error for tweakedPublicKeyToBuffer without classical key', () => {
326
+ const mldsaHash = Buffer.alloc(32, 0x01);
327
+ const address = new Address(mldsaHash);
328
+
329
+ expect(() => address.tweakedPublicKeyToBuffer()).toThrow(
330
+ 'Classical public key not set',
331
+ );
332
+ });
333
+
334
+ it('should get toTweakedHybridPublicKeyHex', () => {
335
+ const addr = getValidAddress();
336
+ const hybridHex = addr.toTweakedHybridPublicKeyHex();
337
+
338
+ expect(hybridHex).toMatch(/^0x[0-9a-f]+$/);
339
+ });
340
+
341
+ it('should throw error for toTweakedHybridPublicKeyHex without key', () => {
342
+ const mldsaHash = Buffer.alloc(32, 0x01);
343
+ const address = new Address(mldsaHash);
344
+
345
+ expect(() => address.toTweakedHybridPublicKeyHex()).toThrow(
346
+ 'Classical public key not set',
347
+ );
348
+ });
349
+
350
+ it('should get toTweakedHybridPublicKeyBuffer', () => {
351
+ const addr = getValidAddress();
352
+ const buffer = addr.toTweakedHybridPublicKeyBuffer();
353
+
354
+ expect(buffer).toBeInstanceOf(Buffer);
355
+ });
356
+
357
+ it('should throw error for toTweakedHybridPublicKeyBuffer without key', () => {
358
+ const mldsaHash = Buffer.alloc(32, 0x01);
359
+ const address = new Address(mldsaHash);
360
+
361
+ expect(() => address.toTweakedHybridPublicKeyBuffer()).toThrow(
362
+ 'Classical public key not set',
363
+ );
364
+ });
365
+ });
366
+
367
+ describe('Conversion Methods - uncompressed and hybrid', () => {
368
+ it('should get uncompressed hex', () => {
369
+ const addr = getValidAddress();
370
+ const uncompressedHex = addr.toUncompressedHex();
371
+
372
+ expect(uncompressedHex).toMatch(/^0x[0-9a-f]{130}$/); // 65 bytes = 130 hex chars
373
+ });
374
+
375
+ it('should throw error for toUncompressedHex without key', () => {
376
+ const mldsaHash = Buffer.alloc(32, 0x01);
377
+ const address = new Address(mldsaHash);
378
+
379
+ expect(() => address.toUncompressedHex()).toThrow('Classical public key not set');
380
+ });
381
+
382
+ it('should get uncompressed buffer', () => {
383
+ const addr = getValidAddress();
384
+ const buffer = addr.toUncompressedBuffer();
385
+
386
+ expect(buffer).toBeInstanceOf(Buffer);
387
+ expect(buffer.length).toBe(65);
388
+ });
389
+
390
+ it('should throw error for toUncompressedBuffer without key', () => {
391
+ const mldsaHash = Buffer.alloc(32, 0x01);
392
+ const address = new Address(mldsaHash);
393
+
394
+ expect(() => address.toUncompressedBuffer()).toThrow('Classical public key not set');
395
+ });
396
+
397
+ it('should get hybrid public key hex', () => {
398
+ const addr = getValidAddress();
399
+ const hybridHex = addr.toHybridPublicKeyHex();
400
+
401
+ expect(hybridHex).toMatch(/^0x[0-9a-f]+$/);
402
+ });
403
+
404
+ it('should throw error for toHybridPublicKeyHex without key', () => {
405
+ const mldsaHash = Buffer.alloc(32, 0x01);
406
+ const address = new Address(mldsaHash);
407
+
408
+ expect(() => address.toHybridPublicKeyHex()).toThrow('Classical public key not set');
409
+ });
410
+
411
+ it('should get hybrid public key buffer', () => {
412
+ const addr = getValidAddress();
413
+ const buffer = addr.toHybridPublicKeyBuffer();
414
+
415
+ expect(buffer).toBeInstanceOf(Buffer);
416
+ });
417
+
418
+ it('should throw error for toHybridPublicKeyBuffer without key', () => {
419
+ const mldsaHash = Buffer.alloc(32, 0x01);
420
+ const address = new Address(mldsaHash);
421
+
422
+ expect(() => address.toHybridPublicKeyBuffer()).toThrow('Classical public key not set');
423
+ });
424
+
425
+ it('should get original public key buffer', () => {
426
+ const addr = getValidAddress();
427
+ const buffer = addr.originalPublicKeyBuffer();
428
+
429
+ expect(buffer).toBeInstanceOf(Buffer);
430
+ expect(buffer.length).toBe(33);
431
+ });
432
+
433
+ it('should throw error for originalPublicKeyBuffer without key', () => {
434
+ const mldsaHash = Buffer.alloc(32, 0x01);
435
+ const address = new Address(mldsaHash);
436
+
437
+ expect(() => address.originalPublicKeyBuffer()).toThrow('Classical public key not set');
438
+ });
439
+ });
440
+
441
+ describe('Comparison Methods - equals', () => {
442
+ it('should return true for equal addresses', () => {
443
+ const bytes = Buffer.alloc(32, 0x42);
444
+ const addr1 = new Address(bytes);
445
+ const addr2 = new Address(bytes);
446
+
447
+ expect(addr1.equals(addr2)).toBe(true);
448
+ });
449
+
450
+ it('should return false for different addresses', () => {
451
+ const bytes1 = Buffer.alloc(32, 0x01);
452
+ const bytes2 = Buffer.alloc(32, 0x02);
453
+ const addr1 = new Address(bytes1);
454
+ const addr2 = new Address(bytes2);
455
+
456
+ expect(addr1.equals(addr2)).toBe(false);
457
+ });
458
+
459
+ it('should return false for addresses with different content', () => {
460
+ const bytes1 = Buffer.alloc(32, 0x11);
461
+ const bytes2 = Buffer.alloc(32, 0x22);
462
+ const addr1 = new Address(bytes1);
463
+ const addr2 = new Address(bytes2);
464
+
465
+ expect(addr1.equals(addr2)).toBe(false);
466
+ });
467
+
468
+ it('should return true when comparing same instance', () => {
469
+ const addr = getValidAddress();
470
+ expect(addr.equals(addr)).toBe(true);
471
+ });
472
+ });
473
+
474
+ describe('Comparison Methods - lessThan', () => {
475
+ it('should return true when address is less than another', () => {
476
+ const bytes1 = Buffer.alloc(32, 0x01);
477
+ const bytes2 = Buffer.alloc(32, 0x02);
478
+ const addr1 = new Address(bytes1);
479
+ const addr2 = new Address(bytes2);
480
+
481
+ expect(addr1.lessThan(addr2)).toBe(true);
482
+ });
483
+
484
+ it('should return false when address is greater than another', () => {
485
+ const bytes1 = Buffer.alloc(32, 0x02);
486
+ const bytes2 = Buffer.alloc(32, 0x01);
487
+ const addr1 = new Address(bytes1);
488
+ const addr2 = new Address(bytes2);
489
+
490
+ expect(addr1.lessThan(addr2)).toBe(false);
491
+ });
492
+
493
+ it('should return false when addresses are equal', () => {
494
+ const bytes = Buffer.alloc(32, 0x42);
495
+ const addr1 = new Address(bytes);
496
+ const addr2 = new Address(bytes);
497
+
498
+ expect(addr1.lessThan(addr2)).toBe(false);
499
+ });
500
+
501
+ it('should compare byte by byte correctly', () => {
502
+ const bytes1 = Buffer.alloc(32, 0x01);
503
+ const bytes2 = Buffer.alloc(32, 0x01);
504
+ bytes1[31] = 0x01; // Last byte smaller
505
+ bytes2[31] = 0x02;
506
+ const addr1 = new Address(bytes1);
507
+ const addr2 = new Address(bytes2);
508
+
509
+ expect(addr1.lessThan(addr2)).toBe(true);
510
+ });
511
+ });
512
+
513
+ describe('Comparison Methods - greaterThan', () => {
514
+ it('should return true when address is greater than another', () => {
515
+ const bytes1 = Buffer.alloc(32, 0x02);
516
+ const bytes2 = Buffer.alloc(32, 0x01);
517
+ const addr1 = new Address(bytes1);
518
+ const addr2 = new Address(bytes2);
519
+
520
+ expect(addr1.greaterThan(addr2)).toBe(true);
521
+ });
522
+
523
+ it('should return false when address is less than another', () => {
524
+ const bytes1 = Buffer.alloc(32, 0x01);
525
+ const bytes2 = Buffer.alloc(32, 0x02);
526
+ const addr1 = new Address(bytes1);
527
+ const addr2 = new Address(bytes2);
528
+
529
+ expect(addr1.greaterThan(addr2)).toBe(false);
530
+ });
531
+
532
+ it('should return false when addresses are equal', () => {
533
+ const bytes = Buffer.alloc(32, 0x42);
534
+ const addr1 = new Address(bytes);
535
+ const addr2 = new Address(bytes);
536
+
537
+ expect(addr1.greaterThan(addr2)).toBe(false);
538
+ });
539
+
540
+ it('should compare byte by byte correctly', () => {
541
+ const bytes1 = Buffer.alloc(32, 0x01);
542
+ const bytes2 = Buffer.alloc(32, 0x01);
543
+ bytes1[0] = 0x02; // First byte greater
544
+ bytes2[0] = 0x01;
545
+ const addr1 = new Address(bytes1);
546
+ const addr2 = new Address(bytes2);
547
+
548
+ expect(addr1.greaterThan(addr2)).toBe(true);
549
+ });
550
+ });
551
+
552
+ describe('Set Method - ML-DSA validation', () => {
553
+ it('should set 32-byte ML-DSA hash', () => {
554
+ const address = new Address();
555
+ const hash = Buffer.alloc(32, 0x77);
556
+ address.set(hash);
557
+
558
+ expect(address.toHex()).toContain('77777777');
559
+ });
560
+
561
+ it('should set 1312-byte ML-DSA public key (LEVEL2)', () => {
562
+ const address = new Address();
563
+ const mldsaPubKey = Buffer.alloc(1312, 0xaa);
564
+ address.set(mldsaPubKey);
565
+
566
+ expect(address.mldsaPublicKey?.length).toBe(1312);
567
+ });
568
+
569
+ it('should set 1952-byte ML-DSA public key (LEVEL3)', () => {
570
+ const address = new Address();
571
+ const mldsaPubKey = Buffer.alloc(1952, 0xbb);
572
+ address.set(mldsaPubKey);
573
+
574
+ expect(address.mldsaPublicKey?.length).toBe(1952);
575
+ });
576
+
577
+ it('should set 2592-byte ML-DSA public key (LEVEL5)', () => {
578
+ const address = new Address();
579
+ const mldsaPubKey = Buffer.alloc(2592, 0xcc);
580
+ address.set(mldsaPubKey);
581
+
582
+ expect(address.mldsaPublicKey?.length).toBe(2592);
583
+ });
584
+
585
+ it('should throw error for invalid ML-DSA public key length', () => {
586
+ const address = new Address();
587
+ const invalidPubKey = Buffer.alloc(1000);
588
+
589
+ expect(() => address.set(invalidPubKey)).toThrow('Invalid ML-DSA public key length');
590
+ });
591
+
592
+ it('should throw error for invalid classical public key length', () => {
593
+ const mldsaHash = Buffer.alloc(32, 0x01);
594
+ const invalidClassicKey = Buffer.alloc(20); // Invalid length
595
+
596
+ expect(() => new Address(mldsaHash, invalidClassicKey)).toThrow(
597
+ 'Invalid public key length',
598
+ );
599
+ });
600
+ });
601
+
602
+ describe('Address Generation - p2pk', () => {
603
+ it('should return p2pk address (hex)', () => {
604
+ const addr = getValidAddress();
605
+ const p2pk = addr.p2pk();
606
+
607
+ expect(p2pk).toBe(addr.toHex());
608
+ });
609
+ });
610
+
611
+ describe('Address Generation - p2wpkh', () => {
612
+ it('should generate p2wpkh address for mainnet', () => {
613
+ const addr = getValidAddress();
614
+ const p2wpkh = addr.p2wpkh(networks.bitcoin);
615
+
616
+ expect(p2wpkh).toMatch(/^bc1q/);
617
+ });
618
+
619
+ it('should generate p2wpkh address for testnet', () => {
620
+ const mnemonic = new Mnemonic(
621
+ testMnemonic,
622
+ '',
623
+ networks.testnet,
624
+ MLDSASecurityLevel.LEVEL2,
625
+ );
626
+ const wallet = mnemonic.derive(0);
627
+ const p2wpkh = wallet.address.p2wpkh(networks.testnet);
628
+
629
+ expect(p2wpkh).toMatch(/^tb1q/);
630
+ });
631
+
632
+ it('should generate p2wpkh address for regtest', () => {
633
+ const mnemonic = new Mnemonic(
634
+ testMnemonic,
635
+ '',
636
+ networks.regtest,
637
+ MLDSASecurityLevel.LEVEL2,
638
+ );
639
+ const wallet = mnemonic.derive(0);
640
+ const p2wpkh = wallet.address.p2wpkh(networks.regtest);
641
+
642
+ expect(p2wpkh).toMatch(/^bcrt1q/);
643
+ });
644
+
645
+ it('should throw error for p2wpkh without key', () => {
646
+ const mldsaHash = Buffer.alloc(32, 0x01);
647
+ const address = new Address(mldsaHash);
648
+
649
+ expect(() => address.p2wpkh(networks.bitcoin)).toThrow('Classical public key not set');
650
+ });
651
+ });
652
+
653
+ describe('Address Generation - p2pkh', () => {
654
+ it('should generate p2pkh address for mainnet', () => {
655
+ const addr = getValidAddress();
656
+ const p2pkh = addr.p2pkh(networks.bitcoin);
657
+
658
+ expect(p2pkh).toMatch(/^1/);
659
+ });
660
+
661
+ it('should generate p2pkh address for testnet', () => {
662
+ const mnemonic = new Mnemonic(
663
+ testMnemonic,
664
+ '',
665
+ networks.testnet,
666
+ MLDSASecurityLevel.LEVEL2,
667
+ );
668
+ const wallet = mnemonic.derive(0);
669
+ const p2pkh = wallet.address.p2pkh(networks.testnet);
670
+
671
+ expect(p2pkh).toMatch(/^[mn]/);
672
+ });
673
+
674
+ it('should throw error for p2pkh without key', () => {
675
+ const mldsaHash = Buffer.alloc(32, 0x01);
676
+ const address = new Address(mldsaHash);
677
+
678
+ expect(() => address.p2pkh(networks.bitcoin)).toThrow(
679
+ 'Classical public key not set for address',
680
+ );
681
+ });
682
+ });
683
+
684
+ describe('Address Generation - p2shp2wpkh', () => {
685
+ it('should generate p2shp2wpkh address for mainnet', () => {
686
+ const addr = getValidAddress();
687
+ const p2sh = addr.p2shp2wpkh(networks.bitcoin);
688
+
689
+ expect(p2sh).toMatch(/^3/);
690
+ });
691
+
692
+ it('should generate p2shp2wpkh address for testnet', () => {
693
+ const mnemonic = new Mnemonic(
694
+ testMnemonic,
695
+ '',
696
+ networks.testnet,
697
+ MLDSASecurityLevel.LEVEL2,
698
+ );
699
+ const wallet = mnemonic.derive(0);
700
+ const p2sh = wallet.address.p2shp2wpkh(networks.testnet);
701
+
702
+ expect(p2sh).toMatch(/^2/);
703
+ });
704
+
705
+ it('should throw error for p2shp2wpkh without key', () => {
706
+ const mldsaHash = Buffer.alloc(32, 0x01);
707
+ const address = new Address(mldsaHash);
708
+
709
+ expect(() => address.p2shp2wpkh(networks.bitcoin)).toThrow(
710
+ 'Classical public key not set for address',
711
+ );
712
+ });
713
+ });
714
+
715
+ describe('Address Generation - p2tr', () => {
716
+ it('should generate p2tr address for mainnet', () => {
717
+ const addr = getValidAddress();
718
+ const p2tr = addr.p2tr(networks.bitcoin);
719
+
720
+ expect(p2tr).toMatch(/^bc1p/);
721
+ });
722
+
723
+ it('should generate p2tr address for testnet', () => {
724
+ const mnemonic = new Mnemonic(
725
+ testMnemonic,
726
+ '',
727
+ networks.testnet,
728
+ MLDSASecurityLevel.LEVEL2,
729
+ );
730
+ const wallet = mnemonic.derive(0);
731
+ const p2tr = wallet.address.p2tr(networks.testnet);
732
+
733
+ expect(p2tr).toMatch(/^tb1p/);
734
+ });
735
+
736
+ it('should cache p2tr address for same network', () => {
737
+ const addr = getValidAddress();
738
+ const p2tr1 = addr.p2tr(networks.bitcoin);
739
+ const p2tr2 = addr.p2tr(networks.bitcoin);
740
+
741
+ expect(p2tr1).toBe(p2tr2);
742
+ });
743
+
744
+ it('should generate different p2tr for different networks', () => {
745
+ const mnemonic = new Mnemonic(
746
+ testMnemonic,
747
+ '',
748
+ networks.bitcoin,
749
+ MLDSASecurityLevel.LEVEL2,
750
+ );
751
+ const wallet = mnemonic.derive(0);
752
+
753
+ // Can't easily test cross-network without recreating, but we can verify it works
754
+ const p2trMain = wallet.address.p2tr(networks.bitcoin);
755
+ expect(p2trMain).toMatch(/^bc1p/);
756
+ });
757
+
758
+ it('should throw error for p2tr without classical key', () => {
759
+ const mldsaHash = Buffer.alloc(32, 0x01);
760
+ const address = new Address(mldsaHash);
761
+
762
+ expect(() => address.p2tr(networks.bitcoin)).toThrow('Classical public key not set');
763
+ });
764
+ });
765
+
766
+ describe('Address Generation - p2op', () => {
767
+ it('should generate p2op address for mainnet', () => {
768
+ const addr = getValidAddress();
769
+ const p2op = addr.p2op(networks.bitcoin);
770
+
771
+ expect(p2op).toBeDefined();
772
+ expect(typeof p2op).toBe('string');
773
+ });
774
+
775
+ it('should generate p2op address for testnet', () => {
776
+ const mnemonic = new Mnemonic(
777
+ testMnemonic,
778
+ '',
779
+ networks.testnet,
780
+ MLDSASecurityLevel.LEVEL2,
781
+ );
782
+ const wallet = mnemonic.derive(0);
783
+ const p2op = wallet.address.p2op(networks.testnet);
784
+
785
+ expect(p2op).toBeDefined();
786
+ expect(typeof p2op).toBe('string');
787
+ });
788
+
789
+ it('should cache p2op address for same network', () => {
790
+ const addr = getValidAddress();
791
+ const p2op1 = addr.p2op(networks.bitcoin);
792
+ const p2op2 = addr.p2op(networks.bitcoin);
793
+
794
+ expect(p2op1).toBe(p2op2);
795
+ });
796
+
797
+ it('should generate p2op for different security levels', () => {
798
+ const addr2 = getValidAddress(MLDSASecurityLevel.LEVEL2);
799
+ const addr3 = getValidAddress(MLDSASecurityLevel.LEVEL3);
800
+ const addr5 = getValidAddress(MLDSASecurityLevel.LEVEL5);
801
+
802
+ const p2op2 = addr2.p2op(networks.bitcoin);
803
+ const p2op3 = addr3.p2op(networks.bitcoin);
804
+ const p2op5 = addr5.p2op(networks.bitcoin);
805
+
806
+ expect(p2op2).toBeDefined();
807
+ expect(p2op3).toBeDefined();
808
+ expect(p2op5).toBeDefined();
809
+ });
810
+ });
811
+
812
+ describe('Address Generation - p2wda', () => {
813
+ it('should generate p2wda address', () => {
814
+ const addr = getValidAddress();
815
+ const p2wda = addr.p2wda(networks.bitcoin);
816
+
817
+ expect(p2wda.address).toMatch(/^bc1q/);
818
+ expect(p2wda.witnessScript).toBeInstanceOf(Buffer);
819
+ });
820
+
821
+ it('should cache p2wda for same network', () => {
822
+ const addr = getValidAddress();
823
+ const p2wda1 = addr.p2wda(networks.bitcoin);
824
+ const p2wda2 = addr.p2wda(networks.bitcoin);
825
+
826
+ expect(p2wda1.address).toBe(p2wda2.address);
827
+ });
828
+
829
+ it('should generate p2wda for testnet', () => {
830
+ const mnemonic = new Mnemonic(
831
+ testMnemonic,
832
+ '',
833
+ networks.testnet,
834
+ MLDSASecurityLevel.LEVEL2,
835
+ );
836
+ const wallet = mnemonic.derive(0);
837
+ const p2wda = wallet.address.p2wda(networks.testnet);
838
+
839
+ expect(p2wda.address).toMatch(/^tb1q/);
840
+ });
841
+
842
+ it('should throw error for p2wda without original public key', () => {
843
+ const mldsaHash = Buffer.alloc(32, 0x01);
844
+ const address = new Address(mldsaHash);
845
+
846
+ expect(() => address.p2wda(networks.bitcoin)).toThrow('Cannot create P2WDA address');
847
+ });
848
+ });
849
+
850
+ describe('Address Generation - toCSV (timelocked)', () => {
851
+ it('should generate CSV address with valid duration (number)', () => {
852
+ const addr = getValidAddress();
853
+ const csv = addr.toCSV(100, networks.bitcoin);
854
+
855
+ expect(csv.address).toMatch(/^bc1q/);
856
+ expect(csv.witnessScript).toBeInstanceOf(Buffer);
857
+ });
858
+
859
+ it('should generate CSV address with valid duration (bigint)', () => {
860
+ const addr = getValidAddress();
861
+ const csv = addr.toCSV(BigInt(1000), networks.bitcoin);
862
+
863
+ expect(csv.address).toMatch(/^bc1q/);
864
+ });
865
+
866
+ it('should generate CSV address with valid duration (string)', () => {
867
+ const addr = getValidAddress();
868
+ const csv = addr.toCSV('500', networks.bitcoin);
869
+
870
+ expect(csv.address).toMatch(/^bc1q/);
871
+ });
872
+
873
+ it('should generate CSV address with minimum duration (1)', () => {
874
+ const addr = getValidAddress();
875
+ const csv = addr.toCSV(1, networks.bitcoin);
876
+
877
+ expect(csv.address).toMatch(/^bc1q/);
878
+ });
879
+
880
+ it('should generate CSV address with maximum duration (65535)', () => {
881
+ const addr = getValidAddress();
882
+ const csv = addr.toCSV(65535, networks.bitcoin);
883
+
884
+ expect(csv.address).toMatch(/^bc1q/);
885
+ });
886
+
887
+ it('should throw error for CSV duration less than 1', () => {
888
+ const addr = getValidAddress();
889
+ expect(() => addr.toCSV(0, networks.bitcoin)).toThrow(
890
+ 'CSV block number must be between 1 and 65535',
891
+ );
892
+ });
893
+
894
+ it('should throw error for CSV duration greater than 65535', () => {
895
+ const addr = getValidAddress();
896
+ expect(() => addr.toCSV(65536, networks.bitcoin)).toThrow(
897
+ 'CSV block number must be between 1 and 65535',
898
+ );
899
+ });
900
+
901
+ it('should throw error for negative CSV duration', () => {
902
+ const addr = getValidAddress();
903
+ expect(() => addr.toCSV(-1, networks.bitcoin)).toThrow(
904
+ 'CSV block number must be between 1 and 65535',
905
+ );
906
+ });
907
+
908
+ it('should throw error for CSV without original public key', () => {
909
+ const mldsaHash = Buffer.alloc(32, 0x01);
910
+ const address = new Address(mldsaHash);
911
+
912
+ expect(() => address.toCSV(100, networks.bitcoin)).toThrow('Cannot create CSV address');
913
+ });
914
+
915
+ it('should generate different CSV addresses for different durations', () => {
916
+ const addr = getValidAddress();
917
+ const csv1 = addr.toCSV(100, networks.bitcoin);
918
+ const csv2 = addr.toCSV(200, networks.bitcoin);
919
+
920
+ expect(csv1.address).not.toBe(csv2.address);
921
+ });
922
+ });
923
+
924
+ describe('isValid Method', () => {
925
+ it('should validate address on mainnet', () => {
926
+ const addr = getValidAddress();
927
+ const isValid = addr.isValid(networks.bitcoin);
928
+
929
+ expect(isValid).toBe(true);
930
+ });
931
+
932
+ it('should validate address on testnet', () => {
933
+ const mnemonic = new Mnemonic(
934
+ testMnemonic,
935
+ '',
936
+ networks.testnet,
937
+ MLDSASecurityLevel.LEVEL2,
938
+ );
939
+ const wallet = mnemonic.derive(0);
940
+ const isValid = wallet.address.isValid(networks.testnet);
941
+
942
+ expect(isValid).toBe(true);
943
+ });
944
+ });
945
+
946
+ describe('Edge Cases and Complex Scenarios', () => {
947
+ it('should handle multiple format conversions', () => {
948
+ const addr = getValidAddress();
949
+
950
+ const hex = addr.toHex();
951
+ const buffer = addr.toBuffer();
952
+ const string = addr.toString();
953
+ const json = addr.toJSON();
954
+
955
+ expect(hex).toBe(string);
956
+ expect(hex).toBe(json);
957
+ expect(Buffer.from(buffer).toString('hex')).toBe(hex.slice(2));
958
+ });
959
+
960
+ it('should handle multiple address generations', () => {
961
+ const addr = getValidAddress();
962
+
963
+ const p2wpkh = addr.p2wpkh(networks.bitcoin);
964
+ const p2tr = addr.p2tr(networks.bitcoin);
965
+ const p2op = addr.p2op(networks.bitcoin);
966
+
967
+ expect(p2wpkh).toMatch(/^bc1q/);
968
+ expect(p2tr).toMatch(/^bc1p/);
969
+ expect(p2op).toBeDefined();
970
+ expect(typeof p2op).toBe('string');
971
+ });
972
+
973
+ it('should handle comparison chain', () => {
974
+ const bytes1 = Buffer.alloc(32, 0x01);
975
+ const bytes2 = Buffer.alloc(32, 0x02);
976
+ const bytes3 = Buffer.alloc(32, 0x03);
977
+
978
+ const addr1 = new Address(bytes1);
979
+ const addr2 = new Address(bytes2);
980
+ const addr3 = new Address(bytes3);
981
+
982
+ expect(addr1.lessThan(addr2)).toBe(true);
983
+ expect(addr2.lessThan(addr3)).toBe(true);
984
+ expect(addr1.lessThan(addr3)).toBe(true);
985
+
986
+ expect(addr3.greaterThan(addr2)).toBe(true);
987
+ expect(addr2.greaterThan(addr1)).toBe(true);
988
+ expect(addr3.greaterThan(addr1)).toBe(true);
989
+ });
990
+
991
+ it('should handle all ML-DSA security levels', () => {
992
+ const level2 = getValidAddress(MLDSASecurityLevel.LEVEL2);
993
+ const level3 = getValidAddress(MLDSASecurityLevel.LEVEL3);
994
+ const level5 = getValidAddress(MLDSASecurityLevel.LEVEL5);
995
+
996
+ expect(level2.mldsaPublicKey?.length).toBe(1312);
997
+ expect(level3.mldsaPublicKey?.length).toBe(1952);
998
+ expect(level5.mldsaPublicKey?.length).toBe(2592);
999
+ });
1000
+
1001
+ it('should handle address with 65-byte uncompressed classical key', () => {
1002
+ const mnemonic = new Mnemonic(
1003
+ testMnemonic,
1004
+ '',
1005
+ networks.bitcoin,
1006
+ MLDSASecurityLevel.LEVEL2,
1007
+ );
1008
+ const wallet = mnemonic.derive(0);
1009
+
1010
+ // Get the uncompressed public key from the wallet
1011
+ const uncompressedKey = wallet.address.toUncompressedBuffer();
1012
+ const mldsaHash = Buffer.alloc(32, 0x01);
1013
+
1014
+ const address = new Address(mldsaHash, uncompressedKey);
1015
+ expect(address.originalPublicKey).toBeDefined();
1016
+ });
1017
+
1018
+ it('should handle dead address operations', () => {
1019
+ const dead = Address.dead();
1020
+
1021
+ expect(dead.toHex()).toContain('000000');
1022
+ expect(dead.p2tr(networks.bitcoin)).toBeDefined();
1023
+ expect(dead.p2op(networks.bitcoin)).toBeDefined();
1024
+ });
1025
+
1026
+ it('should correctly order addresses', () => {
1027
+ const addresses: Address[] = [];
1028
+ for (let i = 0; i < 5; i++) {
1029
+ const bytes = Buffer.alloc(32, i);
1030
+ addresses.push(new Address(bytes));
1031
+ }
1032
+
1033
+ for (let i = 0; i < addresses.length - 1; i++) {
1034
+ expect(addresses[i].lessThan(addresses[i + 1])).toBe(true);
1035
+ expect(addresses[i + 1].greaterThan(addresses[i])).toBe(true);
1036
+ }
1037
+ });
1038
+ });
1039
+
1040
+ describe('Network Caching', () => {
1041
+ it('should cache and reuse p2tr for same network', () => {
1042
+ const addr = getValidAddress();
1043
+
1044
+ const first = addr.p2tr(networks.bitcoin);
1045
+ const second = addr.p2tr(networks.bitcoin);
1046
+
1047
+ expect(first).toBe(second);
1048
+ });
1049
+
1050
+ it('should cache and reuse p2op for same network', () => {
1051
+ const addr = getValidAddress();
1052
+
1053
+ const first = addr.p2op(networks.bitcoin);
1054
+ const second = addr.p2op(networks.bitcoin);
1055
+
1056
+ expect(first).toBe(second);
1057
+ });
1058
+
1059
+ it('should cache and reuse p2wda for same network', () => {
1060
+ const addr = getValidAddress();
1061
+
1062
+ const first = addr.p2wda(networks.bitcoin);
1063
+ const second = addr.p2wda(networks.bitcoin);
1064
+
1065
+ expect(first.address).toBe(second.address);
1066
+ });
1067
+ });
1068
+ });