@exodus/assets-feature 9.4.0 → 9.6.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/README.md +2 -0
- package/atoms/legacy-address-mode.js +15 -6
- package/atoms/taproot-address-mode.js +15 -6
- package/constants.js +1 -0
- package/index.js +8 -2
- package/module/asset-preferences.js +37 -16
- package/module/assets-module.js +15 -8
- package/module/dynamic-combined-assets.js +38 -13
- package/package.json +14 -14
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
|
+
## [9.6.0](https://github.com/ExodusMovement/exodus/compare/@exodus/assets-feature@9.5.0...@exodus/assets-feature@9.6.0) (2026-10-28)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- **assets-feature:** allow bitcoin testnet and regtest address modes ([#47982](https://github.com/ExodusMovement/exodus/issues/47982)) ([e242c66](https://github.com/ExodusMovement/exodus/commit/e242c6627965e7f1f78a44e1a4538752af16c51b))
|
|
11
|
+
|
|
12
|
+
## [9.5.0](https://github.com/ExodusMovement/exodus/compare/@exodus/assets-feature@9.4.0...@exodus/assets-feature@9.5.0) (2026-10-12)
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
- **assets:** configure dynamic combined asset overrides ([#46749](https://github.com/ExodusMovement/exodus/issues/46749)) ([582f204](https://github.com/ExodusMovement/exodus/commit/582f20416509431e63b2d5a47160e4ff6a5296d1))
|
|
17
|
+
|
|
6
18
|
## [9.4.0](https://github.com/ExodusMovement/exodus/compare/@exodus/assets-feature@9.3.3...@exodus/assets-feature@9.4.0) (2026-10-07)
|
|
7
19
|
|
|
8
20
|
### Features
|
package/README.md
CHANGED
|
@@ -40,6 +40,8 @@ See [api/index.d.ts](./api/index.d.ts) for more details on the API and token val
|
|
|
40
40
|
|
|
41
41
|
### API Side
|
|
42
42
|
|
|
43
|
+
`assetsModule.dynamicCombinedAssetOverrides` maps a token's asset name to the asset whose name and ticker should identify its dynamic combined group. For example, `{ cbbtc_basemainnet_58df8ab4: 'bitcoin' }` combines Base cbBTC with Bitcoin while preserving cbBTC's metadata and transaction identity. The target is the primary member; both assets must be loaded and eligible for dynamic grouping. Until the target is available and eligible, the token remains available individually and does not fall back to name/ticker grouping. Static grouping is unchanged.
|
|
44
|
+
|
|
43
45
|
See [using the sdk](../../docs/development/using-the-sdk.md#setup-the-api-side) for more details on how features plug into the SDK and the API interface in the [type declaration](./api/index.d.ts).
|
|
44
46
|
|
|
45
47
|
### UI Side
|
|
@@ -1,19 +1,28 @@
|
|
|
1
|
-
import { compute } from '@exodus/atoms'
|
|
1
|
+
import { combine, compute, createStorageAtomFactory } from '@exodus/atoms'
|
|
2
2
|
import { createFusionAtom } from '@exodus/fusion-atoms'
|
|
3
3
|
|
|
4
|
-
const createLegacyAddressModeAtom = ({ fusion }) => {
|
|
4
|
+
const createLegacyAddressModeAtom = ({ storage, fusion, logger }) => {
|
|
5
|
+
const storageAtom = createStorageAtomFactory({ storage, logger })({
|
|
6
|
+
key: 'legacyAddressMode',
|
|
7
|
+
defaultValue: {},
|
|
8
|
+
isSoleWriter: true,
|
|
9
|
+
})
|
|
10
|
+
|
|
5
11
|
const bitcoinFusionAtom = createFusionAtom({
|
|
6
12
|
fusion,
|
|
7
13
|
path: `bitcoinLegacyAddressEnabled`,
|
|
8
14
|
})
|
|
9
15
|
|
|
10
16
|
const computedAtom = compute({
|
|
11
|
-
atom: bitcoinFusionAtom,
|
|
12
|
-
selector: (bitcoin) => (bitcoin === undefined ?
|
|
17
|
+
atom: combine({ storage: storageAtom, bitcoin: bitcoinFusionAtom }),
|
|
18
|
+
selector: ({ storage, bitcoin }) => (bitcoin === undefined ? storage : { ...storage, bitcoin }),
|
|
13
19
|
})
|
|
14
20
|
|
|
15
21
|
const set = async (value) => {
|
|
16
|
-
const { bitcoin } =
|
|
22
|
+
const { bitcoin, ...rest } =
|
|
23
|
+
typeof value === 'function' ? value(await computedAtom.get()) : value
|
|
24
|
+
|
|
25
|
+
await storageAtom.set(rest)
|
|
17
26
|
|
|
18
27
|
const bitcoinPreviousValue = await bitcoinFusionAtom.get()
|
|
19
28
|
if (bitcoinPreviousValue !== bitcoin) {
|
|
@@ -28,7 +37,7 @@ const legacyAddressModeAtomDefinition = {
|
|
|
28
37
|
id: 'legacyAddressModeAtom',
|
|
29
38
|
type: 'atom',
|
|
30
39
|
factory: createLegacyAddressModeAtom,
|
|
31
|
-
dependencies: ['fusion'],
|
|
40
|
+
dependencies: ['storage', 'fusion', 'logger'],
|
|
32
41
|
public: true,
|
|
33
42
|
}
|
|
34
43
|
|
|
@@ -1,19 +1,28 @@
|
|
|
1
|
-
import { compute } from '@exodus/atoms'
|
|
1
|
+
import { combine, compute, createStorageAtomFactory } from '@exodus/atoms'
|
|
2
2
|
import { createFusionAtom } from '@exodus/fusion-atoms'
|
|
3
3
|
|
|
4
|
-
const createTaprootAddressModeAtom = ({ fusion }) => {
|
|
4
|
+
const createTaprootAddressModeAtom = ({ storage, fusion, logger }) => {
|
|
5
|
+
const storageAtom = createStorageAtomFactory({ storage, logger })({
|
|
6
|
+
key: 'taprootAddressMode',
|
|
7
|
+
defaultValue: {},
|
|
8
|
+
isSoleWriter: true,
|
|
9
|
+
})
|
|
10
|
+
|
|
5
11
|
const bitcoinFusionAtom = createFusionAtom({
|
|
6
12
|
fusion,
|
|
7
13
|
path: `bitcoinTaprootAddressEnabled`,
|
|
8
14
|
})
|
|
9
15
|
|
|
10
16
|
const computedAtom = compute({
|
|
11
|
-
atom: bitcoinFusionAtom,
|
|
12
|
-
selector: (bitcoin) => (bitcoin === undefined ?
|
|
17
|
+
atom: combine({ storage: storageAtom, bitcoin: bitcoinFusionAtom }),
|
|
18
|
+
selector: ({ storage, bitcoin }) => (bitcoin === undefined ? storage : { ...storage, bitcoin }),
|
|
13
19
|
})
|
|
14
20
|
|
|
15
21
|
const set = async (value) => {
|
|
16
|
-
const { bitcoin } =
|
|
22
|
+
const { bitcoin, ...rest } =
|
|
23
|
+
typeof value === 'function' ? value(await computedAtom.get()) : value
|
|
24
|
+
|
|
25
|
+
await storageAtom.set(rest)
|
|
17
26
|
|
|
18
27
|
const bitcoinPreviousValue = await bitcoinFusionAtom.get()
|
|
19
28
|
if (bitcoinPreviousValue !== bitcoin) {
|
|
@@ -28,7 +37,7 @@ const taprootAddressModeAtomDefinition = {
|
|
|
28
37
|
id: 'taprootAddressModeAtom',
|
|
29
38
|
type: 'atom',
|
|
30
39
|
factory: createTaprootAddressModeAtom,
|
|
31
|
-
dependencies: ['fusion'],
|
|
40
|
+
dependencies: ['storage', 'fusion', 'logger'],
|
|
32
41
|
public: true,
|
|
33
42
|
}
|
|
34
43
|
|
package/constants.js
CHANGED
package/index.js
CHANGED
|
@@ -40,8 +40,14 @@ const assets = (config = Object.create(null)) => {
|
|
|
40
40
|
storage: { namespace: 'assetPreferences' },
|
|
41
41
|
config: multiAddressMode,
|
|
42
42
|
},
|
|
43
|
-
{
|
|
44
|
-
|
|
43
|
+
{
|
|
44
|
+
definition: legacyAddressModeAtomDefinition,
|
|
45
|
+
storage: { namespace: 'assetPreferences' },
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
definition: taprootAddressModeAtomDefinition,
|
|
49
|
+
storage: { namespace: 'assetPreferences' },
|
|
50
|
+
},
|
|
45
51
|
{ definition: assetsAtomDefinition },
|
|
46
52
|
{
|
|
47
53
|
definition: disabledPurposesAtomDefinition,
|
|
@@ -1,24 +1,40 @@
|
|
|
1
1
|
import { omit } from '@exodus/basic-utils'
|
|
2
2
|
import assert from 'minimalistic-assert'
|
|
3
3
|
|
|
4
|
+
const supportsLegacyAddressMode = (asset) => asset?.useBip84 === true
|
|
5
|
+
const supportsTaprootAddressMode = (asset) => asset?.useBip86 === true
|
|
6
|
+
|
|
4
7
|
class AssetPreferences {
|
|
8
|
+
#assetsModule
|
|
5
9
|
#disabledPurposesAtom
|
|
6
10
|
#multiAddressModeAtom
|
|
7
11
|
#legacyAddressModeAtom
|
|
8
12
|
#taprootAddressModeAtom
|
|
9
13
|
|
|
10
14
|
constructor({
|
|
15
|
+
assetsModule,
|
|
11
16
|
disabledPurposesAtom,
|
|
12
17
|
multiAddressModeAtom,
|
|
13
18
|
legacyAddressModeAtom,
|
|
14
19
|
taprootAddressModeAtom,
|
|
15
20
|
}) {
|
|
21
|
+
this.#assetsModule = assetsModule
|
|
16
22
|
this.#disabledPurposesAtom = disabledPurposesAtom
|
|
17
23
|
this.#multiAddressModeAtom = multiAddressModeAtom
|
|
18
24
|
this.#legacyAddressModeAtom = legacyAddressModeAtom
|
|
19
25
|
this.#taprootAddressModeAtom = taprootAddressModeAtom
|
|
20
26
|
}
|
|
21
27
|
|
|
28
|
+
#assertAssetsSupport = ({ assetNames, method, isSupported }) => {
|
|
29
|
+
assert(assetNames.length > 0, `${method} requires at least one asset`)
|
|
30
|
+
for (const assetName of assetNames) {
|
|
31
|
+
assert(
|
|
32
|
+
isSupported(this.#assetsModule.getAsset(assetName)),
|
|
33
|
+
`${method} does not support ${assetName}`
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
22
38
|
enableMultiAddressMode = ({ assetNames }) =>
|
|
23
39
|
this.#multiAddressModeAtom.set((value) => ({
|
|
24
40
|
...value,
|
|
@@ -38,10 +54,11 @@ class AssetPreferences {
|
|
|
38
54
|
}))
|
|
39
55
|
|
|
40
56
|
enableLegacyAddressMode = async ({ assetNames }) => {
|
|
41
|
-
|
|
42
|
-
assetNames
|
|
43
|
-
'enableLegacyAddressMode
|
|
44
|
-
|
|
57
|
+
this.#assertAssetsSupport({
|
|
58
|
+
assetNames,
|
|
59
|
+
method: 'enableLegacyAddressMode',
|
|
60
|
+
isSupported: supportsLegacyAddressMode,
|
|
61
|
+
})
|
|
45
62
|
|
|
46
63
|
await this.#legacyAddressModeAtom.set((value) => ({
|
|
47
64
|
...value,
|
|
@@ -53,19 +70,21 @@ class AssetPreferences {
|
|
|
53
70
|
}
|
|
54
71
|
|
|
55
72
|
disableLegacyAddressMode = async ({ assetNames }) => {
|
|
56
|
-
|
|
57
|
-
assetNames
|
|
58
|
-
'disableLegacyAddressMode
|
|
59
|
-
|
|
73
|
+
this.#assertAssetsSupport({
|
|
74
|
+
assetNames,
|
|
75
|
+
method: 'disableLegacyAddressMode',
|
|
76
|
+
isSupported: supportsLegacyAddressMode,
|
|
77
|
+
})
|
|
60
78
|
|
|
61
79
|
await this.#legacyAddressModeAtom.set((value) => omit(value, assetNames))
|
|
62
80
|
}
|
|
63
81
|
|
|
64
82
|
enableTaprootAddressMode = async ({ assetNames }) => {
|
|
65
|
-
|
|
66
|
-
assetNames
|
|
67
|
-
'enableTaprootAddressMode
|
|
68
|
-
|
|
83
|
+
this.#assertAssetsSupport({
|
|
84
|
+
assetNames,
|
|
85
|
+
method: 'enableTaprootAddressMode',
|
|
86
|
+
isSupported: supportsTaprootAddressMode,
|
|
87
|
+
})
|
|
69
88
|
|
|
70
89
|
await this.#taprootAddressModeAtom.set((value) => ({
|
|
71
90
|
...value,
|
|
@@ -77,10 +96,11 @@ class AssetPreferences {
|
|
|
77
96
|
}
|
|
78
97
|
|
|
79
98
|
disableTaprootAddressMode = async ({ assetNames }) => {
|
|
80
|
-
|
|
81
|
-
assetNames
|
|
82
|
-
'disableTaprootAddressMode
|
|
83
|
-
|
|
99
|
+
this.#assertAssetsSupport({
|
|
100
|
+
assetNames,
|
|
101
|
+
method: 'disableTaprootAddressMode',
|
|
102
|
+
isSupported: supportsTaprootAddressMode,
|
|
103
|
+
})
|
|
84
104
|
|
|
85
105
|
await this.#taprootAddressModeAtom.set((value) => omit(value, assetNames))
|
|
86
106
|
}
|
|
@@ -115,6 +135,7 @@ const assetPreferencesDefinition = {
|
|
|
115
135
|
type: 'module',
|
|
116
136
|
factory: (opts) => new AssetPreferences(opts),
|
|
117
137
|
dependencies: [
|
|
138
|
+
'assetsModule',
|
|
118
139
|
'disabledPurposesAtom',
|
|
119
140
|
'multiAddressModeAtom',
|
|
120
141
|
'legacyAddressModeAtom',
|
package/module/assets-module.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
CT_STATUS as STATUS,
|
|
5
5
|
CT_UPDATEABLE_PROPERTIES,
|
|
6
6
|
} from '@exodus/assets'
|
|
7
|
-
import { keyBy, mapValues, partition, pickBy, difference } from '@exodus/basic-utils'
|
|
7
|
+
import { keyBy, mapValues, partition, pickBy, difference, pick } from '@exodus/basic-utils'
|
|
8
8
|
// eslint-disable-next-line no-restricted-imports -- TODO: Fix this the next time the file is edited.
|
|
9
9
|
import lodash from 'lodash'
|
|
10
10
|
import assert from 'minimalistic-assert'
|
|
@@ -30,10 +30,10 @@ import {
|
|
|
30
30
|
createDynamicCombinedAssetDefinitions,
|
|
31
31
|
shouldTokenJoinCombinedAsset,
|
|
32
32
|
findDynamicCombinedAssetForToken,
|
|
33
|
+
getDynamicCombinedAssetKey,
|
|
33
34
|
} from './dynamic-combined-assets.js'
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
const { get, isEmpty, once, uniq, chunk, pick } = lodash
|
|
36
|
+
const { get, isEmpty, once, uniq, chunk } = lodash
|
|
37
37
|
|
|
38
38
|
const getFetchCacheKey = (baseAssetName, assetId) => `${assetId}-${baseAssetName}`
|
|
39
39
|
|
|
@@ -85,6 +85,7 @@ export class AssetsModule {
|
|
|
85
85
|
#logger
|
|
86
86
|
#invalidTokenNames
|
|
87
87
|
#useDynamicCombinedAssets
|
|
88
|
+
#dynamicCombinedAssetOverrides
|
|
88
89
|
|
|
89
90
|
constructor({
|
|
90
91
|
storage,
|
|
@@ -125,6 +126,8 @@ export class AssetsModule {
|
|
|
125
126
|
...(config.invalidTokenNames || []),
|
|
126
127
|
])
|
|
127
128
|
this.#useDynamicCombinedAssets = config.useDynamicCombinedAssets ?? false
|
|
129
|
+
this.#dynamicCombinedAssetOverrides =
|
|
130
|
+
config.dynamicCombinedAssetOverrides ?? Object.create(null)
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
#setRegistry = (registry) => {
|
|
@@ -242,7 +245,9 @@ export class AssetsModule {
|
|
|
242
245
|
|
|
243
246
|
#createDynamicCombinedAssets = () => {
|
|
244
247
|
const allAssets = this.getAssets()
|
|
245
|
-
const definitions = createDynamicCombinedAssetDefinitions(allAssets
|
|
248
|
+
const definitions = createDynamicCombinedAssetDefinitions(allAssets, {
|
|
249
|
+
overrides: this.#dynamicCombinedAssetOverrides,
|
|
250
|
+
})
|
|
246
251
|
|
|
247
252
|
const newlyCreatedNames = []
|
|
248
253
|
for (const definition of definitions) {
|
|
@@ -671,7 +676,8 @@ export class AssetsModule {
|
|
|
671
676
|
|
|
672
677
|
const allAssets = this.getAssets()
|
|
673
678
|
const combinedAssets = Object.values(allAssets).filter((a) => a.isCombined)
|
|
674
|
-
const
|
|
679
|
+
const options = { assets: allAssets, overrides: this.#dynamicCombinedAssetOverrides }
|
|
680
|
+
const matchingCombined = findDynamicCombinedAssetForToken(token, combinedAssets, options)
|
|
675
681
|
|
|
676
682
|
if (matchingCombined) {
|
|
677
683
|
if (!matchingCombined.combinedAssetNames.includes(token.name)) {
|
|
@@ -679,16 +685,17 @@ export class AssetsModule {
|
|
|
679
685
|
return { updated: [matchingCombined.name], created: [], members: [] }
|
|
680
686
|
}
|
|
681
687
|
} else {
|
|
688
|
+
const tokenKey = getDynamicCombinedAssetKey(token, options)
|
|
689
|
+
if (!tokenKey) return { updated: [], created: [], members: [] }
|
|
682
690
|
const matchingAssets = Object.values(allAssets).filter(
|
|
683
691
|
(a) =>
|
|
684
692
|
!a.isCombined &&
|
|
685
|
-
a
|
|
686
|
-
a.displayName?.toLowerCase() === token.displayName?.toLowerCase() &&
|
|
693
|
+
getDynamicCombinedAssetKey(a, options) === tokenKey &&
|
|
687
694
|
shouldTokenJoinCombinedAsset(a)
|
|
688
695
|
)
|
|
689
696
|
|
|
690
697
|
if (matchingAssets.length >= 2) {
|
|
691
|
-
const definitions = createDynamicCombinedAssetDefinitions(matchingAssets)
|
|
698
|
+
const definitions = createDynamicCombinedAssetDefinitions(matchingAssets, options)
|
|
692
699
|
if (definitions.length > 0) {
|
|
693
700
|
const newCombined = this.#registry.addCombinedAsset(definitions[0])
|
|
694
701
|
const memberNames = matchingAssets.map((a) => a.name).filter((n) => n !== token.name)
|
|
@@ -8,13 +8,29 @@ const normalizeForName = (str) => str.toLowerCase().replace(/[^a-z0-9]/g, '')
|
|
|
8
8
|
const createGroupKey = (displayTicker, displayName) =>
|
|
9
9
|
`${normalizeForKey(displayTicker)}::${normalizeForKey(displayName)}`
|
|
10
10
|
|
|
11
|
-
const
|
|
11
|
+
const getGroupingAsset = (asset, { assets = {}, overrides = Object.create(null) } = {}) => {
|
|
12
|
+
if (!Object.hasOwn(overrides, asset.name)) return asset
|
|
13
|
+
|
|
14
|
+
const target = assets[overrides[asset.name]]
|
|
15
|
+
return target && !target.isCombined && shouldTokenJoinCombinedAsset(target) ? target : null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const getDynamicCombinedAssetKey = (asset, options) => {
|
|
19
|
+
const groupingAsset = getGroupingAsset(asset, options)
|
|
20
|
+
if (!groupingAsset) return null
|
|
21
|
+
|
|
22
|
+
const { displayTicker, displayName } = groupingAsset
|
|
23
|
+
return displayTicker && displayName ? createGroupKey(displayTicker, displayName) : null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const groupAssetsByTickerAndName = (assets, options) => {
|
|
12
27
|
const groups = Object.create(null)
|
|
13
28
|
|
|
14
29
|
for (const asset of assets) {
|
|
15
|
-
if (asset.isCombined
|
|
30
|
+
if (asset.isCombined) continue
|
|
16
31
|
|
|
17
|
-
const key =
|
|
32
|
+
const key = getDynamicCombinedAssetKey(asset, options)
|
|
33
|
+
if (!key) continue
|
|
18
34
|
if (!groups[key]) groups[key] = []
|
|
19
35
|
groups[key].push(asset)
|
|
20
36
|
}
|
|
@@ -31,9 +47,12 @@ const resolveDecimals = (assets) => {
|
|
|
31
47
|
return Math.max(...decimals)
|
|
32
48
|
}
|
|
33
49
|
|
|
34
|
-
const createDynamicCombinedAssetDefinition = (assetGroup) => {
|
|
50
|
+
const createDynamicCombinedAssetDefinition = (assetGroup, { overrides }) => {
|
|
35
51
|
const sortedAssets = [...assetGroup].sort(byName)
|
|
36
|
-
const
|
|
52
|
+
const targetNames = new Set(Object.values(overrides))
|
|
53
|
+
const overrideTarget = sortedAssets.find((asset) => targetNames.has(asset.name))
|
|
54
|
+
const primary = overrideTarget ?? sortedAssets[0]
|
|
55
|
+
const members = [primary, ...sortedAssets.filter((asset) => asset !== primary)]
|
|
37
56
|
|
|
38
57
|
const normalizedTicker = normalizeForName(primary.displayTicker)
|
|
39
58
|
const normalizedDisplayName = normalizeForName(primary.displayName)
|
|
@@ -53,7 +72,7 @@ const createDynamicCombinedAssetDefinition = (assetGroup) => {
|
|
|
53
72
|
[`${name}_base`]: 0,
|
|
54
73
|
[ticker]: decimals,
|
|
55
74
|
},
|
|
56
|
-
combinedAssetNames:
|
|
75
|
+
combinedAssetNames: members.map((a) => a.name),
|
|
57
76
|
info: primary.info || { description: '' },
|
|
58
77
|
primaryColor: primary.primaryColor || '#888888',
|
|
59
78
|
gradientColors: primary.gradientColors || ['#888888', '#666666'],
|
|
@@ -71,27 +90,33 @@ export const isTrustedAsset = (asset) => {
|
|
|
71
90
|
return false
|
|
72
91
|
}
|
|
73
92
|
|
|
74
|
-
export const createDynamicCombinedAssetDefinitions = (
|
|
93
|
+
export const createDynamicCombinedAssetDefinitions = (
|
|
94
|
+
assets,
|
|
95
|
+
{ overrides = Object.create(null) } = {}
|
|
96
|
+
) => {
|
|
75
97
|
const assetList = Array.isArray(assets) ? assets : Object.values(assets)
|
|
98
|
+
const options = {
|
|
99
|
+
assets: Object.fromEntries(assetList.map((asset) => [asset.name, asset])),
|
|
100
|
+
overrides,
|
|
101
|
+
}
|
|
76
102
|
const trustedAssets = assetList.filter(
|
|
77
103
|
(asset) => isTrustedAsset(asset) && !isTestnetVariant(asset)
|
|
78
104
|
)
|
|
79
|
-
const groups = groupAssetsByTickerAndName(trustedAssets)
|
|
105
|
+
const groups = groupAssetsByTickerAndName(trustedAssets, options)
|
|
80
106
|
|
|
81
107
|
const definitions = []
|
|
82
108
|
for (const assetGroup of Object.values(groups)) {
|
|
83
109
|
if (assetGroup.length >= MIN_ASSETS_TO_COMBINE) {
|
|
84
|
-
definitions.push(createDynamicCombinedAssetDefinition(assetGroup))
|
|
110
|
+
definitions.push(createDynamicCombinedAssetDefinition(assetGroup, options))
|
|
85
111
|
}
|
|
86
112
|
}
|
|
87
113
|
|
|
88
114
|
return definitions
|
|
89
115
|
}
|
|
90
116
|
|
|
91
|
-
export const findDynamicCombinedAssetForToken = (token, existingCombinedAssets) => {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const tokenKey = createGroupKey(token.displayTicker, token.displayName)
|
|
117
|
+
export const findDynamicCombinedAssetForToken = (token, existingCombinedAssets, options) => {
|
|
118
|
+
const tokenKey = getDynamicCombinedAssetKey(token, options)
|
|
119
|
+
if (!tokenKey) return null
|
|
95
120
|
|
|
96
121
|
for (const combined of existingCombinedAssets) {
|
|
97
122
|
if (!combined.isCombined) continue
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/assets-feature",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.6.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",
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
"@exodus/asset-schema-validation": "^1.2.0",
|
|
41
41
|
"@exodus/asset-types": "^0.5.0",
|
|
42
42
|
"@exodus/assets": "^11.3.0",
|
|
43
|
-
"@exodus/atoms": "^10.3.
|
|
44
|
-
"@exodus/basic-utils": "^5.2.
|
|
43
|
+
"@exodus/atoms": "^10.3.5",
|
|
44
|
+
"@exodus/basic-utils": "^5.2.1",
|
|
45
45
|
"@exodus/fetch": "^1.3.0",
|
|
46
|
-
"@exodus/fusion-atoms": "^1.4.
|
|
47
|
-
"@exodus/timer": "^1.2.
|
|
46
|
+
"@exodus/fusion-atoms": "^1.4.1",
|
|
47
|
+
"@exodus/timer": "^1.2.3",
|
|
48
48
|
"lodash": "^4.17.21",
|
|
49
49
|
"make-concurrent": "^5.4.0",
|
|
50
50
|
"minimalistic-assert": "^1.0.1",
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@exodus/bip32": "^4.3.1",
|
|
56
|
-
"@exodus/bip39": "^1.1.
|
|
57
|
-
"@exodus/bip44-constants": "^195.0.
|
|
56
|
+
"@exodus/bip39": "^1.1.1",
|
|
57
|
+
"@exodus/bip44-constants": "^195.0.3",
|
|
58
58
|
"@exodus/bitcoin-meta": "^2.0.0",
|
|
59
59
|
"@exodus/bitcoin-plugin": "^2.0.0",
|
|
60
60
|
"@exodus/bitcoinregtest-plugin": "^2.0.0",
|
|
@@ -64,16 +64,16 @@
|
|
|
64
64
|
"@exodus/ethereum-lib": "^5.26.0",
|
|
65
65
|
"@exodus/ethereum-meta": "^2.0.0",
|
|
66
66
|
"@exodus/ethereum-plugin": "^3.1.1",
|
|
67
|
-
"@exodus/fusion-local": "^2.1.
|
|
67
|
+
"@exodus/fusion-local": "^2.1.1",
|
|
68
68
|
"@exodus/keychain": "^12.1.0",
|
|
69
|
-
"@exodus/logger": "^1.2.
|
|
70
|
-
"@exodus/models": "^13.3.
|
|
69
|
+
"@exodus/logger": "^1.2.4",
|
|
70
|
+
"@exodus/models": "^13.3.3",
|
|
71
71
|
"@exodus/osmosis-plugin": "^1.3.3",
|
|
72
|
-
"@exodus/public-key-provider": "^4.3.
|
|
72
|
+
"@exodus/public-key-provider": "^4.3.2",
|
|
73
73
|
"@exodus/redux-dependency-injection": "^5.0.0",
|
|
74
|
-
"@exodus/storage-memory": "^2.4.
|
|
74
|
+
"@exodus/storage-memory": "^2.4.1",
|
|
75
75
|
"@exodus/wallet-accounts": "^20.4.12",
|
|
76
|
-
"@exodus/wild-emitter": "^1.1.
|
|
76
|
+
"@exodus/wild-emitter": "^1.1.3",
|
|
77
77
|
"events": "^3.3.0",
|
|
78
78
|
"msw": "^2.0.0",
|
|
79
79
|
"redux": "^4.0.0"
|
|
@@ -82,5 +82,5 @@
|
|
|
82
82
|
"access": "public",
|
|
83
83
|
"provenance": false
|
|
84
84
|
},
|
|
85
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "dc6d4bfa087c6aaf5bf26a6fbe7f8ebebeb23670"
|
|
86
86
|
}
|