@exodus/assets-feature 8.1.2 → 8.2.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 +12 -0
- package/api/index.js +1 -0
- package/module/assets-module.js +79 -23
- package/module/utils.js +23 -0
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
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
|
+
## [8.2.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/assets-feature@8.1.3...@exodus/assets-feature@8.2.0) (2025-08-07)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- feat(assets-feature): add fetch tokens method (#13362)
|
|
11
|
+
|
|
12
|
+
## [8.1.3](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/assets-feature@8.1.2...@exodus/assets-feature@8.1.3) (2025-07-02)
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
- fix: remove gradientCoords (#13023)
|
|
17
|
+
|
|
6
18
|
## [8.1.2](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/assets-feature@8.1.1...@exodus/assets-feature@8.1.2) (2025-05-30)
|
|
7
19
|
|
|
8
20
|
**Note:** Version bump only for package @exodus/assets-feature
|
package/api/index.js
CHANGED
|
@@ -12,6 +12,7 @@ const createAssetsApi = ({ assetPreferences, assetsModule }) => {
|
|
|
12
12
|
},
|
|
13
13
|
assets: {
|
|
14
14
|
fetchToken: (...args) => assetsModule.fetchToken(...args),
|
|
15
|
+
fetchTokens: (...args) => assetsModule.fetchTokens(...args),
|
|
15
16
|
searchTokens: (...args) => assetsModule.searchTokens(...args),
|
|
16
17
|
updateTokens: (...args) => assetsModule.updateTokens(...args),
|
|
17
18
|
addTokens: (...args) => assetsModule.addTokens(...args),
|
package/module/assets-module.js
CHANGED
|
@@ -14,7 +14,12 @@ import {
|
|
|
14
14
|
CT_TIMESTAMP_KEY,
|
|
15
15
|
CT_UPDATE_INTERVAL,
|
|
16
16
|
} from './constants.js'
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
filterBuiltInProps,
|
|
19
|
+
getAssetFromAssetId,
|
|
20
|
+
getFetchErrorMessage,
|
|
21
|
+
isDisabledCustomToken,
|
|
22
|
+
} from './utils.js'
|
|
18
23
|
import createFetchival from '@exodus/fetch/create-fetchival'
|
|
19
24
|
import { validateCustomToken, isValidCustomToken } from '@exodus/asset-schema-validation'
|
|
20
25
|
import makeConcurrent from 'make-concurrent'
|
|
@@ -22,26 +27,6 @@ import oldToNewStyleTokenNames from '@exodus/asset-legacy-token-name-mapping'
|
|
|
22
27
|
|
|
23
28
|
const { get, isEmpty, once, uniq } = lodash
|
|
24
29
|
|
|
25
|
-
const FILTERED_FIELDS = [
|
|
26
|
-
'assetId',
|
|
27
|
-
'baseAssetName',
|
|
28
|
-
'displayName',
|
|
29
|
-
'displayTicker',
|
|
30
|
-
'gradientColors',
|
|
31
|
-
'gradientCoords',
|
|
32
|
-
'icon', // there is no icon field in built in assets, but there may be for custom tokens (TODO?)
|
|
33
|
-
'isBuiltIn',
|
|
34
|
-
'isCustomToken',
|
|
35
|
-
'lifecycleStatus',
|
|
36
|
-
'name',
|
|
37
|
-
'primaryColor',
|
|
38
|
-
'properName',
|
|
39
|
-
'properTicker',
|
|
40
|
-
'ticker',
|
|
41
|
-
]
|
|
42
|
-
|
|
43
|
-
const filterBuiltInProps = (asset) => ({ ...pick(asset, FILTERED_FIELDS), assetName: asset.name })
|
|
44
|
-
|
|
45
30
|
const getFetchCacheKey = (baseAssetName, assetId) => `${assetId}-${baseAssetName}`
|
|
46
31
|
|
|
47
32
|
const _isDisabledCustomToken = (token) => token.lifecycleStatus === STATUS.DISABLED
|
|
@@ -251,6 +236,75 @@ export class AssetsModule {
|
|
|
251
236
|
return this.#getCache(key)
|
|
252
237
|
}
|
|
253
238
|
|
|
239
|
+
#fetchTokens = async (assetDescriptors) => {
|
|
240
|
+
for (const { baseAssetName } of assetDescriptors) {
|
|
241
|
+
this.#assertSupportsCustomTokens(baseAssetName)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const [builtInDescriptors, customTokensDescriptors] = partition(
|
|
245
|
+
assetDescriptors,
|
|
246
|
+
({ assetId, baseAssetName }) => !!this.#getAssetFromAssetId(assetId, baseAssetName)
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
const getBuiltInDefinitions = (descriptors) =>
|
|
250
|
+
descriptors.map(({ assetId, baseAssetName }) =>
|
|
251
|
+
filterBuiltInProps(this.#getAssetFromAssetId(assetId, baseAssetName))
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
const getCustomTokensDefinitions = async (descriptors) => {
|
|
255
|
+
const _tokens = await this.#fetch(
|
|
256
|
+
`tokens`,
|
|
257
|
+
{ assetIds: descriptors, lifecycleStatus: ['c', 'v', 'u'] },
|
|
258
|
+
'tokens'
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
if (this.#shouldValidateCustomToken) {
|
|
262
|
+
for (const token of _tokens) {
|
|
263
|
+
try {
|
|
264
|
+
validateCustomToken(token)
|
|
265
|
+
} catch (e) {
|
|
266
|
+
this.#logger.warn(
|
|
267
|
+
`Token did not pass validation ${token.baseAssetName} ${token.assetId}. Error: ${e.message}`
|
|
268
|
+
)
|
|
269
|
+
throw new Error('Token did not pass validation')
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const tokens = _tokens.map((token) => normalizeToken(token))
|
|
275
|
+
|
|
276
|
+
try {
|
|
277
|
+
await this.#iconsStorage.storeIcons(tokens)
|
|
278
|
+
} catch (err) {
|
|
279
|
+
this.#logger.warn(`An error occurred while decoding icons`, err.message)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
for (const token of tokens) {
|
|
283
|
+
const key = getFetchCacheKey(token.baseAssetName, token.assetId)
|
|
284
|
+
this.#setCache(key, token)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return tokens
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const builtInTokens = getBuiltInDefinitions(builtInDescriptors)
|
|
291
|
+
const customTokens = await getCustomTokensDefinitions(customTokensDescriptors)
|
|
292
|
+
|
|
293
|
+
return { builtInTokens, customTokens }
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
fetchTokens = async (assetIds) => {
|
|
297
|
+
const { builtInTokens, customTokens } = await this.#fetchTokens(assetIds)
|
|
298
|
+
|
|
299
|
+
const builtInAssets = builtInTokens.map(({ name }) => this.getAsset(name))
|
|
300
|
+
const customTokenAssets = customTokens.map((definition) => {
|
|
301
|
+
const baseAsset = this.getAsset(definition.baseAssetName)
|
|
302
|
+
return baseAsset.api.createToken(definition)
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
return [...builtInAssets, ...customTokenAssets]
|
|
306
|
+
}
|
|
307
|
+
|
|
254
308
|
addToken = async (assetId, baseAssetName) => {
|
|
255
309
|
this.#assertCustomTokensStorageSupported()
|
|
256
310
|
this.#assertSupportsCustomTokens(baseAssetName)
|
|
@@ -329,8 +383,9 @@ export class AssetsModule {
|
|
|
329
383
|
: []
|
|
330
384
|
|
|
331
385
|
const validTokens = fetchedTokens.filter(this.#isValidCustomToken).map(normalizeToken)
|
|
332
|
-
if (validTokens.length !== fetchedTokens.length)
|
|
386
|
+
if (validTokens.length !== fetchedTokens.length) {
|
|
333
387
|
this.#logger.warn('Invalid Custom Token schema')
|
|
388
|
+
}
|
|
334
389
|
|
|
335
390
|
const tokens = tokenNamesToUpdate.map((tokenName) => assets[tokenName])
|
|
336
391
|
|
|
@@ -472,8 +527,9 @@ export class AssetsModule {
|
|
|
472
527
|
`${endpoint}${testDataParam}`
|
|
473
528
|
).post(body)
|
|
474
529
|
|
|
475
|
-
if (res.status !== 'OK')
|
|
530
|
+
if (res.status !== 'OK') {
|
|
476
531
|
throw new Error(`Custom tokens registry ${endpoint} ${res.status} ${res.message}`)
|
|
532
|
+
}
|
|
477
533
|
|
|
478
534
|
return get(res, resultPath)
|
|
479
535
|
} catch (error) {
|
package/module/utils.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CT_STATUS as STATUS } from '@exodus/assets'
|
|
2
|
+
import { pick } from '@exodus/basic-utils'
|
|
2
3
|
import lodash from 'lodash'
|
|
3
4
|
import assert from 'minimalistic-assert'
|
|
4
5
|
|
|
@@ -44,3 +45,25 @@ export async function getFetchErrorMessage(error) {
|
|
|
44
45
|
return defaultExtraMessage
|
|
45
46
|
}
|
|
46
47
|
}
|
|
48
|
+
|
|
49
|
+
const FILTERED_FIELDS = [
|
|
50
|
+
'assetId',
|
|
51
|
+
'baseAssetName',
|
|
52
|
+
'displayName',
|
|
53
|
+
'displayTicker',
|
|
54
|
+
'gradientColors',
|
|
55
|
+
'icon', // there is no icon field in built in assets, but there may be for custom tokens (TODO?)
|
|
56
|
+
'isBuiltIn',
|
|
57
|
+
'isCustomToken',
|
|
58
|
+
'lifecycleStatus',
|
|
59
|
+
'name',
|
|
60
|
+
'primaryColor',
|
|
61
|
+
'properName',
|
|
62
|
+
'properTicker',
|
|
63
|
+
'ticker',
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
export const filterBuiltInProps = (asset) => ({
|
|
67
|
+
...pick(asset, FILTERED_FIELDS),
|
|
68
|
+
assetName: asset.name,
|
|
69
|
+
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/assets-feature",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.2.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "This Exodus SDK feature provides access to instances of all blockchain asset adapters supported by the wallet, and enables you to search for and add custom tokens at runtime.",
|
|
6
6
|
"type": "module",
|
|
@@ -52,13 +52,14 @@
|
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@exodus/available-assets": "^8.7.0",
|
|
55
|
+
"@exodus/bip39": "^1.0.3",
|
|
55
56
|
"@exodus/bip44-constants": "^195.0.0",
|
|
56
57
|
"@exodus/bitcoin-meta": "^2.0.0",
|
|
57
58
|
"@exodus/bitcoin-plugin": "^1.29.1",
|
|
58
59
|
"@exodus/bitcoinregtest-plugin": "^1.11.0",
|
|
59
60
|
"@exodus/bitcointestnet-plugin": "^1.13.1",
|
|
60
|
-
"@exodus/blockchain-metadata": "^15.
|
|
61
|
-
"@exodus/cardano-lib": "^
|
|
61
|
+
"@exodus/blockchain-metadata": "^15.14.0",
|
|
62
|
+
"@exodus/cardano-lib": "^3.4.1",
|
|
62
63
|
"@exodus/combined-assets-meta": "^3.0.0",
|
|
63
64
|
"@exodus/cosmos-plugin": "^1.3.3",
|
|
64
65
|
"@exodus/ethereum-lib": "^5.0.0",
|
|
@@ -67,14 +68,13 @@
|
|
|
67
68
|
"@exodus/fusion-local": "^2.1.0",
|
|
68
69
|
"@exodus/keychain": "^7.3.0",
|
|
69
70
|
"@exodus/logger": "^1.2.3",
|
|
70
|
-
"@exodus/models": "^12.
|
|
71
|
+
"@exodus/models": "^12.15.0",
|
|
71
72
|
"@exodus/osmosis-plugin": "^1.3.3",
|
|
72
|
-
"@exodus/public-key-provider": "^4.
|
|
73
|
+
"@exodus/public-key-provider": "^4.2.0",
|
|
73
74
|
"@exodus/redux-dependency-injection": "^4.1.1",
|
|
74
|
-
"@exodus/storage-memory": "^2.
|
|
75
|
-
"@exodus/wallet-accounts": "^17.
|
|
75
|
+
"@exodus/storage-memory": "^2.3.0",
|
|
76
|
+
"@exodus/wallet-accounts": "^17.6.2",
|
|
76
77
|
"@exodus/wild-emitter": "^1.0.0",
|
|
77
|
-
"bip39": "^3.1.0",
|
|
78
78
|
"events": "^3.3.0",
|
|
79
79
|
"msw": "^2.0.0",
|
|
80
80
|
"redux": "^4.0.0"
|
|
@@ -82,5 +82,5 @@
|
|
|
82
82
|
"publishConfig": {
|
|
83
83
|
"access": "public"
|
|
84
84
|
},
|
|
85
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "fb7a01b2e840d775c17311f1bc4e87f465a98816"
|
|
86
86
|
}
|