@exodus/headless 2.0.0-alpha.67 → 2.0.0-alpha.7
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 +0 -486
- package/README.md +4 -133
- package/package.json +19 -51
- package/src/api.js +44 -11
- package/src/application.js +39 -54
- package/src/dependencies/atoms.js +21 -2
- package/src/dependencies/index.js +1 -8
- package/src/dependencies/modules.js +21 -2
- package/src/dependencies/utils.js +4 -0
- package/src/index.js +38 -91
- package/src/ioc.js +6 -32
- package/src/unlock-encrypted-storage.js +1 -3
- package/src/utils/blockchain-metadata.js +48 -0
- package/src/atoms/attach.js +0 -31
- package/src/atoms/base-asset-names-to-monitor.js +0 -38
- package/src/constants.js +0 -38
- package/src/dependencies/plugins.js +0 -7
- package/src/features/available-assets/index.js +0 -15
- package/src/features/balances/index.js +0 -14
- package/src/features/blockchain-metadata/api.js +0 -23
- package/src/features/blockchain-metadata/index.js +0 -20
- package/src/features/blockchain-metadata/plugin.js +0 -31
- package/src/features/blockchain-metadata/utils.js +0 -11
- package/src/features/enabled-assets/api.js +0 -19
- package/src/features/enabled-assets/index.js +0 -26
- package/src/features/enabled-assets/plugin.js +0 -19
- package/src/features/feature-flags/api.js +0 -15
- package/src/features/feature-flags/index.js +0 -37
- package/src/features/feature-flags/plugin.js +0 -19
- package/src/features/fees/index.js +0 -16
- package/src/features/fees/plugin.js +0 -18
- package/src/features/geolocation/index.js +0 -20
- package/src/features/geolocation/plugin.js +0 -15
- package/src/features/locale/api.js +0 -14
- package/src/features/locale/index.js +0 -50
- package/src/features/locale/plugin.js +0 -15
- package/src/features/nfts/api.js +0 -14
- package/src/features/nfts/index.js +0 -33
- package/src/features/nfts/plugin.js +0 -24
- package/src/features/pricing/api.js +0 -15
- package/src/features/pricing/index.js +0 -35
- package/src/features/rates/api.js +0 -13
- package/src/features/rates/index.js +0 -22
- package/src/features/rates/plugin.js +0 -18
- package/src/features/remote-config/api.js +0 -14
- package/src/features/remote-config/index.js +0 -28
- package/src/features/remote-config/plugin.js +0 -21
- package/src/plugins/attach.js +0 -25
- package/src/plugins/index.js +0 -5
- package/src/plugins/log-lifecycle.js +0 -26
package/README.md
CHANGED
|
@@ -2,20 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
The headless Exodus wallet SDK
|
|
4
4
|
|
|
5
|
-
## Table of Contents
|
|
6
|
-
|
|
7
|
-
- [Quick Start](#quick-start)
|
|
8
|
-
- [Lifecycle](#lifecycle)
|
|
9
|
-
- [Port](#port)
|
|
10
|
-
- [Adapters](#adapters)
|
|
11
|
-
- [Config](#config)
|
|
12
|
-
- [Headless API](#headless-api)
|
|
13
|
-
|
|
14
5
|
## Quick Start
|
|
15
6
|
|
|
16
7
|
```js
|
|
17
8
|
import createExodus from '@exodus/headless'
|
|
18
|
-
import referrals from '@exodus/headless/src/modules/referrals'
|
|
19
9
|
import Emitter from '@exodus/wild-emitter'
|
|
20
10
|
|
|
21
11
|
// 1. Create port. Acts as an event bus between headless wallet and client
|
|
@@ -26,10 +16,10 @@ const adapters = {}
|
|
|
26
16
|
const config = {}
|
|
27
17
|
|
|
28
18
|
// 3. Create Exodus container
|
|
29
|
-
const
|
|
19
|
+
const container = createExodus({ port, adapters, config })
|
|
30
20
|
|
|
31
21
|
// 4. Register external modules. Does not support overriding modules at the moment.
|
|
32
|
-
|
|
22
|
+
container.register({
|
|
33
23
|
definition: {
|
|
34
24
|
id: 'remoteConfig',
|
|
35
25
|
factory: createRemoteConfig,
|
|
@@ -37,83 +27,13 @@ exodusContainer.register({
|
|
|
37
27
|
},
|
|
38
28
|
})
|
|
39
29
|
|
|
40
|
-
// see an example feature definition:
|
|
41
|
-
// https://github.com/ExodusMovement/exodus-hydra/blob/2e8d63426421ffcbec84a9b6fbc83eb913b47eba/modules/headless/src/modules/geolocation/index.js
|
|
42
|
-
exodusContainer.use(referrals())
|
|
43
|
-
exodusContainer.use(myCustomFeature({ id: 'myCustomFeature', ... }))
|
|
44
|
-
|
|
45
30
|
// 5. Resolve exodus instance
|
|
46
|
-
const exodus =
|
|
31
|
+
const exodus = container.resolve()
|
|
47
32
|
|
|
48
|
-
// 6.
|
|
49
|
-
await exodus.wallet.start()
|
|
50
|
-
|
|
51
|
-
// 7. Use it!
|
|
33
|
+
// 6. Use it!
|
|
52
34
|
await exodus.wallet.create({ passphrase: 'my-super-secure-passphrase' })
|
|
53
|
-
|
|
54
|
-
// 8. Use your custom feature API, if any
|
|
55
|
-
exodus.myCustomFeature.doThatThingYouDo()
|
|
56
35
|
```
|
|
57
36
|
|
|
58
|
-
## Lifecycle
|
|
59
|
-
|
|
60
|
-
The headless wallet instance transitions through different states during his life. When moving from one another, there are two things that are triggered:
|
|
61
|
-
|
|
62
|
-
- Fires hook call: Allows modules to subscribe and halt transition until listener resolves.
|
|
63
|
-
- Fires event call: Emitted after all hooks had been executed and resolved.
|
|
64
|
-
|
|
65
|
-
Below you can find a state diagram that visualize what hooks are triggered between state transitions:
|
|
66
|
-
|
|
67
|
-
```mermaid
|
|
68
|
-
stateDiagram-v2
|
|
69
|
-
direction LR
|
|
70
|
-
[*] --> Starting
|
|
71
|
-
|
|
72
|
-
state Starting {
|
|
73
|
-
direction LR
|
|
74
|
-
|
|
75
|
-
state "Needs clear storage?*" as NeedsClear
|
|
76
|
-
state "Is importing?" as IsImporting
|
|
77
|
-
|
|
78
|
-
NeedsClear --> Clearing : CLEAR
|
|
79
|
-
Clearing --> IsImporting
|
|
80
|
-
IsImporting --> Importing : IMPORT
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
Starting --> Started : START
|
|
84
|
-
|
|
85
|
-
state Started {
|
|
86
|
-
direction LR
|
|
87
|
-
|
|
88
|
-
state "Has seed?" as HasSeed
|
|
89
|
-
|
|
90
|
-
HasSeed --> Empty : No
|
|
91
|
-
HasSeed --> Locked : Yes
|
|
92
|
-
|
|
93
|
-
Empty --> Locked : CREATE \n---or---\nIMPORT
|
|
94
|
-
|
|
95
|
-
Locked --> Migrating : MIGRATE
|
|
96
|
-
Migrating --> Unlocked : UNLOCK
|
|
97
|
-
Unlocked --> Locked : LOCK
|
|
98
|
-
|
|
99
|
-
Unlocked --> Restarting : DELETE
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
Restarting --> [*] : RESTART
|
|
105
|
-
|
|
106
|
-
Started --> Started : LOAD
|
|
107
|
-
|
|
108
|
-
classDef conditional fill:#ededed,stroke:#c2c2c2,color:#a6a6a6,stroke-width:2;
|
|
109
|
-
|
|
110
|
-
class NeedsClear conditional
|
|
111
|
-
class IsImporting conditional
|
|
112
|
-
class HasSeed conditional
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
\* Wallet needs to clear storage if seed is not present or is restoring a new wallet
|
|
116
|
-
|
|
117
37
|
## Port
|
|
118
38
|
|
|
119
39
|
Event bus between headless wallet and client
|
|
@@ -228,55 +148,6 @@ Currently not used.
|
|
|
228
148
|
|
|
229
149
|
**Returns**: `boolean`
|
|
230
150
|
|
|
231
|
-
## walletAccounts
|
|
232
|
-
|
|
233
|
-
> Type: object
|
|
234
|
-
|
|
235
|
-
| Method | Type | Description |
|
|
236
|
-
| ---------- | ------------------------------------------- | -------------------------------------------------------------- |
|
|
237
|
-
| create | `async (walletAccountFields) => void` | Creates a new WalletAccount with the provided fields. |
|
|
238
|
-
| update | `async (name, walletAccountFields) => void` | Updates an existing WalletAccount with the provided fields. |
|
|
239
|
-
| enable | `async (name) => void` | Enables an existing WalletAccount. |
|
|
240
|
-
| disable | `async (name) => void` | Disables an existing WalletAccount. |
|
|
241
|
-
| getEnabled | `async () => object` | Returns enabled walletAccounts as `{ [name]: WalletAccount }`. |
|
|
242
|
-
|
|
243
|
-
## blockchainMetadata
|
|
244
|
-
|
|
245
|
-
> Type: object
|
|
246
|
-
|
|
247
|
-
| Method | Type | Description |
|
|
248
|
-
| ---------------------- | ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
249
|
-
| getTxLog | `async ({ assetName, walletAccount }) => TxSet` | Get the TxSet for the provided `assetName`/`walletAccount` combination (AssetSource) |
|
|
250
|
-
| getLoadedTxLogs | `async () => object` | Get the all loaded `TxSet`s as a `{ [walletAccount]: { [assetName]: TxSet } } object` |
|
|
251
|
-
| updateTxs | `async ({ assetName: string, walletAccount: string, txs: object[] }) => void` | Add or update txs with updates provided in `txs` |
|
|
252
|
-
| overwriteTxs | `async ({ assetName: string, walletAccount: string, txs: object[], notifyReceivedTxs: ?boolean }) => void` | Overwrite specified txs. |
|
|
253
|
-
| clearTxs | `async ({ assetName: string, walletAccount: string }) => void` | Remove txs for AssetSource. |
|
|
254
|
-
| removeTxs | `async ({ assetName: string, walletAccount: string, txs: object[] }) => void` | Remove provided txs. |
|
|
255
|
-
| getAccountState | `async ({ assetName, walletAccount }) => AccountState` | Get the AccountState for the provided AssetSource |
|
|
256
|
-
| getLoadedAccountStates | `async () => object` | Get the all loaded `AccountState`s as a `{ [walletAccount]: { [assetName]: AccountState } } object` |
|
|
257
|
-
| updateAccountState | `async ({ assetName: string, walletAccount: string, newData: object }) => void` | Update accountState for AssetSource. |
|
|
258
|
-
| removeAccountState | `async ({ assetName: string, walletAccount: string }) => void` | Remove accountState for AssetSource. |
|
|
259
|
-
| batch | `() => Batch` | Create a batch of updates. See [blockchainMetadata](../blockchain-metadata) README for batching details. |
|
|
260
|
-
|
|
261
|
-
## assets
|
|
262
|
-
|
|
263
|
-
> Type: object
|
|
264
|
-
|
|
265
|
-
| Method | Type | Description |
|
|
266
|
-
| ----------------- | ---------------------------------------------------------- | ---------------------------------------------------------------------- |
|
|
267
|
-
| enable | `async (assetNames: string[]) => void` | Enables assets. |
|
|
268
|
-
| disable | `async (assetNames: string[]) => void` | Disables assets. |
|
|
269
|
-
| addAndEnableToken | `async (assetId: string, baseAssetName: string) => string` | Adds and enables a custom token. Returns the created `asset`'s `.name` |
|
|
270
|
-
|
|
271
|
-
## locale
|
|
272
|
-
|
|
273
|
-
> Type: object
|
|
274
|
-
|
|
275
|
-
| Method | Type | Description |
|
|
276
|
-
| ----------- | ---------------------------------- | ------------------------- |
|
|
277
|
-
| setCurrency | `async (currency: string) => void` | Changes current currency. |
|
|
278
|
-
| setLanguage | `async (language: string) => void` | Changes current language. |
|
|
279
|
-
|
|
280
151
|
## subscribe
|
|
281
152
|
|
|
282
153
|
> Type: function
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/headless",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
4
|
-
"description": "The
|
|
5
|
-
"author": "Exodus Movement Inc
|
|
3
|
+
"version": "2.0.0-alpha.7",
|
|
4
|
+
"description": "The headless Exodus wallet SDK",
|
|
5
|
+
"author": "Exodus Movement Inc",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -17,78 +17,46 @@
|
|
|
17
17
|
"src",
|
|
18
18
|
"README.md",
|
|
19
19
|
"CHANGELOG.md",
|
|
20
|
-
"!**/__tests__
|
|
20
|
+
"!**/__tests__",
|
|
21
21
|
"!**/*.test.js"
|
|
22
22
|
],
|
|
23
23
|
"scripts": {
|
|
24
24
|
"lint": "eslint . --ignore-path ../../.gitignore",
|
|
25
25
|
"lint:fix": "yarn lint --fix",
|
|
26
|
-
"test": "jest
|
|
26
|
+
"test": "jest"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@exodus/
|
|
30
|
-
"@exodus/atoms": "^5.2.1",
|
|
31
|
-
"@exodus/auto-enable-assets-plugin": "^4.0.1",
|
|
32
|
-
"@exodus/available-assets": "^2.0.2",
|
|
33
|
-
"@exodus/balances": "^6.0.1",
|
|
29
|
+
"@exodus/atoms": "^2.9.0",
|
|
34
30
|
"@exodus/basic-utils": "^2.0.0",
|
|
35
|
-
"@exodus/blockchain-metadata": "^8.1
|
|
36
|
-
"@exodus/
|
|
37
|
-
"@exodus/dependency-
|
|
38
|
-
"@exodus/dependency-preprocessors": "^2.8.2",
|
|
39
|
-
"@exodus/enabled-assets": "^6.0.2",
|
|
40
|
-
"@exodus/exodus-pricing-client": "^1.2.0",
|
|
41
|
-
"@exodus/feature-flags": "^2.2.0",
|
|
42
|
-
"@exodus/fee-monitors": "^1.0.0",
|
|
31
|
+
"@exodus/blockchain-metadata": "^8.0.1",
|
|
32
|
+
"@exodus/dependency-injection": "^1.2.0",
|
|
33
|
+
"@exodus/dependency-preprocessors": "^2.0.2",
|
|
43
34
|
"@exodus/fetch": "^1.2.1",
|
|
44
|
-
"@exodus/
|
|
45
|
-
"@exodus/
|
|
46
|
-
"@exodus/key-identifier-provider": "^1.1.3",
|
|
47
|
-
"@exodus/keychain": "^4.1.0",
|
|
48
|
-
"@exodus/market-history": "^5.0.0",
|
|
35
|
+
"@exodus/key-identifier-provider": "^1.1.1",
|
|
36
|
+
"@exodus/keychain": "^3.5.0",
|
|
49
37
|
"@exodus/module": "^1.0.0",
|
|
50
|
-
"@exodus/
|
|
51
|
-
"@exodus/
|
|
52
|
-
"@exodus/restore-progress-tracker": "^2.0.0",
|
|
53
|
-
"@exodus/wallet": "^6.3.0",
|
|
54
|
-
"@exodus/wallet-accounts": "^10.1.0",
|
|
38
|
+
"@exodus/wallet": "^6.0.0",
|
|
39
|
+
"@exodus/wallet-accounts": "^8.0.1",
|
|
55
40
|
"@exodus/wallet-compatibility-modes": "^2.0.0",
|
|
56
|
-
"bip39": "
|
|
57
|
-
"
|
|
58
|
-
"lodash": "npm:@exodus/lodash@^4.17.21-exodus.2",
|
|
41
|
+
"bip39": "2.6.0",
|
|
42
|
+
"lodash": "https://registry.yarnpkg.com/@exodus/lodash/-/lodash-4.17.21-exodus.2.tgz",
|
|
59
43
|
"minimalistic-assert": "^1.0.1"
|
|
60
44
|
},
|
|
61
45
|
"devDependencies": {
|
|
62
|
-
"@exodus/ab-testing": "^6.0.0",
|
|
63
|
-
"@exodus/algorand-lib": "^2.0.1",
|
|
64
|
-
"@exodus/algorand-meta": "^1.1.4",
|
|
65
|
-
"@exodus/apy-rates": "^3.0.0",
|
|
66
|
-
"@exodus/bitcoin-lib": "^2.2.1",
|
|
67
46
|
"@exodus/bitcoin-meta": "^1.0.0",
|
|
68
|
-
"@exodus/connected-origins": "^2.0.0",
|
|
69
|
-
"@exodus/crypto-news-monitor": "^3.0.0",
|
|
70
47
|
"@exodus/currency": "^2.2.0",
|
|
71
48
|
"@exodus/ethereum-lib": "^2.22.2",
|
|
72
49
|
"@exodus/ethereum-meta": "^1.0.23",
|
|
73
|
-
"@exodus/kyc": "^4.0.0",
|
|
74
50
|
"@exodus/models": "^8.11.1",
|
|
75
|
-
"@exodus/personal-notes": "^3.3.0",
|
|
76
|
-
"@exodus/referrals": "^6.2.0",
|
|
77
51
|
"@exodus/solana-lib": "^1.3.11",
|
|
78
52
|
"@exodus/solana-meta": "^1.0.2",
|
|
79
|
-
"@exodus/storage-encrypted": "^1.1.
|
|
80
|
-
"@exodus/storage-memory": "^
|
|
81
|
-
"@exodus/top-movers-monitor": "^3.0.0",
|
|
53
|
+
"@exodus/storage-encrypted": "^1.1.1",
|
|
54
|
+
"@exodus/storage-memory": "^1.1.0",
|
|
82
55
|
"@exodus/wild-emitter": "^1.0.0",
|
|
83
56
|
"buffer-json": "^2.0.0",
|
|
84
|
-
"
|
|
85
|
-
"delay": "^5.0.0",
|
|
86
|
-
"eslint": "^8.44.0",
|
|
87
|
-
"eslint-plugin-simple-import-sort": "^7.0.0",
|
|
88
|
-
"events": "^3.3.0",
|
|
57
|
+
"eslint": "^8.33.0",
|
|
89
58
|
"jest": "^29.1.2",
|
|
90
|
-
"nock": "^13.3.1",
|
|
91
59
|
"p-defer": "^4.0.0"
|
|
92
60
|
},
|
|
93
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "8f74e04d3e7d18b5dac7ce2af8438f735c48353f"
|
|
94
62
|
}
|
package/src/api.js
CHANGED
|
@@ -1,23 +1,56 @@
|
|
|
1
1
|
import { validateMnemonic as isMnemonicValid } from 'bip39'
|
|
2
2
|
|
|
3
3
|
const createApi = ({ ioc, port }) => {
|
|
4
|
-
const
|
|
5
|
-
const { remoteConfig } = ioc.getByType('module')
|
|
6
|
-
const { feeMonitors, nftsMonitor } = ioc.getByType('monitor')
|
|
4
|
+
const { passphraseCache } = ioc.getByType('adapter')
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
remoteConfig.stop()
|
|
11
|
-
feeMonitors.stop()
|
|
12
|
-
nftsMonitor?.stop()
|
|
13
|
-
}
|
|
6
|
+
const { application, wallet, walletAccounts, blockchainMetadata } = ioc.getByType('module')
|
|
7
|
+
const { enabledWalletAccountsAtom } = ioc.getByType('atom')
|
|
14
8
|
|
|
15
9
|
return {
|
|
16
|
-
|
|
10
|
+
wallet: {
|
|
11
|
+
exists: () => wallet.exists(),
|
|
12
|
+
load: application.load,
|
|
13
|
+
unload: application.unload,
|
|
14
|
+
create: application.create,
|
|
15
|
+
lock: application.lock,
|
|
16
|
+
unlock: application.unlock,
|
|
17
|
+
import: application.import,
|
|
18
|
+
delete: application.delete,
|
|
19
|
+
getMnemonic: application.getMnemonic,
|
|
20
|
+
setBackedUp: application.setBackedUp,
|
|
21
|
+
changePassphrase: application.changePassphrase,
|
|
22
|
+
restoreFromCurrentPhrase: async ({ passphrase } = {}) => {
|
|
23
|
+
if (!passphrase) passphrase = await passphraseCache.get()
|
|
24
|
+
const mnemonic = await application.getMnemonic({ passphrase })
|
|
25
|
+
|
|
26
|
+
await application.import({ passphrase, mnemonic })
|
|
27
|
+
},
|
|
28
|
+
changeLockTimer: application.changeLockTimer,
|
|
29
|
+
isLocked: () => wallet.isLocked(),
|
|
30
|
+
},
|
|
31
|
+
walletAccounts: {
|
|
32
|
+
create: walletAccounts.create,
|
|
33
|
+
update: walletAccounts.update,
|
|
34
|
+
disable: walletAccounts.disable,
|
|
35
|
+
enable: walletAccounts.enable,
|
|
36
|
+
getEnabled: enabledWalletAccountsAtom.get,
|
|
37
|
+
},
|
|
38
|
+
blockchainMetadata: {
|
|
39
|
+
getTxLog: blockchainMetadata.getTxLog,
|
|
40
|
+
getLoadedTxLogs: blockchainMetadata.getLoadedTxLogs,
|
|
41
|
+
updateTxs: blockchainMetadata.updateTxs,
|
|
42
|
+
overwriteTxs: blockchainMetadata.overwriteTxs,
|
|
43
|
+
clearTxs: blockchainMetadata.clearTxs,
|
|
44
|
+
removeTxs: blockchainMetadata.removeTxs,
|
|
45
|
+
getAccountState: blockchainMetadata.getAccountState,
|
|
46
|
+
getLoadedAccountStates: blockchainMetadata.getLoadedAccountStates,
|
|
47
|
+
updateAccountState: blockchainMetadata.updateAccountState,
|
|
48
|
+
removeAccountState: blockchainMetadata.removeAccountState,
|
|
49
|
+
batch: blockchainMetadata.batch,
|
|
50
|
+
},
|
|
17
51
|
isMnemonicValid,
|
|
18
52
|
subscribe: port.subscribe.bind(port),
|
|
19
53
|
unsubscribe: port.unsubscribe.bind(port),
|
|
20
|
-
stop,
|
|
21
54
|
}
|
|
22
55
|
}
|
|
23
56
|
|
package/src/application.js
CHANGED
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
import ExodusModule from '@exodus/module'
|
|
4
4
|
import assert from 'minimalistic-assert'
|
|
5
5
|
|
|
6
|
-
import { LifecycleHook as Hook } from './constants'
|
|
7
|
-
|
|
8
6
|
// Because we are forced to restart wallet after deleting/importing, we need to store certain flags to persist state between executions
|
|
9
7
|
|
|
10
8
|
// Triggers deletetion logic when wallet starts.
|
|
@@ -19,7 +17,22 @@ const IMPORT_FLAG = 'importFlag'
|
|
|
19
17
|
// Set as true on import method is called, and set to false after restore is completed
|
|
20
18
|
const RESTORE_FLAG = 'restoreFlag'
|
|
21
19
|
|
|
22
|
-
const HOOKS =
|
|
20
|
+
const HOOKS = Object.freeze({
|
|
21
|
+
lock: 'lock',
|
|
22
|
+
unlock: 'unlock',
|
|
23
|
+
clear: 'clear',
|
|
24
|
+
import: 'import',
|
|
25
|
+
migrate: 'migrate',
|
|
26
|
+
start: 'start',
|
|
27
|
+
load: 'load',
|
|
28
|
+
unload: 'unload',
|
|
29
|
+
create: 'create',
|
|
30
|
+
backup: 'backup',
|
|
31
|
+
restore: 'restore',
|
|
32
|
+
'restore-completed': 'restore-completed',
|
|
33
|
+
'assets-synced': 'assets-synced',
|
|
34
|
+
'change-passphrase': 'change-passphrase',
|
|
35
|
+
})
|
|
23
36
|
|
|
24
37
|
class Application extends ExodusModule {
|
|
25
38
|
#hooks = {}
|
|
@@ -37,7 +50,6 @@ class Application extends ExodusModule {
|
|
|
37
50
|
this.#storage = unsafeStorage.namespace('flags')
|
|
38
51
|
|
|
39
52
|
this.#applicationStarted = new Promise((resolve) => (this.#resolveStart = resolve))
|
|
40
|
-
this.setMaxListeners(Number.POSITIVE_INFINITY)
|
|
41
53
|
}
|
|
42
54
|
|
|
43
55
|
start = async () => {
|
|
@@ -56,26 +68,12 @@ class Application extends ExodusModule {
|
|
|
56
68
|
const walletExists = await this.#wallet.exists()
|
|
57
69
|
|
|
58
70
|
if (isImporting || !walletExists) {
|
|
59
|
-
await this.fire(
|
|
71
|
+
await this.fire(HOOKS.clear)
|
|
60
72
|
}
|
|
61
73
|
|
|
62
|
-
if (isImporting) await this.fire(
|
|
63
|
-
|
|
64
|
-
const [hasPassphraseSet, isLocked, isBackedUp, isRestoring] = await Promise.all([
|
|
65
|
-
this.#wallet.hasPassphraseSet(),
|
|
66
|
-
this.#wallet.isLocked(),
|
|
67
|
-
this.#wallet.isBackedUp(),
|
|
68
|
-
this.isRestoring(),
|
|
69
|
-
])
|
|
70
|
-
|
|
71
|
-
await this.fire(Hook.Start, {
|
|
72
|
-
walletExists,
|
|
73
|
-
hasPassphraseSet,
|
|
74
|
-
isLocked,
|
|
75
|
-
isBackedUp,
|
|
76
|
-
isRestoring,
|
|
77
|
-
})
|
|
74
|
+
if (isImporting) await this.fire(HOOKS.import)
|
|
78
75
|
|
|
76
|
+
await this.fire(HOOKS.start)
|
|
79
77
|
await this.#autoUnlock()
|
|
80
78
|
|
|
81
79
|
const locked = await this.#wallet.isLocked()
|
|
@@ -95,7 +93,7 @@ class Application extends ExodusModule {
|
|
|
95
93
|
this.isRestoring(),
|
|
96
94
|
])
|
|
97
95
|
|
|
98
|
-
await this.fire(
|
|
96
|
+
await this.fire(HOOKS.load, {
|
|
99
97
|
walletExists,
|
|
100
98
|
hasPassphraseSet,
|
|
101
99
|
isLocked,
|
|
@@ -106,11 +104,11 @@ class Application extends ExodusModule {
|
|
|
106
104
|
unload = async () => {
|
|
107
105
|
await this.#applicationStarted
|
|
108
106
|
await this.#passphraseCache.scheduleClear()
|
|
109
|
-
await this.fire(
|
|
107
|
+
await this.fire(HOOKS.unload)
|
|
110
108
|
}
|
|
111
109
|
|
|
112
110
|
hook = (hookName, listener) => {
|
|
113
|
-
assert(HOOKS
|
|
111
|
+
assert(HOOKS[hookName], `no such hook: ${hookName}`)
|
|
114
112
|
|
|
115
113
|
if (!this.#hooks[hookName]) {
|
|
116
114
|
this.#hooks[hookName] = []
|
|
@@ -120,18 +118,13 @@ class Application extends ExodusModule {
|
|
|
120
118
|
}
|
|
121
119
|
|
|
122
120
|
fire = async (hookName, params) => {
|
|
123
|
-
assert(HOOKS
|
|
121
|
+
assert(HOOKS[hookName], `no such hook: ${hookName}`)
|
|
124
122
|
this._logger.debug('firing hooks', hookName)
|
|
125
123
|
|
|
126
124
|
const hooks = this.#hooks[hookName] || []
|
|
127
125
|
|
|
128
126
|
for (let i = 0; i < hooks.length; i++) {
|
|
129
|
-
|
|
130
|
-
await hooks[i](params)
|
|
131
|
-
} catch (err) {
|
|
132
|
-
this._logger.error(`application lifecycle hook failed: ${hookName}`, hooks[i], params)
|
|
133
|
-
throw err
|
|
134
|
-
}
|
|
127
|
+
await hooks[i](params)
|
|
135
128
|
}
|
|
136
129
|
|
|
137
130
|
this.emit(hookName, params)
|
|
@@ -143,15 +136,7 @@ class Application extends ExodusModule {
|
|
|
143
136
|
await this.#applicationStarted
|
|
144
137
|
await this.#wallet.create(opts)
|
|
145
138
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
await this.fire(Hook.Create, {
|
|
149
|
-
hasPassphraseSet: !!opts?.passphrase,
|
|
150
|
-
isBackedUp: false,
|
|
151
|
-
isLocked,
|
|
152
|
-
isRestoring: false,
|
|
153
|
-
walletExists: true,
|
|
154
|
-
})
|
|
139
|
+
await this.fire(HOOKS.create, { hasPassphraseSet: !!opts?.passphrase })
|
|
155
140
|
}
|
|
156
141
|
|
|
157
142
|
import = async (opts) => {
|
|
@@ -163,16 +148,16 @@ class Application extends ExodusModule {
|
|
|
163
148
|
|
|
164
149
|
const walletExists = await this.#wallet.exists()
|
|
165
150
|
|
|
166
|
-
const { forceRestart,
|
|
151
|
+
const { forceRestart, ...wallet } = opts
|
|
167
152
|
|
|
168
153
|
await this.#wallet.import(wallet)
|
|
169
154
|
|
|
170
155
|
if (forceRestart || walletExists) {
|
|
171
156
|
await this.#storage.set(IMPORT_FLAG, true)
|
|
172
157
|
|
|
173
|
-
|
|
158
|
+
this.emit('restart', { reason: 'import' })
|
|
174
159
|
} else {
|
|
175
|
-
await this.fire(
|
|
160
|
+
await this.fire(HOOKS.import)
|
|
176
161
|
|
|
177
162
|
this._logger.log('wallet imported')
|
|
178
163
|
}
|
|
@@ -182,7 +167,7 @@ class Application extends ExodusModule {
|
|
|
182
167
|
|
|
183
168
|
setBackedUp = async () => {
|
|
184
169
|
await this.#wallet.setBackedUp()
|
|
185
|
-
await this.fire(
|
|
170
|
+
await this.fire(HOOKS.backup)
|
|
186
171
|
}
|
|
187
172
|
|
|
188
173
|
lock = async (opts) => {
|
|
@@ -191,7 +176,7 @@ class Application extends ExodusModule {
|
|
|
191
176
|
await this.#applicationStarted
|
|
192
177
|
await this.#wallet.lock(opts)
|
|
193
178
|
await this.#passphraseCache.clear()
|
|
194
|
-
await this.fire(
|
|
179
|
+
await this.fire(HOOKS.lock)
|
|
195
180
|
|
|
196
181
|
this._logger.log('locked')
|
|
197
182
|
}
|
|
@@ -200,13 +185,13 @@ class Application extends ExodusModule {
|
|
|
200
185
|
const isRestoring = await this.isRestoring()
|
|
201
186
|
|
|
202
187
|
if (isRestoring) {
|
|
203
|
-
await this.fire(
|
|
188
|
+
await this.fire(HOOKS.restore)
|
|
204
189
|
await this.#storage.delete(RESTORE_FLAG)
|
|
205
190
|
await this.setBackedUp()
|
|
206
|
-
await this.fire(
|
|
191
|
+
await this.fire(HOOKS['restore-completed'])
|
|
207
192
|
}
|
|
208
193
|
|
|
209
|
-
this.fire(
|
|
194
|
+
this.fire(HOOKS['assets-synced'])
|
|
210
195
|
}
|
|
211
196
|
|
|
212
197
|
#autoUnlock = async () => {
|
|
@@ -219,7 +204,7 @@ class Application extends ExodusModule {
|
|
|
219
204
|
this._logger.log('unlocking with cache')
|
|
220
205
|
|
|
221
206
|
await this.#wallet.unlock({ passphrase })
|
|
222
|
-
await this.fire(
|
|
207
|
+
await this.fire(HOOKS.unlock)
|
|
223
208
|
|
|
224
209
|
this.#restoreIfNeeded()
|
|
225
210
|
|
|
@@ -235,8 +220,8 @@ class Application extends ExodusModule {
|
|
|
235
220
|
await this.#applicationStarted
|
|
236
221
|
await this.#wallet.unlock({ passphrase })
|
|
237
222
|
|
|
238
|
-
await this.fire(
|
|
239
|
-
await this.fire(
|
|
223
|
+
await this.fire(HOOKS.migrate)
|
|
224
|
+
await this.fire(HOOKS.unlock)
|
|
240
225
|
|
|
241
226
|
this.#restoreIfNeeded()
|
|
242
227
|
|
|
@@ -251,14 +236,14 @@ class Application extends ExodusModule {
|
|
|
251
236
|
await this.#applicationStarted
|
|
252
237
|
await this.#wallet.changePassphrase({ currentPassphrase, newPassphrase })
|
|
253
238
|
await this.#passphraseCache.set(newPassphrase)
|
|
254
|
-
await this.fire(
|
|
239
|
+
await this.fire(HOOKS['change-passphrase'])
|
|
255
240
|
|
|
256
241
|
this._logger.log('passphrase changed')
|
|
257
242
|
}
|
|
258
243
|
|
|
259
|
-
delete = async (
|
|
244
|
+
delete = async () => {
|
|
260
245
|
await this.#storage.set(DELETE_FLAG, true)
|
|
261
|
-
|
|
246
|
+
this.emit('restart', { reason: 'delete' })
|
|
262
247
|
}
|
|
263
248
|
|
|
264
249
|
changeLockTimer = async ({ ttl }) => {
|
|
@@ -1,5 +1,24 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createInMemoryAtom } from '@exodus/atoms'
|
|
2
|
+
import {
|
|
3
|
+
walletAccountsAtomDefinition,
|
|
4
|
+
enabledWalletAccountsAtomDefinition,
|
|
5
|
+
} from '@exodus/wallet-accounts/atoms'
|
|
6
|
+
import { withType } from './utils'
|
|
2
7
|
|
|
3
|
-
const createAtomDependencies = () =>
|
|
8
|
+
const createAtomDependencies = () =>
|
|
9
|
+
[
|
|
10
|
+
{
|
|
11
|
+
definition: {
|
|
12
|
+
id: 'lockedAtom',
|
|
13
|
+
factory: () => createInMemoryAtom({ defaultValue: true }),
|
|
14
|
+
dependencies: [],
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
definition: walletAccountsAtomDefinition,
|
|
19
|
+
storage: { namespace: 'walletAccounts' },
|
|
20
|
+
},
|
|
21
|
+
{ definition: enabledWalletAccountsAtomDefinition },
|
|
22
|
+
].map(withType('atom'))
|
|
4
23
|
|
|
5
24
|
export default createAtomDependencies
|
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
import assert from 'minimalistic-assert'
|
|
5
5
|
|
|
6
|
+
import createConfigDependencies from './configs'
|
|
6
7
|
import createAdapterDependencies from './adapters'
|
|
7
8
|
import createAtomDependencies from './atoms'
|
|
8
|
-
import createConfigDependencies from './configs'
|
|
9
9
|
import createModuleDependencies from './modules'
|
|
10
|
-
import createPluginDependencies from './plugins'
|
|
11
10
|
import { wrapConstant } from './utils'
|
|
12
11
|
|
|
13
12
|
const adapterKeys = [
|
|
@@ -17,9 +16,6 @@ const adapterKeys = [
|
|
|
17
16
|
'legacyPrivToPub',
|
|
18
17
|
'seedStorage',
|
|
19
18
|
'unsafeStorage',
|
|
20
|
-
'fusion',
|
|
21
|
-
'fetch',
|
|
22
|
-
'freeze',
|
|
23
19
|
]
|
|
24
20
|
|
|
25
21
|
const createDependencies = ({ adapters, config }) => {
|
|
@@ -37,14 +33,11 @@ const createDependencies = ({ adapters, config }) => {
|
|
|
37
33
|
|
|
38
34
|
const adaptersTree = createAdapterDependencies({ adapters, config })
|
|
39
35
|
|
|
40
|
-
const plugins = createPluginDependencies()
|
|
41
|
-
|
|
42
36
|
return []
|
|
43
37
|
.concat(adaptersTree)
|
|
44
38
|
.concat(configs)
|
|
45
39
|
.concat(modules)
|
|
46
40
|
.concat(atoms)
|
|
47
|
-
.concat(plugins)
|
|
48
41
|
.concat(wrapConstant({ id: 'logger', type: 'module', value: logger }))
|
|
49
42
|
}
|
|
50
43
|
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
import { createKeychain } from '@exodus/keychain'
|
|
2
|
+
import walletDefinition from '@exodus/wallet/module'
|
|
3
|
+
import walletAccountsDefinition from '@exodus/wallet-accounts/module'
|
|
4
|
+
import blockchainMetadataDefinition from '@exodus/blockchain-metadata/module'
|
|
1
5
|
import createKeyIdentifierProvider from '@exodus/key-identifier-provider'
|
|
2
6
|
import walletCompatibilityModesDefinition from '@exodus/wallet-compatibility-modes/module'
|
|
3
7
|
|
|
4
8
|
import createApplication from '../application'
|
|
5
|
-
import unlockEncryptedStorageDefinition from '../unlock-encrypted-storage'
|
|
6
9
|
import { withType } from './utils'
|
|
10
|
+
import unlockEncryptedStorageDefinition from '../unlock-encrypted-storage'
|
|
7
11
|
|
|
8
|
-
const createModuleDependencies = (
|
|
12
|
+
const createModuleDependencies = () =>
|
|
9
13
|
[
|
|
10
14
|
{
|
|
11
15
|
definition: {
|
|
@@ -21,10 +25,25 @@ const createModuleDependencies = ({ config }) =>
|
|
|
21
25
|
dependencies: [],
|
|
22
26
|
},
|
|
23
27
|
},
|
|
28
|
+
{
|
|
29
|
+
definition: {
|
|
30
|
+
id: 'keychain',
|
|
31
|
+
factory: createKeychain,
|
|
32
|
+
dependencies: ['legacyPrivToPub'],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
definition: walletDefinition,
|
|
37
|
+
},
|
|
24
38
|
{
|
|
25
39
|
definition: walletCompatibilityModesDefinition,
|
|
26
40
|
},
|
|
27
41
|
{ definition: unlockEncryptedStorageDefinition },
|
|
42
|
+
{ definition: walletAccountsDefinition },
|
|
43
|
+
{
|
|
44
|
+
definition: blockchainMetadataDefinition,
|
|
45
|
+
storage: { namespace: ['blockchain', 'v1'] },
|
|
46
|
+
},
|
|
28
47
|
].map(withType('module'))
|
|
29
48
|
|
|
30
49
|
export default createModuleDependencies
|