@btc-vision/transaction 1.6.19 → 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.
- package/browser/index.js +1 -1
- package/browser/index.js.LICENSE.txt +2 -0
- package/browser/src/_version.d.ts +1 -0
- package/browser/{epoch → src/epoch}/interfaces/IChallengeSolution.d.ts +2 -0
- package/browser/{keypair → src/keypair}/Address.d.ts +7 -4
- package/browser/{keypair → src/keypair}/AddressVerificator.d.ts +3 -0
- package/browser/{keypair → src/keypair}/EcKeyPair.d.ts +3 -2
- package/browser/{keypair → src/keypair}/MessageSigner.d.ts +9 -0
- package/browser/src/keypair/Wallet.d.ts +47 -0
- package/browser/{keypair → src/keypair}/interfaces/IWallet.d.ts +2 -0
- package/browser/src/mnemonic/Mnemonic.d.ts +29 -0
- package/browser/src/mnemonic/MnemonicStrength.d.ts +7 -0
- package/browser/{opnet.d.ts → src/opnet.d.ts} +4 -0
- package/browser/src/transaction/browser/types/OPWallet.d.ts +14 -0
- package/browser/test/address.test.d.ts +1 -0
- package/browser/test/addressverificator-mldsa.test.d.ts +1 -0
- package/browser/test/derivePath.test.d.ts +1 -0
- package/browser/test/messagesigner-mldsa.test.d.ts +1 -0
- package/browser/test/messagesigner-schnorr.test.d.ts +1 -0
- package/browser/test/network-awareness.test.d.ts +1 -0
- package/build/_version.d.ts +1 -1
- package/build/_version.js +1 -1
- package/build/crypto/crypto-browser.d.ts +11 -0
- package/build/crypto/crypto-browser.js +56 -0
- package/build/epoch/ChallengeSolution.js +3 -2
- package/build/epoch/interfaces/IChallengeSolution.d.ts +2 -0
- package/build/keypair/Address.d.ts +7 -4
- package/build/keypair/Address.js +88 -37
- package/build/keypair/AddressVerificator.d.ts +3 -0
- package/build/keypair/AddressVerificator.js +49 -1
- package/build/keypair/EcKeyPair.d.ts +3 -2
- package/build/keypair/EcKeyPair.js +17 -3
- package/build/keypair/MessageSigner.d.ts +9 -0
- package/build/keypair/MessageSigner.js +23 -0
- package/build/keypair/Wallet.d.ts +20 -3
- package/build/keypair/Wallet.js +108 -9
- package/build/keypair/interfaces/IWallet.d.ts +2 -0
- package/build/mnemonic/Mnemonic.d.ts +29 -0
- package/build/mnemonic/Mnemonic.js +98 -0
- package/build/mnemonic/MnemonicStrength.d.ts +7 -0
- package/build/mnemonic/MnemonicStrength.js +8 -0
- package/build/opnet.d.ts +4 -0
- package/build/opnet.js +4 -0
- package/build/transaction/browser/types/OPWallet.d.ts +14 -0
- package/build/transaction/browser/types/OPWallet.js +6 -0
- package/gulpfile.js +2 -2
- package/package.json +25 -17
- package/src/_version.ts +1 -1
- package/src/epoch/ChallengeSolution.ts +3 -2
- package/src/epoch/interfaces/IChallengeSolution.ts +2 -0
- package/src/keypair/Address.ts +145 -43
- package/src/keypair/AddressVerificator.ts +87 -2
- package/src/keypair/EcKeyPair.ts +58 -6
- package/src/keypair/MessageSigner.ts +58 -0
- package/src/keypair/Wallet.ts +339 -57
- package/src/keypair/interfaces/IWallet.ts +13 -3
- package/src/mnemonic/Mnemonic.ts +340 -0
- package/src/mnemonic/MnemonicStrength.ts +12 -0
- package/src/network/ChainId.ts +1 -4
- package/src/opnet.ts +16 -0
- package/src/transaction/browser/types/OPWallet.ts +73 -0
- package/test/address.test.ts +1068 -0
- package/test/addressverificator-mldsa.test.ts +473 -0
- package/test/derivePath.test.ts +234 -0
- package/test/messagesigner-mldsa.test.ts +1060 -0
- package/test/messagesigner-schnorr.test.ts +1011 -0
- package/test/network-awareness.test.ts +163 -0
- package/tsconfig.json +1 -1
- package/vitest.config.ts +21 -0
- package/browser/_version.d.ts +0 -1
- package/browser/keypair/Wallet.d.ts +0 -30
- /package/browser/{abi → src/abi}/ABICoder.d.ts +0 -0
- /package/browser/{buffer → src/buffer}/BinaryReader.d.ts +0 -0
- /package/browser/{buffer → src/buffer}/BinaryWriter.d.ts +0 -0
- /package/browser/{bytecode → src/bytecode}/Compressor.d.ts +0 -0
- /package/browser/{consensus → src/consensus}/Consensus.d.ts +0 -0
- /package/browser/{consensus → src/consensus}/ConsensusConfig.d.ts +0 -0
- /package/browser/{consensus → src/consensus}/metadata/RoswellConsensus.d.ts +0 -0
- /package/browser/{crypto → src/crypto}/crypto-browser.d.ts +0 -0
- /package/browser/{crypto → src/crypto}/crypto.d.ts +0 -0
- /package/browser/{deterministic → src/deterministic}/AddressMap.d.ts +0 -0
- /package/browser/{deterministic → src/deterministic}/AddressSet.d.ts +0 -0
- /package/browser/{deterministic → src/deterministic}/DeterministicMap.d.ts +0 -0
- /package/browser/{deterministic → src/deterministic}/DeterministicSet.d.ts +0 -0
- /package/browser/{deterministic → src/deterministic}/Map.d.ts +0 -0
- /package/browser/{epoch → src/epoch}/ChallengeSolution.d.ts +0 -0
- /package/browser/{epoch → src/epoch}/validator/EpochValidator.d.ts +0 -0
- /package/browser/{event → src/event}/NetEvent.d.ts +0 -0
- /package/browser/{generators → src/generators}/AddressGenerator.d.ts +0 -0
- /package/browser/{generators → src/generators}/Features.d.ts +0 -0
- /package/browser/{generators → src/generators}/Generator.d.ts +0 -0
- /package/browser/{generators → src/generators}/builders/CalldataGenerator.d.ts +0 -0
- /package/browser/{generators → src/generators}/builders/CustomGenerator.d.ts +0 -0
- /package/browser/{generators → src/generators}/builders/DeploymentGenerator.d.ts +0 -0
- /package/browser/{generators → src/generators}/builders/LegacyCalldataGenerator.d.ts +0 -0
- /package/browser/{generators → src/generators}/builders/MultiSignGenerator.d.ts +0 -0
- /package/browser/{generators → src/generators}/builders/P2WDAGenerator.d.ts +0 -0
- /package/browser/{index.d.ts → src/index.d.ts} +0 -0
- /package/browser/{keypair → src/keypair}/Secp256k1PointDeriver.d.ts +0 -0
- /package/browser/{metadata → src/metadata}/ContractBaseMetadata.d.ts +0 -0
- /package/browser/{metadata → src/metadata}/tokens.d.ts +0 -0
- /package/browser/{network → src/network}/ChainId.d.ts +0 -0
- /package/browser/{p2wda → src/p2wda}/P2WDADetector.d.ts +0 -0
- /package/browser/{signer → src/signer}/SignerUtils.d.ts +0 -0
- /package/browser/{signer → src/signer}/TweakedSigner.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/ContractAddress.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/TransactionFactory.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/browser/BrowserSignerBase.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/browser/Web3Provider.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/browser/extensions/UnisatSigner.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/browser/extensions/XverseSigner.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/browser/types/Unisat.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/browser/types/Xverse.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/CancelTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/ChallengeSolutionTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/CustomScriptTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/DeploymentTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/FundingTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/InteractionTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/InteractionTransactionP2WDA.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/MultiSignTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/SharedInteractionTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/builders/TransactionBuilder.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/enums/TransactionType.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/interfaces/ITransactionParameters.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/interfaces/Tap.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/mineable/IP2WSHAddress.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/mineable/TimelockGenerator.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/processor/PsbtTransaction.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/psbt/PSBTTypes.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/shared/P2TR_MS.d.ts +0 -0
- /package/browser/{transaction → src/transaction}/shared/TweakedTransaction.d.ts +0 -0
- /package/browser/{utils → src/utils}/BitcoinUtils.d.ts +0 -0
- /package/browser/{utils → src/utils}/BufferHelper.d.ts +0 -0
- /package/browser/{utils → src/utils}/StringToBuffer.d.ts +0 -0
- /package/browser/{utils → src/utils}/lengths.d.ts +0 -0
- /package/browser/{utils → src/utils}/types.d.ts +0 -0
- /package/browser/{utxo → src/utxo}/OPNetLimitedProvider.d.ts +0 -0
- /package/browser/{utxo → src/utxo}/interfaces/BroadcastResponse.d.ts +0 -0
- /package/browser/{utxo → src/utxo}/interfaces/IUTXO.d.ts +0 -0
- /package/browser/{verification → src/verification}/TapscriptVerificator.d.ts +0 -0
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { AddressTypes, AddressVerificator, MLDSASecurityLevel, Mnemonic } from '../build/opnet.js';
|
|
3
|
+
import { networks } from '@btc-vision/bitcoin';
|
|
4
|
+
|
|
5
|
+
describe('AddressVerificator ML-DSA Support', () => {
|
|
6
|
+
const testMnemonic =
|
|
7
|
+
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
|
|
8
|
+
|
|
9
|
+
describe('isValidMLDSAPublicKey', () => {
|
|
10
|
+
it('should validate ML-DSA-44 (Level 2) public key from hex string', () => {
|
|
11
|
+
const mnemonic = new Mnemonic(
|
|
12
|
+
testMnemonic,
|
|
13
|
+
'',
|
|
14
|
+
networks.bitcoin,
|
|
15
|
+
MLDSASecurityLevel.LEVEL2,
|
|
16
|
+
);
|
|
17
|
+
const wallet = mnemonic.derive(0);
|
|
18
|
+
const publicKeyHex = wallet.quantumPublicKeyHex;
|
|
19
|
+
|
|
20
|
+
const securityLevel = AddressVerificator.isValidMLDSAPublicKey(publicKeyHex);
|
|
21
|
+
|
|
22
|
+
expect(securityLevel).toBe(MLDSASecurityLevel.LEVEL2);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should validate ML-DSA-44 (Level 2) public key from hex string with 0x prefix', () => {
|
|
26
|
+
const mnemonic = new Mnemonic(
|
|
27
|
+
testMnemonic,
|
|
28
|
+
'',
|
|
29
|
+
networks.bitcoin,
|
|
30
|
+
MLDSASecurityLevel.LEVEL2,
|
|
31
|
+
);
|
|
32
|
+
const wallet = mnemonic.derive(0);
|
|
33
|
+
const publicKeyHex = '0x' + wallet.quantumPublicKeyHex;
|
|
34
|
+
|
|
35
|
+
const securityLevel = AddressVerificator.isValidMLDSAPublicKey(publicKeyHex);
|
|
36
|
+
|
|
37
|
+
expect(securityLevel).toBe(MLDSASecurityLevel.LEVEL2);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should validate ML-DSA-44 (Level 2) public key from Buffer', () => {
|
|
41
|
+
const mnemonic = new Mnemonic(
|
|
42
|
+
testMnemonic,
|
|
43
|
+
'',
|
|
44
|
+
networks.bitcoin,
|
|
45
|
+
MLDSASecurityLevel.LEVEL2,
|
|
46
|
+
);
|
|
47
|
+
const wallet = mnemonic.derive(0);
|
|
48
|
+
const publicKeyBuffer = wallet.quantumPublicKey;
|
|
49
|
+
|
|
50
|
+
const securityLevel = AddressVerificator.isValidMLDSAPublicKey(publicKeyBuffer);
|
|
51
|
+
|
|
52
|
+
expect(securityLevel).toBe(MLDSASecurityLevel.LEVEL2);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should validate ML-DSA-44 (Level 2) public key from Uint8Array', () => {
|
|
56
|
+
const mnemonic = new Mnemonic(
|
|
57
|
+
testMnemonic,
|
|
58
|
+
'',
|
|
59
|
+
networks.bitcoin,
|
|
60
|
+
MLDSASecurityLevel.LEVEL2,
|
|
61
|
+
);
|
|
62
|
+
const wallet = mnemonic.derive(0);
|
|
63
|
+
const publicKeyArray = new Uint8Array(wallet.quantumPublicKey);
|
|
64
|
+
|
|
65
|
+
const securityLevel = AddressVerificator.isValidMLDSAPublicKey(publicKeyArray);
|
|
66
|
+
|
|
67
|
+
expect(securityLevel).toBe(MLDSASecurityLevel.LEVEL2);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('should validate ML-DSA-65 (Level 3) public key', () => {
|
|
71
|
+
const mnemonic = new Mnemonic(
|
|
72
|
+
testMnemonic,
|
|
73
|
+
'',
|
|
74
|
+
networks.bitcoin,
|
|
75
|
+
MLDSASecurityLevel.LEVEL3,
|
|
76
|
+
);
|
|
77
|
+
const wallet = mnemonic.derive(0);
|
|
78
|
+
const publicKeyHex = wallet.quantumPublicKeyHex;
|
|
79
|
+
|
|
80
|
+
const securityLevel = AddressVerificator.isValidMLDSAPublicKey(publicKeyHex);
|
|
81
|
+
|
|
82
|
+
expect(securityLevel).toBe(MLDSASecurityLevel.LEVEL3);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should validate ML-DSA-65 (Level 3) public key from Buffer', () => {
|
|
86
|
+
const mnemonic = new Mnemonic(
|
|
87
|
+
testMnemonic,
|
|
88
|
+
'',
|
|
89
|
+
networks.bitcoin,
|
|
90
|
+
MLDSASecurityLevel.LEVEL3,
|
|
91
|
+
);
|
|
92
|
+
const wallet = mnemonic.derive(0);
|
|
93
|
+
const publicKeyBuffer = wallet.quantumPublicKey;
|
|
94
|
+
|
|
95
|
+
const securityLevel = AddressVerificator.isValidMLDSAPublicKey(publicKeyBuffer);
|
|
96
|
+
|
|
97
|
+
expect(securityLevel).toBe(MLDSASecurityLevel.LEVEL3);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should validate ML-DSA-87 (Level 5) public key', () => {
|
|
101
|
+
const mnemonic = new Mnemonic(
|
|
102
|
+
testMnemonic,
|
|
103
|
+
'',
|
|
104
|
+
networks.bitcoin,
|
|
105
|
+
MLDSASecurityLevel.LEVEL5,
|
|
106
|
+
);
|
|
107
|
+
const wallet = mnemonic.derive(0);
|
|
108
|
+
const publicKeyHex = wallet.quantumPublicKeyHex;
|
|
109
|
+
|
|
110
|
+
const securityLevel = AddressVerificator.isValidMLDSAPublicKey(publicKeyHex);
|
|
111
|
+
|
|
112
|
+
expect(securityLevel).toBe(MLDSASecurityLevel.LEVEL5);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('should validate ML-DSA-87 (Level 5) public key from Buffer', () => {
|
|
116
|
+
const mnemonic = new Mnemonic(
|
|
117
|
+
testMnemonic,
|
|
118
|
+
'',
|
|
119
|
+
networks.bitcoin,
|
|
120
|
+
MLDSASecurityLevel.LEVEL5,
|
|
121
|
+
);
|
|
122
|
+
const wallet = mnemonic.derive(0);
|
|
123
|
+
const publicKeyBuffer = wallet.quantumPublicKey;
|
|
124
|
+
|
|
125
|
+
const securityLevel = AddressVerificator.isValidMLDSAPublicKey(publicKeyBuffer);
|
|
126
|
+
|
|
127
|
+
expect(securityLevel).toBe(MLDSASecurityLevel.LEVEL5);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should reject invalid hex string', () => {
|
|
131
|
+
const invalidHex = 'not a valid hex string';
|
|
132
|
+
const securityLevel = AddressVerificator.isValidMLDSAPublicKey(invalidHex);
|
|
133
|
+
|
|
134
|
+
expect(securityLevel).toBeNull();
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('should reject public key with wrong length', () => {
|
|
138
|
+
const wrongLength = 'a'.repeat(100);
|
|
139
|
+
const securityLevel = AddressVerificator.isValidMLDSAPublicKey(wrongLength);
|
|
140
|
+
|
|
141
|
+
expect(securityLevel).toBeNull();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should reject empty string', () => {
|
|
145
|
+
const securityLevel = AddressVerificator.isValidMLDSAPublicKey('');
|
|
146
|
+
|
|
147
|
+
expect(securityLevel).toBeNull();
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('should reject empty Buffer', () => {
|
|
151
|
+
const securityLevel = AddressVerificator.isValidMLDSAPublicKey(Buffer.alloc(0));
|
|
152
|
+
|
|
153
|
+
expect(securityLevel).toBeNull();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should reject classical public key (33 bytes)', () => {
|
|
157
|
+
const mnemonic = new Mnemonic(
|
|
158
|
+
testMnemonic,
|
|
159
|
+
'',
|
|
160
|
+
networks.bitcoin,
|
|
161
|
+
MLDSASecurityLevel.LEVEL2,
|
|
162
|
+
);
|
|
163
|
+
const wallet = mnemonic.derive(0);
|
|
164
|
+
const classicalPublicKey = wallet.publicKey; // 33 bytes
|
|
165
|
+
|
|
166
|
+
const securityLevel = AddressVerificator.isValidMLDSAPublicKey(classicalPublicKey);
|
|
167
|
+
|
|
168
|
+
expect(securityLevel).toBeNull();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('should verify all valid ML-DSA lengths', () => {
|
|
172
|
+
// Test all three security levels
|
|
173
|
+
const levels = [
|
|
174
|
+
MLDSASecurityLevel.LEVEL2,
|
|
175
|
+
MLDSASecurityLevel.LEVEL3,
|
|
176
|
+
MLDSASecurityLevel.LEVEL5,
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
for (const level of levels) {
|
|
180
|
+
const mnemonic = new Mnemonic(testMnemonic, '', networks.bitcoin, level);
|
|
181
|
+
const wallet = mnemonic.derive(0);
|
|
182
|
+
|
|
183
|
+
const securityLevelHex = AddressVerificator.isValidMLDSAPublicKey(
|
|
184
|
+
wallet.quantumPublicKeyHex,
|
|
185
|
+
);
|
|
186
|
+
const securityLevelBuffer = AddressVerificator.isValidMLDSAPublicKey(
|
|
187
|
+
wallet.quantumPublicKey,
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
expect(securityLevelHex).toBe(level);
|
|
191
|
+
expect(securityLevelBuffer).toBe(level);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe('isValidP2OPAddress', () => {
|
|
197
|
+
it('should validate mainnet P2OP address', () => {
|
|
198
|
+
const mnemonic = new Mnemonic(
|
|
199
|
+
testMnemonic,
|
|
200
|
+
'',
|
|
201
|
+
networks.bitcoin,
|
|
202
|
+
MLDSASecurityLevel.LEVEL2,
|
|
203
|
+
);
|
|
204
|
+
const wallet = mnemonic.derive(0);
|
|
205
|
+
const p2opAddress = wallet.address.p2op(networks.bitcoin);
|
|
206
|
+
|
|
207
|
+
const isValid = AddressVerificator.isValidP2OPAddress(p2opAddress, networks.bitcoin);
|
|
208
|
+
|
|
209
|
+
expect(isValid).toBe(true);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('should validate testnet P2OP address', () => {
|
|
213
|
+
const mnemonic = new Mnemonic(
|
|
214
|
+
testMnemonic,
|
|
215
|
+
'',
|
|
216
|
+
networks.testnet,
|
|
217
|
+
MLDSASecurityLevel.LEVEL2,
|
|
218
|
+
);
|
|
219
|
+
const wallet = mnemonic.derive(0);
|
|
220
|
+
const p2opAddress = wallet.address.p2op(networks.testnet);
|
|
221
|
+
|
|
222
|
+
const isValid = AddressVerificator.isValidP2OPAddress(p2opAddress, networks.testnet);
|
|
223
|
+
|
|
224
|
+
expect(isValid).toBe(true);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('should validate regtest P2OP address', () => {
|
|
228
|
+
const mnemonic = new Mnemonic(
|
|
229
|
+
testMnemonic,
|
|
230
|
+
'',
|
|
231
|
+
networks.regtest,
|
|
232
|
+
MLDSASecurityLevel.LEVEL2,
|
|
233
|
+
);
|
|
234
|
+
const wallet = mnemonic.derive(0);
|
|
235
|
+
const p2opAddress = wallet.address.p2op(networks.regtest);
|
|
236
|
+
|
|
237
|
+
const isValid = AddressVerificator.isValidP2OPAddress(p2opAddress, networks.regtest);
|
|
238
|
+
|
|
239
|
+
expect(isValid).toBe(true);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
it('should reject P2TR address as P2OP', () => {
|
|
243
|
+
const mnemonic = new Mnemonic(
|
|
244
|
+
testMnemonic,
|
|
245
|
+
'',
|
|
246
|
+
networks.bitcoin,
|
|
247
|
+
MLDSASecurityLevel.LEVEL2,
|
|
248
|
+
);
|
|
249
|
+
const wallet = mnemonic.derive(0);
|
|
250
|
+
const p2trAddress = wallet.p2tr;
|
|
251
|
+
|
|
252
|
+
const isValid = AddressVerificator.isValidP2OPAddress(p2trAddress, networks.bitcoin);
|
|
253
|
+
|
|
254
|
+
expect(isValid).toBe(false);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('should reject P2WPKH address as P2OP', () => {
|
|
258
|
+
const mnemonic = new Mnemonic(
|
|
259
|
+
testMnemonic,
|
|
260
|
+
'',
|
|
261
|
+
networks.bitcoin,
|
|
262
|
+
MLDSASecurityLevel.LEVEL2,
|
|
263
|
+
);
|
|
264
|
+
const wallet = mnemonic.derive(0);
|
|
265
|
+
const p2wpkhAddress = wallet.p2wpkh;
|
|
266
|
+
|
|
267
|
+
const isValid = AddressVerificator.isValidP2OPAddress(p2wpkhAddress, networks.bitcoin);
|
|
268
|
+
|
|
269
|
+
expect(isValid).toBe(false);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('should reject invalid address string', () => {
|
|
273
|
+
const invalidAddress = 'not a valid address';
|
|
274
|
+
const isValid = AddressVerificator.isValidP2OPAddress(invalidAddress, networks.bitcoin);
|
|
275
|
+
|
|
276
|
+
expect(isValid).toBe(false);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('should reject empty string', () => {
|
|
280
|
+
const isValid = AddressVerificator.isValidP2OPAddress('', networks.bitcoin);
|
|
281
|
+
|
|
282
|
+
expect(isValid).toBe(false);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it('should reject address on wrong network', () => {
|
|
286
|
+
const mnemonic = new Mnemonic(
|
|
287
|
+
testMnemonic,
|
|
288
|
+
'',
|
|
289
|
+
networks.bitcoin,
|
|
290
|
+
MLDSASecurityLevel.LEVEL2,
|
|
291
|
+
);
|
|
292
|
+
const wallet = mnemonic.derive(0);
|
|
293
|
+
const p2opAddress = wallet.address.p2op(networks.bitcoin);
|
|
294
|
+
|
|
295
|
+
// Try to validate mainnet address on testnet
|
|
296
|
+
const isValid = AddressVerificator.isValidP2OPAddress(p2opAddress, networks.testnet);
|
|
297
|
+
|
|
298
|
+
expect(isValid).toBe(false);
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
describe('detectAddressType - P2OP support', () => {
|
|
303
|
+
it('should detect mainnet P2OP address type', () => {
|
|
304
|
+
const mnemonic = new Mnemonic(
|
|
305
|
+
testMnemonic,
|
|
306
|
+
'',
|
|
307
|
+
networks.bitcoin,
|
|
308
|
+
MLDSASecurityLevel.LEVEL2,
|
|
309
|
+
);
|
|
310
|
+
const wallet = mnemonic.derive(0);
|
|
311
|
+
const p2opAddress = wallet.address.p2op(networks.bitcoin);
|
|
312
|
+
|
|
313
|
+
const addressType = AddressVerificator.detectAddressType(p2opAddress, networks.bitcoin);
|
|
314
|
+
|
|
315
|
+
expect(addressType).toBe(AddressTypes.P2OP);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it('should detect testnet P2OP address type', () => {
|
|
319
|
+
const mnemonic = new Mnemonic(
|
|
320
|
+
testMnemonic,
|
|
321
|
+
'',
|
|
322
|
+
networks.testnet,
|
|
323
|
+
MLDSASecurityLevel.LEVEL2,
|
|
324
|
+
);
|
|
325
|
+
const wallet = mnemonic.derive(0);
|
|
326
|
+
const p2opAddress = wallet.address.p2op(networks.testnet);
|
|
327
|
+
|
|
328
|
+
const addressType = AddressVerificator.detectAddressType(p2opAddress, networks.testnet);
|
|
329
|
+
|
|
330
|
+
expect(addressType).toBe(AddressTypes.P2OP);
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
it('should detect regtest P2OP address type', () => {
|
|
334
|
+
const mnemonic = new Mnemonic(
|
|
335
|
+
testMnemonic,
|
|
336
|
+
'',
|
|
337
|
+
networks.regtest,
|
|
338
|
+
MLDSASecurityLevel.LEVEL2,
|
|
339
|
+
);
|
|
340
|
+
const wallet = mnemonic.derive(0);
|
|
341
|
+
const p2opAddress = wallet.address.p2op(networks.regtest);
|
|
342
|
+
|
|
343
|
+
const addressType = AddressVerificator.detectAddressType(p2opAddress, networks.regtest);
|
|
344
|
+
|
|
345
|
+
expect(addressType).toBe(AddressTypes.P2OP);
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
it('should not confuse P2OP with P2TR', () => {
|
|
349
|
+
const mnemonic = new Mnemonic(
|
|
350
|
+
testMnemonic,
|
|
351
|
+
'',
|
|
352
|
+
networks.bitcoin,
|
|
353
|
+
MLDSASecurityLevel.LEVEL2,
|
|
354
|
+
);
|
|
355
|
+
const wallet = mnemonic.derive(0);
|
|
356
|
+
|
|
357
|
+
const p2opAddress = wallet.address.p2op(networks.bitcoin);
|
|
358
|
+
const p2trAddress = wallet.p2tr;
|
|
359
|
+
|
|
360
|
+
const p2opType = AddressVerificator.detectAddressType(p2opAddress, networks.bitcoin);
|
|
361
|
+
const p2trType = AddressVerificator.detectAddressType(p2trAddress, networks.bitcoin);
|
|
362
|
+
|
|
363
|
+
expect(p2opType).toBe(AddressTypes.P2OP);
|
|
364
|
+
expect(p2trType).toBe(AddressTypes.P2TR);
|
|
365
|
+
expect(p2opType).not.toBe(p2trType);
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
it('should not confuse P2OP with P2WPKH', () => {
|
|
369
|
+
const mnemonic = new Mnemonic(
|
|
370
|
+
testMnemonic,
|
|
371
|
+
'',
|
|
372
|
+
networks.bitcoin,
|
|
373
|
+
MLDSASecurityLevel.LEVEL2,
|
|
374
|
+
);
|
|
375
|
+
const wallet = mnemonic.derive(0);
|
|
376
|
+
|
|
377
|
+
const p2opAddress = wallet.address.p2op(networks.bitcoin);
|
|
378
|
+
const p2wpkhAddress = wallet.p2wpkh;
|
|
379
|
+
|
|
380
|
+
const p2opType = AddressVerificator.detectAddressType(p2opAddress, networks.bitcoin);
|
|
381
|
+
const p2wpkhType = AddressVerificator.detectAddressType(
|
|
382
|
+
p2wpkhAddress,
|
|
383
|
+
networks.bitcoin,
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
expect(p2opType).toBe(AddressTypes.P2OP);
|
|
387
|
+
expect(p2wpkhType).toBe(AddressTypes.P2WPKH);
|
|
388
|
+
expect(p2opType).not.toBe(p2wpkhType);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it('should detect P2OP for different security levels', () => {
|
|
392
|
+
const levels = [
|
|
393
|
+
MLDSASecurityLevel.LEVEL2,
|
|
394
|
+
MLDSASecurityLevel.LEVEL3,
|
|
395
|
+
MLDSASecurityLevel.LEVEL5,
|
|
396
|
+
];
|
|
397
|
+
|
|
398
|
+
for (const level of levels) {
|
|
399
|
+
const mnemonic = new Mnemonic(testMnemonic, '', networks.bitcoin, level);
|
|
400
|
+
const wallet = mnemonic.derive(0);
|
|
401
|
+
const p2opAddress = wallet.address.p2op(networks.bitcoin);
|
|
402
|
+
|
|
403
|
+
const addressType = AddressVerificator.detectAddressType(
|
|
404
|
+
p2opAddress,
|
|
405
|
+
networks.bitcoin,
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
expect(addressType).toBe(AddressTypes.P2OP);
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
it('should return null for invalid P2OP address on wrong network', () => {
|
|
413
|
+
const mnemonic = new Mnemonic(
|
|
414
|
+
testMnemonic,
|
|
415
|
+
'',
|
|
416
|
+
networks.bitcoin,
|
|
417
|
+
MLDSASecurityLevel.LEVEL2,
|
|
418
|
+
);
|
|
419
|
+
const wallet = mnemonic.derive(0);
|
|
420
|
+
const p2opAddress = wallet.address.p2op(networks.bitcoin);
|
|
421
|
+
|
|
422
|
+
// Try to detect mainnet address on testnet
|
|
423
|
+
const addressType = AddressVerificator.detectAddressType(p2opAddress, networks.testnet);
|
|
424
|
+
|
|
425
|
+
expect(addressType).toBeNull();
|
|
426
|
+
});
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
describe('ML-DSA integration with other address types', () => {
|
|
430
|
+
it('should correctly identify different address types from same wallet', () => {
|
|
431
|
+
const mnemonic = new Mnemonic(
|
|
432
|
+
testMnemonic,
|
|
433
|
+
'',
|
|
434
|
+
networks.bitcoin,
|
|
435
|
+
MLDSASecurityLevel.LEVEL2,
|
|
436
|
+
);
|
|
437
|
+
const wallet = mnemonic.derive(0);
|
|
438
|
+
|
|
439
|
+
const p2trType = AddressVerificator.detectAddressType(wallet.p2tr, networks.bitcoin);
|
|
440
|
+
const p2wpkhType = AddressVerificator.detectAddressType(
|
|
441
|
+
wallet.p2wpkh,
|
|
442
|
+
networks.bitcoin,
|
|
443
|
+
);
|
|
444
|
+
const p2opType = AddressVerificator.detectAddressType(
|
|
445
|
+
wallet.address.p2op(networks.bitcoin),
|
|
446
|
+
networks.bitcoin,
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
expect(p2trType).toBe(AddressTypes.P2TR);
|
|
450
|
+
expect(p2wpkhType).toBe(AddressTypes.P2WPKH);
|
|
451
|
+
expect(p2opType).toBe(AddressTypes.P2OP);
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
it('should validate classical and ML-DSA public keys separately', () => {
|
|
455
|
+
const mnemonic = new Mnemonic(
|
|
456
|
+
testMnemonic,
|
|
457
|
+
'',
|
|
458
|
+
networks.bitcoin,
|
|
459
|
+
MLDSASecurityLevel.LEVEL2,
|
|
460
|
+
);
|
|
461
|
+
const wallet = mnemonic.derive(0);
|
|
462
|
+
|
|
463
|
+
const classicalValid = AddressVerificator.isValidPublicKey(
|
|
464
|
+
wallet.toPublicKeyHex(),
|
|
465
|
+
networks.bitcoin,
|
|
466
|
+
);
|
|
467
|
+
const mldsaLevel = AddressVerificator.isValidMLDSAPublicKey(wallet.quantumPublicKeyHex);
|
|
468
|
+
|
|
469
|
+
expect(classicalValid).toBe(true);
|
|
470
|
+
expect(mldsaLevel).toBe(MLDSASecurityLevel.LEVEL2);
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
});
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { MLDSASecurityLevel, Mnemonic } from '../build/opnet.js';
|
|
3
|
+
import { networks } from '@btc-vision/bitcoin';
|
|
4
|
+
|
|
5
|
+
describe('Wallet.derivePath', () => {
|
|
6
|
+
const testMnemonic =
|
|
7
|
+
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
|
|
8
|
+
|
|
9
|
+
describe('Basic derivation', () => {
|
|
10
|
+
it('should derive child wallet with unique addresses', () => {
|
|
11
|
+
const mnemonic = new Mnemonic(
|
|
12
|
+
testMnemonic,
|
|
13
|
+
'',
|
|
14
|
+
networks.bitcoin,
|
|
15
|
+
MLDSASecurityLevel.LEVEL2,
|
|
16
|
+
);
|
|
17
|
+
const wallet = mnemonic.derive(0);
|
|
18
|
+
const child = wallet.derivePath('m/0');
|
|
19
|
+
|
|
20
|
+
// Addresses should be different
|
|
21
|
+
expect(child.p2tr).not.toBe(wallet.p2tr);
|
|
22
|
+
expect(child.p2wpkh).not.toBe(wallet.p2wpkh);
|
|
23
|
+
|
|
24
|
+
// Private keys should be different
|
|
25
|
+
expect(child.toPrivateKeyHex()).not.toBe(wallet.toPrivateKeyHex());
|
|
26
|
+
expect(child.quantumPrivateKeyHex).not.toBe(wallet.quantumPrivateKeyHex);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should derive wallet with correct address prefixes', () => {
|
|
30
|
+
const mnemonic = new Mnemonic(
|
|
31
|
+
testMnemonic,
|
|
32
|
+
'',
|
|
33
|
+
networks.bitcoin,
|
|
34
|
+
MLDSASecurityLevel.LEVEL2,
|
|
35
|
+
);
|
|
36
|
+
const wallet = mnemonic.derive(0);
|
|
37
|
+
const child = wallet.derivePath('m/0');
|
|
38
|
+
|
|
39
|
+
expect(child.p2tr).toMatch(/^bc1p/);
|
|
40
|
+
expect(child.p2wpkh).toMatch(/^bc1q/);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('Multiple child derivations', () => {
|
|
45
|
+
it('should derive multiple children with unique addresses', () => {
|
|
46
|
+
const mnemonic = new Mnemonic(
|
|
47
|
+
testMnemonic,
|
|
48
|
+
'',
|
|
49
|
+
networks.bitcoin,
|
|
50
|
+
MLDSASecurityLevel.LEVEL2,
|
|
51
|
+
);
|
|
52
|
+
const wallet = mnemonic.derive(0);
|
|
53
|
+
|
|
54
|
+
const child0 = wallet.derivePath('m/0');
|
|
55
|
+
const child1 = wallet.derivePath('m/1');
|
|
56
|
+
const child2 = wallet.derivePath('m/2');
|
|
57
|
+
|
|
58
|
+
// All addresses should be unique
|
|
59
|
+
const addresses = [child0.p2tr, child1.p2tr, child2.p2tr];
|
|
60
|
+
const uniqueAddresses = new Set(addresses);
|
|
61
|
+
expect(uniqueAddresses.size).toBe(3);
|
|
62
|
+
|
|
63
|
+
// All classical keys should be unique
|
|
64
|
+
const classicalKeys = [
|
|
65
|
+
child0.toPrivateKeyHex(),
|
|
66
|
+
child1.toPrivateKeyHex(),
|
|
67
|
+
child2.toPrivateKeyHex(),
|
|
68
|
+
];
|
|
69
|
+
const uniqueClassicalKeys = new Set(classicalKeys);
|
|
70
|
+
expect(uniqueClassicalKeys.size).toBe(3);
|
|
71
|
+
|
|
72
|
+
// All quantum keys should be unique
|
|
73
|
+
const quantumKeys = [
|
|
74
|
+
child0.quantumPrivateKeyHex,
|
|
75
|
+
child1.quantumPrivateKeyHex,
|
|
76
|
+
child2.quantumPrivateKeyHex,
|
|
77
|
+
];
|
|
78
|
+
const uniqueQuantumKeys = new Set(quantumKeys);
|
|
79
|
+
expect(uniqueQuantumKeys.size).toBe(3);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('Network preservation', () => {
|
|
84
|
+
it('should maintain mainnet network in derived wallet', () => {
|
|
85
|
+
const mnemonic = new Mnemonic(
|
|
86
|
+
testMnemonic,
|
|
87
|
+
'',
|
|
88
|
+
networks.bitcoin,
|
|
89
|
+
MLDSASecurityLevel.LEVEL2,
|
|
90
|
+
);
|
|
91
|
+
const wallet = mnemonic.derive(0);
|
|
92
|
+
const child = wallet.derivePath('m/0');
|
|
93
|
+
|
|
94
|
+
expect(child.network.bech32).toBe('bc');
|
|
95
|
+
expect(child.p2tr).toMatch(/^bc1/);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should maintain testnet network in derived wallet', () => {
|
|
99
|
+
const mnemonic = new Mnemonic(
|
|
100
|
+
testMnemonic,
|
|
101
|
+
'',
|
|
102
|
+
networks.testnet,
|
|
103
|
+
MLDSASecurityLevel.LEVEL2,
|
|
104
|
+
);
|
|
105
|
+
const wallet = mnemonic.derive(0);
|
|
106
|
+
const child = wallet.derivePath('m/0');
|
|
107
|
+
|
|
108
|
+
expect(child.network.bech32).toBe('tb');
|
|
109
|
+
expect(child.p2tr).toMatch(/^tb1/);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('should maintain regtest network in derived wallet', () => {
|
|
113
|
+
const mnemonic = new Mnemonic(
|
|
114
|
+
testMnemonic,
|
|
115
|
+
'',
|
|
116
|
+
networks.regtest,
|
|
117
|
+
MLDSASecurityLevel.LEVEL2,
|
|
118
|
+
);
|
|
119
|
+
const wallet = mnemonic.derive(0);
|
|
120
|
+
const child = wallet.derivePath('m/0');
|
|
121
|
+
|
|
122
|
+
expect(child.network.bech32).toBe('bcrt');
|
|
123
|
+
expect(child.p2tr).toMatch(/^bcrt1/);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe('Network-aware key derivation', () => {
|
|
128
|
+
it('should derive different classical keys for different networks', () => {
|
|
129
|
+
const mnemonicMainnet = new Mnemonic(
|
|
130
|
+
testMnemonic,
|
|
131
|
+
'',
|
|
132
|
+
networks.bitcoin,
|
|
133
|
+
MLDSASecurityLevel.LEVEL2,
|
|
134
|
+
);
|
|
135
|
+
const mnemonicTestnet = new Mnemonic(
|
|
136
|
+
testMnemonic,
|
|
137
|
+
'',
|
|
138
|
+
networks.testnet,
|
|
139
|
+
MLDSASecurityLevel.LEVEL2,
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
const mainnetParent = mnemonicMainnet.derive(0);
|
|
143
|
+
const testnetParent = mnemonicTestnet.derive(0);
|
|
144
|
+
|
|
145
|
+
const mainnetChild = mainnetParent.derivePath('m/0');
|
|
146
|
+
const testnetChild = testnetParent.derivePath('m/0');
|
|
147
|
+
|
|
148
|
+
// Classical keys should differ between networks
|
|
149
|
+
expect(mainnetChild.toPrivateKeyHex()).not.toBe(testnetChild.toPrivateKeyHex());
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('should derive different quantum keys for different networks', () => {
|
|
153
|
+
const mnemonicMainnet = new Mnemonic(
|
|
154
|
+
testMnemonic,
|
|
155
|
+
'',
|
|
156
|
+
networks.bitcoin,
|
|
157
|
+
MLDSASecurityLevel.LEVEL2,
|
|
158
|
+
);
|
|
159
|
+
const mnemonicTestnet = new Mnemonic(
|
|
160
|
+
testMnemonic,
|
|
161
|
+
'',
|
|
162
|
+
networks.testnet,
|
|
163
|
+
MLDSASecurityLevel.LEVEL2,
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const mainnetParent = mnemonicMainnet.derive(0);
|
|
167
|
+
const testnetParent = mnemonicTestnet.derive(0);
|
|
168
|
+
|
|
169
|
+
const mainnetChild = mainnetParent.derivePath('m/0');
|
|
170
|
+
const testnetChild = testnetParent.derivePath('m/0');
|
|
171
|
+
|
|
172
|
+
// Quantum keys should differ between networks
|
|
173
|
+
expect(mainnetChild.quantumPrivateKeyHex).not.toBe(testnetChild.quantumPrivateKeyHex);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
describe('Hardened paths', () => {
|
|
178
|
+
it('should support hardened derivation paths', () => {
|
|
179
|
+
const mnemonic = new Mnemonic(
|
|
180
|
+
testMnemonic,
|
|
181
|
+
'',
|
|
182
|
+
networks.bitcoin,
|
|
183
|
+
MLDSASecurityLevel.LEVEL2,
|
|
184
|
+
);
|
|
185
|
+
const wallet = mnemonic.derive(0);
|
|
186
|
+
|
|
187
|
+
const hardened1 = wallet.derivePath("m/0'");
|
|
188
|
+
const hardened2 = wallet.derivePath("m/44'/0'/0'");
|
|
189
|
+
|
|
190
|
+
expect(hardened1.p2tr).toBeDefined();
|
|
191
|
+
expect(hardened2.p2tr).toBeDefined();
|
|
192
|
+
expect(hardened1.p2tr).not.toBe(hardened2.p2tr);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe('Deterministic derivation', () => {
|
|
197
|
+
it('should produce same results when using same mnemonic-derived wallet', () => {
|
|
198
|
+
const mnemonic = new Mnemonic(
|
|
199
|
+
testMnemonic,
|
|
200
|
+
'',
|
|
201
|
+
networks.bitcoin,
|
|
202
|
+
MLDSASecurityLevel.LEVEL2,
|
|
203
|
+
);
|
|
204
|
+
const wallet = mnemonic.derive(0);
|
|
205
|
+
|
|
206
|
+
// Derive the same path twice from the same wallet instance
|
|
207
|
+
const child1 = wallet.derivePath('m/0/1');
|
|
208
|
+
const child2 = wallet.derivePath('m/0/1');
|
|
209
|
+
|
|
210
|
+
// Should produce identical results (deterministic)
|
|
211
|
+
expect(child1.p2tr).toBe(child2.p2tr);
|
|
212
|
+
expect(child1.p2wpkh).toBe(child2.p2wpkh);
|
|
213
|
+
expect(child1.toPrivateKeyHex()).toBe(child2.toPrivateKeyHex());
|
|
214
|
+
expect(child1.quantumPrivateKeyHex).toBe(child2.quantumPrivateKeyHex);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
describe('Deep path derivation', () => {
|
|
219
|
+
it('should support deep BIP44-style paths', () => {
|
|
220
|
+
const mnemonic = new Mnemonic(
|
|
221
|
+
testMnemonic,
|
|
222
|
+
'',
|
|
223
|
+
networks.bitcoin,
|
|
224
|
+
MLDSASecurityLevel.LEVEL2,
|
|
225
|
+
);
|
|
226
|
+
const wallet = mnemonic.derive(0);
|
|
227
|
+
|
|
228
|
+
const deepChild = wallet.derivePath("m/44'/0'/0'/0/5");
|
|
229
|
+
|
|
230
|
+
expect(deepChild.p2tr).toBeDefined();
|
|
231
|
+
expect(deepChild.p2tr).not.toBe(wallet.p2tr);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
});
|