diff --git a/packages/widget-v2/package.json b/packages/widget-v2/package.json
index ec65eb125..adbb4d2af 100644
--- a/packages/widget-v2/package.json
+++ b/packages/widget-v2/package.json
@@ -60,6 +60,7 @@
"jotai": "^2.9.1",
"jotai-tanstack-query": "^0.8.6",
"lodash.debounce": "^4.0.8",
+ "match-sorter": "^6.3.4",
"pluralize": "^8.0.0",
"rc-virtual-list": "^3.14.5",
"react-error-boundary": "^4.0.13",
diff --git a/packages/widget-v2/src/components/AssetChainInput.tsx b/packages/widget-v2/src/components/AssetChainInput.tsx
index 87a2bba0f..1bc2fb36a 100644
--- a/packages/widget-v2/src/components/AssetChainInput.tsx
+++ b/packages/widget-v2/src/components/AssetChainInput.tsx
@@ -6,7 +6,7 @@ import { useTheme } from "styled-components";
import { CogIcon } from "@/icons/CogIcon";
import { Button, GhostButton } from "@/components/Button";
import { useAtom } from "jotai";
-import { skipAssets } from "@/state/skipClient";
+import { skipAssetsAtom, skipChainsAtom } from "@/state/skipClient";
import { useUsdValue } from "@/utils/useUsdValue";
import { formatUSD } from "@/utils/intl";
@@ -26,12 +26,17 @@ export const AssetChainInput = ({
handleChangeChain,
}: AssetChainInputProps) => {
const theme = useTheme();
- const [{ data: assets }] = useAtom(skipAssets);
+ const [{ data: assets }] = useAtom(skipAssetsAtom);
+ const [{ data: chains }] = useAtom(skipChainsAtom)
const selectedAsset = assets?.find(
(asset) => asset.denom === selectedAssetDenom
);
+ const selectedChain = chains?.find(
+ (chain) => chain.chainID === selectedAsset?.chainID
+ );
+
const usdValue = useUsdValue({ ...selectedAsset, value });
return (
@@ -50,7 +55,7 @@ export const AssetChainInput = ({
{selectedAsset ? (
- {selectedAsset?.name}
+ {selectedAsset?.recommendedSymbol}
) : (
@@ -73,7 +78,7 @@ export const AssetChainInput = ({
secondary
gap={4}
>
- on {selectedAsset?.chainName}
+ on {selectedChain?.prettyName}
) : (
diff --git a/packages/widget-v2/src/modals/ManualAddressModal/ManualAddressModal.tsx b/packages/widget-v2/src/modals/ManualAddressModal/ManualAddressModal.tsx
index e9d0da66d..cfcc9a56b 100644
--- a/packages/widget-v2/src/modals/ManualAddressModal/ManualAddressModal.tsx
+++ b/packages/widget-v2/src/modals/ManualAddressModal/ManualAddressModal.tsx
@@ -12,18 +12,18 @@ import { WALLET_LIST } from "@/modals/WalletSelectorModal/WalletSelectorFlow";
import { Button } from "@/components/Button";
import { SmallText, Text } from "@/components/Typography";
import { destinationAssetAtom, destinationWalletAtom } from "@/state/swapPage";
-import { useAtom } from "jotai";
-import { getChain } from "@/state/skipClient";
+import { useAtom, useAtomValue } from "jotai";
+import { skipChainsAtom } from "@/state/skipClient";
export const ManualAddressModal = createModal((modalProps: ModalProps) => {
const { theme } = modalProps;
const modal = useModal();
const [destinationAsset] = useAtom(destinationAssetAtom);
const [, setDestinationWallet] = useAtom(destinationWalletAtom);
- const chain = getChain(destinationAsset?.chainID ?? "");
- const chainName = destinationAsset?.chainName;
- const chainImage = chain.images?.find((image) => image.svg ?? image.png);
- const chainLogo = chainImage?.svg ?? chainImage?.png;
+ const { data: chains } = useAtomValue(skipChainsAtom);
+ const chain = chains?.find(c => c.chainID === destinationAsset?.chainID)
+ const chainName = chain?.prettyName
+ const chainLogo = chain?.logoURI
const [showManualAddressInput, setShowManualAddressInput] = useState(false);
const [manualWalletAddress, setManualWalletAddress] = useState("");
@@ -63,7 +63,7 @@ export const ManualAddressModal = createModal((modalProps: ModalProps) => {
{showManualAddressInput ? (
setShowManualAddressInput(false)}
rightContent={() => (
@@ -155,8 +155,8 @@ const StyledAddressValidatorDot = styled.div<{ validAddress?: boolean }>`
validAddress === true
? `background-color: ${theme.success.text}`
: validAddress === false
- ? `background-color: ${theme.error.text}`
- : ""};
+ ? `background-color: ${theme.error.text}`
+ : ""};
top: calc(50% - 11px / 2);
right: 20px;
diff --git a/packages/widget-v2/src/modals/TokenAndChainSelectorModal/TokenAndChainSelectorModal.tsx b/packages/widget-v2/src/modals/TokenAndChainSelectorModal/TokenAndChainSelectorModal.tsx
index c4fcfe987..c77d823bb 100644
--- a/packages/widget-v2/src/modals/TokenAndChainSelectorModal/TokenAndChainSelectorModal.tsx
+++ b/packages/widget-v2/src/modals/TokenAndChainSelectorModal/TokenAndChainSelectorModal.tsx
@@ -1,16 +1,17 @@
import { createModal, ModalProps, useModal } from "@/components/Modal";
import { Column } from "@/components/Layout";
import { styled } from "styled-components";
-import { useAtom } from "jotai";
-import { ChainWithAsset, ClientAsset, skipAssets } from "@/state/skipClient";
+import { useAtomValue } from "jotai";
+import { ChainWithAsset, ClientAsset, skipAssetsAtom, skipChainsAtom } from "@/state/skipClient";
import { useCallback, useEffect, useMemo, useState } from "react";
import { VirtualList } from "@/components/VirtualList";
import {
- isChainWithAsset,
TokenAndChainSelectorModalRowItem,
Skeleton,
+ isClientAsset,
} from "./TokenAndChainSelectorModalRowItem";
import { TokenAndChainSelectorModalSearchInput } from "./TokenAndChainSelectorModalSearchInput";
+import { matchSorter } from "match-sorter";
export type TokenAndChainSelectorModalProps = ModalProps & {
onSelect: (token: ClientAsset | null) => void;
@@ -22,37 +23,36 @@ export const TokenAndChainSelectorModal = createModal(
(modalProps: TokenAndChainSelectorModalProps) => {
const modal = useModal();
const { onSelect, chainsContainingAsset, asset } = modalProps;
- const [{ data: assets, isPending }] = useAtom(skipAssets);
+ const { data: assets, isLoading: isAssetsLoading } = useAtomValue(skipAssetsAtom);
+ const { isLoading: isChainsLoading } = useAtomValue(skipChainsAtom)
+ const isLoading = isAssetsLoading || isChainsLoading
const [showSkeleton, setShowSkeleton] = useState(true);
const [searchQuery, setSearchQuery] = useState("");
const filteredAssets = useMemo(() => {
- if (!assets) return;
- const filtered = assets.filter((asset) =>
- asset.symbol?.toLowerCase().includes(searchQuery.toLowerCase())
- );
- return filtered;
- }, [searchQuery, assets]);
+ if (!assets) return
+ return matchSorter(assets, searchQuery, {
+ keys: ["recommendedSymbol", "symbol", "denom"],
+ });
+ }, [assets, searchQuery]);
const filteredChains = useMemo(() => {
- if (!chainsContainingAsset) return;
- const filtered = chainsContainingAsset.filter(
- (chain) =>
- chain.chain_name?.toLowerCase().includes(searchQuery.toLowerCase()) ||
- chain.pretty_name?.toLowerCase().includes(searchQuery.toLowerCase())
- );
- return filtered;
- }, [searchQuery, chainsContainingAsset]);
+ if (!chainsContainingAsset) return
+ return matchSorter(chainsContainingAsset, searchQuery, {
+ keys: ["chainID", "chainName", "prettyName"],
+ });
+ }, [chainsContainingAsset, searchQuery]);
+
useEffect(() => {
- if (!isPending && assets) {
+ if (!isLoading && assets) {
const timer = setTimeout(() => {
setShowSkeleton(false);
}, 100);
return () => clearTimeout(timer);
}
- }, [isPending, assets]);
+ }, [isLoading, assets]);
useEffect(() => {
setSearchQuery("");
@@ -93,13 +93,13 @@ export const TokenAndChainSelectorModal = createModal(
listItems={filteredChains ?? filteredAssets ?? []}
height={530}
itemHeight={70}
- renderItem={renderItem}
itemKey={(item) => {
- if (isChainWithAsset(item)) {
- return `${item.chain_id}${item.chain_name}`;
+ if (isClientAsset(item)) {
+ return `${item.denom}-${item.chainID}-${item.recommendedSymbol}`
}
- return `${item.chainID}${item.denom}`;
+ return `${item.chainID}-${item.asset?.denom}`
}}
+ renderItem={renderItem}
/>
)}
diff --git a/packages/widget-v2/src/modals/TokenAndChainSelectorModal/TokenAndChainSelectorModalRowItem.tsx b/packages/widget-v2/src/modals/TokenAndChainSelectorModal/TokenAndChainSelectorModalRowItem.tsx
index d338d441e..3d4bbc0f1 100644
--- a/packages/widget-v2/src/modals/TokenAndChainSelectorModal/TokenAndChainSelectorModalRowItem.tsx
+++ b/packages/widget-v2/src/modals/TokenAndChainSelectorModal/TokenAndChainSelectorModalRowItem.tsx
@@ -1,10 +1,11 @@
import { Row } from "@/components/Layout";
import { ModalRowItem } from "@/components/ModalRowItem";
import { SmallText, Text } from "@/components/Typography";
-import { ChainWithAsset, ClientAsset } from "@/state/skipClient";
+import { ChainWithAsset, ClientAsset, skipChainsAtom } from "@/state/skipClient";
import { CircleSkeletonElement, SkeletonElement } from "@/components/Skeleton";
import { styled } from "styled-components";
-import { Chain } from "@chain-registry/types";
+import { useAtomValue } from "jotai";
+import { Chain } from "@skip-go/client";
export const isClientAsset = (
item: ClientAsset | ChainWithAsset
@@ -15,7 +16,7 @@ export const isClientAsset = (
export const isChainWithAsset = (
item: ClientAsset | ChainWithAsset
): item is ChainWithAsset => {
- return (item as Chain).chain_id !== undefined;
+ return (item as Chain).chainID !== undefined;
};
export type TokenAndChainSelectorModalRowItemProps = {
@@ -31,9 +32,12 @@ export const TokenAndChainSelectorModalRowItem = ({
skeleton,
onSelect,
}: TokenAndChainSelectorModalRowItemProps) => {
- if (!item) return skeleton;
+ const { isLoading: isChainsLoading, data: chains } = useAtomValue(skipChainsAtom)
+
+ if (!item || isChainsLoading) return skeleton;
if (isClientAsset(item)) {
+ const chain = chains?.find((chain) => chain.chainID === item.chainID)
return (
{item.symbol}
- {item.chainName ?? item.originChainID ?? item.chainID}
+ {chain?.prettyName}
}
@@ -58,9 +62,11 @@ export const TokenAndChainSelectorModalRowItem = ({
}
if (isChainWithAsset(item)) {
+
+ const chain = chains?.find((chain) => chain.chainID === item.chainID)
return (
onSelect(item?.asset || null)}
style={{ margin: "5px 0" }}
leftContent={
@@ -68,11 +74,11 @@ export const TokenAndChainSelectorModalRowItem = ({
- {item.pretty_name}
- {item.chain_name}
+ {chain?.prettyName}
+ {item.chainID}
}
/>
diff --git a/packages/widget-v2/src/modals/TransactionHistoryModal/TransactionHistoryModalItem.tsx b/packages/widget-v2/src/modals/TransactionHistoryModal/TransactionHistoryModalItem.tsx
index f23b14426..d1df7a2b6 100644
--- a/packages/widget-v2/src/modals/TransactionHistoryModal/TransactionHistoryModalItem.tsx
+++ b/packages/widget-v2/src/modals/TransactionHistoryModal/TransactionHistoryModalItem.tsx
@@ -1,7 +1,7 @@
import { RouteResponse } from "@skip-go/client";
import { SmallText } from "@/components/Typography";
import { useAtom } from "jotai";
-import { skipAssets, getChain, ClientAsset } from "@/state/skipClient";
+import { skipAssetsAtom, ClientAsset, skipChainsAtom } from "@/state/skipClient";
import { Column, Row } from "@/components/Layout";
import styled, { useTheme } from "styled-components";
import { getFormattedAssetAmount } from "@/utils/crypto";
@@ -56,25 +56,22 @@ export const TransactionHistoryModalItem = ({
timestamp,
status,
} = txHistoryItem;
- const [{ data: assets }] = useAtom(skipAssets);
- const sourceChain = getChain(sourceAssetChainID ?? "");
- const sourceChainImage = sourceChain.images?.find(
- (image) => image.svg ?? image.png
- );
+ const [{ data: assets }] = useAtom(skipAssetsAtom);
+ const [{ data: chains }] = useAtom(skipChainsAtom)
+ const sourceChain = chains?.find(c => c.chainID === sourceAssetChainID)
+ const sourceChainImage = sourceChain?.logoURI
const source = {
amount: amountIn,
asset: assets?.find((asset) => asset.denom === sourceAssetDenom),
- chainImage: sourceChainImage?.svg ?? sourceChainImage?.png ?? "",
+ chainImage: sourceChainImage ?? "",
};
- const destinationChain = getChain(destAssetChainID ?? "");
- const destinationChainImage = destinationChain.images?.find(
- (image) => image.svg ?? image.png
- );
+ const destinationChain = chains?.find(c => c.chainID === destAssetChainID)
+ const destinationChainImage = destinationChain?.logoURI
const destination = {
amount: amountOut,
asset: assets?.find((asset) => asset.denom === destAssetDenom),
- chainImage: destinationChainImage?.svg ?? destinationChainImage?.png ?? "",
+ chainImage: destinationChainImage ?? "",
};
const renderStatus = useMemo(() => {
@@ -119,7 +116,7 @@ export const TransactionHistoryModalItem = ({
- on {destinationChain?.pretty_name ?? destinationChain?.chain_name}
+ on {destinationChain?.prettyName ?? destinationChain?.chainName}
@@ -130,9 +127,9 @@ export const TransactionHistoryModalItem = ({
{showDetails && (
`
+const StyledHistoryContainer = styled(Column) <{ showDetails?: boolean }>`
background-color: ${({ theme, showDetails }) =>
showDetails && theme.secondary.background.normal};
&:hover {
diff --git a/packages/widget-v2/src/pages/SwapExecutionPage/SwapExecutionPageRouteDetailedRow.tsx b/packages/widget-v2/src/pages/SwapExecutionPage/SwapExecutionPageRouteDetailedRow.tsx
index 4a0998d75..36caff9a5 100644
--- a/packages/widget-v2/src/pages/SwapExecutionPage/SwapExecutionPageRouteDetailedRow.tsx
+++ b/packages/widget-v2/src/pages/SwapExecutionPage/SwapExecutionPageRouteDetailedRow.tsx
@@ -1,7 +1,7 @@
import { useAtom } from "jotai";
import { Row } from "@/components/Layout";
import { SmallText } from "@/components/Typography";
-import { getChain, skipAssets } from "@/state/skipClient";
+import { skipAssetsAtom, skipChainsAtom } from "@/state/skipClient";
import { getFormattedAssetAmount } from "@/utils/crypto";
import { css, styled, useTheme } from "styled-components";
import React from "react";
@@ -56,12 +56,13 @@ export const SwapExecutionPageRouteDetailedRow = ({
...props
}: SwapExecutionPageRouteDetailedRowProps) => {
const theme = useTheme();
- const [{ data: assets }] = useAtom(skipAssets);
+ const [{ data: assets }] = useAtom(skipAssetsAtom);
+ const [{ data: chains }] = useAtom(skipChainsAtom);
const asset = assets?.find((asset) => asset.denom === denom);
- const chain = getChain(chainID ?? "");
- const chainImage = chain.images?.find((image) => image.svg ?? image.png);
+ const chain = chains?.find(c => c.chainID === chainID)
+ const chainImage = chain?.logoURI
return (
@@ -75,7 +76,7 @@ export const SwapExecutionPageRouteDetailedRow = ({
@@ -151,7 +152,7 @@ export const StyledAnimatedBorder = ({
);
-const StyledLoadingContainer = styled(Row)<{
+const StyledLoadingContainer = styled(Row) <{
height: number;
width: number;
borderSize: number;
@@ -178,11 +179,11 @@ const StyledLoadingContainer = styled(Row)<{
&:before {
content: '';
position: absolute;
- height: ${({ height }) => `${height + 20}px;`}
- width: ${({ width }) => `${width + 20}px;`}
+ height: ${({ height }) => `${height + 20}px;`};
+ width: ${({ width }) => `${width + 20}px;`};
${({ txState, backgroundColor, theme }) =>
- txState === "broadcasted" &&
- css`
+ txState === "broadcasted" &&
+ css`
background-image: conic-gradient(
transparent,
transparent,
@@ -202,7 +203,7 @@ const StyledLoadingContainer = styled(Row)<{
}
`;
-const StyledLoadingOverlay = styled(Row)<{
+const StyledLoadingOverlay = styled(Row) <{
backgroundColor?: string;
width: number;
height: number;
diff --git a/packages/widget-v2/src/pages/SwapExecutionPage/SwapExecutionPageRouteSimpleRow.tsx b/packages/widget-v2/src/pages/SwapExecutionPage/SwapExecutionPageRouteSimpleRow.tsx
index 4dd21e297..bc82eca7d 100644
--- a/packages/widget-v2/src/pages/SwapExecutionPage/SwapExecutionPageRouteSimpleRow.tsx
+++ b/packages/widget-v2/src/pages/SwapExecutionPage/SwapExecutionPageRouteSimpleRow.tsx
@@ -2,7 +2,7 @@ import { useTheme } from "styled-components";
import { Button } from "@/components/Button";
import { Column, Row } from "@/components/Layout";
import { SmallText, Text } from "@/components/Typography";
-import { getChain, skipAssets } from "@/state/skipClient";
+import { skipAssetsAtom, skipChainsAtom } from "@/state/skipClient";
import { getFormattedAssetAmount } from "@/utils/crypto";
import { Wallet } from "@/components/RenderWalletList";
import { iconMap, ICONS } from "@/icons";
@@ -45,11 +45,12 @@ export const SwapExecutionPageRouteSimpleRow = ({
"mount";
}, []);
const theme = useTheme();
- const [{ data: assets }] = useAtom(skipAssets);
+ const [{ data: assets }] = useAtom(skipAssetsAtom);
+ const [{ data: chains }] = useAtom(skipChainsAtom);
const asset = assets?.find((asset) => asset.denom === denom);
- const chain = getChain(chainID ?? "");
- const chainImage = chain.images?.find((image) => image.svg ?? image.png);
+ const chain = chains?.find((chain) => chain.chainID === chainID);
+ const chainImage = chain?.logoURI
if (!asset) {
throw new Error(`Asset not found for denom: ${denom}`);
@@ -80,7 +81,7 @@ export const SwapExecutionPageRouteSimpleRow = ({
backgroundColor={theme.success.text}
txState={txStateOfAnimatedBorder}
>
-
+
)}
diff --git a/packages/widget-v2/src/pages/SwapPage/SwapPage.tsx b/packages/widget-v2/src/pages/SwapPage/SwapPage.tsx
index cc50824d7..ba3df03dc 100644
--- a/packages/widget-v2/src/pages/SwapPage/SwapPage.tsx
+++ b/packages/widget-v2/src/pages/SwapPage/SwapPage.tsx
@@ -5,7 +5,7 @@ import { Column } from "@/components/Layout";
import { MainButton } from "@/components/MainButton";
import { SmallText } from "@/components/Typography";
import { ICONS } from "@/icons";
-import { skipAssets, getChainsContainingAsset } from "@/state/skipClient";
+import { skipAssetsAtom, getChainsContainingAsset, skipChainsAtom } from "@/state/skipClient";
import { sourceAssetAtom, destinationAssetAtom } from "@/state/swapPage";
import { TokenAndChainSelectorModal } from "@/modals/TokenAndChainSelectorModal/TokenAndChainSelectorModal";
import { SwapPageSettings } from "./SwapPageSettings";
@@ -20,23 +20,24 @@ export const SwapPage = () => {
const [container, setContainer] = useState();
const [drawerOpen, setDrawerOpen] = useState(false);
const [sourceAsset, setSourceAsset] = useAtom(sourceAssetAtom);
- const [{ data: assets }] = useAtom(skipAssets);
+ const [{ data: assets }] = useAtom(skipAssetsAtom);
+ const [{ data: chains }] = useAtom(skipChainsAtom);
const [destinationAsset, setDestinationAsset] = useAtom(destinationAssetAtom);
const swapFlowSettings = useModal(SwapPageSettings);
const tokenAndChainSelectorFlow = useModal(TokenAndChainSelectorModal);
const chainsContainingSourceAsset = useMemo(() => {
- if (!assets || !sourceAsset?.symbol) return;
- const chains = getChainsContainingAsset(sourceAsset?.symbol, assets);
- return chains;
- }, [assets, sourceAsset?.symbol]);
+ if (!chains || !assets || !sourceAsset?.symbol) return;
+ const result = getChainsContainingAsset(sourceAsset?.symbol, assets, chains);
+ return result;
+ }, [assets, sourceAsset?.symbol, chains]);
const chainsContainingDestinationAsset = useMemo(() => {
- if (!assets || !destinationAsset?.symbol) return;
- const chains = getChainsContainingAsset(destinationAsset?.symbol, assets);
- return chains;
- }, [assets, destinationAsset?.symbol]);
+ if (!chains || !assets || !destinationAsset?.symbol) return;
+ const result = getChainsContainingAsset(destinationAsset?.symbol, assets, chains);
+ return result;
+ }, [assets, destinationAsset?.symbol, chains]);
const handleChangeSourceAsset = useCallback(() => {
tokenAndChainSelectorFlow.show({
diff --git a/packages/widget-v2/src/state/chains.ts b/packages/widget-v2/src/state/chains.ts
new file mode 100644
index 000000000..563d16eee
--- /dev/null
+++ b/packages/widget-v2/src/state/chains.ts
@@ -0,0 +1,43 @@
+
+import { Chain, AssetList } from "@chain-registry/types";
+import {
+ chains as chainsChainRegistry,
+ assets as assetsChainRegistry,
+} from "chain-registry";
+import {
+ chains as chainsInitiaRegistry,
+ assets as assetsInitiaRegistry,
+} from "@initia/initia-registry";
+
+export const chains = [
+ ...chainsChainRegistry,
+ ...chainsInitiaRegistry,
+] as Chain[];
+export const assets = [
+ ...assetsChainRegistry,
+ ...assetsInitiaRegistry,
+] as AssetList[];
+
+export function getChain(chainId: string): Chain {
+ const chain = chains.find((c) => c.chain_id === chainId);
+ if (!chain) {
+ throw new Error(`chain '${chainId}' does not exist in chainRecord`);
+ }
+ return chain;
+}
+
+export function chainIdToName(chainId: string): string {
+ return getChain(chainId).chain_name;
+}
+
+export function getAssets(chainId: string) {
+ const chainName = chainIdToName(chainId);
+ const assetsFoundForChain = assets.find(
+ (a) => a.chain_name === chainName
+ )?.assets;
+
+ if (!assetsFoundForChain) {
+ throw new Error(`chain '${chainId}' does not exist in assetsRecord`);
+ }
+ return assetsFoundForChain;
+}
diff --git a/packages/widget-v2/src/state/skipClient.ts b/packages/widget-v2/src/state/skipClient.ts
index 40e33d6c9..6f4d36b45 100644
--- a/packages/widget-v2/src/state/skipClient.ts
+++ b/packages/widget-v2/src/state/skipClient.ts
@@ -1,24 +1,7 @@
import { atom } from "jotai";
-import { Asset, SkipClient } from "@skip-go/client";
-import { Chain, AssetList } from "@chain-registry/types";
-import {
- chains as chainsChainRegistry,
- assets as assetsChainRegistry,
-} from "chain-registry";
-import {
- chains as chainsInitiaRegistry,
- assets as assetsInitiaRegistry,
-} from "@initia/initia-registry";
+import { Asset, SkipClient, Chain } from "@skip-go/client";
import { atomWithQuery } from "jotai-tanstack-query";
-export const chains = [
- ...chainsChainRegistry,
- ...chainsInitiaRegistry,
-] as Chain[];
-export const assets = [
- ...assetsChainRegistry,
- ...assetsInitiaRegistry,
-] as AssetList[];
export const skipClient = atom(new SkipClient());
@@ -27,16 +10,16 @@ export type ClientAsset = Asset & {
chainName: string;
};
-const flattenData = (data: Record) => {
+const flattenData = (data: Record, chains?: Chain[]) => {
const flattenedData: ClientAsset[] = [];
for (const chainKey in data) {
data[chainKey].forEach((asset: Asset) => {
- const chain = chains.find((c) => c.chain_id === asset.chainID);
+ const chain = chains?.find((c) => c.chainID === asset.chainID);
flattenedData.push({
...asset,
chain_key: chainKey,
- chainName: chain?.pretty_name ?? chain?.chain_name ?? "",
+ chainName: chain?.prettyName ?? chain?.chainName ?? asset.chainID ?? "--",
});
});
}
@@ -44,8 +27,10 @@ const flattenData = (data: Record) => {
return flattenedData;
};
-export const skipAssets = atomWithQuery((get) => {
+export const skipAssetsAtom = atomWithQuery((get) => {
const skip = get(skipClient);
+ const chains = get(skipChainsAtom);
+
return {
queryKey: ["skipAssets"],
queryFn: async () => {
@@ -55,57 +40,47 @@ export const skipAssets = atomWithQuery((get) => {
includeCW20Assets: true,
includeSvmAssets: true,
})
- .then(flattenData);
+ .then((v) => flattenData(v, chains.data));
},
};
});
+export const skipChainsAtom = atomWithQuery((get) => {
+ const skip = get(skipClient);
+ return {
+ queryKey: ["skipChains"],
+ queryFn: async () => {
+ return skip.chains({
+ includeEVM: true,
+ includeSVM: true,
+ })
+ }
+ }
+})
+
export type ChainWithAsset = Chain & {
asset?: ClientAsset;
};
export const getChainsContainingAsset = (
assetSymbol: string,
- assets: ClientAsset[]
+ assets: ClientAsset[],
+ chains: Chain[]
): ChainWithAsset[] => {
if (!assets) return [];
const chainIDs = assets
.filter((asset) => asset.symbol === assetSymbol)
.map((asset) => asset.chainID);
const chainsContainingAsset = chains
- .filter((chain) => chainIDs?.includes(chain.chain_id))
+ .filter((chain) => chainIDs?.includes(chain.chainID))
.map((chain) => {
return {
...chain,
asset: assets.find(
(asset) =>
- asset.chainID === chain.chain_id && asset.symbol === assetSymbol
+ asset.chainID === chain.chainID && asset.symbol === assetSymbol
),
};
});
return chainsContainingAsset;
};
-
-export function getChain(chainId: string): Chain {
- const chain = chains.find((c) => c.chain_id === chainId);
- if (!chain) {
- throw new Error(`chain '${chainId}' does not exist in chainRecord`);
- }
- return chain;
-}
-
-export function chainIdToName(chainId: string): string {
- return getChain(chainId).chain_name;
-}
-
-export function getAssets(chainId: string) {
- const chainName = chainIdToName(chainId);
- const assetsFoundForChain = assets.find(
- (a) => a.chain_name === chainName
- )?.assets;
-
- if (!assetsFoundForChain) {
- throw new Error(`chain '${chainId}' does not exist in assetsRecord`);
- }
- return assetsFoundForChain;
-}
diff --git a/packages/widget-v2/src/stories/ManualAddressModals.stories.tsx b/packages/widget-v2/src/stories/ManualAddressModals.stories.tsx
index 799370abc..9af0e3e87 100644
--- a/packages/widget-v2/src/stories/ManualAddressModals.stories.tsx
+++ b/packages/widget-v2/src/stories/ManualAddressModals.stories.tsx
@@ -4,7 +4,7 @@ import { Row } from "@/components/Layout";
import { defaultTheme, lightTheme } from "@/widget/theme";
import { ManualAddressModal } from "@/modals/ManualAddressModal/ManualAddressModal";
import { useEffect, useState } from "react";
-import { skipAssets } from "@/state/skipClient";
+import { skipAssetsAtom } from "@/state/skipClient";
import { destinationAssetAtom } from "@/state/swapPage";
import { useAtom } from "jotai";
@@ -24,7 +24,7 @@ export const ManualAddressModalsExample = () => {
const [destinationAsset, setDestinationAsset] = useAtom(destinationAssetAtom);
const [shouldRender, setShouldRender] = useState(false);
- const [{ data: assets }] = useAtom(skipAssets);
+ const [{ data: assets }] = useAtom(skipAssetsAtom);
const asset = assets?.find((asset) => asset.denom === "uatom");
diff --git a/packages/widget-v2/src/stories/SwapExecutionPage.stories.tsx b/packages/widget-v2/src/stories/SwapExecutionPage.stories.tsx
index 6f5e4ce51..112d76097 100644
--- a/packages/widget-v2/src/stories/SwapExecutionPage.stories.tsx
+++ b/packages/widget-v2/src/stories/SwapExecutionPage.stories.tsx
@@ -5,7 +5,7 @@ import NiceModal from "@ebay/nice-modal-react";
import { destinationAssetAtom } from "@/state/swapPage";
import { useAtom } from "jotai";
import operations from "@/pages/SwapExecutionPage/operations.json";
-import { skipAssets } from "@/state/skipClient";
+import { skipAssetsAtom } from "@/state/skipClient";
import { useEffect, useState } from "react";
const meta = {
@@ -17,7 +17,7 @@ const meta = {
const firstOperation = operations[0];
const lastOperation = operations[operations.length - 1];
- const [{ data: assets }] = useAtom(skipAssets);
+ const [{ data: assets }] = useAtom(skipAssetsAtom);
const sourceAsset = assets?.find(
(asset) => asset.denom === firstOperation.denomIn
diff --git a/packages/widget-v2/src/utils/useUsdValue.ts b/packages/widget-v2/src/utils/useUsdValue.ts
index aa4c680cf..ab8991996 100644
--- a/packages/widget-v2/src/utils/useUsdValue.ts
+++ b/packages/widget-v2/src/utils/useUsdValue.ts
@@ -1,7 +1,8 @@
-import { useQuery } from "@tanstack/react-query";
+import { skipAssetsAtom } from "@/state/skipClient";
+import { useQuery, UseQueryResult } from "@tanstack/react-query";
+import { useAtomValue } from "jotai";
import { useMemo } from "react";
import { z } from "zod";
-import { getAssets } from "@/state/skipClient";
type Args = {
coingeckoID: string;
@@ -37,33 +38,23 @@ const priceResponseSchema = z.object({
});
export type Asset = {
- chainID: string;
denom: string;
- coingeckoID?: string;
value: string;
};
-const getCoinGeckoId = (asset: Asset) => {
- if (asset.coingeckoID) {
- return asset.coingeckoID;
- } else {
- const assets = getAssets(asset.chainID);
- const assetFound = assets.find((a) => a.base === asset.denom);
- if (!assetFound?.coingecko_id) {
- throw new Error(
- `getUsdValue error: ${asset.denom} does not have a 'coingecko_id' in ${asset.chainID}`
- );
- }
- return assetFound.coingecko_id;
- }
-};
-async function getUsdValue(asset: Asset) {
- const usd = await getUsdPrice({ coingeckoID: getCoinGeckoId(asset) });
+
+async function getUsdValue(asset: Asset, coingeckoID?: string) {
+ if (!coingeckoID) {
+ throw new Error(`getUsdValue error: ${asset.denom} does not have a 'coingeckoID'`);
+ }
+ const usd = await getUsdPrice({ coingeckoID });
return parseFloat(asset.value) * usd;
}
-export function useUsdValue(asset?: Partial) {
+
+export function useUsdValue(asset?: Partial): UseQueryResult {
+ const {data: assets} = useAtomValue(skipAssetsAtom)
const queryKey = useMemo(() => ["USE_USD_VALUE", asset] as const, [asset]);
const enabled = useMemo(() => {
@@ -78,7 +69,8 @@ export function useUsdValue(asset?: Partial) {
asset ? [key, ...Object.values(asset)].join("-") : key,
queryFn: async ({ queryKey: [, asset] }) => {
if (asset?.value) {
- return getUsdValue(asset as Asset);
+ const coingeckoID = assets?.find((a) => a.denom === asset.denom)?.coingeckoID
+ return getUsdValue(asset as Asset, coingeckoID);
}
},
staleTime: 1000 * 60, // 1 minute
diff --git a/yarn.lock b/yarn.lock
index 789793a01..a3a99feaa 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -28835,6 +28835,7 @@ __metadata:
jotai: ^2.9.1
jotai-tanstack-query: ^0.8.6
lodash.debounce: ^4.0.8
+ match-sorter: ^6.3.4
pluralize: ^8.0.0
rc-virtual-list: ^3.14.5
react-error-boundary: ^4.0.13