From 71ef917ef24e0fa553b4cd6c2aa914acddb983e9 Mon Sep 17 00:00:00 2001 From: thiagoulloa Date: Thu, 14 Nov 2024 23:20:14 -0300 Subject: [PATCH 1/3] Sort token list update --- .../SearchModal/CurrencyList/index.tsx | 48 +++++++++++-------- src/hooks/tokens/useToken.ts | 27 ++++++----- src/hooks/tokens/utils.ts | 1 + src/interfaces/tokens.ts | 1 + 4 files changed, 47 insertions(+), 30 deletions(-) diff --git a/src/components/SearchModal/CurrencyList/index.tsx b/src/components/SearchModal/CurrencyList/index.tsx index 71788101..6c64a926 100644 --- a/src/components/SearchModal/CurrencyList/index.tsx +++ b/src/components/SearchModal/CurrencyList/index.tsx @@ -107,30 +107,17 @@ export function CurrencyRow({ otherSelected, style, showCurrencyAmount, + balance, }: { currency: TokenType; onSelect: (hasWarning: boolean) => void; isSelected: boolean; otherSelected: boolean; showCurrencyAmount?: boolean; + balance: number; eventProperties: Record; style?: CSSProperties; }) { - const sorobanContext = useSorobanReact(); - - const { address } = sorobanContext; - - const { tokenBalancesResponse } = useGetMyBalances(); - - const { account } = useHorizonLoadAccount(); - - const { data, isLoading } = useSWRImmutable( - sorobanContext.activeChain && sorobanContext.address && account - ? ['currencyBalance', tokenBalancesResponse, currency, sorobanContext, account] - : null, - ([_, tokenBalancesResponse, currency, sorobanContext, account]) => - getCurrencyBalance(tokenBalancesResponse, currency, sorobanContext, account), - ); const shortenSorobanClassicAsset = (currency: TokenType) => { if (!currency) return ''; if (currency?.name && currency.name.toString().length > 56) { @@ -186,7 +173,7 @@ export function CurrencyRow({ {showCurrencyAmount ? ( - {isLoading ? : address ? : null} + {} {/* Usando o saldo diretamente */} {isSelected && } ) : ( @@ -258,6 +245,12 @@ export default function CurrencyList({ isAddressSearch: string | false; isLoading?: boolean; }) { + const sorobanContext = useSorobanReact(); + + const { tokenBalancesResponse } = useGetMyBalances(); + + const { account } = useHorizonLoadAccount(); + const itemData: TokenType[] = useMemo(() => { if (otherListTokens && otherListTokens?.length > 0) { return [...currencies, ...otherListTokens]; @@ -265,6 +258,22 @@ export default function CurrencyList({ return currencies; }, [currencies, otherListTokens]); + const enhancedItemData = itemData.map((currency) => { + const { data: balance, error } = useSWRImmutable( + sorobanContext.activeChain && sorobanContext.address && account + ? ['currencyBalance', tokenBalancesResponse, currency, sorobanContext, account] + : null, + ([_, tokenBalancesResponse, currency, sorobanContext, account]) => + getCurrencyBalance(tokenBalancesResponse, currency, sorobanContext, account), + ); + return { + ...currency, + balance: Number(balance ?? 0), + }; + }); + + const sortedItemData = enhancedItemData.sort((a, b) => b.balance - a.balance); + const Row = useCallback( function TokenRow({ data, index, style }: TokenRowProps) { const row: TokenType = data[index]; @@ -286,6 +295,7 @@ export default function CurrencyList({ return ( { + const itemKey = useCallback((index: number, data: typeof sortedItemData) => { const currency = data[index]; return currencyKey(currency); }, []); @@ -330,8 +340,8 @@ export default function CurrencyList({ height={height} ref={fixedListRef as any} width="100%" - itemData={itemData} - itemCount={itemData.length} + itemData={sortedItemData} + itemCount={sortedItemData.length} itemSize={56} itemKey={itemKey} > diff --git a/src/hooks/tokens/useToken.ts b/src/hooks/tokens/useToken.ts index 645e95bb..d6171eb6 100644 --- a/src/hooks/tokens/useToken.ts +++ b/src/hooks/tokens/useToken.ts @@ -17,14 +17,14 @@ export const findToken = async ( if (!tokenAddress || tokenAddress === '') return undefined; const classicAssetSearch = getClassicAssetSorobanAddress(tokenAddress!, sorobanContext); - + const formattedAddress = isAddress(classicAssetSearch ? classicAssetSearch : tokenAddress); if (!formattedAddress) return undefined; - + const fromMap = tokensAsMap[formattedAddress]; - + if (fromMap) return fromMap; - + const token = await getToken(sorobanContext, formattedAddress); // const token: TokenType = { // contract: formattedAddress, @@ -33,7 +33,7 @@ export const findToken = async ( // decimals, // icon: logo, // }; - + if (!token?.name || !token?.code) return undefined; // Here from token.name we will try to understand if this is a classic asset (even if we got a soroban contracta as address). const stellarAsset = getClassicStellarAsset(token.name); @@ -44,6 +44,7 @@ export const findToken = async ( */ if (stellarAsset && typeof stellarAsset !== 'boolean') { return { + balance: 0, issuer: stellarAsset.issuer, contract: token.contract, name: stellarAsset.asset, @@ -51,10 +52,9 @@ export const findToken = async ( decimals: 7, icon: '', }; + } else { + return token; } - else { - return token - }; }; const revalidateKeysCondition = (key: any) => { @@ -96,8 +96,12 @@ export function useToken(tokenAddress: string | undefined) { const bothLoading = isLoading || isStellarClassicAssetLoading; const needsWrapping = !data && isStellarClassicAsset; - - const checkContractId = (contractId: string, code: string, issuer: string): boolean | undefined => { + + const checkContractId = ( + contractId: string, + code: string, + issuer: string, + ): boolean | undefined => { if (!issuer) { return undefined; } @@ -107,7 +111,7 @@ export function useToken(tokenAddress: string | undefined) { } else { return false; } - } + }; const isSafe = data ? checkContractId(data.contract, data.code, data.issuer!) : false; const needsWrappingOnAddLiquidity = (!data && isStellarClassicAsset) || !name; @@ -120,6 +124,7 @@ export function useToken(tokenAddress: string | undefined) { if (sorobanAddress || (stellarAsset && typeof sorobanAddress === 'string')) { if (stellarAsset && typeof stellarAsset !== 'boolean') { newTokenData = { + balance: 0, issuer: stellarAsset.issuer, contract: sorobanAddress, name: stellarAsset.asset, diff --git a/src/hooks/tokens/utils.ts b/src/hooks/tokens/utils.ts index ba233397..5a4aeb1e 100644 --- a/src/hooks/tokens/utils.ts +++ b/src/hooks/tokens/utils.ts @@ -67,6 +67,7 @@ export async function getToken( logo = await getTokenLogo(formattedAddress, sorobanContext); const token: TokenType = { + balance: 0, contract: formattedAddress, name: name as string, code: symbol as string, diff --git a/src/interfaces/tokens.ts b/src/interfaces/tokens.ts index 1e354acb..300dcd0e 100644 --- a/src/interfaces/tokens.ts +++ b/src/interfaces/tokens.ts @@ -1,4 +1,5 @@ export interface TokenType { + balance: number; code: string; issuer?: string; contract: string; From 9de86666e7e0b5e306f77e1cc0b419e722711bd2 Mon Sep 17 00:00:00 2001 From: thiagoulloa Date: Thu, 14 Nov 2024 23:23:23 -0300 Subject: [PATCH 2/3] Removing unwanted commented code --- src/components/SearchModal/CurrencyList/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SearchModal/CurrencyList/index.tsx b/src/components/SearchModal/CurrencyList/index.tsx index 6c64a926..37cce73c 100644 --- a/src/components/SearchModal/CurrencyList/index.tsx +++ b/src/components/SearchModal/CurrencyList/index.tsx @@ -173,7 +173,7 @@ export function CurrencyRow({ {showCurrencyAmount ? ( - {} {/* Usando o saldo diretamente */} + {} {isSelected && } ) : ( From b2de96c940c8d5a5f33a5b15950f761161c73900 Mon Sep 17 00:00:00 2001 From: thiagoulloa Date: Fri, 15 Nov 2024 13:42:47 -0300 Subject: [PATCH 3/3] useSWRImmutable removed from CurrencyList --- .../SearchModal/CurrencyList/index.tsx | 82 ++++++++++++------- src/interfaces/tokens.ts | 2 +- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/src/components/SearchModal/CurrencyList/index.tsx b/src/components/SearchModal/CurrencyList/index.tsx index 37cce73c..07468923 100644 --- a/src/components/SearchModal/CurrencyList/index.tsx +++ b/src/components/SearchModal/CurrencyList/index.tsx @@ -1,10 +1,9 @@ import { SorobanContextType, useSorobanReact } from '@soroban-react/core'; import BigNumber from 'bignumber.js'; -import { CSSProperties, MutableRefObject, useCallback, useMemo } from 'react'; +import { CSSProperties, MutableRefObject, useCallback, useEffect, useMemo, useState } from 'react'; import { Check } from 'react-feather'; import { FixedSizeList } from 'react-window'; import { AccountResponse } from '@stellar/stellar-sdk/lib/horizon'; -import useSWRImmutable from 'swr/immutable'; import { CircularProgress, Typography, styled } from 'soroswap-ui'; import Column, { AutoColumn } from 'components/Column'; @@ -114,7 +113,7 @@ export function CurrencyRow({ isSelected: boolean; otherSelected: boolean; showCurrencyAmount?: boolean; - balance: number; + balance?: number; eventProperties: Record; style?: CSSProperties; }) { @@ -171,7 +170,7 @@ export function CurrencyRow({ {currency.domain ? currency.domain : formattedCurrencyName(currency as TokenType)} - {showCurrencyAmount ? ( + {showCurrencyAmount && balance ? ( {} {isSelected && } @@ -246,51 +245,72 @@ export default function CurrencyList({ isLoading?: boolean; }) { const sorobanContext = useSorobanReact(); - const { tokenBalancesResponse } = useGetMyBalances(); - const { account } = useHorizonLoadAccount(); - const itemData: TokenType[] = useMemo(() => { - if (otherListTokens && otherListTokens?.length > 0) { - return [...currencies, ...otherListTokens]; - } - return currencies; + const [balances, setBalances] = useState>({}); + + const itemData = useMemo(() => { + return otherListTokens && otherListTokens.length > 0 + ? [...currencies, ...otherListTokens] + : currencies; }, [currencies, otherListTokens]); - const enhancedItemData = itemData.map((currency) => { - const { data: balance, error } = useSWRImmutable( - sorobanContext.activeChain && sorobanContext.address && account - ? ['currencyBalance', tokenBalancesResponse, currency, sorobanContext, account] - : null, - ([_, tokenBalancesResponse, currency, sorobanContext, account]) => - getCurrencyBalance(tokenBalancesResponse, currency, sorobanContext, account), - ); - return { - ...currency, - balance: Number(balance ?? 0), + useEffect(() => { + const fetchBalances = async () => { + const newBalances: Record = {}; + + if (account) { + for (const currency of itemData) { + const balance = await getCurrencyBalance( + tokenBalancesResponse, + currency, + sorobanContext, + account, + ); + newBalances[currencyKey(currency)] = Number(balance ?? 0); + } + setBalances(newBalances); + } }; - }); - const sortedItemData = enhancedItemData.sort((a, b) => b.balance - a.balance); + if (sorobanContext.activeChain && sorobanContext.address && account && itemData.length > 0) { + fetchBalances(); + } + }, [ + sorobanContext.activeChain, + sorobanContext.address, + account, + itemData, + tokenBalancesResponse, + ]); + + const sortedItemData = useMemo(() => { + if (!itemData || !Array.isArray(itemData)) { + return []; + } + return [...itemData] + .map((currency) => ({ + ...currency, + balance: balances[currencyKey(currency)] || 0, + })) + .sort((a, b) => b.balance - a.balance); + }, [itemData, balances]); const Row = useCallback( function TokenRow({ data, index, style }: TokenRowProps) { - const row: TokenType = data[index]; - + const row = data[index]; const currency = row; const isSelected = Boolean( - currency && selectedCurrency && selectedCurrency.contract == currency.contract, + currency && selectedCurrency && selectedCurrency.contract === currency.contract, ); const otherSelected = Boolean( - currency && otherCurrency && otherCurrency.contract == currency.contract, + currency && otherCurrency && otherCurrency.contract === currency.contract, ); const handleSelect = (hasWarning: boolean) => currency && onCurrencySelect(currency, hasWarning); - const token = currency; - if (currency) { return (