@@ -7,144 +7,150 @@ import {
77 WalletAddress , Tx , SignedTx , BtcAccount , Step ,
88 XverseTx ,
99} from '../types' ;
10+ import { validateAddress } from '../utils' ;
1011
1112export default class XverseService extends WalletService {
12- satsBtcNetwork : BitcoinNetworkType ;
13+ satsBtcNetwork : BitcoinNetworkType ;
1314
14- constructor ( ) {
15- super ( ) ;
16- switch ( this . network ) {
17- case constants . BTC_NETWORK_MAINNET :
18- this . satsBtcNetwork = BitcoinNetworkType . Mainnet ;
19- break ;
20- default :
21- this . satsBtcNetwork = BitcoinNetworkType . Testnet ;
22- break ;
23- }
24- }
15+ btcAccounts : BtcAccount [ ] = [ ] ;
2516
26- async getAccountAddresses ( ) : Promise < WalletAddress [ ] > {
27- // @ts -expect-error method type not provided
28- const permissions = await Wallet . request ( 'wallet_getCurrentPermissions' , undefined ) ;
29- if ( permissions . status !== 'success' ) {
30- // @ts -expect-error method type not provided
31- await Wallet . request ( 'wallet_requestPermissions' , undefined ) ;
32- }
33- return new Promise < WalletAddress [ ] > ( ( resolve , reject ) => {
34- const walletAddresses : WalletAddress [ ] = [ ] ;
35- const payload = {
36- purposes : [ 'payment' ] as AddressPurpose [ ] ,
37- message : 'Welcome to the Powpeg app, please select your Bitcoin account to start.' ,
38- network : {
39- type : this . satsBtcNetwork ,
40- } ,
41- } ;
42- Wallet . request ( 'getAddresses' , payload )
43- . then ( ( response ) => {
44- if ( response . status === 'error' ) {
45- reject ( new Error ( response . error . message ) ) ;
46- } else {
47- response . result . addresses
48- . forEach ( ( addr : { address : string ; publicKey : string ; } ) => {
49- walletAddresses . push ( {
50- address : addr . address ,
51- publicKey : addr . publicKey ,
52- derivationPath : '' ,
53- } ) ;
54- } ) ;
55- }
56- resolve ( walletAddresses ) ;
57- } )
58- . catch ( reject ) ;
59- } ) ;
60- }
17+ constructor ( ) {
18+ super ( ) ;
19+ switch ( this . network ) {
20+ case constants . BTC_NETWORK_MAINNET :
21+ this . satsBtcNetwork = BitcoinNetworkType . Mainnet ;
22+ break ;
23+ default :
24+ this . satsBtcNetwork = BitcoinNetworkType . Testnet ;
25+ break ;
26+ }
27+ }
28+
29+ async getAccountAddresses ( ) : Promise < WalletAddress [ ] > {
30+ // @ts -expect-error method type not provided
31+ const permissions = await Wallet . request ( 'wallet_getCurrentPermissions' , undefined ) ;
32+ if ( permissions . status !== 'success' ) {
33+ // @ts -expect-error method type not provided
34+ await Wallet . request ( 'wallet_requestPermissions' , undefined ) ;
35+ }
36+ return new Promise < WalletAddress [ ] > ( ( resolve , reject ) => {
37+ const walletAddresses : WalletAddress [ ] = [ ] ;
38+ const payload = {
39+ purposes : [ 'payment' ] as AddressPurpose [ ] ,
40+ message : 'Welcome to the Powpeg app, please select your Bitcoin account to start.' ,
41+ network : {
42+ type : this . satsBtcNetwork ,
43+ } ,
44+ } ;
45+ Wallet . request ( 'getAddresses' , payload )
46+ . then ( ( response ) => {
47+ if ( response . status === 'error' ) {
48+ reject ( new Error ( response . error . message ) ) ;
49+ } else {
50+ response . result . addresses
51+ . forEach ( ( addr : { address : string ; publicKey : string ; } ) => {
52+ walletAddresses . push ( {
53+ address : addr . address ,
54+ publicKey : addr . publicKey ,
55+ derivationPath : '' ,
56+ } ) ;
57+ const { addressType } = validateAddress ( addr . address ) ;
58+ this . btcAccounts . push ( addressType as BtcAccount ) ;
59+ } ) ;
60+ }
61+ resolve ( walletAddresses ) ;
62+ } )
63+ . catch ( reject ) ;
64+ } ) ;
65+ }
6166
62- sign ( tx : Tx ) : Promise < SignedTx > {
63- const xverseTx = tx as XverseTx ;
64- return new Promise < SignedTx > ( ( resolve , reject ) => {
65- const signInputs : Record < string , number [ ] > = { } ;
66- xverseTx . inputs . forEach ( ( input : { address : string ; idx : number ; } , inputIdx : number ) => {
67- if ( signInputs [ input . address ] ) {
68- signInputs [ input . address ] . push ( inputIdx ) ;
67+ sign ( tx : Tx ) : Promise < SignedTx > {
68+ const xverseTx = tx as XverseTx ;
69+ return new Promise < SignedTx > ( ( resolve , reject ) => {
70+ const signInputs : Record < string , number [ ] > = { } ;
71+ xverseTx . inputs . forEach ( ( input : { address : string ; idx : number ; } , inputIdx : number ) => {
72+ if ( signInputs [ input . address ] ) {
73+ signInputs [ input . address ] . push ( inputIdx ) ;
74+ } else {
75+ signInputs [ input . address ] = [ inputIdx ] ;
76+ }
77+ } ) ;
78+ const signPsbtOptions = {
79+ psbt : xverseTx . base64UnsignedPsbt ,
80+ signInputs,
81+ broadcast : false ,
82+ } ;
83+ Wallet . request ( 'signPsbt' , signPsbtOptions )
84+ . then ( ( response ) => {
85+ if ( response . status === 'error' ) {
86+ reject ( new Error ( response . error . message ) ) ;
87+ } else {
88+ const signedPsbt = bitcoin . Psbt . fromBase64 ( response . result . psbt as string ) ;
89+ if ( ! signedPsbt . validateSignaturesOfAllInputs ( ) ) {
90+ reject ( new Error ( 'Invalid signature provided' ) ) ;
6991 } else {
70- signInputs [ input . address ] = [ inputIdx ] ;
92+ resolve ( {
93+ signedTx : signedPsbt . finalizeAllInputs ( ) . extractTransaction ( ) . toHex ( ) ,
94+ } ) ;
7195 }
72- } ) ;
73- const signPsbtOptions = {
74- psbt : xverseTx . base64UnsignedPsbt ,
75- signInputs,
76- broadcast : false ,
77- } ;
78- Wallet . request ( 'signPsbt' , signPsbtOptions )
79- . then ( ( response ) => {
80- if ( response . status === 'error' ) {
81- reject ( new Error ( response . error . message ) ) ;
82- } else {
83- const signedPsbt = bitcoin . Psbt . fromBase64 ( response . result . psbt as string ) ;
84- if ( ! signedPsbt . validateSignaturesOfAllInputs ( ) ) {
85- reject ( new Error ( 'Invalid signature provided' ) ) ;
86- } else {
87- resolve ( {
88- signedTx : signedPsbt . finalizeAllInputs ( ) . extractTransaction ( ) . toHex ( ) ,
89- } ) ;
90- }
91- }
92- } )
93- . catch ( ( ) => reject ( new Error ( 'Invalid psbt provided' ) ) ) ;
94- } ) ;
95- }
96+ }
97+ } )
98+ . catch ( ( ) => reject ( new Error ( 'Invalid psbt provided' ) ) ) ;
99+ } ) ;
100+ }
96101
97- isConnected ( ) : Promise < boolean > {
98- return Promise . resolve ( true ) ;
99- }
102+ isConnected ( ) : Promise < boolean > {
103+ return Promise . resolve ( true ) ;
104+ }
100105
101- reconnect ( ) : Promise < void > {
102- return new Promise < void > ( ( resolve , reject ) => {
103- this . getAccountAddresses ( )
104- . then ( ( ) => resolve ( ) )
105- . catch ( reject ) ;
106- } ) ;
107- }
106+ reconnect ( ) : Promise < void > {
107+ return new Promise < void > ( ( resolve , reject ) => {
108+ this . getAccountAddresses ( )
109+ . then ( ( ) => resolve ( ) )
110+ . catch ( reject ) ;
111+ } ) ;
112+ }
108113
109- // eslint-disable-next-line @typescript-eslint/no-unused-vars
110- getXpub ( accountType : BtcAccount , accountNumber : number ) : Promise < string > {
111- throw new Error ( 'Method not supported.' ) ;
112- }
114+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
115+ getXpub ( accountType : BtcAccount , accountNumber : number ) : Promise < string > {
116+ throw new Error ( 'Method not supported.' ) ;
117+ }
113118
114- areEnoughUnusedAddresses ( ) : boolean {
115- return this . addressesToFetch . segwit . lastIndex >= 1 ;
116- }
119+ areEnoughUnusedAddresses ( ) : boolean {
120+ return this . addressesToFetch . segwit . lastIndex >= 1 ;
121+ }
117122
118- availableAccounts ( ) : BtcAccount [ ] {
119- return [ BtcAccount . BITCOIN_SEGWIT_ADDRESS ] ;
120- }
123+ availableAccounts ( ) : BtcAccount [ ] {
124+ return this . btcAccounts ;
125+ return [ BtcAccount . BITCOIN_SEGWIT_ADDRESS , BtcAccount . BITCOIN_NATIVE_SEGWIT_ADDRESS ] ;
126+ }
121127
122- name ( ) : Record < 'formal_name' | 'short_name' | 'long_name' , string > {
123- return constants . WALLET_NAMES . XVERSE ;
124- }
128+ name ( ) : Record < 'formal_name' | 'short_name' | 'long_name' , string > {
129+ return constants . WALLET_NAMES . XVERSE ;
130+ }
125131
126- confirmationSteps ( ) : Step [ ] {
127- return [
128- {
129- title : 'Transaction information' ,
130- subtitle : '' ,
131- outputsToshow : {
132- opReturn : {
133- value : false ,
134- amount : true ,
135- } ,
136- change : {
137- address : true ,
138- amount : true ,
139- } ,
140- federation : {
141- address : true ,
142- amount : true ,
143- } ,
144- } ,
145- fullAmount : false ,
146- fee : true ,
132+ confirmationSteps ( ) : Step [ ] {
133+ return [
134+ {
135+ title : 'Transaction information' ,
136+ subtitle : '' ,
137+ outputsToshow : {
138+ opReturn : {
139+ value : false ,
140+ amount : true ,
141+ } ,
142+ change : {
143+ address : true ,
144+ amount : true ,
145+ } ,
146+ federation : {
147+ address : true ,
148+ amount : true ,
147149 } ,
148- ] ;
149- }
150+ } ,
151+ fullAmount : false ,
152+ fee : true ,
153+ } ,
154+ ] ;
155+ }
150156}
0 commit comments