From e4225ac52a6177817b5e9a223f74143f7401edf3 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Tue, 25 Jul 2023 15:40:59 -0230 Subject: [PATCH] refactor: Update `@metamask/assets-controllers` patch The `@metamask/assets-controllers` patch added as part of the permission system implementation [1] has been updated to more closely match how the feature was implemented upstream [2]. It should be functionally equivalent. This relates to https://github.com/MetaMask/mobile-planning/issues/877 [1]: https://github.com/MetaMask/metamask-mobile/pull/5062 [2]: https://github.com/MetaMask/core/pull/1124 --- app/components/UI/AddCustomToken/index.js | 2 +- .../UI/Ramp/hooks/useHandleSuccessfulOrder.ts | 2 +- .../UI/SearchTokenAutocomplete/index.tsx | 5 +- app/components/UI/Swaps/QuotesView.js | 2 +- app/components/UI/Swaps/index.js | 2 +- .../Views/SendFlow/Confirm/index.js | 5 +- .../useAddressBalance/useAddressBalance.ts | 7 +- .../@metamask+assets-controllers+5.0.0.patch | 232 +++++++++--------- 8 files changed, 128 insertions(+), 129 deletions(-) diff --git a/app/components/UI/AddCustomToken/index.js b/app/components/UI/AddCustomToken/index.js index 7f65c60607cc..2deccd000668 100644 --- a/app/components/UI/AddCustomToken/index.js +++ b/app/components/UI/AddCustomToken/index.js @@ -117,7 +117,7 @@ export default class AddCustomToken extends PureComponent { if (!(await this.validateCustomToken())) return; const { TokensController } = Engine.context; const { address, symbol, decimals, name } = this.state; - await TokensController.addToken(address, symbol, decimals, null, name); + await TokensController.addToken(address, symbol, decimals, { name }); AnalyticsV2.trackEvent( MetaMetricsEvents.TOKEN_ADDED, diff --git a/app/components/UI/Ramp/hooks/useHandleSuccessfulOrder.ts b/app/components/UI/Ramp/hooks/useHandleSuccessfulOrder.ts index 43474671cc2b..3ed09b60bd32 100644 --- a/app/components/UI/Ramp/hooks/useHandleSuccessfulOrder.ts +++ b/app/components/UI/Ramp/hooks/useHandleSuccessfulOrder.ts @@ -45,7 +45,7 @@ function useHandleSuccessfulOrder() { toLowerCaseEquals(t.address, address), ) ) { - await TokensController.addToken(address, symbol, decimals, null, name); + await TokensController.addToken(address, symbol, decimals, { name }); } }, [selectedChainId], diff --git a/app/components/UI/SearchTokenAutocomplete/index.tsx b/app/components/UI/SearchTokenAutocomplete/index.tsx index 6909e354c4c7..be5908c7c07a 100644 --- a/app/components/UI/SearchTokenAutocomplete/index.tsx +++ b/app/components/UI/SearchTokenAutocomplete/index.tsx @@ -106,7 +106,10 @@ const SearchTokenAutocomplete = ({ navigation }: Props) => { const addToken = useCallback(async () => { const { TokensController } = Engine.context as any; - await TokensController.addToken(address, symbol, decimals, iconUrl, name); + await TokensController.addToken(address, symbol, decimals, { + image: iconUrl, + name, + }); AnalyticsV2.trackEvent(MetaMetricsEvents.TOKEN_ADDED, getAnalyticsParams()); diff --git a/app/components/UI/Swaps/QuotesView.js b/app/components/UI/Swaps/QuotesView.js index 089e941be83d..5ab766c292cb 100644 --- a/app/components/UI/Swaps/QuotesView.js +++ b/app/components/UI/Swaps/QuotesView.js @@ -348,7 +348,7 @@ async function addTokenToAssetsController(newToken) { ) ) { const { address, symbol, decimals, name } = newToken; - await TokensController.addToken(address, symbol, decimals, null, name); + await TokensController.addToken(address, symbol, decimals, { name }); } } diff --git a/app/components/UI/Swaps/index.js b/app/components/UI/Swaps/index.js index 73af0449289b..991fb128e11f 100644 --- a/app/components/UI/Swaps/index.js +++ b/app/components/UI/Swaps/index.js @@ -528,7 +528,7 @@ function SwapsAmountView({ ) { const { TokensController } = Engine.context; const { address, symbol, decimals, name } = sourceToken; - await TokensController.addToken(address, symbol, decimals, null, name); + await TokensController.addToken(address, symbol, decimals, { name }); } return navigation.navigate( 'SwapsQuotesView', diff --git a/app/components/Views/SendFlow/Confirm/index.js b/app/components/Views/SendFlow/Confirm/index.js index e98a9ca35067..aa7d1cca1e82 100644 --- a/app/components/Views/SendFlow/Confirm/index.js +++ b/app/components/Views/SendFlow/Confirm/index.js @@ -545,7 +545,10 @@ class Confirm extends PureComponent { const { TokensController } = Engine.context; if (!contractBalances[address]) { - await TokensController.addToken(address, symbol, decimals, image, name); + await TokensController.addToken(address, symbol, decimals, { + image, + name, + }); } const [, , rawAmount] = decodeTransferData('transfer', data); diff --git a/app/components/hooks/useAddressBalance/useAddressBalance.ts b/app/components/hooks/useAddressBalance/useAddressBalance.ts index d8eeaa824513..f0851324cb38 100644 --- a/app/components/hooks/useAddressBalance/useAddressBalance.ts +++ b/app/components/hooks/useAddressBalance/useAddressBalance.ts @@ -42,13 +42,10 @@ const useAddressBalance = (asset: Asset, address?: string) => { return; } if (!contractBalances[contractAddress]) { - TokensController.addToken( - contractAddress, - symbol, - decimals, + TokensController.addToken(contractAddress, symbol, decimals, { image, name, - ); + }); } } // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/patches/@metamask+assets-controllers+5.0.0.patch b/patches/@metamask+assets-controllers+5.0.0.patch index decc17295f45..6f1e192abaad 100644 --- a/patches/@metamask+assets-controllers+5.0.0.patch +++ b/patches/@metamask+assets-controllers+5.0.0.patch @@ -418,7 +418,7 @@ index e3f81e9..c3a13ac 100644 }); } diff --git a/node_modules/@metamask/assets-controllers/dist/TokensController.js b/node_modules/@metamask/assets-controllers/dist/TokensController.js -index 8c02fe6..162376f 100644 +index 8c02fe6..fc32250 100644 --- a/node_modules/@metamask/assets-controllers/dist/TokensController.js +++ b/node_modules/@metamask/assets-controllers/dist/TokensController.js @@ -25,13 +25,6 @@ const base_controller_1 = require("@metamask/base-controller"); @@ -471,20 +471,36 @@ index 8c02fe6..162376f 100644 /** * Fetch metadata for a token. * -@@ -122,10 +115,11 @@ class TokensController extends base_controller_1.BaseController { +@@ -122,16 +115,24 @@ class TokensController extends base_controller_1.BaseController { * @param address - Hex address of the token contract. * @param symbol - Symbol of the token. * @param decimals - Number of decimals the token uses. -+ * @param name - Name of the token. - * @param image - Image of the token. +- * @param image - Image of the token. ++ * @param options - Object containing name and image of the token ++ * @param options.name - Name of the token ++ * @param options.image - Image of the token ++ * @param options.interactingAddress - The address of the account to add a token to. * @returns Current token list. */ - addToken(address, symbol, decimals, image) { -+ addToken(address, symbol, decimals, image, name) { ++ addToken(address, symbol, decimals, { image, name, interactingAddress } = {}) { return __awaiter(this, void 0, void 0, function* () { - const currentChainId = this.config.chainId; +- const currentChainId = this.config.chainId; ++ const { allTokens, allIgnoredTokens, allDetectedTokens } = this.state; ++ const { chainId: currentChainId, selectedAddress } = this.config; ++ const accountAddress = interactingAddress || selectedAddress; ++ const isInteractingWithWalletAccount = accountAddress === selectedAddress; const releaseLock = yield this.mutex.acquire(); -@@ -151,6 +145,7 @@ class TokensController extends base_controller_1.BaseController { + try { + address = (0, controller_utils_1.toChecksumHexAddress)(address); +- const { tokens, ignoredTokens, detectedTokens } = this.state; ++ const tokens = ((_a = allTokens[currentChainId]) === null || _a === void 0 ? void 0 : _a[accountAddress]) || []; ++ const ignoredTokens = ((_b = allIgnoredTokens[currentChainId]) === null || _b === void 0 ? void 0 : _b[accountAddress]) || []; ++ const detectedTokens = ((_c = allDetectedTokens[currentChainId]) === null || _c === void 0 ? void 0 : _c[accountAddress]) || []; + const newTokens = [...tokens]; + const [isERC721, tokenMetadata] = yield Promise.all([ + this._detectIsERC721(address), +@@ -151,6 +152,7 @@ class TokensController extends base_controller_1.BaseController { }), isERC721, aggregators: (0, assetsUtil_1.formatAggregatorNames)((tokenMetadata === null || tokenMetadata === void 0 ? void 0 : tokenMetadata.aggregators) || []), @@ -492,87 +508,31 @@ index 8c02fe6..162376f 100644 }; const previousEntry = newTokens.find((token) => token.address.toLowerCase() === address.toLowerCase()); if (previousEntry) { -@@ -182,6 +177,79 @@ class TokensController extends base_controller_1.BaseController { - } - }); - } -+ -+ -+ /** -+ * Adds a token to the stored token list for a specific wallet. -+ * TODO - Should consolidate this with addToken method since much of the logic is similar. -+ * -+ * @param params - Params used for adding token to an account address. -+ * @param params.accountAddress - Account address to add the token to. -+ * @param params.token - Token to add. -+ * @param params.token.address - Hex address of the token contract. -+ * @param params.token.symbol - Symbol of the token. -+ * @param params.token.decimals - Number of decimals the token uses. -+ * @param params.token.image - Image of the token. -+ * @returns Current token list. -+ */ -+ addTokenToAccount({ accountAddress, token: { address, symbol, decimals, image } }) { -+ return __awaiter(this, void 0, void 0, function* () { -+ const currentChainId = this.config.chainId; -+ const { allTokens, allIgnoredTokens, allDetectedTokens } = this.state; -+ const releaseLock = yield this.mutex.acquire(); -+ try { -+ address = (0, controller_utils_1.toChecksumHexAddress)(address); -+ const tokens = allTokens[currentChainId]?.[accountAddress] || []; -+ const ignoredTokens = allIgnoredTokens[currentChainId]?.[accountAddress] || []; -+ const detectedTokens = allDetectedTokens[currentChainId]?.[accountAddress] || []; -+ const newTokens = [...tokens]; -+ const [isERC721, tokenMetadata] = yield Promise.all([ -+ this._detectIsERC721(address), -+ this.fetchTokenMetadata(address), -+ ]); -+ if (currentChainId !== this.config.chainId) { -+ throw new Error('TokensController Error: Switched networks while adding token'); -+ } -+ const newEntry = { -+ address, -+ symbol, -+ decimals, -+ image: image || -+ (0, assetsUtil_1.formatIconUrlWithProxy)({ -+ chainId: this.config.chainId, -+ tokenAddress: address, -+ }), -+ isERC721, -+ aggregators: (0, assetsUtil_1.formatAggregatorNames)((tokenMetadata === null || tokenMetadata === void 0 ? void 0 : tokenMetadata.aggregators) || []), -+ }; -+ const previousEntry = newTokens.find((token) => token.address.toLowerCase() === address.toLowerCase()); -+ if (previousEntry) { -+ const previousIndex = newTokens.indexOf(previousEntry); -+ newTokens[previousIndex] = newEntry; -+ } -+ else { -+ newTokens.push(newEntry); -+ } -+ const newIgnoredTokens = ignoredTokens.filter((tokenAddress) => tokenAddress.toLowerCase() !== address.toLowerCase()); -+ const newDetectedTokens = detectedTokens.filter((token) => token.address.toLowerCase() !== address.toLowerCase()); -+ const { newAllTokens, newAllIgnoredTokens, newAllDetectedTokens } = this._getNewAllTokensState({ -+ newTokens, -+ newIgnoredTokens, -+ newDetectedTokens, -+ detectionAddress: accountAddress, -+ }); -+ this.update({ -+ allTokens: newAllTokens, -+ allIgnoredTokens: newAllIgnoredTokens, -+ allDetectedTokens: newAllDetectedTokens, -+ }); -+ return newTokens; -+ } -+ finally { -+ releaseLock(); +@@ -166,15 +168,18 @@ class TokensController extends base_controller_1.BaseController { + newTokens, + newIgnoredTokens, + newDetectedTokens, ++ interactingAddress: accountAddress, + }); +- this.update({ +- tokens: newTokens, +- ignoredTokens: newIgnoredTokens, +- detectedTokens: newDetectedTokens, ++ let newState = { + allTokens: newAllTokens, + allIgnoredTokens: newAllIgnoredTokens, + allDetectedTokens: newAllDetectedTokens, +- }); ++ }; ++ // Only update active tokens if user is interacting with their active wallet account. ++ if (isInteractingWithWalletAccount) { ++ newState = Object.assign(Object.assign({}, newState), { tokens: newTokens, ignoredTokens: newIgnoredTokens, detectedTokens: newDetectedTokens }); + } -+ }); -+ } - /** - * Add a batch of tokens. - * -@@ -199,7 +267,7 @@ class TokensController extends base_controller_1.BaseController { ++ this.update(newState); + return newTokens; + } + finally { +@@ -199,7 +204,7 @@ class TokensController extends base_controller_1.BaseController { }, {}); try { tokensToImport.forEach((tokenToAdd) => { @@ -581,7 +541,7 @@ index 8c02fe6..162376f 100644 const checksumAddress = (0, controller_utils_1.toChecksumHexAddress)(address); const formattedToken = { address: checksumAddress, -@@ -207,6 +275,7 @@ class TokensController extends base_controller_1.BaseController { +@@ -207,6 +212,7 @@ class TokensController extends base_controller_1.BaseController { decimals, image, aggregators, @@ -589,7 +549,7 @@ index 8c02fe6..162376f 100644 }; newTokensMap[address] = formattedToken; importedTokensMap[address.toLowerCase()] = true; -@@ -282,7 +351,7 @@ class TokensController extends base_controller_1.BaseController { +@@ -282,7 +288,7 @@ class TokensController extends base_controller_1.BaseController { let newDetectedTokens = [...detectedTokens]; try { incomingDetectedTokens.forEach((tokenToAdd) => { @@ -598,7 +558,7 @@ index 8c02fe6..162376f 100644 const checksumAddress = (0, controller_utils_1.toChecksumHexAddress)(address); const newEntry = { address: checksumAddress, -@@ -291,6 +360,7 @@ class TokensController extends base_controller_1.BaseController { +@@ -291,6 +297,7 @@ class TokensController extends base_controller_1.BaseController { image, isERC721, aggregators, @@ -606,30 +566,46 @@ index 8c02fe6..162376f 100644 }; const previousImportedEntry = newTokens.find((token) => token.address.toLowerCase() === checksumAddress.toLowerCase()); if (previousImportedEntry) { -@@ -357,6 +427,22 @@ class TokensController extends base_controller_1.BaseController { +@@ -313,12 +320,12 @@ class TokensController extends base_controller_1.BaseController { + } + } + }); +- const { selectedAddress: detectionAddress, chainId: detectionChainId } = detectionDetails || {}; ++ const { selectedAddress: interactingAddress, chainId: interactingChainId } = detectionDetails || {}; + const { newAllTokens, newAllDetectedTokens } = this._getNewAllTokensState({ + newTokens, + newDetectedTokens, +- detectionAddress, +- detectionChainId, ++ interactingAddress, ++ interactingChainId, + }); + const { chainId, selectedAddress } = this.config; + // if the newly added detectedTokens were detected on (and therefore added to) a different chainId/selectedAddress than the currently configured combo +@@ -357,6 +364,22 @@ class TokensController extends base_controller_1.BaseController { return tokens[tokenIndex]; }); } + + /** + * This is a function that updates the tokens name for the tokens name if it is not defined -+ * @param tokenList - Represents the fetched token list from service API ++ * @param tokenList - Represents the fetched token list from service API + */ + async updateTokensName(tokenList) { + const { tokens } = this.state; -+ ++ + const newTokens = tokens.map((token) => { + const newToken = tokenList[token.address.toLowerCase()]; + return (!token.name && newToken?.name) ? { ...token, name: newToken.name } : {...token}; + }); -+ ++ + this.update({ tokens: newTokens }); + } + /** * Detects whether or not a token is ERC-721 compatible. * -@@ -396,107 +482,46 @@ class TokensController extends base_controller_1.BaseController { +@@ -396,107 +419,45 @@ class TokensController extends base_controller_1.BaseController { _generateRandomId() { return (0, uuid_1.v1)(); } @@ -652,7 +628,6 @@ index 8c02fe6..162376f 100644 + throw new Error(`Asset of type ${type} not supported`); + } + const { selectedAddress } = this.config; -+ const isAddingOnWalletAccount = interactingAddress ? interactingAddress === selectedAddress : true; const suggestedAssetMeta = { asset, id: this._generateRandomId(), @@ -661,31 +636,26 @@ index 8c02fe6..162376f 100644 type, + interactingAddress: interactingAddress || selectedAddress, }; -- try { ++ (0, assetsUtil_1.validateTokenToWatch)(asset); ++ yield this._requestApproval(suggestedAssetMeta); ++ ++ let name; + try { - switch (type) { - case 'ERC20': - (0, assetsUtil_1.validateTokenToWatch)(asset); - break; - default: - throw new Error(`Asset of type ${type} not supported`); -+ (0, assetsUtil_1.validateTokenToWatch)(asset); -+ yield this._requestApproval(suggestedAssetMeta); -+ const { address, symbol, decimals, image } = suggestedAssetMeta.asset; -+ if (isAddingOnWalletAccount) { -+ let name; -+ try{ -+ name = yield this.getERC20TokenName(address); -+ }catch(error){ -+ name = null; - } -+ yield this.addToken(address, symbol, decimals, image, name); -+ } else { -+ yield this.addTokenToAccount({ accountAddress: interactingAddress, token: { address, symbol, decimals, image } }); - } +- } +- } - catch (error) { - this.failSuggestedAsset(suggestedAssetMeta, error); - return Promise.reject(error); -- } ++ name = yield this.getERC20TokenName(address); ++ } catch(error) { ++ name = null; + } - const result = new Promise((resolve, reject) => { - this.hub.once(`${suggestedAssetMeta.id}:finished`, (meta) => { - switch (meta.status) { @@ -700,14 +670,18 @@ index 8c02fe6..162376f 100644 - return reject(new Error(`Unknown status: ${meta.status}`)); - } - }); -- }); ++ yield this.addToken(asset.address, asset.symbol, asset.decimals, { ++ image: asset.image, ++ name, ++ interactingAddress: suggestedAssetMeta.interactingAddress + }); - const { suggestedAssets } = this.state; - suggestedAssets.push(suggestedAssetMeta); - this.update({ suggestedAssets: [...suggestedAssets] }); - this.hub.emit('pendingSuggestedAsset', suggestedAssetMeta); - return { result, suggestedAssetMeta }; -- }); -- } + }); + } - /** - * Accepts to watch an asset and updates it's status and deletes the suggestedAsset from state, - * adding the asset to corresponding asset state. In this case ERC20 tokens. @@ -737,8 +711,8 @@ index 8c02fe6..162376f 100644 - } - const newSuggestedAssets = suggestedAssets.filter(({ id }) => id !== suggestedAssetID); - this.update({ suggestedAssets: [...newSuggestedAssets] }); - }); - } +- }); +- } - /** - * Rejects a watchAsset request based on its ID by setting its status to "rejected" - * and emitting a `:finished` hub event. @@ -760,7 +734,29 @@ index 8c02fe6..162376f 100644 /** * Takes a new tokens and ignoredTokens array for the current network/account combination * and returns new allTokens and allIgnoredTokens state to update to. -@@ -553,6 +578,26 @@ class TokensController extends base_controller_1.BaseController { +@@ -505,16 +466,16 @@ class TokensController extends base_controller_1.BaseController { + * @param params.newTokens - The new tokens to set for the current network and selected account. + * @param params.newIgnoredTokens - The new ignored tokens to set for the current network and selected account. + * @param params.newDetectedTokens - The new detected tokens to set for the current network and selected account. +- * @param params.detectionAddress - The address on which the detected tokens to add were detected. +- * @param params.detectionChainId - The chainId on which the detected tokens to add were detected. ++ * @param params.interactingAddress - The address on which the detected tokens to add were detected. ++ * @param params.interactingChainId - The chainId on which the detected tokens to add were detected. + * @returns The updated `allTokens` and `allIgnoredTokens` state. + */ + _getNewAllTokensState(params) { +- const { newTokens, newIgnoredTokens, newDetectedTokens, detectionAddress, detectionChainId, } = params; ++ const { newTokens, newIgnoredTokens, newDetectedTokens, interactingAddress, interactingChainId, } = params; + const { allTokens, allIgnoredTokens, allDetectedTokens } = this.state; + const { chainId, selectedAddress } = this.config; +- const userAddressToAddTokens = detectionAddress !== null && detectionAddress !== void 0 ? detectionAddress : selectedAddress; +- const chainIdToAddTokens = detectionChainId !== null && detectionChainId !== void 0 ? detectionChainId : chainId; ++ const userAddressToAddTokens = interactingAddress !== null && interactingAddress !== void 0 ? interactingAddress : selectedAddress; ++ const chainIdToAddTokens = interactingChainId !== null && interactingChainId !== void 0 ? interactingChainId : chainId; + let newAllTokens = allTokens; + if ((newTokens === null || newTokens === void 0 ? void 0 : newTokens.length) || + (newTokens && +@@ -553,6 +514,26 @@ class TokensController extends base_controller_1.BaseController { clearIgnoredTokens() { this.update({ ignoredTokens: [], allIgnoredTokens: {} }); }