@exodus/assets-feature 1.0.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/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # @exodus/assets-feature
2
+
3
+ Assets module, clients and apis
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ yarn add @exodus/assets-feature
9
+ ```
@@ -0,0 +1,210 @@
1
+ import { pickBy } from '@exodus/basic-utils'
2
+ import { isEmpty } from 'lodash'
3
+ import assert from 'minimalistic-assert'
4
+
5
+ class AssetClientInterface {
6
+ #availableAssetNamesAtom
7
+ #walletAccountsAtom
8
+ #enabledWalletAccountsAtom
9
+
10
+ constructor({
11
+ blockchainMetadata,
12
+ wallet,
13
+ walletAccountsAtom,
14
+ enabledWalletAccountsAtom,
15
+ assetsModule,
16
+ availableAssetNamesAtom,
17
+ addressProvider,
18
+ feeMonitors,
19
+ }) {
20
+ this.blockchainMetadata = blockchainMetadata
21
+ this.wallet = wallet
22
+ this.#walletAccountsAtom = walletAccountsAtom
23
+ this.#enabledWalletAccountsAtom = enabledWalletAccountsAtom
24
+ this.assetsModule = assetsModule
25
+ this.addressProvider = addressProvider
26
+ this.feeMonitors = feeMonitors
27
+ this.#availableAssetNamesAtom = availableAssetNamesAtom
28
+ }
29
+
30
+ getTxHistory = async ({ assetName, walletAccount }) => {
31
+ return this.blockchainMetadata.getTxLog({ assetName, walletAccount })
32
+ }
33
+
34
+ async getTxLog({ assetName, walletAccount }) {
35
+ return this.blockchainMetadata.getTxLog({ assetName, walletAccount })
36
+ }
37
+
38
+ async updateTxLogAndNotify(params) {
39
+ return this.updateTxLogAndNotifyBatch(params).commit()
40
+ }
41
+
42
+ updateTxLogAndNotifyBatch = ({
43
+ assetName,
44
+ walletAccount,
45
+ txs,
46
+ batch = this.blockchainMetadata.batch(),
47
+ }) => {
48
+ return batch.updateTxs({ assetName, walletAccount, txs })
49
+ }
50
+
51
+ async getAccountState({ assetName, walletAccount }) {
52
+ return this.blockchainMetadata.getAccountState({ assetName, walletAccount })
53
+ }
54
+
55
+ async updateAccountState(params) {
56
+ return this.updateAccountStateBatch(params).commit()
57
+ }
58
+
59
+ updateAccountStateBatch = ({
60
+ assetName,
61
+ walletAccount,
62
+ newData,
63
+ batch = this.blockchainMetadata.batch(),
64
+ }) => {
65
+ if (!isEmpty(newData)) {
66
+ return batch.updateAccountState({ assetName, walletAccount, newData })
67
+ }
68
+
69
+ return batch
70
+ }
71
+
72
+ removeTxLog = async (params) => {
73
+ return this.removeTxLogBatch(params).commit()
74
+ }
75
+
76
+ removeTxLogBatch = ({
77
+ assetName,
78
+ walletAccount,
79
+ txs,
80
+ batch = this.blockchainMetadata.batch(),
81
+ }) => {
82
+ return batch.removeTxs({ assetName, walletAccount, txs })
83
+ }
84
+
85
+ async getWalletAccounts({ assetName }) {
86
+ // In the future, the list of wallets may be different based on the provided assets
87
+ const asset = this.assetsModule.getAsset(assetName)
88
+ assert(asset, `${assetName} is not supported`)
89
+ return Object.keys(await this.#enabledWalletAccountsAtom.get())
90
+ }
91
+
92
+ async getAssetsForNetwork({ baseAssetName }) {
93
+ const availableAssetNames = new Set(await this.#availableAssetNamesAtom.get())
94
+ return pickBy(
95
+ this.assetsModule.getAssets(),
96
+ (asset) => asset.baseAsset.name === baseAssetName && availableAssetNames.has(asset.name)
97
+ )
98
+ }
99
+
100
+ async getConfirmationsNumber({ assetName }) {
101
+ const baseAsset = this.assetsModule.getAsset(assetName).baseAsset
102
+ return baseAsset.api?.getConfirmationsNumber ? baseAsset.api.getConfirmationsNumber() : 1
103
+ }
104
+
105
+ async updateFeeConfig({ assetName, feeConfig }) {
106
+ await this.feeMonitors.updateFee({ assetName, feeData: feeConfig })
107
+ }
108
+
109
+ async getFeeData({ assetName }) {
110
+ const baseAssetName = this.assetsModule.getAsset(assetName).baseAsset.name
111
+ return this.feeMonitors.getFeeData({ assetName: baseAssetName })
112
+ }
113
+
114
+ // The interface consumer does not need to know the structure of the returned batch object, just
115
+ // that it needs to be passed along wherever operations need to be batched.
116
+ createOperationsBatch = () => this.blockchainMetadata.batch()
117
+
118
+ executeOperationsBatch = async (batch) => batch.commit()
119
+
120
+ getPublicKey = async ({ assetName, walletAccount, addressIndex = 0, chainIndex = 0 }) => {
121
+ const walletAccountInstance = await this.#getWalletAccount(walletAccount)
122
+ return this.wallet.getPublicKey({
123
+ accountIndex: walletAccountInstance.index,
124
+ baseAssetName: assetName,
125
+ addressIndex,
126
+ chainIndex,
127
+ })
128
+ }
129
+
130
+ getAddress = async (opts) => {
131
+ return this.addressProvider.getAddress({
132
+ ...opts,
133
+ walletAccount: await this.#getWalletAccount(opts.walletAccount),
134
+ })
135
+ }
136
+
137
+ getReceiveAddress = async (opts) => {
138
+ const address = await this.getReceiveAddressObject(opts)
139
+ return address.toString()
140
+ }
141
+
142
+ getReceiveAddressObject = async (opts) => {
143
+ return this.addressProvider.getReceiveAddress({
144
+ ...opts,
145
+ walletAccount: await this.#getWalletAccount(opts.walletAccount),
146
+ })
147
+ }
148
+
149
+ getReceiveAddresses = async (opts) => {
150
+ const addresses = await this.addressProvider.getReceiveAddresses({
151
+ ...opts,
152
+ walletAccount: await this.#getWalletAccount(opts.walletAccount),
153
+ })
154
+
155
+ return [...addresses].map((address) => address.toString())
156
+ }
157
+ getChangeAddresses = async (opts) => {
158
+ const addresses = await this.addressProvider.getChangeAddresses({
159
+ ...opts,
160
+ walletAccount: await this.#getWalletAccount(opts.walletAccount),
161
+ })
162
+
163
+ return [...addresses].map((address) => address.toString())
164
+ }
165
+
166
+ #getWalletAccount = async (name) => {
167
+ const walletAccounts = await this.#walletAccountsAtom.get()
168
+ return walletAccounts[name]
169
+ }
170
+
171
+ getSupportedPurposes = async ({ assetName, walletAccount }) => {
172
+ return this.addressProvider.getSupportedPurposes({
173
+ assetName,
174
+ walletAccount: await this.#getWalletAccount(walletAccount),
175
+ })
176
+ }
177
+
178
+ getUnusedAddressIndexes = async ({ assetName, walletAccount }) => {
179
+ return this.addressProvider.getUnusedAddressIndexes({
180
+ assetName,
181
+ walletAccount: await this.#getWalletAccount(walletAccount),
182
+ })
183
+ }
184
+
185
+ saveUnusedAddressIndexes = async () => {
186
+ // no op!! getUnusedAddressIndexes loads from tx log, not from storage
187
+ }
188
+
189
+ signTransaction = async ({ assetName, unsignedTx, walletAccount }) => {
190
+ const accountIndex = (await this.#getWalletAccount(walletAccount)).index
191
+ const baseAssetName = this.assetsModule.getAsset(assetName).baseAsset.name
192
+ return this.wallet.signTransaction({ baseAssetName, unsignedTx, accountIndex })
193
+ }
194
+
195
+ getNextChangeAddress = async ({ assetName, walletAccount }) => {
196
+ return this.addressProvider.getUnusedAddress({
197
+ assetName,
198
+ walletAccount: await this.#getWalletAccount(walletAccount),
199
+ chainIndex: 1,
200
+ })
201
+ }
202
+
203
+ getFeeConfig = async ({ assetName }) => {
204
+ return this.feeMonitors.getFeeData({ assetName })
205
+ }
206
+ }
207
+
208
+ const createAssetClientInterface = (args) => new AssetClientInterface(args)
209
+
210
+ export default createAssetClientInterface
@@ -0,0 +1,19 @@
1
+ import createAssetClientInterface from './asset-client-interface'
2
+
3
+ const assetsClientInterfaceDefinition = {
4
+ id: 'assetClientInterface',
5
+ type: 'module',
6
+ factory: createAssetClientInterface,
7
+ dependencies: [
8
+ 'blockchainMetadata',
9
+ 'wallet',
10
+ 'walletAccountsAtom',
11
+ 'enabledWalletAccountsAtom',
12
+ 'assetsModule',
13
+ 'availableAssetNamesAtom',
14
+ 'addressProvider',
15
+ 'feeMonitors',
16
+ ],
17
+ }
18
+
19
+ export default assetsClientInterfaceDefinition
package/index.js ADDED
@@ -0,0 +1,10 @@
1
+ import assetsClientInterfaceDefinition from './client'
2
+
3
+ const assets = () => {
4
+ return {
5
+ id: 'assets',
6
+ definitions: [{ definition: assetsClientInterfaceDefinition }],
7
+ }
8
+ }
9
+
10
+ export default assets
@@ -0,0 +1,5 @@
1
+ // TODO: ship assets module here in the future
2
+
3
+ const assetsModuleDefinition = {}
4
+
5
+ export default assetsModuleDefinition
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@exodus/assets-feature",
3
+ "version": "1.0.0",
4
+ "license": "UNLICENSED",
5
+ "description": "Assets module, clients and apis",
6
+ "main": "index.js",
7
+ "author": "Exodus Movement Inc.",
8
+ "scripts": {
9
+ "test": "jest",
10
+ "lint": "eslint . --ignore-path ../../.gitignore",
11
+ "lint:fix": "yarn lint --fix"
12
+ },
13
+ "files": [
14
+ "client",
15
+ "module",
16
+ "README.md",
17
+ "CHANGELOG.md",
18
+ "!**/__tests__/**"
19
+ ],
20
+ "homepage": "https://github.com/ExodusMovement/exodus-hydra/tree/master/features/assets-feature",
21
+ "bugs": {
22
+ "url": "https://github.com/ExodusMovement/exodus-hydra/issues?q=is%3Aissue+is%3Aopen+label%3Aassets-feature"
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/ExodusMovement/exodus-hydra.git"
27
+ },
28
+ "dependencies": {
29
+ "@exodus/basic-utils": "^2.1.0",
30
+ "lodash": "^4.17.21",
31
+ "minimalistic-assert": "^1.0.1"
32
+ },
33
+ "devDependencies": {
34
+ "@exodus/available-assets": "^4.0.0",
35
+ "@exodus/models": "^9.1.1",
36
+ "@exodus/storage-memory": "^2.1.0",
37
+ "@exodus/wallet-accounts": "^12.0.2"
38
+ },
39
+ "gitHead": "69a96e03f6c96d7284d98abb832a7b59b58f718b"
40
+ }