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

fix: fix import ERC20 on network 1337 #3777

Merged
merged 4 commits into from
Feb 15, 2024

Conversation

sahar-fehri
Copy link
Contributor

Explanation

This PR fixes importing an ERC20 token on chainId 1337.
This issue is on extension and Mobile.

When you run a local ganache node, you use testDapp to deploy a token, then you try to add the token to your wallet; and go back to home page but you wont be able to see the token.

The error starts on this line. It looks like it fails to pass that line to create the newEntry and push it to newTokens array.
The error is thrown on this line (See screenshot)

Screenshot 2024-01-12 at 18 14 32

I see that tokenApi does not support chainId 1337 and the error is being thrown here https://github.com/consensys-vertical-apps/va-mmcx-token-api/blob/6c1b749c33a110f9dd8004dd283f6d9f7dcb4824/src/server.ts#L522

that is because networkConfig does not contain the 1337 chainId.

After testing also with Goerli testnet, where importing ERC20 works fine, i noticed that goerli is not supported on core so the fetchTokenMetadata threw here because isTokenDetectionSupportedForNetwork returned false

isTokenDetectionSupportedForNetwork(chainId) || chainId === GANACHE_CHAIN_ID
. I wasnt sure why we did not treat chainId 1337 same way as goerli.
So i removed the || chainId === GANACHE_CHAIN_ID check on the utils fct.

After the fix, i tested importing the ERC20, importing ERC721/1155, works fine.

Lemme know if anything! 🙏

Video Before

Screen.Recording.2024-01-12.at.18.08.29.mov

Video After

Screen.Recording.2024-01-12.at.17.16.10.mov

References

Changelog

@metamask/assets-controllers

  • : Updates the fct on assetsUtils isTokenListSupportedForNetwork and removed the check for GANACHE_CHAIN_ID

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've highlighted breaking changes using the "BREAKING" category above as appropriate

@sahar-fehri sahar-fehri requested a review from a team as a code owner January 12, 2024 17:49
@sahar-fehri sahar-fehri force-pushed the fix/MMASSETS-104-fix-import-ERC20-chainId-1337 branch from ff44d8f to 6319b2a Compare January 12, 2024 17:56
Copy link
Member

@mikesposito mikesposito left a comment

Choose a reason for hiding this comment

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

Changes look good, but I also do not have enough context on why GANACHE_CHAIN_ID is treated as an exception: perhaps it is a residual of what we had before the CoinGecko issue, or it is useful for e2e tests?

Were you able to run e2e tests on extension, using this PR's version of assets controllers?

@sahar-fehri sahar-fehri force-pushed the fix/MMASSETS-104-fix-import-ERC20-chainId-1337 branch from 6319b2a to eab835c Compare February 5, 2024 12:22
@sahar-fehri
Copy link
Contributor Author

Changes look good, but I also do not have enough context on why GANACHE_CHAIN_ID is treated as an exception: perhaps it is a residual of what we had before the CoinGecko issue, or it is useful for e2e tests?

Were you able to run e2e tests on extension, using this PR's version of assets controllers?

Hey @mikesposito ! I made a small update so my change does modify the isTokenListSupportedForNetwork fct cause it seems to be also used in TokensListController, noticed that the test test/e2e/tests/add-hide-token.spec.js was failing, but it passes now with latest update 🙏

@@ -78,7 +82,10 @@ export async function fetchTokenMetadata<T>(
abortSignal: AbortSignal,
{ timeout = defaultTimeout } = {},
): Promise<T | undefined> {
if (!isTokenListSupportedForNetwork(chainId)) {
if (
!isTokenListSupportedForNetwork(chainId) ||
Copy link
Contributor

@mcmire mcmire Feb 5, 2024

Choose a reason for hiding this comment

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

Sorry, I don't remember what was here before (it would be better in the future to not squash commits so we can always look back at your previous changes). If the goal of this function is to determine whether a chain supports token lists, what do you think about modifying the isTokenListSupportedForNetwork function to exclude the GANACHE_CHAIN_ID? Or did it cause the e2e test to fail as you mentioned? If that's the case, is there something we can do on the extension side to fix the test rather than making this code less cohesive?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hello @mcmire , apologies was a bad idea to squash 🙏 ^^ But you are right, indeed the old change was to exclude GANACHE_CHAIN_ID from isTokenListSupportedForNetwork function. That caused the test test/e2e/tests/add-hide-token.spec.js to fail. I could see the reason why it was failing.

Because the isTokenListSupportedForNetwork was returning false after removing GANACHE_CHAIN_ID; the code went to this line

instead of doing startPolling.

In our e2e tests we mock the following call https://github.com/MetaMask/metamask-extension/blob/5a968da2eeb6818247af982d58e00b14dc7fb72a/test/e2e/mock-e2e.js#L268 which would correspond to this part

if we did startPolling and went to execute fetchTokenList.

So on the UI part, we endup with an empty state.tokenList, and the test fail because it was looking for the BAT token to click on it and import it.

By leaving the GANACHE_CHAIN_ID in the isTokenListSupportedForNetwork, it will trigger populating the tokenList;
but i agree it makes the code look a bit less cohesive when we add it in fetchTokenMetadata instead.

Looks like for the test to pass, the isTokenListSupportedForNetwork must return true for ganache ID. But at the same time, the ganache ID needs to be excluded for fetchTokenMetadata so the user is able to see the token imported...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have made an update so the fct isTokenListSupportedForNetwork does not consider the GanacheID as supported; (since the call inside fetchTokenMetadata to tokenApi would fail because token api does not support it anyway)

but also so that does not stop the test from doing the startPolling..

@mcmire
Copy link
Contributor

mcmire commented Feb 7, 2024

Hi @sahar-fehri. Sorry it's taken me a while to look at this.

I took some time to test the original issue and look at the code. I believe I found exactly what you found, but just for clarity, this seems to be the sequence of events:

  • The user adds the token to their wallet through a dapp, which calls wallet_watchAsset on the provider and to MetaMask.
  • This causes the addToken method on TokensController to get called.
  • This method calls fetchTokenMetadata, also on TokensController.
  • This method calls fetchTokenMetadata in assetsUtil.
  • This function attempts to request information about the token from the Token API. However, because the Token API doesn't support chain 1337, the request fails and an error is thrown.
  • fetchTokenMetadata may throw an error if isTokenListSupportedForNetwork returns false. If this were to happen, then the TokensController version of fetchTokenMetadata would catch this error and return undefined. addToken expects this to happen and continues on without issue.

As for the failing extension e2e test — "Add existing token using search renders the balance for the chosen token" — I looked at why this was failing too. This test seems to be trying to simulate production, because if you do remove GANACHE_CHAIN_ID from isTokenListSupportedForNetwork, then it removes the option to search for tokens from the UI. The way that the extension has gotten around this is with a check in import-tokens-modal.js, which turns it on in e2e tests.

I see why we make an exception for e2e tests here — we need some way of testing the search box — but I wonder if the way to do this is to use a custom chain ID for Ganache (not 1337, in other words) so that isTokenListSupportedForNetwork returns true. Perhaps we will need to extract this test to a different file so that this is easier, I'm not sure.

To recap, I think we just need to remove GANACHE_CHAIN_ID check from isTokenListSupportedForNetwork here. That path seems to make the most sense to me, but at the same time I think we should update the e2e test so that it better simulates production instead of localhost.

What do you think? Would that work?

@sahar-fehri
Copy link
Contributor Author

Hi @sahar-fehri. Sorry it's taken me a while to look at this.

I took some time to test the original issue and look at the code. I believe I found exactly what you found, but just for clarity, this seems to be the sequence of events:

  • The user adds the token to their wallet through a dapp, which calls wallet_watchAsset on the provider and to MetaMask.
  • This causes the addToken method on TokensController to get called.
  • This method calls fetchTokenMetadata, also on TokensController.
  • This method calls fetchTokenMetadata in assetsUtil.
  • This function attempts to request information about the token from the Token API. However, because the Token API doesn't support chain 1337, the request fails and an error is thrown.
  • fetchTokenMetadata may throw an error if isTokenListSupportedForNetwork returns false. If this were to happen, then the TokensController version of fetchTokenMetadata would catch this error and return undefined. addToken expects this to happen and continues on without issue.

As for the failing extension e2e test — "Add existing token using search renders the balance for the chosen token" — I looked at why this was failing too. This test seems to be trying to simulate production, because if you do remove GANACHE_CHAIN_ID from isTokenListSupportedForNetwork, then it removes the option to search for tokens from the UI. The way that the extension has gotten around this is with a check in import-tokens-modal.js, which turns it on in e2e tests.

I see why we make an exception for e2e tests here — we need some way of testing the search box — but I wonder if the way to do this is to use a custom chain ID for Ganache (not 1337, in other words) so that isTokenListSupportedForNetwork returns true. Perhaps we will need to extract this test to a different file so that this is easier, I'm not sure.

To recap, I think we just need to remove GANACHE_CHAIN_ID check from isTokenListSupportedForNetwork here. That path seems to make the most sense to me, but at the same time I think we should update the e2e test so that it better simulates production instead of localhost.

What do you think? Would that work?

Thnx @mcmire 🙏 It makes sense to update the e2e test to use mainnet instead of ganache since tokenApi does not support it in the first place; pushed a small update to this and updated the e2e test on extension : MetaMask/metamask-extension#22880

Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

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

I hadn't realized you'd already made the change I requested. Sorry for the delay. This looks good to me!

sahar-fehri added a commit to MetaMask/metamask-extension that referenced this pull request Feb 15, 2024
## **Description**

Switches e2e test to connect to BSC instead of ganache.
This is related to an incoming change on core to remove ganache ID from
isTokenListSupportedForNetwork since accountApi does not support ganache
and the fetchTokenMetadata would fail not allowing users who are using
ganache to see the imported ERC20 tokens.

This e2e test using ganache was passing initially because we mock the
following call
https://github.com/MetaMask/metamask-extension/blob/5a968da2eeb6818247af982d58e00b14dc7fb72a/test/e2e/mock-e2e.js#L268.

## **Related issues**
Fixes: MetaMask/metamask-mobile#6410
Related to :(MetaMask/core#3777)

## **Manual testing steps**

1. Run ganache locally
2. Use test dapp to deploy ERC20
3. Use test dapp to add the token to wallet (triggering watchAsset)
4. You should be able to see the new token in tokens tab

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've clearly explained what problem this PR is solving and how it
is solved.
- [ ] I've linked related issues
- [ ] I've included manual testing steps
- [ ] I've included screenshots/recordings if applicable
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
- [ ] I’ve properly set the pull request status:
  - [ ] In case it's not yet "ready for review", I've set it to "draft".
- [ ] In case it's "ready for review", I've changed it from "draft" to
"non-draft".

## **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.
@sahar-fehri sahar-fehri force-pushed the fix/MMASSETS-104-fix-import-ERC20-chainId-1337 branch from a94f8a7 to cc68bfd Compare February 15, 2024 12:57
@sahar-fehri sahar-fehri merged commit 464f899 into main Feb 15, 2024
136 checks passed
@sahar-fehri sahar-fehri deleted the fix/MMASSETS-104-fix-import-ERC20-chainId-1337 branch February 15, 2024 13:01
MajorLift pushed a commit that referenced this pull request Feb 16, 2024
## Explanation

This PR fixes importing an ERC20 token on chainId 1337.
This issue is on extension and Mobile.

When you run a local ganache node, you use testDapp to deploy a token,
then you try to add the token to your wallet; and go back to home page
but you wont be able to see the token.

The error starts on this
[line](https://github.com/MetaMask/core/blob/f8437e9a626007de7192871452273ebd0f2edb35/packages/assets-controllers/src/TokensController.ts#L335).
It looks like it fails to pass that line to create the `newEntry` and
push it to `newTokens` array.
The error is thrown on this
[line](https://github.com/MetaMask/core/blob/f8437e9a626007de7192871452273ebd0f2edb35/packages/assets-controllers/src/token-service.ts#L136)
(See screenshot)

<img width="1510" alt="Screenshot 2024-01-12 at 18 14 32"
src="https://github.com/MetaMask/core/assets/10994169/fc3105a3-eb68-401c-865a-0119917302eb">

I see that
[tokenApi](https://github.com/consensys-vertical-apps/va-mmcx-token-api)
does not support chainId 1337 and the error is being thrown here
https://github.com/consensys-vertical-apps/va-mmcx-token-api/blob/6c1b749c33a110f9dd8004dd283f6d9f7dcb4824/src/server.ts#L522

that is because
[networkConfig](https://github.com/consensys-vertical-apps/va-mmcx-token-api/blob/6c1b749c33a110f9dd8004dd283f6d9f7dcb4824/src/constants.ts#L399)
does not contain the 1337 chainId.

After testing also with Goerli testnet, where importing ERC20 works
fine, i noticed that goerli is not supported on core so the
fetchTokenMetadata threw
[here](https://github.com/MetaMask/core/blob/f8437e9a626007de7192871452273ebd0f2edb35/packages/assets-controllers/src/token-service.ts#L82)
because `isTokenDetectionSupportedForNetwork` returned false
https://github.com/MetaMask/core/blob/f8437e9a626007de7192871452273ebd0f2edb35/packages/assets-controllers/src/assetsUtil.ts#L156.
I wasnt sure why we did not treat chainId 1337 same way as goerli.
So i removed the `|| chainId === GANACHE_CHAIN_ID` check on the utils
fct.

After the fix, i tested importing the ERC20, importing ERC721/1155,
works fine.

Lemme know if anything!  🙏 

## Video Before


https://github.com/MetaMask/core/assets/10994169/7b567366-f5df-4d1b-b61d-7d4a46711faa

## Video After


https://github.com/MetaMask/core/assets/10994169/3068a526-4c95-4c88-9c62-38acb202561f


## References

* Fixes MetaMask/metamask-mobile#6410

## Changelog

<!--
If you're making any consumer-facing changes, list those changes here as
if you were updating a changelog, using the template below as a guide.

(CATEGORY is one of BREAKING, ADDED, CHANGED, DEPRECATED, REMOVED, or
FIXED. For security-related issues, follow the Security Advisory
process.)

Please take care to name the exact pieces of the API you've added or
changed (e.g. types, interfaces, functions, or methods).

If there are any breaking changes, make sure to offer a solution for
consumers to follow once they upgrade to the changes.

Finally, if you're only making changes to development scripts or tests,
you may replace the template below with "None".
-->

### `@metamask/assets-controllers`

- **<FIXED>**: Updates the fct on assetsUtils
`isTokenListSupportedForNetwork` and removed the check for
`GANACHE_CHAIN_ID`


## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've highlighted breaking changes using the "BREAKING" category
above as appropriate
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug] Cannot import an ERC20 token when on a network id 1337
3 participants