@exodus/ethereum-api 9.0.0-alpha.3 → 9.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.
Files changed (143) hide show
  1. package/CHANGELOG.md +2121 -0
  2. package/LICENSE +7 -0
  3. package/README.md +124 -0
  4. package/package.json +34 -33
  5. package/src/address-has-history.js +6 -2
  6. package/src/allowance/constants.js +4 -5
  7. package/src/allowance/index.js +159 -40
  8. package/src/check-tx/create-assess-transaction.js +23 -0
  9. package/src/check-tx/create-check-tx.js +104 -0
  10. package/src/check-tx/index.js +1 -0
  11. package/src/create-asset-plugin-factory.js +115 -0
  12. package/src/create-asset-utils.js +520 -0
  13. package/src/create-asset.js +272 -97
  14. package/src/create-token-factory.js +47 -17
  15. package/src/custom-fees.js +57 -0
  16. package/src/eip7702-whitelist.js +62 -0
  17. package/src/ens/index.js +12 -17
  18. package/src/error-wrapper.js +383 -0
  19. package/src/eth-like-util.js +172 -33
  20. package/src/exodus-eth-server/api-coin-nodes.js +27 -196
  21. package/src/exodus-eth-server/api.js +23 -14
  22. package/src/exodus-eth-server/clarity-v2.js +255 -0
  23. package/src/exodus-eth-server/clarity.js +67 -265
  24. package/src/exodus-eth-server/errors.js +40 -0
  25. package/src/exodus-eth-server/eth-like-server.js +385 -0
  26. package/src/exodus-eth-server/fetch-json.js +48 -0
  27. package/src/exodus-eth-server/index.js +77 -0
  28. package/src/exodus-eth-server/utils.js +31 -0
  29. package/src/exodus-eth-server/ws-gateway.js +306 -0
  30. package/src/exodus-eth-server/ws.js +1 -2
  31. package/src/fee-data/EthLikeFeeData.js +81 -0
  32. package/src/fee-data/index.js +54 -0
  33. package/src/fee-utils.js +229 -0
  34. package/src/gas-estimation.js +183 -66
  35. package/src/get-balance-for-address.js +1 -1
  36. package/src/get-balances.js +285 -27
  37. package/src/get-fee.js +92 -56
  38. package/src/get-historical-balance.js +58 -0
  39. package/src/hooks/index.js +1 -1
  40. package/src/hooks/monitor.js +182 -43
  41. package/src/hooks/staking-freshness.js +58 -0
  42. package/src/index.js +118 -12
  43. package/src/move-funds.js +153 -0
  44. package/src/multicall3/index.js +212 -0
  45. package/src/multisig-address.js +146 -0
  46. package/src/nft-utils.js +60 -0
  47. package/src/number-utils.js +34 -2
  48. package/src/optimism-gas/index.js +13 -5
  49. package/src/send-validations.js +58 -0
  50. package/src/server-based-fee-monitor.js +12 -19
  51. package/src/simulate-tx/fetch-tx-preview.js +0 -2
  52. package/src/simulate-tx/index.js +2 -2
  53. package/src/simulate-tx/simulate-eth-tx.js +24 -11
  54. package/src/simulation/common.js +34 -0
  55. package/src/simulation/create-simulate-message.js +49 -0
  56. package/src/simulation/create-simulate-transactions.js +108 -0
  57. package/src/simulation/estimate-fee.js +14 -0
  58. package/src/simulation/estimate-simple-transfer.js +15 -0
  59. package/src/simulation/get-message-type.js +18 -0
  60. package/src/simulation/simulate-message-api.js +68 -0
  61. package/src/simulation/simulate-transactions-api.js +266 -0
  62. package/src/simulation/simulate-transactions.js +16 -0
  63. package/src/simulation/transactions.js +52 -0
  64. package/src/simulation/try-estimating-changes-locally.js +26 -0
  65. package/src/staking/api/index.js +43 -0
  66. package/src/staking/cached-read.js +33 -0
  67. package/src/staking/ethereum/api.js +166 -34
  68. package/src/staking/ethereum/deps.js +37 -0
  69. package/src/staking/ethereum/everstake.js +113 -0
  70. package/src/staking/ethereum/index.js +4 -3
  71. package/src/staking/ethereum/service.js +682 -181
  72. package/src/staking/ethereum/staking-utils.js +275 -4
  73. package/src/staking/fantom-staking.js +9 -9
  74. package/src/staking/index.js +4 -4
  75. package/src/staking/matic/addresses.js +2 -0
  76. package/src/staking/matic/api.js +69 -49
  77. package/src/staking/matic/index.js +3 -3
  78. package/src/staking/matic/matic-staking-utils.js +243 -5
  79. package/src/staking/matic/matic-staking.md +53 -0
  80. package/src/staking/staking-provider-client.js +1 -1
  81. package/src/staking/utils/index.js +39 -0
  82. package/src/tx-create.js +666 -0
  83. package/src/tx-log/clarity-monitor.js +273 -103
  84. package/src/tx-log/clarity-truncated-history-monitor.js +109 -0
  85. package/src/tx-log/clarity-truncated-history-monitor.md +219 -0
  86. package/src/tx-log/clarity-utils/absolute.js +96 -0
  87. package/src/tx-log/clarity-utils/get-log-items-from-server-tx.js +94 -31
  88. package/src/tx-log/clarity-utils/get-names-of-tokens-transferred-by-server-tx.js +3 -2
  89. package/src/tx-log/clarity-utils/index.js +9 -3
  90. package/src/tx-log/clarity-utils/is-spam-pending-tx.js +13 -0
  91. package/src/tx-log/clarity-utils/normalize-transactions-response.js +65 -0
  92. package/src/tx-log/ethereum-monitor.js +93 -47
  93. package/src/tx-log/ethereum-no-history-monitor.js +52 -41
  94. package/src/tx-log/get-optimistic-txlog-effects.js +379 -0
  95. package/src/tx-log/index.js +5 -3
  96. package/src/tx-log/monitor-utils/check-pending-transactions.js +14 -5
  97. package/src/tx-log/monitor-utils/exclude-unchanged-token-balances.js +1 -1
  98. package/src/tx-log/monitor-utils/extract-balance-from-clarity-account-info.js +108 -0
  99. package/src/tx-log/monitor-utils/get-balance-updates.js +44 -0
  100. package/src/tx-log/monitor-utils/get-batched-rpc-balances.js +47 -0
  101. package/src/tx-log/monitor-utils/get-current-blacklist-status.js +38 -0
  102. package/src/tx-log/monitor-utils/get-current-eip7702-delegation.js +79 -0
  103. package/src/tx-log/monitor-utils/get-derive-transactions-to-check.js +10 -5
  104. package/src/tx-log/monitor-utils/get-fee-amount.js +1 -1
  105. package/src/tx-log/monitor-utils/get-history-from-server.js +1 -1
  106. package/src/tx-log/monitor-utils/get-log-items-from-server-tx.js +75 -33
  107. package/src/tx-log/monitor-utils/get-names-of-tokens-transferred-by-server-tx.js +3 -2
  108. package/src/tx-log/monitor-utils/get-raw-transfer-amount.js +29 -0
  109. package/src/tx-log/monitor-utils/get-transfers-by-token-name.js +3 -2
  110. package/src/tx-log/monitor-utils/get-value-of-transfers.js +10 -12
  111. package/src/tx-log/monitor-utils/index.js +12 -7
  112. package/src/tx-log/monitor-utils/is-unverifiable-pending-tx-expired.js +19 -0
  113. package/src/tx-log/monitor-utils/verify-pending-tx-status-rpc.js +90 -0
  114. package/src/tx-log-staking-processor/asset-staking-tx-data.js +82 -24
  115. package/src/tx-log-staking-processor/index.js +28 -14
  116. package/src/tx-log-staking-processor/utils.js +21 -20
  117. package/src/tx-send/broadcast-error-handler.js +63 -0
  118. package/src/tx-send/index.js +1 -2
  119. package/src/tx-send/nonce-utils.js +97 -0
  120. package/src/tx-send/tx-send.js +94 -288
  121. package/src/tx-sign/index.js +17 -0
  122. package/src/tx-type/index.js +280 -0
  123. package/src/watch-tx.js +36 -0
  124. package/src/web3/createSimulateMessage.js +3 -2
  125. package/src/web3/createSimulateTransactions.js +11 -0
  126. package/src/web3/index.js +3 -1
  127. package/src/etherscan/account.js +0 -49
  128. package/src/etherscan/index.js +0 -28
  129. package/src/etherscan/logs.js +0 -16
  130. package/src/etherscan/proxy.js +0 -47
  131. package/src/etherscan/request.js +0 -26
  132. package/src/etherscan/ws.js +0 -88
  133. package/src/exodus-eth-server/server-factory.js +0 -28
  134. package/src/exodus-eth-server/server-map.js +0 -21
  135. package/src/get-fee-async.js +0 -97
  136. package/src/staking/matic/service.js +0 -437
  137. package/src/staking-api.js +0 -5
  138. package/src/tx-log/clarity-utils/get-derive-data-needed-for-tick.js +0 -12
  139. package/src/tx-log-staking-processor/get-asset-tx-amount.js +0 -26
  140. package/src/tx-send/get-fee-info.js +0 -41
  141. package/src/websocket/index.android.js +0 -2
  142. package/src/websocket/index.ios.js +0 -2
  143. package/src/websocket/index.js +0 -21
@@ -1,319 +1,125 @@
1
- /* eslint-disable @exodus/export-default/last */
2
-
3
- import { getNonce, transactionExists } from '../eth-like-util'
4
- import {
5
- calculateBumpedGasPrice,
6
- isToken as checkIsToken,
7
- normalizeTxId,
8
- } from '@exodus/ethereum-lib'
1
+ import { parseUnsignedTx, updateNonce } from '@exodus/ethereum-lib'
2
+ import { safeString } from '@exodus/safe-string'
9
3
  import assert from 'minimalistic-assert'
10
- import getFeeInfo from './get-fee-info'
11
4
 
12
- const txSendFactory = ({ assetClientInterface, createUnsignedTx }) => {
13
- assert(assetClientInterface, 'assetClientInterface is required')
14
- assert(createUnsignedTx, 'createUnsignedTx is required')
15
- return async ({
16
- asset,
17
- walletAccount,
18
- amount,
19
- address,
20
- feeAmount,
21
- shouldLog = true,
22
- keepTxInput,
23
- txInput,
24
- nonce: _nonce,
25
- bumpTxId,
26
- customFee,
27
- isSendAll,
28
- isExchange,
29
- feeOpts: feeOpts_ = {},
30
- }) => {
31
- const assetName = asset.name
32
- const baseAsset = asset.baseAsset
33
- const feeOpts = { ...feeOpts_ }
34
- const assets = await assetClientInterface.getAssetsForNetwork({ baseAssetName: baseAsset.name })
35
-
36
- // Using a default zero value to not break code relying on the `tx.feeAmount` property.
37
- // For example, some exchange providers don't supply this.
38
- if (!feeAmount) {
39
- feeAmount = asset.baseAsset.currency.ZERO
40
- }
5
+ import { getOptimisticTxLogEffects } from '../tx-log/index.js'
6
+ import { signTx } from '../tx-sign/index.js'
7
+ import { ARBITRARY_ADDRESS } from '../tx-type/index.js'
8
+ import { handleBroadcastError } from './broadcast-error-handler.js'
41
9
 
42
- const fromAddress = await assetClientInterface.getReceiveAddress({
43
- assetName: baseAsset.name,
44
- walletAccount,
45
- })
46
-
47
- let nonceParam = _nonce
10
+ const txSendFactory = ({ assetClientInterface, createTx }) => {
11
+ assert(assetClientInterface, 'assetClientInterface is required')
12
+ assert(createTx, 'createTx is required')
48
13
 
49
- const feeData = await assetClientInterface.getFeeData({
50
- assetName: baseAsset.name,
51
- })
14
+ return async ({ asset, walletAccount, unsignedTx: providedUnsignedTx, ...legacyParams }) => {
15
+ const baseAsset = asset.baseAsset
52
16
 
53
- let eip1559Enabled = feeData.eip1559Enabled
17
+ const { unsignedTx } = providedUnsignedTx
18
+ ? { unsignedTx: providedUnsignedTx }
19
+ : await createTx({ asset, walletAccount, ...legacyParams })
54
20
 
55
- // `replacedTx` is always an ETH/ETC transaction (not a token)
56
- let replacedTx, replacedTokenTx
57
- if (bumpTxId) {
58
- const baseAssetTxLog = await assetClientInterface.getTxLog({
59
- assetName: baseAsset.name,
60
- walletAccount,
61
- })
62
- replacedTx = baseAssetTxLog.get(bumpTxId)
63
- if (!replacedTx || !replacedTx.pending) {
64
- throw new Error(`Cannot bump transaction ${bumpTxId}: not found or confirmed`)
65
- }
21
+ const parsedTx = parseUnsignedTx({ asset, unsignedTx })
66
22
 
67
- if (replacedTx.tokens.length > 0) {
68
- const tokenTxSet = await assetClientInterface.getTxLog({
69
- assetName: replacedTx.tokens[0],
70
- walletAccount,
71
- })
72
- replacedTokenTx = tokenTxSet.get(bumpTxId)
23
+ // unknown data from buffer...
24
+ const to = parsedTx.to
25
+ const fromAddress = unsignedTx.txMeta.fromAddress
73
26
 
74
- if (replacedTokenTx) {
75
- asset = assets[replacedTx.tokens[0]]
76
- }
77
- }
27
+ assert(
28
+ to?.toLowerCase() !== ARBITRARY_ADDRESS,
29
+ `The receiving wallet address must not be ${ARBITRARY_ADDRESS}`
30
+ )
78
31
 
79
- address = (replacedTokenTx || replacedTx).to
80
- amount = (replacedTokenTx || replacedTx).coinAmount.negate()
81
- feeOpts.gasLimit = replacedTx.data.gasLimit
82
-
83
- const { gasPrice: currentGasPrice } = feeData
84
- const { bumpedGasPrice, bumpedTipGasPrice } = calculateBumpedGasPrice({
85
- baseAsset,
86
- tx: replacedTx,
87
- currentGasPrice,
88
- eip1559Enabled,
89
- })
90
- feeOpts.gasPrice = bumpedGasPrice
91
- feeOpts.tipGasPrice = bumpedTipGasPrice
92
- eip1559Enabled = feeData.eip1559Enabled && feeOpts.tipGasPrice
93
- nonceParam = replacedTx.data.nonce
94
- txInput = replacedTokenTx ? null : replacedTx.data.data || '0x'
95
- feeAmount = feeOpts.gasPrice.mul(feeOpts.gasLimit)
96
- if (nonceParam === undefined) {
97
- throw new Error(`Cannot bump transaction ${bumpTxId}: data object seems to be corrupted`)
98
- }
99
- }
100
-
101
- const createTxParams = {
102
- assetClientInterface,
32
+ // Are there any signin-level errors that should be caught here?
33
+ let { txId, rawTx } = await signTx({
103
34
  asset,
35
+ assetClientInterface,
36
+ unsignedTx,
104
37
  walletAccount,
105
- toAddress: address,
106
- amount,
107
- nonce: nonceParam,
108
- fromAddress,
109
- eip1559Enabled,
110
- customFee,
111
- feeOpts,
112
- txInput,
113
- keepTxInput,
114
- isSendAll,
115
- isExchange,
116
- createUnsignedTx,
117
- }
118
- let { txId, rawTx, nonce, gasLimit, tipGasPrice } = await createTx(createTxParams)
38
+ })
119
39
 
120
40
  try {
121
41
  await baseAsset.api.broadcastTx(rawTx.toString('hex'))
122
42
  } catch (err) {
123
- const nonceTooLowErr = err.message.match(/nonce (is |)too low/i)
124
- const txAlreadyExists = nonceTooLowErr
125
- ? await transactionExists({ asset, txId })
126
- : err.message.match(/already known/i)
127
-
128
- if (txAlreadyExists) {
129
- console.info('tx already broadcast') // inject logger factory from platform
130
- } else if (bumpTxId || !nonceTooLowErr) {
131
- throw err
132
- } else if (nonceTooLowErr) {
133
- console.info('trying to send again...') // inject logger factory from platform
134
- // let's try to fix the nonce issue
135
- nonce = await getNonce({ asset: baseAsset, address: fromAddress })
136
- ;({ txId, rawTx } = await createTx({ ...createTxParams, nonce }))
137
- await baseAsset.api.broadcastTx(rawTx.toString('hex'))
138
- }
139
- }
140
-
141
- const selfSend = fromAddress === address
142
-
143
- await assetClientInterface.updateTxLogAndNotify({
144
- assetName: asset.name,
145
- walletAccount,
146
- txs: [
147
- {
148
- txId,
149
- confirmations: 0,
150
- coinAmount: selfSend ? asset.currency.ZERO : amount.abs().negate(),
151
- coinName: asset.name,
152
- feeAmount,
153
- feeCoinName: asset.feeAsset.name,
154
- selfSend,
155
- to: address,
156
- currencies: {
157
- [assetName]: asset.currency,
158
- [asset.feeAsset.name]: asset.feeAsset.currency,
159
- },
160
- data: eip1559Enabled
161
- ? {
162
- gasLimit,
163
- replacedTxId: bumpTxId,
164
- nonce,
165
- ...(tipGasPrice
166
- ? { tipGasPrice: tipGasPrice.toBaseString() }
167
- : Object.create(null)),
168
- }
169
- : { gasLimit, replacedTxId: bumpTxId, nonce },
170
- },
171
- ],
172
- })
173
-
174
- const isToken = checkIsToken(asset)
175
- if (isToken) {
176
- await assetClientInterface.updateTxLogAndNotify({
177
- assetName: baseAsset.name,
178
- walletAccount,
179
- txs: [
180
- {
181
- txId,
182
- coinAmount: baseAsset.currency.ZERO,
183
- coinName: baseAsset.name,
184
- feeAmount,
185
- feeCoinName: baseAsset.name,
186
- selfSend,
187
- to: address,
188
- token: asset.name,
189
- currencies: {
190
- [baseAsset.name]: baseAsset.currency,
191
- [asset.feeAsset.name]: asset.feeAsset.currency,
192
- },
193
- data: eip1559Enabled
194
- ? {
195
- gasLimit,
196
- replacedTxId: bumpTxId,
197
- nonce,
198
- ...(tipGasPrice ? { tipGasPrice: tipGasPrice.toBaseString() } : {}),
199
- }
200
- : { gasLimit, replacedTxId: bumpTxId, nonce },
201
- },
202
- ],
43
+ const isBumpTx = !!unsignedTx.txMeta.bumpTxId
44
+ const { shouldRetry } = await handleBroadcastError(err, {
45
+ asset,
46
+ txId,
47
+ isHardware: !!unsignedTx.txMeta.isHardware,
48
+ hint: isBumpTx ? safeString`bumpTx` : safeString`broadcastTx`,
49
+ isBumpTx,
203
50
  })
204
- }
205
-
206
- return { txId }
207
- }
208
- }
209
51
 
210
- const createTx = async ({
211
- assetClientInterface,
212
- asset,
213
- walletAccount,
214
- toAddress,
215
- amount,
216
- nonce,
217
- txInput,
218
- eip1559Enabled = true,
219
- keepTxInput = false,
220
- customFee: customGasPrice,
221
- isSendAll,
222
- isExchange,
223
- fromAddress,
224
- feeOpts,
225
- createUnsignedTx,
226
- }) => {
227
- const isToken = checkIsToken(asset)
52
+ if (shouldRetry) {
53
+ console.debug('trying to send again...') // inject logger factory from platform
228
54
 
229
- if (txInput && isToken && !keepTxInput)
230
- throw new Error(`Additional data for Ethereum Token (${asset.name}) is not allowed`)
231
-
232
- txInput =
233
- isToken && !keepTxInput
234
- ? asset.contract.transfer.build(toAddress.toLowerCase(), amount.toBaseString())
235
- : txInput
55
+ // let's try to fix the nonce issue
56
+ let newNonce = await baseAsset.getNonce({
57
+ asset,
58
+ fromAddress,
59
+ walletAccount,
60
+ forceFromNode: true,
61
+ })
236
62
 
237
- let { gasLimit, gasPrice, tipGasPrice } = await getFeeInfo({
238
- assetClientInterface,
239
- asset,
240
- fromAddress,
241
- toAddress,
242
- amount,
243
- isExchange,
244
- txInput,
245
- feeOpts,
246
- })
63
+ const triedNonce = parsedTx.nonce
64
+ // Defensive: avoid retrying the same nonce if node nonce is stale (non-replacement sends only).
65
+ if (!isBumpTx && typeof triedNonce === 'number') {
66
+ newNonce = Math.max(newNonce, triedNonce + 1)
67
+ }
247
68
 
248
- if (eip1559Enabled) {
249
- if (customGasPrice) {
250
- gasPrice = customGasPrice // aka maxFeePerGas
69
+ // NOTE: An `unsignedTx.txData.transactionBuffer` may be optional
70
+ // in `unsignedTx`, since a `providedUnsignedTx` may be
71
+ // truthy but composed only of `legacyParams`:
72
+ // https://github.com/ExodusMovement/assets/blob/4e3e873e3f5bfa8fce36f60be7d95a3dba9546e4/ethereum/ethereum-lib/src/unsigned-tx/parse-unsigned-tx.js#L104C5-L104C6
73
+ //
74
+ // TODO: should return an unsignedTx -> i.e. completely replicate the transaction
75
+ if (unsignedTx.txData.transactionBuffer) {
76
+ // eslint-disable-next-line @exodus/hydra/no-param-reassign-prop-only
77
+ unsignedTx.txData.transactionBuffer = updateNonce({
78
+ chainId: baseAsset.chainId,
79
+ newNonce,
80
+ unsignedTx,
81
+ })
82
+ } else {
83
+ // eslint-disable-next-line @exodus/hydra/no-param-reassign-prop-only
84
+ unsignedTx.txData.nonce = newNonce
85
+ }
251
86
 
252
- // We must ensure maxPriorityFeePerGas <= maxFeePerGas or our transaction library throws an error
253
- // It's a bit counterintuitive since maxPriorityFeePerGas should only contain the tip,
254
- // so we should be subtracting the base gas price from the custom gas price to keep just the tip
255
- // but the fee is also limited by our maxFeePerGas above, so that implicitly captures the max tip.
256
- // Setting this tipGasPrice to undefined will result in a legacy transaction (not an EIP1559 anymore)
257
- tipGasPrice = customGasPrice // aka maxPriorityFeePerGas
258
- }
87
+ ;({ txId, rawTx } = await signTx({
88
+ asset,
89
+ assetClientInterface,
90
+ unsignedTx,
91
+ walletAccount,
92
+ }))
259
93
 
260
- if (isSendAll && !isToken) {
261
- // force consuming all gas
262
- tipGasPrice = gasPrice
94
+ try {
95
+ await baseAsset.api.broadcastTx(rawTx.toString('hex'))
96
+ } catch (retryErr) {
97
+ await handleBroadcastError(retryErr, {
98
+ asset,
99
+ txId,
100
+ isHardware: false,
101
+ hint: safeString`retry:broadcastTx`,
102
+ isBumpTx: false, // retry path is only for non-bump anyway
103
+ isRetryNonceTx: true,
104
+ })
105
+ }
106
+ }
263
107
  }
264
108
 
265
- // gasLimit = customGasLimit
266
- }
267
-
268
- if (asset.baseAsset?.api?.hasFeature?.('noHistory')) {
269
- nonce = await getNonce({ asset: asset.baseAsset, address: fromAddress })
270
- }
271
-
272
- if (nonce === undefined) {
273
- // Calculate latest nonce from base asset's TX log
274
- const baseAssetTxLog = await assetClientInterface.getTxLog({
275
- assetName: asset.baseAsset.name,
109
+ const { nonce, optimisticTxLogEffects } = await getOptimisticTxLogEffects({
110
+ asset,
111
+ assetClientInterface,
112
+ fromAddress,
113
+ txId,
114
+ unsignedTx,
276
115
  walletAccount,
277
116
  })
278
- nonce = [...baseAssetTxLog]
279
- .filter((tx) => tx.sent && !tx.dropped && tx.data.nonce != null)
280
- .reduce((nonce, tx) => Math.max(tx.data.nonce + 1, nonce), 0)
281
- }
282
-
283
- const unsignedTx = await createUnsignedTx({
284
- asset,
285
- walletAccount,
286
- address: toAddress,
287
- amount,
288
- nonce,
289
- txInput,
290
- gasLimit,
291
- gasPrice,
292
- tipGasPrice,
293
- fromAddress,
294
- eip1559Enabled,
295
- })
296
117
 
297
- // TODO: move into createUnsignedTx()
298
- if (keepTxInput && !isToken) {
299
- unsignedTx.txData.to = toAddress
300
- }
301
-
302
- unsignedTx.txMeta.eip1559Enabled = eip1559Enabled
303
-
304
- const { txId, rawTx } = await assetClientInterface.signTransaction({
305
- assetName: asset.baseAsset.name,
306
- unsignedTx,
307
- walletAccount,
308
- })
118
+ for (const optimisticTxLogEffect of optimisticTxLogEffects) {
119
+ await assetClientInterface.updateTxLogAndNotify(optimisticTxLogEffect)
120
+ }
309
121
 
310
- return {
311
- txId: normalizeTxId(txId),
312
- rawTx,
313
- nonce,
314
- gasLimit,
315
- gasPrice,
316
- tipGasPrice,
122
+ return { txId, nonce }
317
123
  }
318
124
  }
319
125
 
@@ -0,0 +1,17 @@
1
+ import { normalizeTxId } from '@exodus/ethereum-lib'
2
+ import assert from 'minimalistic-assert'
3
+
4
+ export const signTx = async ({ asset, assetClientInterface, unsignedTx, walletAccount }) => {
5
+ assert(asset, 'expected asset')
6
+ assert(assetClientInterface, 'expected assetClientInterface')
7
+ assert(unsignedTx, 'expected unsignedTx')
8
+ assert(walletAccount, 'expected walletAccount')
9
+
10
+ const { rawTx, txId } = await assetClientInterface.signTransaction({
11
+ assetName: asset.baseAsset.name,
12
+ unsignedTx,
13
+ walletAccount,
14
+ })
15
+
16
+ return { rawTx, txId: normalizeTxId(txId) }
17
+ }