@exodus/ethereum-api 9.0.0-alpha.2 → 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.
- package/CHANGELOG.md +2121 -0
- package/LICENSE +7 -0
- package/README.md +124 -0
- package/package.json +34 -33
- package/src/address-has-history.js +6 -2
- package/src/allowance/constants.js +4 -5
- package/src/allowance/index.js +159 -40
- package/src/check-tx/create-assess-transaction.js +23 -0
- package/src/check-tx/create-check-tx.js +104 -0
- package/src/check-tx/index.js +1 -0
- package/src/create-asset-plugin-factory.js +115 -0
- package/src/create-asset-utils.js +520 -0
- package/src/create-asset.js +272 -97
- package/src/create-token-factory.js +47 -17
- package/src/custom-fees.js +57 -0
- package/src/eip7702-whitelist.js +62 -0
- package/src/ens/index.js +12 -17
- package/src/error-wrapper.js +383 -0
- package/src/eth-like-util.js +172 -33
- package/src/exodus-eth-server/api-coin-nodes.js +27 -196
- package/src/exodus-eth-server/api.js +23 -14
- package/src/exodus-eth-server/clarity-v2.js +255 -0
- package/src/exodus-eth-server/clarity.js +67 -265
- package/src/exodus-eth-server/errors.js +40 -0
- package/src/exodus-eth-server/eth-like-server.js +385 -0
- package/src/exodus-eth-server/fetch-json.js +48 -0
- package/src/exodus-eth-server/index.js +77 -0
- package/src/exodus-eth-server/utils.js +31 -0
- package/src/exodus-eth-server/ws-gateway.js +306 -0
- package/src/exodus-eth-server/ws.js +1 -2
- package/src/fee-data/EthLikeFeeData.js +81 -0
- package/src/fee-data/index.js +54 -0
- package/src/fee-utils.js +229 -0
- package/src/gas-estimation.js +183 -66
- package/src/get-balance-for-address.js +1 -1
- package/src/get-balances.js +285 -27
- package/src/get-fee.js +92 -56
- package/src/get-historical-balance.js +58 -0
- package/src/hooks/index.js +1 -1
- package/src/hooks/monitor.js +182 -43
- package/src/hooks/staking-freshness.js +58 -0
- package/src/index.js +118 -12
- package/src/move-funds.js +153 -0
- package/src/multicall3/index.js +212 -0
- package/src/multisig-address.js +146 -0
- package/src/nft-utils.js +60 -0
- package/src/number-utils.js +34 -2
- package/src/optimism-gas/index.js +13 -5
- package/src/send-validations.js +58 -0
- package/src/server-based-fee-monitor.js +12 -19
- package/src/simulate-tx/fetch-tx-preview.js +0 -2
- package/src/simulate-tx/index.js +2 -2
- package/src/simulate-tx/simulate-eth-tx.js +24 -11
- package/src/simulation/common.js +34 -0
- package/src/simulation/create-simulate-message.js +49 -0
- package/src/simulation/create-simulate-transactions.js +108 -0
- package/src/simulation/estimate-fee.js +14 -0
- package/src/simulation/estimate-simple-transfer.js +15 -0
- package/src/simulation/get-message-type.js +18 -0
- package/src/simulation/simulate-message-api.js +68 -0
- package/src/simulation/simulate-transactions-api.js +266 -0
- package/src/simulation/simulate-transactions.js +16 -0
- package/src/simulation/transactions.js +52 -0
- package/src/simulation/try-estimating-changes-locally.js +26 -0
- package/src/staking/api/index.js +43 -0
- package/src/staking/cached-read.js +33 -0
- package/src/staking/ethereum/api.js +166 -34
- package/src/staking/ethereum/deps.js +37 -0
- package/src/staking/ethereum/everstake.js +113 -0
- package/src/staking/ethereum/index.js +4 -3
- package/src/staking/ethereum/service.js +682 -181
- package/src/staking/ethereum/staking-utils.js +275 -4
- package/src/staking/fantom-staking.js +9 -9
- package/src/staking/index.js +4 -4
- package/src/staking/matic/addresses.js +2 -0
- package/src/staking/matic/api.js +69 -49
- package/src/staking/matic/index.js +3 -3
- package/src/staking/matic/matic-staking-utils.js +243 -5
- package/src/staking/matic/matic-staking.md +53 -0
- package/src/staking/staking-provider-client.js +1 -1
- package/src/staking/utils/index.js +39 -0
- package/src/tx-create.js +666 -0
- package/src/tx-log/clarity-monitor.js +273 -103
- package/src/tx-log/clarity-truncated-history-monitor.js +109 -0
- package/src/tx-log/clarity-truncated-history-monitor.md +219 -0
- package/src/tx-log/clarity-utils/absolute.js +96 -0
- package/src/tx-log/clarity-utils/get-log-items-from-server-tx.js +94 -31
- package/src/tx-log/clarity-utils/get-names-of-tokens-transferred-by-server-tx.js +3 -2
- package/src/tx-log/clarity-utils/index.js +9 -3
- package/src/tx-log/clarity-utils/is-spam-pending-tx.js +13 -0
- package/src/tx-log/clarity-utils/normalize-transactions-response.js +65 -0
- package/src/tx-log/ethereum-monitor.js +93 -47
- package/src/tx-log/ethereum-no-history-monitor.js +52 -41
- package/src/tx-log/get-optimistic-txlog-effects.js +379 -0
- package/src/tx-log/index.js +5 -3
- package/src/tx-log/monitor-utils/check-pending-transactions.js +14 -5
- package/src/tx-log/monitor-utils/exclude-unchanged-token-balances.js +1 -1
- package/src/tx-log/monitor-utils/extract-balance-from-clarity-account-info.js +108 -0
- package/src/tx-log/monitor-utils/get-balance-updates.js +44 -0
- package/src/tx-log/monitor-utils/get-batched-rpc-balances.js +47 -0
- package/src/tx-log/monitor-utils/get-current-blacklist-status.js +38 -0
- package/src/tx-log/monitor-utils/get-current-eip7702-delegation.js +79 -0
- package/src/tx-log/monitor-utils/get-derive-transactions-to-check.js +10 -5
- package/src/tx-log/monitor-utils/get-fee-amount.js +1 -1
- package/src/tx-log/monitor-utils/get-history-from-server.js +1 -1
- package/src/tx-log/monitor-utils/get-log-items-from-server-tx.js +75 -33
- package/src/tx-log/monitor-utils/get-names-of-tokens-transferred-by-server-tx.js +3 -2
- package/src/tx-log/monitor-utils/get-raw-transfer-amount.js +29 -0
- package/src/tx-log/monitor-utils/get-transfers-by-token-name.js +3 -2
- package/src/tx-log/monitor-utils/get-value-of-transfers.js +10 -12
- package/src/tx-log/monitor-utils/index.js +12 -7
- package/src/tx-log/monitor-utils/is-unverifiable-pending-tx-expired.js +19 -0
- package/src/tx-log/monitor-utils/verify-pending-tx-status-rpc.js +90 -0
- package/src/tx-log-staking-processor/asset-staking-tx-data.js +82 -24
- package/src/tx-log-staking-processor/index.js +28 -14
- package/src/tx-log-staking-processor/utils.js +21 -20
- package/src/tx-send/broadcast-error-handler.js +63 -0
- package/src/tx-send/index.js +1 -2
- package/src/tx-send/nonce-utils.js +97 -0
- package/src/tx-send/tx-send.js +94 -288
- package/src/tx-sign/index.js +17 -0
- package/src/tx-type/index.js +280 -0
- package/src/watch-tx.js +36 -0
- package/src/web3/createSimulateMessage.js +3 -2
- package/src/web3/createSimulateTransactions.js +11 -0
- package/src/web3/index.js +3 -1
- package/src/etherscan/account.js +0 -49
- package/src/etherscan/index.js +0 -28
- package/src/etherscan/logs.js +0 -16
- package/src/etherscan/proxy.js +0 -47
- package/src/etherscan/request.js +0 -26
- package/src/etherscan/ws.js +0 -88
- package/src/exodus-eth-server/server-factory.js +0 -28
- package/src/exodus-eth-server/server-map.js +0 -21
- package/src/get-fee-async.js +0 -97
- package/src/staking/matic/service.js +0 -437
- package/src/staking-api.js +0 -5
- package/src/tx-log/clarity-utils/get-derive-data-needed-for-tick.js +0 -12
- package/src/tx-log-staking-processor/get-asset-tx-amount.js +0 -26
- package/src/tx-send/get-fee-info.js +0 -41
- package/src/websocket/index.android.js +0 -2
- package/src/websocket/index.ios.js +0 -2
- package/src/websocket/index.js +0 -21
package/src/tx-send/tx-send.js
CHANGED
|
@@ -1,319 +1,125 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
})
|
|
14
|
+
return async ({ asset, walletAccount, unsignedTx: providedUnsignedTx, ...legacyParams }) => {
|
|
15
|
+
const baseAsset = asset.baseAsset
|
|
52
16
|
|
|
53
|
-
|
|
17
|
+
const { unsignedTx } = providedUnsignedTx
|
|
18
|
+
? { unsignedTx: providedUnsignedTx }
|
|
19
|
+
: await createTx({ asset, walletAccount, ...legacyParams })
|
|
54
20
|
|
|
55
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
27
|
+
assert(
|
|
28
|
+
to?.toLowerCase() !== ARBITRARY_ADDRESS,
|
|
29
|
+
`The receiving wallet address must not be ${ARBITRARY_ADDRESS}`
|
|
30
|
+
)
|
|
78
31
|
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
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
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
211
|
-
|
|
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
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
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
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
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
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
87
|
+
;({ txId, rawTx } = await signTx({
|
|
88
|
+
asset,
|
|
89
|
+
assetClientInterface,
|
|
90
|
+
unsignedTx,
|
|
91
|
+
walletAccount,
|
|
92
|
+
}))
|
|
259
93
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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
|
-
|
|
298
|
-
|
|
299
|
-
|
|
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
|
-
|
|
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
|
+
}
|