@@ -64,30 +64,38 @@ describe('Watch only wallet', () => {
6464 } ) ;
6565
6666 it ( 'can create PSBT base64 without signature for HW wallet xpub' , async ( ) => {
67- const w = new WatchOnlyWallet ( ) ;
68- w . setSecret ( 'xpub6CQdfC3v9gU86eaSn7AhUFcBVxiGhdtYxdC5Cw2vLmFkfth2KXCMmYcPpvZviA89X6DXDs4PJDk5QVL2G2xaVjv7SM4roWHr1gR4xB3Z7Ps' ) ;
69- w . init ( ) ;
70- const changeAddress = '1KZjqYHm7a1DjhjcdcjfQvYfF2h6PqatjX' ;
71- // hardcoding so we wont have to call w.getChangeAddressAsync()
72- const utxos = [
73- {
74- height : 530926 ,
75- value : 1000 ,
76- address : '12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG' ,
77- txid : 'd0432027a86119c63a0be8fa453275c2333b59067f1e559389cd3e0e377c8b96' ,
78- vout : 1 ,
79- txhex :
80- '0100000001b630ac364a04b83548994ded4705b98316b2d1fe18b9fffa2627be9eef11bf60000000006b48304502210096e68d94d374e3a688ed2e6605289f81172540abaab5f6cc431c231919860746022075ee4e64c867ed9d369d01a9b35d8b1689a821be8d729fff7fb3dfcc75d16f6401210281d2e40ba6422fc97b61fd5643bee83dd749d8369339edc795d7b3f00e96c681fdffffff02ef020000000000001976a914e4271ef9e9a03a89b981c73d3d6936d2f6fccc0688ace8030000000000001976a914120ad7854152901ebeb269acb6cef20e71b3cf5988acea190800' ,
81- } ,
82- ] ;
83- // hardcoding utxo so we wont have to call w.fetchUtxo() and w.getUtxo()
84-
85- const { psbt } = await w . createTransaction ( utxos , [ { address : '1QDCFcpnrZ4yrAQxmbvSgeUC9iZZ8ehcR5' } ] , 1 , changeAddress ) ;
67+ for ( const cleanupInternals of [ false , true ] ) {
68+ const w = new WatchOnlyWallet ( ) ;
69+ w . setSecret ( 'xpub6CQdfC3v9gU86eaSn7AhUFcBVxiGhdtYxdC5Cw2vLmFkfth2KXCMmYcPpvZviA89X6DXDs4PJDk5QVL2G2xaVjv7SM4roWHr1gR4xB3Z7Ps' ) ;
70+ w . init ( ) ;
71+ const changeAddress = '1KZjqYHm7a1DjhjcdcjfQvYfF2h6PqatjX' ;
72+ // hardcoding so we wont have to call w.getChangeAddressAsync()
73+ const utxos = [
74+ {
75+ height : 530926 ,
76+ value : 1000 ,
77+ address : '12eQ9m4sgAwTSQoNXkRABKhCXCsjm2jdVG' ,
78+ txid : 'd0432027a86119c63a0be8fa453275c2333b59067f1e559389cd3e0e377c8b96' ,
79+ vout : 1 ,
80+ txhex :
81+ '0100000001b630ac364a04b83548994ded4705b98316b2d1fe18b9fffa2627be9eef11bf60000000006b48304502210096e68d94d374e3a688ed2e6605289f81172540abaab5f6cc431c231919860746022075ee4e64c867ed9d369d01a9b35d8b1689a821be8d729fff7fb3dfcc75d16f6401210281d2e40ba6422fc97b61fd5643bee83dd749d8369339edc795d7b3f00e96c681fdffffff02ef020000000000001976a914e4271ef9e9a03a89b981c73d3d6936d2f6fccc0688ace8030000000000001976a914120ad7854152901ebeb269acb6cef20e71b3cf5988acea190800' ,
82+ } ,
83+ ] ;
84+ // hardcoding utxo so we wont have to call w.fetchUtxo() and w.getUtxo()
85+
86+ const { psbt } = await w . createTransaction ( utxos , [ { address : '1QDCFcpnrZ4yrAQxmbvSgeUC9iZZ8ehcR5' } ] , 1 , changeAddress ) ;
87+
88+ if ( cleanupInternals ) {
89+ // these might be purged when preparing for serialization before saving to disk
90+ w . _hdWalletInstance . _node0 = undefined ;
91+ w . _hdWalletInstance . _node1 = undefined ;
92+ }
8693
87- assert . strictEqual (
88- psbt . toBase64 ( ) ,
89- 'cHNidP8BAFUCAAAAAZaLfDcOPs2Jk1UefwZZOzPCdTJF+ugLOsYZYagnIEPQAQAAAAAAAACAASgDAAAAAAAAGXapFP6ZRvxlaU5S/9HQFr1i2lsgp58AiKwAAAAAAAEA4gEAAAABtjCsNkoEuDVImU3tRwW5gxay0f4Yuf/6Jie+nu8Rv2AAAAAAa0gwRQIhAJbmjZTTdOOmiO0uZgUon4EXJUCrqrX2zEMcIxkZhgdGAiB17k5kyGftnTadAamzXYsWiaghvo1yn/9/s9/MddFvZAEhAoHS5AumQi/Je2H9VkO+6D3XSdg2kzntx5XXs/AOlsaB/f///wLvAgAAAAAAABl2qRTkJx756aA6ibmBxz09aTbS9vzMBois6AMAAAAAAAAZdqkUEgrXhUFSkB6+smmsts7yDnGzz1mIrOoZCAAiBgPGm5BfckKzaIEi8GlRM5oe4A2mUvbsxlJ+pmMhRsrOYhgAAAAALAAAgAAAAIAAAACAAAAAAAAAAAAAAA==' ,
90- ) ;
94+ assert . strictEqual (
95+ psbt . toBase64 ( ) ,
96+ 'cHNidP8BAFUCAAAAAZaLfDcOPs2Jk1UefwZZOzPCdTJF+ugLOsYZYagnIEPQAQAAAAAAAACAASgDAAAAAAAAGXapFP6ZRvxlaU5S/9HQFr1i2lsgp58AiKwAAAAAAAEA4gEAAAABtjCsNkoEuDVImU3tRwW5gxay0f4Yuf/6Jie+nu8Rv2AAAAAAa0gwRQIhAJbmjZTTdOOmiO0uZgUon4EXJUCrqrX2zEMcIxkZhgdGAiB17k5kyGftnTadAamzXYsWiaghvo1yn/9/s9/MddFvZAEhAoHS5AumQi/Je2H9VkO+6D3XSdg2kzntx5XXs/AOlsaB/f///wLvAgAAAAAAABl2qRTkJx756aA6ibmBxz09aTbS9vzMBois6AMAAAAAAAAZdqkUEgrXhUFSkB6+smmsts7yDnGzz1mIrOoZCAAiBgPGm5BfckKzaIEi8GlRM5oe4A2mUvbsxlJ+pmMhRsrOYhgAAAAALAAAgAAAAIAAAACAAAAAAAAAAAAAAA==' ,
97+ ) ;
98+ }
9199 } ) ;
92100
93101 it ( 'can create PSBT base64 without signature for HW wallet ypub' , async ( ) => {
@@ -303,6 +311,29 @@ describe('Watch only wallet', () => {
303311 assert . ok ( w . useWithHardwareWalletEnabled ( ) ) ;
304312 } ) ;
305313
314+ it ( 'can import taproot BIP86 from keystone with zpub instead of xpub' , async ( ) => {
315+ const w = new WatchOnlyWallet ( ) ;
316+ w . setSecret (
317+ JSON . stringify ( {
318+ ExtPubKey : 'zpub6rxQT4vrGrdLmFicJZnLxx1odj1C8xNtHW5pW84hMSXdtoFnCbqBFJm3bF5PrwYL5ScxFhdzRuv3pb9beyoraQLMuQWkV9faGuxstBPgLw4' ,
319+ MasterFingerprint : 'B68AF6E4' ,
320+ AccountKeyPath : "m/86'/0'/0'" ,
321+ } ) ,
322+ ) ;
323+ w . init ( ) ;
324+ assert . ok ( w . valid ( ) ) ;
325+ assert . strictEqual (
326+ w . getSecret ( ) ,
327+ 'zpub6rxQT4vrGrdLmFicJZnLxx1odj1C8xNtHW5pW84hMSXdtoFnCbqBFJm3bF5PrwYL5ScxFhdzRuv3pb9beyoraQLMuQWkV9faGuxstBPgLw4' ,
328+ ) ;
329+ assert . strictEqual ( w . getMasterFingerprintHex ( ) , 'B68AF6E4' . toLowerCase ( ) ) ;
330+ assert . strictEqual ( w . getLabel ( ) , 'Wallet' ) ;
331+ assert . strictEqual ( w . getDerivationPath ( ) , "m/86'/0'/0'" ) ;
332+ assert . ok ( w . _getExternalAddressByIndex ( 0 ) . startsWith ( 'bc1p' ) , `not taproot address generated: ${ w . _getExternalAddressByIndex ( 0 ) } ` ) ;
333+ assert . ok ( w . allowMasterFingerprint ( ) ) ;
334+ // assert.ok(w.useWithHardwareWalletEnabled());
335+ } ) ;
336+
306337 it ( 'can import zpub with master fingerprint and derivation path' , async ( ) => {
307338 const w = new WatchOnlyWallet ( ) ;
308339 w . setSecret ( require ( 'fs' ) . readFileSync ( './tests/unit/fixtures/skeleton-walletdescriptor.txt' , 'ascii' ) ) ;
@@ -389,6 +420,72 @@ describe('Watch only wallet', () => {
389420 ) ;
390421
391422 assert . ok ( w . _getExternalAddressByIndex ( 0 ) . startsWith ( 'bc1p' ) , 'not taproot address, got: ' + w . _getExternalAddressByIndex ( 0 ) ) ;
423+ assert . ok ( w . allowMasterFingerprint ( ) ) ;
424+ assert . ok ( ! w . useWithHardwareWalletEnabled ( ) ) ;
425+ }
426+ } ) ;
427+
428+ it ( 'can import BIP86 (taproot) wallet descriptor but with zpub instead of xpub' , async ( ) => {
429+ const w = new WatchOnlyWallet ( ) ;
430+ w . setSecret (
431+ "tr([b68af6e4/86'/0'/0']zpub6rxQT4vrGrdLmFicJZnLxx1odj1C8xNtHW5pW84hMSXdtoFnCbqBFJm3bF5PrwYL5ScxFhdzRuv3pb9beyoraQLMuQWkV9faGuxstBPgLw4)" ,
432+ ) ;
433+ w . init ( ) ;
434+ assert . ok ( w . valid ( ) ) ;
435+
436+ assert . strictEqual ( w . getMasterFingerprintHex ( ) , 'b68af6e4' ) ;
437+ assert . strictEqual ( w . getDerivationPath ( ) , "m/86'/0'/0'" ) ;
438+
439+ assert . strictEqual (
440+ w . getSecret ( ) ,
441+ 'zpub6rxQT4vrGrdLmFicJZnLxx1odj1C8xNtHW5pW84hMSXdtoFnCbqBFJm3bF5PrwYL5ScxFhdzRuv3pb9beyoraQLMuQWkV9faGuxstBPgLw4' ,
442+ ) ;
443+
444+ assert . ok ( w . _getExternalAddressByIndex ( 0 ) . startsWith ( 'bc1p' ) , 'not taproot address, got: ' + w . _getExternalAddressByIndex ( 0 ) ) ;
445+
446+ assert . ok ( ! w . useWithHardwareWalletEnabled ( ) ) ;
447+ } ) ;
448+
449+ it ( 'can import BIP86 (taproot) wallet descriptor and create transaction' , async ( ) => {
450+ for ( const cleanupInternals of [ false , true ] ) {
451+ const w = new WatchOnlyWallet ( ) ;
452+ // MNEMONICS_KEYSTONE
453+ w . setSecret (
454+ "tr([b68af6e4/86'/0'/0']zpub6rxQT4vrGrdLmFicJZnLxx1odj1C8xNtHW5pW84hMSXdtoFnCbqBFJm3bF5PrwYL5ScxFhdzRuv3pb9beyoraQLMuQWkV9faGuxstBPgLw4)" ,
455+ ) ;
456+ w . init ( ) ;
457+ assert . ok ( w . valid ( ) ) ;
458+
459+ assert . strictEqual ( w . getMasterFingerprintHex ( ) , 'b68af6e4' ) ;
460+ assert . strictEqual ( w . getDerivationPath ( ) , "m/86'/0'/0'" ) ;
461+
462+ assert . strictEqual (
463+ w . getSecret ( ) ,
464+ 'zpub6rxQT4vrGrdLmFicJZnLxx1odj1C8xNtHW5pW84hMSXdtoFnCbqBFJm3bF5PrwYL5ScxFhdzRuv3pb9beyoraQLMuQWkV9faGuxstBPgLw4' ,
465+ ) ;
466+
467+ assert . ok ( w . _getExternalAddressByIndex ( 0 ) . startsWith ( 'bc1p' ) , 'not taproot address, got: ' + w . _getExternalAddressByIndex ( 0 ) ) ;
468+
469+ const utxos = [
470+ {
471+ height : 923789 ,
472+ value : 10108 ,
473+ address : 'bc1pyren45uwytsghuxelahgyjflrx9dhq9zhavangrcmw2avfre6spqtwxgm4' ,
474+ txid : 'dd8a90cfef8b5966781cfaddf8a5e8f1e2dce12e7ceed25c6d329c1df2e17c4f' ,
475+ vout : 0 ,
476+ wif : false ,
477+ confirmations : 7 ,
478+ } ,
479+ ] ;
480+
481+ if ( cleanupInternals ) {
482+ // these might be purged when preparing for serialization before saving to disk
483+ w . _hdWalletInstance . _node0 = undefined ;
484+ w . _hdWalletInstance . _node1 = undefined ;
485+ }
486+
487+ const { psbt } = w . createTransaction ( utxos , [ { address : '13HaCAB4jf7FYSZexJxoczyDDnutzZigjS' } ] , 1 , w . _getInternalAddressByIndex ( 0 ) ) ;
488+ assert . ok ( psbt ) ;
392489
393490 assert . ok ( ! w . useWithHardwareWalletEnabled ( ) ) ;
394491 }
0 commit comments