From a3e338db183f4117f819dc8a3821bdb8335856ba Mon Sep 17 00:00:00 2001 From: Nur Fikri Date: Wed, 15 May 2024 14:40:12 -0400 Subject: [PATCH 01/19] detach widget to single entrypoint --- package-lock.json | 1 + package.json | 1 + src/components/AdaptiveLink.tsx | 8 +--- src/components/Footer.tsx | 7 +-- src/components/Header.tsx | 7 ++- src/pages/_app.tsx | 56 ++-------------------- src/pages/index.tsx | 30 +++++++----- src/styles/globals.css | 2 + src/utils/clients.ts | 2 +- src/widget/Widget.tsx | 83 +++++++++++++++++++++++++++++++++ src/widget/index.ts | 0 11 files changed, 120 insertions(+), 77 deletions(-) create mode 100644 src/widget/Widget.tsx create mode 100644 src/widget/index.ts diff --git a/package-lock.json b/package-lock.json index 12284994..4188cd2b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,6 +65,7 @@ "date-fns": "^3.3.1", "dotenv": "^16.4.5", "download": "^8.0.0", + "kujira.js": "0.9.x", "match-sorter": "^6.3.3", "next": "^14.1.0", "next-seo": "^6.4.0", diff --git a/package.json b/package.json index 4b72b1e2..1c612ff3 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "date-fns": "^3.3.1", "dotenv": "^16.4.5", "download": "^8.0.0", + "kujira.js": "0.9.x", "match-sorter": "^6.3.3", "next": "^14.1.0", "next-seo": "^6.4.0", diff --git a/src/components/AdaptiveLink.tsx b/src/components/AdaptiveLink.tsx index 03b43864..89539cbd 100644 --- a/src/components/AdaptiveLink.tsx +++ b/src/components/AdaptiveLink.tsx @@ -1,7 +1,6 @@ -import Link, { LinkProps } from "next/link"; import { ComponentPropsWithoutRef, useMemo } from "react"; -export type AdaptiveLinkProps = LinkProps & Omit, "href"> & { isExternal?: boolean }; +export type AdaptiveLinkProps = ComponentPropsWithoutRef<"a"> & { isExternal?: boolean }; export function AdaptiveLink({ href, isExternal, rel = "", target, ...props }: AdaptiveLinkProps) { const isActuallyExternal = useMemo(() => { @@ -11,9 +10,6 @@ export function AdaptiveLink({ href, isExternal, rel = "", target, ...props }: A if (typeof href === "string") { return href.startsWith("http"); } - if (typeof href === "object") { - return href.href?.startsWith("http"); - } }, [href, isExternal]); const externalProps = useMemo(() => { @@ -25,7 +21,7 @@ export function AdaptiveLink({ href, isExternal, rel = "", target, ...props }: A }, [isActuallyExternal, rel, target]); return ( -

Crafted by

- @@ -20,7 +21,7 @@ function Footer() { }} /> - + ); } diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 8cbb995e..7fbee42d 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,13 +1,12 @@ -import Link from "next/link"; - +import { AdaptiveLink } from "./AdaptiveLink"; import { IbcFunLogo } from "./IbcFunLogo"; function Header() { return ( ); } diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 5737fbcc..eb6cf1c9 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -1,67 +1,19 @@ -import "@fontsource/jost/latin.css"; import "@/styles/globals.css"; -import "@interchain-ui/react/styles"; -import { ChainProvider } from "@cosmos-kit/react"; -import { WalletProvider } from "@solana/wallet-adapter-react"; -import { PersistQueryClientProvider } from "@tanstack/react-query-persist-client"; import { Analytics } from "@vercel/analytics/react"; import { AppProps } from "next/app"; -import { ComponentProps } from "react"; -import { WagmiProvider } from "wagmi"; -import { getAssetLists, getChains } from "@/chains"; import { DefaultSeo } from "@/components/DefaultSeo"; -import { metadata } from "@/constants/seo"; -import { wallets } from "@/lib/cosmos-kit"; -import { persister, queryClient } from "@/lib/react-query"; -import { solanaWallets } from "@/lib/solana-wallet-adapter"; -import { config } from "@/lib/wagmi"; - -type ChainProviderProps = ComponentProps; - -const assets = getAssetLists() as ChainProviderProps["assetLists"]; -const chains = getChains() as ChainProviderProps["chains"]; +import { Provider } from "@/widget/Widget"; export default function App({ Component, pageProps }: AppProps) { return ( <> - - - - - - - - - + + + ); } diff --git a/src/pages/index.tsx b/src/pages/index.tsx index cfaa72b5..ba34f5e1 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,17 +1,25 @@ -import { SwapWidget } from "@/components/SwapWidget"; -import { WalletModalProvider } from "@/components/WalletModal"; -import { DefaultLayout } from "@/layouts/default"; +import Footer from "@/components/Footer"; +import Header from "@/components/Header"; +import { Help } from "@/components/Help"; +import SkipBanner from "@/components/SkipBanner"; +import { VersionCheck } from "@/components/VersionCheck"; +import { Widget } from "@/widget/Widget"; export default function Home() { return ( - -
-
- - - + <> +
+ +
+
+
+ +
+
-
- + + + + ); } diff --git a/src/styles/globals.css b/src/styles/globals.css index b5c61c95..de61c382 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -1,3 +1,5 @@ +@import "@fontsource/jost/latin.css"; + @tailwind base; @tailwind components; @tailwind utilities; diff --git a/src/utils/clients.ts b/src/utils/clients.ts index 1e5140a7..617d5862 100644 --- a/src/utils/clients.ts +++ b/src/utils/clients.ts @@ -1,6 +1,6 @@ import { CosmWasmClient } from "@cosmjs/cosmwasm-stargate"; import { StargateClient } from "@cosmjs/stargate"; -import { accountParser } from "@skip-router/core/parser"; +import { accountParser } from "kujira.js"; import { appUrl } from "@/constants/api"; diff --git a/src/widget/Widget.tsx b/src/widget/Widget.tsx new file mode 100644 index 00000000..21e5d7d9 --- /dev/null +++ b/src/widget/Widget.tsx @@ -0,0 +1,83 @@ +import { ChainProvider } from "@cosmos-kit/react"; +import { WalletProvider } from "@solana/wallet-adapter-react"; +import { PersistQueryClientProvider } from "@tanstack/react-query-persist-client"; +import { ComponentProps, ReactNode } from "react"; +import { Toaster } from "react-hot-toast"; +import { WagmiProvider } from "wagmi"; + +import { getAssetLists, getChains } from "@/chains"; +import { SwapWidget } from "@/components/SwapWidget"; +import { WalletModalProvider } from "@/components/WalletModal"; +import { metadata } from "@/constants/seo"; +import { AssetsProvider } from "@/context/assets"; +import { wallets } from "@/lib/cosmos-kit"; +import { persister, queryClient } from "@/lib/react-query"; +import { solanaWallets } from "@/lib/solana-wallet-adapter"; +import { config } from "@/lib/wagmi"; +import { SkipProvider } from "@/solve"; + +type ChainProviderProps = ComponentProps; + +const assets = getAssetLists() as ChainProviderProps["assetLists"]; +const chains = getChains() as ChainProviderProps["chains"]; + +export const Provider = ({ children }: { children: ReactNode }) => { + return ( + + + + + + + {children} + + + + + + + + ); +}; + +export const Widget = () => { + return ( + + + + ); +}; diff --git a/src/widget/index.ts b/src/widget/index.ts new file mode 100644 index 00000000..e69de29b From 2b5bc53afb270f506fbed413aa9c3b6308de99e5 Mon Sep 17 00:00:00 2001 From: Nur Fikri Date: Wed, 15 May 2024 15:24:44 -0400 Subject: [PATCH 02/19] remove next image --- src/components/ChainSelect/ChainSelectContent.tsx | 3 +-- src/components/ConnectedWalletButton.tsx | 4 +--- src/components/PreviewRoute/ChainStep.tsx | 9 +++------ src/components/PreviewRoute/SetAddressDialog.tsx | 4 +--- src/components/WalletModal/WalletModal.tsx | 4 +--- 5 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/components/ChainSelect/ChainSelectContent.tsx b/src/components/ChainSelect/ChainSelectContent.tsx index 8ab80080..c6852fe6 100644 --- a/src/components/ChainSelect/ChainSelectContent.tsx +++ b/src/components/ChainSelect/ChainSelectContent.tsx @@ -1,7 +1,6 @@ import { ArrowLeftIcon } from "@heroicons/react/20/solid"; import * as ScrollArea from "@radix-ui/react-scroll-area"; import { matchSorter } from "match-sorter"; -import Image from "next/image"; import { useEffect, useMemo, useRef, useState } from "react"; import { Chain } from "@/hooks/useChains"; @@ -87,7 +86,7 @@ function ChainSelectContent({ chains, onChange, onClose }: Props) { onClick={() => onChange(chain)} data-testid="chain-item" > - {chain.prettyName}( ref={ref} > {walletLogo && ( - {walletName}
- {chainAddress?.source !== "input" ? ( - {"wallet"} {chainAddress?.source !== "input" ? ( - {"wallet"} {wallet.walletInfo.logo && ( - {wallet.walletPrettyName} {wallet.walletInfo.logo && ( - {wallet.walletPrettyName} Date: Thu, 16 May 2024 17:44:36 -0400 Subject: [PATCH 03/19] widget page --- src/components/TransactionDialog.tsx | 2 +- src/pages/_app.tsx | 2 +- src/pages/_document.tsx | 16 ++-------------- src/pages/index.tsx | 14 +++++++++++--- src/pages/widget.tsx | 9 +++++++++ src/widget/index.ts | 1 + 6 files changed, 25 insertions(+), 19 deletions(-) create mode 100644 src/pages/widget.tsx diff --git a/src/components/TransactionDialog.tsx b/src/components/TransactionDialog.tsx index 7f0d0ddb..d51a564d 100644 --- a/src/components/TransactionDialog.tsx +++ b/src/components/TransactionDialog.tsx @@ -71,7 +71,7 @@ function TransactionDialog({ className={cn( "w-full rounded-md bg-[#FF486E] py-4 font-semibold text-white outline-none transition-[opacity,transform]", "disabled:cursor-not-allowed disabled:opacity-75", - "enabled:hover:rotate-1 enabled:hover:scale-105", + "enabled:hover:rotate-1", )} disabled={!route || (typeof isLoading === "boolean" && isLoading)} onClick={() => confirmControl.open()} diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index eb6cf1c9..76fa7029 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -4,7 +4,7 @@ import { Analytics } from "@vercel/analytics/react"; import { AppProps } from "next/app"; import { DefaultSeo } from "@/components/DefaultSeo"; -import { Provider } from "@/widget/Widget"; +import { Provider } from "@/widget"; export default function App({ Component, pageProps }: AppProps) { return ( diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx index 7ab842f7..9807d9f7 100644 --- a/src/pages/_document.tsx +++ b/src/pages/_document.tsx @@ -1,13 +1,8 @@ import { Head, Html, Main, NextScript } from "next/document"; -import { cn } from "@/utils/ui"; - export default function Document() { return ( - + - +
diff --git a/src/pages/index.tsx b/src/pages/index.tsx index ba34f5e1..7d8d5e37 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -3,11 +3,19 @@ import Header from "@/components/Header"; import { Help } from "@/components/Help"; import SkipBanner from "@/components/SkipBanner"; import { VersionCheck } from "@/components/VersionCheck"; -import { Widget } from "@/widget/Widget"; +import { cn } from "@/utils/ui"; +import { Widget } from "@/widget"; export default function Home() { return ( - <> +
@@ -20,6 +28,6 @@ export default function Home() {
- +
); } diff --git a/src/pages/widget.tsx b/src/pages/widget.tsx new file mode 100644 index 00000000..e556ec5f --- /dev/null +++ b/src/pages/widget.tsx @@ -0,0 +1,9 @@ +import { Widget } from "@/widget"; + +export default function WidgetPage() { + return ( +
+ +
+ ); +} diff --git a/src/widget/index.ts b/src/widget/index.ts index e69de29b..b3b50ff2 100644 --- a/src/widget/index.ts +++ b/src/widget/index.ts @@ -0,0 +1 @@ +export { Provider, Widget } from "./Widget"; From 5ae4f737050925cda435465cbc28e305143000f6 Mon Sep 17 00:00:00 2001 From: Nur Fikri Date: Thu, 16 May 2024 17:56:14 -0400 Subject: [PATCH 04/19] remove rounded edge --- src/components/Dialog/DialogContent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Dialog/DialogContent.tsx b/src/components/Dialog/DialogContent.tsx index d0d04e6f..68e4c209 100644 --- a/src/components/Dialog/DialogContent.tsx +++ b/src/components/Dialog/DialogContent.tsx @@ -16,7 +16,7 @@ export function DialogContent({ children, onInteractOutside }: Props) { return ( {children} From 1d23d55f689aa51305e76fcac154692fe35de287 Mon Sep 17 00:00:00 2001 From: Nur Fikri Date: Thu, 16 May 2024 18:03:26 -0400 Subject: [PATCH 05/19] remove outer wallet --- src/components/WalletModal/WalletListItem.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/WalletModal/WalletListItem.tsx b/src/components/WalletModal/WalletListItem.tsx index 0b74ec5f..a2f2b263 100644 --- a/src/components/WalletModal/WalletListItem.tsx +++ b/src/components/WalletModal/WalletListItem.tsx @@ -49,6 +49,9 @@ const CosmosWalletListItem = ({ if ("snapInstalled" in walletClient) { return walletClient.snapInstalled; } + if (wallet?.prettyName.toLowerCase() === "outer wallet") { + return false; + } if (_isMobile) { return isWalletConnect || walletClient; } @@ -56,7 +59,7 @@ const CosmosWalletListItem = ({ return !isWalletConnect; } return true; - }, [_isMobile, isWalletConnect, walletClient]); + }, [_isMobile, isWalletConnect, wallet?.prettyName, walletClient]); useEffect(() => { const unregister = () => { From 86026fbd8301492bfca1304e17ffdc982e8c5668 Mon Sep 17 00:00:00 2001 From: Nur Fikri Date: Fri, 17 May 2024 18:02:45 -0400 Subject: [PATCH 06/19] url query param --- package-lock.json | 17 +++ package.json | 1 + src/components/SwapWidget/useSwapWidget.ts | 125 ++++++++++++++++++++- 3 files changed, 140 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4188cd2b..2b410cd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -69,6 +69,7 @@ "match-sorter": "^6.3.3", "next": "^14.1.0", "next-seo": "^6.4.0", + "nuqs": "^1.17.4", "postcss": "^8.4.33", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -30144,6 +30145,11 @@ } } }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==" + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -30903,6 +30909,17 @@ "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", "peer": true }, + "node_modules/nuqs": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/nuqs/-/nuqs-1.17.4.tgz", + "integrity": "sha512-wraphFfKI+Y/aWIGFsld/Ta7fTFEyeya1LkgEGNPDiMuY+Hwea/eVHBiq1GYlyMqTYSAoxRWvQyjCIo1Dy1u7g==", + "dependencies": { + "mitt": "^3.0.1" + }, + "peerDependencies": { + "next": ">=13.4 <14.0.2 || ^14.0.3" + } + }, "node_modules/nwsapi": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", diff --git a/package.json b/package.json index 1c612ff3..801b686c 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "match-sorter": "^6.3.3", "next": "^14.1.0", "next-seo": "^6.4.0", + "nuqs": "^1.17.4", "postcss": "^8.4.33", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/src/components/SwapWidget/useSwapWidget.ts b/src/components/SwapWidget/useSwapWidget.ts index 17d5fef4..52241997 100644 --- a/src/components/SwapWidget/useSwapWidget.ts +++ b/src/components/SwapWidget/useSwapWidget.ts @@ -3,6 +3,8 @@ import { useManager as useCosmosManager } from "@cosmos-kit/react"; import { Asset, BridgeType } from "@skip-router/core"; import { useWallet } from "@solana/wallet-adapter-react"; import { BigNumber } from "bignumber.js"; +import { matchSorter } from "match-sorter"; +import { useQueryState } from "nuqs"; import { MouseEvent, useCallback, useEffect, useMemo, useState } from "react"; import toast from "react-hot-toast"; import { formatUnits } from "viem"; @@ -15,6 +17,7 @@ import { createJSONStorage, persist, subscribeWithSelector } from "zustand/middl import { shallow } from "zustand/shallow"; import { createWithEqualityFn as create } from "zustand/traditional"; +import { appUrl } from "@/constants/api"; import { EVMOS_GAS_AMOUNT, isChainIdEvmos } from "@/constants/gas"; import { useAssets } from "@/context/assets"; import { useAnyDisclosureOpen } from "@/context/disclosures"; @@ -44,7 +47,7 @@ export function useSwapWidget() { const skipClient = useSkipClient(); - const { assetsByChainID, getFeeAsset } = useAssets(); + const { assetsByChainID, getFeeAsset, isReady: isAssetsReady } = useAssets(); const { data: chains } = useChains(); const { getWalletRepo } = useCosmosManager(); @@ -285,7 +288,7 @@ export function useSwapWidget() { * - if not, select first available asset */ const onDestinationChainChange = useCallback( - async (chain: Chain) => { + async (chain: Chain, injectAsset?: Asset) => { const { destinationAsset: currentDstAsset } = useSwapWidgetStore.getState(); const assets = assetsByChainID(chain.chainID); @@ -317,7 +320,7 @@ export function useSwapWidget() { useSwapWidgetStore.setState({ destinationChain: chain, - destinationAsset: asset, + destinationAsset: injectAsset ? injectAsset : asset, }); }, @@ -673,6 +676,121 @@ export function useSwapWidget() { // #endregion + // #region -- query params + const [srcChainQP, setSrcChainQP] = useQueryState("src_chain"); + const [srcAssetQP, setSrcAssetQP] = useQueryState("src_asset"); + useEffect(() => { + if (!chains || !isAssetsReady) return; + if (srcChainQP) { + const findChain = matchSorter(chains, decodeURI(srcChainQP).toLowerCase(), { + keys: ["chainID", "chainName", "prettyName"], + }); + if (findChain && findChain.length > 0) { + onSourceChainChange(findChain[0]); + if (srcAssetQP) { + const assets = assetsByChainID(findChain[0].chainID); + const findAsset = matchSorter(assets || [], decodeURI(srcAssetQP).toLowerCase(), { + keys: ["symbol", "denom", "recommendedSymbol"], + }); + if (findAsset && findAsset.length > 0) { + onSourceAssetChange(findAsset[0]); + } + } + } + setSrcChainQP(null); + setSrcAssetQP(null); + } + }, [ + assetsByChainID, + chains, + isAssetsReady, + onSourceAssetChange, + onSourceChainChange, + setSrcAssetQP, + setSrcChainQP, + srcAssetQP, + srcChainQP, + ]); + + const [destChainQP, setDestChainQP] = useQueryState("dest_chain"); + const [destAssetQP, setDestAssetQP] = useQueryState("dest_asset"); + useEffect(() => { + if (!chains || !isAssetsReady) return; + if (destChainQP) { + const findChain = matchSorter(chains, decodeURI(destChainQP).toLowerCase(), { + keys: ["chainID", "chainName", "prettyName"], + }); + if (findChain && findChain.length > 0) { + if (destAssetQP) { + const assets = assetsByChainID(findChain[0].chainID); + const findAsset = matchSorter(assets || [], decodeURI(destAssetQP).toLowerCase(), { + keys: ["symbol", "denom", "recommendedSymbol"], + }); + if (findAsset && findAsset.length > 0) { + onDestinationChainChange(findChain[0], findAsset[0]); + setDestChainQP(null); + setDestAssetQP(null); + return; + } + } + onDestinationChainChange(findChain[0]); + } + setDestChainQP(null); + setDestAssetQP(null); + } + }, [ + assetsByChainID, + chains, + isAssetsReady, + onDestinationAssetChange, + onDestinationChainChange, + setDestAssetQP, + setDestChainQP, + destAssetQP, + destChainQP, + ]); + + const [amountInQP, setAmountInQP] = useQueryState("amount_in"); + const [amountOutQP, setAmountOutQP] = useQueryState("amount_out"); + + useEffect(() => { + if (amountInQP) { + onSourceAmountChange(amountInQP); + setAmountOutQP(null); + setAmountInQP(null); + return; + } + if (amountOutQP) { + onDestinationAmountChange(amountOutQP); + setAmountOutQP(null); + setAmountInQP(null); + } + }, [amountInQP, amountOutQP, onDestinationAmountChange, onSourceAmountChange, setAmountInQP, setAmountOutQP]); + + const shareableLink = useMemo(() => { + const params = new URLSearchParams(); + if (srcChain) { + params.set("src_chain", srcChain.chainID.toLowerCase()); + } + if (srcAsset) { + params.set("src_asset", (srcAsset.recommendedSymbol || srcAsset.symbol || srcAsset.denom).toLowerCase()); + } + if (dstChain) { + params.set("dest_chain", dstChain.chainID.toLowerCase()); + } + if (dstAsset) { + params.set("dest_asset", (dstAsset.recommendedSymbol || dstAsset.symbol || dstAsset.denom).toLowerCase()); + } + if (amountIn) { + params.set("amount_in", amountIn); + } + if (amountOut) { + params.set("amount_out", amountOut); + } + return `${appUrl}?${params}`; + }, [srcChain, srcAsset, dstChain, dstAsset, amountIn, amountOut]); + + // #endregion ///////////////////////////////////////////////////////////////////////////// return { @@ -707,6 +825,7 @@ export function useSwapWidget() { sourceFeeAsset: srcFeeAsset, swapPriceImpactPercent, usdDiffPercent, + shareableLink, }; } From d0037c7f3362e3e4a69a9a8aaf87ac7af1430845 Mon Sep 17 00:00:00 2001 From: Nur Fikri Date: Fri, 17 May 2024 18:16:56 -0400 Subject: [PATCH 07/19] share button --- package-lock.json | 104 +++++++++++++++++++++++ package.json | 1 + src/components/ShareButton.tsx | 62 ++++++++++++++ src/components/SwapWidget/SwapWidget.tsx | 5 +- 4 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 src/components/ShareButton.tsx diff --git a/package-lock.json b/package-lock.json index 2b410cd4..ae5ee47c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,6 +40,7 @@ "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-collapsible": "^1.0.3", "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-menubar": "^1.0.4", "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-tooltip": "^1.0.7", @@ -10094,6 +10095,78 @@ } } }, + "node_modules/@radix-ui/react-menu": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.6.tgz", + "integrity": "sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-callback-ref": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menubar": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menubar/-/react-menubar-1.0.4.tgz", + "integrity": "sha512-bHgUo9gayKZfaQcWSSLr++LyS0rgh+MvD89DE4fJ6TkGHvjHgPaBZf44hdka7ogOxIOdj9163J+5xL2Dn4qzzg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-menu": "2.0.6", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@radix-ui/react-use-controllable-state": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-popper": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", @@ -10196,6 +10269,37 @@ } } }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", + "integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-collection": "1.0.3", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-direction": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-scroll-area": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.0.5.tgz", diff --git a/package.json b/package.json index 801b686c..2a557944 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-collapsible": "^1.0.3", "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-menubar": "^1.0.4", "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-tooltip": "^1.0.7", diff --git a/src/components/ShareButton.tsx b/src/components/ShareButton.tsx new file mode 100644 index 00000000..234ac1f3 --- /dev/null +++ b/src/components/ShareButton.tsx @@ -0,0 +1,62 @@ +import { ShareIcon } from "@heroicons/react/20/solid"; +import * as Menubar from "@radix-ui/react-menubar"; +import toast from "react-hot-toast"; + +import { cn } from "@/utils/ui"; + +import { SimpleTooltip } from "./SimpleTooltip"; + +export const ShareButton = ({ shareableLink }: { shareableLink: string }) => { + return ( + + + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/src/components/SwapWidget/SwapWidget.tsx b/src/components/SwapWidget/SwapWidget.tsx index 22484e02..3d32ebe4 100644 --- a/src/components/SwapWidget/SwapWidget.tsx +++ b/src/components/SwapWidget/SwapWidget.tsx @@ -17,6 +17,7 @@ import { Spinner } from "../Icons/Spinner"; import { JsonDialog } from "../JsonDialog"; import { SettingsButton } from "../SettingsButton"; import { SettingsDialog } from "../SettingsDialog"; +import { ShareButton } from "../ShareButton"; import { SimpleTooltip } from "../SimpleTooltip"; import TransactionDialog from "../TransactionDialog"; import { UsdDiff } from "../UsdValue"; @@ -62,6 +63,7 @@ export function SwapWidget() { sourceFeeAsset, swapPriceImpactPercent, usdDiffPercent, + shareableLink, } = useSwapWidget(); const srcAccount = useAccount(sourceChain?.chainID); @@ -97,6 +99,7 @@ export function SwapWidget() {

From

+
@@ -250,7 +253,7 @@ export function SwapWidget() { {sourceChain && isWalletConnected && (
Date: Wed, 22 May 2024 11:04:50 +0700 Subject: [PATCH 08/19] switch to denom query param --- package.json | 1 - src/components/ShareButton.tsx | 61 ++++-------------- src/components/SwapWidget/SwapWidget.tsx | 2 +- src/components/SwapWidget/useSwapWidget.ts | 72 ++++++++++++++-------- src/pages/index.tsx | 2 +- 5 files changed, 61 insertions(+), 77 deletions(-) diff --git a/package.json b/package.json index 2a557944..801b686c 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,6 @@ "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-collapsible": "^1.0.3", "@radix-ui/react-dialog": "^1.0.5", - "@radix-ui/react-menubar": "^1.0.4", "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-tooltip": "^1.0.7", diff --git a/src/components/ShareButton.tsx b/src/components/ShareButton.tsx index 234ac1f3..dd001069 100644 --- a/src/components/ShareButton.tsx +++ b/src/components/ShareButton.tsx @@ -1,5 +1,4 @@ import { ShareIcon } from "@heroicons/react/20/solid"; -import * as Menubar from "@radix-ui/react-menubar"; import toast from "react-hot-toast"; import { cn } from "@/utils/ui"; @@ -9,54 +8,18 @@ import { SimpleTooltip } from "./SimpleTooltip"; export const ShareButton = ({ shareableLink }: { shareableLink: string }) => { return ( - - - - - - - - - - - - - - - - - - - - + ); }; diff --git a/src/components/SwapWidget/SwapWidget.tsx b/src/components/SwapWidget/SwapWidget.tsx index 3d32ebe4..fd525380 100644 --- a/src/components/SwapWidget/SwapWidget.tsx +++ b/src/components/SwapWidget/SwapWidget.tsx @@ -253,7 +253,7 @@ export function SwapWidget() { {sourceChain && isWalletConnected && (
{ if (!chains || !isAssetsReady) return; if (srcChainQP) { - const findChain = matchSorter(chains, decodeURI(srcChainQP).toLowerCase(), { - keys: ["chainID", "chainName", "prettyName"], - }); - if (findChain && findChain.length > 0) { - onSourceChainChange(findChain[0]); + const findChain = chains.find((x) => x.chainID === decodeURI(srcChainQP).toLowerCase()); + if (findChain) { + onSourceChainChange(findChain); if (srcAssetQP) { - const assets = assetsByChainID(findChain[0].chainID); - const findAsset = matchSorter(assets || [], decodeURI(srcAssetQP).toLowerCase(), { - keys: ["symbol", "denom", "recommendedSymbol"], - }); - if (findAsset && findAsset.length > 0) { - onSourceAssetChange(findAsset[0]); + const assets = assetsByChainID(findChain.chainID); + const findAsset = assets.find((x) => x.denom === decodeURI(srcAssetQP).toLowerCase()); + if (findAsset) { + onSourceAssetChange(findAsset); } } } + toast.success("URL parameters processed successfully", { + id: toastId, + duration: 5000, + }); setSrcChainQP(null); setSrcAssetQP(null); } @@ -717,24 +718,24 @@ export function useSwapWidget() { useEffect(() => { if (!chains || !isAssetsReady) return; if (destChainQP) { - const findChain = matchSorter(chains, decodeURI(destChainQP).toLowerCase(), { - keys: ["chainID", "chainName", "prettyName"], - }); - if (findChain && findChain.length > 0) { + const findChain = chains.find((x) => x.chainID === decodeURI(destChainQP).toLowerCase()); + if (findChain) { if (destAssetQP) { - const assets = assetsByChainID(findChain[0].chainID); - const findAsset = matchSorter(assets || [], decodeURI(destAssetQP).toLowerCase(), { - keys: ["symbol", "denom", "recommendedSymbol"], - }); - if (findAsset && findAsset.length > 0) { - onDestinationChainChange(findChain[0], findAsset[0]); + const assets = assetsByChainID(findChain.chainID); + const findAsset = assets.find((x) => x.denom === decodeURI(destAssetQP).toLowerCase()); + if (findAsset) { + onDestinationChainChange(findChain, findAsset); setDestChainQP(null); setDestAssetQP(null); return; } } - onDestinationChainChange(findChain[0]); + onDestinationChainChange(findChain); } + toast.success("URL parameters processed successfully", { + id: toastId, + duration: 5000, + }); setDestChainQP(null); setDestAssetQP(null); } @@ -758,12 +759,20 @@ export function useSwapWidget() { onSourceAmountChange(amountInQP); setAmountOutQP(null); setAmountInQP(null); + toast.success("URL parameters processed successfully", { + id: toastId, + duration: 5000, + }); return; } if (amountOutQP) { onDestinationAmountChange(amountOutQP); setAmountOutQP(null); setAmountInQP(null); + toast.success("URL parameters processed successfully", { + id: toastId, + duration: 5000, + }); } }, [amountInQP, amountOutQP, onDestinationAmountChange, onSourceAmountChange, setAmountInQP, setAmountOutQP]); @@ -773,13 +782,13 @@ export function useSwapWidget() { params.set("src_chain", srcChain.chainID.toLowerCase()); } if (srcAsset) { - params.set("src_asset", (srcAsset.recommendedSymbol || srcAsset.symbol || srcAsset.denom).toLowerCase()); + params.set("src_asset", srcAsset.denom.toLowerCase()); } if (dstChain) { params.set("dest_chain", dstChain.chainID.toLowerCase()); } if (dstAsset) { - params.set("dest_asset", (dstAsset.recommendedSymbol || dstAsset.symbol || dstAsset.denom).toLowerCase()); + params.set("dest_asset", dstAsset.denom.toLowerCase()); } if (amountIn) { params.set("amount_in", amountIn); @@ -790,6 +799,19 @@ export function useSwapWidget() { return `${appUrl}?${params}`; }, [srcChain, srcAsset, dstChain, dstAsset, amountIn, amountOut]); + useEffect(() => { + // this is a loading state when we are waiting for chains and assets to load when query params are present + if ( + (!chains || !isAssetsReady) && + (srcChainQP || srcAssetQP || destChainQP || destAssetQP || amountInQP || amountOutQP) + ) { + toast.loading("URL parameters are being processed...", { + id: toastId, + duration: Infinity, + }); + } + }, [amountInQP, amountOutQP, chains, destAssetQP, destChainQP, isAssetsReady, srcAssetQP, srcChainQP]); + // #endregion ///////////////////////////////////////////////////////////////////////////// diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 7d8d5e37..0ecb0f70 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -20,7 +20,7 @@ export default function Home() {
-
+