@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 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
  ],
@@ -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 extends ExodusModule {
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._logger.log('error reading custom tokens from storage:', e)
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 _token = await this.#fetch(`networks/${baseAssetName}`, { assetId }, 'token')
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._logger.warn('Invalid Custom Token schema')
218
- throw new Error('Token did not pass validation')
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._logger.warn(`An error occurred while decoding icon for ${assetId}`, err.message)
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._logger.warn(`Add custom token ${assetId} error on ${baseAssetName}`, err.message)
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._logger.warn('fetch custom tokens error:', err.message)
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._logger.warn('Invalid Custom Token schema')
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._logger.warn('Invalid Custom Token schema')
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._logger.warn('Invalid Custom Token schema')
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._logger.log('Custom token added:', name)
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._logger.warn('Handle fetched custom tokens error:', err.message)
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._logger.warn(reason)
486
+ this.#logger.warn(reason)
479
487
  throw new Error(reason)
480
488
  }
481
489
  }
package/module/index.js CHANGED
@@ -15,6 +15,8 @@ const assetsModuleDefinition = {
15
15
  'validateCustomToken?',
16
16
  'config',
17
17
  'fetch',
18
+ 'logger',
19
+ 'assetRegistry?', // temporary
18
20
  ],
19
21
  }
20
22
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/assets-feature",
3
- "version": "3.8.0",
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": "^6.0.1",
45
- "@exodus/available-assets": "^7.0.0",
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": "^14.2.0",
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": "4480f8501a837520fd19403ea1cffb1e3d7ac9d8"
66
+ "gitHead": "8a27fc57a2783ecc728030da8b3d2a10fa8f915c"
67
67
  }
package/plugin/index.js CHANGED
@@ -20,7 +20,6 @@ const createAssetsPlugin = ({
20
20
  }
21
21
 
22
22
  port.emit('assets', payload)
23
- port.emit('assets-load', payload) // legacy to be removed
24
23
  }
25
24
 
26
25
  const observers = [