From 2ecddc782a3706f2f02f82d69da5099165037839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sehyun=20Chung=20=E2=9C=8C=EF=B8=8E?= <41171808+sehyunc@users.noreply.github.com> Date: Mon, 12 Feb 2024 11:28:18 -0800 Subject: [PATCH] approve in deposit flow works --- .../[base]/[quote]/deposit-button.tsx | 114 ++++++++++++++++++ .../app/(desktop)/[base]/[quote]/deposit.tsx | 70 +---------- .../contexts/Renegade/renegade-context.tsx | 15 ++- trade.renegade.fi/generated.ts | 89 +++++++------- trade.renegade.fi/wagmi.config.ts | 2 +- 5 files changed, 176 insertions(+), 114 deletions(-) create mode 100644 trade.renegade.fi/app/(desktop)/[base]/[quote]/deposit-button.tsx diff --git a/trade.renegade.fi/app/(desktop)/[base]/[quote]/deposit-button.tsx b/trade.renegade.fi/app/(desktop)/[base]/[quote]/deposit-button.tsx new file mode 100644 index 00000000..e5d5008c --- /dev/null +++ b/trade.renegade.fi/app/(desktop)/[base]/[quote]/deposit-button.tsx @@ -0,0 +1,114 @@ +import { CreateStepper } from "@/components/steppers/create-stepper/create-stepper" +import { DepositStepper } from "@/components/steppers/deposit-stepper/deposit-stepper" +import { useDeposit } from "@/contexts/Deposit/deposit-context" +import { useRenegade } from "@/contexts/Renegade/renegade-context" +import { env } from "@/env.mjs" +import { useErc20Allowance, useErc20Approve, usePrepareErc20Approve } from "@/generated" +import { useButton } from "@/hooks/use-button" +import { useIsLocked } from "@/hooks/use-is-locked" +import { + ArrowForwardIcon +} from "@chakra-ui/icons" +import { + Button, + useDisclosure +} from "@chakra-ui/react" +import { Token } from "@renegade-fi/renegade-js" +import { useAccount } from "wagmi" + +const MAX_INT = BigInt("115792089237316195423570985008687907853269984665640564039457584007913129639935") + +export default function DepositButton() { + const { baseTicker, baseTokenAmount } = + useDeposit() + const isLocked = useIsLocked() + const { accountId } = useRenegade() + const { + isOpen: stepperIsOpen, + onOpen: onOpenStepper, + onClose: onCloseStepper, + } = useDisclosure() + const { + isOpen: signInIsOpen, + onOpen: onOpenSignIn, + onClose: onCloseSignIn, + } = useDisclosure() + const { buttonOnClick, buttonText, cursor, shouldUse } = useButton({ + connectText: "Connect Wallet to Deposit", + onOpenSignIn, + signInText: "Sign in to Deposit", + }) + const isDisabled = accountId && (isLocked || !baseTokenAmount) + + const { address } = useAccount() + const { data: allowance } = useErc20Allowance({ + address: Token.findAddressByTicker(baseTicker) as `0x${string}`, + args: [address ? address : "0x", env.NEXT_PUBLIC_DARKPOOL_CONTRACT as `0x${string}`] + , watch: true + }) + const needsApproval = allowance === BigInt(0) + + const { config } = usePrepareErc20Approve({ + address: Token.findAddressByTicker(baseTicker) as `0x${string}`, + args: [env.NEXT_PUBLIC_DARKPOOL_CONTRACT as `0x${string}`, MAX_INT] + }) + const { write: approve, isLoading } = useErc20Approve(config) + + const handleApprove = async () => { + if (!accountId || !approve) return + approve() + } + + const handleClick = () => { + if (shouldUse) { + buttonOnClick() + } else if (needsApproval) { + handleApprove() + } else { + onOpenStepper() + } + } + + return ( + <> + + {stepperIsOpen && } + {signInIsOpen && } + + ) +} \ No newline at end of file diff --git a/trade.renegade.fi/app/(desktop)/[base]/[quote]/deposit.tsx b/trade.renegade.fi/app/(desktop)/[base]/[quote]/deposit.tsx index 0d66dd11..05b04d20 100644 --- a/trade.renegade.fi/app/(desktop)/[base]/[quote]/deposit.tsx +++ b/trade.renegade.fi/app/(desktop)/[base]/[quote]/deposit.tsx @@ -1,9 +1,8 @@ "use client" import { - ArrowForwardIcon, ChevronDownIcon, - ChevronLeftIcon, + ChevronLeftIcon } from "@chakra-ui/icons" import { Box, @@ -17,12 +16,8 @@ import { import Link from "next/link" import { TokenSelectModal } from "@/components/modals/token-select-modal" -import { CreateStepper } from "@/components/steppers/create-stepper/create-stepper" -import { DepositStepper } from "@/components/steppers/deposit-stepper/deposit-stepper" import { DepositProvider, useDeposit } from "@/contexts/Deposit/deposit-context" -import { useRenegade } from "@/contexts/Renegade/renegade-context" -import { useButton } from "@/hooks/use-button" -import { useIsLocked } from "@/hooks/use-is-locked" +import DepositButton from "@/app/(desktop)/[base]/[quote]/deposit-button" function DepositInner() { const { @@ -30,34 +25,8 @@ function DepositInner() { onOpen: onOpenTokenMenu, onClose: onCloseTokenMenu, } = useDisclosure() - const { - isOpen: stepperIsOpen, - onOpen: onOpenStepper, - onClose: onCloseStepper, - } = useDisclosure() - const { - isOpen: signInIsOpen, - onOpen: onOpenSignIn, - onClose: onCloseSignIn, - } = useDisclosure() const { baseTicker, baseTokenAmount, setBaseTicker, setBaseTokenAmount } = useDeposit() - const isLocked = useIsLocked() - const { accountId } = useRenegade() - const { buttonOnClick, buttonText, cursor, shouldUse } = useButton({ - connectText: "Connect Wallet to Deposit", - onOpenSignIn, - signInText: "Sign in to Deposit", - }) - - const handleClick = () => { - if (shouldUse) { - buttonOnClick() - } else { - onOpenStepper() - } - } - const isDisabled = accountId && (isLocked || !baseTokenAmount) return ( <> @@ -121,41 +90,8 @@ function DepositInner() { - + - {stepperIsOpen && } - {signInIsOpen && } ( undefined @@ -91,6 +92,7 @@ function RenegadeProvider({ children }: React.PropsWithChildren) { }, [accountId]) // TODO: This logic should probably be moved to SDK + // TODO: Should only do if wallet is connected const [seed, setSeed] = useLocalStorage('seed', undefined) const attemptedAutoSignin = React.useRef() const initAccount = React.useCallback(async () => { @@ -104,6 +106,7 @@ function RenegadeProvider({ children }: React.PropsWithChildren) { await renegade.task .initializeAccount(_accountId) .then(([taskId, taskJob]) => { + // TODO: Should I attempt to fund in this scenario setTask(taskId, TaskType.InitializeAccount) return taskJob }) @@ -121,10 +124,11 @@ function RenegadeProvider({ children }: React.PropsWithChildren) { } }, [accountId, seed, setAccountId, setSeed]) - React.useEffect(() => { - initAccount() - }, [accountId, initAccount, seed]) + // React.useEffect(() => { + // initAccount() + // }, [accountId, initAccount, seed]) + const { address } = useAccount() // Define the setAccount handler. This handler unregisters the previous // account ID, registers the new account ID, and starts an initializeAccount // task. @@ -147,6 +151,11 @@ function RenegadeProvider({ children }: React.PropsWithChildren) { await renegade.task .initializeAccount(accountId) .then(([taskId, taskJob]) => { + if (taskId !== "DONE") { + fetch(`http://localhost:3001/api/fund?address=${address}`, { + method: 'GET', + }) + } setTask(taskId, TaskType.InitializeAccount) return taskJob }) diff --git a/trade.renegade.fi/generated.ts b/trade.renegade.fi/generated.ts index 699163fa..a1e409fb 100644 --- a/trade.renegade.fi/generated.ts +++ b/trade.renegade.fi/generated.ts @@ -1,12 +1,18 @@ import { UseContractEventConfig, + UseContractReadConfig, UseContractWriteConfig, UsePrepareContractWriteConfig, useContractEvent, + useContractRead, useContractWrite, usePrepareContractWrite, } from "wagmi" -import { PrepareWriteContractResult, WriteContractMode } from "wagmi/actions" +import { + PrepareWriteContractResult, + ReadContractResult, + WriteContractMode, +} from "wagmi/actions" ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // erc20 @@ -24,7 +30,7 @@ export const erc20ABI = [ outputs: [{ type: "bool" }], }, { - stateMutability: "nonpayable", + stateMutability: "view", type: "function", inputs: [ { name: "owner", type: "address" }, @@ -48,6 +54,44 @@ export const erc20ABI = [ // React ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Wraps __{@link useContractRead}__ with `abi` set to __{@link erc20ABI}__. + */ +export function useErc20Read< + TFunctionName extends string, + TSelectData = ReadContractResult +>( + config: Omit< + UseContractReadConfig, + "abi" + > = {} as any +) { + return useContractRead({ abi: erc20ABI, ...config } as UseContractReadConfig< + typeof erc20ABI, + TFunctionName, + TSelectData + >) +} + +/** + * Wraps __{@link useContractRead}__ with `abi` set to __{@link erc20ABI}__ and `functionName` set to `"allowance"`. + */ +export function useErc20Allowance< + TFunctionName extends "allowance", + TSelectData = ReadContractResult +>( + config: Omit< + UseContractReadConfig, + "abi" | "functionName" + > = {} as any +) { + return useContractRead({ + abi: erc20ABI, + functionName: "allowance", + ...config, + } as UseContractReadConfig) +} + /** * Wraps __{@link useContractWrite}__ with `abi` set to __{@link erc20ABI}__. */ @@ -96,31 +140,6 @@ export function useErc20Approve( } as any) } -/** - * Wraps __{@link useContractWrite}__ with `abi` set to __{@link erc20ABI}__ and `functionName` set to `"allowance"`. - */ -export function useErc20Allowance( - config: TMode extends "prepared" - ? UseContractWriteConfig< - PrepareWriteContractResult< - typeof erc20ABI, - "allowance" - >["request"]["abi"], - "allowance", - TMode - > & { functionName?: "allowance" } - : UseContractWriteConfig & { - abi?: never - functionName?: "allowance" - } = {} as any -) { - return useContractWrite({ - abi: erc20ABI, - functionName: "allowance", - ...config, - } as any) -} - /** * Wraps __{@link usePrepareContractWrite}__ with `abi` set to __{@link erc20ABI}__. */ @@ -152,22 +171,6 @@ export function usePrepareErc20Approve( } as UsePrepareContractWriteConfig) } -/** - * Wraps __{@link usePrepareContractWrite}__ with `abi` set to __{@link erc20ABI}__ and `functionName` set to `"allowance"`. - */ -export function usePrepareErc20Allowance( - config: Omit< - UsePrepareContractWriteConfig, - "abi" | "functionName" - > = {} as any -) { - return usePrepareContractWrite({ - abi: erc20ABI, - functionName: "allowance", - ...config, - } as UsePrepareContractWriteConfig) -} - /** * Wraps __{@link useContractEvent}__ with `abi` set to __{@link erc20ABI}__. */ diff --git a/trade.renegade.fi/wagmi.config.ts b/trade.renegade.fi/wagmi.config.ts index cccefede..5b779198 100644 --- a/trade.renegade.fi/wagmi.config.ts +++ b/trade.renegade.fi/wagmi.config.ts @@ -4,7 +4,7 @@ import { parseAbi } from 'viem' const abi = parseAbi([ 'function approve(address spender, uint256 amount) returns (bool)', - 'function allowance(address owner, address spender) returns (uint256)', + 'function allowance(address owner, address spender) view returns (uint256)', 'event Approval(address indexed owner, address indexed spender, uint256 amount)', ])