@exodus/ethereum-api 8.76.2 → 8.76.3

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 CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [8.76.3](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.76.2...@exodus/ethereum-api@8.76.3) (2026-06-01)
7
+
8
+ **Note:** Version bump only for package @exodus/ethereum-api
9
+
10
+
11
+
12
+
13
+
6
14
  ## [8.76.2](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.76.1...@exodus/ethereum-api@8.76.2) (2026-05-27)
7
15
 
8
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/ethereum-api",
3
- "version": "8.76.2",
3
+ "version": "8.76.3",
4
4
  "description": "Transaction monitors, fee monitors, RPC with the blockchain node, and other networking code for Ethereum and EVM-based blockchains",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -70,5 +70,5 @@
70
70
  "type": "git",
71
71
  "url": "git+https://github.com/ExodusMovement/assets.git"
72
72
  },
73
- "gitHead": "6c398eaf7bcaecf41b720833f1dae5b8c56b3d57"
73
+ "gitHead": "aac7087b928f14da94a1a071b5abaf0983136c2a"
74
74
  }
@@ -5,10 +5,9 @@ import assert from 'minimalistic-assert'
5
5
  import ms from 'ms'
6
6
 
7
7
  import { EVM_ERROR_REASONS, withErrorReason } from './error-wrapper.js'
8
- import { createEvmServer, createWsGateway, ValidMonitorTypes } from './exodus-eth-server/index.js'
8
+ import { createEvmServer, ValidMonitorTypes } from './exodus-eth-server/index.js'
9
9
  import { createEthereumHooks } from './hooks/index.js'
10
10
  import { ClarityMonitor } from './tx-log/clarity-monitor.js'
11
- import { ClarityMonitorV2 } from './tx-log/clarity-monitor-v2.js'
12
11
  import { ClarityTruncatedHistoryMonitor } from './tx-log/clarity-truncated-history-monitor.js'
13
12
  import { EthereumMonitor } from './tx-log/ethereum-monitor.js'
14
13
  import { EthereumNoHistoryMonitor } from './tx-log/ethereum-no-history-monitor.js'
@@ -284,6 +283,9 @@ export const createHistoryMonitorFactory = ({
284
283
  return (args) => {
285
284
  let monitor
286
285
  switch (monitorType) {
286
+ case 'clarity-v3':
287
+ console.log('clarity-v3 is no longer supported, falling back to clarity-v2')
288
+ // eslint-disable-next-line no-fallthrough
287
289
  case 'clarity':
288
290
  case 'clarity-v2':
289
291
  monitor = new ClarityMonitor({
@@ -306,18 +308,6 @@ export const createHistoryMonitorFactory = ({
306
308
  ...args,
307
309
  })
308
310
  break
309
- case 'clarity-v3':
310
- monitor = new ClarityMonitorV2({
311
- assetClientInterface,
312
- interval: ms(monitorInterval || '5m'),
313
- server,
314
- rpcBalanceAssetNames,
315
- wsGatewayClient: createWsGateway({ uri: wsGatewayUri }),
316
- eip7702Supported,
317
- getBlackListStatus,
318
- ...args,
319
- })
320
- break
321
311
  case 'no-history':
322
312
  monitor = new EthereumNoHistoryMonitor({
323
313
  assetClientInterface,
@@ -1,637 +0,0 @@
1
- import { BaseMonitor } from '@exodus/asset-lib'
2
- import { getAssetAddresses } from '@exodus/ethereum-lib'
3
- import lodash from 'lodash'
4
- import assert from 'minimalistic-assert'
5
-
6
- import WsGateway from '../exodus-eth-server/ws-gateway.js'
7
- import { executeEthLikeFeeMonitorUpdate } from '../fee-utils.js'
8
- import { fromHexToString } from '../number-utils.js'
9
- import {
10
- filterEffects,
11
- getLogItemsFromServerTx,
12
- normalizeTransactionsResponse,
13
- } from './clarity-utils/index.js'
14
- import {
15
- checkPendingTransactions,
16
- excludeUnchangedTokenBalances,
17
- getAllLogItemsByAsset,
18
- getCurrentBlackListStatus,
19
- getCurrentEIP7702Delegation,
20
- getDeriveDataNeededForTick,
21
- getDeriveTransactionsToCheck,
22
- verifyRpcPendingTxStatusBatch,
23
- } from './monitor-utils/index.js'
24
-
25
- const { isEmpty } = lodash
26
-
27
- export class ClarityMonitorV2 extends BaseMonitor {
28
- #wsClient = null
29
- #walletAccountByAddress = new Map()
30
- #walletAccountInfo = new Map()
31
- #rpcBalanceAssetNames = []
32
- constructor({
33
- server,
34
- wsGatewayClient,
35
- rpcBalanceAssetNames,
36
- eip7702Supported,
37
- getBlackListStatus,
38
- config,
39
- ...args
40
- } = {}) {
41
- super(args)
42
- assert(wsGatewayClient instanceof WsGateway, 'expected WsGateway wsGatewayClient')
43
-
44
- this.config = { GAS_PRICE_FROM_WEBSOCKET: true, ...config }
45
- this.server = server
46
- this.#wsClient = wsGatewayClient
47
- this.#rpcBalanceAssetNames = rpcBalanceAssetNames
48
- this.eip7702Supported = eip7702Supported
49
- this.getBlackListStatus = getBlackListStatus
50
- this.getAllLogItemsByAsset = getAllLogItemsByAsset
51
- this.deriveDataNeededForTick = getDeriveDataNeededForTick(this.aci)
52
- this.deriveTransactionsToCheck = getDeriveTransactionsToCheck({
53
- getTxLog: (...args) => this.aci.getTxLog(...args),
54
- })
55
-
56
- this.addHook('before-start', (...args) => this.beforeStart(...args))
57
- this.addHook('after-stop', (...args) => this.afterStop(...args))
58
- }
59
-
60
- setServer(config) {
61
- const uri = config?.server || this.server.defaultUri
62
-
63
- this.#wsClient.on('connected', () => this.subscribeAllWalletAccounts())
64
- this.#wsClient.start()
65
-
66
- if (uri === this.server.uri) {
67
- return
68
- }
69
-
70
- this.server.setURI(uri)
71
- if (this.config.GAS_PRICE_FROM_WEBSOCKET) {
72
- this.server.connectFee()
73
- }
74
- }
75
-
76
- async deriveData({ assetName, walletAccount, tokens }) {
77
- const { ourWalletAddress, currentAccountState } = await this.deriveDataNeededForTick({
78
- assetName,
79
- walletAccount,
80
- })
81
- const transactionsToCheck = await this.deriveTransactionsToCheck({
82
- assetName,
83
- walletAccount,
84
- tokens,
85
- ourWalletAddress,
86
- })
87
-
88
- return {
89
- ourWalletAddress,
90
- currentAccountState,
91
- ...transactionsToCheck,
92
- }
93
- }
94
-
95
- // eslint-disable-next-line no-undef
96
- async checkPendingTransactions(params) {
97
- const { pendingTransactionsToCheck, pendingTransactionsGroupedByAddressAndNonce } =
98
- checkPendingTransactions(params)
99
- const txsToRemove = []
100
- const { walletAccount } = params
101
-
102
- const updateTx = (tx, asset, { error, remove }) => {
103
- if (remove) {
104
- txsToRemove.push({ tx, assetSource: { asset, walletAccount } })
105
- } else {
106
- params.logItemsByAsset[asset].push({
107
- ...tx,
108
- dropped: true,
109
- error,
110
- })
111
- }
112
-
113
- // in case this is an ETH fee tx that has associated ERC20 send txs
114
- const promises = tx.tokens.map(async (assetName) => {
115
- const tokenTxSet = await this.aci.getTxLog({ assetName, walletAccount })
116
- if (remove) {
117
- txsToRemove.push({
118
- tx: tokenTxSet.get(tx.txId),
119
- assetSource: { asset: assetName, walletAccount },
120
- })
121
- } else if (tokenTxSet && tokenTxSet.has(tx.txId)) {
122
- params.logItemsByAsset[assetName].push({
123
- ...tokenTxSet.get(tx.txId),
124
- error,
125
- dropped: true,
126
- })
127
- }
128
- })
129
- return Promise.all(promises)
130
- }
131
-
132
- for (const { tx, assetName, replaced = false } of Object.values(
133
- pendingTransactionsGroupedByAddressAndNonce
134
- )) {
135
- if (replaced) {
136
- await updateTx(tx, assetName, { remove: true })
137
- delete pendingTransactionsToCheck[tx.txId]
138
- }
139
- }
140
-
141
- // Batch verify all pending txs with a single RPC call (skip if refresh)
142
- const txIds = Object.keys(pendingTransactionsToCheck)
143
- const statuses = params.refresh
144
- ? {}
145
- : await verifyRpcPendingTxStatusBatch({
146
- server: this.server,
147
- logger: this.logger,
148
- txIds,
149
- })
150
-
151
- for (const { tx, assetName } of Object.values(pendingTransactionsToCheck)) {
152
- if (params.refresh) {
153
- await updateTx(tx, assetName, { remove: true })
154
- } else {
155
- const txStatus = statuses[tx.txId]
156
- if (txStatus?.status === 'dropped') {
157
- await updateTx(tx, assetName, { error: 'Dropped' })
158
- }
159
- // status === 'confirmed' or 'pending' - tx is fine, wait for Clarity to confirm
160
- }
161
- }
162
-
163
- return { txsToRemove }
164
- }
165
-
166
- async persistSecurityState({ walletAccount, accountState, isBlacklisted, eip7702Delegation }) {
167
- const securityStatePatch = {
168
- ...(isBlacklisted !== undefined && { isBlacklisted }),
169
- ...(eip7702Delegation !== undefined && { eip7702Delegation }),
170
- }
171
-
172
- if (isEmpty(securityStatePatch)) {
173
- return
174
- }
175
-
176
- await this.updateAccountState({
177
- walletAccount,
178
- accountState,
179
- newData: securityStatePatch,
180
- })
181
- }
182
-
183
- async tick({ walletAccount, refresh }) {
184
- await this.subscribeWalletAddresses(walletAccount)
185
-
186
- const walletAccountInfo = this.#walletAccountInfo.get(walletAccount)
187
-
188
- if (!walletAccountInfo) {
189
- return this.logger.warn('walletAccountInfo is empty', { walletAccount })
190
- }
191
-
192
- const { derivedData, tokensByAddress, assets, tokens, assetName } = walletAccountInfo
193
- const { eip7702Delegation, isBlacklisted } = await this.getSecurityAccountState({
194
- derivedData,
195
- walletAccount,
196
- })
197
-
198
- await this.persistSecurityState({
199
- walletAccount,
200
- accountState: derivedData.currentAccountState,
201
- isBlacklisted,
202
- eip7702Delegation,
203
- })
204
-
205
- const accountState = await this.getNewAccountState({
206
- tokens,
207
- currentTokenBalances: derivedData.currentAccountState?.tokenBalances,
208
- ourWalletAddress: derivedData.ourWalletAddress,
209
- })
210
-
211
- const batch = this.aci.createOperationsBatch()
212
- const newData = { ...accountState }
213
- let allTxs = []
214
- let hasNewTxs = false
215
- let historyError
216
-
217
- try {
218
- const response = await this.getHistoryFromServer({ walletAccount, derivedData, refresh })
219
-
220
- ;({ allTxs } = await normalizeTransactionsResponse({
221
- asset: this.asset,
222
- fromAddress: derivedData.ourWalletAddress,
223
- response,
224
- walletAccount,
225
- }))
226
-
227
- hasNewTxs = allTxs.length > 0
228
-
229
- const logItemsByAsset = this.getAllLogItemsByAsset({
230
- getLogItemsFromServerTx,
231
- ourWalletAddress: derivedData.ourWalletAddress,
232
- allTransactionsFromServer: allTxs,
233
- asset: this.asset,
234
- tokensByAddress,
235
- assets,
236
- })
237
-
238
- const { txsToRemove } = await this.checkPendingTransactions({
239
- txlist: allTxs,
240
- walletAccount,
241
- refresh,
242
- logItemsByAsset,
243
- asset: this.asset,
244
- ...derivedData,
245
- })
246
-
247
- this.aci.removeTxLogBatch({
248
- assetName,
249
- walletAccount,
250
- txs: txsToRemove,
251
- batch,
252
- })
253
-
254
- for (const [assetName, txs] of Object.entries(logItemsByAsset)) {
255
- this.aci.updateTxLogAndNotifyBatch({
256
- assetName,
257
- walletAccount,
258
- txs,
259
- refresh,
260
- batch,
261
- })
262
- }
263
-
264
- if (response.cursor) {
265
- newData.clarityCursor = response.cursor
266
- }
267
- } catch (error) {
268
- historyError = error
269
- }
270
-
271
- try {
272
- this.aci.updateAccountStateBatch({
273
- assetName,
274
- walletAccount,
275
- accountState,
276
- newData,
277
- batch,
278
- })
279
-
280
- await this.aci.executeOperationsBatch(batch)
281
- } catch (batchError) {
282
- if (!historyError) throw batchError
283
- this.logger.warn('error persisting account state after history failure', batchError)
284
- }
285
-
286
- if (historyError) {
287
- throw historyError
288
- }
289
-
290
- if (refresh || hasNewTxs) {
291
- const unknownTokenAddresses = this.getUnknownTokenAddresses({
292
- transactions: allTxs,
293
- tokensByAddress,
294
- })
295
- if (unknownTokenAddresses.length > 0) {
296
- this.emit('unknown-tokens', unknownTokenAddresses)
297
- }
298
- }
299
- }
300
-
301
- async processAndFillTransactionsToState({
302
- allTxs,
303
- derivedData,
304
- tokensByAddress,
305
- assets,
306
- tokens,
307
- assetName,
308
- walletAccount,
309
- refresh,
310
- cursor,
311
- }) {
312
- const hasNewTxs = allTxs.length > 0
313
-
314
- const { eip7702Delegation, isBlacklisted } = await this.getSecurityAccountState({
315
- derivedData,
316
- walletAccount,
317
- })
318
-
319
- await this.persistSecurityState({
320
- walletAccount,
321
- accountState: derivedData.currentAccountState,
322
- isBlacklisted,
323
- eip7702Delegation,
324
- })
325
-
326
- const accountState = await this.getNewAccountState({
327
- tokens,
328
- currentTokenBalances: derivedData.currentAccountState?.tokenBalances,
329
- ourWalletAddress: derivedData.ourWalletAddress,
330
- })
331
-
332
- const logItemsByAsset = this.getAllLogItemsByAsset({
333
- getLogItemsFromServerTx,
334
- ourWalletAddress: derivedData.ourWalletAddress,
335
- allTransactionsFromServer: allTxs,
336
- asset: this.asset,
337
- tokensByAddress,
338
- assets,
339
- })
340
-
341
- const { txsToRemove } = await this.checkPendingTransactions({
342
- txlist: allTxs,
343
- walletAccount,
344
- refresh,
345
- logItemsByAsset,
346
- asset: this.asset,
347
- ...derivedData,
348
- })
349
-
350
- const batch = this.aci.createOperationsBatch()
351
-
352
- this.aci.removeTxLogBatch({
353
- assetName,
354
- walletAccount,
355
- txs: txsToRemove,
356
- batch,
357
- })
358
-
359
- for (const [assetName, txs] of Object.entries(logItemsByAsset)) {
360
- this.aci.updateTxLogAndNotifyBatch({
361
- assetName,
362
- walletAccount,
363
- txs,
364
- refresh,
365
- batch,
366
- })
367
- }
368
-
369
- // All updates must go through newData (accountState param is only used for mem merging)
370
- const newData = { ...accountState }
371
-
372
- if (cursor) {
373
- newData.clarityCursor = cursor
374
- }
375
-
376
- this.aci.updateAccountStateBatch({
377
- assetName,
378
- walletAccount,
379
- accountState,
380
- newData,
381
- batch,
382
- })
383
-
384
- await this.aci.executeOperationsBatch(batch)
385
-
386
- if (refresh || hasNewTxs) {
387
- const unknownTokenAddresses = this.getUnknownTokenAddresses({
388
- transactions: allTxs,
389
- tokensByAddress,
390
- })
391
- if (unknownTokenAddresses.length > 0) {
392
- this.emit('unknown-tokens', unknownTokenAddresses)
393
- }
394
- }
395
- }
396
-
397
- async getSecurityAccountState({ derivedData, walletAccount }) {
398
- const shouldCheckBlacklist = this.tickCount[walletAccount] === 0
399
- const eip7702Delegation = await getCurrentEIP7702Delegation({
400
- server: this.server,
401
- address: derivedData.ourWalletAddress,
402
- eip7702Supported: this.eip7702Supported,
403
- currentDelegation: derivedData.currentAccountState?.eip7702Delegation,
404
- logger: this.logger,
405
- })
406
- const isBlacklisted = shouldCheckBlacklist
407
- ? await getCurrentBlackListStatus({
408
- getBlackListStatus: this.getBlackListStatus,
409
- address: derivedData.ourWalletAddress,
410
- currentIsBlacklisted: derivedData.currentAccountState?.isBlacklisted,
411
- logger: this.logger,
412
- })
413
- : undefined
414
-
415
- return { eip7702Delegation, isBlacklisted }
416
- }
417
-
418
- async addSingleTx({ tx, address, cursor }) {
419
- const walletAccounts = this.#walletAccountByAddress.get(address)
420
-
421
- if (!walletAccounts || walletAccounts.length === 0) {
422
- return
423
- }
424
-
425
- for (const walletAccount of walletAccounts) {
426
- const walletAccountInfo = this.#walletAccountInfo.get(walletAccount)
427
-
428
- if (!walletAccountInfo) {
429
- continue
430
- }
431
-
432
- const { derivedData, tokensByAddress, assets, tokens, assetName } = walletAccountInfo
433
-
434
- await this.processAndFillTransactionsToState({
435
- allTxs: [tx],
436
- derivedData,
437
- tokensByAddress,
438
- assets,
439
- tokens,
440
- assetName,
441
- walletAccount,
442
- refresh: false,
443
- cursor,
444
- })
445
- }
446
- }
447
-
448
- async getNewAccountState({ tokens, currentTokenBalances, ourWalletAddress }) {
449
- const asset = this.asset
450
- const newAccountState = Object.create(null)
451
- const balances = await this.getBalances({ tokens, ourWalletAddress })
452
- if (this.#rpcBalanceAssetNames.includes(asset.name)) {
453
- const balance = balances[asset.name]
454
- newAccountState.balance = asset.currency.baseUnit(balance)
455
- }
456
-
457
- const tokenBalancePairs = Object.entries(balances).filter((entry) => entry[0] !== asset.name)
458
- const tokenBalanceEntries = tokenBalancePairs
459
- .map((pair) => {
460
- const token = tokens.find((token) => token.name === pair[0])
461
- const value = token.currency.baseUnit(pair[1] || 0)
462
- return [token.name, value]
463
- })
464
- .filter(Boolean)
465
-
466
- const tokenBalances = excludeUnchangedTokenBalances(currentTokenBalances, tokenBalanceEntries)
467
- if (!isEmpty(tokenBalances)) newAccountState.tokenBalances = tokenBalances
468
- return newAccountState
469
- }
470
-
471
- async getReceiveAddressesByWalletAccount() {
472
- const walletAccounts = await this.aci.getWalletAccounts({ assetName: this.asset.name })
473
- const addressesByAccount = Object.create(null)
474
- for (const walletAccount of walletAccounts) {
475
- addressesByAccount[walletAccount] = await this.aci.getReceiveAddresses({
476
- assetName: this.asset.name,
477
- walletAccount,
478
- useCache: true,
479
- })
480
- }
481
-
482
- return addressesByAccount
483
- }
484
-
485
- async fillAssetsTokensAndData({ walletAccount }) {
486
- const assetName = this.asset.name
487
- const assets = await this.aci.getAssetsForNetwork({ baseAssetName: assetName })
488
- const tokens = Object.values(assets).filter((asset) => assetName !== asset.name)
489
-
490
- const tokensByAddress = tokens.reduce((map, token) => {
491
- const addresses = getAssetAddresses(token)
492
- for (const address of addresses) map.set(address.toLowerCase(), token)
493
- return map
494
- }, new Map())
495
-
496
- const derivedData = await this.deriveData({ assetName, walletAccount, tokens })
497
-
498
- this.#walletAccountInfo.set(walletAccount, {
499
- assets,
500
- tokens,
501
- tokensByAddress,
502
- derivedData,
503
- assetName,
504
- })
505
- }
506
-
507
- async subscribeAllWalletAccounts() {
508
- const addressesByWalletAccount = await this.getReceiveAddressesByWalletAccount()
509
- const entriesAddressesByWalletAccount = Object.entries(addressesByWalletAccount)
510
-
511
- for (const [walletAccount] of entriesAddressesByWalletAccount) {
512
- await this.subscribeWalletAddresses(walletAccount)
513
- }
514
- }
515
-
516
- async subscribeWalletAddresses(walletAccount) {
517
- const addressesByWalletAccount = await this.aci.getReceiveAddresses({
518
- assetName: this.asset.name,
519
- walletAccount,
520
- useCache: true,
521
- })
522
-
523
- const address = addressesByWalletAccount[0].toLowerCase() // Only check m/0/0
524
- await this.fillAssetsTokensAndData({ walletAccount })
525
-
526
- if (!this.#walletAccountByAddress.has(address)) {
527
- this.#walletAccountByAddress.set(address, [])
528
- }
529
-
530
- const walletAccounts = this.#walletAccountByAddress.get(address)
531
-
532
- if (!walletAccounts.includes(walletAccount)) {
533
- walletAccounts.push(walletAccount)
534
- this.#walletAccountByAddress.set(address, walletAccounts)
535
- }
536
-
537
- this.server.connectTransactions({ walletAccount, address })
538
-
539
- this.#wsClient.subscribeWalletAddresses({
540
- network: this.asset.name,
541
- addresses: [address],
542
- })
543
- }
544
-
545
- async getBalances({ tokens, ourWalletAddress }) {
546
- const batch = Object.create(null)
547
- if (this.#rpcBalanceAssetNames.includes(this.asset.name)) {
548
- const request = this.server.getBalanceRequest(ourWalletAddress)
549
- batch[this.asset.name] = request
550
- }
551
-
552
- for (const token of tokens) {
553
- if (this.#rpcBalanceAssetNames.includes(token.name) && token.contract.address) {
554
- const request = this.server.balanceOfRequest(ourWalletAddress, token.contract.address)
555
- batch[token.name] = request
556
- }
557
- }
558
-
559
- const pairs = Object.entries(batch)
560
- if (pairs.length === 0) {
561
- return {}
562
- }
563
-
564
- const requests = pairs.map((pair) => pair[1])
565
- const responses = await this.server.sendBatchRequest(requests)
566
- const entries = pairs.map((pair, idx) => {
567
- const balanceHex = responses[idx]
568
- const name = pair[0]
569
- const balance = fromHexToString(balanceHex)
570
- return [name, balance]
571
- })
572
- return Object.fromEntries(entries)
573
- }
574
-
575
- getUnknownTokenAddresses({ transactions, tokensByAddress }) {
576
- const set = transactions.reduce((acc, txn) => {
577
- const transfers = filterEffects(txn.effects, 'erc20') || []
578
- transfers.forEach((transfer) => {
579
- const addr = transfer.address.toLowerCase()
580
- if (!tokensByAddress.has(addr)) {
581
- acc.add(addr)
582
- }
583
- })
584
- return acc
585
- }, new Set())
586
- return [...set]
587
- }
588
-
589
- // NOTE: Here, fetchedGasPrices is the result of a call to `ClarityMonitor.getFee()`.
590
- async updateGasPrice(fetchedGasPrices) {
591
- try {
592
- await executeEthLikeFeeMonitorUpdate({
593
- assetClientInterface: this.aci,
594
- feeAsset: this.asset,
595
- fetchedGasPrices,
596
- })
597
- } catch (e) {
598
- this.logger.warn('error updating gasPrice', e)
599
- }
600
- }
601
-
602
- async onFeeUpdated(fee) {
603
- return this.updateGasPrice(fee)
604
- }
605
-
606
- async beforeStart() {
607
- this.listenToServerEvents()
608
- if (this.config.GAS_PRICE_FROM_WEBSOCKET) {
609
- this.server.connectFee()
610
- }
611
- }
612
-
613
- async afterStop() {
614
- this.server.dispose()
615
- this.#wsClient.dispose(this.asset.name)
616
- }
617
-
618
- async getHistoryFromServer({ walletAccount, derivedData, refresh }) {
619
- const address = derivedData.ourWalletAddress
620
- const currentCursor = derivedData.currentAccountState?.clarityCursor
621
- const cursor = currentCursor && !refresh ? currentCursor : null
622
- return this.server.getAllTransactions({ walletAccount, address, cursor })
623
- }
624
-
625
- listenToServerEvents() {
626
- this.server.on('feeUpdated', (...args) => this.onFeeUpdated(...args))
627
- this.#wsClient.on(
628
- `${this.asset.name}:new_transaction`,
629
- async ({ transaction, address, cursor }) =>
630
- this.addSingleTx({
631
- tx: transaction,
632
- address,
633
- cursor,
634
- })
635
- )
636
- }
637
- }