Commit 56717005 authored by Zach Pomerantz's avatar Zach Pomerantz Committed by GitHub

feat: pending tx state (#3189)

* refactor: state cleanup

* feat: add pending tx hash to swap state

* fix: update name to display tx hash
parent b50d10cb
...@@ -2,7 +2,7 @@ import { t } from '@lingui/macro' ...@@ -2,7 +2,7 @@ import { t } from '@lingui/macro'
import { Trade } from '@uniswap/router-sdk' import { Trade } from '@uniswap/router-sdk'
import { Currency, Percent, TradeType } from '@uniswap/sdk-core' import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { useAtom } from 'jotai' import { useAtom } from 'jotai'
import { integratorFeeAtom } from 'lib/state/swap' import { integratorFeeAtom } from 'lib/state/settings'
import { ThemedText } from 'lib/theme' import { ThemedText } from 'lib/theme'
import { useMemo } from 'react' import { useMemo } from 'react'
import { currencyId } from 'utils/currencyId' import { currencyId } from 'utils/currencyId'
......
...@@ -4,6 +4,7 @@ import { Token } from '@uniswap/sdk-core' ...@@ -4,6 +4,7 @@ import { Token } from '@uniswap/sdk-core'
import { CHAIN_INFO } from 'constants/chainInfo' import { CHAIN_INFO } from 'constants/chainInfo'
import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp' import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp'
import { useERC20PermitFromTrade } from 'hooks/useERC20Permit' import { useERC20PermitFromTrade } from 'hooks/useERC20Permit'
import { useUpdateAtom } from 'jotai/utils'
import { useAtomValue } from 'jotai/utils' import { useAtomValue } from 'jotai/utils'
import { useSwapInfo } from 'lib/hooks/swap' import { useSwapInfo } from 'lib/hooks/swap'
import useSwapApproval, { import useSwapApproval, {
...@@ -17,7 +18,7 @@ import { usePendingApproval } from 'lib/hooks/transactions' ...@@ -17,7 +18,7 @@ import { usePendingApproval } from 'lib/hooks/transactions'
import useActiveWeb3React from 'lib/hooks/useActiveWeb3React' import useActiveWeb3React from 'lib/hooks/useActiveWeb3React'
import { Link, Spinner } from 'lib/icons' import { Link, Spinner } from 'lib/icons'
import { transactionTtlAtom } from 'lib/state/settings' import { transactionTtlAtom } from 'lib/state/settings'
import { Field } from 'lib/state/swap' import { displayTxHashAtom, Field } from 'lib/state/swap'
import { TransactionType } from 'lib/state/transactions' import { TransactionType } from 'lib/state/transactions'
import styled from 'lib/theme' import styled from 'lib/theme'
import { useCallback, useEffect, useMemo, useState } from 'react' import { useCallback, useEffect, useMemo, useState } from 'react'
...@@ -127,18 +128,19 @@ export default function SwapButton({ disabled }: SwapButtonProps) { ...@@ -127,18 +128,19 @@ export default function SwapButton({ disabled }: SwapButtonProps) {
) )
//@TODO(ianlapham): add a loading state, process errors //@TODO(ianlapham): add a loading state, process errors
const setDisplayTxHash = useUpdateAtom(displayTxHashAtom)
const onConfirm = useCallback(() => { const onConfirm = useCallback(() => {
swapCallback?.() swapCallback?.()
.then((transactionResponse) => { .then((transactionResponse) => {
// TODO(ianlapham): Add the swap tx to transactionsAtom // TODO(ianlapham): Add the swap tx to transactionsAtom
// TODO(ianlapham): Add the pending swap tx to a new swap state
console.log(transactionResponse) console.log(transactionResponse)
setDisplayTxHash(transactionResponse.hash)
}) })
.catch((error) => { .catch((error) => {
//@TODO(ianlapham): add error handling //@TODO(ianlapham): add error handling
console.log(error) console.log(error)
}) })
}, [swapCallback]) }, [setDisplayTxHash, swapCallback])
return ( return (
<> <>
...@@ -155,11 +157,6 @@ export default function SwapButton({ disabled }: SwapButtonProps) { ...@@ -155,11 +157,6 @@ export default function SwapButton({ disabled }: SwapButtonProps) {
<SummaryDialog trade={activeTrade} allowedSlippage={allowedSlippage} onConfirm={onConfirm} /> <SummaryDialog trade={activeTrade} allowedSlippage={allowedSlippage} onConfirm={onConfirm} />
</Dialog> </Dialog>
)} )}
{/* TODO(zzmp): Pass the completed tx, possibly at a different level of the DOM.
<Dialog color="dialog">
<StatusDialog onClose={() => void 0} />
</Dialog>
*/}
</> </>
) )
} }
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { TokenInfo } from '@uniswap/token-lists' import { TokenInfo } from '@uniswap/token-lists'
import { useAtom } from 'jotai'
import useSwapDefaults from 'lib/hooks/swap/useSwapDefaults' import useSwapDefaults from 'lib/hooks/swap/useSwapDefaults'
import { SwapInfoUpdater } from 'lib/hooks/swap/useSwapInfo' import { SwapInfoUpdater } from 'lib/hooks/swap/useSwapInfo'
import { usePendingTransactions } from 'lib/hooks/transactions'
import useActiveWeb3React from 'lib/hooks/useActiveWeb3React' import useActiveWeb3React from 'lib/hooks/useActiveWeb3React'
import useTokenList from 'lib/hooks/useTokenList' import useTokenList from 'lib/hooks/useTokenList'
import { displayTxHashAtom } from 'lib/state/swap'
import { SwapTransactionInfo, Transaction, TransactionType } from 'lib/state/transactions'
import { useState } from 'react' import { useState } from 'react'
import Dialog from '../Dialog'
import Header from '../Header' import Header from '../Header'
import { BoundaryProvider } from '../Popover' import { BoundaryProvider } from '../Popover'
import Wallet from '../Wallet' import Wallet from '../Wallet'
...@@ -13,11 +18,23 @@ import Input from './Input' ...@@ -13,11 +18,23 @@ import Input from './Input'
import Output from './Output' import Output from './Output'
import ReverseButton from './ReverseButton' import ReverseButton from './ReverseButton'
import Settings from './Settings' import Settings from './Settings'
import { StatusDialog } from './Status'
import SwapButton from './SwapButton' import SwapButton from './SwapButton'
import SwapPropValidator from './SwapPropValidator' import SwapPropValidator from './SwapPropValidator'
import Toolbar from './Toolbar' import Toolbar from './Toolbar'
export type DefaultAddress = string | { [chainId: number]: string | 'NATIVE' } | 'NATIVE' export type DefaultAddress = string | { [chainId: number]: string | 'NATIVE' } | 'NATIVE'
function getSwapTx(txs: { [hash: string]: Transaction }, hash?: string): Transaction<SwapTransactionInfo> | undefined {
if (hash) {
const tx = txs[hash]
if (tx.info.type === TransactionType.SWAP) {
return tx as Transaction<SwapTransactionInfo>
}
}
return
}
export interface SwapProps { export interface SwapProps {
tokenList?: string | TokenInfo[] tokenList?: string | TokenInfo[]
defaultInputAddress?: DefaultAddress defaultInputAddress?: DefaultAddress
...@@ -35,6 +52,10 @@ export default function Swap(props: SwapProps) { ...@@ -35,6 +52,10 @@ export default function Swap(props: SwapProps) {
const { active, account } = useActiveWeb3React() const { active, account } = useActiveWeb3React()
const [boundary, setBoundary] = useState<HTMLDivElement | null>(null) const [boundary, setBoundary] = useState<HTMLDivElement | null>(null)
const [displayTxHash, setDisplayTxHash] = useAtom(displayTxHashAtom)
const pendingTxs = usePendingTransactions()
const displayTx = getSwapTx(pendingTxs, displayTxHash)
return ( return (
<SwapPropValidator {...props}> <SwapPropValidator {...props}>
<SwapInfoUpdater /> <SwapInfoUpdater />
...@@ -52,6 +73,11 @@ export default function Swap(props: SwapProps) { ...@@ -52,6 +73,11 @@ export default function Swap(props: SwapProps) {
</Output> </Output>
</BoundaryProvider> </BoundaryProvider>
</div> </div>
{displayTx && (
<Dialog color="dialog">
<StatusDialog tx={displayTx} onClose={() => setDisplayTxHash()} />
</Dialog>
)}
</SwapPropValidator> </SwapPropValidator>
) )
} }
...@@ -2,10 +2,12 @@ import { Currency } from '@uniswap/sdk-core' ...@@ -2,10 +2,12 @@ import { Currency } from '@uniswap/sdk-core'
import { useAtom } from 'jotai' import { useAtom } from 'jotai'
import { useAtomValue, useUpdateAtom } from 'jotai/utils' import { useAtomValue, useUpdateAtom } from 'jotai/utils'
import { pickAtom } from 'lib/state/atoms' import { pickAtom } from 'lib/state/atoms'
import { amountAtom, Field, independentFieldAtom, swapAtom } from 'lib/state/swap' import { Field, independentFieldAtom, swapAtom } from 'lib/state/swap'
import { useCallback, useMemo } from 'react' import { useCallback, useMemo } from 'react'
export { default as useSwapInfo } from './useSwapInfo' export { default as useSwapInfo } from './useSwapInfo'
export const amountAtom = pickAtom(swapAtom, 'amount')
function otherField(field: Field) { function otherField(field: Field) {
switch (field) { switch (field) {
case Field.INPUT: case Field.INPUT:
......
...@@ -8,13 +8,15 @@ export const TRANSACTION_TTL_DEFAULT = 40 ...@@ -8,13 +8,15 @@ export const TRANSACTION_TTL_DEFAULT = 40
interface Settings { interface Settings {
maxSlippage: Percent | 'auto' // auto will cause slippage to resort to default calculation maxSlippage: Percent | 'auto' // auto will cause slippage to resort to default calculation
transactionTtl: number | undefined transactionTtl: number | undefined
integratorFee: number | undefined
mockTogglable: boolean mockTogglable: boolean
clientSideRouter: boolean // wether to use clientSideRouter: boolean // whether to use the client-side router or query the remote API
} }
const initialSettings: Settings = { const initialSettings: Settings = {
maxSlippage: 'auto', maxSlippage: 'auto',
transactionTtl: TRANSACTION_TTL_DEFAULT, transactionTtl: TRANSACTION_TTL_DEFAULT,
integratorFee: undefined,
mockTogglable: true, mockTogglable: true,
clientSideRouter: false, clientSideRouter: false,
} }
...@@ -22,5 +24,6 @@ const initialSettings: Settings = { ...@@ -22,5 +24,6 @@ const initialSettings: Settings = {
export const settingsAtom = atomWithReset(initialSettings) export const settingsAtom = atomWithReset(initialSettings)
export const maxSlippageAtom = pickAtom(settingsAtom, 'maxSlippage') export const maxSlippageAtom = pickAtom(settingsAtom, 'maxSlippage')
export const transactionTtlAtom = pickAtom(settingsAtom, 'transactionTtl') export const transactionTtlAtom = pickAtom(settingsAtom, 'transactionTtl')
export const integratorFeeAtom = pickAtom(settingsAtom, 'integratorFee')
export const mockTogglableAtom = pickAtom(settingsAtom, 'mockTogglable', setTogglable) export const mockTogglableAtom = pickAtom(settingsAtom, 'mockTogglable', setTogglable)
export const clientSideRouterAtom = pickAtom(settingsAtom, 'clientSideRouter') export const clientSideRouterAtom = pickAtom(settingsAtom, 'clientSideRouter')
import { Currency } from '@uniswap/sdk-core' import { Currency } from '@uniswap/sdk-core'
import { SupportedChainId } from 'constants/chains' import { SupportedChainId } from 'constants/chains'
import { nativeOnChain } from 'constants/tokens' import { nativeOnChain } from 'constants/tokens'
import { atom } from 'jotai'
import { atomWithImmer } from 'jotai/immer' import { atomWithImmer } from 'jotai/immer'
import { pickAtom } from 'lib/state/atoms' import { pickAtom } from 'lib/state/atoms'
...@@ -14,7 +15,6 @@ export interface Swap { ...@@ -14,7 +15,6 @@ export interface Swap {
amount: string amount: string
[Field.INPUT]?: Currency [Field.INPUT]?: Currency
[Field.OUTPUT]?: Currency [Field.OUTPUT]?: Currency
integratorFee?: number
} }
export const swapAtom = atomWithImmer<Swap>({ export const swapAtom = atomWithImmer<Swap>({
...@@ -24,5 +24,6 @@ export const swapAtom = atomWithImmer<Swap>({ ...@@ -24,5 +24,6 @@ export const swapAtom = atomWithImmer<Swap>({
}) })
export const independentFieldAtom = pickAtom(swapAtom, 'independentField') export const independentFieldAtom = pickAtom(swapAtom, 'independentField')
export const integratorFeeAtom = pickAtom(swapAtom, 'integratorFee')
export const amountAtom = pickAtom(swapAtom, 'amount') // If set to a transaction hash, that transaction will display in a status dialog.
export const displayTxHashAtom = atom<string | undefined>(undefined)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment