Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(runway): cherry-pick fix: cp-12.14.0 duplicate dest assets visible in bridge page #30914

Open
wants to merge 1 commit into
base: Version-v12.14.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions shared/types/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ export type BridgeToken = {
symbol: string;
image: string;
decimals: number;
chainId: CaipChainId;
chainId: number | Hex | ChainId | CaipChainId;
balance: string; // raw balance
string: string | undefined; // normalized balance as a stringified number
tokenFiatAmount?: number | null;
} | null;
};
// Types copied from Metabridge API

export enum BridgeFlag {
Expand Down
7 changes: 6 additions & 1 deletion ui/ducks/bridge/bridge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,12 @@ describe('Ducks - Bridge', () => {
expect(actions[0].type).toStrictEqual('bridge/setToToken');
const newState = bridgeReducer(state, actions[0]);
expect(newState.toToken).toStrictEqual(
expect.objectContaining({ ...actionPayload, chainId: 'eip155:10' }),
expect.objectContaining({
...actionPayload,
balance: '0',
chainId: '0xa',
string: '0',
}),
);
});
});
Expand Down
8 changes: 4 additions & 4 deletions ui/ducks/bridge/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import { getTokenExchangeRate } from './utils';

export type BridgeState = {
toChainId: CaipChainId | null;
fromToken: BridgeToken;
toToken: BridgeToken;
fromToken: BridgeToken | null;
toToken: BridgeToken | null;
fromTokenInputValue: string | null;
fromTokenExchangeRate: number | null; // Exchange rate from selected token to the default currency (can be fiat or crypto)
toTokenExchangeRate: number | null; // Exchange rate from the selected token to the default currency (can be fiat or crypto)
Expand Down Expand Up @@ -82,7 +82,7 @@ const bridgeSlice = createSlice({
...payload,
balance: payload.balance ?? '0',
string: payload.string ?? '0',
chainId: formatChainIdToCaip(payload.chainId),
chainId: payload.chainId,
};
} else {
state.fromToken = payload;
Expand All @@ -94,7 +94,7 @@ const bridgeSlice = createSlice({
...payload,
balance: payload.balance ?? '0',
string: payload.string ?? '0',
chainId: formatChainIdToCaip(payload.chainId),
chainId: payload.chainId,
address: payload.address || zeroAddress(),
};
} else {
Expand Down
4 changes: 2 additions & 2 deletions ui/ducks/bridge/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export const getToChain = createSelector(
export const getFromToken = createSelector(
(state: BridgeAppState) => state.bridge.fromToken,
getFromChain,
(fromToken, fromChain): BridgeToken => {
(fromToken, fromChain): BridgeToken | null => {
if (!fromChain?.chainId) {
return null;
}
Expand All @@ -204,7 +204,7 @@ export const getFromToken = createSelector(
},
);

export const getToToken = (state: BridgeAppState): BridgeToken => {
export const getToToken = (state: BridgeAppState): BridgeToken | null => {
return state.bridge.toToken;
};

Expand Down
35 changes: 13 additions & 22 deletions ui/hooks/bridge/useTokensWithFiltering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import { AssetType } from '../../../shared/constants/transaction';
import {
formatChainIdToCaip,
formatChainIdToHex,
isNativeAddress,
} from '../../../shared/modules/bridge-utils/caip-formatters';
import { CHAIN_ID_TOKEN_IMAGE_MAP } from '../../../shared/constants/network';
Expand All @@ -35,6 +36,7 @@ import {
type BridgeAppState,
getTopAssetsFromFeatureFlags,
} from '../../ducks/bridge/selectors';
import { type BridgeToken } from '../../../shared/types/bridge';

type FilterPredicate = (
symbol: string,
Expand All @@ -58,11 +60,7 @@ type FilterPredicate = (
*/
export const useTokensWithFiltering = (
chainId?: ChainId | Hex | CaipChainId,
tokenToExclude?: null | {
symbol: string;
address?: string;
chainId?: string;
},
tokenToExclude?: null | Pick<BridgeToken, 'symbol' | 'address' | 'chainId'>,
) => {
const allDetectedTokens: Record<string, Token[]> = useSelector(
getAllDetectedTokensForSelectedAddress,
Expand All @@ -79,15 +77,15 @@ export const useTokensWithFiltering = (
const { value: tokenList, pending: isTokenListLoading } = useAsyncResult<
Record<string, SwapsTokenObject>
>(async () => {
if (chainId && isStrictHexString(chainId)) {
const timestamp = cachedTokens[chainId]?.timestamp;
if (chainId && chainId !== MultichainNetworks.SOLANA) {
const hexChainId = formatChainIdToHex(chainId);
const timestamp = cachedTokens[hexChainId]?.timestamp;
// Use cached token data if updated in the last 10 minutes
if (timestamp && Date.now() - timestamp <= 10 * MINUTE) {
return cachedTokens[chainId]?.data;
return cachedTokens[hexChainId]?.data;
}
// Otherwise fetch new token data

return await fetchBridgeTokens(chainId);
return await fetchBridgeTokens(hexChainId);
}
if (chainId && formatChainIdToCaip(chainId) === MultichainNetworks.SOLANA) {
return await fetchNonEvmTokens(chainId);
Expand Down Expand Up @@ -118,8 +116,9 @@ export const useTokensWithFiltering = (
if (!chainId || !token || !isStrictHexString(chainId)) {
return undefined;
}
const hexChainId = formatChainIdToHex(chainId);
// Only tokens on the active chain are processed here here
const sharedFields = { ...token, chainId };
const sharedFields = { ...token, chainId: hexChainId };

if (isNativeAddress(token.address)) {
return {
Expand All @@ -138,12 +137,8 @@ export const useTokensWithFiltering = (

return {
...sharedFields,
...(tokenList?.[token.address.toLowerCase()] ?? {}),
type: AssetType.token,
image:
token.iconUrl ??
tokenList?.[token.address.toLowerCase()]?.iconUrl ??
'',
image: token.iconUrl ?? tokenList?.[token.address]?.iconUrl ?? '',
// Only tokens with 0 balance are processed here so hardcode empty string
balance: '',
string: undefined,
Expand Down Expand Up @@ -273,11 +268,7 @@ export const useTokensWithFiltering = (
const matchedToken = tokenList?.[token_.address];
if (
matchedToken &&
shouldAddToken(
matchedToken.symbol,
matchedToken.address ?? undefined,
chainId,
)
shouldAddToken(matchedToken.symbol, matchedToken.address, chainId)
) {
const token = buildTokenData(matchedToken);
if (token) {
Expand All @@ -290,7 +281,7 @@ export const useTokensWithFiltering = (
for (const token_ of Object.values(tokenList)) {
if (
token_ &&
shouldAddToken(token_.symbol, token_.address ?? undefined, chainId)
shouldAddToken(token_.symbol, token_.address, chainId)
) {
const token = buildTokenData(token_);
if (token) {
Expand Down
Loading