Skip to content

Commit

Permalink
add fund route and approval funcitons
Browse files Browse the repository at this point in the history
  • Loading branch information
sehyunc committed Feb 11, 2024
1 parent d3611c9 commit 8acd2ac
Show file tree
Hide file tree
Showing 10 changed files with 1,036 additions and 84 deletions.
99 changes: 99 additions & 0 deletions trade.renegade.fi/app/api/fund/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { stylusDevnetEc2 } from "@/lib/stylus";
import { Token } from "@renegade-fi/renegade-js";
import { createPublicClient, createWalletClient, formatEther, formatUnits, http, parseEther, parseUnits } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { parseAbi } from 'viem'

const abi = parseAbi([
'function transfer(address to, uint256 amount) returns (bool)',
'event Transfer(address indexed from, address indexed to, uint256 amount)',
])

export async function GET(request: Request) {
if (!process.env.DEV_PRIVATE_KEY) {
return new Response("DEV_PRIVATE_KEY is required", {
status: 400,
})
}

const { searchParams } = new URL(request.url)
const recipient = searchParams.get('address') as `0x${string}`
if (!recipient) {
return new Response("Address is required", {
status: 400,
})
}

try {
// Account to fund from
const account = privateKeyToAccount(process.env.DEV_PRIVATE_KEY as `0x${string}`);

const publicClient = createPublicClient({
chain: stylusDevnetEc2,
transport: http(),
});

const walletClient = createWalletClient({
account,
chain: stylusDevnetEc2,
transport: http(),
});

// TODO: Check if already funded?

const ethAmount = parseEther("0.1")
const wethAmount = parseEther("1")
const usdcAmount = parseUnits("3000", 18)

// TODO: Parallelize
// Fund with ETH
const hash = await walletClient.sendTransaction({
account,
to: recipient,
value: ethAmount,
})
const transaction = await publicClient.waitForTransactionReceipt({
hash
})
console.log(`Funded ${recipient} with ${formatEther(ethAmount)} ETH. Transaction hash: ${transaction.transactionHash}`)

// Fund with WETH
const { request: wethRequest } = await publicClient.simulateContract({
account,
address: Token.findAddressByTicker("WETH") as `0x${string}`,
abi,
functionName: "transfer",
args: [recipient, wethAmount],
})

const wethHash = await walletClient.writeContract(wethRequest)
const wethTransaction = await publicClient.waitForTransactionReceipt({
hash: wethHash
})
console.log(`Funded ${recipient} with ${formatUnits(wethAmount, 18)} WETH. Transaction hash: ${wethTransaction.transactionHash}`)

// Fund with UDSC
const { request: usdcRequest } = await publicClient.simulateContract({
account,
address: Token.findAddressByTicker("USDC") as `0x${string}`,
abi,
functionName: "transfer",
args: [recipient, usdcAmount],
})

const usdcHash = await walletClient.writeContract(usdcRequest)
const usdcTransaction = await publicClient.waitForTransactionReceipt({
hash: usdcHash
})
console.log(`Funded ${recipient} with ${formatUnits(usdcAmount, 18)} USDC. Transaction hash: ${usdcTransaction.transactionHash}`)

return new Response("Success!", {
status: 200,
})
} catch (error) {
return new Response(`Error funding ${recipient}: ${error}`, {
status: 500,
})
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,26 +1,44 @@
import { useRenegade } from "@/contexts/Renegade/renegade-context"
import { env } from "@/env.mjs"
import {
Button,
Flex,
ModalBody,
ModalFooter,
Spacer,
Text
} from "@chakra-ui/react"


import { useErc20Approve, usePrepareErc20Approve } from "@/generated"
import { CheckIcon } from "@chakra-ui/icons"
import { Token } from "@renegade-fi/renegade-js"
import { useStepper } from "../testnet-stepper"

const MAX_INT = BigInt("115792089237316195423570985008687907853269984665640564039457584007913129639935")

export function ApprovalStep() {
const { accountId } = useRenegade()
const { onNext } = useStepper()
const { config: wethConfig } = usePrepareErc20Approve({
address: Token.findAddressByTicker("WETH") as `0x${string}`,
args: [env.NEXT_PUBLIC_DARKPOOL_CONTRACT as `0x${string}`, MAX_INT]
})
const { isLoading: wethIsLoading, isSuccess: wethIsSuccess, write: approveWETH } = useErc20Approve(wethConfig)

const { config: usdcConfig } = usePrepareErc20Approve({
address: Token.findAddressByTicker("USDC") as `0x${string}`,
args: [env.NEXT_PUBLIC_DARKPOOL_CONTRACT as `0x${string}`, MAX_INT]
})
const { isLoading: usdcIsLoading, isSuccess: usdcIsSuccess, write: approveUSDC } = useErc20Approve(usdcConfig)

const handleApproveWETH = async () => {
if (!accountId || !approveWETH) return
approveWETH()
}

const handleApproval = async () => {
if (!accountId) return
// TODO: Hit approval contract
// TODO: Should funds get automatically deposited into Renegade Wallet?
// Move to loading step
onNext()
const handleApproveUSDC = async () => {
if (!accountId || !approveUSDC) return
approveUSDC()
}

return (
Expand All @@ -30,20 +48,39 @@ export function ApprovalStep() {
alignItems="center"
justifyContent="center"
flexDirection="column"
gap="8px"
textAlign="center"
>
<Text
marginBottom='4'
color="white.50"
fontFamily="Favorit Extended"
fontSize="1.3em"
fontWeight="200"
>
Approve the Renegade contract to use your testnet funds
</Text>
<Spacer />
<Flex gap='4'>
<Flex flexDirection='column'>
<Text marginBottom='2' fontFamily="Aime" fontSize="2em" fontWeight="700" >
WETH
</Text>
<Text fontFamily="Aime" fontSize="2em" fontWeight="700">
USDC
</Text>

</Flex>
<Flex flexDirection='column'>
<Button marginBottom='3' isDisabled={wethIsSuccess} isLoading={wethIsLoading} onClick={handleApproveWETH}>
{wethIsSuccess ? <CheckIcon /> : "Approve"}
</Button>

<Button isDisabled={usdcIsSuccess} isLoading={usdcIsLoading} onClick={handleApproveUSDC}>
{usdcIsSuccess ? <CheckIcon /> : "Approve"}
</Button>
</Flex>
</Flex>
</Flex>
</ModalBody>
</ModalBody >
<ModalFooter justifyContent="center">
<Button
padding="20px"
Expand All @@ -62,9 +99,10 @@ export function ApprovalStep() {
}}
transition="0.15s"
backgroundColor="transparent"
onClick={handleApproval}
isDisabled={!wethIsSuccess && !usdcIsSuccess}
onClick={onNext}
>
Approve
Next
</Button>
</ModalFooter>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Direction } from "@/contexts/Order/types"
import { ArrowForwardIcon } from "@chakra-ui/icons"
import {
Button,
Expand All @@ -10,18 +9,16 @@ import {
Text,
} from "@chakra-ui/react"

import { useLocalStorage } from "usehooks-ts"
import { useStepper } from "../testnet-stepper"
import { useAccount } from "wagmi"
import { ViewEnum, useApp } from "@/contexts/App/app-context"
import { useRouter } from "next/navigation"
import { useAccount } from "wagmi"
import { useStepper } from "../testnet-stepper"

export function ExitStep() {
const router = useRouter()
const { setView } = useApp()
const { address } = useAccount()
const { onClose, ticker } = useStepper()
const [, setDirection] = useLocalStorage('direction', Direction.BUY)
const formattedAddress = address ? address.slice(0, 6) + "..." : ""
if (ticker === 'USDC') {
router.prefetch("/USDC")
Expand Down Expand Up @@ -69,13 +66,16 @@ export function ExitStep() {
backgroundColor="transparent"
onClick={() => {
// TODO: Not good enough, should render in deposit/order contexts and set baseToken accordingly
setDirection(ticker === "USDC" ? Direction.BUY : Direction.SELL)
if (ticker === "USDC") {
router.push("/USDC")
} else {
setView(ViewEnum.DEPOSIT)
onClose()
}
// setDirection(ticker === "USDC" ? Direction.BUY : Direction.SELL)
// if (ticker === "USDC") {
// router.push("/USDC")
// } else {
// setView(ViewEnum.DEPOSIT)
// onClose()
// }
// TODO: Funding with both tokens so no longer need to conditionally step
setView(ViewEnum.DEPOSIT)
onClose()
}}
>
<HStack spacing="4px">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ import {
} from "@chakra-ui/react"
import React, { createContext, useContext, useState } from "react"

import { ApprovalStep } from "@/components/steppers/testnet-stepper/steps/approval-step"
import { DefaultStep } from "@/components/steppers/testnet-stepper/steps/default-step"
import { ExitStep } from "@/components/steppers/testnet-stepper/steps/exit-step"
import { LoadingStep } from "@/components/steppers/testnet-stepper/steps/loading-step"
import { ApprovalStep } from "@/components/steppers/testnet-stepper/steps/approval-step"
import { ApprovalLoadingStep } from "@/components/steppers/testnet-stepper/steps/approval-loading-step"

const TestnetStepperInner = () => {
const { step, onClose } = useStepper()
Expand Down Expand Up @@ -47,12 +46,6 @@ const TestnetStepperInner = () => {
>
{step === Step.APPROVAL && <ApprovalStep />}
</Fade>
<Fade
transition={{ enter: { duration: 0.25 } }}
in={step === Step.APPROVAL_LOADING}
>
{step === Step.APPROVAL_LOADING && <ApprovalLoadingStep />}
</Fade>
<Fade
transition={{ enter: { duration: 0.25 } }}
in={step === Step.EXIT}
Expand All @@ -69,7 +62,6 @@ export enum Step {
DEFAULT,
LOADING,
APPROVAL,
APPROVAL_LOADING,
EXIT,
}

Expand Down
2 changes: 2 additions & 0 deletions trade.renegade.fi/env.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const env = createEnv({
NEXT_PUBLIC_RENEGADE_RELAYER_HOSTNAME: z.string().min(1),
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID: z.string().min(1),
NEXT_PUBLIC_INTERCOM_APP_ID: z.string().min(1),
NEXT_PUBLIC_DARKPOOL_CONTRACT: z.string().min(1),
},
// For Next.js >= 13.4.4, you only need to destructure client variables:
experimental__runtimeEnv: {
Expand All @@ -15,5 +16,6 @@ export const env = createEnv({
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID:
process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID,
NEXT_PUBLIC_INTERCOM_APP_ID: process.env.NEXT_PUBLIC_INTERCOM_APP_ID,
NEXT_PUBLIC_DARKPOOL_CONTRACT: process.env.NEXT_PUBLIC_DARKPOOL_CONTRACT,
},
})
Loading

0 comments on commit 8acd2ac

Please sign in to comment.