diff --git a/src/bridge/LibcoreBridge.js b/src/bridge/LibcoreBridge.js index 81ce2cb8..789fbd1a 100644 --- a/src/bridge/LibcoreBridge.js +++ b/src/bridge/LibcoreBridge.js @@ -51,6 +51,11 @@ const LibcoreBridge: WalletBridge = { }, synchronize(account, { next, complete, error }) { + // FIXME TODO: + // - when you implement addPendingOperation you also here need to: + // - if there were pendingOperations that are now in operations, remove them as well. + // - if there are pendingOperations that is older than a threshold (that depends on blockchain speed typically) + // then we probably should trash them out? it's a complex question for UI ;(async () => { try { const rawAccount = encodeAccount(account) @@ -68,15 +73,6 @@ const LibcoreBridge: WalletBridge = { error(e) } })() - // FIXME TODO: use next(), to actually emit account updates..... - // - need to sync the balance - // - need to sync block height & block hash - // - need to sync operations. - // - once all that, need to set lastSyncDate to new Date() - // - when you implement addPendingOperation you also here need to: - // - if there were pendingOperations that are now in operations, remove them as well. - // - if there are pendingOperations that is older than a threshold (that depends on blockchain speed typically) - // then we probably should trash them out? it's a complex question for UI return { unsubscribe() { console.warn('LibcoreBridge: unsub sync not implemented') diff --git a/src/commands/libcoreSignAndBroadcast.js b/src/commands/libcoreSignAndBroadcast.js index a804f95a..ed852f05 100644 --- a/src/commands/libcoreSignAndBroadcast.js +++ b/src/commands/libcoreSignAndBroadcast.js @@ -63,7 +63,7 @@ const cmd: Command = createCommand( const signedTransaction = await core.signTransaction({ hwApp, transaction: builded, - sigHashType: `0x${sigHashType}`, + sigHashType: parseInt(sigHashType, 16).toString(), supportsSegwit: !!currency.supportsSegwit, isSegwit: account.isSegwit, }) diff --git a/src/commands/libcoreSyncAccount.js b/src/commands/libcoreSyncAccount.js index fd030939..a6a38ec6 100644 --- a/src/commands/libcoreSyncAccount.js +++ b/src/commands/libcoreSyncAccount.js @@ -8,14 +8,15 @@ import { syncAccount } from 'helpers/libcore' import withLibcore from 'helpers/withLibcore' type Input = { - core: Object, rawAccount: AccountRaw, } type Result = AccountRaw const cmd: Command = createCommand('libcoreSyncAccount', ({ rawAccount }) => - fromPromise(withLibcore(core => syncAccount({ rawAccount, core }))), + fromPromise( + withLibcore((core, njsWalletPool) => syncAccount({ rawAccount, core, njsWalletPool })), + ), ) export default cmd diff --git a/src/components/SideBar/Item.js b/src/components/SideBar/Item.js index 71e48124..932de6da 100644 --- a/src/components/SideBar/Item.js +++ b/src/components/SideBar/Item.js @@ -3,7 +3,7 @@ import React from 'react' import styled from 'styled-components' import { compose } from 'redux' -import { matchPath, withRouter } from 'react-router' +import { withRouter } from 'react-router' import { push } from 'react-router-redux' import { connect } from 'react-redux' @@ -91,13 +91,7 @@ function Item({ highlight, }: Props) { const { pathname } = location - const isActive = linkTo - ? linkTo === '/' - ? linkTo === pathname - : matchPath(pathname, { - path: linkTo, - }) - : false + const isActive = linkTo === pathname return ( { render() { const { pending, error, onClick } = this.props return ( - + diff --git a/src/helpers/accountId.js b/src/helpers/accountId.js new file mode 100644 index 00000000..b70b5cef --- /dev/null +++ b/src/helpers/accountId.js @@ -0,0 +1,16 @@ +// @flow + +type Params = { + type: string, + xpub: string, + walletName: string, +} + +export function encode({ type, xpub, walletName }: Params) { + return `${type}:${xpub}:${walletName}` +} + +export function decode(accountId: string) { + const [type, xpub, walletName] = accountId.split(':') + return { type, xpub, walletName } +} diff --git a/src/helpers/libcore.js b/src/helpers/libcore.js index 05e7b168..b50f5320 100644 --- a/src/helpers/libcore.js +++ b/src/helpers/libcore.js @@ -7,6 +7,8 @@ import { getCryptoCurrencyById } from '@ledgerhq/live-common/lib/helpers/currenc import type { AccountRaw, OperationRaw, OperationType } from '@ledgerhq/live-common/lib/types' import type { NJSAccount, NJSOperation } from '@ledgerhq/ledger-core/src/ledgercore_doc' +import * as accountId from 'helpers/accountId' + type Props = { core: Object, devicePath: string, @@ -80,6 +82,7 @@ async function scanAccountsOnDeviceBySegwit({ isSegwit, showNewAccount, }: { + core: Object, hwApp: Object, currencyId: string, onAccountScanned: AccountRaw => void, @@ -138,8 +141,6 @@ async function scanNextAccount(props: { showNewAccount, } = props - console.log(`>> Scanning account ${accountIndex} - isSegwit: ${isSegwit.toString()}`) // eslint-disable-line no-console - // create account only if account has not been scanned yet // if it has already been created, we just need to get it, and sync it const hasBeenScanned = accountIndex < accountsCount @@ -220,7 +221,6 @@ async function buildAccountRaw({ currencyId: string, accountIndex: number, core: Object, - hwApp: Object, // $FlowFixMe ops: NJSOperation[], }): Promise { @@ -260,7 +260,7 @@ async function buildAccountRaw({ } const rawAccount: AccountRaw = { - id: xpub, // FIXME for account id you might want to prepend the crypto currency id to this because it's not gonna be unique. + id: accountId.encode({ type: 'libcore', xpub, walletName: wallet.getName() }), xpub, path: walletPath, name, @@ -319,26 +319,38 @@ function buildOperationRaw({ } } -export async function syncAccount({ rawAccount }: { rawAccount: AccountRaw }) { - // AWWWWW.. little problem here. - // - // we need to get account from libcore db. in order to do that we have to: - // 1) get wallet using a wallet identifier - // 2) get account from wallet using `rawAccount.index` - // - // Here is the problem: the wallet identifier is currently built like that: - // `${publicKey}__${currencyId}${isSegwit ? '_segwit' : ''}` - // - // and to get the `publicKey` we need the device. - // - // BUT we don't want the device to be required to access ledger-live - // SO.. it's a problem. - // - // Solution 1: store wallet identifier inside the Account (uurgh...) - // Solution 2: stop this project +export async function syncAccount({ + rawAccount, + core, + njsWalletPool, +}: { + core: Object, + rawAccount: AccountRaw, + njsWalletPool: Object, +}) { + const decodedAccountId = accountId.decode(rawAccount.id) + const njsWallet = await njsWalletPool.getWallet(decodedAccountId.walletName) + const njsAccount = await njsWallet.getAccount(rawAccount.index) - return { - ...rawAccount, - balance: 424242424242, - } + await core.syncAccount(njsAccount) + + const query = njsAccount.queryOperations() + const ops = await query.complete().execute() + const njsBalance = await njsAccount.getBalance() + + const syncedRawAccount = await buildAccountRaw({ + njsAccount, + isSegwit: rawAccount.isSegwit === true, + accountIndex: rawAccount.index, + wallet: njsWallet, + currencyId: rawAccount.currencyId, + core, + ops, + }) + + syncedRawAccount.balance = njsBalance.toLong() + + console.log(`Synced account [${syncedRawAccount.name}]: ${syncedRawAccount.balance}`) + + return syncedRawAccount } diff --git a/src/helpers/withLibcore.js b/src/helpers/withLibcore.js index 0fc08212..7b053ea4 100644 --- a/src/helpers/withLibcore.js +++ b/src/helpers/withLibcore.js @@ -2,23 +2,26 @@ const core = require('@ledgerhq/ledger-core') -let instanciated = false +let walletPool = null let queue = Promise.resolve() -// TODO: `core` should be typed -type Job = Object => Promise +// TODO: `core` and `NJSWalletPool` should be typed +type Job = (Object, Object) => any export default function withLibcore(job: Job) { - if (!instanciated) { - core.instanciateWalletPool({ + if (!walletPool) { + walletPool = core.instanciateWalletPool({ // sqlite files will be located in the app local data folder dbPath: process.env.LEDGER_LIVE_SQLITE_PATH, }) - instanciated = true } - queue = queue.then(() => { + // $FlowFixMe WTF is happening here, dudes. + queue = queue.then(async () => { try { - return job(core) + if (!walletPool) { + throw new Error('wallet pool not instanciated. this should not happen') + } + return job(core, walletPool) } catch (e) { console.log(`withLibCore: Error in job`, e) // eslint-disable-line no-console return Promise.resolve()