@orbinum/sdk 0.7.5 → 0.7.7
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/dist/index.d.mts +34 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +83 -18
- package/dist/index.mjs +83 -18
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -10,6 +10,20 @@ export { base58 } from '@scure/base';
|
|
|
10
10
|
export { getPolkadotSigner } from 'polkadot-api/signer';
|
|
11
11
|
export { SignPayload, SignRaw, connectInjectedExtension, getInjectedExtensions, getPolkadotSignerFromPjs } from 'polkadot-api/pjs-signer';
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Minimal JSON-RPC 2.0 over HTTP — batch transport.
|
|
15
|
+
*
|
|
16
|
+
* Substrate and EVM nodes both serve JSON-RPC over HTTP. PAPI's WebSocket
|
|
17
|
+
* transport (used by `SubstrateClient` for everything else) does not expose
|
|
18
|
+
* batch requests, so high-throughput callers (e.g. indexer backfill) use this
|
|
19
|
+
* to fetch many results in a single round-trip instead of N.
|
|
20
|
+
*/
|
|
21
|
+
/** A single JSON-RPC call: method name plus positional params. */
|
|
22
|
+
interface JsonRpcCall {
|
|
23
|
+
method: string;
|
|
24
|
+
params?: unknown[];
|
|
25
|
+
}
|
|
26
|
+
|
|
13
27
|
type ChainInfo = {
|
|
14
28
|
name: string;
|
|
15
29
|
version: string;
|
|
@@ -87,6 +101,7 @@ type ExtrinsicDecoder = ReturnType<typeof getExtrinsicDecoder>;
|
|
|
87
101
|
*/
|
|
88
102
|
declare class SubstrateClient {
|
|
89
103
|
private readonly _papi;
|
|
104
|
+
private readonly _httpUrl;
|
|
90
105
|
private constructor();
|
|
91
106
|
private _dynamicBuilder;
|
|
92
107
|
private _extDecoder;
|
|
@@ -100,6 +115,17 @@ declare class SubstrateClient {
|
|
|
100
115
|
* (shieldedPool_*, accountMapping_*, privacy_*, etc.).
|
|
101
116
|
*/
|
|
102
117
|
request<T>(method: string, params?: unknown[]): Promise<T>;
|
|
118
|
+
/**
|
|
119
|
+
* Performs multiple JSON-RPC calls in a single HTTP request (batch). Results
|
|
120
|
+
* are returned in the same order as `calls`, as a typed tuple. A `null`
|
|
121
|
+
* result (or per-call error) maps to `null` in that slot — the call itself
|
|
122
|
+
* only rejects on HTTP/transport failure.
|
|
123
|
+
*
|
|
124
|
+
* Uses the HTTP RPC endpoint (derived from the WS URL); PAPI's WS transport
|
|
125
|
+
* does not expose batching. Ideal for high-throughput backfill: fetch many
|
|
126
|
+
* block hashes / blocks / storage reads in one round-trip instead of N.
|
|
127
|
+
*/
|
|
128
|
+
batchRequest<T extends unknown[]>(calls: JsonRpcCall[]): Promise<T>;
|
|
103
129
|
/**
|
|
104
130
|
* Returns basic chain information from the node.
|
|
105
131
|
* Combines `system_name`, `system_chain`, `system_properties`, and `state_getRuntimeVersion`.
|
|
@@ -2124,6 +2150,14 @@ declare class OrbinumClientProvider {
|
|
|
2124
2150
|
* Waits for the client to be ready before dispatching.
|
|
2125
2151
|
*/
|
|
2126
2152
|
rpcSend<T>(method: string, params?: unknown[]): Promise<T>;
|
|
2153
|
+
/**
|
|
2154
|
+
* Sends multiple Substrate JSON-RPC calls as a single HTTP batch request.
|
|
2155
|
+
* Returns a tuple of typed results in the same order as `calls`.
|
|
2156
|
+
*/
|
|
2157
|
+
rpcBatch<T extends unknown[]>(calls: Array<{
|
|
2158
|
+
method: string;
|
|
2159
|
+
params?: unknown[];
|
|
2160
|
+
}>): Promise<T>;
|
|
2127
2161
|
/**
|
|
2128
2162
|
* Sends a single EVM JSON-RPC request and returns the typed result.
|
|
2129
2163
|
* Throws if `evmRpc` was not configured.
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,20 @@ export { base58 } from '@scure/base';
|
|
|
10
10
|
export { getPolkadotSigner } from 'polkadot-api/signer';
|
|
11
11
|
export { SignPayload, SignRaw, connectInjectedExtension, getInjectedExtensions, getPolkadotSignerFromPjs } from 'polkadot-api/pjs-signer';
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Minimal JSON-RPC 2.0 over HTTP — batch transport.
|
|
15
|
+
*
|
|
16
|
+
* Substrate and EVM nodes both serve JSON-RPC over HTTP. PAPI's WebSocket
|
|
17
|
+
* transport (used by `SubstrateClient` for everything else) does not expose
|
|
18
|
+
* batch requests, so high-throughput callers (e.g. indexer backfill) use this
|
|
19
|
+
* to fetch many results in a single round-trip instead of N.
|
|
20
|
+
*/
|
|
21
|
+
/** A single JSON-RPC call: method name plus positional params. */
|
|
22
|
+
interface JsonRpcCall {
|
|
23
|
+
method: string;
|
|
24
|
+
params?: unknown[];
|
|
25
|
+
}
|
|
26
|
+
|
|
13
27
|
type ChainInfo = {
|
|
14
28
|
name: string;
|
|
15
29
|
version: string;
|
|
@@ -87,6 +101,7 @@ type ExtrinsicDecoder = ReturnType<typeof getExtrinsicDecoder>;
|
|
|
87
101
|
*/
|
|
88
102
|
declare class SubstrateClient {
|
|
89
103
|
private readonly _papi;
|
|
104
|
+
private readonly _httpUrl;
|
|
90
105
|
private constructor();
|
|
91
106
|
private _dynamicBuilder;
|
|
92
107
|
private _extDecoder;
|
|
@@ -100,6 +115,17 @@ declare class SubstrateClient {
|
|
|
100
115
|
* (shieldedPool_*, accountMapping_*, privacy_*, etc.).
|
|
101
116
|
*/
|
|
102
117
|
request<T>(method: string, params?: unknown[]): Promise<T>;
|
|
118
|
+
/**
|
|
119
|
+
* Performs multiple JSON-RPC calls in a single HTTP request (batch). Results
|
|
120
|
+
* are returned in the same order as `calls`, as a typed tuple. A `null`
|
|
121
|
+
* result (or per-call error) maps to `null` in that slot — the call itself
|
|
122
|
+
* only rejects on HTTP/transport failure.
|
|
123
|
+
*
|
|
124
|
+
* Uses the HTTP RPC endpoint (derived from the WS URL); PAPI's WS transport
|
|
125
|
+
* does not expose batching. Ideal for high-throughput backfill: fetch many
|
|
126
|
+
* block hashes / blocks / storage reads in one round-trip instead of N.
|
|
127
|
+
*/
|
|
128
|
+
batchRequest<T extends unknown[]>(calls: JsonRpcCall[]): Promise<T>;
|
|
103
129
|
/**
|
|
104
130
|
* Returns basic chain information from the node.
|
|
105
131
|
* Combines `system_name`, `system_chain`, `system_properties`, and `state_getRuntimeVersion`.
|
|
@@ -2124,6 +2150,14 @@ declare class OrbinumClientProvider {
|
|
|
2124
2150
|
* Waits for the client to be ready before dispatching.
|
|
2125
2151
|
*/
|
|
2126
2152
|
rpcSend<T>(method: string, params?: unknown[]): Promise<T>;
|
|
2153
|
+
/**
|
|
2154
|
+
* Sends multiple Substrate JSON-RPC calls as a single HTTP batch request.
|
|
2155
|
+
* Returns a tuple of typed results in the same order as `calls`.
|
|
2156
|
+
*/
|
|
2157
|
+
rpcBatch<T extends unknown[]>(calls: Array<{
|
|
2158
|
+
method: string;
|
|
2159
|
+
params?: unknown[];
|
|
2160
|
+
}>): Promise<T>;
|
|
2127
2161
|
/**
|
|
2128
2162
|
* Sends a single EVM JSON-RPC request and returns the typed result.
|
|
2129
2163
|
* Throws if `evmRpc` was not configured.
|
package/dist/index.js
CHANGED
|
@@ -163,12 +163,59 @@ function hexToBigint(hex) {
|
|
|
163
163
|
return BigInt(hex);
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
+
// src/utils/jsonRpcHttp.ts
|
|
167
|
+
var DEFAULT_MAX_RETRIES = 5;
|
|
168
|
+
var DEFAULT_BASE_BACKOFF_MS = 250;
|
|
169
|
+
var DEFAULT_MAX_BACKOFF_MS = 4e3;
|
|
170
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
171
|
+
async function jsonRpcBatch(httpUrl, calls, options = {}) {
|
|
172
|
+
if (calls.length === 0) return [];
|
|
173
|
+
const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
174
|
+
const baseBackoffMs = options.baseBackoffMs ?? DEFAULT_BASE_BACKOFF_MS;
|
|
175
|
+
const maxBackoffMs = options.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS;
|
|
176
|
+
const body = calls.map((c, i) => ({
|
|
177
|
+
id: i,
|
|
178
|
+
jsonrpc: "2.0",
|
|
179
|
+
method: c.method,
|
|
180
|
+
params: c.params ?? []
|
|
181
|
+
}));
|
|
182
|
+
const payload = JSON.stringify(body);
|
|
183
|
+
let attempt = 0;
|
|
184
|
+
for (; ; ) {
|
|
185
|
+
const res = await fetch(httpUrl, {
|
|
186
|
+
method: "POST",
|
|
187
|
+
headers: { "Content-Type": "application/json" },
|
|
188
|
+
body: payload
|
|
189
|
+
});
|
|
190
|
+
if (res.ok) {
|
|
191
|
+
const arr = await res.json();
|
|
192
|
+
const byId = new Map(arr.map((r) => [r.id, r]));
|
|
193
|
+
return calls.map((_, i) => byId.get(i)?.result ?? null);
|
|
194
|
+
}
|
|
195
|
+
const retryable = res.status === 429 || res.status === 503;
|
|
196
|
+
if (!retryable || attempt >= maxRetries) {
|
|
197
|
+
throw new Error(`JSON-RPC HTTP ${res.status}: ${res.statusText}`);
|
|
198
|
+
}
|
|
199
|
+
const retryAfter = Number(res.headers.get("retry-after"));
|
|
200
|
+
const delayMs = Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter * 1e3 : Math.min(baseBackoffMs * 2 ** attempt, maxBackoffMs);
|
|
201
|
+
await sleep(delayMs);
|
|
202
|
+
attempt++;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function wsUrlToHttp(wsUrl) {
|
|
206
|
+
if (wsUrl.startsWith("wss://")) return "https://" + wsUrl.slice("wss://".length);
|
|
207
|
+
if (wsUrl.startsWith("ws://")) return "http://" + wsUrl.slice("ws://".length);
|
|
208
|
+
return wsUrl;
|
|
209
|
+
}
|
|
210
|
+
|
|
166
211
|
// src/substrate/SubstrateClient.ts
|
|
167
212
|
var SubstrateClient = class _SubstrateClient {
|
|
168
|
-
constructor(_papi) {
|
|
213
|
+
constructor(_papi, _httpUrl) {
|
|
169
214
|
this._papi = _papi;
|
|
215
|
+
this._httpUrl = _httpUrl;
|
|
170
216
|
}
|
|
171
217
|
_papi;
|
|
218
|
+
_httpUrl;
|
|
172
219
|
_dynamicBuilder = null;
|
|
173
220
|
_extDecoder = null;
|
|
174
221
|
/**
|
|
@@ -187,7 +234,7 @@ var SubstrateClient = class _SubstrateClient {
|
|
|
187
234
|
)
|
|
188
235
|
)
|
|
189
236
|
]);
|
|
190
|
-
return new _SubstrateClient(papi);
|
|
237
|
+
return new _SubstrateClient(papi, wsUrlToHttp(wsUrl));
|
|
191
238
|
}
|
|
192
239
|
/**
|
|
193
240
|
* Performs a raw JSON-RPC request. Use this for custom Orbinum RPCs
|
|
@@ -196,6 +243,19 @@ var SubstrateClient = class _SubstrateClient {
|
|
|
196
243
|
async request(method, params = []) {
|
|
197
244
|
return this._papi._request(method, params);
|
|
198
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* Performs multiple JSON-RPC calls in a single HTTP request (batch). Results
|
|
248
|
+
* are returned in the same order as `calls`, as a typed tuple. A `null`
|
|
249
|
+
* result (or per-call error) maps to `null` in that slot — the call itself
|
|
250
|
+
* only rejects on HTTP/transport failure.
|
|
251
|
+
*
|
|
252
|
+
* Uses the HTTP RPC endpoint (derived from the WS URL); PAPI's WS transport
|
|
253
|
+
* does not expose batching. Ideal for high-throughput backfill: fetch many
|
|
254
|
+
* block hashes / blocks / storage reads in one round-trip instead of N.
|
|
255
|
+
*/
|
|
256
|
+
async batchRequest(calls) {
|
|
257
|
+
return jsonRpcBatch(this._httpUrl, calls);
|
|
258
|
+
}
|
|
199
259
|
/**
|
|
200
260
|
* Returns basic chain information from the node.
|
|
201
261
|
* Combines `system_name`, `system_chain`, `system_properties`, and `state_getRuntimeVersion`.
|
|
@@ -777,14 +837,7 @@ var EvmExplorer = class _EvmExplorer {
|
|
|
777
837
|
async getLatestBlocks(count = 10) {
|
|
778
838
|
const latest = await this.evm.getBlockNumber();
|
|
779
839
|
const nums = Array.from({ length: Math.min(count, latest + 1) }, (_, i) => latest - i);
|
|
780
|
-
const results = await
|
|
781
|
-
nums.map(
|
|
782
|
-
(n) => this.evm.request("eth_getBlockByNumber", [
|
|
783
|
-
`0x${n.toString(16)}`,
|
|
784
|
-
false
|
|
785
|
-
]).catch(() => null)
|
|
786
|
-
)
|
|
787
|
-
);
|
|
840
|
+
const results = await this.evm.batchRequest(nums.map((n) => ({ method: "eth_getBlockByNumber", params: [`0x${n.toString(16)}`, false] }))).catch(() => nums.map(() => null));
|
|
788
841
|
return results.filter((b) => b !== null && !!b.hash).map((b) => this.parseBlock(b));
|
|
789
842
|
}
|
|
790
843
|
/** Returns a single block by number or hash, or `null` if not found. */
|
|
@@ -827,14 +880,18 @@ var EvmExplorer = class _EvmExplorer {
|
|
|
827
880
|
const latest = await this.evm.getBlockNumber();
|
|
828
881
|
const from = Math.max(0, latest - maxBlocks + 1);
|
|
829
882
|
const blockNums = Array.from({ length: latest - from + 1 }, (_, i) => latest - i);
|
|
830
|
-
const
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
883
|
+
const CHUNK = 50;
|
|
884
|
+
const blocks = [];
|
|
885
|
+
for (let i = 0; i < blockNums.length; i += CHUNK) {
|
|
886
|
+
const slice = blockNums.slice(i, i + CHUNK);
|
|
887
|
+
const part = await this.evm.batchRequest(
|
|
888
|
+
slice.map((n) => ({
|
|
889
|
+
method: "eth_getBlockByNumber",
|
|
890
|
+
params: [`0x${n.toString(16)}`, true]
|
|
891
|
+
}))
|
|
892
|
+
).catch(() => slice.map(() => null));
|
|
893
|
+
blocks.push(...part);
|
|
894
|
+
}
|
|
838
895
|
const matchingTxs = [];
|
|
839
896
|
for (const block of blocks) {
|
|
840
897
|
if (!block?.transactions) continue;
|
|
@@ -3698,6 +3755,14 @@ var OrbinumClientProvider = class {
|
|
|
3698
3755
|
const client = await this.getOrbinumClient();
|
|
3699
3756
|
return client.substrate.request(method, params);
|
|
3700
3757
|
}
|
|
3758
|
+
/**
|
|
3759
|
+
* Sends multiple Substrate JSON-RPC calls as a single HTTP batch request.
|
|
3760
|
+
* Returns a tuple of typed results in the same order as `calls`.
|
|
3761
|
+
*/
|
|
3762
|
+
async rpcBatch(calls) {
|
|
3763
|
+
const client = await this.getOrbinumClient();
|
|
3764
|
+
return client.substrate.batchRequest(calls);
|
|
3765
|
+
}
|
|
3701
3766
|
/**
|
|
3702
3767
|
* Sends a single EVM JSON-RPC request and returns the typed result.
|
|
3703
3768
|
* Throws if `evmRpc` was not configured.
|
package/dist/index.mjs
CHANGED
|
@@ -36,12 +36,59 @@ function hexToBigint(hex) {
|
|
|
36
36
|
return BigInt(hex);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
// src/utils/jsonRpcHttp.ts
|
|
40
|
+
var DEFAULT_MAX_RETRIES = 5;
|
|
41
|
+
var DEFAULT_BASE_BACKOFF_MS = 250;
|
|
42
|
+
var DEFAULT_MAX_BACKOFF_MS = 4e3;
|
|
43
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
44
|
+
async function jsonRpcBatch(httpUrl, calls, options = {}) {
|
|
45
|
+
if (calls.length === 0) return [];
|
|
46
|
+
const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
47
|
+
const baseBackoffMs = options.baseBackoffMs ?? DEFAULT_BASE_BACKOFF_MS;
|
|
48
|
+
const maxBackoffMs = options.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS;
|
|
49
|
+
const body = calls.map((c, i) => ({
|
|
50
|
+
id: i,
|
|
51
|
+
jsonrpc: "2.0",
|
|
52
|
+
method: c.method,
|
|
53
|
+
params: c.params ?? []
|
|
54
|
+
}));
|
|
55
|
+
const payload = JSON.stringify(body);
|
|
56
|
+
let attempt = 0;
|
|
57
|
+
for (; ; ) {
|
|
58
|
+
const res = await fetch(httpUrl, {
|
|
59
|
+
method: "POST",
|
|
60
|
+
headers: { "Content-Type": "application/json" },
|
|
61
|
+
body: payload
|
|
62
|
+
});
|
|
63
|
+
if (res.ok) {
|
|
64
|
+
const arr = await res.json();
|
|
65
|
+
const byId = new Map(arr.map((r) => [r.id, r]));
|
|
66
|
+
return calls.map((_, i) => byId.get(i)?.result ?? null);
|
|
67
|
+
}
|
|
68
|
+
const retryable = res.status === 429 || res.status === 503;
|
|
69
|
+
if (!retryable || attempt >= maxRetries) {
|
|
70
|
+
throw new Error(`JSON-RPC HTTP ${res.status}: ${res.statusText}`);
|
|
71
|
+
}
|
|
72
|
+
const retryAfter = Number(res.headers.get("retry-after"));
|
|
73
|
+
const delayMs = Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter * 1e3 : Math.min(baseBackoffMs * 2 ** attempt, maxBackoffMs);
|
|
74
|
+
await sleep(delayMs);
|
|
75
|
+
attempt++;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function wsUrlToHttp(wsUrl) {
|
|
79
|
+
if (wsUrl.startsWith("wss://")) return "https://" + wsUrl.slice("wss://".length);
|
|
80
|
+
if (wsUrl.startsWith("ws://")) return "http://" + wsUrl.slice("ws://".length);
|
|
81
|
+
return wsUrl;
|
|
82
|
+
}
|
|
83
|
+
|
|
39
84
|
// src/substrate/SubstrateClient.ts
|
|
40
85
|
var SubstrateClient = class _SubstrateClient {
|
|
41
|
-
constructor(_papi) {
|
|
86
|
+
constructor(_papi, _httpUrl) {
|
|
42
87
|
this._papi = _papi;
|
|
88
|
+
this._httpUrl = _httpUrl;
|
|
43
89
|
}
|
|
44
90
|
_papi;
|
|
91
|
+
_httpUrl;
|
|
45
92
|
_dynamicBuilder = null;
|
|
46
93
|
_extDecoder = null;
|
|
47
94
|
/**
|
|
@@ -60,7 +107,7 @@ var SubstrateClient = class _SubstrateClient {
|
|
|
60
107
|
)
|
|
61
108
|
)
|
|
62
109
|
]);
|
|
63
|
-
return new _SubstrateClient(papi);
|
|
110
|
+
return new _SubstrateClient(papi, wsUrlToHttp(wsUrl));
|
|
64
111
|
}
|
|
65
112
|
/**
|
|
66
113
|
* Performs a raw JSON-RPC request. Use this for custom Orbinum RPCs
|
|
@@ -69,6 +116,19 @@ var SubstrateClient = class _SubstrateClient {
|
|
|
69
116
|
async request(method, params = []) {
|
|
70
117
|
return this._papi._request(method, params);
|
|
71
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Performs multiple JSON-RPC calls in a single HTTP request (batch). Results
|
|
121
|
+
* are returned in the same order as `calls`, as a typed tuple. A `null`
|
|
122
|
+
* result (or per-call error) maps to `null` in that slot — the call itself
|
|
123
|
+
* only rejects on HTTP/transport failure.
|
|
124
|
+
*
|
|
125
|
+
* Uses the HTTP RPC endpoint (derived from the WS URL); PAPI's WS transport
|
|
126
|
+
* does not expose batching. Ideal for high-throughput backfill: fetch many
|
|
127
|
+
* block hashes / blocks / storage reads in one round-trip instead of N.
|
|
128
|
+
*/
|
|
129
|
+
async batchRequest(calls) {
|
|
130
|
+
return jsonRpcBatch(this._httpUrl, calls);
|
|
131
|
+
}
|
|
72
132
|
/**
|
|
73
133
|
* Returns basic chain information from the node.
|
|
74
134
|
* Combines `system_name`, `system_chain`, `system_properties`, and `state_getRuntimeVersion`.
|
|
@@ -650,14 +710,7 @@ var EvmExplorer = class _EvmExplorer {
|
|
|
650
710
|
async getLatestBlocks(count = 10) {
|
|
651
711
|
const latest = await this.evm.getBlockNumber();
|
|
652
712
|
const nums = Array.from({ length: Math.min(count, latest + 1) }, (_, i) => latest - i);
|
|
653
|
-
const results = await
|
|
654
|
-
nums.map(
|
|
655
|
-
(n) => this.evm.request("eth_getBlockByNumber", [
|
|
656
|
-
`0x${n.toString(16)}`,
|
|
657
|
-
false
|
|
658
|
-
]).catch(() => null)
|
|
659
|
-
)
|
|
660
|
-
);
|
|
713
|
+
const results = await this.evm.batchRequest(nums.map((n) => ({ method: "eth_getBlockByNumber", params: [`0x${n.toString(16)}`, false] }))).catch(() => nums.map(() => null));
|
|
661
714
|
return results.filter((b) => b !== null && !!b.hash).map((b) => this.parseBlock(b));
|
|
662
715
|
}
|
|
663
716
|
/** Returns a single block by number or hash, or `null` if not found. */
|
|
@@ -700,14 +753,18 @@ var EvmExplorer = class _EvmExplorer {
|
|
|
700
753
|
const latest = await this.evm.getBlockNumber();
|
|
701
754
|
const from = Math.max(0, latest - maxBlocks + 1);
|
|
702
755
|
const blockNums = Array.from({ length: latest - from + 1 }, (_, i) => latest - i);
|
|
703
|
-
const
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
756
|
+
const CHUNK = 50;
|
|
757
|
+
const blocks = [];
|
|
758
|
+
for (let i = 0; i < blockNums.length; i += CHUNK) {
|
|
759
|
+
const slice = blockNums.slice(i, i + CHUNK);
|
|
760
|
+
const part = await this.evm.batchRequest(
|
|
761
|
+
slice.map((n) => ({
|
|
762
|
+
method: "eth_getBlockByNumber",
|
|
763
|
+
params: [`0x${n.toString(16)}`, true]
|
|
764
|
+
}))
|
|
765
|
+
).catch(() => slice.map(() => null));
|
|
766
|
+
blocks.push(...part);
|
|
767
|
+
}
|
|
711
768
|
const matchingTxs = [];
|
|
712
769
|
for (const block of blocks) {
|
|
713
770
|
if (!block?.transactions) continue;
|
|
@@ -3571,6 +3628,14 @@ var OrbinumClientProvider = class {
|
|
|
3571
3628
|
const client = await this.getOrbinumClient();
|
|
3572
3629
|
return client.substrate.request(method, params);
|
|
3573
3630
|
}
|
|
3631
|
+
/**
|
|
3632
|
+
* Sends multiple Substrate JSON-RPC calls as a single HTTP batch request.
|
|
3633
|
+
* Returns a tuple of typed results in the same order as `calls`.
|
|
3634
|
+
*/
|
|
3635
|
+
async rpcBatch(calls) {
|
|
3636
|
+
const client = await this.getOrbinumClient();
|
|
3637
|
+
return client.substrate.batchRequest(calls);
|
|
3638
|
+
}
|
|
3574
3639
|
/**
|
|
3575
3640
|
* Sends a single EVM JSON-RPC request and returns the typed result.
|
|
3576
3641
|
* Throws if `evmRpc` was not configured.
|