diff --git a/src/domains/misc/components/Modal/Modal.tsx b/src/domains/misc/components/Modal/Modal.tsx index 81ec9cf..b30c7bf 100644 --- a/src/domains/misc/components/Modal/Modal.tsx +++ b/src/domains/misc/components/Modal/Modal.tsx @@ -58,13 +58,13 @@ const Modal = ({ useEffect(() => { const handleEsc = (e: KeyboardEvent) => { - if (e.key === 'Escape' && !nonDismissible) { + if (e.key === 'Escape' && !nonDismissible && isTopModal) { triggerClose(); } }; document.addEventListener('keydown', handleEsc); return () => void document.removeEventListener('keydown', handleEsc); - }, [nonDismissible, triggerClose]); + }, [nonDismissible, triggerClose, isTopModal]); const pages = Array.isArray(config) ? config : [config]; diff --git a/src/domains/shielder/components/TokenList/Modals/SendModal/SelectAmountPage.tsx b/src/domains/shielder/components/TokenList/Modals/SendModal/SelectAmountPage.tsx index 073efc9..fca13e4 100644 --- a/src/domains/shielder/components/TokenList/Modals/SendModal/SelectAmountPage.tsx +++ b/src/domains/shielder/components/TokenList/Modals/SendModal/SelectAmountPage.tsx @@ -31,15 +31,18 @@ type Props = { }, onContinue: (amount: bigint) => void, hasInsufficientFees: boolean, + value: string, + onValueChange: (value: string) => void, }; -const SelectAmountPage = ({ onContinue, token, hasInsufficientFees }: Props) => { +const SelectAmountPage = ({ onContinue, token, hasInsufficientFees, value, onValueChange }: Props) => { const { address } = useWallet(); const chainConfig = useChain(); - const [value, setValue] = useState(''); const [isExceedingBalance, setIsExceedingBalance] = useState(false); + const amount = token.decimals ? fromDecimals(value, token.decimals) : 0n; + const { fees, totalFee, isLoading } = useShielderFees({ token, operation: 'send' }); const { @@ -56,7 +59,6 @@ const SelectAmountPage = ({ onContinue, token, hasInsufficientFees }: Props) => return result > 0n ? result : 0n; }, [token, totalFee]); - const amount = token.decimals ? fromDecimals(value, token.decimals) : 0n; const hasNotSelectedAmount = amount <= 0n; const isButtonDisabled = hasNotSelectedAmount || isExceedingBalance || hasInsufficientFees; @@ -80,7 +82,7 @@ const SelectAmountPage = ({ onContinue, token, hasInsufficientFees }: Props) => maxAmount={maxAmountToSend} token={token} effectiveAssetValue={value} - onAssetValueChange={setValue} + onAssetValueChange={onValueChange} accountAddress={address} onAssetBalanceExceeded={setIsExceedingBalance} /> diff --git a/src/domains/shielder/components/TokenList/Modals/SendModal/SendModal.tsx b/src/domains/shielder/components/TokenList/Modals/SendModal/SendModal.tsx index ebe76f9..104bc31 100644 --- a/src/domains/shielder/components/TokenList/Modals/SendModal/SendModal.tsx +++ b/src/domains/shielder/components/TokenList/Modals/SendModal/SendModal.tsx @@ -26,6 +26,7 @@ const SendModal = ({ token }: Props) => { const { address } = useWallet(); const [addressTo, setAddressTo] = useState(''); const [amount, setAmount] = useState(0n); + const [inputValue, setInputValue] = useState(''); const { withdraw, isWithdrawing } = useWithdraw(); const [page, setPage] = useState(0); const { close } = useModalControls(); @@ -63,52 +64,49 @@ const SendModal = ({ token }: Props) => { return ( - ), - }, - { - title: 'Send', - content: ( - - ), - }, - { - title: 'Send', - content: ( - - ), - }, - ] - } + config={[ + { + title: 'Send', + content: ( + + ), + }, + { + title: 'Send', + content: ( + + ), + }, + { + title: 'Send', + content: ( + + ), + }, + ]} /> ); }; diff --git a/src/domains/shielder/components/TokenList/Modals/ShieldModal/SelectAmountPage.tsx b/src/domains/shielder/components/TokenList/Modals/ShieldModal/SelectAmountPage.tsx index 6a4b90a..2410907 100644 --- a/src/domains/shielder/components/TokenList/Modals/ShieldModal/SelectAmountPage.tsx +++ b/src/domains/shielder/components/TokenList/Modals/ShieldModal/SelectAmountPage.tsx @@ -31,13 +31,14 @@ type Props = { }, onContinue: (amount: bigint) => void, hasInsufficientFees: boolean, + value: string, + onValueChange: (value: string) => void, }; -const SelectAmountPage = ({ onContinue, token, hasInsufficientFees }: Props) => { +const SelectAmountPage = ({ onContinue, token, hasInsufficientFees, value, onValueChange }: Props) => { const { address } = useWallet(); const chainConfig = useChain(); - const [value, setValue] = useState(''); const [isExceedingBalance, setIsExceedingBalance] = useState(false); const amount = token.decimals ? fromDecimals(value, token.decimals) : 0n; @@ -85,7 +86,7 @@ const SelectAmountPage = ({ onContinue, token, hasInsufficientFees }: Props) => maxAmount={maxAmountToShield} token={token} effectiveAssetValue={value} - onAssetValueChange={setValue} + onAssetValueChange={onValueChange} accountAddress={address} onAssetBalanceExceeded={setIsExceedingBalance} /> diff --git a/src/domains/shielder/components/TokenList/Modals/ShieldModal/ShieldModal.tsx b/src/domains/shielder/components/TokenList/Modals/ShieldModal/ShieldModal.tsx index 402102a..b6a17a4 100644 --- a/src/domains/shielder/components/TokenList/Modals/ShieldModal/ShieldModal.tsx +++ b/src/domains/shielder/components/TokenList/Modals/ShieldModal/ShieldModal.tsx @@ -25,6 +25,7 @@ const ShieldModal = ({ token }: Props) => { const { address } = useWallet(); const { close } = useModalControls(); const [amount, setAmount] = useState(0n); + const [inputValue, setInputValue] = useState(''); const chainConfig = useChain(); const { shield, isShielding, reset } = useShield(); const [page, setPage] = useState(0); @@ -63,40 +64,38 @@ const ShieldModal = ({ token }: Props) => { - ), - }, - { - title: 'Shield', - content: ( - void handleShield()} - isLoading={isShielding} - buttonLabel={ - hasInsufficientFees ? - `Insufficient ${chainConfig?.nativeCurrency.symbol} Balance` : - isShielding ? 'Shielding' : 'Confirm' - } - addressFrom={address} - hasInsufficientFees={hasInsufficientFees} - /> - ), - }, - ] - } + config={[ + { + title: 'Shield', + content: ( + + ), + }, + { + title: 'Shield', + content: ( + void handleShield()} + isLoading={isShielding} + buttonLabel={ + hasInsufficientFees ? + `Insufficient ${chainConfig?.nativeCurrency.symbol} Balance` : + isShielding ? 'Shielding' : 'Confirm' + } + addressFrom={address} + hasInsufficientFees={hasInsufficientFees} + /> + ), + }, + ]} /> ); }; diff --git a/src/domains/shielder/components/TokenList/TokenListItem.tsx b/src/domains/shielder/components/TokenList/TokenListItem.tsx index 0d0cfc1..fbed681 100644 --- a/src/domains/shielder/components/TokenList/TokenListItem.tsx +++ b/src/domains/shielder/components/TokenList/TokenListItem.tsx @@ -50,7 +50,7 @@ const TokenListItem = ({ token }: Props) => { variables.token.address === token.address && variables.token.isNative === token.isNative; }, - }); + }) && selectedAccountType === 'public'; const isWithdrawing = !!useIsMutating({ predicate: mutation => { @@ -60,7 +60,7 @@ const TokenListItem = ({ token }: Props) => { variables.token.address === token.address && variables.token.isNative === token.isNative; }, - }); + }) && selectedAccountType === 'shielded'; const isProcessing = isShielding || isWithdrawing; const processingText = isShielding ? 'Shielding' : isWithdrawing ? 'Sending privately' : undefined; diff --git a/src/domains/shielder/components/TransactionDetailsModal/ActivityDetailsModal.tsx b/src/domains/shielder/components/TransactionDetailsModal/ActivityDetailsModal.tsx index 0859f9e..850a772 100644 --- a/src/domains/shielder/components/TransactionDetailsModal/ActivityDetailsModal.tsx +++ b/src/domains/shielder/components/TransactionDetailsModal/ActivityDetailsModal.tsx @@ -57,6 +57,7 @@ const ActivityDetailsModal = (props: Props) => { { isNative: true as const }; const operation = transaction?.type === 'Withdraw' ? 'send' : 'shield'; + const { fees, totalFee: estimatedTotalFee } = useShielderFees({ token, operation, diff --git a/src/domains/shielder/components/TransactionDetailsModal/Title.tsx b/src/domains/shielder/components/TransactionDetailsModal/Title.tsx index 31c87b4..d5e0f21 100644 --- a/src/domains/shielder/components/TransactionDetailsModal/Title.tsx +++ b/src/domains/shielder/components/TransactionDetailsModal/Title.tsx @@ -60,10 +60,13 @@ const Container = styled.div` display: flex; justify-content: center; flex-direction: column; - ${typography.decorative.subtitle2}; - & > p { + & > :first-of-type { + ${typography.decorative.subtitle2}; + }; + + & > :last-of-type { ${typography.web.caption2}; - color:${vars('--color-neutral-foreground-3-rest')} - } + color:${vars('--color-neutral-foreground-3-rest')} + }; `; diff --git a/src/domains/shielder/utils/useEstimateAllowanceFee.tsx b/src/domains/shielder/utils/useEstimateAllowanceFee.tsx index d183203..44973b2 100644 --- a/src/domains/shielder/utils/useEstimateAllowanceFee.tsx +++ b/src/domains/shielder/utils/useEstimateAllowanceFee.tsx @@ -1,11 +1,9 @@ -import { skipToken, useQuery } from '@tanstack/react-query'; import { erc20Abi, encodeFunctionData } from 'viem'; -import { useEstimateFeesPerGas, useEstimateGas, usePublicClient } from 'wagmi'; +import { useEstimateFeesPerGas, useEstimateGas } from 'wagmi'; import { useWallet } from 'src/domains/chains/components/WalletProvider.tsx'; import { Token } from 'src/domains/chains/types/misc'; import useChain from 'src/domains/chains/utils/useChain'; -import getQueryKey from 'src/domains/misc/utils/getQueryKey'; type Props = { token: Token, @@ -15,38 +13,13 @@ type Props = { const useEstimateAllowanceFee = ({ token, amount, disabled }: Props) => { const chainConfig = useChain(); - const publicClient = usePublicClient(); const { address: walletAddress } = useWallet(); const shouldCheckAllowance = !token.isNative && amount > 0n && !disabled; - const { data: needsApproval } = useQuery({ - queryKey: chainConfig && walletAddress && shouldCheckAllowance ? - getQueryKey.allowanceCheck(token.address, chainConfig.id.toString(), walletAddress, amount.toString()) : [], - queryFn: !publicClient || !chainConfig?.shielderConfig || !walletAddress || !shouldCheckAllowance ? - skipToken : - async (): Promise => { - try { - const shielderConfig = chainConfig.shielderConfig; - if (!shielderConfig) return false; - - const allowance = await publicClient.readContract({ - address: token.address, - abi: erc20Abi, - functionName: 'allowance', - args: [walletAddress, shielderConfig.shielderContractAddress], - }); - return allowance < amount; - } catch { - return false; - } - }, - enabled: shouldCheckAllowance && !!publicClient && !!chainConfig?.shielderConfig && !!walletAddress, - }); - - const { data: gasEstimate } = useEstimateGas({ + const { data: gasEstimate, isLoading: isGasEstimateLoading } = useEstimateGas({ to: token.address, - data: needsApproval && chainConfig?.shielderConfig ? + data: chainConfig?.shielderConfig ? encodeFunctionData({ abi: erc20Abi, functionName: 'approve', @@ -57,18 +30,16 @@ const useEstimateAllowanceFee = ({ token, amount, disabled }: Props) => { query: { enabled: shouldCheckAllowance && - !!needsApproval && !!chainConfig?.shielderConfig && !!walletAddress, }, }); - const { data: feeEstimate } = useEstimateFeesPerGas({ + const { data: feeEstimate, isLoading: isFeeEstimateLoading } = useEstimateFeesPerGas({ chainId: chainConfig?.id, query: { enabled: shouldCheckAllowance && - !!needsApproval && !!chainConfig?.shielderConfig && !!walletAddress, }, @@ -77,22 +48,20 @@ const useEstimateAllowanceFee = ({ token, amount, disabled }: Props) => { const gasPrice = feeEstimate?.maxFeePerGas; const allowanceFee = - gasEstimate && feeEstimate?.maxFeePerGas ? - gasEstimate * feeEstimate.maxFeePerGas : + gasEstimate && gasPrice? + gasEstimate * gasPrice : null; if (!shouldCheckAllowance) { return { data: null, isLoading: false, - error: null, }; } return { - data: needsApproval ? allowanceFee : allowanceFee, - isLoading: needsApproval === undefined || (needsApproval && (!gasEstimate || !gasPrice)), - error: null, + data: allowanceFee, + isLoading: isGasEstimateLoading || isFeeEstimateLoading, }; }; diff --git a/src/domains/shielder/utils/useFeeBreakdownModal.tsx b/src/domains/shielder/utils/useFeeBreakdownModal.tsx index 778b07f..47c2f9a 100644 --- a/src/domains/shielder/utils/useFeeBreakdownModal.tsx +++ b/src/domains/shielder/utils/useFeeBreakdownModal.tsx @@ -111,11 +111,12 @@ const useFeeBreakdownModal = ({ fees, totalFee }: Props) => { This is the maximum estimate—it can be slightly lower upon execution. -
+ {/* TODO: Temporarily commented out until fee documentation links are ready */} + {/*

Want to know more about fees? {' '} - Learn more + Learn more */}
), @@ -155,12 +156,13 @@ const Disclaimer = styled.p` color: ${vars('--color-neutral-foreground-2-rest')}; `; -const LearnMoreLink = styled.span` - color: ${vars('--color-brand-foreground-1-rest')}; - cursor: pointer; - - text-decoration: underline; -`; +// TODO: Temporarily commented out until fee documentation links are ready +// const LearnMoreLink = styled.span` +// color: ${vars('--color-brand-foreground-1-rest')}; +// cursor: pointer; +// +// text-decoration: underline; +// `; const VerticalConnector = styled.div` height: 11px;