@exodus/assets-feature 3.8.0 → 4.0.1
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 +14 -0
- package/index.js +0 -2
- package/module/assets-module.js +33 -25
- package/module/index.js +2 -0
- package/package.json +5 -5
- package/plugin/index.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [4.0.1](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/assets-feature@4.0.0...@exodus/assets-feature@4.0.1) (2023-12-13)
|
|
7
|
+
|
|
8
|
+
- refactor: cache CTR request failures (https://github.com/ExodusMovement/exodus-hydra/pull/4975)
|
|
9
|
+
|
|
10
|
+
## [4.0.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/assets-feature@3.8.0...@exodus/assets-feature@4.0.0) (2023-11-23)
|
|
11
|
+
|
|
12
|
+
### ⚠ BREAKING CHANGES
|
|
13
|
+
|
|
14
|
+
- remove legacy asset events (#4826)
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
- remove legacy asset events ([#4826](https://github.com/ExodusMovement/exodus-hydra/issues/4826)) ([6f27e5f](https://github.com/ExodusMovement/exodus-hydra/commit/6f27e5fa2294cb82db2651069eba4964b37f8e5e))
|
|
19
|
+
|
|
6
20
|
## [3.8.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/assets-feature@3.7.0...@exodus/assets-feature@3.8.0) (2023-11-21)
|
|
7
21
|
|
|
8
22
|
### Features
|
package/index.js
CHANGED
|
@@ -33,12 +33,10 @@ const assets = ({ config = {} } = {}) => {
|
|
|
33
33
|
{
|
|
34
34
|
definition: assetModuleDefinition,
|
|
35
35
|
// storage: { namespace: 'customTokens' },
|
|
36
|
-
writesAtoms: ['assetsAtom'],
|
|
37
36
|
aliases: [{ implementationId: 'customTokensStorage', interfaceId: 'storage' }],
|
|
38
37
|
},
|
|
39
38
|
{
|
|
40
39
|
definition: assetPreferencesDefinition,
|
|
41
|
-
writesAtoms: ['multiAddressModeAtom', 'disabledPurposesAtom'],
|
|
42
40
|
},
|
|
43
41
|
{ definition: customTokensMonitorDefinition },
|
|
44
42
|
],
|
package/module/assets-module.js
CHANGED
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
CT_UPDATEABLE_PROPERTIES,
|
|
7
7
|
} from '@exodus/assets'
|
|
8
8
|
import { mapValues, pick, pickBy } from '@exodus/basic-utils'
|
|
9
|
-
import ExodusModule from '@exodus/module'
|
|
10
9
|
// eslint-disable-next-line @exodus/restricted-imports/prefer-basic-utils
|
|
11
10
|
import { get, isEmpty, keyBy, once } from 'lodash'
|
|
12
11
|
import assert from 'minimalistic-assert'
|
|
@@ -70,7 +69,7 @@ const initialAssetRegistry = {
|
|
|
70
69
|
},
|
|
71
70
|
}
|
|
72
71
|
|
|
73
|
-
export class AssetsModule
|
|
72
|
+
export class AssetsModule {
|
|
74
73
|
#registry
|
|
75
74
|
#storage
|
|
76
75
|
#fetchCache
|
|
@@ -88,6 +87,7 @@ export class AssetsModule extends ExodusModule {
|
|
|
88
87
|
#isExternalRegistry
|
|
89
88
|
#assetsAtom
|
|
90
89
|
#fetchival
|
|
90
|
+
#logger
|
|
91
91
|
|
|
92
92
|
constructor({
|
|
93
93
|
storage,
|
|
@@ -99,9 +99,8 @@ export class AssetsModule extends ExodusModule {
|
|
|
99
99
|
validateCustomToken = () => true,
|
|
100
100
|
config = {},
|
|
101
101
|
fetch,
|
|
102
|
+
logger,
|
|
102
103
|
}) {
|
|
103
|
-
super({ name: 'AssetsModule' })
|
|
104
|
-
|
|
105
104
|
this.#assetsAtom = assetsAtom
|
|
106
105
|
this.#storage = storage
|
|
107
106
|
this.#isExternalRegistry = !!assetRegistry
|
|
@@ -119,6 +118,7 @@ export class AssetsModule extends ExodusModule {
|
|
|
119
118
|
this.#customTokenUpdateInterval = config.customTokenUpdateInterval || CT_UPDATE_INTERVAL
|
|
120
119
|
this.#fetchCacheExpiry = config.fetchCacheExpiry ?? CT_FETCH_CACHE_EXPIRY
|
|
121
120
|
this.#fetchival = createFetchival({ fetch })
|
|
121
|
+
this.#logger = logger
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
#setRegistry = (registry) => {
|
|
@@ -176,8 +176,6 @@ export class AssetsModule extends ExodusModule {
|
|
|
176
176
|
getBaseAssetNames = () => this.#getAssetNamesBy((asset) => asset.baseAsset.name === asset.name)
|
|
177
177
|
|
|
178
178
|
load = once(async () => {
|
|
179
|
-
this.emit('assets-load', { importedTokens: {} })
|
|
180
|
-
|
|
181
179
|
try {
|
|
182
180
|
const storedTokens = await this.#readCustomTokens()
|
|
183
181
|
const tokens = pickBy(storedTokens, ({ baseAssetName }) => {
|
|
@@ -187,13 +185,13 @@ export class AssetsModule extends ExodusModule {
|
|
|
187
185
|
|
|
188
186
|
// tokens may be:
|
|
189
187
|
// 1. pure custom tokens from the CTR
|
|
190
|
-
// 2. built-in tokens previously from the CTR
|
|
188
|
+
// 2. built-in tokens previously from the CTR which may or may not be available
|
|
191
189
|
// 3. both of the above from a network that has feature flag customTokens === false
|
|
192
190
|
// It is OK to add all of these to the assets registry
|
|
193
191
|
const { added, updated } = this.#handleFetchedTokens(Object.values(tokens))
|
|
194
192
|
this.#flushChanges({ added, updated })
|
|
195
193
|
} catch (e) {
|
|
196
|
-
this.
|
|
194
|
+
this.#logger.log('error reading custom tokens from storage:', e)
|
|
197
195
|
}
|
|
198
196
|
})
|
|
199
197
|
|
|
@@ -210,12 +208,27 @@ export class AssetsModule extends ExodusModule {
|
|
|
210
208
|
|
|
211
209
|
const key = getFetchCacheKey(baseAssetName, assetId)
|
|
212
210
|
const cache = this.#getCache(key)
|
|
211
|
+
if (cache?.cachedError) throw cache.cachedError
|
|
213
212
|
if (cache) return cache
|
|
214
213
|
|
|
215
|
-
const
|
|
214
|
+
const fetchTokenAndCacheError = async () => {
|
|
215
|
+
try {
|
|
216
|
+
return await this.#fetch(`networks/${baseAssetName}`, { assetId }, 'token')
|
|
217
|
+
} catch (err) {
|
|
218
|
+
if (err.message !== 'Too Many Requests') {
|
|
219
|
+
this.#setCache(key, { cachedError: err })
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
throw err
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const _token = await fetchTokenAndCacheError()
|
|
216
227
|
if (!this.#validateCustomToken(_token)) {
|
|
217
|
-
this.
|
|
218
|
-
|
|
228
|
+
this.#logger.warn('Invalid Custom Token schema')
|
|
229
|
+
const err = new Error('Token did not pass validation')
|
|
230
|
+
this.#setCache(key, { cachedError: err })
|
|
231
|
+
throw err
|
|
219
232
|
}
|
|
220
233
|
|
|
221
234
|
const token = normalizeToken(_token)
|
|
@@ -223,7 +236,7 @@ export class AssetsModule extends ExodusModule {
|
|
|
223
236
|
try {
|
|
224
237
|
await this.#iconsStorage.storeIcons([token])
|
|
225
238
|
} catch (err) {
|
|
226
|
-
this.
|
|
239
|
+
this.#logger.warn(`An error occurred while decoding icon for ${assetId}`, err.message)
|
|
227
240
|
}
|
|
228
241
|
|
|
229
242
|
this.#setCache(key, token)
|
|
@@ -246,7 +259,7 @@ export class AssetsModule extends ExodusModule {
|
|
|
246
259
|
|
|
247
260
|
return asset
|
|
248
261
|
} catch (err) {
|
|
249
|
-
this.
|
|
262
|
+
this.#logger.warn(`Add custom token ${assetId} error on ${baseAssetName}`, err.message)
|
|
250
263
|
throw err
|
|
251
264
|
}
|
|
252
265
|
}
|
|
@@ -263,7 +276,7 @@ export class AssetsModule extends ExodusModule {
|
|
|
263
276
|
try {
|
|
264
277
|
return await this.fetchToken(assetId, baseAssetName)
|
|
265
278
|
} catch (err) {
|
|
266
|
-
this.
|
|
279
|
+
this.#logger.warn('fetch custom tokens error:', err.message)
|
|
267
280
|
}
|
|
268
281
|
})
|
|
269
282
|
)
|
|
@@ -306,7 +319,7 @@ export class AssetsModule extends ExodusModule {
|
|
|
306
319
|
if (isEmpty(tokens)) return
|
|
307
320
|
|
|
308
321
|
const validTokens = tokensToAdd.filter(this.#validateCustomToken).map(normalizeToken)
|
|
309
|
-
if (validTokens.length !== tokensToAdd.length) this.
|
|
322
|
+
if (validTokens.length !== tokensToAdd.length) this.#logger.warn('Invalid Custom Token schema')
|
|
310
323
|
|
|
311
324
|
const { fetchedAndHandledTokens, added, updated } = this.#handleFetchedTokens(validTokens)
|
|
312
325
|
|
|
@@ -368,7 +381,7 @@ export class AssetsModule extends ExodusModule {
|
|
|
368
381
|
)
|
|
369
382
|
const validTokens = tokens.filter(this.#validateCustomToken)
|
|
370
383
|
|
|
371
|
-
if (validTokens.length !== tokens.length) this.
|
|
384
|
+
if (validTokens.length !== tokens.length) this.#logger.warn('Invalid Custom Token schema')
|
|
372
385
|
|
|
373
386
|
return validTokens.map((token) => {
|
|
374
387
|
const asset = this.#getAssetFromAssetId(token.assetId, token.baseAssetName)
|
|
@@ -385,7 +398,7 @@ export class AssetsModule extends ExodusModule {
|
|
|
385
398
|
const updatedTokens = await this.#fetch('updates', assetVersions, 'tokens')
|
|
386
399
|
const validatedTokens = updatedTokens.filter(this.#validateCustomToken).map(normalizeToken)
|
|
387
400
|
if (validatedTokens.length !== updatedTokens.length) {
|
|
388
|
-
this.
|
|
401
|
+
this.#logger.warn('Invalid Custom Token schema')
|
|
389
402
|
}
|
|
390
403
|
|
|
391
404
|
await this.#iconsStorage.storeIcons(validatedTokens)
|
|
@@ -408,11 +421,6 @@ export class AssetsModule extends ExodusModule {
|
|
|
408
421
|
}
|
|
409
422
|
|
|
410
423
|
#flushChanges = ({ added = [], updated = [], disabled = [] } = {}) => {
|
|
411
|
-
// TODO: remove these once all consumers are refactored
|
|
412
|
-
if (added.length > 0) this.emit('assets-add', added)
|
|
413
|
-
if (updated.length > 0) this.emit('assets-update', updated)
|
|
414
|
-
if (disabled.length > 0) this.emit('assets-disable', disabled)
|
|
415
|
-
|
|
416
424
|
if (added.length + updated.length + disabled.length === 0) {
|
|
417
425
|
return
|
|
418
426
|
}
|
|
@@ -446,7 +454,7 @@ export class AssetsModule extends ExodusModule {
|
|
|
446
454
|
if (asset) return { asset, isAdded: false }
|
|
447
455
|
|
|
448
456
|
const { name } = this.#registry.addCustomToken(token) // add to `#/assets`
|
|
449
|
-
this.
|
|
457
|
+
this.#logger.log('Custom token added:', name)
|
|
450
458
|
return { asset: this.getAsset(name), isAdded: true }
|
|
451
459
|
}
|
|
452
460
|
|
|
@@ -464,7 +472,7 @@ export class AssetsModule extends ExodusModule {
|
|
|
464
472
|
updated.push(asset)
|
|
465
473
|
}
|
|
466
474
|
} catch (err) {
|
|
467
|
-
this.
|
|
475
|
+
this.#logger.warn('Handle fetched custom tokens error:', err.message)
|
|
468
476
|
}
|
|
469
477
|
}
|
|
470
478
|
|
|
@@ -475,7 +483,7 @@ export class AssetsModule extends ExodusModule {
|
|
|
475
483
|
const baseAsset = this.getAsset(baseAssetName)
|
|
476
484
|
if (!baseAsset.api.hasFeature('customTokens')) {
|
|
477
485
|
const reason = `BUG: network ${baseAsset.name} does not support custom tokens.`
|
|
478
|
-
this.
|
|
486
|
+
this.#logger.warn(reason)
|
|
479
487
|
throw new Error(reason)
|
|
480
488
|
}
|
|
481
489
|
}
|
package/module/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/assets-feature",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"description": "Assets module, clients and apis",
|
|
6
6
|
"main": "index.js",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@exodus/assets": "^8.0.95",
|
|
44
|
-
"@exodus/atoms": "^
|
|
45
|
-
"@exodus/available-assets": "^
|
|
44
|
+
"@exodus/atoms": "^7.0.0",
|
|
45
|
+
"@exodus/available-assets": "^8.0.0",
|
|
46
46
|
"@exodus/bitcoin-meta": "^1.0.1",
|
|
47
47
|
"@exodus/bitcoin-plugin": "^1.0.3",
|
|
48
48
|
"@exodus/bitcoinregtest-plugin": "^1.0.3",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@exodus/osmosis-plugin": "^1.0.0",
|
|
56
56
|
"@exodus/redux-dependency-injection": "^3.0.0",
|
|
57
57
|
"@exodus/storage-memory": "^2.1.1",
|
|
58
|
-
"@exodus/wallet-accounts": "^
|
|
58
|
+
"@exodus/wallet-accounts": "^15.0.0",
|
|
59
59
|
"@exodus/wild-emitter": "^1.0.0",
|
|
60
60
|
"eslint": "^8.44.0",
|
|
61
61
|
"events": "^3.3.0",
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"msw": "^2.0.0",
|
|
64
64
|
"redux": "^4.0.0"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "8a27fc57a2783ecc728030da8b3d2a10fa8f915c"
|
|
67
67
|
}
|