Skip to content

Commit e4b0414

Browse files
chore(runway): cherry-pick feat: fetch all tokens for bridge input (#16029)
- feat: cp-7.47.0 fetch all tokens for bridge input (#15993)
1 parent 4fc4a08 commit e4b0414

3 files changed

Lines changed: 45 additions & 31 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## [Unreleased]
9+
10+
- feat(bridge): add "hardware wallets not supported" error when attempting Solana swap/bridge ([#15743](https://github.com/MetaMask/metamask-mobile/pull/15743))
11+
- feat(bridge): fetch all tokens for bridge input([#15993](https://github.com/MetaMask/metamask-mobile/pull/15993))
912
- fix(bridge): don't show currency value unless amount is above zero ([#15798](https://github.com/MetaMask/metamask-mobile/pull/15798))
1013

1114

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { useTokensWithBalance } from './useTokensWithBalance';
22
import { Hex, CaipChainId } from '@metamask/utils';
3-
import { useMemo } from 'react';
43
import { useTopTokens } from './useTopTokens';
54
import { BridgeToken } from '../types';
65

@@ -27,32 +26,29 @@ export function useTokens({
2726
chainIds: balanceChainIds
2827
});
2928

30-
const { topTokens, pending } = useTopTokens({ chainId: topTokensChainId });
29+
const { topTokens, remainingTokens, pending } = useTopTokens({ chainId: topTokensChainId });
3130

32-
const topTokensFiltered = useMemo(() =>
33-
topTokens
34-
// filter out tokens that are already in the tokensWithBalance array
35-
?.filter((token) => !tokensWithBalance.some(
36-
(t) => t.address === token.address && t.chainId === token.chainId
37-
)) ?? [],
38-
[topTokens, tokensWithBalance]
39-
);
31+
const getTokenKey = (token: { address: string; chainId: Hex | CaipChainId }) => `${token.address}-${token.chainId}`;
4032

41-
const uniqueTokens = useMemo(
42-
() => [...tokensWithBalance, ...topTokensFiltered],
43-
[tokensWithBalance, topTokensFiltered]
33+
// Create Sets for O(1) lookups
34+
const tokensWithBalanceSet = new Set(
35+
tokensWithBalance.map(token => getTokenKey(token))
4436
);
45-
46-
const filteredTokens = useMemo(
47-
() => uniqueTokens.filter((token) => {
48-
// filter out tokens that are in the tokensToExclude array
49-
const isSelectedToken = tokensToExclude?.some(
50-
(t) => t.address === token.address && t.chainId === token.chainId
51-
);
52-
return !isSelectedToken;
53-
}),
54-
[uniqueTokens, tokensToExclude]
37+
const excludedTokensSet = new Set(
38+
tokensToExclude?.map(token => getTokenKey(token)) ?? []
5539
);
5640

57-
return { tokens: filteredTokens, pending };
41+
// Combine and filter tokens in a single pass
42+
const tokensWithoutBalance = (topTokens ?? []).concat(remainingTokens ?? []).filter(token => {
43+
const tokenKey = getTokenKey(token);
44+
return !tokensWithBalanceSet.has(tokenKey);
45+
});
46+
47+
// Combine tokens with balance and filtered tokens and filter out excluded tokens
48+
const tokens = tokensWithBalance.concat(tokensWithoutBalance).filter(token => {
49+
const tokenKey = getTokenKey(token);
50+
return !excludedTokensSet.has(tokenKey);
51+
});
52+
53+
return { tokens, pending };
5854
}

app/components/UI/Bridge/hooks/useTopTokens/index.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ interface UseTopTokensProps {
1919
chainId?: Hex | CaipChainId;
2020
}
2121

22-
export const useTopTokens = ({ chainId }: UseTopTokensProps): { topTokens: BridgeToken[] | undefined, pending: boolean } => {
22+
export const useTopTokens = ({ chainId }: UseTopTokensProps): {
23+
topTokens: BridgeToken[] | undefined,
24+
remainingTokens: BridgeToken[] | undefined,
25+
pending: boolean
26+
} => {
2327
const swapsChainCache: SwapsControllerState['chainCache'] = useSelector(selectChainCache);
2428
const swapsTopAssets = useMemo(
2529
() => (chainId ? swapsChainCache[chainId]?.topAssets : null),
@@ -104,12 +108,13 @@ export const useTopTokens = ({ chainId }: UseTopTokensProps): { topTokens: Bridg
104108
}, [chainId]);
105109

106110
// Merge the top assets from the Swaps API with the token data from the bridge API
107-
const topTokens = useMemo(() => {
111+
const { topTokens, remainingTokens } = useMemo(() => {
108112
if (!bridgeTokens) {
109-
return [];
113+
return { topTokens: [], remainingTokens: [] };
110114
}
111115

112116
const result: BridgeToken[] = [];
117+
const remainingTokensList: BridgeToken[] = [];
113118
const addedAddresses = new Set<string>();
114119
const topAssetAddrs = topAssetsFromFeatureFlags || swapsTopAssets?.map((asset) => asset.address) || [];
115120

@@ -146,13 +151,23 @@ export const useTopTokens = ({ chainId }: UseTopTokensProps): { topTokens: Bridg
146151
// Then add remaining unique bridge tokens until we reach the limit
147152
if (result.length < MAX_TOP_TOKENS) {
148153
for (const token of Object.values(bridgeTokens)) {
149-
if (result.length >= MAX_TOP_TOKENS) break;
150-
addTokenIfNotExists(token);
154+
if (result.length >= MAX_TOP_TOKENS) {
155+
remainingTokensList.push(token);
156+
} else {
157+
addTokenIfNotExists(token);
158+
}
151159
}
152160
}
153161

154-
return result;
162+
return {
163+
topTokens: result,
164+
remainingTokens: remainingTokensList
165+
};
155166
}, [bridgeTokens, swapsTopAssets, topAssetsFromFeatureFlags]);
156167

157-
return { topTokens, pending: chainId ? (bridgeTokensPending || swapsTopAssetsPending) : false };
168+
return {
169+
topTokens,
170+
remainingTokens,
171+
pending: chainId ? (bridgeTokensPending || swapsTopAssetsPending) : false
172+
};
158173
};

0 commit comments

Comments
 (0)