@exodus/ethereum-api 8.76.6 → 8.77.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 +29 -0
- package/package.json +2 -3
- package/src/create-asset-plugin-factory.js +1 -0
- package/src/create-asset-utils.js +39 -35
- package/src/create-asset.js +32 -14
- package/src/create-token-factory.js +3 -0
- package/src/exodus-eth-server/api-coin-nodes.js +11 -84
- package/src/exodus-eth-server/clarity-v2.js +30 -51
- package/src/exodus-eth-server/clarity.js +2 -115
- package/src/exodus-eth-server/errors.js +5 -1
- package/src/exodus-eth-server/eth-like-server-base.js +123 -0
- package/src/exodus-eth-server/fetch-json.js +48 -0
- package/src/gas-estimation.js +19 -4
- package/src/get-balances.js +14 -0
- package/src/get-historical-balance.js +58 -0
- package/src/index.js +2 -0
- package/src/multicall3/index.js +169 -0
- package/src/simulation/common.js +34 -0
- package/src/simulation/create-simulate-message.js +49 -0
- package/src/simulation/create-simulate-transactions.js +106 -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 +265 -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/ethereum/staking-utils.js +3 -1
- package/src/staking/matic/matic-staking-utils.js +3 -1
- package/src/tx-log/clarity-truncated-history-monitor.js +34 -0
- package/src/tx-log/clarity-utils/absolute.js +5 -1
- package/src/tx-log/ethereum-no-history-monitor.js +2 -23
- package/src/tx-log/monitor-utils/get-batched-rpc-balances.js +28 -0
- package/src/tx-send/broadcast-error-handler.js +7 -2
- package/src/tx-send/tx-send.js +1 -0
- package/src/web3/createSimulateMessage.js +2 -1
- package/src/web3/createSimulateTransactions.js +3 -9
|
@@ -75,6 +75,40 @@ export class ClarityTruncatedHistoryMonitor extends ClarityMonitor {
|
|
|
75
75
|
let clarityCursor
|
|
76
76
|
|
|
77
77
|
try {
|
|
78
|
+
// When refreshing, we need to clear out old asset
|
|
79
|
+
// balances in `accountState` since these can surface
|
|
80
|
+
// values populated from alternative monitors i.e.
|
|
81
|
+
// `no-history`, which can be written at arbitrary
|
|
82
|
+
// points in time.
|
|
83
|
+
//
|
|
84
|
+
// Since the `truncated-history-monitor` does not
|
|
85
|
+
// guarantee an `accountState` write for an asset,
|
|
86
|
+
// (these are only provided when the history is
|
|
87
|
+
// truncated), we must ensure older checkpoints cannot
|
|
88
|
+
// be inadvertently relied upon.
|
|
89
|
+
//
|
|
90
|
+
if (refresh) {
|
|
91
|
+
const defaultAccountState = this.asset.api.createAccountState().create()
|
|
92
|
+
|
|
93
|
+
const currentAccountState = derivedData.currentAccountState ?? defaultAccountState
|
|
94
|
+
|
|
95
|
+
const resetTokenBalances = {
|
|
96
|
+
balance: defaultAccountState.balance,
|
|
97
|
+
tokenBalances: defaultAccountState.tokenBalances,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Optimistically update the `derivedData` for downstream.
|
|
101
|
+
derivedData.currentAccountState = currentAccountState.merge(resetTokenBalances)
|
|
102
|
+
|
|
103
|
+
this.aci.updateAccountStateBatch({
|
|
104
|
+
assetName,
|
|
105
|
+
walletAccount,
|
|
106
|
+
accountState: currentAccountState,
|
|
107
|
+
newData: resetTokenBalances,
|
|
108
|
+
batch,
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
|
|
78
112
|
const response = await this.getHistoryFromServer({ walletAccount, derivedData, refresh })
|
|
79
113
|
|
|
80
114
|
;({ allTxs } = await normalizeTransactionsResponse({
|
|
@@ -50,12 +50,15 @@ const getLatestCanonicalAbsoluteTx = ({
|
|
|
50
50
|
searchDepthMs = DEFAULT_CANONICAL_ABSOLUTE_TX_SEARCH_DEPTH,
|
|
51
51
|
reversedTxLog,
|
|
52
52
|
fieldName,
|
|
53
|
+
deadline = Infinity,
|
|
53
54
|
}) => {
|
|
54
55
|
assert(reversedTxLog, 'expected reversedTxLog')
|
|
55
56
|
|
|
56
57
|
let latest = null
|
|
57
58
|
|
|
58
59
|
for (const tx of reversedTxLog) {
|
|
60
|
+
if (+tx.date > deadline) continue
|
|
61
|
+
|
|
59
62
|
if (latest) {
|
|
60
63
|
const diff = +latest.date - +tx.date
|
|
61
64
|
|
|
@@ -77,10 +80,11 @@ const getLatestCanonicalAbsoluteTx = ({
|
|
|
77
80
|
return latest
|
|
78
81
|
}
|
|
79
82
|
|
|
80
|
-
export const getLatestCanonicalAbsoluteBalanceTx = ({ searchDepthMs, reversedTxLog }) =>
|
|
83
|
+
export const getLatestCanonicalAbsoluteBalanceTx = ({ searchDepthMs, reversedTxLog, deadline }) =>
|
|
81
84
|
getLatestCanonicalAbsoluteTx({
|
|
82
85
|
searchDepthMs,
|
|
83
86
|
reversedTxLog,
|
|
87
|
+
deadline,
|
|
84
88
|
fieldName: ABSOLUTE_FIELD_NAME_BALANCE_CHANGE,
|
|
85
89
|
})
|
|
86
90
|
|
|
@@ -3,7 +3,7 @@ import { SynchronizedTime } from '@exodus/basic-utils'
|
|
|
3
3
|
import { Tx } from '@exodus/models'
|
|
4
4
|
import lodash from 'lodash'
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { getBatchedRpcBalances } from './monitor-utils/get-batched-rpc-balances.js'
|
|
7
7
|
import { UNCONFIRMED_TX_LIMIT } from './monitor-utils/get-derive-transactions-to-check.js'
|
|
8
8
|
import {
|
|
9
9
|
excludeUnchangedTokenBalances,
|
|
@@ -41,28 +41,7 @@ export class EthereumNoHistoryMonitor extends BaseMonitor {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
async getBalances({ tokens, ourWalletAddress }) {
|
|
44
|
-
|
|
45
|
-
const request = this.server.getBalanceRequest(ourWalletAddress)
|
|
46
|
-
batch[this.asset.name] = request
|
|
47
|
-
for (const token of tokens) {
|
|
48
|
-
const request = this.server.balanceOfRequest(ourWalletAddress, token.contract.address)
|
|
49
|
-
batch[token.name] = request
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const pairs = Object.entries(batch)
|
|
53
|
-
if (pairs.length === 0) {
|
|
54
|
-
return {}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const requests = pairs.map((pair) => pair[1])
|
|
58
|
-
const responses = await this.server.sendBatchRequest(requests)
|
|
59
|
-
const entries = pairs.map((pair, idx) => {
|
|
60
|
-
const balanceHex = responses[idx]
|
|
61
|
-
const name = pair[0]
|
|
62
|
-
const balance = fromHexToString(balanceHex)
|
|
63
|
-
return [name, balance]
|
|
64
|
-
})
|
|
65
|
-
return Object.fromEntries(entries)
|
|
44
|
+
return getBatchedRpcBalances({ baseAsset: this.asset, ourWalletAddress, tokens })
|
|
66
45
|
}
|
|
67
46
|
|
|
68
47
|
async getNewAccountState({ tokens, currentTokenBalances, ourWalletAddress }) {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import assert from 'minimalistic-assert'
|
|
2
|
+
|
|
3
|
+
import { fromHexToString } from '../../number-utils.js'
|
|
4
|
+
|
|
5
|
+
export const getBatchedRpcBalances = async ({ baseAsset, tokens, ourWalletAddress }) => {
|
|
6
|
+
assert(baseAsset, 'expected baseAsset')
|
|
7
|
+
assert(Array.isArray(tokens), 'expected array tokens')
|
|
8
|
+
assert(ourWalletAddress, 'expected ourWalletAddress')
|
|
9
|
+
|
|
10
|
+
const [balance, ...tokenBalances] = await tokens
|
|
11
|
+
.reduce(
|
|
12
|
+
(acc, { contract: { address: tokenAddress } }) =>
|
|
13
|
+
acc.balanceOfRequest(ourWalletAddress, tokenAddress),
|
|
14
|
+
baseAsset.createRpcRequestAccumulator().getBalanceRequest(ourWalletAddress)
|
|
15
|
+
)
|
|
16
|
+
.flush(baseAsset.server)
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
[baseAsset.name]: fromHexToString(balance),
|
|
20
|
+
...Object.fromEntries(
|
|
21
|
+
tokens.map(({ name, contract: { address: tokenAddress } }, i) => {
|
|
22
|
+
const tokenBalance = tokenBalances[i]?.confirmed?.[tokenAddress]
|
|
23
|
+
assert(tokenBalance != null, `missing token balance for ${name} (${tokenAddress})`)
|
|
24
|
+
return [name, tokenBalance]
|
|
25
|
+
})
|
|
26
|
+
),
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -11,10 +11,15 @@ import { transactionExists } from '../eth-like-util.js'
|
|
|
11
11
|
* @param {string} options.txId - The transaction ID.
|
|
12
12
|
* @param {boolean} options.isHardware - Whether this is a hardware wallet.
|
|
13
13
|
* @param {string} options.hint - Hint for the error.
|
|
14
|
+
* @param {boolean} options.isBumpTx - Whether the occur occured whilst bumping a Tx.
|
|
15
|
+
* @param {boolean} options.isRetryNonceTx - If the error occurred during a nonce bump.
|
|
14
16
|
* @returns {Promise<{ shouldRetry: boolean }>} - Returns if nonce too low and can retry.
|
|
15
17
|
* @throws {EthLikeError} - Throws for all other error cases.
|
|
16
18
|
*/
|
|
17
|
-
export const handleBroadcastError = async (
|
|
19
|
+
export const handleBroadcastError = async (
|
|
20
|
+
err,
|
|
21
|
+
{ asset, txId, isHardware, hint, isBumpTx, isRetryNonceTx }
|
|
22
|
+
) => {
|
|
18
23
|
const message = err.message
|
|
19
24
|
|
|
20
25
|
const errorInfo = getEvmErrorReason(message) || EVM_ERROR_REASONS.broadcastTxFailed
|
|
@@ -46,7 +51,7 @@ export const handleBroadcastError = async (err, { asset, txId, isHardware, hint,
|
|
|
46
51
|
// NOTE: Don't auto-retry nonce repair for bump/replacement txs.
|
|
47
52
|
// A replacement must keep the *same nonce* as the tx it's replacing.
|
|
48
53
|
// If we "fix" a bump tx by advancing the nonce, we create a brand-new tx instead of replacing the pending one.
|
|
49
|
-
if (isNonceTooLow && !isHardware && !isBumpTx) return { shouldRetry: true }
|
|
54
|
+
if (isNonceTooLow && !isHardware && !isBumpTx && !isRetryNonceTx) return { shouldRetry: true }
|
|
50
55
|
|
|
51
56
|
throw new EthLikeError({
|
|
52
57
|
message: err.message,
|
package/src/tx-send/tx-send.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { createSimulateMessage as createSimulateEVMMessage } from '@exodus/web3-ethereum-utils'
|
|
2
1
|
import assert from 'minimalistic-assert'
|
|
3
2
|
|
|
3
|
+
import { createSimulateMessage as createSimulateEVMMessage } from '../simulation/create-simulate-message.js'
|
|
4
|
+
|
|
4
5
|
export const createSimulateMessage = ({ asset }) => {
|
|
5
6
|
assert(asset, '"asset" should be passed.')
|
|
6
7
|
|
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
import { createSimulateTransactions as createSimulateEVMTransactions } from '@exodus/web3-ethereum-utils'
|
|
2
1
|
import assert from 'minimalistic-assert'
|
|
3
2
|
|
|
3
|
+
import { simulateTransactions as simulateEthereumTransactions } from '../simulation/simulate-transactions.js'
|
|
4
|
+
|
|
4
5
|
export const createSimulateTransactions = ({ asset }) => {
|
|
5
6
|
assert(asset, '"asset" should be passed.')
|
|
6
7
|
|
|
7
|
-
const simulateEVMTransactions = createSimulateEVMTransactions({
|
|
8
|
-
apiEndpoint: 'https://simulation.a.exodus.io/simulate',
|
|
9
|
-
headers: {
|
|
10
|
-
'X-Api-Version': '2023-06-05',
|
|
11
|
-
},
|
|
12
|
-
})
|
|
13
|
-
|
|
14
8
|
return function simulateTransaction({ transactions, ...restParameters }) {
|
|
15
|
-
return
|
|
9
|
+
return simulateEthereumTransactions({ asset, transactions, ...restParameters })
|
|
16
10
|
}
|
|
17
11
|
}
|