diff --git a/src/components/element/participate/Interact.client.tsx b/src/components/element/participate/Interact.client.tsx index 4dbc4d6..8ab4f35 100644 --- a/src/components/element/participate/Interact.client.tsx +++ b/src/components/element/participate/Interact.client.tsx @@ -1,11 +1,10 @@ import type { Opportunity } from "@merkl/api"; import type { InteractionTarget } from "@merkl/api/dist/src/modules/v4/interaction/interaction.model"; import { - Box, Button, type ButtonProps, - Checkbox, - Collapsible, + Divider, + Dropdown, Group, Icon, PrimitiveTag, @@ -19,6 +18,7 @@ import { useMemo, useState } from "react"; import useBalances from "../../../hooks/useBalances"; import useInteractionTransaction from "../../../hooks/useInteractionTransaction"; import Token from "../token/Token"; +import TransactionOverview from "../transaction/TransactionOverview"; export type InteractProps = { opportunity: Opportunity; @@ -42,7 +42,7 @@ export default function Interact({ target, disabled, }: InteractProps) { - const { chainId, switchChain, address: user, sponsorTransactions, setSponsorTransactions } = useWalletContext(); + const { chainId, switchChain, address: user } = useWalletContext(); const { transaction, reload, @@ -90,6 +90,15 @@ export default function Interact({ ), }); + else if (transaction.approved && !transaction.transaction) + createProps({ + disabled: true, + children: ( + <> + An error occured + + ), + }); // biome-ignore lint/suspicious/noExplicitAny: if (buttonProps) return + + + }> + + Enso + + ); if (target.provider === "zap") return ( <> - {" "} - Zap + + + Zap enables users to effortlessly add liquidity into any concentrated liquidity protocol using any + tokens, thanks to the KyberSwap aggregator. + + + + + + + }> + + {" "} + Kyberswap Zap + + ); }, [target]); const canTransactionBeSponsored = opportunity.chainId === 324; - const [settingsCollapsed, setSettingsCollapsed] = useState(false); return ( <> - - - - {amount && inputToken && ( - - Supply - with{" "} - {providerIcon} - - )} - - setSettingsCollapsed(o => !o)} - size="sm" - look="base" - className="flex flex-nowrap gap-md"> - - - - - - - {canTransactionBeSponsored && ( - - Gasless - - - )} - {settings} - - + + {amount && inputToken && ( + + Supply + with{" "} + {providerIcon} + + )} + {currentInteraction} diff --git a/src/components/element/participate/Participate.tsx b/src/components/element/participate/Participate.tsx index ab8e4d2..da44003 100644 --- a/src/components/element/participate/Participate.tsx +++ b/src/components/element/participate/Participate.tsx @@ -1,7 +1,7 @@ import type { Opportunity } from "@merkl/api"; import { useLocation } from "@remix-run/react"; import { Button, Group, Icon, Input, PrimitiveTag, Text, Value } from "dappkit"; -import { Collapsible } from "dappkit"; +import { Box, Collapsible } from "dappkit"; import { useWalletContext } from "dappkit"; import { Fmt } from "dappkit"; import { Suspense, useMemo, useState } from "react"; @@ -43,6 +43,7 @@ export default function Participate({ const { link } = useOpportunity(opportunity); const location = useLocation(); const isOnOpportunityPage = location.pathname.includes("/opportunities/"); + const [success, setSuccess] = useState(false); const { connected } = useWalletContext(); @@ -118,7 +119,10 @@ export default function Participate({ /> setAmount(undefined)} + onSuccess={() => { + setAmount(undefined); + setSuccess(true); + }} disabled={!loading && !targets?.length} target={targets?.[0]} slippage={slippage} @@ -185,13 +189,14 @@ export default function Participate({ )} - {!!I18n.trad.get.pages.home.depositInformation && ( - - - - {I18n.trad.get.pages.home.depositInformation} - - + + {!loading && !!interactor && ( + + + + {I18n.trad.get.pages.home.depositInformation} + + )} {loading && ( @@ -199,6 +204,21 @@ export default function Participate({ )} {interactor} + + + + + + Deposit successful ! + + + + Your liquidity is now earning rewards (if any are currently being distributed to this opportunity). You'll + soon be able to claim them directly from your dashboard. You can monitor your positions and withdraw your + liquidity anytime directly through the protocol app. + + + ); } diff --git a/src/components/element/rewards/ClaimRewardsChainTableRow.tsx b/src/components/element/rewards/ClaimRewardsChainTableRow.tsx index 7558000..81df2f7 100644 --- a/src/components/element/rewards/ClaimRewardsChainTableRow.tsx +++ b/src/components/element/rewards/ClaimRewardsChainTableRow.tsx @@ -8,6 +8,7 @@ import { Fmt } from "dappkit"; import { useMemo, useState } from "react"; import merklConfig from "../../../config"; import useReward from "../../../hooks/resources/useReward"; +import { UserService } from "../../../modules/user/user.service"; import Tag from "../Tag"; import { ClaimRewardsChainRow } from "./ClaimRewardsChainTable"; import { ClaimRewardsTokenTable } from "./ClaimRewardsTokenTable"; @@ -30,7 +31,7 @@ export default function ClaimRewardsChainTableRow({ const [selectedTokens, setSelectedTokens] = useState>(new Set()); const { address: user, chainId, switchChain } = useWalletContext(); - const isUserRewards = useMemo(() => user === from, [user, from]); + const isUserRewards = useMemo(() => UserService.isSame(user, from), [user, from]); const isAbleToClaim = useMemo( () => isUserRewards && !reward.rewards.every(({ amount, claimed }) => amount === claimed), [isUserRewards, reward], diff --git a/src/components/element/transaction/TransactionOverview.tsx b/src/components/element/transaction/TransactionOverview.tsx new file mode 100644 index 0000000..64fa105 --- /dev/null +++ b/src/components/element/transaction/TransactionOverview.tsx @@ -0,0 +1,78 @@ +import { + Box, + Button, + Checkbox, + Collapsible, + Divider, + Dropdown, + Group, + Icon, + PrimitiveTag, + Space, + Text, + useWalletContext, +} from "dappkit"; +import { type ReactNode, useState } from "react"; + +export interface TransactionOverviewProps { + gas?: number; + allowTxSponsoring?: boolean; + settings?: ReactNode; + children?: ReactNode; +} + +export default function TransactionOverview({ allowTxSponsoring, settings, children }: TransactionOverviewProps) { + const { sponsorTransactions, setSponsorTransactions } = useWalletContext(); + const [settingsCollapsed, setSettingsCollapsed] = useState(false); + + return ( + + + {children} + setSettingsCollapsed(o => !o)} + size="sm" + look="base" + className="flex flex-nowrap gap-md"> + + + + + + + {allowTxSponsoring && ( + + + Sponsor with{" "} + + + Zyfi leverages ZKSync's native account abstraction to allow dApps simplify gas management for + dApps users. + + + + + + + }> + + Zyfi + + + + + + )} + {settings} + + + ); +} diff --git a/src/modules/user/routes/user.$address.header.tsx b/src/modules/user/routes/user.$address.header.tsx index 7178851..7e89c65 100644 --- a/src/modules/user/routes/user.$address.header.tsx +++ b/src/modules/user/routes/user.$address.header.tsx @@ -13,6 +13,7 @@ import useReward from "../../../hooks/resources/useReward"; import useRewards from "../../../hooks/resources/useRewards"; import { RewardService } from "../../../modules/reward/reward.service"; import { TokenService } from "../../../modules/token/token.service"; +import { UserService } from "../user.service"; export async function loader({ params: { address }, request }: LoaderFunctionArgs) { if (!address || !isAddress(address)) throw ""; @@ -63,7 +64,7 @@ export default function Index() { const reward = useMemo(() => rawRewards.find(({ chain: { id } }) => id === chainId), [chainId, rawRewards]); const { claimTransaction } = useReward(reward, user); - const isUserRewards = useMemo(() => user === address, [user, address]); + const isUserRewards = useMemo(() => UserService.isSame(user, address), [user, address]); const isAbleToClaim = useMemo( () => isUserRewards && reward && !reward.rewards.every(({ amount, claimed }) => amount === claimed), [isUserRewards, reward], diff --git a/src/modules/user/user.service.ts b/src/modules/user/user.service.ts new file mode 100644 index 0000000..164cc87 --- /dev/null +++ b/src/modules/user/user.service.ts @@ -0,0 +1,14 @@ +import { isAddressEqual } from "viem"; + +export abstract class UserService { + /** + * Compares addresses to check if they are equal + * @notice needed because addresse can be checksum or not + * @param a address + * @param b address + */ + static isSame(a?: string, b?: string): boolean { + if (a?.startsWith("0x") && b.startsWith("0x")) return isAddressEqual(a as `0x${string}`, b as `0x${string}`); + return false; + } +}