mirror of
https://github.com/trezor/trezor-wallet
synced 2024-12-01 04:38:15 +00:00
handle pending tx from blockchain notification
This commit is contained in:
parent
a32f0faf38
commit
ab4ab8b5a4
@ -3,6 +3,7 @@
|
|||||||
import TrezorConnect from 'trezor-connect';
|
import TrezorConnect from 'trezor-connect';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import * as BLOCKCHAIN from 'actions/constants/blockchain';
|
import * as BLOCKCHAIN from 'actions/constants/blockchain';
|
||||||
|
import * as PENDING from 'actions/constants/pendingTx';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
TrezorDevice,
|
TrezorDevice,
|
||||||
@ -99,7 +100,6 @@ export const onBlockMined = (payload: $ElementType<BlockchainBlock, 'payload'>):
|
|||||||
const fee = await TrezorConnect.blockchainGetFee({
|
const fee = await TrezorConnect.blockchainGetFee({
|
||||||
coin: network,
|
coin: network,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!fee.success) return;
|
if (!fee.success) return;
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
@ -141,10 +141,52 @@ export const onBlockMined = (payload: $ElementType<BlockchainBlock, 'payload'>):
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const onNotification = (payload: $ElementType<BlockchainNotification, 'payload'>): PromiseAction<void> => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||||
|
const { notification } = payload;
|
||||||
|
const account = getState().accounts.find(a => a.address === notification.address);
|
||||||
|
if (!account) return;
|
||||||
|
|
||||||
// not used for now, waiting for fix in blockbook
|
if (notification.status === 'pending') {
|
||||||
export const onNotification = (payload: $ElementType<BlockchainNotification, 'payload'>): PromiseAction<void> => async (/*dispatch: Dispatch, getState: GetState*/): Promise<void> => {
|
dispatch({
|
||||||
console.warn('OnBL', payload);
|
type: PENDING.ADD,
|
||||||
|
payload: {
|
||||||
|
type: notification.type,
|
||||||
|
hash: notification.hash,
|
||||||
|
network: account.network,
|
||||||
|
address: account.address,
|
||||||
|
currency: account.network,
|
||||||
|
amount: notification.amount,
|
||||||
|
total: notification.amount,
|
||||||
|
fee: notification.fee,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// todo: replace "send success" notification with link to explorer
|
||||||
|
} else if (notification.status === 'confirmed') {
|
||||||
|
dispatch({
|
||||||
|
type: PENDING.TX_RESOLVED,
|
||||||
|
hash: notification.hash,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatedAccount = await TrezorConnect.rippleGetAccountInfo({
|
||||||
|
account: {
|
||||||
|
address: account.address,
|
||||||
|
block: account.block,
|
||||||
|
history: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!updatedAccount.success) return;
|
||||||
|
|
||||||
|
dispatch(AccountsActions.update({
|
||||||
|
...account,
|
||||||
|
balance: updatedAccount.payload.balance,
|
||||||
|
block: updatedAccount.payload.block,
|
||||||
|
sequence: updatedAccount.payload.sequence,
|
||||||
|
}));
|
||||||
|
|
||||||
|
// todo: get transaction history here
|
||||||
|
// console.warn("OnBlAccount", account);
|
||||||
// this event can be triggered multiple times
|
// this event can be triggered multiple times
|
||||||
// // 1. check if pair [txid + address] is already in reducer
|
// // 1. check if pair [txid + address] is already in reducer
|
||||||
// const network: string = payload.coin.shortcut.toLowerCase();
|
// const network: string = payload.coin.shortcut.toLowerCase();
|
||||||
|
@ -13,12 +13,11 @@ export type PendingTxAction = {
|
|||||||
payload: PendingTx
|
payload: PendingTx
|
||||||
} | {
|
} | {
|
||||||
type: typeof PENDING.TX_RESOLVED,
|
type: typeof PENDING.TX_RESOLVED,
|
||||||
tx: PendingTx,
|
hash: string,
|
||||||
receipt?: Object,
|
|
||||||
} | {
|
} | {
|
||||||
type: typeof PENDING.TX_REJECTED,
|
type: typeof PENDING.TX_REJECTED,
|
||||||
tx: PendingTx,
|
hash: string,
|
||||||
} | {
|
} | {
|
||||||
type: typeof PENDING.TX_TOKEN_ERROR,
|
type: typeof PENDING.TX_TOKEN_ERROR,
|
||||||
tx: PendingTx,
|
hash: string,
|
||||||
}
|
}
|
@ -137,25 +137,24 @@ export const resolvePendingTransactions = (network: string): PromiseAction<void>
|
|||||||
const instance: Web3Instance = await dispatch(initWeb3(network));
|
const instance: Web3Instance = await dispatch(initWeb3(network));
|
||||||
const pending = getState().pending.filter(p => p.network === network);
|
const pending = getState().pending.filter(p => p.network === network);
|
||||||
pending.forEach(async (tx) => {
|
pending.forEach(async (tx) => {
|
||||||
const status = await instance.web3.eth.getTransaction(tx.id);
|
const status = await instance.web3.eth.getTransaction(tx.hash);
|
||||||
if (!status) {
|
if (!status) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: PENDING.TX_REJECTED,
|
type: PENDING.TX_REJECTED,
|
||||||
tx,
|
hash: tx.hash,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const receipt = await instance.web3.eth.getTransactionReceipt(tx.id);
|
const receipt = await instance.web3.eth.getTransactionReceipt(tx.hash);
|
||||||
if (receipt) {
|
if (receipt) {
|
||||||
if (status.gas !== receipt.gasUsed) {
|
if (status.gas !== receipt.gasUsed) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: PENDING.TX_TOKEN_ERROR,
|
type: PENDING.TX_TOKEN_ERROR,
|
||||||
tx,
|
hash: tx.hash,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
type: PENDING.TX_RESOLVED,
|
type: PENDING.TX_RESOLVED,
|
||||||
tx,
|
hash: tx.hash,
|
||||||
receipt,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,59 +4,55 @@ import * as PENDING from 'actions/constants/pendingTx';
|
|||||||
import * as SEND from 'actions/constants/send';
|
import * as SEND from 'actions/constants/send';
|
||||||
|
|
||||||
import type { TrezorDevice, Action } from 'flowtype';
|
import type { TrezorDevice, Action } from 'flowtype';
|
||||||
import type { SendTxAction } from 'actions/SendFormActions';
|
|
||||||
|
|
||||||
export type PendingTx = {
|
export type PendingTx = {
|
||||||
+type: 'send' | 'receive';
|
+type: 'send' | 'recv',
|
||||||
+id: string;
|
+hash: string,
|
||||||
+network: string;
|
+network: string,
|
||||||
+address: string;
|
+address: string,
|
||||||
+deviceState: string;
|
+currency: string,
|
||||||
+currency: string;
|
+amount: string,
|
||||||
+amount: string;
|
+total: string,
|
||||||
+total: string;
|
+fee: string,
|
||||||
+tx: any;
|
rejected?: boolean,
|
||||||
+nonce: number;
|
};
|
||||||
rejected: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type State = Array<PendingTx>;
|
export type State = Array<PendingTx>;
|
||||||
|
|
||||||
const initialState: State = [];
|
const initialState: State = [];
|
||||||
|
|
||||||
const add = (state: State, action: SendTxAction): State => {
|
// const add = (state: State, action: SendTxAction): State => {
|
||||||
const newState = [...state];
|
// const newState = [...state];
|
||||||
newState.push({
|
// newState.push({
|
||||||
type: 'send',
|
// type: 'send',
|
||||||
id: action.txid,
|
// id: action.txid,
|
||||||
network: action.account.network,
|
// network: action.account.network,
|
||||||
address: action.account.address,
|
// address: action.account.address,
|
||||||
deviceState: action.account.deviceState,
|
// deviceState: action.account.deviceState,
|
||||||
|
|
||||||
currency: action.selectedCurrency,
|
// currency: action.selectedCurrency,
|
||||||
amount: action.amount,
|
// amount: action.amount,
|
||||||
total: action.total,
|
// total: action.total,
|
||||||
tx: action.tx,
|
// tx: action.tx,
|
||||||
nonce: action.nonce,
|
// nonce: action.nonce,
|
||||||
rejected: false,
|
// rejected: false,
|
||||||
});
|
// });
|
||||||
return newState;
|
// return newState;
|
||||||
};
|
// };
|
||||||
|
|
||||||
/*
|
|
||||||
const addFromBloockbokNotifiaction = (state: State, payload: any): State => {
|
const addFromNotification = (state: State, payload: PendingTx): State => {
|
||||||
const newState = [...state];
|
const newState = [...state];
|
||||||
newState.push(payload);
|
newState.push(payload);
|
||||||
return newState;
|
return newState;
|
||||||
};
|
};
|
||||||
*/
|
|
||||||
|
|
||||||
const clear = (state: State, device: TrezorDevice): State => state.filter(tx => tx.deviceState !== device.state);
|
//const clear = (state: State, device: TrezorDevice): State => state.filter(tx => tx.deviceState !== device.state);
|
||||||
|
|
||||||
const remove = (state: State, id: string): State => state.filter(tx => tx.id !== id);
|
const remove = (state: State, hash: string): State => state.filter(tx => tx.hash !== hash);
|
||||||
|
|
||||||
const reject = (state: State, id: string): State => state.map((tx) => {
|
const reject = (state: State, hash: string): State => state.map((tx) => {
|
||||||
if (tx.id === id && !tx.rejected) {
|
if (tx.hash === hash && !tx.rejected) {
|
||||||
return { ...tx, rejected: true };
|
return { ...tx, rejected: true };
|
||||||
}
|
}
|
||||||
return tx;
|
return tx;
|
||||||
@ -64,21 +60,21 @@ const reject = (state: State, id: string): State => state.map((tx) => {
|
|||||||
|
|
||||||
export default function pending(state: State = initialState, action: Action): State {
|
export default function pending(state: State = initialState, action: Action): State {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case SEND.TX_COMPLETE:
|
// case SEND.TX_COMPLETE:
|
||||||
return add(state, action);
|
// return add(state, action);
|
||||||
|
|
||||||
case CONNECT.FORGET:
|
// case CONNECT.FORGET:
|
||||||
case CONNECT.FORGET_SINGLE:
|
// case CONNECT.FORGET_SINGLE:
|
||||||
case CONNECT.FORGET_SILENT:
|
// case CONNECT.FORGET_SILENT:
|
||||||
case CONNECT.RECEIVE_WALLET_TYPE:
|
// case CONNECT.RECEIVE_WALLET_TYPE:
|
||||||
return clear(state, action.device);
|
// return clear(state, action.device);
|
||||||
|
|
||||||
// case PENDING.ADD:
|
case PENDING.ADD:
|
||||||
// return add(state, action.payload);
|
return addFromNotification(state, action.payload);
|
||||||
case PENDING.TX_RESOLVED:
|
case PENDING.TX_RESOLVED:
|
||||||
return remove(state, action.tx.id);
|
return remove(state, action.hash);
|
||||||
case PENDING.TX_REJECTED:
|
case PENDING.TX_REJECTED:
|
||||||
return reject(state, action.tx.id);
|
return reject(state, action.hash);
|
||||||
|
|
||||||
case PENDING.FROM_STORAGE:
|
case PENDING.FROM_STORAGE:
|
||||||
return action.payload;
|
return action.payload;
|
||||||
|
@ -140,7 +140,7 @@ class PendingTransactions extends PureComponent<Props> {
|
|||||||
<H2>Pending transactions</H2>
|
<H2>Pending transactions</H2>
|
||||||
{this.getPendingTransactions().map(tx => (
|
{this.getPendingTransactions().map(tx => (
|
||||||
<TransactionWrapper
|
<TransactionWrapper
|
||||||
key={tx.id}
|
key={tx.hash}
|
||||||
>
|
>
|
||||||
<TransactionIcon
|
<TransactionIcon
|
||||||
textColor={() => this.getTransactionIconColors(tx).textColor}
|
textColor={() => this.getTransactionIconColors(tx).textColor}
|
||||||
@ -154,7 +154,7 @@ class PendingTransactions extends PureComponent<Props> {
|
|||||||
|
|
||||||
<TransactionName>
|
<TransactionName>
|
||||||
<StyledLink
|
<StyledLink
|
||||||
href={`${this.props.network.explorer.tx}${tx.id}`}
|
href={`${this.props.network.explorer.tx}${tx.hash}`}
|
||||||
isGray
|
isGray
|
||||||
>
|
>
|
||||||
{this.getTransactionName(tx)}
|
{this.getTransactionName(tx)}
|
||||||
|
Loading…
Reference in New Issue
Block a user