2018-12-03 18:04:57 +00:00
|
|
|
/* @flow */
|
|
|
|
|
|
|
|
import TrezorConnect from 'trezor-connect';
|
2018-12-28 15:15:18 +00:00
|
|
|
import * as BLOCKCHAIN from 'actions/constants/blockchain';
|
2018-12-03 18:04:57 +00:00
|
|
|
import * as PENDING from 'actions/constants/pendingTx';
|
|
|
|
import * as AccountsActions from 'actions/AccountsActions';
|
2020-03-30 18:44:17 +00:00
|
|
|
import { mergeAccount, enhanceTransaction } from 'utils/accountUtils';
|
2019-01-02 16:14:54 +00:00
|
|
|
import { observeChanges } from 'reducers/utils';
|
2018-12-03 18:04:57 +00:00
|
|
|
|
|
|
|
import type { BlockchainNotification } from 'trezor-connect';
|
|
|
|
import type {
|
|
|
|
Dispatch,
|
|
|
|
GetState,
|
|
|
|
PromiseAction,
|
2018-12-28 15:15:18 +00:00
|
|
|
PayloadAction,
|
|
|
|
Network,
|
|
|
|
BlockchainFeeLevel,
|
2018-12-03 18:04:57 +00:00
|
|
|
} from 'flowtype';
|
|
|
|
|
2019-03-04 12:33:02 +00:00
|
|
|
export const subscribe = (network: string): PromiseAction<void> => async (
|
|
|
|
dispatch: Dispatch,
|
|
|
|
getState: GetState
|
2020-03-30 18:44:17 +00:00
|
|
|
) => {
|
|
|
|
const accounts = getState()
|
2019-03-04 12:33:02 +00:00
|
|
|
.accounts.filter(a => a.network === network)
|
2020-03-30 18:44:17 +00:00
|
|
|
.map(a => ({ descriptor: a.descriptor }));
|
2018-12-03 18:04:57 +00:00
|
|
|
await TrezorConnect.blockchainSubscribe({
|
|
|
|
accounts,
|
|
|
|
coin: network,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2018-12-28 15:15:18 +00:00
|
|
|
// Get current known fee
|
|
|
|
// Use default values from appConfig.json if it wasn't downloaded from blockchain yet
|
|
|
|
// update them later, after onBlockMined event
|
2019-03-04 12:33:02 +00:00
|
|
|
export const getFeeLevels = (network: Network): PayloadAction<Array<BlockchainFeeLevel>> => (
|
|
|
|
dispatch: Dispatch,
|
|
|
|
getState: GetState
|
|
|
|
): Array<BlockchainFeeLevel> => {
|
2018-12-28 15:15:18 +00:00
|
|
|
const blockchain = getState().blockchain.find(b => b.shortcut === network.shortcut);
|
|
|
|
if (!blockchain || blockchain.feeLevels.length < 1) {
|
|
|
|
return network.fee.levels.map(level => ({
|
|
|
|
name: level.name,
|
|
|
|
value: level.value,
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
return blockchain.feeLevels;
|
|
|
|
};
|
|
|
|
|
2020-03-30 18:44:17 +00:00
|
|
|
export const onBlockMined = (network: Network): PromiseAction<void> => async (
|
2019-03-04 12:33:02 +00:00
|
|
|
dispatch: Dispatch,
|
|
|
|
getState: GetState
|
|
|
|
): Promise<void> => {
|
2020-03-30 18:44:17 +00:00
|
|
|
const blockchain = getState().blockchain.find(b => b.shortcut === network.shortcut);
|
2018-12-28 15:15:18 +00:00
|
|
|
if (!blockchain) return; // flowtype fallback
|
|
|
|
|
|
|
|
// if last update was more than 5 minutes ago
|
|
|
|
const now = new Date().getTime();
|
|
|
|
if (blockchain.feeTimestamp < now - 300000) {
|
|
|
|
const feeRequest = await TrezorConnect.blockchainEstimateFee({
|
2020-03-30 18:44:17 +00:00
|
|
|
request: {
|
|
|
|
feeLevels: 'smart',
|
|
|
|
},
|
|
|
|
coin: network.shortcut,
|
2018-12-28 15:15:18 +00:00
|
|
|
});
|
2019-01-02 16:14:54 +00:00
|
|
|
if (feeRequest.success && observeChanges(blockchain.feeLevels, feeRequest.payload)) {
|
|
|
|
// check if downloaded fee levels are different
|
2018-12-28 15:15:18 +00:00
|
|
|
dispatch({
|
|
|
|
type: BLOCKCHAIN.UPDATE_FEE,
|
2020-03-30 18:44:17 +00:00
|
|
|
shortcut: network.shortcut,
|
|
|
|
feeLevels: feeRequest.payload.levels.map(l => ({
|
|
|
|
name: 'Normal',
|
|
|
|
value: l.feePerUnit,
|
|
|
|
})),
|
2018-12-28 15:15:18 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: check for blockchain rollbacks here!
|
2018-12-20 13:14:25 +00:00
|
|
|
|
2020-03-30 18:44:17 +00:00
|
|
|
const accounts = getState().accounts.filter(a => a.network === network.shortcut);
|
2019-05-17 15:41:00 +00:00
|
|
|
if (accounts.length === 0) return;
|
|
|
|
|
2020-03-30 18:44:17 +00:00
|
|
|
const bundle = accounts.map(a => ({ descriptor: a.descriptor, coin: network.shortcut }));
|
|
|
|
const response = await TrezorConnect.getAccountInfo({ bundle });
|
|
|
|
|
|
|
|
if (!response.success) return;
|
|
|
|
|
|
|
|
response.payload.forEach((info, i) => {
|
|
|
|
dispatch(
|
|
|
|
AccountsActions.update(mergeAccount(info, accounts[i], network, blockchain.block))
|
|
|
|
);
|
2019-05-17 15:41:00 +00:00
|
|
|
});
|
2018-12-03 18:04:57 +00:00
|
|
|
};
|
|
|
|
|
2019-03-04 12:33:02 +00:00
|
|
|
export const onNotification = (
|
2020-03-30 18:44:17 +00:00
|
|
|
payload: BlockchainNotification,
|
|
|
|
network: Network
|
2019-03-04 12:33:02 +00:00
|
|
|
): PromiseAction<void> => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
2020-03-30 18:44:17 +00:00
|
|
|
const { descriptor, tx } = payload.notification;
|
|
|
|
const account = getState().accounts.find(a => a.descriptor === descriptor);
|
|
|
|
const blockchain = getState().blockchain.find(b => b.shortcut === network.shortcut);
|
|
|
|
if (!account || !blockchain) return;
|
2018-12-03 18:04:57 +00:00
|
|
|
|
2020-03-30 18:44:17 +00:00
|
|
|
if (!tx.blockHeight) {
|
2018-12-03 18:04:57 +00:00
|
|
|
dispatch({
|
|
|
|
type: PENDING.ADD,
|
2020-03-30 18:44:17 +00:00
|
|
|
payload: enhanceTransaction(account, tx, network),
|
2018-12-03 18:04:57 +00:00
|
|
|
});
|
2019-01-04 12:58:34 +00:00
|
|
|
} else {
|
2018-12-03 18:04:57 +00:00
|
|
|
dispatch({
|
|
|
|
type: PENDING.TX_RESOLVED,
|
2020-03-30 18:44:17 +00:00
|
|
|
hash: tx.txid,
|
2018-12-03 18:04:57 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-03-30 18:44:17 +00:00
|
|
|
const response = await TrezorConnect.getAccountInfo({
|
|
|
|
descriptor: account.descriptor,
|
|
|
|
coin: account.network,
|
|
|
|
});
|
2019-11-01 11:15:30 +00:00
|
|
|
|
2020-03-30 18:44:17 +00:00
|
|
|
if (!response.success) return;
|
2019-04-09 12:20:36 +00:00
|
|
|
|
2020-03-30 18:44:17 +00:00
|
|
|
dispatch(
|
|
|
|
AccountsActions.update(mergeAccount(response.payload, account, network, blockchain.block))
|
|
|
|
);
|
2018-12-03 18:04:57 +00:00
|
|
|
};
|