From 3d8f64465ab2b451950a9e7160a96b2080dcc5d8 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 30 Oct 2019 16:26:17 +0100 Subject: [PATCH 01/11] add "reconnectionAttempts" to blockchain reducer --- src/reducers/BlockchainReducer.js | 32 ++++++------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/src/reducers/BlockchainReducer.js b/src/reducers/BlockchainReducer.js index 865f1f2f..d6a1e029 100644 --- a/src/reducers/BlockchainReducer.js +++ b/src/reducers/BlockchainReducer.js @@ -17,6 +17,7 @@ export type BlockchainNetwork = { feeLevels: Array, connected: boolean, connecting: boolean, + reconnectionAttempts: number, block: number, }; @@ -41,30 +42,7 @@ const onStartSubscribe = (state: State, shortcut: string): State => { shortcut, connected: false, connecting: true, - block: 0, - feeTimestamp: 0, - feeLevels: [], - }, - ]); -}; - -const onFailSubscribe = (state: State, shortcut: string): State => { - const network = state.find(b => b.shortcut === shortcut); - if (network) { - const others = state.filter(b => b !== network); - return others.concat([ - { - ...network, - connecting: false, - }, - ]); - } - - return state.concat([ - { - shortcut, - connected: false, - connecting: false, + reconnectionAttempts: 0, block: 0, feeTimestamp: 0, feeLevels: [], @@ -84,6 +62,7 @@ const onConnect = (state: State, action: BlockchainConnect): State => { block: info.block, connected: true, connecting: false, + reconnectionAttempts: 0, }, ]); } @@ -93,6 +72,7 @@ const onConnect = (state: State, action: BlockchainConnect): State => { shortcut, connected: true, connecting: false, + reconnectionAttempts: 0, block: info.block, feeTimestamp: 0, feeLevels: [], @@ -110,6 +90,7 @@ const onError = (state: State, action: BlockchainError): State => { ...network, connected: false, connecting: false, + reconnectionAttempts: network.reconnectionAttempts + 1, }, ]); } @@ -119,6 +100,7 @@ const onError = (state: State, action: BlockchainError): State => { shortcut, connected: false, connecting: false, + reconnectionAttempts: 0, block: 0, feeTimestamp: 0, feeLevels: [], @@ -160,8 +142,6 @@ export default (state: State = initialState, action: Action): State => { switch (action.type) { case BLOCKCHAIN_ACTION.START_SUBSCRIBE: return onStartSubscribe(state, action.shortcut); - case BLOCKCHAIN_ACTION.FAIL_SUBSCRIBE: - return onFailSubscribe(state, action.shortcut); case BLOCKCHAIN_EVENT.CONNECT: return onConnect(state, action); case BLOCKCHAIN_EVENT.ERROR: From ce990f60c388395bf42cc876262e4eed9482cd31 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 30 Oct 2019 16:27:17 +0100 Subject: [PATCH 02/11] use BlockchainActions.subscribe insteadof DiscoveryActions.reconnect --- src/actions/DiscoveryActions.js | 27 +------------------ .../Context/components/Account/index.js | 10 ++++--- .../components/Account/index.messages.js | 4 +++ src/components/notifications/Context/index.js | 6 ++--- 4 files changed, 15 insertions(+), 32 deletions(-) diff --git a/src/actions/DiscoveryActions.js b/src/actions/DiscoveryActions.js index 06ee9e3e..1c749ab0 100644 --- a/src/actions/DiscoveryActions.js +++ b/src/actions/DiscoveryActions.js @@ -2,7 +2,6 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; import TrezorConnect, { UI } from 'trezor-connect'; -import * as BLOCKCHAIN_ACTION from 'actions/constants/blockchain'; import * as DISCOVERY from 'actions/constants/discovery'; import * as ACCOUNT from 'actions/constants/account'; import * as NOTIFICATION from 'actions/constants/notification'; @@ -10,7 +9,6 @@ import * as NOTIFICATION from 'actions/constants/notification'; import type { ThunkAction, AsyncAction, - PromiseAction, PayloadAction, GetState, Dispatch, @@ -331,30 +329,7 @@ const finish = (device: TrezorDevice, discoveryProcess: Discovery): AsyncAction }); }; -export const reconnect = (network: string, timeout: number = 30): PromiseAction => async ( - dispatch: Dispatch -): Promise => { - // Runs two promises. - // First promise is a subscribe action which will never resolve in case of completely lost connection to the backend - // That's why there is a second promise that rejects after the specified timeout. - return Promise.race([ - dispatch(BlockchainActions.subscribe(network)), - new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeout)), - ]) - .catch(() => { - // catch error from first promises that rejects (most likely timeout) - dispatch({ - type: BLOCKCHAIN_ACTION.FAIL_SUBSCRIBE, - shortcut: network, - }); - }) - .then(() => { - // dispatch restore when subscribe promise resolves - dispatch(restore()); - }); -}; - -// Called after DEVICE.CONNECT ('trezor-connect') or CONNECT.AUTH_DEVICE actions in WalletService +// Called after DEVICE.CONNECT ('trezor-connect') or CONNECT.AUTH_DEVICE or BLOCKCHAIN.CONNECT actions in WalletService // OR after BlockchainSubscribe in this.reconnect export const restore = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { // check if current url has "network" parameter diff --git a/src/components/notifications/Context/components/Account/index.js b/src/components/notifications/Context/components/Account/index.js index 48ce722a..331e2b82 100644 --- a/src/components/notifications/Context/components/Account/index.js +++ b/src/components/notifications/Context/components/Account/index.js @@ -14,17 +14,21 @@ export default (props: Props) => { if (notification.type === 'backend') { // special case: backend is down // TODO: this is a different component with "auto resolve" button + const inProgress = blockchain && blockchain.connecting; + const status = inProgress + ? l10nMessages.TR_RECONNECTING + : l10nMessages.TR_CONNECT_TO_BACKEND; return ( { - await props.blockchainReconnect(network.shortcut); + if (!inProgress) props.blockchainReconnect(network.shortcut); }, }, ]} diff --git a/src/components/notifications/Context/components/Account/index.messages.js b/src/components/notifications/Context/components/Account/index.messages.js index 436faa00..e39b19f9 100644 --- a/src/components/notifications/Context/components/Account/index.messages.js +++ b/src/components/notifications/Context/components/Account/index.messages.js @@ -7,6 +7,10 @@ const definedMessages: Messages = defineMessages({ id: 'TR_CONNECT_TO_BACKEND', defaultMessage: 'Connect', }, + TR_RECONNECTING: { + id: 'TR_RECONNECTING', + defaultMessage: 'Reconnecting...', + }, }); export default definedMessages; diff --git a/src/components/notifications/Context/index.js b/src/components/notifications/Context/index.js index ff2de3a3..1480ac77 100644 --- a/src/components/notifications/Context/index.js +++ b/src/components/notifications/Context/index.js @@ -7,7 +7,7 @@ import type { IntlShape } from 'react-intl'; import type { State, Dispatch } from 'flowtype'; -import { reconnect } from 'actions/DiscoveryActions'; +import { subscribe } from 'actions/BlockchainActions'; import * as NotificationActions from 'actions/NotificationActions'; import StaticNotifications from './components/Static'; @@ -29,7 +29,7 @@ export type StateProps = {| export type DispatchProps = {| close: typeof NotificationActions.close, - blockchainReconnect: typeof reconnect, + blockchainReconnect: typeof subscribe, |}; export type Props = {| ...OwnProps, ...StateProps, ...DispatchProps |}; @@ -52,7 +52,7 @@ const mapStateToProps = (state: State): StateProps => ({ const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({ close: bindActionCreators(NotificationActions.close, dispatch), - blockchainReconnect: bindActionCreators(reconnect, dispatch), + blockchainReconnect: bindActionCreators(subscribe, dispatch), }); export default injectIntl( From 4c3d0d3b92fb494220bec926e86da44549f70908 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 30 Oct 2019 16:27:37 +0100 Subject: [PATCH 03/11] remove FAIL_SUBSCRIBE action --- src/actions/constants/blockchain.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/actions/constants/blockchain.js b/src/actions/constants/blockchain.js index 3cd6b50d..3cdd0a2e 100644 --- a/src/actions/constants/blockchain.js +++ b/src/actions/constants/blockchain.js @@ -1,6 +1,5 @@ /* @flow */ export const START_SUBSCRIBE: 'blockchain__start_subscribe' = 'blockchain__start_subscribe'; -export const FAIL_SUBSCRIBE: 'blockchain__fail_subscribe' = 'blockchain__fail_subscribe'; export const READY: 'blockchain__ready' = 'blockchain__ready'; export const UPDATE_FEE: 'blockchain__update_fee' = 'blockchain__update_fee'; From eb20aee923b80880ea09760d6c0208590c6a9cff Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 30 Oct 2019 16:30:28 +0100 Subject: [PATCH 04/11] rewrite BlockchainActions.autoReconnect method --- src/actions/BlockchainActions.js | 26 ++++++-------------------- src/services/WalletService.js | 8 +++++++- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/actions/BlockchainActions.js b/src/actions/BlockchainActions.js index da2d9c66..1e5e12c7 100644 --- a/src/actions/BlockchainActions.js +++ b/src/actions/BlockchainActions.js @@ -1,9 +1,9 @@ /* @flow */ import * as BLOCKCHAIN from 'actions/constants/blockchain'; -import * as DiscoveryActions from 'actions/DiscoveryActions'; import * as EthereumBlockchainActions from 'actions/ethereum/BlockchainActions'; import * as RippleBlockchainActions from 'actions/ripple/BlockchainActions'; +import { resolveAfter } from 'utils/promiseUtils'; import type { Dispatch, GetState, PromiseAction, BlockchainFeeLevel } from 'flowtype'; import type { BlockchainBlock, BlockchainNotification, BlockchainError } from 'trezor-connect'; @@ -20,10 +20,6 @@ export type BlockchainAction = | { type: typeof BLOCKCHAIN.START_SUBSCRIBE, shortcut: string, - } - | { - type: typeof BLOCKCHAIN.FAIL_SUBSCRIBE, - shortcut: string, }; // Conditionally subscribe to blockchain backend @@ -153,23 +149,13 @@ const autoReconnect = (shortcut: string): PromiseAction => async ( dispatch: Dispatch, getState: GetState ): Promise => { - const MAX_ATTEMPTS = 4; let blockchain = getState().blockchain.find(b => b.shortcut === shortcut); - // try to automatically reconnect and wait after each attemp (5s * #attempt) untill max number of attemps is reached - for (let i = 0; i < MAX_ATTEMPTS; i++) { - const waitTime = 5000 * (i + 1); /// 5s * #attempt - if (!blockchain || blockchain.connected) { - break; - } + if (!blockchain || blockchain.reconnectionAttempts >= 5) return; - blockchain = getState().blockchain.find(b => b.shortcut === shortcut); + await resolveAfter(5000 * (blockchain.reconnectionAttempts + 1)); - // reconnect with 7s timeout - // eslint-disable-next-line no-await-in-loop - await dispatch(DiscoveryActions.reconnect(shortcut, 7000)); + blockchain = getState().blockchain.find(b => b.shortcut === shortcut); + if (!blockchain || blockchain.connected || blockchain.connecting) return; - // wait before next try - // eslint-disable-next-line no-await-in-loop - await new Promise(resolve => setTimeout(resolve, waitTime)); - } + await dispatch(subscribe(shortcut)); }; diff --git a/src/services/WalletService.js b/src/services/WalletService.js index 0578c84e..1e42ab55 100644 --- a/src/services/WalletService.js +++ b/src/services/WalletService.js @@ -1,5 +1,5 @@ /* @flow */ -import { DEVICE } from 'trezor-connect'; +import { DEVICE, BLOCKCHAIN } from 'trezor-connect'; import { LOCATION_CHANGE } from 'connected-react-router'; import * as WALLET from 'actions/constants/wallet'; import * as CONNECT from 'actions/constants/TrezorConnect'; @@ -132,6 +132,12 @@ const WalletService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispa api.dispatch(DiscoveryActions.stop()); } + // try to restore discovery on BLOCKCHAIN.CONNECT event + // edge case when backend throws error during discovery + if (action.type === BLOCKCHAIN.CONNECT) { + api.dispatch(DiscoveryActions.restore()); + } + return action; }; From ebb3f0302c82b128dce2f2910dc1c920daa2cd49 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 31 Oct 2019 12:56:28 +0100 Subject: [PATCH 05/11] Update TrezorConnectActions.js --- src/actions/TrezorConnectActions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/actions/TrezorConnectActions.js b/src/actions/TrezorConnectActions.js index dd5ef604..c1b1cf57 100644 --- a/src/actions/TrezorConnectActions.js +++ b/src/actions/TrezorConnectActions.js @@ -160,7 +160,7 @@ export const init = (): AsyncAction => async ( if (buildUtils.isDev()) { // eslint-disable-next-line window.__TREZOR_CONNECT_SRC = - typeof LOCAL === 'string' ? LOCAL : 'https://sisyfos.sldev.cz/connect/'; // eslint-disable-line no-underscore-dangle + typeof LOCAL === 'string' ? LOCAL : 'https://connect.corp.sldev.cz/fix/v7-ripple-lib-error/'; // eslint-disable-line no-underscore-dangle // window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://localhost:8088/'; // eslint-disable-line no-underscore-dangle window.TrezorConnect = TrezorConnect; } From 78e48873418c716f341e64399ee8d64bc6fd7b36 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 31 Oct 2019 13:13:42 +0100 Subject: [PATCH 06/11] Update TrezorConnectActions.js --- src/actions/TrezorConnectActions.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/actions/TrezorConnectActions.js b/src/actions/TrezorConnectActions.js index c1b1cf57..b80ff891 100644 --- a/src/actions/TrezorConnectActions.js +++ b/src/actions/TrezorConnectActions.js @@ -160,7 +160,9 @@ export const init = (): AsyncAction => async ( if (buildUtils.isDev()) { // eslint-disable-next-line window.__TREZOR_CONNECT_SRC = - typeof LOCAL === 'string' ? LOCAL : 'https://connect.corp.sldev.cz/fix/v7-ripple-lib-error/'; // eslint-disable-line no-underscore-dangle + typeof LOCAL === 'string' + ? LOCAL + : 'https://connect.corp.sldev.cz/fix/v7-ripple-lib-error/'; // eslint-disable-line no-underscore-dangle // window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://localhost:8088/'; // eslint-disable-line no-underscore-dangle window.TrezorConnect = TrezorConnect; } From aecfbb76df538079475fcefdc998f8687eb15bec Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 31 Oct 2019 15:50:19 +0100 Subject: [PATCH 07/11] enable pendingTxs in ripple send form --- .../Wallet/views/Account/Send/ripple/index.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/views/Wallet/views/Account/Send/ripple/index.js b/src/views/Wallet/views/Account/Send/ripple/index.js index e7b1d427..c9aa699e 100644 --- a/src/views/Wallet/views/Account/Send/ripple/index.js +++ b/src/views/Wallet/views/Account/Send/ripple/index.js @@ -489,14 +489,13 @@ const AccountSend = (props: Props) => { )} - {props.selectedAccount.pending.length > 0 || - (account.imported && ( - - ))} + {props.selectedAccount.pending.length > 0 && ( + + )} ); }; From b5f2692d385fe40d86fe9b2fc7739b294e367f2e Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 1 Nov 2019 12:15:30 +0100 Subject: [PATCH 08/11] fix XRP balance update if tx is sent between 2 Trezor accounts --- src/actions/ripple/BlockchainActions.js | 67 +++++++++++++++---------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/src/actions/ripple/BlockchainActions.js b/src/actions/ripple/BlockchainActions.js index 2c42911b..50b62141 100644 --- a/src/actions/ripple/BlockchainActions.js +++ b/src/actions/ripple/BlockchainActions.js @@ -161,31 +161,46 @@ export const onNotification = ( }); } - const updatedAccount = await TrezorConnect.rippleGetAccountInfo({ - account: { - descriptor: account.descriptor, - from: account.block, - history: false, - }, - coin: account.network, - }); + // In case of tx sent between two Trezor accounts there is a possibility that only 1 notification will be received + // therefore we need to find target account and update data for it as well + const accountsToUpdate = [account]; + const targetAddress = + notification.type === 'send' + ? notification.outputs[0].addresses[0] + : notification.inputs[0].addresses[0]; + + const targetAccount = getState().accounts.find(a => a.descriptor === targetAddress); + if (targetAccount) { + accountsToUpdate.push(targetAccount); + } + + accountsToUpdate.forEach(async a => { + const response = await TrezorConnect.rippleGetAccountInfo({ + account: { + descriptor: a.descriptor, + from: a.block, + history: false, + }, + coin: a.network, + }); - if (!updatedAccount.success) return; - - const empty = updatedAccount.payload.sequence <= 0 && updatedAccount.payload.balance === '0'; - dispatch( - AccountsActions.update({ - networkType: 'ripple', - ...account, - balance: toDecimalAmount(updatedAccount.payload.balance, network.decimals), - availableBalance: toDecimalAmount( - updatedAccount.payload.availableBalance, - network.decimals - ), - block: updatedAccount.payload.block, - sequence: updatedAccount.payload.sequence, - reserve: '0', - empty, - }) - ); + if (response.success) { + const updatedAccount = response.payload; + const empty = updatedAccount.sequence <= 0 && updatedAccount.balance === '0'; + dispatch( + AccountsActions.update({ + ...a, + balance: toDecimalAmount(updatedAccount.balance, network.decimals), + availableBalance: toDecimalAmount( + updatedAccount.availableBalance, + network.decimals + ), + block: updatedAccount.block, + sequence: updatedAccount.sequence, + reserve: '0', + empty, + }) + ); + } + }); }; From e41015b630a7e68b554abe62d1e45c2a17dbea64 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 1 Nov 2019 12:15:43 +0100 Subject: [PATCH 09/11] update tXRP explorer --- public/data/appConfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/data/appConfig.json b/public/data/appConfig.json index c9641f3d..3ffa08a4 100644 --- a/public/data/appConfig.json +++ b/public/data/appConfig.json @@ -128,8 +128,8 @@ ] }, "explorer": { - "tx": "https://sisyfos.trezor.io/ripple-testnet-explorer/tx/", - "address": "https://sisyfos.trezor.io/ripple-testnet-explorer/address/" + "tx": "https://test.bithomp.com/explorer/", + "address": "https://test.bithomp.com/explorer/" }, "hasSignVerify": false } From 35dc6b49359012dd451707ff02b7d108b4db87b8 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 1 Nov 2019 12:23:15 +0100 Subject: [PATCH 10/11] flow fix --- src/actions/ripple/BlockchainActions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/actions/ripple/BlockchainActions.js b/src/actions/ripple/BlockchainActions.js index 50b62141..e481fe1f 100644 --- a/src/actions/ripple/BlockchainActions.js +++ b/src/actions/ripple/BlockchainActions.js @@ -189,6 +189,7 @@ export const onNotification = ( const empty = updatedAccount.sequence <= 0 && updatedAccount.balance === '0'; dispatch( AccountsActions.update({ + networkType: 'ripple', ...a, balance: toDecimalAmount(updatedAccount.balance, network.decimals), availableBalance: toDecimalAmount( @@ -197,7 +198,7 @@ export const onNotification = ( ), block: updatedAccount.block, sequence: updatedAccount.sequence, - reserve: '0', + reserve: updatedAccount.reserve, empty, }) ); From f6171c560f6fb71b2129214247f79f9e878072c1 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 1 Nov 2019 13:50:54 +0100 Subject: [PATCH 11/11] fix XRP account update reserve to decimals --- src/actions/ripple/BlockchainActions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/actions/ripple/BlockchainActions.js b/src/actions/ripple/BlockchainActions.js index e481fe1f..8d19b9af 100644 --- a/src/actions/ripple/BlockchainActions.js +++ b/src/actions/ripple/BlockchainActions.js @@ -198,7 +198,7 @@ export const onNotification = ( ), block: updatedAccount.block, sequence: updatedAccount.sequence, - reserve: updatedAccount.reserve, + reserve: toDecimalAmount(updatedAccount.reserve, network.decimals), empty, }) );