Skip to content

Commit

Permalink
Merge pull request #4 from hackbg/main
Browse files Browse the repository at this point in the history
Feat: Add AVAX/USD feed
  • Loading branch information
danielgruesso authored Oct 30, 2023
2 parents 18cdcc0 + b168c64 commit da1260f
Show file tree
Hide file tree
Showing 11 changed files with 531 additions and 127 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ For your convenience the deploy script has all the constructor arguments filled

After deploying the `DataStreamsConsumer` contract you should register your upkeep by following [Chainlink's guide](https://docs.chain.link/data-streams/getting-started#register-the-upkeep). In our use case "Contract to automate" and "Contract emitting logs" are the same contract i.e `DataStreamsConsumer`. When you choose "Contract emitting logs" you should click the "use custom ABI instead?" option and send the `DataStreamsConsumer.sol` ABI from the `artifacts/contracts/DataStreamsConsumer.sol/DataStreamsConsumer.json` file. After sending the ABI you will have to pick an emitted log. Pick the `InitiateTrade` option from the select with the events options and continue registering your upkeep.

You should set an initiale balance of at least 2 LINK. The other inputs are optional and you can enter whatever value you want.
You should set an initial balance of at least 2 LINK. The other inputs are optional and you can enter whatever value you want.

## Emit a log

Expand Down
4 changes: 3 additions & 1 deletion app/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,9 @@ export default function Home() {
</div>
</TableCell>
{isTradeEnabled && (
<TableCell className="rounded-r-md text-right"></TableCell>
<TableCell className="rounded-r-md text-right">
<TradeButton pair={Pair.AVAX_USD} />
</TableCell>
)}
</TableRow>
</TableBody>
Expand Down
114 changes: 91 additions & 23 deletions app/src/components/trade-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@ import { DialogFooter, DialogTrigger } from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Form, FormField, FormItem, FormLabel } from "@/components//ui/form";
import { avaxAddress, symbols, usdcAddress } from "@/config/trade";
import { symbols } from "@/config/trade";
import { useDatafeed } from "@/app/datafeed-provider";
import { Pair } from "@/_types";
import { Pair, chainlinkPairToFeedId } from "@/_types";
import { useState } from "react";
import { wethConfig, proxyConfig, usdcConfig } from "@/config/contracts";
import {
wethConfig,
proxyConfig,
usdcConfig,
avaxConfig,
} from "@/config/contracts";

const formSchema = z.object({
from: z.coerce.number().gt(0),
Expand All @@ -35,12 +40,18 @@ const TradeDialog = ({ pair }: { pair: Pair }) => {
const { address } = useAccount();
const { prices } = useDatafeed();
const [tokenA, setTokenA] = useState<Address | undefined>(
pair === Pair.AVAX_USD ? avaxAddress : undefined,
pair === Pair.AVAX_USD ? avaxConfig.address : wethConfig.address,
);
const [tokenB, setTokenB] = useState<Address | undefined>(usdcAddress);
const [tokenB, setTokenB] = useState<Address | undefined>(usdcConfig.address);
const { data: tokenABalance } = useBalance({ address, token: tokenA });
const { data: tokenBBalance } = useBalance({ address, token: tokenB });

const [feedId, setFeedId] = useState(
pair === Pair.AVAX_USD
? chainlinkPairToFeedId[Pair.AVAX_USD]
: chainlinkPairToFeedId[Pair.ETH_USD],
);

const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
Expand Down Expand Up @@ -75,6 +86,40 @@ const TradeDialog = ({ pair }: { pair: Pair }) => {
},
});

const { writeAsync: approveAvax } = useContractWrite({
...avaxConfig,
functionName: "approve",
onError(error) {
toast({
variant: "destructive",
title: error.name,
description: error.message,
});
},
onSuccess() {
toast({
title: "Approve transaction has been sent",
});
},
});

const { writeAsync: approveUsdc } = useContractWrite({
...usdcConfig,
functionName: "approve",
onError(error) {
toast({
variant: "destructive",
title: error.name,
description: error.message,
});
},
onSuccess() {
toast({
title: "Approve transaction has been sent",
});
},
});

const { writeAsync: trade } = useContractWrite({
...proxyConfig,
functionName: "trade",
Expand All @@ -94,8 +139,14 @@ const TradeDialog = ({ pair }: { pair: Pair }) => {

async function onSubmit(values: z.infer<typeof formSchema>) {
setIsLoading(true);
setFeedId(
tokenA === wethConfig.address
? chainlinkPairToFeedId[Pair.ETH_USD]
: chainlinkPairToFeedId[Pair.AVAX_USD],
);
const amountA = parseUnits(`${values.from}`, tokenABalance?.decimals ?? 0);
const amountB = parseUnits(`${values.to}`, tokenBBalance?.decimals ?? 0);

if (amountA > (tokenABalance?.value ?? BigInt(0))) {
toast({
title: "Error:",
Expand All @@ -105,19 +156,31 @@ const TradeDialog = ({ pair }: { pair: Pair }) => {
setIsLoading(false);
return;
}
await wrapEth({
to: wethConfig.address,
value: fromAmount ? parseEther(`${fromAmount}`) : undefined,
});
await approveWeth({
args: [proxyConfig.address, parseEther(`${fromAmount}`)],
});

if (tokenA == wethConfig.address) {
await wrapEth({
to: wethConfig.address,
value: fromAmount ? parseEther(`${fromAmount}`) : undefined,
});
await approveWeth({
args: [proxyConfig.address, parseEther(`${fromAmount}`)],
});
}

if (tokenA == avaxConfig.address) {
await approveAvax({
args: [proxyConfig.address, parseEther(`${fromAmount}`)],
});
}

if (tokenA == usdcConfig.address) {
await approveUsdc({
args: [proxyConfig.address, parseEther(`${fromAmount}`)],
});
}

await trade({
args: [
wethConfig.address,
usdcConfig.address,
parseEther(`${fromAmount}`),
],
args: [tokenA!, tokenB!, parseEther(`${fromAmount}`), feedId],
});
toast({
title: "Swap completed:",
Expand Down Expand Up @@ -150,7 +213,7 @@ const TradeDialog = ({ pair }: { pair: Pair }) => {
}
form.setValue(
"to",
tokenA === usdcAddress
tokenA === usdcConfig.address
? Math.round(
(Number(e.target.value) + Number.EPSILON) * 100,
) /
Expand Down Expand Up @@ -188,7 +251,7 @@ const TradeDialog = ({ pair }: { pair: Pair }) => {
</div>
<div className="flex w-full items-center space-x-6">
<div className="h-[1px] flex-1 bg-border" />
{/* <Button
<Button
variant="ghost"
onClick={(e) => {
e.preventDefault();
Expand All @@ -197,9 +260,14 @@ const TradeDialog = ({ pair }: { pair: Pair }) => {
const values = form.getValues();
form.reset({ from: values.to, to: values.from });
}}
> */}
<Image src="/sync-arrows.svg" height={16} width={16} alt="arrows" />
{/* </Button> */}
>
<Image
src="/sync-arrows.svg"
height={16}
width={16}
alt="arrows"
/>
</Button>
<div className="h-[1px] flex-1 bg-border" />
</div>
<div className="grid w-full grid-cols-2">
Expand All @@ -221,7 +289,7 @@ const TradeDialog = ({ pair }: { pair: Pair }) => {
}
form.setValue(
"from",
tokenA === usdcAddress
tokenA === usdcConfig.address
? Number(e.target.value) * Number(prices[pair])
: Math.round(
(Number(e.target.value) + Number.EPSILON) * 100,
Expand Down
Loading

0 comments on commit da1260f

Please sign in to comment.