get past and new Transfer events for in/out txs
This commit is contained in:
parent
c1ec94fa6c
commit
affa0582a1
|
@ -3,7 +3,7 @@ import { RootState } from '../reducers';
|
||||||
import { Contract } from 'web3-eth-contract';
|
import { Contract } from 'web3-eth-contract';
|
||||||
import Web3 from 'web3';
|
import Web3 from 'web3';
|
||||||
import { TransactionReceipt } from 'web3-core';
|
import { TransactionReceipt } from 'web3-core';
|
||||||
// import { loadBalance } from './wallet';
|
import { loadWalletBalance } from './wallet';
|
||||||
import { loadBlock } from './blocks';
|
import { loadBlock } from './blocks';
|
||||||
import { abi as keycardWalletABI } from '../contracts/KeycardWallet';
|
import { abi as keycardWalletABI } from '../contracts/KeycardWallet';
|
||||||
import { addPadding } from "../utils";
|
import { addPadding } from "../utils";
|
||||||
|
@ -68,23 +68,6 @@ export const transactionConfirmed = (transactionHash: string): TxsTransactionCon
|
||||||
transactionHash,
|
transactionHash,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const watchPendingTransaction = (web3: Web3, dispatch: Dispatch, walletAddress: string | undefined, wallet: Contract, transactionHash: string) => {
|
|
||||||
web3.eth.getTransactionReceipt(transactionHash).then((tx: TransactionReceipt) => {
|
|
||||||
if (tx.status) {
|
|
||||||
dispatch(transactionConfirmed(transactionHash));
|
|
||||||
if (walletAddress !== undefined) {
|
|
||||||
// dispatch<any>(loadBalance(web3, walletAddress, wallet));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.setTimeout(() => watchPendingTransaction(web3, dispatch, walletAddress, wallet, transactionHash), 5000)
|
|
||||||
}).catch((error: string) => {
|
|
||||||
//FIXME: handle error
|
|
||||||
console.log("error", error)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const loadTransactions = (web3: Web3, erc20: Contract) => {
|
export const loadTransactions = (web3: Web3, erc20: Contract) => {
|
||||||
return (dispatch: Dispatch, getState: () => RootState) => {
|
return (dispatch: Dispatch, getState: () => RootState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
@ -93,38 +76,87 @@ export const loadTransactions = (web3: Web3, erc20: Contract) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wallet = new web3.eth.Contract(keycardWalletABI, walletAddress);
|
|
||||||
const topic = web3.utils.sha3("Transfer(address,address,uint256)");
|
|
||||||
const options = {
|
|
||||||
fromBlock: 0,
|
|
||||||
toBlock: "latest",
|
|
||||||
topics: [
|
|
||||||
topic,
|
|
||||||
null,
|
|
||||||
addPadding(64, walletAddress),
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
erc20.getPastEvents("allEvents", options).then((events: any) => {
|
|
||||||
events.forEach((event: any) => {
|
|
||||||
const values = event.returnValues;
|
|
||||||
dispatch<any>(loadBlock(event.blockNumber));
|
|
||||||
dispatch(transactionDiscovered("TopUp", event.id, event.blockNumber, event.transactionHash, false, values.from, walletAddress, values.value));
|
|
||||||
});
|
|
||||||
dispatch(transactionsLoaded());
|
|
||||||
});
|
|
||||||
|
|
||||||
dispatch(loadingTransactions());
|
|
||||||
|
|
||||||
const filter = {
|
|
||||||
to: walletAddress,
|
|
||||||
};
|
|
||||||
web3.eth.getBlockNumber().then((blockNumber: number) => {
|
web3.eth.getBlockNumber().then((blockNumber: number) => {
|
||||||
erc20.events.Transfer({filter: filter}).on('data', (event: any) => {
|
dispatch<any>(getPastTransactions(web3, erc20, walletAddress, blockNumber, "to"))
|
||||||
const values = event.returnValues;
|
dispatch<any>(getPastTransactions(web3, erc20, walletAddress, blockNumber, "from"))
|
||||||
dispatch(transactionDiscovered("TopUp", event.id, event.blockNumber, event.transactionHash, true, values.from, walletAddress, values.value));
|
|
||||||
watchPendingTransaction(web3, dispatch, walletAddress, wallet, event.transactionHash);
|
dispatch<any>(subscribeToTransactions(web3, erc20, walletAddress, blockNumber, "to"))
|
||||||
})
|
dispatch<any>(subscribeToTransactions(web3, erc20, walletAddress, blockNumber, "from"))
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ToOrFrom = "to" | "from";
|
||||||
|
|
||||||
|
const getPastTransactions = (web3: Web3, erc20: Contract, walletAddress: string, fromBlock: number, toOrFrom: ToOrFrom) => {
|
||||||
|
return (dispatch: Dispatch, getState: () => RootState) => {
|
||||||
|
const paddedWalletAddress = addPadding(64, walletAddress);
|
||||||
|
const eventType = toOrFrom == "to" ? "TopUp" : "NewPaymentRequest";
|
||||||
|
const topics: (null | string)[] = [null, null, null];
|
||||||
|
|
||||||
|
switch(toOrFrom) {
|
||||||
|
case "from":
|
||||||
|
topics[1] = paddedWalletAddress;
|
||||||
|
break;
|
||||||
|
case "to":
|
||||||
|
topics[2] = paddedWalletAddress;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
fromBlock: 0,
|
||||||
|
toBlock: "latest",
|
||||||
|
topics: topics,
|
||||||
|
};
|
||||||
|
|
||||||
|
dispatch(loadingTransactions());
|
||||||
|
erc20.getPastEvents("Transfer", options).then((events: any) => {
|
||||||
|
events.forEach((event: any) => {
|
||||||
|
const values = event.returnValues;
|
||||||
|
dispatch<any>(loadBlock(event.blockNumber));
|
||||||
|
dispatch(transactionDiscovered(eventType, event.id, event.blockNumber, event.transactionHash, false, values.from, walletAddress, values.value));
|
||||||
|
});
|
||||||
|
dispatch(transactionsLoaded());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const subscribeToTransactions = (web3: Web3, erc20: Contract, walletAddress: string, fromBlock: number, toOrFrom: ToOrFrom) => {
|
||||||
|
return (dispatch: Dispatch, getState: () => RootState) => {
|
||||||
|
const options = {
|
||||||
|
fromBlock: fromBlock,
|
||||||
|
filter: {
|
||||||
|
[toOrFrom]: walletAddress,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const eventType = toOrFrom == "to" ? "TopUp" : "NewPaymentRequest";
|
||||||
|
|
||||||
|
erc20.events.Transfer(options).on('data', (event: any) => {
|
||||||
|
const values = event.returnValues;
|
||||||
|
const pending = event.blockHash === null;
|
||||||
|
dispatch(transactionDiscovered(eventType, event.id, event.blockNumber, event.transactionHash, pending, values.from, walletAddress, values.value));
|
||||||
|
dispatch<any>(loadWalletBalance(web3, undefined));
|
||||||
|
if (pending) {
|
||||||
|
watchPendingTransaction(web3, dispatch, walletAddress, event.transactionHash);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const watchPendingTransaction = (web3: Web3, dispatch: Dispatch, walletAddress: string | undefined, transactionHash: string) => {
|
||||||
|
web3.eth.getTransactionReceipt(transactionHash).then((tx: TransactionReceipt) => {
|
||||||
|
if (tx.status) {
|
||||||
|
dispatch(transactionConfirmed(transactionHash));
|
||||||
|
if (walletAddress !== undefined) {
|
||||||
|
dispatch<any>(loadWalletBalance(web3, undefined));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.setTimeout(() => watchPendingTransaction(web3, dispatch, walletAddress, transactionHash), 5000)
|
||||||
|
}).catch((error: string) => {
|
||||||
|
//FIXME: handle error
|
||||||
|
console.log("error", error)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -279,10 +279,14 @@ const loadERC20Symbol = (web3: Web3, erc20: Contract) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadWalletBalance = (web3: Web3, erc20: Contract) => {
|
export const loadWalletBalance = (web3: Web3, _erc20: Contract | undefined) => {
|
||||||
return async (dispatch: Dispatch, getState: () => RootState) => {
|
return async (dispatch: Dispatch, getState: () => RootState) => {
|
||||||
const address = getState().wallet.walletAddress!;
|
const state = getState();
|
||||||
|
const address = state.wallet.walletAddress!;
|
||||||
|
const erc20 = _erc20 !== undefined ? _erc20 : new web3.eth.Contract(erc20DetailedABI, state.wallet.erc20Address!);
|
||||||
|
|
||||||
dispatch(loadingWalletBalance(address));
|
dispatch(loadingWalletBalance(address));
|
||||||
|
|
||||||
return erc20.methods.balanceOf(address).call().then((balance: string) => {
|
return erc20.methods.balanceOf(address).call().then((balance: string) => {
|
||||||
dispatch(balanceLoaded(balance, balance));
|
dispatch(balanceLoaded(balance, balance));
|
||||||
return erc20;
|
return erc20;
|
||||||
|
|
|
@ -12,7 +12,6 @@ export const VALID_NETWORK_ID = 3;
|
||||||
// export const VALID_NETWORK_ID = 5;
|
// export const VALID_NETWORK_ID = 5;
|
||||||
export const LOCAL_NETWORK_ID = 1337;
|
export const LOCAL_NETWORK_ID = 1337;
|
||||||
|
|
||||||
|
|
||||||
enum Web3Type {
|
enum Web3Type {
|
||||||
Generic,
|
Generic,
|
||||||
Remote,
|
Remote,
|
||||||
|
|
|
@ -39,7 +39,8 @@ const WalletsList = (props: Props) => {
|
||||||
{props.loading && <div className={classes.loading}>
|
{props.loading && <div className={classes.loading}>
|
||||||
<CircularProgress className={classes.progress} disableShrink></CircularProgress>
|
<CircularProgress className={classes.progress} disableShrink></CircularProgress>
|
||||||
</div>}
|
</div>}
|
||||||
{!props.loading && <List>
|
|
||||||
|
{<List>
|
||||||
{props.transactions.map((tx) => (
|
{props.transactions.map((tx) => (
|
||||||
<TransactionsListItem key={tx.id} id={tx.id} />
|
<TransactionsListItem key={tx.id} id={tx.id} />
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -33,7 +33,7 @@ const mapStateToProps = (state: RootState): StateProps => {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...props,
|
...props,
|
||||||
loading: state.transactions.loading,
|
loading: state.transactions.loadingRequests > 0,
|
||||||
transactions: transactions,
|
transactions: transactions,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@ export interface TransactionState {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TransactionsState {
|
export interface TransactionsState {
|
||||||
loading: boolean
|
loadingRequests: number
|
||||||
transactions: {
|
transactions: {
|
||||||
[txHash: string]: TransactionState
|
[txHash: string]: TransactionState
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ const newTransactionState = (): TransactionState => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const initialState: TransactionsState = {
|
const initialState: TransactionsState = {
|
||||||
loading: false,
|
loadingRequests: 0,
|
||||||
transactions: {},
|
transactions: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,14 +48,14 @@ export const transactionsReducer = (state: TransactionsState = initialState, act
|
||||||
case TXS_LOADING: {
|
case TXS_LOADING: {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
loading: true,
|
loadingRequests: state.loadingRequests + 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case TXS_LOADED: {
|
case TXS_LOADED: {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
loading: false,
|
loadingRequests: state.loadingRequests - 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue