Skip to content

Commit

Permalink
add: depositor (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
clmntsnr authored Dec 16, 2024
1 parent 39be322 commit 2d0abd2
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 108 deletions.
1 change: 1 addition & 0 deletions merkl.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default createConfig({
appName: "Merkl",
modes: ["dark", "light"],
defaultTheme: "ignite",
deposit: false,
themes: {
ignite: {
base: createColoring(["#1755F4", "#FF7900", "#0D1530"], ["#1755F4", "#FF7900", "#FFFFFF"]),
Expand Down
1 change: 1 addition & 0 deletions src/components/element/campaign/CampaignLibrary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default function CampaignLibrary({ opportunity, chain }: IProps) {

return (
<CampaignTable
className="w-full"
dividerClassName={index => (index < 2 ? "bg-accent-8" : "bg-main-8")}
hideLabels={!rows?.length}
header={
Expand Down
74 changes: 74 additions & 0 deletions src/components/element/participate/Participate.client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import type { Opportunity } from "@merkl/api";
import { Box, Button, Group, Input, Select, Space, Text } from "dappkit";
import TransactionButton from "packages/dappkit/src/components/dapp/TransactionButton";
import { useMemo, useState } from "react";
import useParticipate from "src/hooks/useParticipate";
import { formatUnits } from "viem";
import Token from "../token/Token";

export type ParticipateProps = {
opportunity: Opportunity;
};

export default function Participate({ opportunity }: ParticipateProps) {
const [tokenAddress, setTokenAddress] = useState();
const [amount, setAmount] = useState<bigint>(0n);
const {
target,
targets,
balance,
token: inputToken,
approve,
deposit,
transaction,
} = useParticipate(opportunity.chainId, opportunity.protocol?.id, opportunity.identifier, tokenAddress, amount);

console.log("tx", transaction, opportunity.identifier, target);

const balanceOptions = useMemo(
() =>
balance?.reduce(
(obj, token) =>
Object.assign(obj, {
[token.address]: (
<>
<Token key={token.address} value token={token} />({formatUnits(token?.balance, token?.decimals)})
</>
),
}),
{},
) ?? {},
[balance],
);
return (
<>
<Box>
<Box size="sm" look="soft" className="flex-row [&>*]:grow">
<Button look="bold" className="justify-center">
Deposit
</Button>
<Button look="soft" className="justify-center">
{target && "TARGET"}
</Button>
</Box>
<Group>
<Input.BigInt state={[amount, setAmount]} base={inputToken?.decimals ?? 18} placeholder="0.0" />
<Select
state={[tokenAddress, setTokenAddress]}
loading={!balanceOptions}
placeholder="Token"
options={balanceOptions}
/>
</Group>
<Input header={<Text size="xs">token0</Text>} />
<Input header={<Text size="xs">token1</Text>} />
<TransactionButton tx={transaction?.approval}>Approve</TransactionButton>
<TransactionButton tx={transaction?.transaction}>Participate</TransactionButton>
</Box>
<Space size="md" />
<Text className="text-center w-full" size="sm">
Warning about the fiability of the feature
</Text>
</>
);
}
32 changes: 0 additions & 32 deletions src/components/element/participate/Participate.tsx

This file was deleted.

67 changes: 34 additions & 33 deletions src/components/element/rewards/ClaimRewardsChainTableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import TransactionButton from "packages/dappkit/src/components/dapp/TransactionB
import Collapsible from "packages/dappkit/src/components/primitives/Collapsible";
import EventBlocker from "packages/dappkit/src/components/primitives/EventBlocker";
import { useWalletContext } from "packages/dappkit/src/context/Wallet.context";
import { Fmt } from "packages/dappkit/src/utils/formatter.service";
import { useMemo, useState } from "react";
import useReward from "src/hooks/resources/useReward";
import { formatUnits } from "viem";
import Tag from "../Tag";
import { ClaimRewardsChainRow } from "./ClaimRewardsChainTable";
import { ClaimRewardsTokenTable } from "./ClaimRewardsTokenTable";
Expand Down Expand Up @@ -40,39 +40,41 @@ export default function ClaimRewardsChainTableRow({
selectedTokens?.size > 0 ? selectedTokens : undefined,
);

const unclaimed = useMemo(() => {
return reward.rewards.reduce(
(sum, { amount, claimed, token: { decimals, price } }) =>
sum + Number.parseFloat(formatUnits(amount - claimed, decimals)) * (price ?? 0),
0,
);
}, [reward]);
const unclaimed = useMemo(
() => reward.rewards.reduce((sum, { amount, claimed, token }) => sum + Fmt.toPrice(amount - claimed, token), 0),
[reward],
);

const renderTokenRewards = useMemo(
() =>
reward.rewards
.sort((a, b) => Number(b.amount - b.claimed - (a.amount - a.claimed)))
.map(_reward => (
<ClaimRewardsTokenTableRow
key={_reward.token.address}
className="cursor-pointer [&>*>*]:cursor-auto"
showCheckbox={isOnCorrectChain && isAbleToClaim}
checkedState={[
selectedTokens.has(_reward.token.address) || !selectedTokens.size,
checked => {
setSelectedTokens(t => {
if (checked) t.add(_reward.token.address);
else t.delete(_reward.token.address);
const renderTokenRewards = useMemo(() => {
return reward.rewards
.sort((a, b) => {
const priceA = Fmt.toPrice(a.amount - a.claimed, a.token);
const priceB = Fmt.toPrice(b.amount - b.claimed, b.token);

return new Set(t);
});
},
]}
reward={_reward}
/>
)),
[reward, selectedTokens, isOnCorrectChain, isAbleToClaim],
);
if (b.amount === b.claimed && a.amount === a.claimed)
return Fmt.toPrice(b.amount, b.token) - Fmt.toPrice(a.amount, a.token);
return priceB - priceA;
})
.map(_reward => (
<ClaimRewardsTokenTableRow
key={_reward.token.address}
className="cursor-pointer [&>*>*]:cursor-auto"
showCheckbox={isOnCorrectChain && isAbleToClaim}
checkedState={[
selectedTokens.has(_reward.token.address) || !selectedTokens.size,
() => {
setSelectedTokens(t => {
if (!t.has(_reward.token.address)) t.add(_reward.token.address);
else t.delete(_reward.token.address);

return new Set(t);
});
},
]}
reward={_reward}
/>
));
}, [reward, selectedTokens.size, selectedTokens, isOnCorrectChain, isAbleToClaim]);

return (
<ClaimRewardsChainRow
Expand Down Expand Up @@ -110,7 +112,6 @@ export default function ClaimRewardsChainTableRow({
}>
<Collapsible state={[open, setOpen]}>
<Space size="md" />
{/* <List size="md" dividerClassName={() => "bg-main-8"}>{renderTokenRewards}</List> */}
<ClaimRewardsTokenTable size="sm" dividerClassName={() => "!bg-main-8"} className="[&>*]:bg-main-4" look="soft">
{renderTokenRewards}
</ClaimRewardsTokenTable>
Expand Down
6 changes: 5 additions & 1 deletion src/components/element/rewards/ClaimRewardsTokenTableRow.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Reward } from "@merkl/api";
import { Checkbox, type Component, Divider, type GetSet, Group, Icon, Space } from "dappkit";
import Collapsible from "packages/dappkit/src/components/primitives/Collapsible";
import { Fmt } from "packages/dappkit/src/utils/formatter.service";
import { useMemo, useState } from "react";
import Tag from "../Tag";
import OpportuntiyButton from "../opportunity/OpportunityButton";
Expand Down Expand Up @@ -58,7 +59,10 @@ export default function ClaimRewardsTokenTableRow({
<Collapsible state={[open, setOpen]}>
<Space size="md" />
{reward.breakdowns
.sort((a, b) => Number(b.amount - b.claimed - (a.amount - a.claimed)))
.sort(
(a, b) => Fmt.toPrice(b.amount - b.claimed, reward.token) - Fmt.toPrice(a.amount - a.claimed, reward.token),
)
.filter(b => b.opportunity !== null)
.map(b => {
return (
<>
Expand Down
1 change: 1 addition & 0 deletions src/config/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export type MerklConfig<T extends Themes> = {
};
tags?: string[];
defaultTheme: keyof T;
deposit?: boolean;
modes: Mode[];
wagmi: Parameters<typeof createWagmiConfig>["0"];
appName: string;
Expand Down
6 changes: 2 additions & 4 deletions src/hooks/resources/useRewards.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import type { Reward } from "@merkl/api";
import { Fmt } from "packages/dappkit/src/utils/formatter.service";
import { useMemo } from "react";
import { formatUnits } from "viem";

function getValueOf(chainRewards: Reward["rewards"], amount: (t: Reward["rewards"][number]) => bigint) {
return chainRewards.reduce((sum, token) => {
const value = Number.parseFloat(formatUnits(amount(token), token.token.decimals)) * (token.token.price ?? 0);

return sum + value;
return sum + Fmt.toPrice(amount(token), token.token);
}, 0);
}

Expand Down
56 changes: 25 additions & 31 deletions src/hooks/useParticipate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import { parseAbi } from "viem";
import { useSendTransaction } from "wagmi";
import { useWriteContract } from "wagmi";

type Targets = Awaited<ReturnType<typeof clientApi.v4.participate.targets.get>>["data"];
type Protocols = Awaited<ReturnType<typeof clientApi.v4.participate.protocols.get>>["data"];
type Targets = Awaited<ReturnType<typeof clientApi.v4.interaction.targets.get>>["data"];
type Protocols = Awaited<ReturnType<typeof clientApi.v4.interaction.protocols.get>>["data"];
type TokenBalances = Awaited<ReturnType<typeof clientApi.v4.tokens.balances.get>>["data"];
type Payload = Parameters<typeof clientApi.v4.participate.transaction.get>[0]["query"];
type Transaction = Awaited<ReturnType<typeof clientApi.v4.participate.transaction.get>>["data"];
type Payload = Parameters<typeof clientApi.v4.interaction.transaction.get>[0]["query"];
type Transaction = Awaited<ReturnType<typeof clientApi.v4.interaction.transaction.get>>["data"];

const abi = parseAbi([
"function approve(address, uint256) returns (bool)",
Expand All @@ -30,15 +30,17 @@ export default function useParticipate(
[chainId: number]: { [protocolId: string]: Targets };
}>();
const [transaction, setTransaction] = useState<Transaction>();
const [protocols, setProtocols] = useState<Protocols>();

const { address } = useWalletContext();
const { sendTransaction } = useSendTransaction();
const { writeContract } = useWriteContract();

const target = useMemo(() => {
if (!chainId || !protocolId) return;
return targets?.[chainId]?.[protocolId]?.find(({ identifier: id }) => id === identifier);

return targets?.[chainId]?.[protocolId]?.find?.(
({ identifier: id }) => id?.toLowerCase?.() === identifier?.toLowerCase?.(),
);
}, [chainId, protocolId, targets, identifier]);

const balance = useMemo(() => {
Expand All @@ -52,10 +54,12 @@ export default function useParticipate(

useEffect(() => {
async function fetchTargets() {
if (!chainId || !protocolId) return;
console.log(chainId, protocolId, identifier);

if (!chainId || !protocolId || !identifier) return;

const { data: targets, ...res } = await clientApi.v4.participate.targets.get({
query: { chainId, protocolId },
const { data: targets, ...res } = await clientApi.v4.interaction.targets.get({
query: { chainId, protocolId, identifier },
});

if (res.status === 200)
Expand All @@ -69,17 +73,7 @@ export default function useParticipate(
}

fetchTargets();
}, [chainId, protocolId]);

useEffect(() => {
async function fetchProtocols() {
const { data: protocols, ...res } = await clientApi.v4.participate.protocols.get({ query: {} });

if (res.status === 200) setProtocols(protocols);
}

fetchProtocols();
}, []);
}, [chainId, protocolId, identifier]);

useEffect(() => {
async function fetchTokenBalances() {
Expand Down Expand Up @@ -121,7 +115,9 @@ export default function useParticipate(
async function fetchTransaction() {
if (!payload) return;

const { data: transaction, ...res } = await clientApi.v4.participate.transaction.get({ query: payload });
const { data: transaction, ...res } = await clientApi.v4.interaction.transaction.get({ query: payload });

console.log("tcx", transaction);

if (res.status === 200) setTransaction(transaction);
}
Expand All @@ -131,22 +127,21 @@ export default function useParticipate(

const approve = useCallback(() => {
if (!transaction) return;
const res = writeContract({
address: payload?.fromTokenAddress as `0x${string}`,
abi,
functionName: "approve",
args: [transaction.tx.to as `0x${string}`, BigInt(payload?.fromAmount ?? "0")],

const res = sendTransaction({
to: transaction.approval.to as `0x${string}`,
data: transaction.approval.data,
});

console.info(res);
}, [transaction, payload, writeContract]);
return res;
}, [transaction, sendTransaction]);

const deposit = useCallback(() => {
if (!transaction) return;

const res = sendTransaction({
to: transaction.tx.to as `0x${string}`,
data: transaction?.tx.data as `0x${string}`,
to: transaction.transaction.to as `0x${string}`,
data: transaction?.transaction.data as `0x${string}`,
});

console.info(res);
Expand All @@ -155,7 +150,6 @@ export default function useParticipate(
return {
target,
targets,
protocols,
token,
balance,
balances,
Expand Down
Loading

0 comments on commit 2d0abd2

Please sign in to comment.