import { Address , CeloTx , EncodedTransaction , ReadOnlyWallet , Signer } from '@celo/connect' ; import { sleep } from '@celo/utils/lib/async' ; import { EIP712TypedData } from '@celo/utils/lib/sign-typed-data-utils' ; import { WalletBase } from '@celo/wallet-base' ; /**
 * Abstract class representing a remote wallet that requires async initialization
 */ export abstract class RemoteWallet < TSigner extends Signer > extends WalletBase < TSigner > implements ReadOnlyWallet { private setupFinished = false ; private setupLocked = false ; private INIT_TIMEOUT_IN_MS = 10 * 1000 ; /**
     * Discovers wallet accounts and caches results in memory
     * Idempotent to ensure multiple calls are benign
     */ async init ( ) { if ( this . setupLocked || this . setupFinished ) { await this . initCompleted ( ) ; return ; } try { this . setupLocked = true ; const accountSigners = await this . loadAccountSigners ( ) ; accountSigners . forEach ( ( signer , address ) => { this . addSigner ( address , signer ) ; } ) ; this . setupFinished = true ; } finally { this . setupLocked = false ; } } /**
     * Monitor the initialization state until it reaches completion or time out
     */ private async initCompleted ( ) { let initTimeout = this . INIT_TIMEOUT_IN_MS ; const sleepIntervalInMs = 1 * 1000 ; while ( initTimeout > 0 ) { initTimeout -= sleepIntervalInMs ; if ( this . setupFinished ) { return ; } await sleep ( sleepIntervalInMs ) ; } throw new Error ( 'Initialization took too long. Ensure the wallet signer is available' ) ; } /**
     * Discover accounts and store mapping in accountSigners
     */ protected abstract loadAccountSigners ( ) ; /**
     * Get a list of accounts in the remote wallet
     */ getAccounts ( ) { this . initializationRequired ( ) ; return super . getAccounts ( ) ; } param address hasAccount ( address ? ) { this . initializationRequired ( ) ; return super . hasAccount ( address ) ; } param txParams async signTransaction ( txParams ) { this . initializationRequired ( ) ; return super . signTransaction ( txParams ) ; } param address param data return async signPersonalMessage ( address , data ) { this . initializationRequired ( ) ; return super . signPersonalMessage ( address , data ) ; } param address param typedData return async signTypedData ( address , typedData ) { this . initializationRequired ( ) ; return super . signTypedData ( address , typedData ) ; } protected initializationRequired ( ) { if ( ! this . setupFinished ) { throw new Error ( 'wallet needs to be initialized first' ) ; } } public isSetupFinished = ( ) => this . setupFinished ; }