Skip to content

Commit c6bc289

Browse files
committed
feat: assets-controllers polish getAssetId and unit tests
1 parent 734dfcf commit c6bc289

3 files changed

Lines changed: 97 additions & 19 deletions

File tree

packages/assets-controllers/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Add exported `getAssetId` in `codefi-v2.ts` for CAIP-19 asset ID derivation - extracted from existing `fetchTokenPrices` ([#9386](https://github.com/MetaMask/core/pull/9386))
13+
1014
## [109.3.0]
1115

1216
### Added

packages/assets-controllers/src/token-prices-service/codefi-v2.test.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
fetchSupportedNetworks,
1616
getSupportedNetworks,
1717
resetSupportedNetworksCache,
18+
getAssetId,
1819
} from './codefi-v2';
1920

2021
// We're not customizing the default max delay
@@ -2183,6 +2184,74 @@ describe('CodefiTokenPricesServiceV2', () => {
21832184
expect(service.validateChainIdSupported('0xdeadbeef')).toBe(false);
21842185
});
21852186
});
2187+
2188+
describe('getAssetId', () => {
2189+
it('returns a CAIP-19 erc20 id with a lowercased address for ERC20 tokens', () => {
2190+
expect(getAssetId({ chainId: '0x1', tokenAddress: '0xABCDEF' })).toBe(
2191+
'eip155:1/erc20:0xabcdef',
2192+
);
2193+
});
2194+
2195+
it('returns the hardcoded id for native tokens on supported chains', () => {
2196+
expect(getAssetId({ chainId: '0x1', tokenAddress: ZERO_ADDRESS })).toBe(
2197+
'eip155:1/slip44:60',
2198+
);
2199+
});
2200+
2201+
it('detects native tokens on chains with a custom native address', () => {
2202+
expect(
2203+
getAssetId({
2204+
chainId: '0x89',
2205+
tokenAddress: '0x0000000000000000000000000000000000001010',
2206+
}),
2207+
).toBe('eip155:137/slip44:966');
2208+
});
2209+
2210+
it('matches native token addresses case-insensitively', () => {
2211+
expect(
2212+
getAssetId({
2213+
chainId: '0x89',
2214+
tokenAddress: '0x0000000000000000000000000000000000001010'
2215+
.toUpperCase()
2216+
.replace('0X', '0x'),
2217+
}),
2218+
).toBe('eip155:137/slip44:966');
2219+
});
2220+
2221+
it('falls back to nativeAssetIdentifiers when the chain has no hardcoded entry', () => {
2222+
// 0x42 (OKXChain) is not in SPOT_PRICES_SUPPORT_INFO
2223+
expect(
2224+
getAssetId({
2225+
chainId: '0x42',
2226+
tokenAddress: ZERO_ADDRESS,
2227+
nativeAssetIdentifiers: { 'eip155:66': 'eip155:66/slip44:996' },
2228+
}),
2229+
).toBe('eip155:66/slip44:996');
2230+
});
2231+
2232+
it('prefers the hardcoded entry over nativeAssetIdentifiers', () => {
2233+
expect(
2234+
getAssetId({
2235+
chainId: '0x1',
2236+
tokenAddress: ZERO_ADDRESS,
2237+
nativeAssetIdentifiers: { 'eip155:1': 'eip155:1/erc20:0xwrong' },
2238+
}),
2239+
).toBe('eip155:1/slip44:60');
2240+
});
2241+
2242+
it('returns undefined for a native token with no hardcoded entry and no identifier', () => {
2243+
expect(
2244+
getAssetId({ chainId: '0x42', tokenAddress: ZERO_ADDRESS }),
2245+
).toBeUndefined();
2246+
});
2247+
2248+
it('returns undefined instead of throwing when given a malformed chain ID', () => {
2249+
expect(
2250+
// @ts-expect-error Testing runtime behavior with invalid input
2251+
getAssetId({ chainId: 'not-a-hex-string', tokenAddress: '0xAAA' }),
2252+
).toBeUndefined();
2253+
});
2254+
});
21862255
});
21872256

21882257
/**

packages/assets-controllers/src/token-prices-service/codefi-v2.ts

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -589,31 +589,36 @@ export function resetSupportedCurrenciesCache(): void {
589589
export function getAssetId({
590590
chainId,
591591
tokenAddress,
592-
nativeAssetIdentifiers,
592+
nativeAssetIdentifiers = {},
593593
}: {
594594
chainId: Hex;
595595
tokenAddress: string;
596-
nativeAssetIdentifiers: NativeAssetIdentifiersMap;
596+
nativeAssetIdentifiers?: NativeAssetIdentifiersMap;
597597
}): CaipAssetType | undefined {
598-
const caipChainId = toCaipChainId(
599-
KnownCaipNamespace.Eip155,
600-
hexToNumber(chainId).toString(),
601-
);
598+
try {
599+
const caipChainId = toCaipChainId(
600+
KnownCaipNamespace.Eip155,
601+
hexToNumber(chainId).toString(),
602+
);
602603

603-
const nativeAddress = getNativeTokenAddress(chainId);
604-
const isNativeToken =
605-
nativeAddress.toLowerCase() === tokenAddress.toLowerCase();
606-
607-
if (isNativeToken) {
608-
const hardcodedId = (
609-
SPOT_PRICES_SUPPORT_INFO as Partial<Record<Hex, string>>
610-
)[chainId];
611-
return (hardcodedId ?? nativeAssetIdentifiers[caipChainId]) as
612-
| CaipAssetType
613-
| undefined;
614-
}
604+
const nativeAddress = getNativeTokenAddress(chainId);
605+
const isNativeToken =
606+
nativeAddress.toLowerCase() === tokenAddress.toLowerCase();
607+
608+
if (isNativeToken) {
609+
const hardcodedId = (
610+
SPOT_PRICES_SUPPORT_INFO as Partial<Record<Hex, string>>
611+
)[chainId];
612+
return (hardcodedId ?? nativeAssetIdentifiers[caipChainId]) as
613+
| CaipAssetType
614+
| undefined;
615+
}
615616

616-
return `${caipChainId}/erc20:${tokenAddress.toLowerCase()}` as CaipAssetType;
617+
return `${caipChainId}/erc20:${tokenAddress.toLowerCase()}` as CaipAssetType;
618+
} catch {
619+
// This block should never be reached as long as using Typescript, but added for safety.
620+
return undefined;
621+
}
617622
}
618623

619624
/**

0 commit comments

Comments
 (0)