diff --git a/apps/example/app/globals.css b/apps/example/app/globals.css index cc12b1d..c75e022 100644 --- a/apps/example/app/globals.css +++ b/apps/example/app/globals.css @@ -5,6 +5,10 @@ :root { --background: 0 0% 98%; --foreground: 0 0% 100%; + --muted: 0 0% 100%; + + --popover: 0 0% 100%; + --text-color: 93 17% 10%; /* across teal */ @@ -12,33 +16,44 @@ /* gray */ --border: 220 14% 96%; - --ring: 0 100% 65%; - - --black: 93 17% 10%; - --white: 0, 0%, 100%; + --ring: 166 92% 70%; /* Leaving this here if we want to have different status colors for light/dark */ --success: 119 90% 35%; - --fail: 0 100% 65%; - --loading: 50 52% 66%; - --idle: 0 0% 68%; + --destructive: 0 100% 65%; } .dark { - --background: 0 0% 12%; - --foreground: 0 0% 16%; - --text-color: 0 0% 100%; + --background: 230 6% 19%; + --foreground: 231.43 6.31% 21.76%; - /* gray */ - --border: 0 0% 21%; + --muted: 231.43 6.31% 21.76%; + + --popover: 240 5.88% 13.33%; - --chainlink-blue: #2a5ada; + --text-color: 204 30% 83%; - --ring: 0 100% 65%; + /* gray */ + --border: 226.67 5.52% 31.96%; + --border-secondary: 226.67 6.77% 26.08%; + + --ring: 226.67 6.77% 60%; /* Leaving this here if we want to have different status colors for light/dark */ --success: 133 56% 55%; - --fail: 0 95% 66%; - --loading: 50 52% 66%; - --idle: 0 0 68%; + --destructive: 0 95% 66%; +} + +* { + font-weight: 200; +} + +/* remove arrows from number input */ +@layer base { + input[type="number"]::-webkit-outer-spin-button, + input[type="number"]::-webkit-inner-spin-button, + input[type="number"] { + -webkit-appearance: none; + -moz-appearance: textfield !important; + } } diff --git a/apps/example/app/page.tsx b/apps/example/app/page.tsx index 96aff5d..fe1b32f 100644 --- a/apps/example/app/page.tsx +++ b/apps/example/app/page.tsx @@ -1,12 +1,12 @@ -import { Header } from "./viem/components"; +import { Header, Bridge } from "./viem/components"; import { Providers } from "./viem/providers"; export default function Home() { return (
-
-
+
+
); diff --git a/apps/example/app/viem/components/Bridge.tsx b/apps/example/app/viem/components/Bridge.tsx new file mode 100644 index 0000000..f3dd9f7 --- /dev/null +++ b/apps/example/app/viem/components/Bridge.tsx @@ -0,0 +1,187 @@ +"use client"; + +import { ChainSelect } from "@/components/ChainSelect"; +import { Divider } from "@/components/Divider"; +import { TokenSelect } from "@/components/TokenSelect"; +import { Button, Input, Label, Skeleton } from "@/components/ui"; +import { useAvailableRoutes } from "@/lib/hooks/useAvailableRoutes"; +import { useInputTokens } from "@/lib/hooks/useInputTokens"; +import { useOutputTokens } from "@/lib/hooks/useOutputTokens"; +import { useQuote } from "@/lib/hooks/useQuote"; +import { useSupportedAcrossChains } from "@/lib/hooks/useSupportedAcrossChains"; +import { cn, reduceAcrossChains } from "@/lib/utils"; +import { TokenInfo } from "@across-toolkit/sdk"; +import { useEffect, useState } from "react"; +import { Address, formatUnits, parseUnits } from "viem"; +import { useAccount, useChains } from "wagmi"; +import { useDebounce } from "@uidotdev/usehooks"; + +export function Bridge() { + const { address } = useAccount(); + const chains = useChains(); + // CHAINS + + const { supportedChains } = useSupportedAcrossChains({}); + + // use only token data for chains we support + const acrossChains = reduceAcrossChains(supportedChains, [...chains]); + + // Optimism default input chain + const defaultOriginChainId = chains.find((chain) => chain.id === 10)?.id; + const [originChainId, setOriginChainId] = useState( + defaultOriginChainId, + ); + + // FROM TOKEN + const { inputTokens } = useInputTokens(originChainId); + const [fromTokenAddress, setFromTokenAddress] = useState
( + inputTokens?.[2]?.address, + ); + const inputToken = inputTokens?.find( + (token) => token.address.toLowerCase() === fromTokenAddress?.toLowerCase(), + ); + + const [destinationChainId, setDestinationChainId] = useState< + number | undefined + >(chains.find((chain) => chain.id !== originChainId)?.id); + + const { availableRoutes } = useAvailableRoutes({ + originChainId, + destinationChainId, + originToken: fromTokenAddress, + }); + + const outputTokensForRoute = availableRoutes?.map((route) => + route.outputToken.toLowerCase(), + ); + + const { outputTokens: outputTokensForChain } = + useOutputTokens(destinationChainId); + + const [outputTokens, setOutputTokens] = useState(); + + useEffect(() => { + const _outputTokens = outputTokensForChain?.filter((token) => + outputTokensForRoute?.includes(token.address.toLowerCase()), + ); + setOutputTokens(_outputTokens); + }, [availableRoutes]); + + const [toTokenAddress, setToTokenAddress] = useState
( + outputTokens?.[0]?.address, + ); + const toToken = outputTokens?.find( + (token) => token.address.toLowerCase() === toTokenAddress?.toLowerCase(), + ); + + useEffect(() => { + if (outputTokens) { + setToTokenAddress(outputTokens?.[0]?.address); + } + }, [outputTokens]); + + const [inputAmount, setInputAmount] = useState(); + const debouncedInputAmount = useDebounce(inputAmount, 300); + const route = availableRoutes?.find( + (route) => + route.outputToken.toLocaleLowerCase() === toTokenAddress?.toLowerCase(), + ); + + const quoteConfig = + route && debouncedInputAmount && inputToken + ? { + route, + recipient: address, + inputAmount: parseUnits(debouncedInputAmount, inputToken?.decimals), + } + : undefined; + + const { quote, isLoading: quoteLoading } = useQuote(quoteConfig); + + return ( + <> +
+
+ +
+ { + setDestinationChainId(undefined); + setOriginChainId(chainId); + }} + /> + + +
+ + + + +
+ + + 1) : true} + tokens={outputTokens} + onTokenChange={setToTokenAddress} + token={toTokenAddress} + /> +
+ + + + + setInputAmount(e.currentTarget.value)} + /> +
+
+ +
+ + {!quote && quoteLoading && ( + + fetching quote... + + )} + {quote && toToken && ( +

+ {parseFloat( + formatUnits(quote.deposit.outputAmount, toToken.decimals), + ).toFixed(3)} +

+ )} + +
+ + ); +} diff --git a/apps/example/app/viem/components/ConnectButton.tsx b/apps/example/app/viem/components/ConnectButton.tsx index 5eeff6d..5d45147 100644 --- a/apps/example/app/viem/components/ConnectButton.tsx +++ b/apps/example/app/viem/components/ConnectButton.tsx @@ -73,7 +73,7 @@ const HamburgerButton = (props: ButtonProps) => {