import { TransactionResponse } from "@ethersproject/providers"; import { RangeOrderData } from "@gelatonetwork/range-orders-lib"; import { useCallback, useMemo } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useWeb3 } from "../../web3"; import { AppDispatch, AppState } from "../index"; import { addTransaction, TransactionType } from "./actions"; import { TransactionDetails } from "./reducer"; // helper that can take a ethers library transaction response and add it to the list of transactions export function useTransactionAdder(): ( response: TransactionResponse, customData?: { summary?: string; order?: RangeOrderData; type: TransactionType; approval?: { tokenAddress: string; spender: string }; } ) => void { const { chainId, account } = useWeb3(); const dispatch = useDispatch(); return useCallback( ( response: TransactionResponse, { summary, type, order, approval, }: { summary?: string; order?: RangeOrderData; type: TransactionType; approval?: { tokenAddress: string; spender: string }; } = { type: "submission" } ) => { if (!account) return; if (!chainId) return; const { hash } = response; if (!hash) { throw Error("No transaction hash found."); } dispatch( addTransaction({ hash, from: account, order, chainId, type, approval, summary, }) ); }, [dispatch, chainId, account] ); } // returns all the transactions for the current chain export function useAllTransactions(): { [txHash: string]: TransactionDetails } { const { chainId } = useWeb3(); const state = useSelector( (state) => state.rtransactions ); return chainId ? state[chainId] ?? {} : {}; } export function useIsTransactionPending(transactionHash?: string): boolean { const transactions = useAllTransactions(); if (!transactionHash || !transactions[transactionHash]) return false; return !transactions[transactionHash].receipt; } /** * Returns whether a transaction happened in the last day (86400 seconds * 1000 milliseconds / second) * @param tx to check for recency */ export function isTransactionRecent(tx: TransactionDetails): boolean { return new Date().getTime() - tx.addedTime < 86_400_000; } // returns whether a token has a pending approval transaction export function useHasPendingApproval( tokenAddress: string | undefined, spender: string | undefined ): boolean { const allTransactions = useAllTransactions(); return useMemo( () => typeof tokenAddress === "string" && typeof spender === "string" && Object.keys(allTransactions).some((hash) => { const tx = allTransactions[hash]; if (!tx) return false; if (tx.receipt) { return false; } else { const approval = tx.approval; if (!approval) return false; return ( approval.spender === spender && approval.tokenAddress === tokenAddress && isTransactionRecent(tx) ); } }), [allTransactions, spender, tokenAddress] ); }