@exodus/balances 1.1.2 → 1.2.1

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.
Files changed (2) hide show
  1. package/index.js +62 -42
  2. package/package.json +2 -2
package/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { isNumberUnit } from '@exodus/currency'
2
+ import { TxSet } from '@exodus/models'
2
3
  import ExodusModule from '@exodus/module'
3
4
  import { cloneDeepWith, difference, isEmpty, merge, set, zipObject } from 'lodash'
4
5
  import makeConcurrent from 'make-concurrent'
@@ -41,24 +42,24 @@ class Balances extends ExodusModule {
41
42
 
42
43
  // these share a queue
43
44
  this.#updateAssetSource = shareQueue(this.#updateAssetSource)
45
+ this.#handleTxLogUpdate = shareQueue(this.#handleTxLogUpdate)
44
46
  this.#recompute = shareQueue(this.#recompute)
45
47
 
46
48
  blockchainMetadata.on('loaded', () => {
47
- this.#recompute()
49
+ walletAccountsAtom.observe((payload) =>
50
+ this.#setWalletAccounts(
51
+ Object.keys(payload).filter((walletAccount) => payload[walletAccount].enabled)
52
+ )
53
+ )
48
54
  blockchainMetadata.on('account-state', this.#handleAccountStateUpdate)
49
55
  blockchainMetadata.on('tx-log', this.#handleTxLogUpdate)
50
56
  })
51
57
 
52
- walletAccountsAtom.observe((payload) =>
53
- this.#setWalletAccounts(
54
- Object.keys(payload).filter((walletAccount) => payload[walletAccount].enabled)
55
- )
56
- )
57
-
58
58
  assetsModule.on('assets-add', this.#onAssetsChanged)
59
59
  }
60
60
 
61
61
  #getAsset = (assetName) => this.#assetsModule.getAsset(assetName)
62
+ #getAssets = () => this.#assetsModule.getAssets()
62
63
 
63
64
  #handleAccountStateUpdate = async (opts) => {
64
65
  if (!this.#ready) {
@@ -77,7 +78,8 @@ class Balances extends ExodusModule {
77
78
  })
78
79
  return
79
80
  }
80
- if (this.#isHistoryBasedBalanceAsset(opts.assetName)) return this.#updateAssetSource(opts)
81
+
82
+ return this.#updateAssetSource(opts)
81
83
  }
82
84
 
83
85
  #pushIntoSharedQueue = makeConcurrent((fn) => fn(), { concurrency: 1 })
@@ -90,30 +92,21 @@ class Balances extends ExodusModule {
90
92
 
91
93
  #getBalancesForAssetSource = async ({ walletAccount, assetName }) => {
92
94
  const metadata = await this.#loadBlockchainMetadataForBalance({ walletAccount, assetName })
93
- return this.#getBalancesFromBlockchainMetadata({ assetName, ...metadata })
95
+ return this.#getBalancesFromBlockchainMetadata({
96
+ assetNames: this.#getRelatedAssetNames(assetName),
97
+ ...metadata,
98
+ })
94
99
  }
95
100
 
96
- #getBalancesFromBlockchainMetadata = ({ assetName, accountState, txLog }) => {
101
+ #getBalancesFromBlockchainMetadata = ({ assetNames, accountState, txLogsByAssetName }) => {
97
102
  // in the future accountState may have all the balances and we won't need to rely on txLog
98
103
  // for now, accountState-based balance has both the baseAsset and token balances while txLog is per asset/token
99
104
  const getAssetBalances = (assetName) => {
100
105
  const asset = this.#getAsset(assetName)
106
+ const txLog = txLogsByAssetName[assetName]
101
107
  return asset.api.getBalances({ asset, accountState, txLog })
102
108
  }
103
109
 
104
- if (this.#isHistoryBasedBalanceAsset(assetName)) {
105
- const balances = getAssetBalances(assetName)
106
- return balances
107
- ? {
108
- [assetName]: balances,
109
- }
110
- : {}
111
- }
112
-
113
- const assetNames = [assetName, ...this.#assetsModule.getTokenNames(assetName)].filter(
114
- this.#isSupportedAsset
115
- )
116
-
117
110
  const balances = assetNames.map(getAssetBalances)
118
111
  return zipNonNull(assetNames, balances)
119
112
  }
@@ -161,23 +154,41 @@ class Balances extends ExodusModule {
161
154
  }
162
155
 
163
156
  #isSupportedAsset = (assetName) => !this.#getAsset(assetName).isCombined
164
- #getSupportedAssetNames = () =>
165
- Object.keys(this.#assetsModule.getAssets()).filter(this.#isSupportedAsset)
157
+ #getSupportedAssetNames = () => Object.keys(this.#getAssets()).filter(this.#isSupportedAsset)
166
158
 
167
- #isHistoryBasedBalanceAsset = (assetName) => {
168
- const asset = this.#getAsset(assetName)
169
- return asset.api?.hasFeature('historyBasedBalance')
170
- }
159
+ #getRelatedAssetNames = (assetName) =>
160
+ [assetName, ...this.#assetsModule.getTokenNames(assetName)].filter(this.#isSupportedAsset)
161
+
162
+ #loadBlockchainMetadataForBalance = async ({
163
+ assetName,
164
+ walletAccount,
165
+ accountState: providedAccountState = null,
166
+ txLogsByAssetName: providedTxLogsByAssetName = {},
167
+ }) => {
168
+ const [txLogsByAssetSource, accountState] = await Promise.all([
169
+ this.#blockchainMetadata.getLoadedTxLogs(),
170
+ providedAccountState
171
+ ? Promise.resolve(providedAccountState)
172
+ : this.#blockchainMetadata.getAccountState({
173
+ assetName: this.#getAsset(assetName).baseAsset.name,
174
+ walletAccount,
175
+ }),
176
+ ])
177
+
178
+ const assetNames = this.#getRelatedAssetNames(assetName)
179
+ const txLogsByAssetName = zipObject(
180
+ assetNames,
181
+ assetNames.map(
182
+ (assetName) =>
183
+ providedTxLogsByAssetName[assetName] ||
184
+ txLogsByAssetSource[walletAccount]?.[assetName] ||
185
+ TxSet.EMPTY
186
+ )
187
+ )
171
188
 
172
- #loadBlockchainMetadataForBalance = async ({ assetName, walletAccount, accountState, txLog }) => {
173
189
  return {
174
- accountState:
175
- accountState ||
176
- (await this.#blockchainMetadata.getAccountState({
177
- assetName: this.#getAsset(assetName).baseAsset.name,
178
- walletAccount,
179
- })),
180
- txLog: txLog || (await this.#blockchainMetadata.getTxLog({ assetName, walletAccount })),
190
+ accountState,
191
+ txLogsByAssetName,
181
192
  }
182
193
  }
183
194
 
@@ -194,15 +205,22 @@ class Balances extends ExodusModule {
194
205
  return
195
206
  }
196
207
 
197
- const { accountState, txLog } = await this.#loadBlockchainMetadataForBalance({
208
+ const { accountState, txLogsByAssetName } = await this.#loadBlockchainMetadataForBalance({
198
209
  assetName,
199
210
  walletAccount,
200
211
  accountState: providedAccountState,
201
- txLog: providedTxLog,
212
+ txLogsByAssetName: {
213
+ [assetName]: providedTxLog,
214
+ },
202
215
  })
203
216
 
204
217
  const accountBalances = this.#balances[walletAccount]
205
- const newBalances = this.#getBalancesFromBlockchainMetadata({ assetName, accountState, txLog })
218
+ const newBalances = this.#getBalancesFromBlockchainMetadata({
219
+ assetNames: this.#getRelatedAssetNames(assetName),
220
+ accountState,
221
+ txLogsByAssetName,
222
+ })
223
+
206
224
  const changes = Object.create(null)
207
225
  for (let subAssetName in newBalances) {
208
226
  const { currency } = this.#getAsset(subAssetName)
@@ -234,10 +252,12 @@ class Balances extends ExodusModule {
234
252
  }
235
253
 
236
254
  sync = ({ changes } = {}) => {
237
- this._logger.log('balances updated')
238
-
239
255
  const oldBalances = this.#oldBalances
240
256
  const balances = cloneBalances(this.#balances)
257
+
258
+ if (Object.keys(balances).length === 0) return // wait till `load` finished
259
+
260
+ this._logger.log('balances updated')
241
261
  this.emit('balances', {
242
262
  balances,
243
263
  oldBalances,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/balances",
3
- "version": "1.1.2",
3
+ "version": "1.2.1",
4
4
  "description": "balances",
5
5
  "author": "Exodus Movement Inc",
6
6
  "license": "UNLICENSED",
@@ -31,5 +31,5 @@
31
31
  "@exodus/basic-utils": "^1.0.0",
32
32
  "@exodus/models": "^8.9.0"
33
33
  },
34
- "gitHead": "d23a92b5962eedd5874f0362a6983b7c4b8a3ce4"
34
+ "gitHead": "03c583ee3f8e75c54871f0da68dd15dd336da09b"
35
35
  }