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 Web3 from 'web3';
|
||||
import { TransactionReceipt } from 'web3-core';
|
||||
// import { loadBalance } from './wallet';
|
||||
import { loadWalletBalance } from './wallet';
|
||||
import { loadBlock } from './blocks';
|
||||
import { abi as keycardWalletABI } from '../contracts/KeycardWallet';
|
||||
import { addPadding } from "../utils";
|
||||
|
@ -68,23 +68,6 @@ export const transactionConfirmed = (transactionHash: string): TxsTransactionCon
|
|||
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) => {
|
||||
return (dispatch: Dispatch, getState: () => RootState) => {
|
||||
const state = getState();
|
||||
|
@ -93,38 +76,87 @@ export const loadTransactions = (web3: Web3, erc20: Contract) => {
|
|||
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) => {
|
||||
erc20.events.Transfer({filter: filter}).on('data', (event: any) => {
|
||||
const values = event.returnValues;
|
||||
dispatch(transactionDiscovered("TopUp", event.id, event.blockNumber, event.transactionHash, true, values.from, walletAddress, values.value));
|
||||
watchPendingTransaction(web3, dispatch, walletAddress, wallet, event.transactionHash);
|
||||
})
|
||||
dispatch<any>(getPastTransactions(web3, erc20, walletAddress, blockNumber, "to"))
|
||||
dispatch<any>(getPastTransactions(web3, erc20, walletAddress, blockNumber, "from"))
|
||||
|
||||
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) => {
|
||||
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));
|
||||
|
||||
return erc20.methods.balanceOf(address).call().then((balance: string) => {
|
||||
dispatch(balanceLoaded(balance, balance));
|
||||
return erc20;
|
||||
|
|
|
@ -12,7 +12,6 @@ export const VALID_NETWORK_ID = 3;
|
|||
// export const VALID_NETWORK_ID = 5;
|
||||
export const LOCAL_NETWORK_ID = 1337;
|
||||
|
||||
|
||||
enum Web3Type {
|
||||
Generic,
|
||||
Remote,
|
||||
|
|
|
@ -39,7 +39,8 @@ const WalletsList = (props: Props) => {
|
|||
{props.loading && <div className={classes.loading}>
|
||||
<CircularProgress className={classes.progress} disableShrink></CircularProgress>
|
||||
</div>}
|
||||
{!props.loading && <List>
|
||||
|
||||
{<List>
|
||||
{props.transactions.map((tx) => (
|
||||
<TransactionsListItem key={tx.id} id={tx.id} />
|
||||
))}
|
||||
|
|
|
@ -33,7 +33,7 @@ const mapStateToProps = (state: RootState): StateProps => {
|
|||
|
||||
return {
|
||||
...props,
|
||||
loading: state.transactions.loading,
|
||||
loading: state.transactions.loadingRequests > 0,
|
||||
transactions: transactions,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,7 +20,7 @@ export interface TransactionState {
|
|||
}
|
||||
|
||||
export interface TransactionsState {
|
||||
loading: boolean
|
||||
loadingRequests: number
|
||||
transactions: {
|
||||
[txHash: string]: TransactionState
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ const newTransactionState = (): TransactionState => ({
|
|||
});
|
||||
|
||||
const initialState: TransactionsState = {
|
||||
loading: false,
|
||||
loadingRequests: 0,
|
||||
transactions: {},
|
||||
};
|
||||
|
||||
|
@ -48,14 +48,14 @@ export const transactionsReducer = (state: TransactionsState = initialState, act
|
|||
case TXS_LOADING: {
|
||||
return {
|
||||
...state,
|
||||
loading: true,
|
||||
loadingRequests: state.loadingRequests + 1,
|
||||
}
|
||||
}
|
||||
|
||||
case TXS_LOADED: {
|
||||
return {
|
||||
...state,
|
||||
loading: false,
|
||||
loadingRequests: state.loadingRequests - 1,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue