@@ -13,6 +13,7 @@ import {
1313 NoAmountSpecifiedError ,
1414 PendingFundsError
1515} from 'edge-core-js/types'
16+ import type { WalletBackend } from 'react-native-monero-lwsf'
1617import { TransactionDirection } from 'react-native-monero-lwsf'
1718import { base64 , base64url } from 'rfc4648'
1819
@@ -36,13 +37,15 @@ import {
3637 asMoneroPrivateKeys ,
3738 asMoneroUserSettings ,
3839 asMoneroWalletOtherData ,
40+ asMoneroWalletSettings ,
3941 asSafeMoneroWalletInfo ,
4042 LoginResponse ,
4143 MoneroInitOptions ,
4244 MoneroNetworkInfo ,
4345 MoneroPrivateKeys ,
4446 MoneroUserSettings ,
4547 MoneroWalletOtherData ,
48+ MoneroWalletSettings ,
4649 SafeMoneroWalletInfo ,
4750 translateFee
4851} from './moneroTypes'
@@ -54,6 +57,7 @@ export class MoneroEngine extends CurrencyEngine<
5457> {
5558 networkInfo : MoneroNetworkInfo
5659 currentSettings : MoneroUserSettings
60+ currentWalletSettings : MoneroWalletSettings
5761 otherData ! : MoneroWalletOtherData
5862 initOptions : MoneroInitOptions
5963 unlockedBalance : string
@@ -63,6 +67,7 @@ export class MoneroEngine extends CurrencyEngine<
6367 private txSortOrder : 'asc' | 'desc' = 'asc'
6468 private unsubscribeWalletEvent ?: ( ) => void
6569 private abortKeysWait ?: ( ) => void
70+ private settingsChangeQueue : Promise < void > = Promise . resolve ( )
6671
6772 constructor (
6873 env : PluginEnvironment < MoneroNetworkInfo > ,
@@ -77,7 +82,12 @@ export class MoneroEngine extends CurrencyEngine<
7782
7883 this . unlockedBalance = '0'
7984
85+ // Shared across all wallets using this engine:
8086 this . currentSettings = asMoneroUserSettings ( opts . userSettings )
87+ // Unique to this particular wallet instance:
88+ this . currentWalletSettings = asMoneroWalletSettings (
89+ opts . walletSettings ?? { }
90+ )
8191
8292 // Singleton promise resolved once by the first syncNetwork call.
8393 // Stays resolved across restarts so onStart gets keys immediately.
@@ -98,36 +108,47 @@ export class MoneroEngine extends CurrencyEngine<
98108 base64 . parse ( this . walletId )
99109 )
100110
111+ const { backend } = this . currentWalletSettings
112+ this . log . warn ( 'Using backend:' , backend )
101113 const defaults = asMoneroUserSettings ( { } )
102- const daemonAddress = this . currentSettings . enableCustomServers
103- ? this . currentSettings . moneroLightwalletServer
104- : defaults . moneroLightwalletServer
114+ const daemonAddress =
115+ backend === 'lws'
116+ ? this . currentSettings . enableCustomServers
117+ ? this . currentSettings . moneroLightwalletServer
118+ : defaults . moneroLightwalletServer
119+ : this . currentSettings . enableCustomMonerod
120+ ? this . currentSettings . monerodServer
121+ : defaults . monerodServer
105122
106123 try {
107- // LWS setup: API key and login
108- const isEdgeLws = daemonAddress === this . networkInfo . edgeLwsServer
124+ // LWS-specific setup: API key and login
109125 let loginResult : LoginResponse | undefined
110- await this . tools . cppBridge . setLwsApiKey (
111- isEdgeLws ? this . initOptions . edgeApiKey : ''
112- )
113- if ( isEdgeLws ) {
114- loginResult = await this . loginToLwsServer (
115- daemonAddress ,
116- this . walletInfo . keys . moneroAddress ,
117- this . walletInfo . keys . moneroViewKeyPrivate
126+ if ( backend === 'lws' ) {
127+ const isEdgeLws = daemonAddress === this . networkInfo . edgeLwsServer
128+ await this . tools . cppBridge . setLwsApiKey (
129+ isEdgeLws ? this . initOptions . edgeApiKey : ''
118130 )
131+ if ( isEdgeLws ) {
132+ loginResult = await this . loginToLwsServer (
133+ daemonAddress ,
134+ this . walletInfo . keys . moneroAddress ,
135+ this . walletInfo . keys . moneroViewKeyPrivate
136+ )
137+ }
119138 }
120139
121140 // Resolve birthday height (never open a wallet with height 0)
122141 const birthdayHeight = await this . resolveBirthdayHeight (
123142 keys . birthdayHeight ,
143+ backend ,
124144 daemonAddress ,
145+ defaults . moneroLightwalletServer ,
125146 loginResult
126147 )
127148
128149 await this . tools . cppBridge . openWallet (
129150 base64UrlWalletId ,
130- 'lws' ,
151+ backend ,
131152 keys . moneroKey ,
132153 base64url . stringify ( base64 . parse ( keys . dataKey ) ) ,
133154 this . networkInfo . networkType ,
@@ -188,7 +209,9 @@ export class MoneroEngine extends CurrencyEngine<
188209 */
189210 private async resolveBirthdayHeight (
190211 height : number | undefined ,
212+ backend : WalletBackend ,
191213 daemonAddress : string ,
214+ edgeLwsServer : string ,
192215 loginResult ?: LoginResponse
193216 ) : Promise < number > {
194217 if ( height != null ) return height
@@ -198,12 +221,20 @@ export class MoneroEngine extends CurrencyEngine<
198221 return loginResult . start_height
199222 }
200223
201- // Fall back to getAddressInfo
224+ // For monerod wallets, fall back to the Edge LWS server
225+ const serverUrl = backend === 'lws' ? daemonAddress : edgeLwsServer
202226 const addressInfo = await this . getAddressInfo (
203- daemonAddress ,
227+ serverUrl ,
204228 this . walletInfo . keys . moneroAddress ,
205229 this . walletInfo . keys . moneroViewKeyPrivate
206230 )
231+
232+ if ( addressInfo . start_height === 0 ) {
233+ throw new Error (
234+ 'Cannot open wallet: birthdayHeight is 0. ' +
235+ 'The wallet creation height could not be determined.'
236+ )
237+ }
207238 return addressInfo . start_height
208239 }
209240
@@ -531,7 +562,7 @@ export class MoneroEngine extends CurrencyEngine<
531562 await this . clearBlockchainCache ( )
532563 await this . tools . cppBridge . deleteWallet (
533564 base64url . stringify ( base64 . parse ( this . walletId ) ) ,
534- 'lws'
565+ this . currentWalletSettings . backend
535566 )
536567 await this . startEngine ( )
537568 }
@@ -542,9 +573,30 @@ export class MoneroEngine extends CurrencyEngine<
542573 return
543574 }
544575
545- this . currentSettings = newSettings
546- await this . killEngine ( )
547- await this . startEngine ( )
576+ this . settingsChangeQueue = this . settingsChangeQueue . then ( async ( ) => {
577+ this . currentSettings = newSettings
578+ await this . killEngine ( )
579+ await this . startEngine ( )
580+ } )
581+ await this . settingsChangeQueue
582+ }
583+
584+ async changeWalletSettings ( walletSettings : JsonObject ) : Promise < void > {
585+ const newSettings = asMaybe ( asMoneroWalletSettings ) ( walletSettings )
586+ if (
587+ newSettings == null ||
588+ matchJson ( this . currentWalletSettings , newSettings )
589+ ) {
590+ return
591+ }
592+
593+ this . settingsChangeQueue = this . settingsChangeQueue . then ( async ( ) => {
594+ this . currentWalletSettings = newSettings
595+ await this . killEngine ( )
596+ await this . clearBlockchainCache ( )
597+ await this . startEngine ( )
598+ } )
599+ await this . settingsChangeQueue
548600 }
549601
550602 async getMaxSpendable ( edgeSpendInfo : EdgeSpendInfo ) : Promise < string > {
0 commit comments