@exodus/assets-feature 3.6.0 → 3.8.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/atoms/assets.js +10 -0
- package/index.js +6 -1
- package/module/assets-module.js +52 -25
- package/module/index.js +3 -3
- package/package.json +8 -7
- package/plugin/index.js +53 -22
- package/redux/index.js +4 -7
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
|
+
## [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
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- assets atom ([#4109](https://github.com/ExodusMovement/exodus-hydra/issues/4109)) ([d08880d](https://github.com/ExodusMovement/exodus-hydra/commit/d08880d8fe6f2f596cb01b955787de07f2a0747e))
|
|
11
|
+
|
|
12
|
+
## [3.7.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/assets-feature@3.6.0...@exodus/assets-feature@3.7.0) (2023-10-25)
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
- **assets-feature:** start custom tokens monitor on unlock ([#4562](https://github.com/ExodusMovement/exodus-hydra/issues/4562)) ([adcd284](https://github.com/ExodusMovement/exodus-hydra/commit/adcd2849d7ed383ebe494b123a20e60ae4e89d58))
|
|
17
|
+
|
|
6
18
|
## [3.6.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/assets-feature@3.5.0...@exodus/assets-feature@3.6.0) (2023-10-20)
|
|
7
19
|
|
|
8
20
|
### Features
|
package/atoms/assets.js
ADDED
package/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import assetsApiDefinition from './api'
|
|
|
6
6
|
import assetModuleDefinition from './module'
|
|
7
7
|
import customTokensMonitorDefinition from './monitor'
|
|
8
8
|
import assetPreferencesDefinition from './module/asset-preferences'
|
|
9
|
+
import assetsAtomDefinition from './atoms/assets'
|
|
9
10
|
|
|
10
11
|
const assets = ({ config = {} } = {}) => {
|
|
11
12
|
return {
|
|
@@ -18,6 +19,9 @@ const assets = ({ config = {} } = {}) => {
|
|
|
18
19
|
storage: { namespace: 'assetPreferences' },
|
|
19
20
|
config: config.multiAddressMode || {},
|
|
20
21
|
},
|
|
22
|
+
{
|
|
23
|
+
definition: assetsAtomDefinition,
|
|
24
|
+
},
|
|
21
25
|
{
|
|
22
26
|
definition: disabledPurposesAtomDefinition,
|
|
23
27
|
storage: { namespace: 'assetPreferences' },
|
|
@@ -25,10 +29,11 @@ const assets = ({ config = {} } = {}) => {
|
|
|
25
29
|
},
|
|
26
30
|
{ definition: assetsApiDefinition },
|
|
27
31
|
// TODO: add storage namespace once we remove customTokensStorage
|
|
28
|
-
// eslint-disable-next-line hydra/missing-storage-namespace
|
|
32
|
+
// eslint-disable-next-line @exodus/hydra/missing-storage-namespace
|
|
29
33
|
{
|
|
30
34
|
definition: assetModuleDefinition,
|
|
31
35
|
// storage: { namespace: 'customTokens' },
|
|
36
|
+
writesAtoms: ['assetsAtom'],
|
|
32
37
|
aliases: [{ implementationId: 'customTokensStorage', interfaceId: 'storage' }],
|
|
33
38
|
},
|
|
34
39
|
{
|
package/module/assets-module.js
CHANGED
|
@@ -6,8 +6,6 @@ import {
|
|
|
6
6
|
CT_UPDATEABLE_PROPERTIES,
|
|
7
7
|
} from '@exodus/assets'
|
|
8
8
|
import { mapValues, pick, pickBy } from '@exodus/basic-utils'
|
|
9
|
-
// eslint-disable-next-line no-restricted-imports
|
|
10
|
-
import { fetchival } from '@exodus/fetch'
|
|
11
9
|
import ExodusModule from '@exodus/module'
|
|
12
10
|
// eslint-disable-next-line @exodus/restricted-imports/prefer-basic-utils
|
|
13
11
|
import { get, isEmpty, keyBy, once } from 'lodash'
|
|
@@ -20,6 +18,7 @@ import {
|
|
|
20
18
|
CT_UPDATE_INTERVAL,
|
|
21
19
|
} from './constants'
|
|
22
20
|
import { getAssetFromAssetId, getFetchErrorMessage, isDisabledCustomToken } from './utils'
|
|
21
|
+
import createFetchival from '@exodus/fetch/create-fetchival'
|
|
23
22
|
|
|
24
23
|
const FILTERED_FIELDS = [
|
|
25
24
|
'assetId',
|
|
@@ -86,24 +85,27 @@ export class AssetsModule extends ExodusModule {
|
|
|
86
85
|
#storageTimestampKey
|
|
87
86
|
#customTokenUpdateInterval
|
|
88
87
|
#fetchCacheExpiry
|
|
89
|
-
#globalAssetRegistry // temporary
|
|
90
88
|
#isExternalRegistry
|
|
89
|
+
#assetsAtom
|
|
90
|
+
#fetchival
|
|
91
91
|
|
|
92
92
|
constructor({
|
|
93
93
|
storage,
|
|
94
94
|
iconsStorage,
|
|
95
95
|
assetRegistry, // temporary
|
|
96
96
|
assetPlugins,
|
|
97
|
+
assetsAtom,
|
|
97
98
|
combinedAssetsList = [],
|
|
98
|
-
globalAssetRegistry, // temporary
|
|
99
99
|
validateCustomToken = () => true,
|
|
100
100
|
config = {},
|
|
101
|
+
fetch,
|
|
101
102
|
}) {
|
|
102
103
|
super({ name: 'AssetsModule' })
|
|
103
104
|
|
|
105
|
+
this.#assetsAtom = assetsAtom
|
|
104
106
|
this.#storage = storage
|
|
105
107
|
this.#isExternalRegistry = !!assetRegistry
|
|
106
|
-
this.#
|
|
108
|
+
this.#setRegistry(assetRegistry ?? initialAssetRegistry)
|
|
107
109
|
this.#assetPlugins = assetPlugins
|
|
108
110
|
this.#combinedAssetsList = combinedAssetsList
|
|
109
111
|
this.#fetchCache = {}
|
|
@@ -116,10 +118,24 @@ export class AssetsModule extends ExodusModule {
|
|
|
116
118
|
this.#storageTimestampKey = config.storageTimestampKey || CT_TIMESTAMP_KEY
|
|
117
119
|
this.#customTokenUpdateInterval = config.customTokenUpdateInterval || CT_UPDATE_INTERVAL
|
|
118
120
|
this.#fetchCacheExpiry = config.fetchCacheExpiry ?? CT_FETCH_CACHE_EXPIRY
|
|
119
|
-
this.#
|
|
121
|
+
this.#fetchival = createFetchival({ fetch })
|
|
120
122
|
}
|
|
121
123
|
|
|
122
|
-
|
|
124
|
+
#setRegistry = (registry) => {
|
|
125
|
+
this.#registry = registry
|
|
126
|
+
|
|
127
|
+
if (registry === initialAssetRegistry) {
|
|
128
|
+
return
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// we want this to happen asap before load and even before start
|
|
132
|
+
this.#assetsAtom.set({
|
|
133
|
+
value: { ...this.#registry.getAssets() },
|
|
134
|
+
added: [],
|
|
135
|
+
updated: [],
|
|
136
|
+
disabled: [],
|
|
137
|
+
})
|
|
138
|
+
}
|
|
123
139
|
|
|
124
140
|
initialize = ({ assetClientInterface }) => {
|
|
125
141
|
assert(
|
|
@@ -135,11 +151,11 @@ export class AssetsModule extends ExodusModule {
|
|
|
135
151
|
console.warn(`Incorrectly referenced supported asset ${name}. Expected ${asset.name}.`)
|
|
136
152
|
})
|
|
137
153
|
.filter(Boolean)
|
|
138
|
-
this.#
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
154
|
+
this.#setRegistry(
|
|
155
|
+
createAssetRegistry({
|
|
156
|
+
supportedAssetsList: [...assetsList, ...this.#combinedAssetsList],
|
|
157
|
+
})
|
|
158
|
+
)
|
|
143
159
|
}
|
|
144
160
|
|
|
145
161
|
getAssets = () => this.#registry.getAssets()
|
|
@@ -175,7 +191,7 @@ export class AssetsModule extends ExodusModule {
|
|
|
175
191
|
// 3. both of the above from a network that has feature flag customTokens === false
|
|
176
192
|
// It is OK to add all of these to the assets registry
|
|
177
193
|
const { added, updated } = this.#handleFetchedTokens(Object.values(tokens))
|
|
178
|
-
this.#
|
|
194
|
+
this.#flushChanges({ added, updated })
|
|
179
195
|
} catch (e) {
|
|
180
196
|
this._logger.log('error reading custom tokens from storage:', e)
|
|
181
197
|
}
|
|
@@ -223,9 +239,9 @@ export class AssetsModule extends ExodusModule {
|
|
|
223
239
|
|
|
224
240
|
if (isAdded) {
|
|
225
241
|
await this.#storeCustomTokens([token])
|
|
226
|
-
this.#
|
|
242
|
+
this.#flushChanges({ added: [asset] })
|
|
227
243
|
} else {
|
|
228
|
-
this.#
|
|
244
|
+
this.#flushChanges({ updated: [asset] })
|
|
229
245
|
}
|
|
230
246
|
|
|
231
247
|
return asset
|
|
@@ -269,7 +285,7 @@ export class AssetsModule extends ExodusModule {
|
|
|
269
285
|
await this.#storeCustomTokens(fetchedAndHandledTokens)
|
|
270
286
|
}
|
|
271
287
|
|
|
272
|
-
this.#
|
|
288
|
+
this.#flushChanges({ added, updated })
|
|
273
289
|
|
|
274
290
|
return added.concat(updated)
|
|
275
291
|
}
|
|
@@ -299,7 +315,7 @@ export class AssetsModule extends ExodusModule {
|
|
|
299
315
|
await this.#iconsStorage.storeIcons(fetchedAndHandledTokens)
|
|
300
316
|
}
|
|
301
317
|
|
|
302
|
-
this.#
|
|
318
|
+
this.#flushChanges({ added, updated })
|
|
303
319
|
}
|
|
304
320
|
|
|
305
321
|
updateTokens = async () => {
|
|
@@ -324,10 +340,8 @@ export class AssetsModule extends ExodusModule {
|
|
|
324
340
|
(token) => _isDisabledCustomToken(token) && !isDisabledCustomToken(this.getAsset(token.name))
|
|
325
341
|
)
|
|
326
342
|
const updatedAssets = tokens.map(this.#registry.updateCustomToken)
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
this.emit('assets-disable', disabled)
|
|
330
|
-
}
|
|
343
|
+
|
|
344
|
+
this.#flushChanges({ updated: updatedAssets, disabled })
|
|
331
345
|
}
|
|
332
346
|
|
|
333
347
|
searchTokens = async ({ baseAssetName, lifecycleStatus, query, excludeTags = ['offensive'] }) => {
|
|
@@ -393,17 +407,30 @@ export class AssetsModule extends ExodusModule {
|
|
|
393
407
|
return item?.value && Date.now() < item.expiry ? item.value : null
|
|
394
408
|
}
|
|
395
409
|
|
|
396
|
-
#
|
|
410
|
+
#flushChanges = ({ added = [], updated = [], disabled = [] } = {}) => {
|
|
411
|
+
// TODO: remove these once all consumers are refactored
|
|
397
412
|
if (added.length > 0) this.emit('assets-add', added)
|
|
398
413
|
if (updated.length > 0) this.emit('assets-update', updated)
|
|
414
|
+
if (disabled.length > 0) this.emit('assets-disable', disabled)
|
|
415
|
+
|
|
416
|
+
if (added.length + updated.length + disabled.length === 0) {
|
|
417
|
+
return
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
this.#assetsAtom.set({
|
|
421
|
+
value: { ...this.#registry.getAssets() },
|
|
422
|
+
added,
|
|
423
|
+
updated,
|
|
424
|
+
disabled,
|
|
425
|
+
})
|
|
399
426
|
}
|
|
400
427
|
|
|
401
428
|
#fetch = async (endpoint, body, resultPath) => {
|
|
402
429
|
try {
|
|
403
430
|
const testDataParam = this.#config.fetchTestValues ? '?test=true' : ''
|
|
404
|
-
const res = await fetchival(this.#customTokensServerUrl)(
|
|
405
|
-
|
|
406
|
-
)
|
|
431
|
+
const res = await this.#fetchival(this.#customTokensServerUrl)(
|
|
432
|
+
`${endpoint}${testDataParam}`
|
|
433
|
+
).post(body)
|
|
407
434
|
|
|
408
435
|
if (res.status !== 'OK')
|
|
409
436
|
throw new Error(`Custom tokens registry ${endpoint} ${res.status} ${res.message}`)
|
package/module/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
// eslint-disable-next-line @exodus/restricted-imports/no-exodus-assets
|
|
2
|
-
import globalAssetRegistry from '@exodus/assets' // this is deprecated, do not use for any other purpose. Remove when we have @exodus/models v10.
|
|
3
1
|
import AssetsModule from './assets-module'
|
|
4
2
|
|
|
5
|
-
const createAssetsModule = (props) => new AssetsModule(
|
|
3
|
+
const createAssetsModule = (props) => new AssetsModule(props)
|
|
6
4
|
|
|
7
5
|
const assetsModuleDefinition = {
|
|
8
6
|
id: 'assetsModule',
|
|
9
7
|
type: 'module',
|
|
10
8
|
factory: createAssetsModule,
|
|
11
9
|
dependencies: [
|
|
10
|
+
'assetsAtom',
|
|
12
11
|
'storage',
|
|
13
12
|
'iconsStorage',
|
|
14
13
|
'assetPlugins',
|
|
15
14
|
'combinedAssetsList?',
|
|
16
15
|
'validateCustomToken?',
|
|
17
16
|
'config',
|
|
17
|
+
'fetch',
|
|
18
18
|
],
|
|
19
19
|
}
|
|
20
20
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/assets-feature",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.0",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"description": "Assets module, clients and apis",
|
|
6
6
|
"main": "index.js",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@exodus/basic-utils": "^2.1.0",
|
|
35
|
-
"@exodus/fetch": "^1.
|
|
35
|
+
"@exodus/fetch": "^1.3.0",
|
|
36
36
|
"@exodus/timer": "^1.0.0",
|
|
37
37
|
"lodash": "^4.17.21",
|
|
38
38
|
"minimalistic-assert": "^1.0.1",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@exodus/assets": "^8.0.95",
|
|
44
|
-
"@exodus/atoms": "^
|
|
44
|
+
"@exodus/atoms": "^6.0.1",
|
|
45
45
|
"@exodus/available-assets": "^7.0.0",
|
|
46
46
|
"@exodus/bitcoin-meta": "^1.0.1",
|
|
47
47
|
"@exodus/bitcoin-plugin": "^1.0.3",
|
|
@@ -49,18 +49,19 @@
|
|
|
49
49
|
"@exodus/bitcointestnet-plugin": "^1.0.3",
|
|
50
50
|
"@exodus/combined-assets-meta": "^1.2.5",
|
|
51
51
|
"@exodus/cosmos-plugin": "^1.0.0",
|
|
52
|
-
"@exodus/ethereum-meta": "^1.0
|
|
52
|
+
"@exodus/ethereum-meta": "^1.1.0",
|
|
53
53
|
"@exodus/models": "^9.1.1",
|
|
54
|
-
"@exodus/module": "^1.2.
|
|
54
|
+
"@exodus/module": "^1.2.2",
|
|
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.
|
|
58
|
+
"@exodus/wallet-accounts": "^14.2.0",
|
|
59
59
|
"@exodus/wild-emitter": "^1.0.0",
|
|
60
60
|
"eslint": "^8.44.0",
|
|
61
61
|
"events": "^3.3.0",
|
|
62
62
|
"jest": "^29.1.2",
|
|
63
|
+
"msw": "^2.0.0",
|
|
63
64
|
"redux": "^4.0.0"
|
|
64
65
|
},
|
|
65
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "4480f8501a837520fd19403ea1cffb1e3d7ac9d8"
|
|
66
67
|
}
|
package/plugin/index.js
CHANGED
|
@@ -1,66 +1,97 @@
|
|
|
1
1
|
import { mapValues, pickBy } from '@exodus/basic-utils'
|
|
2
2
|
import { createAtomObserver } from '@exodus/atoms'
|
|
3
3
|
|
|
4
|
-
const createAssetsPlugin = ({
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
const createAssetsPlugin = ({
|
|
5
|
+
port,
|
|
6
|
+
assetsModule,
|
|
7
|
+
assetsAtom,
|
|
8
|
+
customTokensMonitor,
|
|
9
|
+
disabledPurposesAtom,
|
|
10
|
+
multiAddressModeAtom,
|
|
11
|
+
}) => {
|
|
12
|
+
const emitAssets = async () => {
|
|
13
|
+
const { value: assets } = await assetsAtom.get()
|
|
14
|
+
const payload = {
|
|
8
15
|
assets,
|
|
9
16
|
defaultAccountStates: mapValues(
|
|
10
17
|
pickBy(assets, (asset) => asset.api?.hasFeature?.('accountState')),
|
|
11
18
|
(asset) => asset.api.createAccountState().create()
|
|
12
19
|
),
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const listeners = [
|
|
17
|
-
['assets-add', (data) => port.emit('assets-add', data)],
|
|
18
|
-
['assets-update', (data) => port.emit('assets-update', data)],
|
|
19
|
-
]
|
|
20
|
+
}
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
22
|
+
port.emit('assets', payload)
|
|
23
|
+
port.emit('assets-load', payload) // legacy to be removed
|
|
24
|
+
}
|
|
24
25
|
|
|
25
26
|
const observers = [
|
|
26
27
|
createAtomObserver({ atom: disabledPurposesAtom, port, event: 'disabledPurposes' }),
|
|
27
28
|
createAtomObserver({ atom: multiAddressModeAtom, port, event: 'multiAddressMode' }),
|
|
28
29
|
]
|
|
29
30
|
|
|
31
|
+
const subscribers = []
|
|
32
|
+
|
|
30
33
|
const onStart = async () => {
|
|
34
|
+
subscribers.push(
|
|
35
|
+
assetsAtom.observe(({ added, updated, disabled }) => {
|
|
36
|
+
if (added.length > 0) {
|
|
37
|
+
port.emit('assets-add', added)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (updated.length > 0) {
|
|
41
|
+
port.emit('assets-update', updated)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (disabled.length > 0) {
|
|
45
|
+
port.emit('assets-disable', disabled)
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
)
|
|
49
|
+
|
|
31
50
|
observers.forEach((observer) => observer.register())
|
|
32
51
|
|
|
33
52
|
await assetsModule.load()
|
|
34
|
-
|
|
53
|
+
await emitAssets()
|
|
35
54
|
}
|
|
36
55
|
|
|
37
56
|
const onLoad = async () => {
|
|
38
57
|
observers.forEach((observer) => observer.start())
|
|
39
58
|
|
|
40
59
|
await assetsModule.load()
|
|
41
|
-
|
|
60
|
+
await emitAssets()
|
|
42
61
|
}
|
|
43
62
|
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
})
|
|
63
|
+
const onUnlock = () => {
|
|
64
|
+
customTokensMonitor.start()
|
|
65
|
+
}
|
|
48
66
|
|
|
67
|
+
const onLock = () => {
|
|
68
|
+
customTokensMonitor.stop()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const onStop = () => {
|
|
49
72
|
observers.forEach((observer) => observer.unregister())
|
|
73
|
+
subscribers.forEach((unsubscribe) => unsubscribe())
|
|
50
74
|
}
|
|
51
75
|
|
|
52
76
|
const onClear = async () => {
|
|
53
77
|
await assetsModule.clear()
|
|
54
78
|
}
|
|
55
79
|
|
|
56
|
-
return { onStart, onLoad, onStop, onClear }
|
|
80
|
+
return { onStart, onLoad, onUnlock, onLock, onStop, onClear }
|
|
57
81
|
}
|
|
58
82
|
|
|
59
83
|
const assetsPluginDefinition = {
|
|
60
84
|
id: 'assetsPlugin',
|
|
61
85
|
type: 'plugin',
|
|
62
86
|
factory: createAssetsPlugin,
|
|
63
|
-
dependencies: [
|
|
87
|
+
dependencies: [
|
|
88
|
+
'port',
|
|
89
|
+
'assetsModule',
|
|
90
|
+
'assetsAtom',
|
|
91
|
+
'customTokensMonitor',
|
|
92
|
+
'disabledPurposesAtom',
|
|
93
|
+
'multiAddressModeAtom',
|
|
94
|
+
],
|
|
64
95
|
}
|
|
65
96
|
|
|
66
97
|
export default assetsPluginDefinition
|
package/redux/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { keyBy } from '@exodus/basic-utils'
|
|
2
1
|
import id from './id'
|
|
3
2
|
import initialState from './initial-state'
|
|
4
3
|
import selectorDefinitions from './selectors'
|
|
4
|
+
import { keyBy } from '@exodus/basic-utils'
|
|
5
5
|
|
|
6
6
|
const mergeAssets = (state, payload) => ({
|
|
7
7
|
...state,
|
|
@@ -16,14 +16,11 @@ const assetsReduxDefinition = {
|
|
|
16
16
|
type: 'redux-module',
|
|
17
17
|
initialState,
|
|
18
18
|
eventReducers: {
|
|
19
|
-
'assets-load': (state, { assets }) => ({
|
|
20
|
-
...state,
|
|
21
|
-
error: null,
|
|
22
|
-
loaded: true,
|
|
23
|
-
data: assets,
|
|
24
|
-
}),
|
|
25
19
|
'assets-add': mergeAssets,
|
|
26
20
|
'assets-update': mergeAssets,
|
|
21
|
+
assets: (state, { assets }) => {
|
|
22
|
+
return { ...state, error: null, loaded: true, data: assets }
|
|
23
|
+
},
|
|
27
24
|
multiAddressMode: (state, payload) => ({
|
|
28
25
|
...state,
|
|
29
26
|
multiAddressMode: payload,
|