@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 +9 -0
- package/client/asset-client-interface.js +210 -0
- package/client/index.js +19 -0
- package/index.js +10 -0
- package/module/index.js +5 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -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
|
package/client/index.js
ADDED
|
@@ -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
package/module/index.js
ADDED
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
|
+
}
|