@metamask-previews/assets-controllers 100.1.0-preview-384cfdfef → 100.1.0-preview-15dd7d63f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -7
- package/dist/NftController.cjs +150 -198
- package/dist/NftController.cjs.map +1 -1
- package/dist/NftController.d.cts.map +1 -1
- package/dist/NftController.d.mts.map +1 -1
- package/dist/NftController.mjs +150 -198
- package/dist/NftController.mjs.map +1 -1
- package/dist/TokenBalancesController.cjs +12 -51
- package/dist/TokenBalancesController.cjs.map +1 -1
- package/dist/TokenBalancesController.d.cts.map +1 -1
- package/dist/TokenBalancesController.d.mts.map +1 -1
- package/dist/TokenBalancesController.mjs +12 -51
- package/dist/TokenBalancesController.mjs.map +1 -1
- package/dist/TokenDetectionController.cjs +2 -0
- package/dist/TokenDetectionController.cjs.map +1 -1
- package/dist/TokenDetectionController.d.cts.map +1 -1
- package/dist/TokenDetectionController.d.mts.map +1 -1
- package/dist/TokenDetectionController.mjs +2 -0
- package/dist/TokenDetectionController.mjs.map +1 -1
- package/dist/balances.cjs +12 -46
- package/dist/balances.cjs.map +1 -1
- package/dist/balances.d.cts +3 -14
- package/dist/balances.d.cts.map +1 -1
- package/dist/balances.d.mts +3 -14
- package/dist/balances.d.mts.map +1 -1
- package/dist/balances.mjs +12 -46
- package/dist/balances.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/multi-chain-accounts-service/api-balance-fetcher.cjs +9 -18
- package/dist/multi-chain-accounts-service/api-balance-fetcher.cjs.map +1 -1
- package/dist/multi-chain-accounts-service/api-balance-fetcher.d.cts +0 -10
- package/dist/multi-chain-accounts-service/api-balance-fetcher.d.cts.map +1 -1
- package/dist/multi-chain-accounts-service/api-balance-fetcher.d.mts +0 -10
- package/dist/multi-chain-accounts-service/api-balance-fetcher.d.mts.map +1 -1
- package/dist/multi-chain-accounts-service/api-balance-fetcher.mjs +9 -18
- package/dist/multi-chain-accounts-service/api-balance-fetcher.mjs.map +1 -1
- package/dist/rpc-service/rpc-balance-fetcher.cjs +58 -99
- package/dist/rpc-service/rpc-balance-fetcher.cjs.map +1 -1
- package/dist/rpc-service/rpc-balance-fetcher.d.cts +1 -4
- package/dist/rpc-service/rpc-balance-fetcher.d.cts.map +1 -1
- package/dist/rpc-service/rpc-balance-fetcher.d.mts +1 -4
- package/dist/rpc-service/rpc-balance-fetcher.d.mts.map +1 -1
- package/dist/rpc-service/rpc-balance-fetcher.mjs +58 -99
- package/dist/rpc-service/rpc-balance-fetcher.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,20 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
### Added
|
|
11
|
-
|
|
12
|
-
- Add optional `networkConfigurationsByChainId` parameter to `calculateBalanceForAllWallets`, `calculateBalanceChangeForAllWallets`, and `calculateBalanceChangeForAccountGroup`. When provided, native (and staked-native) token balances fall back to `CurrencyRateController` when `TokenRatesController` has no market data for the chain, so aggregated balance can be displayed when only a native-currency rate is available. Export type `NetworkConfigurationNativeCurrency` for consumers passing network configs into these functions ([#8141](https://github.com/MetaMask/core/pull/8141))
|
|
13
|
-
|
|
14
10
|
### Changed
|
|
15
11
|
|
|
16
|
-
- Optimize NFT Controller state writes from O(2n) to O(2) for NFT detection by batching contract and NFT additions ([#8079](https://github.com/MetaMask/core/pull/8079))
|
|
17
|
-
- Remove on-chain ERC-721 RPC fallback for contract name and symbol in `NftController`; contract metadata is now sourced exclusively from the NFT API, eliminating `getERC721AssetName`/`getERC721AssetSymbol` calls during NFT detection. NFT contracts that previously had `name` or `symbol` populated via on-chain calls will no longer have those fields if the NFT API does not supply them ([#8079](https://github.com/MetaMask/core/pull/8079))
|
|
18
12
|
- When `isHomepageSectionsV1Enabled` is true, `AccountTrackerController` now uses all popular EVM networks (via `NetworkEnablementController:listPopularEvmNetworks`) for balance refresh on account change and keyring unlock, instead of only the enabled networks from `NetworkEnablementController` state ([#8117](https://github.com/MetaMask/core/pull/8117))
|
|
19
13
|
|
|
20
14
|
### Fixed
|
|
21
15
|
|
|
22
16
|
- Gate `TokenListController` polling on controller initialization to avoid duplicate token list API requests during startup races ([#8113](https://github.com/MetaMask/core/pull/8113))
|
|
23
|
-
- Update token balance fallback behavior so missing ERC-20 balances from `AccountsApiBalanceFetcher` are returned as `unprocessedTokens` and fetched through RPC fallback, rather than being forcibly set to zero ([#8132](https://github.com/MetaMask/core/pull/8132))
|
|
24
17
|
|
|
25
18
|
## [100.1.0]
|
|
26
19
|
|
package/dist/NftController.cjs
CHANGED
|
@@ -13,7 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
13
13
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
14
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
15
|
};
|
|
16
|
-
var _NftController_instances, _NftController_mutex, _NftController_selectedAccountId, _NftController_ipfsGateway, _NftController_displayNftMedia, _NftController_useIpfsSubdomains, _NftController_isIpfsGatewayEnabled, _NftController_onNftAdded, _NftController_onPreferencesControllerStateChange, _NftController_onSelectedAccountChange, _NftController_updateNestedNftState, _NftController_getNftInformationFromApi, _NftController_getNftInformationFromTokenURI, _NftController_getNftURIAndStandard, _NftController_getNftInformation, _NftController_getNftContractInformation,
|
|
16
|
+
var _NftController_instances, _NftController_mutex, _NftController_selectedAccountId, _NftController_ipfsGateway, _NftController_displayNftMedia, _NftController_useIpfsSubdomains, _NftController_isIpfsGatewayEnabled, _NftController_onNftAdded, _NftController_onPreferencesControllerStateChange, _NftController_onSelectedAccountChange, _NftController_updateNestedNftState, _NftController_getNftInformationFromApi, _NftController_getNftInformationFromTokenURI, _NftController_getNftURIAndStandard, _NftController_getNftInformation, _NftController_getNftContractInformationFromContract, _NftController_getNftContractInformation, _NftController_addIndividualNft, _NftController_addNftContract, _NftController_removeAndIgnoreIndividualNft, _NftController_removeIndividualNft, _NftController_removeNftContract, _NftController_validateWatchNft, _NftController_getAddressOrSelectedAddress, _NftController_updateNftUpdateForAccount, _NftController_bulkSanitizeNftMetadata, _NftController_sanitizeNftMetadata;
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.NftController = exports.getDefaultNftControllerState = void 0;
|
|
19
19
|
const address_1 = require("@ethersproject/address");
|
|
@@ -234,35 +234,23 @@ class NftController extends base_controller_1.BaseController {
|
|
|
234
234
|
// Sanitize provided metadata
|
|
235
235
|
nftMetadata = await __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_sanitizeNftMetadata).call(this, nftMetadata);
|
|
236
236
|
}
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
},
|
|
244
|
-
]);
|
|
237
|
+
const newNftContracts = await __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_addNftContract).call(this, networkClientId, {
|
|
238
|
+
tokenAddress: checksumHexAddress,
|
|
239
|
+
userAddress: addressToSearch,
|
|
240
|
+
source,
|
|
241
|
+
nftMetadata,
|
|
242
|
+
});
|
|
245
243
|
// If NFT contract was not added, do not add individual NFT
|
|
246
|
-
const nftContract =
|
|
247
|
-
.flat()
|
|
248
|
-
.find((contract) => contract.address.toLowerCase() === checksumHexAddress.toLowerCase());
|
|
244
|
+
const nftContract = newNftContracts.find((contract) => contract.address.toLowerCase() === checksumHexAddress.toLowerCase());
|
|
249
245
|
const { configuration: { chainId }, } = this.messenger.call('NetworkController:getNetworkClientById', networkClientId);
|
|
250
246
|
// This is the case when the NFT is added manually and not detected automatically
|
|
251
247
|
// TODO: An improvement would be to make the chainId a required field and return it when getting the NFT information
|
|
252
248
|
if (!nftMetadata.chainId) {
|
|
253
249
|
nftMetadata.chainId = (0, controller_utils_1.convertHexToDecimal)(chainId);
|
|
254
250
|
}
|
|
251
|
+
// If NFT contract information, add individual NFT
|
|
255
252
|
if (nftContract) {
|
|
256
|
-
await __classPrivateFieldGet(this, _NftController_instances, "m",
|
|
257
|
-
{
|
|
258
|
-
tokenAddress: checksumHexAddress,
|
|
259
|
-
tokenId,
|
|
260
|
-
nftMetadata,
|
|
261
|
-
nftContract,
|
|
262
|
-
chainId,
|
|
263
|
-
source,
|
|
264
|
-
},
|
|
265
|
-
]);
|
|
253
|
+
await __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_addIndividualNft).call(this, checksumHexAddress, tokenId, nftMetadata, nftContract, chainId, addressToSearch, source);
|
|
266
254
|
}
|
|
267
255
|
}
|
|
268
256
|
/**
|
|
@@ -283,51 +271,23 @@ class NftController extends base_controller_1.BaseController {
|
|
|
283
271
|
}
|
|
284
272
|
// Remember max number of urls this allows is 250
|
|
285
273
|
const sanitizedNftMetadata = await __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_bulkSanitizeNftMetadata).call(this, nfts.map((nft) => nft.nftMetadata));
|
|
286
|
-
// Resolve network client IDs per item up front. Items that fail (e.g.,
|
|
287
|
-
// the user removes a network during detection) are skipped individually
|
|
288
|
-
// so the rest of the batch is unaffected. Resolved data is bundled into
|
|
289
|
-
// one object per NFT to avoid index-alignment issues between the two loops.
|
|
290
|
-
const resolvedNfts = [];
|
|
291
274
|
for (const [index, nft] of nfts.entries()) {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
checksumHexAddress,
|
|
305
|
-
hexChainId,
|
|
306
|
-
sanitizedMetadata: sanitizedNftMetadata[index],
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
catch (error) {
|
|
310
|
-
console.error('Failed to resolve network for NFT', nft.tokenAddress, error);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
const { contracts: newNftContracts } = await __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_addNftContracts).call(this, addressToSearch, resolvedNfts.map((item) => item.contractToAdd));
|
|
314
|
-
const nftsToAdd = [];
|
|
315
|
-
for (const { checksumHexAddress, tokenId, hexChainId, sanitizedMetadata, } of resolvedNfts) {
|
|
316
|
-
const nftContract = newNftContracts[hexChainId]?.find((contract) => contract.address.toLowerCase() === checksumHexAddress.toLowerCase());
|
|
275
|
+
const checksumHexAddress = (0, controller_utils_1.toChecksumHexAddress)(nft.tokenAddress);
|
|
276
|
+
const hexChainId = (0, controller_utils_1.toHex)(nft.nftMetadata.chainId);
|
|
277
|
+
const networkClientId = this.messenger.call('NetworkController:findNetworkClientIdByChainId', hexChainId);
|
|
278
|
+
const newNftContracts = await __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_addNftContract).call(this, networkClientId, {
|
|
279
|
+
tokenAddress: checksumHexAddress,
|
|
280
|
+
userAddress: addressToSearch,
|
|
281
|
+
source,
|
|
282
|
+
nftMetadata: sanitizedNftMetadata[index],
|
|
283
|
+
});
|
|
284
|
+
// If NFT contract was not added, do not add individual NFT
|
|
285
|
+
const nftContract = newNftContracts.find((contract) => contract.address.toLowerCase() === checksumHexAddress.toLowerCase());
|
|
286
|
+
// If NFT contract information, add individual NFT
|
|
317
287
|
if (nftContract) {
|
|
318
|
-
|
|
319
|
-
tokenAddress: checksumHexAddress,
|
|
320
|
-
tokenId,
|
|
321
|
-
nftMetadata: sanitizedMetadata,
|
|
322
|
-
nftContract,
|
|
323
|
-
chainId: hexChainId,
|
|
324
|
-
source,
|
|
325
|
-
});
|
|
288
|
+
await __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_addIndividualNft).call(this, checksumHexAddress, nft.tokenId, sanitizedNftMetadata[index], nftContract, hexChainId, addressToSearch, source);
|
|
326
289
|
}
|
|
327
290
|
}
|
|
328
|
-
if (nftsToAdd.length > 0) {
|
|
329
|
-
await __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_addMultipleNfts).call(this, addressToSearch, nftsToAdd);
|
|
330
|
-
}
|
|
331
291
|
}
|
|
332
292
|
/**
|
|
333
293
|
* Refetches NFT metadata and updates the state
|
|
@@ -910,16 +870,43 @@ async function _NftController_getNftInformation(contractAddress, tokenId, networ
|
|
|
910
870
|
};
|
|
911
871
|
// Sanitize the metadata by checking external links against phishing protection
|
|
912
872
|
return await __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_sanitizeNftMetadata).call(this, metadata);
|
|
913
|
-
},
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
873
|
+
}, _NftController_getNftContractInformationFromContract =
|
|
874
|
+
/**
|
|
875
|
+
* Request NFT contract information from the contract itself.
|
|
876
|
+
*
|
|
877
|
+
* @param contractAddress - Hex address of the NFT contract.
|
|
878
|
+
* @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.
|
|
879
|
+
* @returns Promise resolving to the current NFT name and image.
|
|
880
|
+
*/
|
|
881
|
+
async function _NftController_getNftContractInformationFromContract(
|
|
882
|
+
// TODO for calls to blockchain we need to explicitly pass the currentNetworkClientId since its relying on the provider
|
|
883
|
+
contractAddress, networkClientId) {
|
|
884
|
+
const [name, symbol] = await Promise.all([
|
|
885
|
+
this.messenger.call('AssetsContractController:getERC721AssetName', contractAddress, networkClientId),
|
|
886
|
+
this.messenger.call('AssetsContractController:getERC721AssetSymbol', contractAddress, networkClientId),
|
|
887
|
+
]);
|
|
888
|
+
return {
|
|
889
|
+
collection: { name },
|
|
890
|
+
symbol,
|
|
891
|
+
address: contractAddress,
|
|
892
|
+
};
|
|
893
|
+
}, _NftController_getNftContractInformation =
|
|
894
|
+
/**
|
|
895
|
+
* Request NFT contract information from Blockchain and aggregate with received data from NFTMetadata.
|
|
896
|
+
*
|
|
897
|
+
* @param contractAddress - Hex address of the NFT contract.
|
|
898
|
+
* @param nftMetadataFromApi - Received NFT information to be aggregated with blockchain contract information.
|
|
899
|
+
* @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.
|
|
900
|
+
* @returns Promise resolving to the NFT contract name, image and description.
|
|
901
|
+
*/
|
|
902
|
+
async function _NftController_getNftContractInformation(contractAddress, nftMetadataFromApi, networkClientId) {
|
|
903
|
+
const blockchainContractData = await (0, controller_utils_1.safelyExecute)(() => __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_getNftContractInformationFromContract).call(this, contractAddress, networkClientId));
|
|
904
|
+
if (blockchainContractData ||
|
|
918
905
|
!Object.values(nftMetadataFromApi).every((value) => value === null)) {
|
|
919
906
|
return {
|
|
920
907
|
address: contractAddress,
|
|
908
|
+
...blockchainContractData,
|
|
921
909
|
schema_name: nftMetadataFromApi?.standard ?? null,
|
|
922
|
-
...(symbol !== undefined && { symbol }),
|
|
923
910
|
collection: {
|
|
924
911
|
name: null,
|
|
925
912
|
image_url: nftMetadataFromApi?.collection?.image ??
|
|
@@ -927,7 +914,7 @@ async function _NftController_getNftInformation(contractAddress, tokenId, networ
|
|
|
927
914
|
null,
|
|
928
915
|
tokenCount: nftMetadataFromApi?.collection?.tokenCount ?? null,
|
|
929
916
|
...nftMetadataFromApi?.collection,
|
|
930
|
-
...
|
|
917
|
+
...blockchainContractData?.collection,
|
|
931
918
|
},
|
|
932
919
|
};
|
|
933
920
|
}
|
|
@@ -943,157 +930,122 @@ async function _NftController_getNftInformation(contractAddress, tokenId, networ
|
|
|
943
930
|
external_link: null,
|
|
944
931
|
collection: { name: null, image_url: null },
|
|
945
932
|
};
|
|
946
|
-
},
|
|
933
|
+
}, _NftController_addIndividualNft =
|
|
947
934
|
/**
|
|
948
|
-
* Adds
|
|
935
|
+
* Adds an individual NFT to the stored NFT list.
|
|
949
936
|
*
|
|
950
|
-
* @param
|
|
951
|
-
* @param
|
|
952
|
-
* @param
|
|
953
|
-
* @param
|
|
954
|
-
* @param
|
|
955
|
-
* @param
|
|
956
|
-
* @param
|
|
957
|
-
* @
|
|
937
|
+
* @param tokenAddress - Hex address of the NFT contract.
|
|
938
|
+
* @param tokenId - The NFT identifier.
|
|
939
|
+
* @param nftMetadata - NFT optional information (name, image and description).
|
|
940
|
+
* @param nftContract - An object containing contract data of the NFT being added.
|
|
941
|
+
* @param chainId - The chainId of the network where the NFT is being added.
|
|
942
|
+
* @param userAddress - The address of the account where the NFT is being added.
|
|
943
|
+
* @param source - Whether the NFT was detected, added manually or suggested by a dapp.
|
|
944
|
+
* @returns A promise resolving to `undefined`.
|
|
958
945
|
*/
|
|
959
|
-
async function
|
|
946
|
+
async function _NftController_addIndividualNft(tokenAddress, tokenId, nftMetadata, nftContract, chainId, userAddress, source) {
|
|
960
947
|
const releaseLock = await __classPrivateFieldGet(this, _NftController_mutex, "f").acquire();
|
|
961
948
|
try {
|
|
949
|
+
const checksumHexAddress = (0, controller_utils_1.toChecksumHexAddress)(tokenAddress);
|
|
962
950
|
const { allNfts } = this.state;
|
|
963
|
-
const
|
|
964
|
-
const
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
];
|
|
974
|
-
}
|
|
975
|
-
const existingEntry = allNftsForUserPerChain[chainId].find((nft) => nft.address.toLowerCase() === checksumHexAddress.toLowerCase() &&
|
|
976
|
-
nft.tokenId === tokenId);
|
|
977
|
-
if (existingEntry) {
|
|
978
|
-
const differentMetadata = (0, assetsUtil_1.compareNftMetadata)(nftMetadata, existingEntry);
|
|
979
|
-
const hasNewFields = (0, assetsUtil_1.hasNewCollectionFields)(nftMetadata, existingEntry);
|
|
980
|
-
if (!differentMetadata &&
|
|
981
|
-
existingEntry.isCurrentlyOwned &&
|
|
982
|
-
!hasNewFields) {
|
|
983
|
-
continue;
|
|
984
|
-
}
|
|
985
|
-
const indexToUpdate = allNftsForUserPerChain[chainId].findIndex((nft) => nft.address.toLowerCase() ===
|
|
986
|
-
checksumHexAddress.toLowerCase() && nft.tokenId === tokenId);
|
|
987
|
-
if (indexToUpdate !== -1) {
|
|
988
|
-
allNftsForUserPerChain[chainId][indexToUpdate] = {
|
|
989
|
-
...existingEntry,
|
|
990
|
-
...nftMetadata,
|
|
991
|
-
};
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
else {
|
|
995
|
-
const newEntry = {
|
|
996
|
-
address: checksumHexAddress,
|
|
997
|
-
tokenId,
|
|
998
|
-
favorite: false,
|
|
999
|
-
isCurrentlyOwned: true,
|
|
1000
|
-
...nftMetadata,
|
|
1001
|
-
};
|
|
1002
|
-
allNftsForUserPerChain[chainId].push(newEntry);
|
|
1003
|
-
}
|
|
1004
|
-
modifiedChainIds.add(chainId);
|
|
1005
|
-
if (__classPrivateFieldGet(this, _NftController_onNftAdded, "f")) {
|
|
1006
|
-
pendingCallbacks.push({
|
|
1007
|
-
address: checksumHexAddress,
|
|
1008
|
-
symbol: nftContract.symbol,
|
|
1009
|
-
tokenId: tokenId.toString(),
|
|
1010
|
-
standard: nftMetadata.standard,
|
|
1011
|
-
source,
|
|
1012
|
-
});
|
|
1013
|
-
}
|
|
951
|
+
const nfts = [...(allNfts[userAddress]?.[chainId] ?? [])];
|
|
952
|
+
const existingEntry = nfts.find((nft) => nft.address.toLowerCase() === checksumHexAddress.toLowerCase() &&
|
|
953
|
+
nft.tokenId === tokenId);
|
|
954
|
+
if (existingEntry) {
|
|
955
|
+
const differentMetadata = (0, assetsUtil_1.compareNftMetadata)(nftMetadata, existingEntry);
|
|
956
|
+
const hasNewFields = (0, assetsUtil_1.hasNewCollectionFields)(nftMetadata, existingEntry);
|
|
957
|
+
if (!differentMetadata &&
|
|
958
|
+
existingEntry.isCurrentlyOwned &&
|
|
959
|
+
!hasNewFields) {
|
|
960
|
+
return;
|
|
1014
961
|
}
|
|
1015
|
-
|
|
1016
|
-
|
|
962
|
+
const indexToUpdate = nfts.findIndex((nft) => nft.address.toLowerCase() === checksumHexAddress.toLowerCase() &&
|
|
963
|
+
nft.tokenId === tokenId);
|
|
964
|
+
if (indexToUpdate !== -1) {
|
|
965
|
+
nfts[indexToUpdate] = {
|
|
966
|
+
...existingEntry,
|
|
967
|
+
...nftMetadata,
|
|
968
|
+
};
|
|
1017
969
|
}
|
|
1018
970
|
}
|
|
1019
|
-
|
|
1020
|
-
|
|
971
|
+
else {
|
|
972
|
+
const newEntry = {
|
|
973
|
+
address: checksumHexAddress,
|
|
974
|
+
tokenId,
|
|
975
|
+
favorite: false,
|
|
976
|
+
isCurrentlyOwned: true,
|
|
977
|
+
...nftMetadata,
|
|
978
|
+
};
|
|
979
|
+
nfts.push(newEntry);
|
|
1021
980
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
981
|
+
__classPrivateFieldGet(this, _NftController_instances, "m", _NftController_updateNestedNftState).call(this, nfts, ALL_NFTS_STATE_KEY, {
|
|
982
|
+
chainId,
|
|
983
|
+
userAddress,
|
|
984
|
+
});
|
|
985
|
+
if (__classPrivateFieldGet(this, _NftController_onNftAdded, "f")) {
|
|
986
|
+
__classPrivateFieldGet(this, _NftController_onNftAdded, "f").call(this, {
|
|
987
|
+
address: checksumHexAddress,
|
|
988
|
+
symbol: nftContract.symbol,
|
|
989
|
+
tokenId: tokenId.toString(),
|
|
990
|
+
standard: nftMetadata.standard,
|
|
991
|
+
source,
|
|
992
|
+
});
|
|
1024
993
|
}
|
|
1025
994
|
}
|
|
1026
995
|
finally {
|
|
1027
996
|
releaseLock();
|
|
1028
997
|
}
|
|
1029
|
-
},
|
|
998
|
+
}, _NftController_addNftContract =
|
|
1030
999
|
/**
|
|
1031
|
-
* Adds
|
|
1000
|
+
* Adds an NFT contract to the stored NFT contracts list.
|
|
1032
1001
|
*
|
|
1033
|
-
* @param
|
|
1034
|
-
* @param
|
|
1035
|
-
* @param
|
|
1036
|
-
* @param
|
|
1037
|
-
* @param
|
|
1038
|
-
* @param
|
|
1039
|
-
* @returns Promise resolving to
|
|
1002
|
+
* @param networkClientId - The networkClientId that can be used to identify the network client to use for this request.
|
|
1003
|
+
* @param options - options.
|
|
1004
|
+
* @param options.tokenAddress - Hex address of the NFT contract.
|
|
1005
|
+
* @param options.userAddress - The address of the account where the NFT is being added.
|
|
1006
|
+
* @param options.nftMetadata - The retrieved NFTMetadata from API.
|
|
1007
|
+
* @param options.source - Whether the NFT was detected, added manually or suggested by a dapp.
|
|
1008
|
+
* @returns Promise resolving to the current NFT contracts list.
|
|
1040
1009
|
*/
|
|
1041
|
-
async function
|
|
1010
|
+
async function _NftController_addNftContract(networkClientId, { tokenAddress, userAddress, source, nftMetadata, }) {
|
|
1042
1011
|
const releaseLock = await __classPrivateFieldGet(this, _NftController_mutex, "f").acquire();
|
|
1043
1012
|
try {
|
|
1013
|
+
const checksumHexAddress = (0, controller_utils_1.toChecksumHexAddress)(tokenAddress);
|
|
1044
1014
|
const { allNftContracts } = this.state;
|
|
1045
|
-
const
|
|
1046
|
-
const
|
|
1047
|
-
const
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
const { configuration: { chainId }, } = this.messenger.call('NetworkController:getNetworkClientById', networkClientId);
|
|
1052
|
-
// Initialised before the existingEntry check so pre-existing contracts
|
|
1053
|
-
// are still present in the returned map for callers to look up.
|
|
1054
|
-
if (!nftContractsForUserPerChain[chainId]) {
|
|
1055
|
-
nftContractsForUserPerChain[chainId] = [
|
|
1056
|
-
...(allNftContractsForUser?.[chainId] ?? []),
|
|
1057
|
-
];
|
|
1058
|
-
}
|
|
1059
|
-
const existingEntry = nftContractsForUserPerChain[chainId].find((nftContract) => nftContract.address.toLowerCase() ===
|
|
1060
|
-
checksumHexAddress.toLowerCase());
|
|
1061
|
-
if (existingEntry) {
|
|
1062
|
-
continue;
|
|
1063
|
-
}
|
|
1064
|
-
// this doesn't work currently for detection if the user switches networks while the detection is processing
|
|
1065
|
-
// will be fixed once detection uses networkClientIds
|
|
1066
|
-
// get name and symbol if ERC721 then put together the metadata
|
|
1067
|
-
const contractInformation = __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_getNftContractInformation).call(this, checksumHexAddress, nftMetadata);
|
|
1068
|
-
// If the nft is auto-detected we want some valid metadata to be present
|
|
1069
|
-
if (source === constants_1.Source.Detected &&
|
|
1070
|
-
'address' in contractInformation &&
|
|
1071
|
-
typeof contractInformation.address === 'string' &&
|
|
1072
|
-
'collection' in contractInformation &&
|
|
1073
|
-
contractInformation.collection.name === null &&
|
|
1074
|
-
'image_url' in contractInformation.collection &&
|
|
1075
|
-
contractInformation.collection.image_url === null &&
|
|
1076
|
-
Object.entries(contractInformation).every(([key, value]) => {
|
|
1077
|
-
return key === 'address' || key === 'collection' || !value;
|
|
1078
|
-
})) {
|
|
1079
|
-
continue;
|
|
1080
|
-
}
|
|
1081
|
-
const { asset_contract_type, created_date, symbol, description, external_link, schema_name, collection: { name, image_url, tokenCount }, } = contractInformation;
|
|
1082
|
-
/* istanbul ignore next */
|
|
1083
|
-
const newEntry = Object.assign({}, { address: checksumHexAddress }, description && { description }, name && { name }, image_url && { logo: image_url }, symbol && { symbol }, tokenCount !== null &&
|
|
1084
|
-
typeof tokenCount !== 'undefined' && { totalSupply: tokenCount }, asset_contract_type && { assetContractType: asset_contract_type }, created_date && { createdDate: created_date }, schema_name && { schemaName: schema_name }, external_link && { externalLink: external_link });
|
|
1085
|
-
nftContractsForUserPerChain[chainId].push(newEntry);
|
|
1086
|
-
modifiedChainIds.add(chainId);
|
|
1087
|
-
}
|
|
1088
|
-
catch (error) {
|
|
1089
|
-
console.error('Failed to add NFT contract', tokenAddress, error);
|
|
1090
|
-
}
|
|
1015
|
+
const { configuration: { chainId }, } = this.messenger.call('NetworkController:getNetworkClientById', networkClientId);
|
|
1016
|
+
const nftContracts = allNftContracts[userAddress]?.[chainId] || [];
|
|
1017
|
+
const existingEntry = nftContracts.find((nftContract) => nftContract.address.toLowerCase() ===
|
|
1018
|
+
checksumHexAddress.toLowerCase());
|
|
1019
|
+
if (existingEntry) {
|
|
1020
|
+
return nftContracts;
|
|
1091
1021
|
}
|
|
1092
|
-
//
|
|
1093
|
-
|
|
1094
|
-
|
|
1022
|
+
// this doesn't work currently for detection if the user switches networks while the detection is processing
|
|
1023
|
+
// will be fixed once detection uses networkClientIds
|
|
1024
|
+
// get name and symbol if ERC721 then put together the metadata
|
|
1025
|
+
const contractInformation = await __classPrivateFieldGet(this, _NftController_instances, "m", _NftController_getNftContractInformation).call(this, checksumHexAddress, nftMetadata, networkClientId);
|
|
1026
|
+
const { asset_contract_type, created_date, symbol, description, external_link, schema_name, collection: { name, image_url, tokenCount }, } = contractInformation;
|
|
1027
|
+
// If the nft is auto-detected we want some valid metadata to be present
|
|
1028
|
+
if (source === constants_1.Source.Detected &&
|
|
1029
|
+
'address' in contractInformation &&
|
|
1030
|
+
typeof contractInformation.address === 'string' &&
|
|
1031
|
+
'collection' in contractInformation &&
|
|
1032
|
+
contractInformation.collection.name === null &&
|
|
1033
|
+
'image_url' in contractInformation.collection &&
|
|
1034
|
+
contractInformation.collection.image_url === null &&
|
|
1035
|
+
Object.entries(contractInformation).every(([key, value]) => {
|
|
1036
|
+
return key === 'address' || key === 'collection' || !value;
|
|
1037
|
+
})) {
|
|
1038
|
+
return nftContracts;
|
|
1095
1039
|
}
|
|
1096
|
-
|
|
1040
|
+
/* istanbul ignore next */
|
|
1041
|
+
const newEntry = Object.assign({}, { address: checksumHexAddress }, description && { description }, name && { name }, image_url && { logo: image_url }, symbol && { symbol }, tokenCount !== null &&
|
|
1042
|
+
typeof tokenCount !== 'undefined' && { totalSupply: tokenCount }, asset_contract_type && { assetContractType: asset_contract_type }, created_date && { createdDate: created_date }, schema_name && { schemaName: schema_name }, external_link && { externalLink: external_link });
|
|
1043
|
+
const newNftContracts = [...nftContracts, newEntry];
|
|
1044
|
+
__classPrivateFieldGet(this, _NftController_instances, "m", _NftController_updateNestedNftState).call(this, newNftContracts, ALL_NFTS_CONTRACTS_STATE_KEY, {
|
|
1045
|
+
chainId,
|
|
1046
|
+
userAddress,
|
|
1047
|
+
});
|
|
1048
|
+
return newNftContracts;
|
|
1097
1049
|
}
|
|
1098
1050
|
finally {
|
|
1099
1051
|
releaseLock();
|