@metamask/assets-controllers 30.0.0 → 31.0.0
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 +81 -1
- package/dist/AccountTrackerController.js +2 -2
- package/dist/AccountTrackerController.mjs +1 -1
- package/dist/AssetsContractController.js +2 -2
- package/dist/AssetsContractController.mjs +1 -1
- package/dist/NftController.js +2 -2
- package/dist/NftController.mjs +3 -3
- package/dist/NftDetectionController.js +2 -2
- package/dist/NftDetectionController.mjs +1 -1
- package/dist/TokenBalancesController.js +2 -2
- package/dist/TokenBalancesController.mjs +1 -1
- package/dist/TokenListController.js +3 -3
- package/dist/TokenListController.mjs +2 -2
- package/dist/TokenRatesController.js +2 -2
- package/dist/TokenRatesController.mjs +1 -1
- package/dist/TokensController.js +3 -3
- package/dist/TokensController.mjs +2 -2
- package/dist/chunk-4AC3X2U5.js +771 -0
- package/dist/chunk-4AC3X2U5.js.map +1 -0
- package/dist/chunk-543CC74T.mjs +253 -0
- package/dist/chunk-543CC74T.mjs.map +1 -0
- package/dist/{chunk-Z3OQU4XW.mjs → chunk-5W5OO2Q5.mjs} +2 -2
- package/dist/chunk-5W5OO2Q5.mjs.map +1 -0
- package/dist/chunk-62T7RKU3.mjs +1265 -0
- package/dist/chunk-62T7RKU3.mjs.map +1 -0
- package/dist/{chunk-PAJTKWEC.mjs → chunk-65PB33TE.mjs} +1 -1
- package/dist/chunk-65PB33TE.mjs.map +1 -0
- package/dist/{chunk-7MMEHAKG.mjs → chunk-73F3SN5O.mjs} +332 -265
- package/dist/chunk-73F3SN5O.mjs.map +1 -0
- package/dist/{chunk-XHMM35YT.mjs → chunk-A2DDWXMS.mjs} +2 -2
- package/dist/chunk-CGLUTXI7.js +1265 -0
- package/dist/chunk-CGLUTXI7.js.map +1 -0
- package/dist/{chunk-X4FFNQHE.mjs → chunk-E4ECCGJV.mjs} +1 -1
- package/dist/chunk-E4ECCGJV.mjs.map +1 -0
- package/dist/{chunk-V4ZO3F2S.js → chunk-GU53EI7A.js} +1 -1
- package/dist/chunk-GU53EI7A.js.map +1 -0
- package/dist/{chunk-MHN7CJCZ.mjs → chunk-HLCGZGPA.mjs} +1 -1
- package/dist/chunk-HLCGZGPA.mjs.map +1 -0
- package/dist/{chunk-LD4GC7OR.js → chunk-IBK6AXPP.js} +8 -9
- package/dist/chunk-IBK6AXPP.js.map +1 -0
- package/dist/{chunk-5F5EQAX5.js → chunk-JUI3XNEF.js} +3 -3
- package/dist/{chunk-3R43XIIX.js → chunk-PYMUBJQX.js} +2 -2
- package/dist/chunk-PYMUBJQX.js.map +1 -0
- package/dist/chunk-QFDTOEYR.js +253 -0
- package/dist/chunk-QFDTOEYR.js.map +1 -0
- package/dist/{chunk-4ODKGWYQ.js → chunk-QHWKLZUC.js} +1 -1
- package/dist/chunk-QHWKLZUC.js.map +1 -0
- package/dist/{chunk-6W5EQ3JQ.js → chunk-UEDNQBJN.js} +1 -1
- package/dist/chunk-UEDNQBJN.js.map +1 -0
- package/dist/{chunk-4LY47RPI.mjs → chunk-WCCLSUOI.mjs} +8 -9
- package/dist/{chunk-4LY47RPI.mjs.map → chunk-WCCLSUOI.mjs.map} +1 -1
- package/dist/index.js +10 -12
- package/dist/index.mjs +11 -13
- package/dist/token-service.js +2 -2
- package/dist/token-service.mjs +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/AccountTrackerController.d.ts +1 -1
- package/dist/types/AccountTrackerController.d.ts.map +1 -1
- package/dist/types/AssetsContractController.d.ts +1 -1
- package/dist/types/AssetsContractController.d.ts.map +1 -1
- package/dist/types/NftController.d.ts +65 -184
- package/dist/types/NftController.d.ts.map +1 -1
- package/dist/types/NftDetectionController.d.ts +34 -75
- package/dist/types/NftDetectionController.d.ts.map +1 -1
- package/dist/types/TokenRatesController.d.ts +6 -6
- package/dist/types/TokenRatesController.d.ts.map +1 -1
- package/dist/types/TokensController.d.ts +27 -131
- package/dist/types/TokensController.d.ts.map +1 -1
- package/dist/types/index.d.ts +5 -3
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +12 -12
- package/dist/chunk-3R43XIIX.js.map +0 -1
- package/dist/chunk-46UZDIXW.mjs +0 -1205
- package/dist/chunk-46UZDIXW.mjs.map +0 -1
- package/dist/chunk-4ODKGWYQ.js.map +0 -1
- package/dist/chunk-6W5EQ3JQ.js.map +0 -1
- package/dist/chunk-7MMEHAKG.mjs.map +0 -1
- package/dist/chunk-FMZML3V5.js +0 -237
- package/dist/chunk-FMZML3V5.js.map +0 -1
- package/dist/chunk-KOKB6U4Z.mjs +0 -237
- package/dist/chunk-KOKB6U4Z.mjs.map +0 -1
- package/dist/chunk-LAU6ZDZR.js +0 -1205
- package/dist/chunk-LAU6ZDZR.js.map +0 -1
- package/dist/chunk-LD4GC7OR.js.map +0 -1
- package/dist/chunk-MBCN3MNX.js +0 -704
- package/dist/chunk-MBCN3MNX.js.map +0 -1
- package/dist/chunk-MHN7CJCZ.mjs.map +0 -1
- package/dist/chunk-PAJTKWEC.mjs.map +0 -1
- package/dist/chunk-V4ZO3F2S.js.map +0 -1
- package/dist/chunk-X4FFNQHE.mjs.map +0 -1
- package/dist/chunk-Z3OQU4XW.mjs.map +0 -1
- /package/dist/{chunk-XHMM35YT.mjs.map → chunk-A2DDWXMS.mjs.map} +0 -0
- /package/dist/{chunk-5F5EQAX5.js.map → chunk-JUI3XNEF.js.map} +0 -0
package/dist/chunk-MBCN3MNX.js
DELETED
|
@@ -1,704 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
2
|
-
|
|
3
|
-
var _chunkB5YY22QQjs = require('./chunk-B5YY22QQ.js');
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
var _chunkBOTVAG4Ajs = require('./chunk-BOTVAG4A.js');
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
var _chunk3R43XIIXjs = require('./chunk-3R43XIIX.js');
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
var _chunkNEXY7SE2js = require('./chunk-NEXY7SE2.js');
|
|
15
|
-
|
|
16
|
-
// src/TokensController.ts
|
|
17
|
-
var _contracts = require('@ethersproject/contracts');
|
|
18
|
-
var _providers = require('@ethersproject/providers');
|
|
19
|
-
var _basecontroller = require('@metamask/base-controller');
|
|
20
|
-
var _contractmetadata = require('@metamask/contract-metadata'); var _contractmetadata2 = _interopRequireDefault(_contractmetadata);
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
var _controllerutils = require('@metamask/controller-utils');
|
|
32
|
-
var _metamaskethabis = require('@metamask/metamask-eth-abis');
|
|
33
|
-
var _rpcerrors = require('@metamask/rpc-errors');
|
|
34
|
-
var _asyncmutex = require('async-mutex');
|
|
35
|
-
var _events = require('events');
|
|
36
|
-
var _uuid = require('uuid');
|
|
37
|
-
var controllerName = "TokensController";
|
|
38
|
-
var getDefaultTokensState = () => {
|
|
39
|
-
return {
|
|
40
|
-
tokens: [],
|
|
41
|
-
ignoredTokens: [],
|
|
42
|
-
detectedTokens: [],
|
|
43
|
-
allTokens: {},
|
|
44
|
-
allIgnoredTokens: {},
|
|
45
|
-
allDetectedTokens: {}
|
|
46
|
-
};
|
|
47
|
-
};
|
|
48
|
-
var TokensController = class extends _basecontroller.BaseControllerV1 {
|
|
49
|
-
/**
|
|
50
|
-
* Creates a TokensController instance.
|
|
51
|
-
*
|
|
52
|
-
* @param options - The controller options.
|
|
53
|
-
* @param options.chainId - The chain ID of the current network.
|
|
54
|
-
* @param options.config - Initial options used to configure this controller.
|
|
55
|
-
* @param options.state - Initial state to set on this controller.
|
|
56
|
-
* @param options.messenger - The controller messenger.
|
|
57
|
-
*/
|
|
58
|
-
constructor({
|
|
59
|
-
chainId: initialChainId,
|
|
60
|
-
config,
|
|
61
|
-
state,
|
|
62
|
-
messenger
|
|
63
|
-
}) {
|
|
64
|
-
super(config, state);
|
|
65
|
-
this.mutex = new (0, _asyncmutex.Mutex)();
|
|
66
|
-
/**
|
|
67
|
-
* EventEmitter instance used to listen to specific EIP747 events
|
|
68
|
-
*/
|
|
69
|
-
this.hub = new (0, _events.EventEmitter)();
|
|
70
|
-
/**
|
|
71
|
-
* Name of this controller used during composition
|
|
72
|
-
*/
|
|
73
|
-
this.name = "TokensController";
|
|
74
|
-
this.defaultConfig = {
|
|
75
|
-
selectedAddress: "",
|
|
76
|
-
chainId: initialChainId,
|
|
77
|
-
provider: void 0,
|
|
78
|
-
...config
|
|
79
|
-
};
|
|
80
|
-
this.defaultState = {
|
|
81
|
-
...getDefaultTokensState(),
|
|
82
|
-
...state
|
|
83
|
-
};
|
|
84
|
-
this.initialize();
|
|
85
|
-
this.abortController = new AbortController();
|
|
86
|
-
this.messagingSystem = messenger;
|
|
87
|
-
this.messagingSystem.registerActionHandler(
|
|
88
|
-
`${controllerName}:addDetectedTokens`,
|
|
89
|
-
this.addDetectedTokens.bind(this)
|
|
90
|
-
);
|
|
91
|
-
this.messagingSystem.subscribe(
|
|
92
|
-
"PreferencesController:stateChange",
|
|
93
|
-
({ selectedAddress }) => {
|
|
94
|
-
const { allTokens, allIgnoredTokens, allDetectedTokens } = this.state;
|
|
95
|
-
const { chainId } = this.config;
|
|
96
|
-
this.configure({ selectedAddress });
|
|
97
|
-
this.update({
|
|
98
|
-
tokens: allTokens[chainId]?.[selectedAddress] ?? [],
|
|
99
|
-
ignoredTokens: allIgnoredTokens[chainId]?.[selectedAddress] ?? [],
|
|
100
|
-
detectedTokens: allDetectedTokens[chainId]?.[selectedAddress] ?? []
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
);
|
|
104
|
-
this.messagingSystem.subscribe(
|
|
105
|
-
"NetworkController:networkDidChange",
|
|
106
|
-
({ providerConfig }) => {
|
|
107
|
-
const { allTokens, allIgnoredTokens, allDetectedTokens } = this.state;
|
|
108
|
-
const { selectedAddress } = this.config;
|
|
109
|
-
const { chainId } = providerConfig;
|
|
110
|
-
this.abortController.abort();
|
|
111
|
-
this.abortController = new AbortController();
|
|
112
|
-
this.configure({ chainId });
|
|
113
|
-
this.update({
|
|
114
|
-
tokens: allTokens[chainId]?.[selectedAddress] || [],
|
|
115
|
-
ignoredTokens: allIgnoredTokens[chainId]?.[selectedAddress] || [],
|
|
116
|
-
detectedTokens: allDetectedTokens[chainId]?.[selectedAddress] || []
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
);
|
|
120
|
-
this.messagingSystem.subscribe(
|
|
121
|
-
"TokenListController:stateChange",
|
|
122
|
-
({ tokenList }) => {
|
|
123
|
-
const { tokens } = this.state;
|
|
124
|
-
if (tokens.length && !tokens[0].name) {
|
|
125
|
-
this.updateTokensAttribute(tokenList, "name");
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Fetch metadata for a token.
|
|
132
|
-
*
|
|
133
|
-
* @param tokenAddress - The address of the token.
|
|
134
|
-
* @returns The token metadata.
|
|
135
|
-
*/
|
|
136
|
-
async fetchTokenMetadata(tokenAddress) {
|
|
137
|
-
try {
|
|
138
|
-
const token = await _chunk3R43XIIXjs.fetchTokenMetadata.call(void 0,
|
|
139
|
-
this.config.chainId,
|
|
140
|
-
tokenAddress,
|
|
141
|
-
this.abortController.signal
|
|
142
|
-
);
|
|
143
|
-
return token;
|
|
144
|
-
} catch (error) {
|
|
145
|
-
if (error instanceof Error && error.message.includes(_chunk3R43XIIXjs.TOKEN_METADATA_NO_SUPPORT_ERROR)) {
|
|
146
|
-
return void 0;
|
|
147
|
-
}
|
|
148
|
-
throw error;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Adds a token to the stored token list.
|
|
153
|
-
*
|
|
154
|
-
* @param options - The method argument object.
|
|
155
|
-
* @param options.address - Hex address of the token contract.
|
|
156
|
-
* @param options.symbol - Symbol of the token.
|
|
157
|
-
* @param options.decimals - Number of decimals the token uses.
|
|
158
|
-
* @param options.name - Name of the token.
|
|
159
|
-
* @param options.image - Image of the token.
|
|
160
|
-
* @param options.interactingAddress - The address of the account to add a token to.
|
|
161
|
-
* @param options.networkClientId - Network Client ID.
|
|
162
|
-
* @returns Current token list.
|
|
163
|
-
*/
|
|
164
|
-
async addToken({
|
|
165
|
-
address,
|
|
166
|
-
symbol,
|
|
167
|
-
decimals,
|
|
168
|
-
name,
|
|
169
|
-
image,
|
|
170
|
-
interactingAddress,
|
|
171
|
-
networkClientId
|
|
172
|
-
}) {
|
|
173
|
-
const { chainId, selectedAddress } = this.config;
|
|
174
|
-
const releaseLock = await this.mutex.acquire();
|
|
175
|
-
const { allTokens, allIgnoredTokens, allDetectedTokens } = this.state;
|
|
176
|
-
let currentChainId = chainId;
|
|
177
|
-
if (networkClientId) {
|
|
178
|
-
currentChainId = this.messagingSystem.call(
|
|
179
|
-
"NetworkController:getNetworkClientById",
|
|
180
|
-
networkClientId
|
|
181
|
-
).configuration.chainId;
|
|
182
|
-
}
|
|
183
|
-
const accountAddress = interactingAddress || selectedAddress;
|
|
184
|
-
const isInteractingWithWalletAccount = accountAddress === selectedAddress;
|
|
185
|
-
try {
|
|
186
|
-
address = _controllerutils.toChecksumHexAddress.call(void 0, address);
|
|
187
|
-
const tokens = allTokens[currentChainId]?.[accountAddress] || [];
|
|
188
|
-
const ignoredTokens = allIgnoredTokens[currentChainId]?.[accountAddress] || [];
|
|
189
|
-
const detectedTokens = allDetectedTokens[currentChainId]?.[accountAddress] || [];
|
|
190
|
-
const newTokens = [...tokens];
|
|
191
|
-
const [isERC721, tokenMetadata] = await Promise.all([
|
|
192
|
-
this._detectIsERC721(address, networkClientId),
|
|
193
|
-
// TODO parameterize the token metadata fetch by networkClientId
|
|
194
|
-
this.fetchTokenMetadata(address)
|
|
195
|
-
]);
|
|
196
|
-
if (!networkClientId && currentChainId !== this.config.chainId) {
|
|
197
|
-
throw new Error(
|
|
198
|
-
"TokensController Error: Switched networks while adding token"
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
const newEntry = {
|
|
202
|
-
address,
|
|
203
|
-
symbol,
|
|
204
|
-
decimals,
|
|
205
|
-
image: image || _chunkNEXY7SE2js.formatIconUrlWithProxy.call(void 0, {
|
|
206
|
-
chainId: currentChainId,
|
|
207
|
-
tokenAddress: address
|
|
208
|
-
}),
|
|
209
|
-
isERC721,
|
|
210
|
-
aggregators: _chunkNEXY7SE2js.formatAggregatorNames.call(void 0, tokenMetadata?.aggregators || []),
|
|
211
|
-
name
|
|
212
|
-
};
|
|
213
|
-
const previousIndex = newTokens.findIndex(
|
|
214
|
-
(token) => token.address.toLowerCase() === address.toLowerCase()
|
|
215
|
-
);
|
|
216
|
-
if (previousIndex !== -1) {
|
|
217
|
-
newTokens[previousIndex] = newEntry;
|
|
218
|
-
} else {
|
|
219
|
-
newTokens.push(newEntry);
|
|
220
|
-
}
|
|
221
|
-
const newIgnoredTokens = ignoredTokens.filter(
|
|
222
|
-
(tokenAddress) => tokenAddress.toLowerCase() !== address.toLowerCase()
|
|
223
|
-
);
|
|
224
|
-
const newDetectedTokens = detectedTokens.filter(
|
|
225
|
-
(token) => token.address.toLowerCase() !== address.toLowerCase()
|
|
226
|
-
);
|
|
227
|
-
const { newAllTokens, newAllIgnoredTokens, newAllDetectedTokens } = this._getNewAllTokensState({
|
|
228
|
-
newTokens,
|
|
229
|
-
newIgnoredTokens,
|
|
230
|
-
newDetectedTokens,
|
|
231
|
-
interactingAddress: accountAddress,
|
|
232
|
-
interactingChainId: currentChainId
|
|
233
|
-
});
|
|
234
|
-
let newState = {
|
|
235
|
-
allTokens: newAllTokens,
|
|
236
|
-
allIgnoredTokens: newAllIgnoredTokens,
|
|
237
|
-
allDetectedTokens: newAllDetectedTokens
|
|
238
|
-
};
|
|
239
|
-
if (isInteractingWithWalletAccount) {
|
|
240
|
-
newState = {
|
|
241
|
-
...newState,
|
|
242
|
-
tokens: newTokens,
|
|
243
|
-
ignoredTokens: newIgnoredTokens,
|
|
244
|
-
detectedTokens: newDetectedTokens
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
this.update(newState);
|
|
248
|
-
return newTokens;
|
|
249
|
-
} finally {
|
|
250
|
-
releaseLock();
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* Add a batch of tokens.
|
|
255
|
-
*
|
|
256
|
-
* @param tokensToImport - Array of tokens to import.
|
|
257
|
-
* @param networkClientId - Optional network client ID used to determine interacting chain ID.
|
|
258
|
-
*/
|
|
259
|
-
async addTokens(tokensToImport, networkClientId) {
|
|
260
|
-
const releaseLock = await this.mutex.acquire();
|
|
261
|
-
const { tokens, detectedTokens, ignoredTokens } = this.state;
|
|
262
|
-
const importedTokensMap = {};
|
|
263
|
-
const newTokensMap = tokens.reduce((output, current) => {
|
|
264
|
-
output[current.address] = current;
|
|
265
|
-
return output;
|
|
266
|
-
}, {});
|
|
267
|
-
try {
|
|
268
|
-
tokensToImport.forEach((tokenToAdd) => {
|
|
269
|
-
const { address, symbol, decimals, image, aggregators, name } = tokenToAdd;
|
|
270
|
-
const checksumAddress = _controllerutils.toChecksumHexAddress.call(void 0, address);
|
|
271
|
-
const formattedToken = {
|
|
272
|
-
address: checksumAddress,
|
|
273
|
-
symbol,
|
|
274
|
-
decimals,
|
|
275
|
-
image,
|
|
276
|
-
aggregators,
|
|
277
|
-
name
|
|
278
|
-
};
|
|
279
|
-
newTokensMap[address] = formattedToken;
|
|
280
|
-
importedTokensMap[address.toLowerCase()] = true;
|
|
281
|
-
return formattedToken;
|
|
282
|
-
});
|
|
283
|
-
const newTokens = Object.values(newTokensMap);
|
|
284
|
-
const newDetectedTokens = detectedTokens.filter(
|
|
285
|
-
(token) => !importedTokensMap[token.address.toLowerCase()]
|
|
286
|
-
);
|
|
287
|
-
const newIgnoredTokens = ignoredTokens.filter(
|
|
288
|
-
(tokenAddress) => !newTokensMap[tokenAddress.toLowerCase()]
|
|
289
|
-
);
|
|
290
|
-
let interactingChainId;
|
|
291
|
-
if (networkClientId) {
|
|
292
|
-
interactingChainId = this.messagingSystem.call(
|
|
293
|
-
"NetworkController:getNetworkClientById",
|
|
294
|
-
networkClientId
|
|
295
|
-
).configuration.chainId;
|
|
296
|
-
}
|
|
297
|
-
const { newAllTokens, newAllDetectedTokens, newAllIgnoredTokens } = this._getNewAllTokensState({
|
|
298
|
-
newTokens,
|
|
299
|
-
newDetectedTokens,
|
|
300
|
-
newIgnoredTokens,
|
|
301
|
-
interactingChainId
|
|
302
|
-
});
|
|
303
|
-
this.update({
|
|
304
|
-
tokens: newTokens,
|
|
305
|
-
allTokens: newAllTokens,
|
|
306
|
-
detectedTokens: newDetectedTokens,
|
|
307
|
-
allDetectedTokens: newAllDetectedTokens,
|
|
308
|
-
ignoredTokens: newIgnoredTokens,
|
|
309
|
-
allIgnoredTokens: newAllIgnoredTokens
|
|
310
|
-
});
|
|
311
|
-
} finally {
|
|
312
|
-
releaseLock();
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
/**
|
|
316
|
-
* Ignore a batch of tokens.
|
|
317
|
-
*
|
|
318
|
-
* @param tokenAddressesToIgnore - Array of token addresses to ignore.
|
|
319
|
-
*/
|
|
320
|
-
ignoreTokens(tokenAddressesToIgnore) {
|
|
321
|
-
const { ignoredTokens, detectedTokens, tokens } = this.state;
|
|
322
|
-
const ignoredTokensMap = {};
|
|
323
|
-
let newIgnoredTokens = [...ignoredTokens];
|
|
324
|
-
const checksummedTokenAddresses = tokenAddressesToIgnore.map((address) => {
|
|
325
|
-
const checksumAddress = _controllerutils.toChecksumHexAddress.call(void 0, address);
|
|
326
|
-
ignoredTokensMap[address.toLowerCase()] = true;
|
|
327
|
-
return checksumAddress;
|
|
328
|
-
});
|
|
329
|
-
newIgnoredTokens = [...ignoredTokens, ...checksummedTokenAddresses];
|
|
330
|
-
const newDetectedTokens = detectedTokens.filter(
|
|
331
|
-
(token) => !ignoredTokensMap[token.address.toLowerCase()]
|
|
332
|
-
);
|
|
333
|
-
const newTokens = tokens.filter(
|
|
334
|
-
(token) => !ignoredTokensMap[token.address.toLowerCase()]
|
|
335
|
-
);
|
|
336
|
-
const { newAllIgnoredTokens, newAllDetectedTokens, newAllTokens } = this._getNewAllTokensState({
|
|
337
|
-
newIgnoredTokens,
|
|
338
|
-
newDetectedTokens,
|
|
339
|
-
newTokens
|
|
340
|
-
});
|
|
341
|
-
this.update({
|
|
342
|
-
ignoredTokens: newIgnoredTokens,
|
|
343
|
-
tokens: newTokens,
|
|
344
|
-
detectedTokens: newDetectedTokens,
|
|
345
|
-
allIgnoredTokens: newAllIgnoredTokens,
|
|
346
|
-
allDetectedTokens: newAllDetectedTokens,
|
|
347
|
-
allTokens: newAllTokens
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* Adds a batch of detected tokens to the stored token list.
|
|
352
|
-
*
|
|
353
|
-
* @param incomingDetectedTokens - Array of detected tokens to be added or updated.
|
|
354
|
-
* @param detectionDetails - An object containing the chain ID and address of the currently selected network on which the incomingDetectedTokens were detected.
|
|
355
|
-
* @param detectionDetails.selectedAddress - the account address on which the incomingDetectedTokens were detected.
|
|
356
|
-
* @param detectionDetails.chainId - the chainId on which the incomingDetectedTokens were detected.
|
|
357
|
-
*/
|
|
358
|
-
async addDetectedTokens(incomingDetectedTokens, detectionDetails) {
|
|
359
|
-
const releaseLock = await this.mutex.acquire();
|
|
360
|
-
const chainId = detectionDetails?.chainId ?? this.config.chainId;
|
|
361
|
-
const accountAddress = detectionDetails?.selectedAddress ?? this.config.selectedAddress;
|
|
362
|
-
const { allTokens, allDetectedTokens, allIgnoredTokens } = this.state;
|
|
363
|
-
let newTokens = [...allTokens?.[chainId]?.[accountAddress] ?? []];
|
|
364
|
-
let newDetectedTokens = [
|
|
365
|
-
...allDetectedTokens?.[chainId]?.[accountAddress] ?? []
|
|
366
|
-
];
|
|
367
|
-
try {
|
|
368
|
-
incomingDetectedTokens.forEach((tokenToAdd) => {
|
|
369
|
-
const {
|
|
370
|
-
address,
|
|
371
|
-
symbol,
|
|
372
|
-
decimals,
|
|
373
|
-
image,
|
|
374
|
-
aggregators,
|
|
375
|
-
isERC721,
|
|
376
|
-
name
|
|
377
|
-
} = tokenToAdd;
|
|
378
|
-
const checksumAddress = _controllerutils.toChecksumHexAddress.call(void 0, address);
|
|
379
|
-
const newEntry = {
|
|
380
|
-
address: checksumAddress,
|
|
381
|
-
symbol,
|
|
382
|
-
decimals,
|
|
383
|
-
image,
|
|
384
|
-
isERC721,
|
|
385
|
-
aggregators,
|
|
386
|
-
name
|
|
387
|
-
};
|
|
388
|
-
const previousImportedIndex = newTokens.findIndex(
|
|
389
|
-
(token) => token.address.toLowerCase() === checksumAddress.toLowerCase()
|
|
390
|
-
);
|
|
391
|
-
if (previousImportedIndex !== -1) {
|
|
392
|
-
newTokens[previousImportedIndex] = newEntry;
|
|
393
|
-
} else {
|
|
394
|
-
const ignoredTokenIndex = allIgnoredTokens?.[chainId]?.[accountAddress]?.indexOf(address) ?? -1;
|
|
395
|
-
if (ignoredTokenIndex === -1) {
|
|
396
|
-
const previousDetectedIndex = newDetectedTokens.findIndex(
|
|
397
|
-
(token) => token.address.toLowerCase() === checksumAddress.toLowerCase()
|
|
398
|
-
);
|
|
399
|
-
if (previousDetectedIndex !== -1) {
|
|
400
|
-
newDetectedTokens[previousDetectedIndex] = newEntry;
|
|
401
|
-
} else {
|
|
402
|
-
newDetectedTokens.push(newEntry);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
});
|
|
407
|
-
const { newAllTokens, newAllDetectedTokens } = this._getNewAllTokensState(
|
|
408
|
-
{
|
|
409
|
-
newTokens,
|
|
410
|
-
newDetectedTokens,
|
|
411
|
-
interactingAddress: accountAddress,
|
|
412
|
-
interactingChainId: chainId
|
|
413
|
-
}
|
|
414
|
-
);
|
|
415
|
-
const { chainId: currentChain, selectedAddress: currentAddress } = this.config;
|
|
416
|
-
newTokens = newAllTokens?.[currentChain]?.[currentAddress] || [];
|
|
417
|
-
newDetectedTokens = newAllDetectedTokens?.[currentChain]?.[currentAddress] || [];
|
|
418
|
-
this.update({
|
|
419
|
-
tokens: newTokens,
|
|
420
|
-
allTokens: newAllTokens,
|
|
421
|
-
detectedTokens: newDetectedTokens,
|
|
422
|
-
allDetectedTokens: newAllDetectedTokens
|
|
423
|
-
});
|
|
424
|
-
} finally {
|
|
425
|
-
releaseLock();
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Adds isERC721 field to token object. This is called when a user attempts to add tokens that
|
|
430
|
-
* were previously added which do not yet had isERC721 field.
|
|
431
|
-
*
|
|
432
|
-
* @param tokenAddress - The contract address of the token requiring the isERC721 field added.
|
|
433
|
-
* @returns The new token object with the added isERC721 field.
|
|
434
|
-
*/
|
|
435
|
-
async updateTokenType(tokenAddress) {
|
|
436
|
-
const isERC721 = await this._detectIsERC721(tokenAddress);
|
|
437
|
-
const { tokens } = this.state;
|
|
438
|
-
const tokenIndex = tokens.findIndex((token) => {
|
|
439
|
-
return token.address.toLowerCase() === tokenAddress.toLowerCase();
|
|
440
|
-
});
|
|
441
|
-
tokens[tokenIndex].isERC721 = isERC721;
|
|
442
|
-
this.update({ tokens });
|
|
443
|
-
return tokens[tokenIndex];
|
|
444
|
-
}
|
|
445
|
-
/**
|
|
446
|
-
* This is a function that updates the tokens name for the tokens name if it is not defined.
|
|
447
|
-
*
|
|
448
|
-
* @param tokenList - Represents the fetched token list from service API
|
|
449
|
-
* @param tokenAttribute - Represents the token attribute that we want to update on the token list
|
|
450
|
-
*/
|
|
451
|
-
updateTokensAttribute(tokenList, tokenAttribute) {
|
|
452
|
-
const { tokens } = this.state;
|
|
453
|
-
const newTokens = tokens.map((token) => {
|
|
454
|
-
const newToken = tokenList[token.address.toLowerCase()];
|
|
455
|
-
return !token[tokenAttribute] && newToken?.[tokenAttribute] ? { ...token, [tokenAttribute]: newToken[tokenAttribute] } : { ...token };
|
|
456
|
-
});
|
|
457
|
-
this.update({ tokens: newTokens });
|
|
458
|
-
}
|
|
459
|
-
/**
|
|
460
|
-
* Detects whether or not a token is ERC-721 compatible.
|
|
461
|
-
*
|
|
462
|
-
* @param tokenAddress - The token contract address.
|
|
463
|
-
* @param networkClientId - Optional network client ID to fetch contract info with.
|
|
464
|
-
* @returns A boolean indicating whether the token address passed in supports the EIP-721
|
|
465
|
-
* interface.
|
|
466
|
-
*/
|
|
467
|
-
async _detectIsERC721(tokenAddress, networkClientId) {
|
|
468
|
-
const checksumAddress = _controllerutils.toChecksumHexAddress.call(void 0, tokenAddress);
|
|
469
|
-
if (_contractmetadata2.default[checksumAddress]?.erc721 === true) {
|
|
470
|
-
return Promise.resolve(true);
|
|
471
|
-
} else if (_contractmetadata2.default[checksumAddress]?.erc20 === true) {
|
|
472
|
-
return Promise.resolve(false);
|
|
473
|
-
}
|
|
474
|
-
const tokenContract = this._createEthersContract(
|
|
475
|
-
tokenAddress,
|
|
476
|
-
_metamaskethabis.abiERC721,
|
|
477
|
-
networkClientId
|
|
478
|
-
);
|
|
479
|
-
try {
|
|
480
|
-
return await tokenContract.supportsInterface(_controllerutils.ERC721_INTERFACE_ID);
|
|
481
|
-
} catch (error) {
|
|
482
|
-
return false;
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
_getProvider(networkClientId) {
|
|
486
|
-
return new (0, _providers.Web3Provider)(
|
|
487
|
-
// @ts-expect-error TODO: remove this annotation once the `Eip1193Provider` class is released
|
|
488
|
-
networkClientId ? this.messagingSystem.call(
|
|
489
|
-
"NetworkController:getNetworkClientById",
|
|
490
|
-
networkClientId
|
|
491
|
-
).provider : this.config.provider
|
|
492
|
-
);
|
|
493
|
-
}
|
|
494
|
-
_createEthersContract(tokenAddress, abi, networkClientId) {
|
|
495
|
-
const web3provider = this._getProvider(networkClientId);
|
|
496
|
-
const tokenContract = new (0, _contracts.Contract)(tokenAddress, abi, web3provider);
|
|
497
|
-
return tokenContract;
|
|
498
|
-
}
|
|
499
|
-
_generateRandomId() {
|
|
500
|
-
return _uuid.v1.call(void 0, );
|
|
501
|
-
}
|
|
502
|
-
/**
|
|
503
|
-
* Adds a new suggestedAsset to the list of watched assets.
|
|
504
|
-
* Parameters will be validated according to the asset type being watched.
|
|
505
|
-
*
|
|
506
|
-
* @param options - The method options.
|
|
507
|
-
* @param options.asset - The asset to be watched. For now only ERC20 tokens are accepted.
|
|
508
|
-
* @param options.type - The asset type.
|
|
509
|
-
* @param options.interactingAddress - The address of the account that is requesting to watch the asset.
|
|
510
|
-
* @param options.networkClientId - Network Client ID.
|
|
511
|
-
* @returns A promise that resolves if the asset was watched successfully, and rejects otherwise.
|
|
512
|
-
*/
|
|
513
|
-
async watchAsset({
|
|
514
|
-
asset,
|
|
515
|
-
type,
|
|
516
|
-
interactingAddress,
|
|
517
|
-
networkClientId
|
|
518
|
-
}) {
|
|
519
|
-
if (type !== _controllerutils.ERC20) {
|
|
520
|
-
throw new Error(`Asset of type ${type} not supported`);
|
|
521
|
-
}
|
|
522
|
-
if (!asset.address) {
|
|
523
|
-
throw _rpcerrors.rpcErrors.invalidParams("Address must be specified");
|
|
524
|
-
}
|
|
525
|
-
if (!_controllerutils.isValidHexAddress.call(void 0, asset.address)) {
|
|
526
|
-
throw _rpcerrors.rpcErrors.invalidParams(`Invalid address "${asset.address}"`);
|
|
527
|
-
}
|
|
528
|
-
if (await this._detectIsERC721(asset.address, networkClientId)) {
|
|
529
|
-
throw _rpcerrors.rpcErrors.invalidParams(
|
|
530
|
-
`Contract ${asset.address} must match type ${type}, but was detected as ${_controllerutils.ERC721}`
|
|
531
|
-
);
|
|
532
|
-
}
|
|
533
|
-
const provider = this._getProvider(networkClientId);
|
|
534
|
-
const isErc1155 = await _controllerutils.safelyExecute.call(void 0,
|
|
535
|
-
() => new (0, _chunkBOTVAG4Ajs.ERC1155Standard)(provider).contractSupportsBase1155Interface(
|
|
536
|
-
asset.address
|
|
537
|
-
)
|
|
538
|
-
);
|
|
539
|
-
if (isErc1155) {
|
|
540
|
-
throw _rpcerrors.rpcErrors.invalidParams(
|
|
541
|
-
`Contract ${asset.address} must match type ${type}, but was detected as ${_controllerutils.ERC1155}`
|
|
542
|
-
);
|
|
543
|
-
}
|
|
544
|
-
const erc20 = new (0, _chunkB5YY22QQjs.ERC20Standard)(provider);
|
|
545
|
-
const [contractName, contractSymbol, contractDecimals] = await Promise.all([
|
|
546
|
-
_controllerutils.safelyExecute.call(void 0, () => erc20.getTokenName(asset.address)),
|
|
547
|
-
_controllerutils.safelyExecute.call(void 0, () => erc20.getTokenSymbol(asset.address)),
|
|
548
|
-
_controllerutils.safelyExecute.call(void 0, async () => erc20.getTokenDecimals(asset.address))
|
|
549
|
-
]);
|
|
550
|
-
asset.name = contractName;
|
|
551
|
-
if (!asset.symbol && !contractSymbol) {
|
|
552
|
-
throw _rpcerrors.rpcErrors.invalidParams(
|
|
553
|
-
"A symbol is required, but was not found in either the request or contract"
|
|
554
|
-
);
|
|
555
|
-
}
|
|
556
|
-
if (contractSymbol !== void 0 && asset.symbol !== void 0 && asset.symbol.toUpperCase() !== contractSymbol.toUpperCase()) {
|
|
557
|
-
throw _rpcerrors.rpcErrors.invalidParams(
|
|
558
|
-
`The symbol in the request (${asset.symbol}) does not match the symbol in the contract (${contractSymbol})`
|
|
559
|
-
);
|
|
560
|
-
}
|
|
561
|
-
asset.symbol = contractSymbol ?? asset.symbol;
|
|
562
|
-
if (typeof asset.symbol !== "string") {
|
|
563
|
-
throw _rpcerrors.rpcErrors.invalidParams(`Invalid symbol: not a string`);
|
|
564
|
-
}
|
|
565
|
-
if (asset.symbol.length > 11) {
|
|
566
|
-
throw _rpcerrors.rpcErrors.invalidParams(
|
|
567
|
-
`Invalid symbol "${asset.symbol}": longer than 11 characters`
|
|
568
|
-
);
|
|
569
|
-
}
|
|
570
|
-
if (asset.decimals === void 0 && contractDecimals === void 0) {
|
|
571
|
-
throw _rpcerrors.rpcErrors.invalidParams(
|
|
572
|
-
"Decimals are required, but were not found in either the request or contract"
|
|
573
|
-
);
|
|
574
|
-
}
|
|
575
|
-
if (contractDecimals !== void 0 && asset.decimals !== void 0 && String(asset.decimals) !== contractDecimals) {
|
|
576
|
-
throw _rpcerrors.rpcErrors.invalidParams(
|
|
577
|
-
`The decimals in the request (${asset.decimals}) do not match the decimals in the contract (${contractDecimals})`
|
|
578
|
-
);
|
|
579
|
-
}
|
|
580
|
-
const decimalsStr = contractDecimals ?? asset.decimals;
|
|
581
|
-
const decimalsNum = parseInt(decimalsStr, 10);
|
|
582
|
-
if (!Number.isInteger(decimalsNum) || decimalsNum > 36 || decimalsNum < 0) {
|
|
583
|
-
throw _rpcerrors.rpcErrors.invalidParams(
|
|
584
|
-
`Invalid decimals "${decimalsStr}": must be an integer 0 <= 36`
|
|
585
|
-
);
|
|
586
|
-
}
|
|
587
|
-
asset.decimals = decimalsNum;
|
|
588
|
-
const suggestedAssetMeta = {
|
|
589
|
-
asset,
|
|
590
|
-
id: this._generateRandomId(),
|
|
591
|
-
time: Date.now(),
|
|
592
|
-
type,
|
|
593
|
-
interactingAddress: interactingAddress || this.config.selectedAddress
|
|
594
|
-
};
|
|
595
|
-
await this._requestApproval(suggestedAssetMeta);
|
|
596
|
-
const { address, symbol, decimals, name, image } = asset;
|
|
597
|
-
await this.addToken({
|
|
598
|
-
address,
|
|
599
|
-
symbol,
|
|
600
|
-
decimals,
|
|
601
|
-
name,
|
|
602
|
-
image,
|
|
603
|
-
interactingAddress: suggestedAssetMeta.interactingAddress,
|
|
604
|
-
networkClientId
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
|
-
/**
|
|
608
|
-
* Takes a new tokens and ignoredTokens array for the current network/account combination
|
|
609
|
-
* and returns new allTokens and allIgnoredTokens state to update to.
|
|
610
|
-
*
|
|
611
|
-
* @param params - Object that holds token params.
|
|
612
|
-
* @param params.newTokens - The new tokens to set for the current network and selected account.
|
|
613
|
-
* @param params.newIgnoredTokens - The new ignored tokens to set for the current network and selected account.
|
|
614
|
-
* @param params.newDetectedTokens - The new detected tokens to set for the current network and selected account.
|
|
615
|
-
* @param params.interactingAddress - The account address to use to store the tokens.
|
|
616
|
-
* @param params.interactingChainId - The chainId to use to store the tokens.
|
|
617
|
-
* @returns The updated `allTokens` and `allIgnoredTokens` state.
|
|
618
|
-
*/
|
|
619
|
-
_getNewAllTokensState(params) {
|
|
620
|
-
const {
|
|
621
|
-
newTokens,
|
|
622
|
-
newIgnoredTokens,
|
|
623
|
-
newDetectedTokens,
|
|
624
|
-
interactingAddress,
|
|
625
|
-
interactingChainId
|
|
626
|
-
} = params;
|
|
627
|
-
const { allTokens, allIgnoredTokens, allDetectedTokens } = this.state;
|
|
628
|
-
const { chainId, selectedAddress } = this.config;
|
|
629
|
-
const userAddressToAddTokens = interactingAddress ?? selectedAddress;
|
|
630
|
-
const chainIdToAddTokens = interactingChainId ?? chainId;
|
|
631
|
-
let newAllTokens = allTokens;
|
|
632
|
-
if (newTokens?.length || newTokens && allTokens && allTokens[chainIdToAddTokens] && allTokens[chainIdToAddTokens][userAddressToAddTokens]) {
|
|
633
|
-
const networkTokens = allTokens[chainIdToAddTokens];
|
|
634
|
-
const newNetworkTokens = {
|
|
635
|
-
...networkTokens,
|
|
636
|
-
...{ [userAddressToAddTokens]: newTokens }
|
|
637
|
-
};
|
|
638
|
-
newAllTokens = {
|
|
639
|
-
...allTokens,
|
|
640
|
-
...{ [chainIdToAddTokens]: newNetworkTokens }
|
|
641
|
-
};
|
|
642
|
-
}
|
|
643
|
-
let newAllIgnoredTokens = allIgnoredTokens;
|
|
644
|
-
if (newIgnoredTokens?.length || newIgnoredTokens && allIgnoredTokens && allIgnoredTokens[chainIdToAddTokens] && allIgnoredTokens[chainIdToAddTokens][userAddressToAddTokens]) {
|
|
645
|
-
const networkIgnoredTokens = allIgnoredTokens[chainIdToAddTokens];
|
|
646
|
-
const newIgnoredNetworkTokens = {
|
|
647
|
-
...networkIgnoredTokens,
|
|
648
|
-
...{ [userAddressToAddTokens]: newIgnoredTokens }
|
|
649
|
-
};
|
|
650
|
-
newAllIgnoredTokens = {
|
|
651
|
-
...allIgnoredTokens,
|
|
652
|
-
...{ [chainIdToAddTokens]: newIgnoredNetworkTokens }
|
|
653
|
-
};
|
|
654
|
-
}
|
|
655
|
-
let newAllDetectedTokens = allDetectedTokens;
|
|
656
|
-
if (newDetectedTokens?.length || newDetectedTokens && allDetectedTokens && allDetectedTokens[chainIdToAddTokens] && allDetectedTokens[chainIdToAddTokens][userAddressToAddTokens]) {
|
|
657
|
-
const networkDetectedTokens = allDetectedTokens[chainIdToAddTokens];
|
|
658
|
-
const newDetectedNetworkTokens = {
|
|
659
|
-
...networkDetectedTokens,
|
|
660
|
-
...{ [userAddressToAddTokens]: newDetectedTokens }
|
|
661
|
-
};
|
|
662
|
-
newAllDetectedTokens = {
|
|
663
|
-
...allDetectedTokens,
|
|
664
|
-
...{ [chainIdToAddTokens]: newDetectedNetworkTokens }
|
|
665
|
-
};
|
|
666
|
-
}
|
|
667
|
-
return { newAllTokens, newAllIgnoredTokens, newAllDetectedTokens };
|
|
668
|
-
}
|
|
669
|
-
/**
|
|
670
|
-
* Removes all tokens from the ignored list.
|
|
671
|
-
*/
|
|
672
|
-
clearIgnoredTokens() {
|
|
673
|
-
this.update({ ignoredTokens: [], allIgnoredTokens: {} });
|
|
674
|
-
}
|
|
675
|
-
async _requestApproval(suggestedAssetMeta) {
|
|
676
|
-
return this.messagingSystem.call(
|
|
677
|
-
"ApprovalController:addRequest",
|
|
678
|
-
{
|
|
679
|
-
id: suggestedAssetMeta.id,
|
|
680
|
-
origin: _controllerutils.ORIGIN_METAMASK,
|
|
681
|
-
type: _controllerutils.ApprovalType.WatchAsset,
|
|
682
|
-
requestData: {
|
|
683
|
-
id: suggestedAssetMeta.id,
|
|
684
|
-
interactingAddress: suggestedAssetMeta.interactingAddress,
|
|
685
|
-
asset: {
|
|
686
|
-
address: suggestedAssetMeta.asset.address,
|
|
687
|
-
decimals: suggestedAssetMeta.asset.decimals,
|
|
688
|
-
symbol: suggestedAssetMeta.asset.symbol,
|
|
689
|
-
image: suggestedAssetMeta.asset.image || null
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
},
|
|
693
|
-
true
|
|
694
|
-
);
|
|
695
|
-
}
|
|
696
|
-
};
|
|
697
|
-
var TokensController_default = TokensController;
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
exports.getDefaultTokensState = getDefaultTokensState; exports.TokensController = TokensController; exports.TokensController_default = TokensController_default;
|
|
704
|
-
//# sourceMappingURL=chunk-MBCN3MNX.js.map
|