transaction list
This commit is contained in:
parent
e289bc2033
commit
5e6796f2d0
|
@ -11,9 +11,9 @@ import "./BlockConsumer.sol";
|
|||
import "./EVMUtils.sol";
|
||||
|
||||
contract StatusPay is BlockConsumer {
|
||||
event NewPayment(address from, address to, uint256 amount);
|
||||
event TopUp(address account, uint256 amount);
|
||||
event Withdraw(address account, uint256 amount);
|
||||
event NewPayment(address indexed from, address indexed to, uint256 amount);
|
||||
event TopUp(address indexed to, uint256 amount);
|
||||
event Withdraw(address indexed from, uint256 amount);
|
||||
|
||||
struct Payment {
|
||||
uint256 blockNumber;
|
||||
|
|
|
@ -5,7 +5,8 @@ import Web3 from 'web3';
|
|||
import { TransactionReceipt } from 'web3-core';
|
||||
import { loadWalletBalance } from './wallet';
|
||||
import { loadBlock } from './blocks';
|
||||
import { addPadding } from "../utils";
|
||||
|
||||
type ToOrFrom = "to" | "from";
|
||||
|
||||
export const TXS_LOADING = "TXS_LOADING";
|
||||
export interface TxsLoadingAction {
|
||||
|
@ -20,6 +21,7 @@ export interface TxsLoadedAction {
|
|||
export const TXS_TRANSACTION_DISCOVERED = "TXS_TRANSACTION_DISCOVERED";
|
||||
export interface TxsTransactionDiscoveredAction {
|
||||
type: typeof TXS_TRANSACTION_DISCOVERED
|
||||
direction: ToOrFrom
|
||||
event: string
|
||||
pending: boolean
|
||||
id: string
|
||||
|
@ -42,8 +44,9 @@ export type TxsActions =
|
|||
TxsTransactionDiscoveredAction |
|
||||
TxsTransactionConfirmedAction;
|
||||
|
||||
export const transactionDiscovered = (event: string, id: string, blockNumber: number, transactionHash: string, pending: boolean, from: string, to: string | undefined, value: string): TxsTransactionDiscoveredAction => ({
|
||||
export const transactionDiscovered = (direction: ToOrFrom, event: string, id: string, blockNumber: number, transactionHash: string, pending: boolean, from: string | undefined, to: string | undefined, value: string): TxsTransactionDiscoveredAction => ({
|
||||
type: TXS_TRANSACTION_DISCOVERED,
|
||||
direction,
|
||||
event,
|
||||
id,
|
||||
blockNumber,
|
||||
|
@ -85,42 +88,27 @@ export const loadTransactions = (web3: Web3, statusPay: Contract) => {
|
|||
};
|
||||
}
|
||||
|
||||
type ToOrFrom = "to" | "from";
|
||||
|
||||
const getPastTransactions = (web3: Web3, statusPay: Contract, walletAddress: string, fromBlock: number, toOrFrom: ToOrFrom) => {
|
||||
return (dispatch: Dispatch, getState: () => RootState) => {
|
||||
const paddedWalletAddress = addPadding(64, walletAddress);
|
||||
const eventType = toOrFrom === "to" ? "TopUp" : "NewPayment";
|
||||
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,
|
||||
filter: { [toOrFrom]: walletAddress}
|
||||
};
|
||||
|
||||
dispatch(loadingTransactions());
|
||||
statusPay.getPastEvents("Transfer", options).then((events: any) => {
|
||||
statusPay.getPastEvents("allEvents", 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(transactionDiscovered(toOrFrom, event.event, event.id, event.blockNumber, event.transactionHash, false, values.from, values.to, values.value));
|
||||
});
|
||||
dispatch(transactionsLoaded());
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
const subscribeToTransactions = (web3: Web3, erc20: Contract, walletAddress: string, fromBlock: number, toOrFrom: ToOrFrom) => {
|
||||
const subscribeToTransactions = (web3: Web3, statusPay: Contract, walletAddress: string, fromBlock: number, toOrFrom: ToOrFrom) => {
|
||||
return (dispatch: Dispatch, getState: () => RootState) => {
|
||||
const options = {
|
||||
fromBlock: fromBlock,
|
||||
|
@ -129,12 +117,10 @@ const subscribeToTransactions = (web3: Web3, erc20: Contract, walletAddress: str
|
|||
}
|
||||
};
|
||||
|
||||
const eventType = toOrFrom === "to" ? "TopUp" : "NewPayment";
|
||||
|
||||
erc20.events.Transfer(options).on('data', (event: any) => {
|
||||
statusPay.events.allEvents(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(transactionDiscovered(toOrFrom, event.event, event.id, event.blockNumber, event.transactionHash, pending, values.from, values.to, values.amount));
|
||||
dispatch<any>(loadWalletBalance(web3, undefined));
|
||||
if (pending) {
|
||||
watchPendingTransaction(web3, dispatch, walletAddress, event.transactionHash);
|
||||
|
|
|
@ -217,7 +217,7 @@ export const loadWallet = async (web3: Web3, dispatch: Dispatch, getState: () =>
|
|||
const loadWalletAddress = (web3: Web3, statusPay: Contract, keycardAddress: string) => {
|
||||
return async (dispatch: Dispatch) => {
|
||||
dispatch(loadingWalletAddress(keycardAddress));
|
||||
return statusPay.methods.keycards(keycardAddress).call().then((address: string) => {
|
||||
return statusPay.methods.resolveAccount(keycardAddress).call().then((address: string) => {
|
||||
if (isEmptyAddress(address)) {
|
||||
dispatch(keycardNotFound(address));
|
||||
throw({
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
// import React from 'react';
|
||||
|
||||
// import Button from '@material-ui/core/Button';
|
||||
// import Typography from '@material-ui/core/Typography';
|
||||
// import Dialog from '@material-ui/core/Dialog';
|
||||
// import DialogActions from '@material-ui/core/DialogActions';
|
||||
// import DialogContent from '@material-ui/core/DialogContent';
|
||||
// import DialogContentText from '@material-ui/core/DialogContentText';
|
||||
// import DialogTitle from '@material-ui/core/DialogTitle';
|
||||
// import Slide from '@material-ui/core/Slide';
|
||||
// import TextField from '@material-ui/core/TextField';
|
||||
// import CircularProgress from '@material-ui/core/CircularProgress';
|
||||
// import Divider from '@material-ui/core/Divider';
|
||||
// import InputAdornment from '@material-ui/core/InputAdornment';
|
||||
|
||||
// const icons = ["💳", "👛", "💸", "😺"]
|
||||
|
||||
// const iconStyles = {
|
||||
// fontSize: "2em",
|
||||
// marginRight: 16,
|
||||
// padding: 4,
|
||||
// cursor: "pointer"
|
||||
// }
|
||||
|
||||
// const selectedIconStyles = {
|
||||
// ...iconStyles,
|
||||
// border: "4px solid #999"
|
||||
// }
|
||||
|
||||
// const errorStyles = {
|
||||
// color: "red",
|
||||
// }
|
||||
|
||||
// function Transition(props) {
|
||||
// return <Slide direction="up" {...props} />;
|
||||
// }
|
||||
|
||||
// const NewWalletDialog = ({open, creating, selected, keycardAddress, onIconClick, onCancelClick, onCreateClick, onKeycardChange, error, onTapButtonClick, onMaxTxValueChange, maxTxValue}) => (
|
||||
// <Dialog
|
||||
// fullScreen
|
||||
// TransitionComponent={Transition}
|
||||
// open={open}
|
||||
// aria-labelledby="alert-dialog-title"
|
||||
// aria-describedby="alert-dialog-description"
|
||||
// >
|
||||
// <DialogTitle id="alert-dialog-title">New Wallet</DialogTitle>
|
||||
// <DialogContent>
|
||||
// <Typography variant="body2" gutterBottom>
|
||||
// Choose an icon to identify your wallet
|
||||
// </Typography>
|
||||
// <div style={{marginBottom: 16}}>
|
||||
// {icons.map((icon) =>
|
||||
// <a key={icon} onClick={() => onIconClick(icon) }
|
||||
// style={selected == icon ? selectedIconStyles : iconStyles}>{icon}</a>
|
||||
// )}
|
||||
// </div>
|
||||
|
||||
// <TextField
|
||||
// margin="dense"
|
||||
// label="Maximum transaction value"
|
||||
// type="text"
|
||||
// value={maxTxValue}
|
||||
// style={{marginBottom: 16}}
|
||||
// fullWidth
|
||||
// onChange={(event) => onMaxTxValueChange(event.currentTarget.value)}
|
||||
// InputProps={{
|
||||
// startAdornment: <InputAdornment position="start" style={{paddingBottom: 7}}>Ξ</InputAdornment>,
|
||||
// }}
|
||||
// />
|
||||
|
||||
// <TextField
|
||||
// margin="dense"
|
||||
// label="Keycard address"
|
||||
// type="text"
|
||||
// value={keycardAddress}
|
||||
// style={{marginBottom: 16}}
|
||||
// fullWidth
|
||||
// onChange={(event) => onKeycardChange(event.currentTarget.value)}
|
||||
// />
|
||||
|
||||
// <div style={{margin: 16, textAlign: "center"}}>
|
||||
// <Typography variant="body2" gutterBottom>
|
||||
// or
|
||||
// </Typography>
|
||||
// </div>
|
||||
|
||||
// <Button onClick={() => onTapButtonClick("hello world")} size="large" color="primary" variant="contained" fullWidth>
|
||||
// CONNECT TAPPING YOUR KEYCARD
|
||||
// </Button>
|
||||
|
||||
// {creating && <div style={{marginTop: 50, textAlign: "center"}}>
|
||||
// <CircularProgress />
|
||||
// </div>}
|
||||
|
||||
// </DialogContent>
|
||||
|
||||
// <DialogActions>
|
||||
// {!creating &&
|
||||
// <Button onClick={onCancelClick} color="primary">
|
||||
// Cancel
|
||||
// </Button>}
|
||||
|
||||
// <Button onClick={onCreateClick} color="primary" autoFocus disabled={(selected && !creating) ? false : true}>
|
||||
// {!creating ? "Create" : "Creating..."}
|
||||
// </Button>
|
||||
// </DialogActions>
|
||||
|
||||
// {error &&
|
||||
// <DialogActions>
|
||||
// <div style={errorStyles}>{error}</div>
|
||||
// </DialogActions>}
|
||||
// </Dialog>
|
||||
// );
|
||||
|
||||
// export default NewWalletDialog;
|
|
@ -69,10 +69,9 @@ const useStyles = makeStyles(theme => ({
|
|||
|
||||
const icon = (event: string, className: any) => {
|
||||
switch(event) {
|
||||
case "TopUp":
|
||||
case "to":
|
||||
return <TransactionInIcon className={className} />
|
||||
case "NewPayment":
|
||||
case "Withdraw":
|
||||
case "from":
|
||||
return <TransactionOutIcon className={className} />
|
||||
default:
|
||||
return <TransactionUnknownIcon />
|
||||
|
@ -120,17 +119,16 @@ const TransactionsListItem = (props: Props) => {
|
|||
<span className={classes.block}>to: {toAddress}</span>
|
||||
</span>;
|
||||
|
||||
const [avatarClass, iconClass] = (event => {
|
||||
switch(event) {
|
||||
case "TopUp":
|
||||
const [avatarClass, iconClass] = (direction => {
|
||||
switch(direction) {
|
||||
case "to":
|
||||
return [classes.avatarIn, classes.iconIn];
|
||||
case "NewPayment":
|
||||
case "Withdraw":
|
||||
case "from":
|
||||
return [classes.avatarOut, classes.iconOut];
|
||||
default:
|
||||
return [classes.avatar, classes.icon];
|
||||
}
|
||||
})(tx.event)
|
||||
})(tx.direction)
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -140,7 +138,7 @@ const TransactionsListItem = (props: Props) => {
|
|||
<Avatar className={avatarClass}>
|
||||
{(tx.pending === true || tx.pending === undefined)
|
||||
&& <CircularProgress color="secondary" className={classes.avatarLoading}/>}
|
||||
{icon(tx.event, iconClass)}
|
||||
{icon(tx.direction, iconClass)}
|
||||
</Avatar>
|
||||
</Fade>
|
||||
</ListItemAvatar>
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
// import { connect } from 'react-redux';
|
||||
// import NewWalletDialog from '../components/NewWalletDialog';
|
||||
// import {
|
||||
// newWalletSelectIcon,
|
||||
// newWalletCancel,
|
||||
// createWallet,
|
||||
// newWalletFormKeycardAddressChanged,
|
||||
// newWalletFormMaxTxValueChanged,
|
||||
// signMessagePinless,
|
||||
// } from '../actions';
|
||||
|
||||
// const mapStateToProps = state => ({
|
||||
// open: state.newWalletForm.open,
|
||||
// selected: state.newWalletForm.icon,
|
||||
// creating: state.newWalletForm.creating,
|
||||
// error: (state.newWalletForm.error || "").toString(),
|
||||
// keycardAddress: state.newWalletForm.keycardAddress || "",
|
||||
// maxTxValue: state.newWalletForm.maxTxValue,
|
||||
// });
|
||||
|
||||
// const mapDispatchToProps = dispatch => ({
|
||||
// onIconClick: (icon) => dispatch(newWalletSelectIcon(icon)),
|
||||
// onCancelClick: () => dispatch(newWalletCancel()),
|
||||
// onCreateClick: () => dispatch(createWallet()),
|
||||
// onKeycardChange: (address) => dispatch(newWalletFormKeycardAddressChanged(address)),
|
||||
// onMaxTxValueChange: (value) => dispatch(newWalletFormMaxTxValueChanged(value)),
|
||||
// onTapButtonClick: (message) => dispatch(signMessagePinless(message)),
|
||||
// });
|
||||
|
||||
// export default connect(
|
||||
// mapStateToProps,
|
||||
// mapDispatchToProps
|
||||
// )(NewWalletDialog);
|
|
@ -10,6 +10,7 @@ import {
|
|||
export interface TransactionState {
|
||||
id: string
|
||||
blockNumber: number
|
||||
direction: string
|
||||
event: string
|
||||
transactionHash: string
|
||||
pending: boolean | undefined
|
||||
|
@ -29,6 +30,7 @@ export interface TransactionsState {
|
|||
const newTransactionState = (): TransactionState => ({
|
||||
id: "",
|
||||
blockNumber: 0,
|
||||
direction: "",
|
||||
event: "",
|
||||
transactionHash: "",
|
||||
pending: undefined,
|
||||
|
@ -80,6 +82,7 @@ export const transactionsReducer = (state: TransactionsState = initialState, act
|
|||
...txState,
|
||||
id: action.id,
|
||||
blockNumber: action.blockNumber,
|
||||
direction: action.direction,
|
||||
event: action.event,
|
||||
transactionHash: action.transactionHash,
|
||||
pending: action.pending,
|
||||
|
|
Loading…
Reference in New Issue