@exodus/ethereum-api 8.39.0 → 8.40.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
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
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.40.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.39.0...@exodus/ethereum-api@8.40.0) (2025-06-26)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
* feat: enable ws reconnection and timeout fallback to rest on clarity (#5900)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
6
16
|
## [8.39.0](https://github.com/ExodusMovement/assets/compare/@exodus/ethereum-api@8.38.1...@exodus/ethereum-api@8.39.0) (2025-06-20)
|
|
7
17
|
|
|
8
18
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/ethereum-api",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.40.0",
|
|
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",
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"type": "git",
|
|
64
64
|
"url": "git+https://github.com/ExodusMovement/assets.git"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "8c81c64076e7092e8a1a0d7c9a51f410a94aeec9"
|
|
67
67
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { retry } from '@exodus/simple-retry'
|
|
2
|
+
import assert from 'minimalistic-assert'
|
|
2
3
|
|
|
3
|
-
import ClarityServer from './clarity.js'
|
|
4
|
+
import ClarityServer, { RPC_REQUEST_TIMEOUT } from './clarity.js'
|
|
4
5
|
|
|
5
6
|
export const encodeCursor = (blockNumberBigInt, isLegacy = false) => {
|
|
6
7
|
if (typeof blockNumberBigInt !== 'bigint') throw new Error('expected bigint')
|
|
@@ -50,6 +51,22 @@ const fetchJson = async (url, fetchOptions) => {
|
|
|
50
51
|
return response.json()
|
|
51
52
|
}
|
|
52
53
|
|
|
54
|
+
const fetchHttpRequest = ({ baseApiPath, path, method, body }) => {
|
|
55
|
+
assert(typeof baseApiPath === 'string', 'expected string baseApiPath')
|
|
56
|
+
|
|
57
|
+
const url = new URL(`${baseApiPath}${path}`)
|
|
58
|
+
const fetchOptions = {
|
|
59
|
+
method,
|
|
60
|
+
headers: { 'Content-Type': 'application/json' },
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (body) fetchOptions.body = JSON.stringify(body)
|
|
64
|
+
return fetchJson(url, fetchOptions)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const fetchRpcHttpRequest = ({ baseApiPath, body }) =>
|
|
68
|
+
fetchHttpRequest({ baseApiPath, path: '/rpc', method: 'POST', body })
|
|
69
|
+
|
|
53
70
|
async function fetchJsonRetry(url, fetchOptions) {
|
|
54
71
|
const waitTimes = ['3s']
|
|
55
72
|
const fetchWithRetry = retry(fetchJson, { delayTimesMs: waitTimes })
|
|
@@ -105,7 +122,7 @@ export default class ClarityServerV2 extends ClarityServer {
|
|
|
105
122
|
// In addition, when `eip1559Enabled` on Clarity:
|
|
106
123
|
// + baseFeePerGas
|
|
107
124
|
// + nextBaseFeePerGas
|
|
108
|
-
// + rewardPercentiles
|
|
125
|
+
// + rewardPercentiles
|
|
109
126
|
//
|
|
110
127
|
// See: https://github.com/ExodusMovement/clarity/blob/d3c2a7f501a4391da630592bca3bf57c3ddd5e89/src/modules/ethereum-like/gas-price/index.js#L192C5-L219C6
|
|
111
128
|
return await this.getGasPriceEstimation()
|
|
@@ -167,40 +184,29 @@ export default class ClarityServerV2 extends ClarityServer {
|
|
|
167
184
|
}
|
|
168
185
|
}
|
|
169
186
|
|
|
170
|
-
async
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
fetchOptions.body = JSON.stringify(body)
|
|
187
|
+
async sendRpcRequest(rpcRequest) {
|
|
188
|
+
try {
|
|
189
|
+
return await super.sendRpcRequest(rpcRequest)
|
|
190
|
+
} catch (err) {
|
|
191
|
+
// If we encounter an error which isn't associated
|
|
192
|
+
// with transport timeouts, then bubble up.
|
|
193
|
+
if (err.message !== RPC_REQUEST_TIMEOUT) throw err
|
|
194
|
+
|
|
195
|
+
const { baseApiPath } = this
|
|
196
|
+
return fetchRpcHttpRequest({ baseApiPath, body: rpcRequest })
|
|
181
197
|
}
|
|
182
|
-
|
|
183
|
-
const response = await fetchJson(url, fetchOptions)
|
|
184
|
-
|
|
185
|
-
return this.handleJsonRPCResponse(response)
|
|
186
198
|
}
|
|
187
199
|
|
|
188
200
|
async sendRawTransaction(...params) {
|
|
201
|
+
const { baseApiPath } = this
|
|
189
202
|
const request = this.sendRawTransactionRequest(...params)
|
|
190
|
-
return this.
|
|
191
|
-
path: '/rpc',
|
|
192
|
-
method: 'POST',
|
|
193
|
-
body: request,
|
|
194
|
-
})
|
|
203
|
+
return this.handleJsonRPCResponse(await fetchRpcHttpRequest({ baseApiPath, body: request }))
|
|
195
204
|
}
|
|
196
205
|
|
|
197
206
|
async getTransactionCount(...params) {
|
|
198
207
|
// nonce is called during tx send, use it in rest api
|
|
208
|
+
const { baseApiPath } = this
|
|
199
209
|
const request = this.getTransactionCountRequest(...params)
|
|
200
|
-
return this.
|
|
201
|
-
path: '/rpc',
|
|
202
|
-
method: 'POST',
|
|
203
|
-
body: request,
|
|
204
|
-
})
|
|
210
|
+
return this.handleJsonRPCResponse(await fetchRpcHttpRequest({ baseApiPath, body: request }))
|
|
205
211
|
}
|
|
206
212
|
}
|
|
@@ -5,6 +5,8 @@ import io from 'socket.io-client'
|
|
|
5
5
|
|
|
6
6
|
import { fromHexToString } from '../number-utils.js'
|
|
7
7
|
|
|
8
|
+
export const RPC_REQUEST_TIMEOUT = 'RPC_REQUEST_TIMEOUT'
|
|
9
|
+
|
|
8
10
|
export default class ClarityServer extends EventEmitter {
|
|
9
11
|
constructor({ baseAssetName, uri }) {
|
|
10
12
|
super()
|
|
@@ -56,6 +58,7 @@ export default class ClarityServer extends EventEmitter {
|
|
|
56
58
|
return io(`${this.uri}${namespace}`, {
|
|
57
59
|
transports: ['websocket', 'polling'],
|
|
58
60
|
extraHeaders: { 'User-Agent': 'exodus' },
|
|
61
|
+
reconnection: true,
|
|
59
62
|
})
|
|
60
63
|
}
|
|
61
64
|
|
|
@@ -140,7 +143,7 @@ export default class ClarityServer extends EventEmitter {
|
|
|
140
143
|
getFeeFromWebSocket() {
|
|
141
144
|
const socket = this.connectFee()
|
|
142
145
|
return new Promise((resolve, reject) => {
|
|
143
|
-
const timeout = setTimeout(() => reject(new Error('Fee Timeout')),
|
|
146
|
+
const timeout = setTimeout(() => reject(new Error('Fee Timeout')), 3000)
|
|
144
147
|
socket.emit('getFee', (fee) => {
|
|
145
148
|
clearTimeout(timeout)
|
|
146
149
|
if (!fee) {
|
|
@@ -166,7 +169,7 @@ export default class ClarityServer extends EventEmitter {
|
|
|
166
169
|
async sendRpcRequest(rpcRequest) {
|
|
167
170
|
const rpcSocket = this.connectRpc()
|
|
168
171
|
return new Promise((resolve, reject) => {
|
|
169
|
-
const timeout = setTimeout(() => reject(new Error(
|
|
172
|
+
const timeout = setTimeout(() => reject(new Error(RPC_REQUEST_TIMEOUT)), 3000)
|
|
170
173
|
rpcSocket.emit('request', rpcRequest, (response) => {
|
|
171
174
|
clearTimeout(timeout)
|
|
172
175
|
resolve(response)
|
package/src/tx-send/tx-send.js
CHANGED
|
@@ -231,7 +231,7 @@ const txSendFactory = ({ assetClientInterface, createUnsignedTx, useAbsoluteBala
|
|
|
231
231
|
|
|
232
232
|
let { txId, rawTx, nonce, gasLimit, tipGasPrice, feeAmount } = await createTx(createTxParams)
|
|
233
233
|
|
|
234
|
-
if (isPrivate && !baseAsset.api.
|
|
234
|
+
if (isPrivate && !baseAsset.api.features.transactionPrivacy)
|
|
235
235
|
throw new Error(
|
|
236
236
|
`unable to send private transaction - transactionPrivacy is not enabled for ${baseAsset.name}`
|
|
237
237
|
)
|