import { ensureLeading0x , normalizeAddressWith0x , privateKeyToAddress , } from '@celo/utils/lib/address' ; import Wallet from 'ethereumjs-wallet' ; export enum ErrorMessages { KEYSTORE_ENTRY_EXISTS = 'Existing encrypted keystore for address' , NO_MATCHING_ENTRY = 'Keystore entry not found for address' , UNKNOWN_STRUCTURE = 'Unexpected keystore entry structure' } export abstract class KeystoreBase { /**
     * Handles encrytion and transformation between private keys <-> V3Keystore strings
     * See https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition
     * for more details on conventions around Web3 Secret Storage.
     */ param keystoreName param keystore abstract persistKeystore ( keystoreName , keystore ) ; param keystoreName abstract getRawKeystore ( keystoreName ) ; /**
     * Gets a list of the names of each entry in the keystore
     */ abstract getAllKeystoreNames ( ) ; param keystoreName abstract removeKeystore ( keystoreName ) ; param keystoreName returns getAddress ( keystoreName ) { const rawKeystore = this . getRawKeystore ( keystoreName ) ; try { const address = JSON . parse ( rawKeystore ) . address ; return ensureLeading0x ( address ) ; } catch ( e ) { throw new Error ( ErrorMessages . UNKNOWN_STRUCTURE ) ; } } returns async listKeystoreAddresses ( ) { return Object . keys ( await this . getAddressMap ( ) ) ; } returns async getAddressMap ( ) { const addressToFile = { } ; ( await this . getAllKeystoreNames ( ) ) . forEach ( ( file ) => ( addressToFile [ this . getAddress ( file ) ] = file ) ) ; return addressToFile ; } param privateKey param passphrase async importPrivateKey ( privateKey , passphrase ) { const address = normalizeAddressWith0x ( privateKeyToAddress ( privateKey ) ) ; if ( ( await this . listKeystoreAddresses ( ) ) . includes ( address ) ) { throw new Error ( ErrorMessages . KEYSTORE_ENTRY_EXISTS ) ; } const key = Buffer . from ( privateKey , 'hex' ) ; const wallet = Wallet . fromPrivateKey ( key ) ; const keystore = await wallet . toV3String ( passphrase ) ; const keystoreName = wallet . getV3Filename ( Date . now ( ) ) ; this . persistKeystore ( keystoreName , keystore ) ; } param address returns async getKeystoreName ( address ) { const keystoreName = ( await this . getAddressMap ( ) ) [ normalizeAddressWith0x ( address ) ] ; if ( keystoreName === undefined ) { throw new Error ( ErrorMessages . NO_MATCHING_ENTRY ) ; } return keystoreName ; } param address param passphrase returns async getPrivateKey ( address , passphrase ) { const rawKeystore = this . getRawKeystore ( await this . getKeystoreName ( address ) ) ; return ( await Wallet . fromV3 ( rawKeystore , passphrase ) ) . getPrivateKeyString ( ) ; } param address param oldPassphrase param newPassphrase async changeKeystorePassphrase ( address , oldPassphrase , newPassphrase ) { const keystoreName = await this . getKeystoreName ( address ) ; const rawKeystore = this . getRawKeystore ( keystoreName ) ; const newKeystore = await ( await Wallet . fromV3 ( rawKeystore , oldPassphrase ) ) . toV3String ( newPassphrase ) ; this . persistKeystore ( keystoreName , newKeystore ) ; } param address async deleteKeystore ( address ) { this . removeKeystore ( await this . getKeystoreName ( address ) ) ; } }