/* @flow */ import TrezorConnect from 'trezor-connect'; import EthereumjsUtil from 'ethereumjs-util'; import * as DISCOVERY from 'actions/constants/discovery'; import * as BlockchainActions from 'actions/ethereum/BlockchainActions'; import type { PromiseAction, Dispatch, GetState, TrezorDevice, Network, Account } from 'flowtype'; import type { Discovery } from 'reducers/DiscoveryReducer'; export type DiscoveryStartAction = { type: typeof DISCOVERY.START, networkType: 'ethereum', network: Network, device: TrezorDevice, publicKey: string, chainCode: string, basePath: Array, }; // first iteration // generate public key for this account // start discovery process export const begin = ( device: TrezorDevice, network: Network ): PromiseAction => async (): Promise => { // get xpub from TREZOR const response = await TrezorConnect.getPublicKey({ device: { path: device.path, instance: device.instance, state: device.state, }, path: network.bip44, keepSession: true, // acquire and hold session //useEmptyPassphrase: !device.instance, useEmptyPassphrase: device.useEmptyPassphrase, network: network.name, }); // handle TREZOR response error if (!response.success) { throw new Error(response.payload.error); } const basePath: Array = response.payload.path; return { type: DISCOVERY.START, networkType: 'ethereum', network, device, publicKey: response.payload.publicKey, chainCode: response.payload.chainCode, basePath, }; }; export const discoverAccount = ( device: TrezorDevice, discoveryProcess: Discovery ): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { const { config } = getState().localStorage; const network = config.networks.find(c => c.shortcut === discoveryProcess.network); if (!network) throw new Error('Discovery network not found'); const derivedKey = discoveryProcess.hdKey.derive(`m/${discoveryProcess.accountIndex}`); const path = discoveryProcess.basePath.concat(discoveryProcess.accountIndex); const publicAddress: string = EthereumjsUtil.publicToAddress( derivedKey.publicKey, true ).toString('hex'); const ethAddress: string = EthereumjsUtil.toChecksumAddress(publicAddress); // TODO: check if address was created before const account = await dispatch( BlockchainActions.discoverAccount(device, ethAddress, network.shortcut) ); // const accountIsEmpty = account.transactions <= 0 && account.nonce <= 0 && account.balance === '0'; const empty = account.nonce <= 0 && account.balance === '0'; return { imported: false, index: discoveryProcess.accountIndex, network: network.shortcut, deviceID: device.features ? device.features.device_id : '0', deviceState: device.state || '0', accountPath: path, descriptor: ethAddress, balance: account.balance, availableBalance: account.balance, block: account.block, transactions: account.transactions, empty, networkType: 'ethereum', nonce: account.nonce, }; };