diff --git a/src/api/externalAssetRegistry.ts b/src/api/externalAssetRegistry.ts index 23a9aa1e7..90d19d547 100644 --- a/src/api/externalAssetRegistry.ts +++ b/src/api/externalAssetRegistry.ts @@ -5,12 +5,12 @@ import { Parachain, SubstrateApis } from "@galacticcouncil/xcm-core" import { HydradxRuntimeXcmAssetLocation } from "@polkadot/types/lookup" import { TExternalAsset, + TRegisteredAsset, useUserExternalTokenStore, } from "sections/wallet/addToken/AddToken.utils" import { isJson, isNotNil } from "utils/helpers" import { u32 } from "@polkadot/types" import { AccountId32 } from "@polkadot/types/interfaces" -import { Maybe } from "utils/helpers" import { Fragment, useMemo } from "react" import { useTotalIssuances } from "api/totalIssuance" import { useRpcProvider } from "providers/rpcProvider" @@ -294,12 +294,10 @@ export const useAssetHubTokenBalance = ( export const useAssetHubTokenBalances = ( account: AccountId32 | string, - ids: Maybe[], + ids: string[], ) => { - const tokenIds = ids.filter((id): id is u32 => !!id) - return useQueries({ - queries: tokenIds.map((id) => ({ + queries: ids.map((id) => ({ queryKey: QUERY_KEYS.assetHubTokenBalance( account.toString(), id.toString(), @@ -325,29 +323,33 @@ export const useExternalTokensRugCheck = () => { : [] const internalIds = addedTokens.map(({ id }) => id) - const externalIds = addedTokens.map(({ externalId }) => externalId) + const assetHubExternalIds = addedTokens + .map(({ parachainId, externalId }) => + Number(parachainId) === ASSET_HUB_ID ? externalId : "", + ) + .filter(isNotNil) const issuanceQueries = useTotalIssuances(internalIds) const balanceQueries = useAssetHubTokenBalances( HYDRADX_PARACHAIN_ACCOUNT, - externalIds, + assetHubExternalIds, ) const tokens = useMemo(() => { if ( - issuanceQueries.some((q) => !q.data) || - balanceQueries.some((q) => !q.data) + issuanceQueries.some(({ data }) => !data) || + balanceQueries.some(({ fetchStatus }) => fetchStatus !== "idle") ) { return [] } - const issuanceData = issuanceQueries.map((q) => q.data).filter(isNotNil) - const balanceData = balanceQueries.map((q) => q.data).filter(isNotNil) + const issuanceData = issuanceQueries.map((q) => q.data) + const balanceData = balanceQueries.map((q) => q.data) return zipArrays(issuanceData, balanceData) .map(([issuance, balance]) => { - if (!issuance.token) return null + if (!issuance?.token) return null const internalToken = assets.getAsset(issuance.token.toString()) const storedToken = externalStore.getTokenByInternalId( @@ -364,40 +366,17 @@ export const useExternalTokensRugCheck = () => { if (!externalToken) return null if (!storedToken) return null - const totalSupplyExternal = BN(balance?.balance ?? 0) - const totalSupplyInternal = BN(issuance?.total ?? 0) - - const supplyCheck = totalSupplyExternal.lt(totalSupplyInternal) - const symbolCheck = externalToken.symbol !== storedToken.symbol - const decimalsCheck = externalToken.decimals !== storedToken.decimals - - const supplyWarning: RugWarning | null = supplyCheck - ? { - type: "supply", - severity: "high", - diff: [totalSupplyInternal, totalSupplyExternal], - } - : null - - const symbolWarning: RugWarning | null = symbolCheck - ? { - type: "symbol", - severity: "medium", - diff: [storedToken.symbol, externalToken.symbol], - } + const totalSupplyExternal = balance?.balance + ? BN(balance.balance) : null + const totalSupplyInternal = issuance?.total ? BN(issuance.total) : null - const decimalsWarning: RugWarning | null = decimalsCheck - ? { - type: "decimals", - severity: "medium", - diff: [storedToken.decimals, externalToken.decimals], - } - : null - - const warnings = [supplyWarning, symbolWarning, decimalsWarning].filter( - isNotNil, - ) + const warnings = createRugWarningList({ + totalSupplyExternal, + totalSupplyInternal, + storedToken, + externalToken, + }) const severity = warnings.reduce((acc, { severity }) => { return RUG_SEVERITY_LEVELS.indexOf(severity) > @@ -428,3 +407,47 @@ export const useExternalTokensRugCheck = () => { tokensMap, } } + +const createRugWarningList = ({ + totalSupplyExternal, + totalSupplyInternal, + storedToken, + externalToken, +}: { + totalSupplyExternal: BN | null + totalSupplyInternal: BN | null + storedToken: TRegisteredAsset + externalToken: TExternalAsset +}) => { + const warnings: RugWarning[] = [] + + if ( + totalSupplyExternal && + totalSupplyInternal && + totalSupplyExternal.lt(totalSupplyInternal) + ) { + warnings.push({ + type: "supply", + severity: "high", + diff: [totalSupplyInternal ?? BN_0, totalSupplyExternal ?? BN_0], + }) + } + + if (externalToken.symbol !== storedToken.symbol) { + warnings.push({ + type: "symbol", + severity: "medium", + diff: [storedToken.symbol, externalToken.symbol], + }) + } + + if (externalToken.decimals !== storedToken.decimals) { + warnings.push({ + type: "decimals", + severity: "medium", + diff: [storedToken.decimals, externalToken.decimals], + }) + } + + return warnings +} diff --git a/src/i18n/locales/en/translations.json b/src/i18n/locales/en/translations.json index fcbded4ad..c1c39077a 100644 --- a/src/i18n/locales/en/translations.json +++ b/src/i18n/locales/en/translations.json @@ -526,7 +526,6 @@ "wallet.assets.farmingPositions.data.date": "{{ date, dd/MM/yyyy }}", "wallet.addToken.header.addCustom": "Add custom asset", "wallet.addToken.header.availableAssets": "Available assets", - "wallet.addToken.link.assetHubCheck": "Check on AssetHub", "wallet.addToken.button.customAsset": "Add Custom Asset", "wallet.addToken.filter.source": "Source:", "wallet.addToken.filter.comingSoon": "More coming soon", diff --git a/src/sections/wallet/addToken/modal/AddTokenListModal.tsx b/src/sections/wallet/addToken/modal/AddTokenListModal.tsx index e0d01ae4b..7d81f7312 100644 --- a/src/sections/wallet/addToken/modal/AddTokenListModal.tsx +++ b/src/sections/wallet/addToken/modal/AddTokenListModal.tsx @@ -1,7 +1,4 @@ import { useExternalAssetRegistry } from "api/externalAssetRegistry" -import React from "react" -import { AssetId } from "@galacticcouncil/ui" -import { createComponent } from "@lit-labs/react" import { EmptySearchState } from "components/EmptySearchState/EmptySearchState" import { Icon } from "components/Icon/Icon" import { ModalScrollableContent } from "components/Modal/Modal" @@ -19,12 +16,7 @@ import { AssetRow } from "sections/wallet/addToken/modal/AddTokenModal.styled" import { SourceFilter } from "sections/wallet/addToken/modal/filter/SourceFilter" import { AddTokenListSkeleton } from "sections/wallet/addToken/modal/skeleton/AddTokenListSkeleton" import { theme } from "theme" - -export const UigcAssetId = createComponent({ - tagName: "uigc-asset-id", - elementClass: AssetId, - react: React, -}) +import { AssetLogo } from "components/AssetIcon/AssetIcon" type Props = { onAssetSelect?: (asset: TExternalAsset) => void @@ -120,10 +112,7 @@ export const AddTokenListModal: React.FC = ({ fs={14} sx={{ flex: "row", align: "center", gap: 10 }} > - } - /> + } size={24} /> {asset.name} diff --git a/src/sections/wallet/addToken/modal/components/TokenHeader/TokenHeader.tsx b/src/sections/wallet/addToken/modal/components/TokenHeader/TokenHeader.tsx deleted file mode 100644 index ddae95746..000000000 --- a/src/sections/wallet/addToken/modal/components/TokenHeader/TokenHeader.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { AssetId } from "@galacticcouncil/ui" -import { createComponent } from "@lit-labs/react" -import { Icon } from "components/Icon/Icon" -import { Text } from "components/Typography/Text/Text" -import * as React from "react" -import { TExternalAsset } from "sections/wallet/addToken/AddToken.utils" - -export const UigcAssetId = createComponent({ - tagName: "uigc-asset-id", - elementClass: AssetId, - react: React, -}) - -export type TokenHeaderProps = { - asset: TExternalAsset -} - -export const TokenHeader: React.FC = ({ asset }) => { - return ( -
- } - /> -
- - {asset.symbol} - - - {asset.name} - -
-
- ) -} diff --git a/src/sections/wallet/addToken/modal/components/TokenInfo/TokenInfoHeader.tsx b/src/sections/wallet/addToken/modal/components/TokenInfo/TokenInfoHeader.tsx index 7e1722e76..232c23c21 100644 --- a/src/sections/wallet/addToken/modal/components/TokenInfo/TokenInfoHeader.tsx +++ b/src/sections/wallet/addToken/modal/components/TokenInfo/TokenInfoHeader.tsx @@ -1,18 +1,14 @@ import { AssetId } from "@galacticcouncil/ui" import { createComponent } from "@lit-labs/react" import { - ASSET_HUB_ID, getIconByRugSeverity, useExternalTokensRugCheck, } from "api/externalAssetRegistry" -import LinkIcon from "assets/icons/LinkIcon.svg?react" import { Icon } from "components/Icon/Icon" import { Text } from "components/Typography/Text/Text" import * as React from "react" -import { useTranslation } from "react-i18next" import { TExternalAsset } from "sections/wallet/addToken/AddToken.utils" import { SLogoContainer } from "./TokenInfo.styled" -import { theme } from "theme" export const UigcAssetId = createComponent({ tagName: "uigc-asset-id", @@ -29,7 +25,6 @@ export const TokenInfoHeader: React.FC = ({ asset, internalId, }) => { - const { t } = useTranslation() const rugCheck = useExternalTokensRugCheck() const rugCheckData = rugCheck.tokensMap.get(internalId ?? "") @@ -38,51 +33,32 @@ export const TokenInfoHeader: React.FC = ({ : null return ( -
-
- - - e?.shadowRoot - ?.querySelector("uigc-logo-asset") - ?.setAttribute("style", "width:100%;height:100%;") - } - /> - } - /> - {SeverityIcon && } - -
- - {asset.symbol} - - - {asset.name} - -
-
- {asset.origin === ASSET_HUB_ID && ( - - - {t("wallet.addToken.link.assetHubCheck")} - +
+ + + e?.shadowRoot + ?.querySelector("uigc-logo-asset") + ?.setAttribute("style", "width:100%;height:100%;") + } + /> + } + /> + {SeverityIcon && } + +
+ + {asset.symbol} + + + {asset.name} - )} +
) }