Skip to content

fix: handle evm unsupported chains gracefully in send flow for custom network cp-13.17.0#39806

Merged
khanti42 merged 3 commits intomainfrom
fix/custom-network-send-error
Feb 5, 2026
Merged

fix: handle evm unsupported chains gracefully in send flow for custom network cp-13.17.0#39806
khanti42 merged 3 commits intomainfrom
fix/custom-network-send-error

Conversation

@khanti42
Copy link
Contributor

@khanti42 khanti42 commented Feb 4, 2026

Description

Fixes error when sending native tokens on EVM networks with decimal string chainIds (e.g., Injective testnet). The fix normalizes decimal string chainIds to hex format in isEvmChainId before conversion, preventing conversion errors. Defensive error handling is also added as a fallback for unsupported chains.

Open in GitHub Codespaces

Changelog

CHANGELOG entry: Fixed error when sending native tokens on EVM networks when chainId is provided as decimal string.

Related issues

Fixes:

Manual testing steps

  1. Go to this page...

Screenshots/Recordings

Before

Screen.Recording.2026-02-04.at.23.25.00.mov

After

Screen.Recording.2026-02-04.at.23.21.43.mov

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Note

Medium Risk
Touches chain-id normalization and native asset lookups that can affect pricing/send flows across many networks; changes are small but impact broad utility functions and error handling paths.

Overview
Fixes failures when EVM chainIds are provided as decimal strings (e.g. Injective testnet) by updating isEvmChainId to normalize non-CAIP/non-hex inputs (after guarding with isNonEvmChainId) before converting to CAIP.

Makes native-asset resolution more defensive on unsupported/custom networks: toAssetId now catches getNativeAssetForChainId errors and returns undefined, the UI adds getNativeAssetForChainIdSafe, and useCurrentPrice uses it to avoid throwing and to return no price when a native assetId can’t be derived. Tests were updated/added to cover decimal-string chain IDs and unsupported-chain native asset handling.

Written by Cursor Bugbot for commit 3fbca98. This will update automatically on new commits. Configure here.

Cursor Bugbot reviewed your changes and found no issues for commit 3fbca98

@github-actions
Copy link
Contributor

github-actions bot commented Feb 4, 2026

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 4, 2026

✨ Files requiring CODEOWNER review ✨

🔄 @MetaMask/swaps-engineers (1 files, +19 -0)
  • 📁 ui/
    • 📁 ducks/
      • 📁 bridge/
        • 📄 utils.ts +19 -0

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 4, 2026

Builds ready [207acc0]
UI Startup Metrics (1376 ± 82 ms)
PlatformBuildTypePageMetricTest Title (ms)Persona (ms)Mean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
ChromeBrowserifyStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--1376116715628214401506
load--117797513568412341309
domContentLoaded--117197113498312281303
domInteractive--271599182377
firstPaint--145651044111189260
backgroundConnect--23621729913239261
firstReactRender--17113541925
initialActions--106114
loadScripts--95175711338410101086
setupStore--1262541419
numNetworkReqs--231590201583
19--------
BrowserifyPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--17441376290518618032071
load--11681030232918711451593
domContentLoaded--11521023223317811321585
domInteractive--40172844434137
firstPaint--21182850108264403
backgroundConnect--32228147738334413
firstReactRender--20153842127
initialActions--105111
loadScripts--91078119231678891299
setupStore--1474251626
numNetworkReqs--1134726949138252
19--------
WebpackStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--83966811171059091036
load--708599103597793884
domContentLoaded--703594102996787877
domInteractive--251592172274
firstPaint--1156280091135277
backgroundConnect--3618135234382
firstReactRender--15103441626
initialActions--103113
loadScripts--700592102795782875
setupStore--1163451123
numNetworkReqs--231595211586
19--------
WebpackPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--1211844179919213201600
load--68759510971166691027
domContentLoaded--67859010841156581021
domInteractive--3217131223292
firstPaint--136621002111160257
backgroundConnect--15612733541158263
firstReactRender--21173332327
initialActions--101011
loadScripts--67558810701136561013
setupStore--1243951419
numNetworkReqs--1254829357150275
19--------
FirefoxBrowserifyStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--17701371277226918872381
load--14771182259622215761984
domContentLoaded--14761181259622215721984
domInteractive--94331371135107149
firstPaint--------
backgroundConnect--873138159128196
firstReactRender--13104141417
initialActions--103122
loadScripts--14301157257420515261842
setupStore--195257361376
numNetworkReqs--251294221889
19--------
BrowserifyPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--27412082429847430023726
load--15461190243928116392283
domContentLoaded--15461190243428116382283
domInteractive--1093477499110323
firstPaint--------
backgroundConnect--2851121338244298881
firstReactRender--18146171926
initialActions--113122
loadScripts--14931169226625515822185
setupStore--107875216196523
numNetworkReqs--66361402990128
19--------
WebpackStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--15541279210315416531806
load--13431140158011414221552
domContentLoaded--13421139157911414221552
domInteractive--772818941108144
firstPaint--------
backgroundConnect--61221883976143
firstReactRender--14116061419
initialActions--103122
loadScripts--13101124154610013911492
setupStore--125177181230
numNetworkReqs--231284181772
19--------
WebpackPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--27482099677360728633888
load--15891223548551617192498
domContentLoaded--15881220548551617192498
domInteractive--11929769127104449
firstPaint--------
backgroundConnect--2951141376250326898
firstReactRender--21143242329
initialActions--207122
loadScripts--15361202545849616382393
setupStore--1577832220169711
numNetworkReqs--64371392991117
19--------
📊 Page Load Benchmark Results

Current Commit: 207acc0 | Date: 2/4/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.02s (±44ms) 🟡 | historical mean value: 1.03s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 711ms (±41ms) 🟢 | historical mean value: 723ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 76ms (±14ms) 🟢 | historical mean value: 80ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.02s 44ms 999ms 1.38s 1.05s 1.38s
domContentLoaded 711ms 41ms 691ms 1.04s 736ms 1.04s
firstPaint 76ms 14ms 56ms 204ms 88ms 204ms
firstContentfulPaint 76ms 14ms 56ms 204ms 88ms 204ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚀 Bundle size reduced!]
  • background: 58 Bytes (0%)
  • ui: -6.58 KiB (-0.08%)
  • common: -694 Bytes (-0.01%)

@metamaskbotv2
Copy link
Contributor

metamaskbotv2 bot commented Feb 4, 2026

Builds ready [3fbca98]
UI Startup Metrics (1396 ± 85 ms)
PlatformBuildTypePageMetricTest Title (ms)Persona (ms)Mean (ms)Min (ms)Max (ms)Std Dev (ms)P 75 (ms)P 95 (ms)
ChromeBrowserifyStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--1396121516218514491550
load--1188100313918312501331
domContentLoaded--118199813818212431322
domInteractive--2717107202382
firstPaint--174701300136210320
backgroundConnect--23722030415240269
firstReactRender--17102731922
initialActions--105113
loadScripts--96077811568410271112
setupStore--1162341419
numNetworkReqs--221584191579
19--------
BrowserifyPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--16721299227716417122018
load--1101986165415210831543
domContentLoaded--1087974164114810711513
domInteractive--35171742634110
firstPaint--194701651220221348
backgroundConnect--31126446033321392
firstReactRender--23145082547
initialActions--105113
loadScripts--85775613961398341268
setupStore--17670111945
numNetworkReqs--1205027650146238
19--------
WebpackStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--86869011381139601067
load--7286111034105799951
domContentLoaded--7236061026104792944
domInteractive--2617100172474
firstPaint--1096232946134187
backgroundConnect--3417109203993
firstReactRender--1711132131730
initialActions--105112
loadScripts--7206041024103789942
setupStore--1264261223
numNetworkReqs--231587211585
19--------
WebpackPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--1244833187720913361815
load--71162410921147001060
domContentLoaded--70261610801146891045
domInteractive--36181973036106
firstPaint--1416550781176310
backgroundConnect--16813136553171320
firstReactRender--22174342429
initialActions--102011
loadScripts--69961410691126871032
setupStore--1142131316
numNetworkReqs--1204629556144280
19--------
FirefoxBrowserifyStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--16921325241820917822121
load--14141147191116515021835
domContentLoaded--14131147190616515021835
domInteractive--75302393990150
firstPaint--------
backgroundConnect--852721451132206
firstReactRender--12102221315
initialActions--103012
loadScripts--13651131188414414271702
setupStore--2242894612126
numNetworkReqs--2512101221891
19--------
BrowserifyPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--26872131422644828193636
load--15151210275326315952202
domContentLoaded--15141210275226315952202
domInteractive--120341386150114347
firstPaint--------
backgroundConnect--270113923212293902
firstReactRender--18146571826
initialActions--207123
loadScripts--14661188271724115262150
setupStore--1268753197114684
numNetworkReqs--68371362996126
19--------
WebpackStandard Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--15591306219217216511960
load--13491120187113614331625
domContentLoaded--13481120187013614321624
domInteractive--812818339111142
firstPaint--------
backgroundConnect--62231693972150
firstReactRender--14119591419
initialActions--102012
loadScripts--13121106181112513621500
setupStore--164247331142
numNetworkReqs--241299191874
19--------
WebpackPower User Home0--------
1--------
2--------
3--------
4--------
5--------
6--------
7--------
8--------
9--------
10--------
11--------
12--------
13--------
14--------
15--------
16--------
17--------
18--------
uiStartup--27622109532949529473662
load--15731195271931016812251
domContentLoaded--15731195271931016812250
domInteractive--12531593113125405
firstPaint--------
backgroundConnect--3101201014232308926
firstReactRender--22163852532
initialActions--203123
loadScripts--15291182269328316502080
setupStore--1568797205184675
numNetworkReqs--68361393099127
19--------
📊 Page Load Benchmark Results

Current Commit: 3fbca98 | Date: 2/4/2026

📄 Localhost MetaMask Test Dapp

Samples: 100

Summary

  • pageLoadTime-> current mean value: 1.03s (±43ms) 🟡 | historical mean value: 1.03s ⬇️ (historical data)
  • domContentLoaded-> current mean value: 720ms (±39ms) 🟢 | historical mean value: 723ms ⬇️ (historical data)
  • firstContentfulPaint-> current mean value: 76ms (±13ms) 🟢 | historical mean value: 80ms ⬇️ (historical data)

📈 Detailed Results

Metric Mean Std Dev Min Max P95 P99
pageLoadTime 1.03s 43ms 1.01s 1.36s 1.06s 1.36s
domContentLoaded 720ms 39ms 698ms 1.03s 745ms 1.03s
firstPaint 76ms 13ms 60ms 192ms 84ms 192ms
firstContentfulPaint 76ms 13ms 60ms 192ms 84ms 192ms
largestContentfulPaint 0ms 0ms 0ms 0ms 0ms 0ms
Bundle size diffs [🚀 Bundle size reduced!]
  • background: 58 Bytes (0%)
  • ui: -6.58 KiB (-0.08%)
  • common: -694 Bytes (-0.01%)

@khanti42 khanti42 marked this pull request as ready for review February 5, 2026 00:06
@khanti42 khanti42 requested a review from a team as a code owner February 5, 2026 00:06
@HowardBraham HowardBraham changed the title fix: handle evm unsupported chains gracefully in send flow for custom network fix: handle evm unsupported chains gracefully in send flow for custom network cp-13.17.0 Feb 5, 2026
Copy link
Contributor

@Julink-eth Julink-eth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment on lines +239 to +243
// Before converting decimal strings to hex, check if it's a non-EVM chainId
// This prevents misidentifying non-EVM chains (e.g., Solana, Bitcoin, Tron) as EVM
if (isNonEvmChainId(chainId)) {
return false;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on moving this to the top of the function? We'd return early from the function, and we wouldn't have an if statement inside another else statement

Comment on lines +476 to +499
it('should return true for EVM chain ids passed as decimal strings', () => {
// Test Injective testnet (1439) - the original bug case
expect(isEvmChainId('1439' as Hex)).toBe(true);
// Test other EVM chains as decimal strings
expect(isEvmChainId('1' as Hex)).toBe(true); // Ethereum mainnet
expect(isEvmChainId('137' as Hex)).toBe(true); // Polygon
expect(isEvmChainId('1776' as Hex)).toBe(true); // Injective mainnet
});

it('should return false for non-EVM chain ids passed as decimal strings', () => {
// Test Solana (1151111081099710)
expect(isEvmChainId('1151111081099710' as Hex)).toBe(false);
// Test Bitcoin (20000000000001)
expect(isEvmChainId('20000000000001' as Hex)).toBe(false);
// Test Tron (728126428)
expect(isEvmChainId('728126428' as Hex)).toBe(false);
});

it('should handle Injective testnet chainId in different formats', () => {
// All these should return true for Injective testnet (1439)
expect(isEvmChainId('1439' as Hex)).toBe(true); // Decimal string
expect(isEvmChainId('0x59f' as Hex)).toBe(true); // Hex format
expect(isEvmChainId('eip155:1439' as CaipChainId)).toBe(true); // CAIP format
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
it('should return true for EVM chain ids passed as decimal strings', () => {
// Test Injective testnet (1439) - the original bug case
expect(isEvmChainId('1439' as Hex)).toBe(true);
// Test other EVM chains as decimal strings
expect(isEvmChainId('1' as Hex)).toBe(true); // Ethereum mainnet
expect(isEvmChainId('137' as Hex)).toBe(true); // Polygon
expect(isEvmChainId('1776' as Hex)).toBe(true); // Injective mainnet
});
it('should return false for non-EVM chain ids passed as decimal strings', () => {
// Test Solana (1151111081099710)
expect(isEvmChainId('1151111081099710' as Hex)).toBe(false);
// Test Bitcoin (20000000000001)
expect(isEvmChainId('20000000000001' as Hex)).toBe(false);
// Test Tron (728126428)
expect(isEvmChainId('728126428' as Hex)).toBe(false);
});
it('should handle Injective testnet chainId in different formats', () => {
// All these should return true for Injective testnet (1439)
expect(isEvmChainId('1439' as Hex)).toBe(true); // Decimal string
expect(isEvmChainId('0x59f' as Hex)).toBe(true); // Hex format
expect(isEvmChainId('eip155:1439' as CaipChainId)).toBe(true); // CAIP format
});
it.each(['1439' as Hex, '1' as Hex, '137' as Hex, '1776' as Hex])(
'should return true for EVM chain ids passed as decimal strings',
(chainId) => {
expect(isEvmChainId(chainId)).toBe(true);
},
);
it.each([
'1151111081099710' as Hex,
'20000000000001' as Hex,
'728126428' as Hex,
])(
'should return false for non-EVM chain ids passed as decimal strings',
(chainId) => {
expect(isEvmChainId(chainId)).toBe(false);
},
);
it.each(['1439' as Hex, '0x59f', 'eip155:1439'])(
'should handle Injective testnet chainId in different formats',
(chainId) => {
expect(isEvmChainId(chainId)).toBe(true);
},
);

@khanti42 khanti42 added this pull request to the merge queue Feb 5, 2026
Merged via the queue into main with commit 493bc23 Feb 5, 2026
204 checks passed
@khanti42 khanti42 deleted the fix/custom-network-send-error branch February 5, 2026 16:32
@github-actions github-actions bot locked and limited conversation to collaborators Feb 5, 2026
@metamaskbot metamaskbot added the release-13.18.0 Issue or pull request that will be included in release 13.18.0 label Feb 5, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-13.18.0 Issue or pull request that will be included in release 13.18.0 size-S team-network-enablement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants