@exodus/headless 2.0.0-alpha.39 → 2.0.0-alpha.4

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/src/index.js CHANGED
@@ -1,121 +1,22 @@
1
- import { pick } from '@exodus/basic-utils'
2
-
3
- import createApi from './api'
4
- import attachAtoms from './atoms/attach'
5
- import { atomsToAttach } from './constants'
6
1
  import createIOC from './ioc'
7
- import attachPlugins from './plugins/attach'
8
- import { createLoadWalletAccountsHandler } from './utils/blockchain-metadata'
2
+ import createApi from './api'
9
3
 
10
4
  const createExodus = ({ adapters, config, port }) => {
11
5
  const ioc = createIOC({ adapters, config })
12
- const { headless: headlessConfig } = config
13
6
 
14
7
  const resolve = () => {
15
8
  ioc.resolve()
16
9
 
17
- const { assetsModule, storage } = ioc.getByType('adapter')
18
-
19
- const { languageAtom } = ioc.getByType('atom')
20
-
21
- const {
22
- application,
23
- blockchainMetadata,
24
- connectedOrigins,
25
- enabledAssets,
26
- featureFlags,
27
- kyc,
28
- nfts,
29
- personalNotes,
30
- referrals,
31
- remoteConfig,
32
- unlockEncryptedStorage,
33
- walletAccounts,
34
- } = ioc.getByType('module')
35
-
36
- const {
37
- apyRatesMonitor,
38
- cryptoNewsMonitor,
39
- feeMonitors,
40
- geolocationMonitor,
41
- marketHistory,
42
- nftsMonitor,
43
- ratesMonitor,
44
- topMoversMonitor,
45
- } = ioc.getByType('monitor')
46
-
47
- const { featureFlagAtoms } = ioc.getByType('atom-collection')
48
-
49
- const handleLoadWalletAccounts = createLoadWalletAccountsHandler({
50
- blockchainMetadata,
51
- port,
52
- })
53
-
54
- blockchainMetadata.on('load-wallet-accounts', handleLoadWalletAccounts)
55
- blockchainMetadata.on('tx-logs-update', (payload) => port.emit('tx-logs-update', payload))
56
- blockchainMetadata.on('account-states-update', (payload) =>
57
- port.emit('account-states-update', payload)
58
- )
59
-
60
- feeMonitors.on('fees-load', () => port.emit('fees-load', feeMonitors.getAllFeeData()))
61
- feeMonitors.on('fees-update', (payload) => port.emit('fees-update', payload))
62
-
63
- remoteConfig.on('sync', ({ current }) => port.emit('remote-config', current))
10
+ const { assetsModule } = ioc.getByType('adapter')
64
11
 
65
- // TODO: migrate to marketHistoryAtom. Will be easier once it's on headless
66
- marketHistory.on('market-history', (payload) => port.emit('market-history', payload))
67
- marketHistory.on('market-history-new-assets', (payload) =>
68
- port.emit('market-history-new-assets', payload)
69
- )
12
+ const { application } = ioc.getByType('module')
70
13
 
71
- // TODO: migrate to ratesAtom. Will be easier once it's on headless
72
- ratesMonitor.on('rates', (payload) => port.emit('rates', payload))
73
-
74
- nftsMonitor.on('nfts', (data) => port.emit('nfts', data))
75
- nftsMonitor.on('nfts-txs', (data) => port.emit('nfts-txs', data))
76
-
77
- application.hook('start', (payload) => {
78
- remoteConfig.load()
79
- featureFlags.load()
80
- geolocationMonitor.start()
81
-
82
- port.emit('start', payload)
14
+ application.hook('start', () => {
15
+ port.emit('start')
83
16
  })
84
17
 
85
18
  application.hook('unlock', async () => {
86
- if (typeof storage.unlock === 'function') unlockEncryptedStorage(storage)
87
-
88
- remoteConfig.sync()
89
- marketHistory.start()
90
- ratesMonitor.start()
91
- feeMonitors.start()
92
- apyRatesMonitor.start()
93
- nftsMonitor.start()
94
-
95
19
  await assetsModule.load()
96
- await connectedOrigins.load()
97
- await walletAccounts.load()
98
- await Promise.all([
99
- //
100
- blockchainMetadata.load(),
101
- enabledAssets.load(),
102
- ])
103
-
104
- featureFlagAtoms.referrals?.get().then(({ isOn }) => {
105
- if (!isOn) return
106
- kyc.load()
107
- referrals.load()
108
- })
109
-
110
- featureFlagAtoms.topMovers?.get().then(({ isOn }) => {
111
- if (!isOn) return
112
- topMoversMonitor.start()
113
- })
114
-
115
- featureFlagAtoms.cryptoNews?.get().then(({ isOn }) => {
116
- if (!isOn) return
117
- cryptoNewsMonitor.start()
118
- })
119
20
  })
120
21
 
121
22
  application.on('unlock', () => {
@@ -123,37 +24,14 @@ const createExodus = ({ adapters, config, port }) => {
123
24
  })
124
25
 
125
26
  application.hook('clear', async () => {
126
- await Promise.all([
127
- //
128
- assetsModule.clear(),
129
- walletAccounts.clear(),
130
- blockchainMetadata.clear(),
131
- enabledAssets.clear(),
132
- connectedOrigins.clear(),
133
- featureFlags.clear(),
134
- languageAtom.set(undefined),
135
- ])
136
-
137
- // TEMP: dont wait to clear as encrypted storage is not yet unlocked
138
- personalNotes.clear()
139
- nfts.clear()
140
-
141
- port.emit('clear')
27
+ await Promise.all([assetsModule.clear()])
142
28
  })
143
29
 
144
30
  application.on('restart', (payload) => {
145
31
  port.emit('restart', payload)
146
32
  })
147
33
 
148
- attachAtoms({
149
- port,
150
- application,
151
- logger: ioc.get('createLogger')('attachAtoms'),
152
- atoms: pick(ioc.getByType('atom'), atomsToAttach),
153
- lifecycleEvents: headlessConfig?.attachAtomsLifecycleEvents,
154
- })
155
-
156
- attachPlugins({ application, plugins: ioc.getByType('plugin') })
34
+ application.start()
157
35
 
158
36
  return createApi({ ioc, port })
159
37
  }
package/src/ioc.js CHANGED
@@ -1,48 +1,23 @@
1
1
  import createIocContainer from '@exodus/dependency-injection'
2
2
  import preprocess from '@exodus/dependency-preprocessors'
3
3
  import alias from '@exodus/dependency-preprocessors/src/preprocessors/alias'
4
- import devModeAtoms from '@exodus/dependency-preprocessors/src/preprocessors/dev-mode-atoms'
5
4
  import logify from '@exodus/dependency-preprocessors/src/preprocessors/logify'
6
5
  import namespaceConfig from '@exodus/dependency-preprocessors/src/preprocessors/namespace-config'
7
- import namespaceStorage from '@exodus/dependency-preprocessors/src/preprocessors/namespace-storage'
8
- import optional from '@exodus/dependency-preprocessors/src/preprocessors/optional'
9
- import readOnlyAtoms from '@exodus/dependency-preprocessors/src/preprocessors/read-only-atoms'
10
6
 
11
7
  import createDependencies from './dependencies'
12
8
 
13
9
  const createIOC = ({ adapters, config }) => {
14
10
  const { createLogger } = adapters
15
- const { readOnlyAtoms: readOnlyAtomsConfig, devModeAtoms: devModeAtomsConfig } = config.ioc ?? {}
16
11
 
17
- const ioc = createIocContainer({ logger: createLogger('exodus:ioc') })
12
+ const logger = createLogger('exodus:ioc')
18
13
  const dependencies = createDependencies({ adapters, config })
14
+ const preprocessors = [logify({ createLogger }), namespaceConfig(), alias()]
15
+ const definitions = preprocess({ dependencies, preprocessors })
16
+ const ioc = createIocContainer({ logger })
19
17
 
20
- const preprocessors = [
21
- logify({ createLogger }),
22
- namespaceConfig(),
23
- alias(),
24
- // NOTE: order matters, this should come after `alias`
25
- namespaceStorage(),
26
- readOnlyAtoms({
27
- logger: createLogger('exodus:read-only-atoms'),
28
- warn: true,
29
- ...readOnlyAtomsConfig,
30
- }),
31
- optional(),
32
- ...(devModeAtomsConfig ? [devModeAtoms(devModeAtomsConfig)] : []),
33
- ]
18
+ ioc.registerMultiple(definitions)
34
19
 
35
- const registerMultiple = (dependencies) => {
36
- ioc.registerMultiple(preprocess({ dependencies, preprocessors }))
37
- }
38
-
39
- const register = (dependency) => {
40
- registerMultiple([dependency])
41
- }
42
-
43
- registerMultiple(dependencies)
44
-
45
- return { ...ioc, register, registerMultiple }
20
+ return ioc
46
21
  }
47
22
 
48
23
  export default createIOC
@@ -1,31 +0,0 @@
1
- const emitAtomValue = async (opts) => {
2
- const { port, atomId, atom } = opts
3
- const value = 'value' in opts ? opts.value : await atom.get()
4
- port.emit(atomId, value)
5
- }
6
-
7
- export const emitFromAtoms = ({ atoms, port }) =>
8
- Object.entries(atoms).forEach(async ([atomId, atom]) => emitAtomValue({ port, atomId, atom }))
9
-
10
- const attachAtom = ({ port, application, logger, atom, atomId, lifecycleEvents }) => {
11
- let loaded = false
12
-
13
- lifecycleEvents.forEach((event) =>
14
- application.on(event, async () => {
15
- loaded = true
16
- await emitAtomValue({ port, atomId, atom })
17
- })
18
- )
19
-
20
- atom.observe((value) => {
21
- if (loaded) emitAtomValue({ port, atomId, atom, value })
22
- })
23
- }
24
-
25
- const attachAtoms = ({ port, application, logger, atoms, lifecycleEvents = ['start'] }) => {
26
- for (const [atomId, atom] of Object.entries(atoms)) {
27
- attachAtom({ port, application, logger, atom, atomId, lifecycleEvents })
28
- }
29
- }
30
-
31
- export default attachAtoms
@@ -1,36 +0,0 @@
1
- import { combine, compute } from '@exodus/atoms'
2
- import { uniq } from 'lodash'
3
-
4
- const getNetworks = (assetNames, assets) =>
5
- uniq(
6
- assetNames
7
- .map((assetName) => assets[assetName]?.baseAsset.name)
8
- .filter((assetName) => !!assetName && !assets[assetName].isCombined)
9
- )
10
-
11
- const createBaseAssetNamesToMonitorAtom = ({
12
- assetsModule,
13
- enabledAssetsAtom,
14
- restoreAtom,
15
- availableAssetNamesAtom,
16
- }) => {
17
- const selector = ({ isRestore, enabledAssets, availableAssetNames }) => {
18
- const assetNames = isRestore ? availableAssetNames : Object.keys(enabledAssets)
19
- return getNetworks(assetNames, assetsModule.getAssets())
20
- }
21
-
22
- return compute({
23
- atom: combine({
24
- isRestore: restoreAtom,
25
- enabledAssets: enabledAssetsAtom,
26
- availableAssetNames: availableAssetNamesAtom,
27
- }),
28
- selector,
29
- })
30
- }
31
-
32
- export default {
33
- id: 'baseAssetNamesToMonitorAtom',
34
- factory: createBaseAssetNamesToMonitorAtom,
35
- dependencies: ['assetsModule', 'availableAssetNamesAtom', 'enabledAssetsAtom', 'restoreAtom'],
36
- }
@@ -1,10 +0,0 @@
1
- import { createInMemoryAtom } from '@exodus/atoms'
2
-
3
- const nonDustBalanceAssetNamesAtomDefinition = {
4
- id: 'nonDustBalanceAssetNamesAtom',
5
- type: 'atom',
6
- factory: () => createInMemoryAtom({ defaultValue: [] }),
7
- dependencies: [],
8
- }
9
-
10
- export default nonDustBalanceAssetNamesAtomDefinition
@@ -1,10 +0,0 @@
1
- import { createInMemoryAtom } from '@exodus/atoms'
2
-
3
- const restoreAtomDefinition = {
4
- id: 'restoreAtom',
5
- type: 'atom',
6
- factory: () => createInMemoryAtom(),
7
- dependencies: [],
8
- }
9
-
10
- export default restoreAtomDefinition
package/src/constants.js DELETED
@@ -1,18 +0,0 @@
1
- export const atomsToAttach = [
2
- 'apyRatesAtom',
3
- 'availableAssetNamesAtom',
4
- 'balancesAtom',
5
- 'connectedOriginsAtom',
6
- 'cryptoNewsAtom',
7
- 'currencyAtom',
8
- 'enabledWalletAccountsAtom',
9
- 'featureFlagsAtom',
10
- 'geolocationAtom',
11
- 'kycAtom',
12
- 'languageAtom',
13
- 'nftsConfigAtom',
14
- 'personalNotesAtom',
15
- 'referralsAtom',
16
- 'topMoversAtom',
17
- 'walletAccountsAtom',
18
- ]
@@ -1,25 +0,0 @@
1
- import {
2
- featureFlagAtomsDefinition,
3
- remoteConfigFeatureFlagAtomsDefinition,
4
- } from '@exodus/feature-flags/atoms'
5
-
6
- import { withType } from './utils'
7
-
8
- const createAtomCollectionDependencies = () =>
9
- [
10
- {
11
- definition: remoteConfigFeatureFlagAtomsDefinition,
12
- },
13
- {
14
- definition: featureFlagAtomsDefinition,
15
- storage: { namespace: 'featureFlags' },
16
- aliases: [
17
- {
18
- implementationId: 'unsafeStorage',
19
- interfaceId: 'storage',
20
- },
21
- ],
22
- },
23
- ].map(withType('atom-collection'))
24
-
25
- export default createAtomCollectionDependencies
@@ -1,66 +0,0 @@
1
- import apyRatesMonitorDefinition from '@exodus/apy-rates/monitor'
2
- import cryptoNewsMonitorDefinition from '@exodus/crypto-news-monitor/monitor'
3
- import feeMonitorsDefinition from '@exodus/fee-monitors/monitor'
4
- import geolocationMonitorDefinition from '@exodus/geolocation/monitor'
5
- import marketHistoryMonitorDefinition from '@exodus/market-history/module'
6
- import nftsMonitorDefinition from '@exodus/nfts/monitor'
7
- import ratesMonitorDefinition from '@exodus/rates-monitor/module'
8
- import localTopMoversMonitorDefinition from '@exodus/top-movers-monitor/monitor/local'
9
- import remoteTopMoversMonitorDefinition from '@exodus/top-movers-monitor/monitor/remote'
10
-
11
- import { withType } from './utils'
12
-
13
- const createMonitorDependencies = ({ config }) =>
14
- [
15
- {
16
- definition: geolocationMonitorDefinition,
17
- writesAtoms: ['geolocationAtom'],
18
- },
19
- {
20
- definition: marketHistoryMonitorDefinition,
21
- storage: { namespace: 'marketHistory' },
22
- aliases: [
23
- {
24
- implementationId: 'unsafeStorage',
25
- interfaceId: 'storage',
26
- },
27
- {
28
- implementationId: 'marketHistoryClearCacheAtom',
29
- interfaceId: 'clearCacheAtom',
30
- },
31
- {
32
- implementationId: 'remoteConfigClearMarketHistoryCacheAtom',
33
- interfaceId: 'remoteConfigClearCacheAtom',
34
- },
35
- {
36
- implementationId: 'marketHistoryRefreshIntervalAtom',
37
- interfaceId: 'remoteConfigRefreshIntervalAtom',
38
- },
39
- ],
40
- },
41
- { definition: feeMonitorsDefinition },
42
- {
43
- definition: ratesMonitorDefinition,
44
- writesAtoms: ['ratesAtom'],
45
- },
46
- {
47
- definition: config.topMoversMonitor.computeLocally
48
- ? localTopMoversMonitorDefinition
49
- : remoteTopMoversMonitorDefinition,
50
- writesAtoms: ['topMoversAtom'],
51
- },
52
- {
53
- definition: cryptoNewsMonitorDefinition,
54
- writesAtoms: ['cryptoNewsAtom'],
55
- },
56
- {
57
- definition: apyRatesMonitorDefinition,
58
- writesAtoms: ['apyRatesAtom'],
59
- },
60
- {
61
- definition: nftsMonitorDefinition,
62
- writesAtoms: ['nftsCacheAtom'],
63
- },
64
- ].map(withType('monitor'))
65
-
66
- export default createMonitorDependencies
@@ -1,7 +0,0 @@
1
- import plugins from '../plugins'
2
- import { withType } from './utils'
3
-
4
- const createPluginDependencies = () =>
5
- plugins.map((definition) => ({ definition })).map(withType('plugin'))
6
-
7
- export default createPluginDependencies
@@ -1,19 +0,0 @@
1
- import { kebabCase, memoize } from 'lodash'
2
-
3
- // e.g. onUnlock -> unlock -> onUnlock, onChangePassphrase -> change-passphrase
4
- const getApplicationHookName = memoize((lifecycleMethod) =>
5
- kebabCase(lifecycleMethod.replace(/^on/, ''))
6
- )
7
-
8
- const attachPlugins = ({ plugins, application }) => {
9
- Object.entries(plugins).forEach(([name, lifecycleMethods]) => {
10
- const entries = Object.entries(lifecycleMethods || {})
11
-
12
- for (const [lifecycleMethod, fn] of entries) {
13
- const hookName = getApplicationHookName(lifecycleMethod)
14
- application.hook(hookName, fn)
15
- }
16
- })
17
- }
18
-
19
- export default attachPlugins
@@ -1,6 +0,0 @@
1
- import autoEnableAssetsPlugin from '@exodus/auto-enable-assets-plugin'
2
-
3
- import logLifecyclePlugin from './log-lifecycle'
4
- import restorePlugin from './restore'
5
-
6
- export default [logLifecyclePlugin, restorePlugin, autoEnableAssetsPlugin]
@@ -1,25 +0,0 @@
1
- const logLifecycle = {
2
- id: 'logLifecyclePlugin',
3
- type: 'plugin',
4
- factory: ({ logger }) => {
5
- return {
6
- onLock: () => logger.debug('onLock'),
7
- onUnlock: () => logger.debug('onUnlock'),
8
- onClear: () => logger.debug('onClear'),
9
- onImport: () => logger.debug('onImport'),
10
- onMigrate: () => logger.debug('onMigrate'),
11
- onStart: () => logger.debug('onStart'),
12
- onLoad: () => logger.debug('onLoad'),
13
- onUnload: () => logger.debug('onUnload'),
14
- onCreate: () => logger.debug('onCreate'),
15
- onBackup: () => logger.debug('onBackup'),
16
- onRestore: () => logger.debug('onRestore'),
17
- onRestoreCompleted: () => logger.debug('onRestoreCompleted'),
18
- onAssetsSynced: () => logger.debug('onAssetsSynced'),
19
- onChangePassphrase: () => logger.debug('onChangePassphrase'),
20
- }
21
- },
22
- dependencies: ['logger'],
23
- }
24
-
25
- export default logLifecycle
@@ -1,16 +0,0 @@
1
- const restorePlugin = ({ restoreAtom }) => {
2
- return {
3
- onStart: async ({ isRestoring }) => {
4
- await restoreAtom.set(!!isRestoring)
5
- },
6
- onAssetsSynced: async () => {
7
- await restoreAtom.set(false)
8
- },
9
- }
10
- }
11
-
12
- export default {
13
- id: 'restorePlugin',
14
- factory: restorePlugin,
15
- dependencies: ['restoreAtom'],
16
- }
@@ -1,19 +0,0 @@
1
- import { EXODUS_KEY_IDS } from '@exodus/keychain/module'
2
-
3
- const createUnlockEncryptedStorage = ({ keychain }) => {
4
- return async (encryptedStorage) => {
5
- // should the key id be part of a `config` dep?
6
- const sodiumEncryptor = keychain.createSodiumEncryptor(EXODUS_KEY_IDS.WALLET_INFO)
7
-
8
- await encryptedStorage.unlock({
9
- encrypt: (data) => sodiumEncryptor.encryptSecretBox({ data }),
10
- decrypt: (data) => sodiumEncryptor.decryptSecretBox({ data }),
11
- })
12
- }
13
- }
14
-
15
- export default {
16
- id: 'unlockEncryptedStorage',
17
- factory: createUnlockEncryptedStorage,
18
- dependencies: ['keychain'],
19
- }
@@ -1,11 +0,0 @@
1
- export function createLoadWalletAccountsHandler({ port, blockchainMetadata }) {
2
- return async () => {
3
- const [txLogs, accountStates] = await Promise.all([
4
- blockchainMetadata.getLoadedTxLogs(),
5
- blockchainMetadata.getLoadedAccountStates(),
6
- ])
7
-
8
- port.emit('tx-logs', txLogs)
9
- port.emit('account-states', accountStates)
10
- }
11
- }