@talismn/chain-connectors 0.0.13 → 0.0.15

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 (31) hide show
  1. package/dist/index.d.mts +139 -0
  2. package/dist/index.d.ts +139 -0
  3. package/dist/{talismn-chain-connectors.cjs.dev.js → index.js} +496 -510
  4. package/dist/index.js.map +1 -0
  5. package/dist/{talismn-chain-connectors.esm.js → index.mjs} +443 -468
  6. package/dist/index.mjs.map +1 -0
  7. package/package.json +26 -22
  8. package/dist/declarations/src/dot/ChainConnectorDot.d.ts +0 -79
  9. package/dist/declarations/src/dot/ChainConnectorDotStub.d.ts +0 -11
  10. package/dist/declarations/src/dot/IChainConnectorDot.d.ts +0 -10
  11. package/dist/declarations/src/dot/Websocket.d.ts +0 -111
  12. package/dist/declarations/src/dot/helpers.d.ts +0 -15
  13. package/dist/declarations/src/dot/index.d.ts +0 -3
  14. package/dist/declarations/src/eth/ChainConnectorEth.d.ts +0 -10
  15. package/dist/declarations/src/eth/ChainConnectorEthStub.d.ts +0 -10
  16. package/dist/declarations/src/eth/IChainConnectorEth.d.ts +0 -7
  17. package/dist/declarations/src/eth/getChainFromEvmNetwork.d.ts +0 -4
  18. package/dist/declarations/src/eth/getEvmNetworkPublicClient.d.ts +0 -4
  19. package/dist/declarations/src/eth/getEvmNetworkWalletClient.d.ts +0 -7
  20. package/dist/declarations/src/eth/getTransportForEvmNetwork.d.ts +0 -8
  21. package/dist/declarations/src/eth/index.d.ts +0 -3
  22. package/dist/declarations/src/index.d.ts +0 -3
  23. package/dist/declarations/src/log.d.ts +0 -2
  24. package/dist/declarations/src/sol/ChainConnectorSol.d.ts +0 -8
  25. package/dist/declarations/src/sol/ChainConnectorSolStub.d.ts +0 -8
  26. package/dist/declarations/src/sol/IChainConnectorSol.d.ts +0 -5
  27. package/dist/declarations/src/sol/getSolConnection.d.ts +0 -3
  28. package/dist/declarations/src/sol/index.d.ts +0 -3
  29. package/dist/talismn-chain-connectors.cjs.d.ts +0 -1
  30. package/dist/talismn-chain-connectors.cjs.js +0 -7
  31. package/dist/talismn-chain-connectors.cjs.prod.js +0 -1243
@@ -1,25 +1,93 @@
1
- import { throwAfter, Deferred, sleep, isTruthy } from '@talismn/util';
2
- import anylogger from 'anylogger';
3
- import { RpcCoder } from '@polkadot/rpc-provider/coder';
4
- import { getWSErrorString } from '@polkadot/rpc-provider/ws/errors';
5
- import { isChildClass, isUndefined, isNull, objectSpread } from '@polkadot/util';
6
- import { xglobal } from '@polkadot/x-global';
7
- import { WebSocket } from '@polkadot/x-ws';
8
- import EventEmitter from 'eventemitter3';
9
- import { WsProvider } from '@polkadot/rpc-provider';
10
- import { fallback, http, createPublicClient, createWalletClient } from 'viem';
11
- import { fromPairs, toPairs, camelCase } from 'lodash-es';
12
- import * as viemChains from 'viem/chains';
13
- import { Connection } from '@solana/web3.js';
14
-
15
- var packageJson = {
16
- name: "@talismn/chain-connectors"};
17
-
18
- var log = anylogger(packageJson.name);
1
+ // src/dot/ChainConnectorDot.ts
2
+ import { Deferred, isTruthy, sleep, throwAfter } from "@talismn/util";
3
+
4
+ // src/log.ts
5
+ import anylogger from "anylogger";
6
+
7
+ // package.json
8
+ var package_default = {
9
+ name: "@talismn/chain-connectors",
10
+ version: "0.0.15",
11
+ author: "Talisman",
12
+ homepage: "https://talisman.xyz",
13
+ license: "GPL-3.0-or-later",
14
+ publishConfig: {
15
+ access: "public"
16
+ },
17
+ repository: {
18
+ directory: "packages/chain-connectors",
19
+ type: "git",
20
+ url: "https://github.com/TalismanSociety/talisman.git"
21
+ },
22
+ main: "./dist/index.js",
23
+ module: "./dist/index.mjs",
24
+ files: [
25
+ "dist"
26
+ ],
27
+ engines: {
28
+ node: ">=20"
29
+ },
30
+ scripts: {
31
+ test: "vitest run",
32
+ clean: "rm -rf dist .turbo node_modules",
33
+ build: "tsup --silent",
34
+ typecheck: "tsc --noEmit"
35
+ },
36
+ dependencies: {
37
+ "@solana/web3.js": "^1.98.2",
38
+ "@talismn/chaindata-provider": "workspace:*",
39
+ "@talismn/connection-meta": "workspace:*",
40
+ "@talismn/util": "workspace:*",
41
+ anylogger: "^1.0.11",
42
+ eventemitter3: "^5.0.0",
43
+ "lodash-es": "4.17.21",
44
+ viem: "^2.27.3"
45
+ },
46
+ devDependencies: {
47
+ "@polkadot/rpc-provider": "16.1.2",
48
+ "@polkadot/util": "13.5.3",
49
+ "@polkadot/x-global": "13.5.3",
50
+ "@polkadot/x-ws": "13.5.3",
51
+ "@talismn/tsconfig": "workspace:*",
52
+ typescript: "^5.6.3"
53
+ },
54
+ peerDependencies: {
55
+ "@polkadot/rpc-provider": "*",
56
+ "@polkadot/util": "*",
57
+ "@polkadot/x-global": "*",
58
+ "@polkadot/x-ws": "*"
59
+ },
60
+ types: "./dist/index.d.ts",
61
+ exports: {
62
+ ".": {
63
+ "@talismn/source": "./src/index.ts",
64
+ import: {
65
+ types: "./dist/index.d.mts",
66
+ default: "./dist/index.mjs"
67
+ },
68
+ require: {
69
+ types: "./dist/index.d.ts",
70
+ default: "./dist/index.js"
71
+ }
72
+ }
73
+ }
74
+ };
19
75
 
20
- const twoSecondsMs = 2 * 1000;
21
- const twoMinutesMs = 2 * 60 * 1000;
22
- class ExponentialBackoff {
76
+ // src/log.ts
77
+ var log_default = anylogger(package_default.name);
78
+
79
+ // src/dot/Websocket.ts
80
+ import { RpcCoder } from "@polkadot/rpc-provider/coder";
81
+ import { getWSErrorString } from "@polkadot/rpc-provider/ws/errors";
82
+ import { isChildClass, isNull, isUndefined, objectSpread } from "@polkadot/util";
83
+ import { xglobal } from "@polkadot/x-global";
84
+ import { WebSocket } from "@polkadot/x-ws";
85
+ import EventEmitter from "eventemitter3";
86
+
87
+ // src/dot/helpers.ts
88
+ var twoSecondsMs = 2 * 1e3;
89
+ var twoMinutesMs = 2 * 60 * 1e3;
90
+ var ExponentialBackoff = class {
23
91
  #minInterval;
24
92
  #maxInterval;
25
93
  #nextInterval = 0;
@@ -69,46 +137,25 @@ class ExponentialBackoff {
69
137
  #capMax(value) {
70
138
  return Math.min(this.#maxInterval, value);
71
139
  }
72
- }
73
-
74
- // to account for new requirement for generic arg in this type https://github.com/polkadot-js/api/commit/f4c2b150d3d69d43c56699613666b96dd0a763f4#diff-f87c17bc7fae027ec6d43bac5fc089614d9fa097f466aa2be333b44cee81f0fd
75
- // TODO incrementally replace 'unknown' with proper types where possible
140
+ };
76
141
 
77
- const ALIASES = {
142
+ // src/dot/Websocket.ts
143
+ var ALIASES = {
78
144
  chain_finalisedHead: "chain_finalizedHead",
79
145
  chain_subscribeFinalisedHeads: "chain_subscribeFinalizedHeads",
80
146
  chain_unsubscribeFinalisedHeads: "chain_unsubscribeFinalizedHeads"
81
147
  };
82
- const DEFAULT_TIMEOUT_MS = 60 * 1000;
83
- const TIMEOUT_INTERVAL = 5_000;
148
+ var DEFAULT_TIMEOUT_MS = 60 * 1e3;
149
+ var TIMEOUT_INTERVAL = 5e3;
84
150
  function eraseRecord(record, cb) {
85
- Object.keys(record).forEach(key => {
151
+ Object.keys(record).forEach((key) => {
86
152
  if (cb) {
87
153
  cb(record[key]);
88
154
  }
89
155
  delete record[key];
90
156
  });
91
157
  }
92
-
93
- /**
94
- * # @talismn/chain-connector/Websocket
95
- *
96
- * @name Websocket
97
- *
98
- * @description The WebSocket Provider allows sending requests using WebSocket to a WebSocket RPC server TCP port. Unlike the [[HttpProvider]], it does support subscriptions and allows listening to events such as new blocks or balance changes.
99
- *
100
- * @example
101
- * <BR>
102
- *
103
- * ```javascript
104
- * import { Websocket } from '@talismn/chain-connector';
105
- *
106
- * const provider = new Websocket('ws://127.0.0.1:9944');
107
- * ```
108
- *
109
- * @see [[HttpProvider]]
110
- */
111
- class Websocket {
158
+ var Websocket = class _Websocket {
112
159
  #coder;
113
160
  #endpoints;
114
161
  #headers;
@@ -124,7 +171,6 @@ class Websocket {
124
171
  #timeoutId = null;
125
172
  #websocket;
126
173
  #timeout;
127
-
128
174
  /**
129
175
  * @param {string | string[]} endpoint The endpoint url. Usually `ws://ip:9944` or `wss://ip:9944`, may provide an array of endpoint strings.
130
176
  * @param {Record<string, string>} headers The headers provided to the underlying WebSocket
@@ -135,9 +181,9 @@ class Websocket {
135
181
  if (endpoints.length === 0) {
136
182
  throw new Error("Websocket requires at least one Endpoint");
137
183
  }
138
- endpoints.forEach(endpoint => {
139
- if (!/^(wss|ws):\/\//.test(endpoint)) {
140
- throw new Error(`Endpoint should start with 'ws://', received '${endpoint}'`);
184
+ endpoints.forEach((endpoint2) => {
185
+ if (!/^(wss|ws):\/\//.test(endpoint2)) {
186
+ throw new Error(`Endpoint should start with 'ws://', received '${endpoint2}'`);
141
187
  }
142
188
  });
143
189
  this.#eventemitter = new EventEmitter();
@@ -151,30 +197,26 @@ class Websocket {
151
197
  this.#timeout = timeout || DEFAULT_TIMEOUT_MS;
152
198
  if (this.#autoConnectBackoff.isActive) {
153
199
  this.connectWithRetry().catch(() => {
154
- // does not throw
155
200
  });
156
201
  }
157
- this.#isReadyPromise = new Promise(resolve => {
202
+ this.#isReadyPromise = new Promise((resolve) => {
158
203
  this.#eventemitter.once("connected", () => {
159
204
  resolve(this);
160
205
  });
161
206
  });
162
207
  }
163
-
164
208
  /**
165
209
  * @summary `true` when this provider supports subscriptions
166
210
  */
167
211
  get hasSubscriptions() {
168
212
  return true;
169
213
  }
170
-
171
214
  /**
172
215
  * @summary `true` when this provider supports clone()
173
216
  */
174
217
  get isClonable() {
175
218
  return true;
176
219
  }
177
-
178
220
  /**
179
221
  * @summary Whether the node is connected or not.
180
222
  * @return {boolean} true if connected
@@ -182,7 +224,6 @@ class Websocket {
182
224
  get isConnected() {
183
225
  return this.#isConnected;
184
226
  }
185
-
186
227
  /**
187
228
  * @description Promise that resolves the first time we are connected and loaded
188
229
  */
@@ -192,54 +233,46 @@ class Websocket {
192
233
  get endpoint() {
193
234
  return this.#endpoints[this.#endpointIndex];
194
235
  }
195
-
196
236
  /**
197
237
  * @description Returns a clone of the object
198
238
  */
199
239
  clone() {
200
- return new Websocket(this.#endpoints);
240
+ return new _Websocket(this.#endpoints);
201
241
  }
202
242
  selectEndpointIndex(endpoints) {
203
243
  this.#endpointsTriedSinceLastConnection += 1;
204
244
  return (this.#endpointIndex + 1) % endpoints.length;
205
245
  }
206
-
207
246
  /**
208
247
  * @summary Manually connect
209
248
  * @description The [[Websocket]] connects automatically by default, however if you decided otherwise, you may
210
249
  * connect manually using this method.
211
250
  */
212
- // eslint-disable-next-line @typescript-eslint/require-await
213
251
  async connect() {
214
252
  if (this.#websocket) {
215
253
  throw new Error("WebSocket is already connected");
216
254
  }
217
255
  try {
218
256
  this.#endpointIndex = this.selectEndpointIndex(this.#endpoints);
219
-
220
- // the as typeof WebSocket here is Deno-specific - not available on the globalThis
221
- this.#websocket = typeof xglobal.WebSocket !== "undefined" && isChildClass(xglobal.WebSocket, WebSocket) ? new WebSocket(this.endpoint) :
222
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
223
- // @ts-ignore - WS may be an instance of ws, which supports options
224
- new WebSocket(this.endpoint, undefined, {
225
- headers: this.#headers
226
- });
257
+ this.#websocket = typeof xglobal.WebSocket !== "undefined" && isChildClass(xglobal.WebSocket, WebSocket) ? new WebSocket(this.endpoint) : (
258
+ // @ts-expect-error - WS may be an instance of ws, which supports options
259
+ new WebSocket(this.endpoint, void 0, {
260
+ headers: this.#headers
261
+ })
262
+ );
227
263
  if (this.#websocket) {
228
264
  this.#websocket.onclose = this.#onSocketClose;
229
265
  this.#websocket.onerror = this.#onSocketError;
230
266
  this.#websocket.onmessage = this.#onSocketMessage;
231
267
  this.#websocket.onopen = this.#onSocketOpen;
232
268
  }
233
-
234
- // timeout any handlers that have not had a response
235
269
  this.#timeoutId = setInterval(() => this.#timeoutHandlers(), TIMEOUT_INTERVAL);
236
270
  } catch (error) {
237
- log.error(error);
271
+ log_default.error(error);
238
272
  this.#emit("error", error);
239
273
  throw error;
240
274
  }
241
275
  }
242
-
243
276
  /**
244
277
  * @description Connect, never throwing an error, but rather forcing a retry
245
278
  */
@@ -247,48 +280,39 @@ class Websocket {
247
280
  if (!this.#autoConnectBackoff.isActive) return;
248
281
  try {
249
282
  await this.connect();
250
- } catch (error) {
283
+ } catch {
251
284
  this.scheduleNextRetry();
252
285
  }
253
286
  }
254
287
  scheduleNextRetry() {
255
288
  if (!this.#autoConnectBackoff.isActive) return;
256
289
  const haveTriedAllEndpoints = this.#endpointsTriedSinceLastConnection > 0 && this.#endpointsTriedSinceLastConnection % this.#endpoints.length === 0;
257
- setTimeout(() => {
258
- this.connectWithRetry().catch(() => {
259
- // does not throw
260
- });
261
- }, haveTriedAllEndpoints ? this.#autoConnectBackoff.next : 0);
262
-
263
- // Increase backoff when we've tried all endpoints
290
+ setTimeout(
291
+ () => {
292
+ this.connectWithRetry().catch(() => {
293
+ });
294
+ },
295
+ haveTriedAllEndpoints ? this.#autoConnectBackoff.next : 0
296
+ );
264
297
  if (haveTriedAllEndpoints) this.#autoConnectBackoff.increase();
265
-
266
- // Fire a stale-rpcs event when we've tried all endpoints in the list
267
- // but haven't successfully connected to any of them
268
- if (haveTriedAllEndpoints) this.#emit("stale-rpcs", {
269
- nextBackoffInterval: this.#autoConnectBackoff.next
270
- });
298
+ if (haveTriedAllEndpoints)
299
+ this.#emit("stale-rpcs", { nextBackoffInterval: this.#autoConnectBackoff.next });
271
300
  }
272
-
273
301
  /**
274
302
  * @description Manually disconnect from the connection, clearing auto-connect logic
275
303
  */
276
- // eslint-disable-next-line @typescript-eslint/require-await
277
304
  async disconnect() {
278
- // switch off autoConnect, we are in manual mode now
279
305
  this.#autoConnectBackoff.disable();
280
306
  try {
281
307
  if (this.#websocket) {
282
- // 1000 - Normal closure; the connection successfully completed
283
- this.#websocket.close(1000);
308
+ this.#websocket.close(1e3);
284
309
  }
285
310
  } catch (error) {
286
- log.error(error);
311
+ log_default.error(error);
287
312
  this.#emit("error", error);
288
313
  throw error;
289
314
  }
290
315
  }
291
-
292
316
  /**
293
317
  * @summary Listens on events after having subscribed using the [[subscribe]] function.
294
318
  * @param {ProviderInterfaceEmitted} type Event
@@ -301,16 +325,14 @@ class Websocket {
301
325
  this.#eventemitter.removeListener(type, sub);
302
326
  };
303
327
  }
304
-
305
328
  /**
306
329
  * @summary Send JSON data using WebSockets to configured HTTP Endpoint or queue.
307
330
  * @param method The RPC methods to execute
308
331
  * @param params Encoded parameters as applicable for the method
309
332
  * @param subscription Subscription details (internally used)
310
333
  */
311
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
312
- send(method, params, /** @deprecated \@talismn/chain-connector doesn't implement a cache */
313
- isCacheable, subscription) {
334
+ // biome-ignore lint/suspicious/noExplicitAny: legacy
335
+ send(method, params, _isCacheable, subscription) {
314
336
  const [id, body] = this.#coder.encodeJson(method, params);
315
337
  const resultPromise = this.#send(id, body, method, params, subscription);
316
338
  return resultPromise;
@@ -324,9 +346,6 @@ class Websocket {
324
346
  const callback = (error, result) => {
325
347
  error ? reject(error) : resolve(result);
326
348
  };
327
-
328
- // log.debug(() => ["calling", method, body])
329
-
330
349
  this.#handlers[id] = {
331
350
  callback,
332
351
  method,
@@ -340,7 +359,6 @@ class Websocket {
340
359
  }
341
360
  });
342
361
  }
343
-
344
362
  /**
345
363
  * @name subscribe
346
364
  * @summary Allows subscribing to a specific event.
@@ -360,42 +378,32 @@ class Websocket {
360
378
  * ```
361
379
  */
362
380
  subscribe(type, method, params, callback) {
363
- return this.send(method, params, false, {
364
- callback,
365
- type
366
- });
381
+ return this.send(method, params, false, { callback, type });
367
382
  }
368
-
369
383
  /**
370
384
  * @summary Allows unsubscribing to subscriptions made with [[subscribe]].
371
385
  */
372
386
  async unsubscribe(type, method, id) {
373
387
  const subscription = `${type}::${id}`;
374
-
375
- // FIXME This now could happen with re-subscriptions. The issue is that with a re-sub
376
- // the assigned id now does not match what the API user originally received. It has
377
- // a slight complication in solving - since we cannot rely on the send id, but rather
378
- // need to find the actual subscription id to map it
379
388
  if (isUndefined(this.#subscriptions[subscription])) {
380
- // log.debug(() => `Unable to find active subscription=${subscription}`)
381
-
382
389
  return false;
383
390
  }
384
391
  delete this.#subscriptions[subscription];
385
392
  try {
386
393
  return this.isConnected && !isNull(this.#websocket) ? this.send(method, [id]) : true;
387
- } catch (error) {
394
+ } catch {
388
395
  return false;
389
396
  }
390
397
  }
391
398
  #emit = (type, ...args) => {
392
399
  this.#eventemitter.emit(type, ...args);
393
400
  };
394
- #onSocketClose = event => {
395
- const error = new Error(`disconnected from ${this.endpoint}: ${event.code}:: ${event.reason || getWSErrorString(event.code)}`);
401
+ #onSocketClose = (event) => {
402
+ const error = new Error(
403
+ `disconnected from ${this.endpoint}: ${event.code}:: ${event.reason || getWSErrorString(event.code)}`
404
+ );
396
405
  if (this.#autoConnectBackoff.isActive) {
397
- // 1000 is a normal closure and should not be logged as an error
398
- if (event.code !== 1000) log.error(error.message);
406
+ if (event.code !== 1e3) log_default.error(error.message);
399
407
  }
400
408
  this.#isConnected = false;
401
409
  if (this.#websocket) {
@@ -409,52 +417,36 @@ class Websocket {
409
417
  clearInterval(this.#timeoutId);
410
418
  this.#timeoutId = null;
411
419
  }
412
-
413
- // reject all hanging requests
414
- eraseRecord(this.#handlers, h => {
420
+ eraseRecord(this.#handlers, (h) => {
415
421
  try {
416
- h.callback(error, undefined);
422
+ h.callback(error, void 0);
417
423
  } catch (err) {
418
- // does not throw
419
- log.error(err);
424
+ log_default.error(err);
420
425
  }
421
426
  });
422
427
  eraseRecord(this.#waitingForId);
423
428
  this.#emit("disconnected");
424
429
  this.scheduleNextRetry();
425
430
  };
426
- #onSocketError = error => {
427
- // log.debug(() => ["socket error", error])
431
+ #onSocketError = (error) => {
428
432
  this.#emit("error", error);
429
433
  };
430
- #onSocketMessage = message => {
431
- // log.debug(() => ["received", message.data])
434
+ #onSocketMessage = (message) => {
432
435
  try {
433
436
  const response = JSON.parse(message.data);
434
437
  return isUndefined(response.method) ? this.#onSocketMessageResult(response) : this.#onSocketMessageSubscribe(response);
435
438
  } catch (e) {
436
- this.#emit("error", new Error("Invalid websocket message received", {
437
- cause: e
438
- }));
439
+ this.#emit("error", new Error("Invalid websocket message received", { cause: e }));
439
440
  }
440
441
  };
441
- #onSocketMessageResult = response => {
442
+ #onSocketMessageResult = (response) => {
442
443
  const handler = this.#handlers[response.id];
443
444
  if (!handler) {
444
- // log.debug(() => `Unable to find handler for id=${response.id}`)
445
-
446
445
  return;
447
446
  }
448
447
  try {
449
- const {
450
- method,
451
- params,
452
- subscription
453
- } = handler;
448
+ const { method, params, subscription } = handler;
454
449
  const result = this.#coder.decodeResponse(response);
455
-
456
- // first send the result - in case of subs, we may have an update
457
- // immediately if we have some queued results already
458
450
  handler.callback(null, result);
459
451
  if (subscription) {
460
452
  const subId = `${subscription.type}::${result}`;
@@ -462,46 +454,35 @@ class Websocket {
462
454
  method,
463
455
  params
464
456
  });
465
-
466
- // if we have a result waiting for this subscription already
467
457
  if (this.#waitingForId[subId]) {
468
458
  this.#onSocketMessageSubscribe(this.#waitingForId[subId]);
469
459
  }
470
460
  }
471
461
  } catch (error) {
472
- handler.callback(error, undefined);
462
+ handler.callback(error, void 0);
473
463
  }
474
464
  delete this.#handlers[response.id];
475
465
  };
476
- #onSocketMessageSubscribe = response => {
466
+ #onSocketMessageSubscribe = (response) => {
477
467
  const method = ALIASES[response.method] || response.method || "invalid";
478
468
  const subId = `${method}::${response.params.subscription}`;
479
469
  const handler = this.#subscriptions[subId];
480
470
  if (!handler) {
481
- // store the JSON, we could have out-of-order subid coming in
482
471
  this.#waitingForId[subId] = response;
483
-
484
- // log.debug(() => `Unable to find handler for subscription=${subId}`)
485
-
486
472
  return;
487
473
  }
488
-
489
- // housekeeping
490
474
  delete this.#waitingForId[subId];
491
475
  try {
492
476
  const result = this.#coder.decodeResponse(response);
493
477
  handler.callback(null, result);
494
478
  } catch (error) {
495
- handler.callback(error, undefined);
479
+ handler.callback(error, void 0);
496
480
  }
497
481
  };
498
482
  #onSocketOpen = () => {
499
483
  if (this.#websocket === null) {
500
484
  throw new Error("WebSocket cannot be null in onOpen");
501
485
  }
502
-
503
- // log.debug(() => ["connected to", this.endpoint])
504
-
505
486
  this.#isConnected = true;
506
487
  this.#endpointsTriedSinceLastConnection = 0;
507
488
  this.#autoConnectBackoff.reset();
@@ -512,26 +493,19 @@ class Websocket {
512
493
  #resubscribe = () => {
513
494
  const subscriptions = this.#subscriptions;
514
495
  this.#subscriptions = {};
515
- Promise.all(Object.keys(subscriptions).map(async id => {
516
- const {
517
- callback,
518
- method,
519
- params,
520
- type
521
- } = subscriptions[id];
522
-
523
- // only re-create subscriptions which are not in author (only area where
524
- // transactions are created, i.e. submissions such as 'author_submitAndWatchExtrinsic'
525
- // are not included (and will not be re-broadcast)
526
- if (type.startsWith("author_")) {
527
- return;
528
- }
529
- try {
530
- await this.subscribe(type, method, params, callback);
531
- } catch (error) {
532
- log.error(error);
533
- }
534
- })).catch(log.error);
496
+ Promise.all(
497
+ Object.keys(subscriptions).map(async (id) => {
498
+ const { callback, method, params, type } = subscriptions[id];
499
+ if (type.startsWith("author_")) {
500
+ return;
501
+ }
502
+ try {
503
+ await this.subscribe(type, method, params, callback);
504
+ } catch (error) {
505
+ log_default.error(error);
506
+ }
507
+ })
508
+ ).catch(log_default.error);
535
509
  };
536
510
  #timeoutHandlers = () => {
537
511
  const now = Date.now();
@@ -540,63 +514,65 @@ class Websocket {
540
514
  const handler = this.#handlers[ids[i]];
541
515
  if (now - handler.start > this.#timeout) {
542
516
  try {
543
- handler.callback(new Error(`No response received from RPC endpoint in ${this.#timeout / 1000}s`), undefined);
517
+ handler.callback(
518
+ new Error(`No response received from RPC endpoint in ${this.#timeout / 1e3}s`),
519
+ void 0
520
+ );
544
521
  } catch {
545
- // ignore
546
522
  }
547
523
  delete this.#handlers[ids[i]];
548
524
  }
549
525
  }
550
526
  };
551
- }
527
+ };
552
528
 
553
- // errors that require an rpc fallback
554
- // https://docs.blastapi.io/blast-documentation/things-you-need-to-know/error-reference
555
- const BAD_RPC_ERRORS = {
529
+ // src/dot/ChainConnectorDot.ts
530
+ var BAD_RPC_ERRORS = {
556
531
  "-32097": "Rate limit exceeded",
557
532
  "-32098": "Capacity exceeded"
558
533
  };
559
- class ChainConnectionError extends Error {
534
+ var ChainConnectionError = class extends Error {
535
+ type;
536
+ chainId;
560
537
  constructor(chainId, options) {
561
538
  super(`Unable to connect to chain ${chainId}`, options);
562
539
  this.type = "CHAIN_CONNECTION_ERROR";
563
540
  this.chainId = chainId;
564
541
  }
565
- }
566
- class StaleRpcError extends Error {
542
+ };
543
+ var StaleRpcError = class extends Error {
544
+ type;
545
+ chainId;
567
546
  constructor(chainId, options) {
568
547
  super(`RPCs are stale/unavailable for chain ${chainId}`, options);
569
548
  this.type = "STALE_RPC_ERROR";
570
549
  this.chainId = chainId;
571
550
  }
572
- }
573
- class WebsocketAllocationExhaustedError extends Error {
551
+ };
552
+ var WebsocketAllocationExhaustedError = class extends Error {
553
+ type;
554
+ chainId;
574
555
  constructor(chainId, options) {
575
- super(`No websockets are available from the browser pool to connect to chain ${chainId}`, options);
556
+ super(
557
+ `No websockets are available from the browser pool to connect to chain ${chainId}`,
558
+ options
559
+ );
576
560
  this.type = "WEBSOCKET_ALLOCATION_EXHAUSTED_ERROR";
577
561
  this.chainId = chainId;
578
562
  }
579
- }
580
- class CallerUnsubscribedError extends Error {
563
+ };
564
+ var CallerUnsubscribedError = class extends Error {
565
+ type;
566
+ chainId;
567
+ unsubscribeMethod;
581
568
  constructor(chainId, unsubscribeMethod, options) {
582
569
  super(`Caller unsubscribed from ${chainId}`, options);
583
570
  this.type = "CALLER_UNSUBSCRIBED_ERROR";
584
571
  this.chainId = chainId;
585
572
  this.unsubscribeMethod = unsubscribeMethod;
586
573
  }
587
- }
588
- /**
589
- * ChainConnector provides an interface similar to WsProvider, but with three points of difference:
590
- *
591
- * 1. ChainConnector methods all accept a `chainId` instead of an array of RPCs. RPCs are then fetched internally from chaindata.
592
- * 2. ChainConnector creates only one `WsProvider` per chain and ensures that all downstream requests to a chain share the one socket connection.
593
- * 3. Subscriptions return a callable `unsubscribe` method instead of an id.
594
- *
595
- * Additionally, when run on the clientside of a dapp where `window.talismanSub` is available, instead of spinning up new websocket
596
- * connections this class will forward all requests through to the wallet backend - where another instance of this class will
597
- * handle the websocket connections.
598
- */
599
- class ChainConnectorDot {
574
+ };
575
+ var ChainConnectorDot = class {
600
576
  #chaindataChainProvider;
601
577
  #connectionMetaDb;
602
578
  #socketConnections = {};
@@ -606,14 +582,12 @@ class ChainConnectorDot {
606
582
  this.#chaindataChainProvider = chaindataChainProvider;
607
583
  this.#connectionMetaDb = connectionMetaDb;
608
584
  if (this.#connectionMetaDb) {
609
- this.#chaindataChainProvider.getNetworkIds("polkadot").then(chainIds => {
610
- // tidy up connectionMeta for chains which no longer exist
585
+ this.#chaindataChainProvider.getNetworkIds("polkadot").then((chainIds) => {
611
586
  this.#connectionMetaDb?.chainPriorityRpcs.where("id").noneOf(chainIds).delete();
612
587
  this.#connectionMetaDb?.chainBackoffInterval.where("id").noneOf(chainIds).delete();
613
588
  });
614
589
  }
615
590
  }
616
-
617
591
  /**
618
592
  * Creates a facade over this ChainConnector which conforms to the PJS ProviderInterface
619
593
  * @example // Using a chainConnector as a Provider for an ApiPromise
@@ -621,7 +595,7 @@ class ChainConnectorDot {
621
595
  * const api = new ApiPromise({ provider })
622
596
  */
623
597
  asProvider(chainId) {
624
- const unsubHandler = new Map();
598
+ const unsubHandler = /* @__PURE__ */ new Map();
625
599
  const providerFacade = {
626
600
  hasSubscriptions: true,
627
601
  isClonable: false,
@@ -629,12 +603,15 @@ class ChainConnectorDot {
629
603
  clone: () => providerFacade,
630
604
  connect: () => Promise.resolve(),
631
605
  disconnect: () => Promise.resolve(),
632
- on: () => () => {},
633
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
606
+ on: () => () => {
607
+ },
608
+ // biome-ignore lint/suspicious/noExplicitAny: legacy
634
609
  send: async (method, params, isCacheable) => await this.send(chainId, method, params, isCacheable),
635
610
  subscribe: async (type, method, params, cb) => {
636
611
  const unsubscribe = await this.subscribe(chainId, method, type, params, cb);
637
- const subscriptionId = this.getExclusiveRandomId([...unsubHandler.keys()].map(Number)).toString();
612
+ const subscriptionId = this.getExclusiveRandomId(
613
+ [...unsubHandler.keys()].map(Number)
614
+ ).toString();
638
615
  unsubHandler.set(subscriptionId, unsubscribe);
639
616
  return subscriptionId;
640
617
  },
@@ -646,141 +623,122 @@ class ChainConnectorDot {
646
623
  };
647
624
  return providerFacade;
648
625
  }
649
-
650
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
626
+ // biome-ignore lint/suspicious/noExplicitAny: legacy
651
627
  async send(chainId, method, params, isCacheable, extraOptions) {
652
628
  const talismanSub = this.getTalismanSub();
653
- if (talismanSub !== undefined) {
629
+ if (talismanSub !== void 0) {
654
630
  try {
655
631
  const chain = await this.#chaindataChainProvider.getNetworkById(chainId, "polkadot");
656
632
  if (!chain) throw new Error(`Chain ${chainId} not found in store`);
657
- const {
658
- genesisHash
659
- } = chain;
660
- if (typeof genesisHash !== "string") throw new Error(`Chain ${chainId} has no genesisHash in store`);
633
+ const { genesisHash } = chain;
634
+ if (typeof genesisHash !== "string")
635
+ throw new Error(`Chain ${chainId} has no genesisHash in store`);
661
636
  return await talismanSub.send(genesisHash, method, params);
662
637
  } catch (error) {
663
- log.warn(`Failed to make wallet-proxied send request for chain ${chainId}. Falling back to plain websocket`, error);
638
+ log_default.warn(
639
+ `Failed to make wallet-proxied send request for chain ${chainId}. Falling back to plain websocket`,
640
+ error
641
+ );
664
642
  }
665
643
  }
666
644
  try {
667
- // eslint-disable-next-line no-var
668
645
  var [socketUserId, ws] = await this.connectChainSocket(chainId);
669
646
  } catch (error) {
670
- throw new StaleRpcError(chainId, {
671
- cause: error
672
- });
647
+ throw new StaleRpcError(chainId, { cause: error });
673
648
  }
674
649
  try {
675
- // wait for ws to be ready, but don't wait forever
676
- const timeout = 15_000; // 15 seconds in milliseconds
650
+ const timeout = 15e3;
677
651
  await this.waitForWs(ws, timeout);
678
652
  } catch (error) {
679
653
  await this.disconnectChainSocket(chainId, socketUserId);
680
- throw new ChainConnectionError(chainId, {
681
- cause: error
682
- });
654
+ throw new ChainConnectionError(chainId, { cause: error });
683
655
  }
684
656
  try {
685
- const timeout = 30_000; // throw after 30 seconds if no response
686
- // eslint-disable-next-line no-var
687
- var response = await Promise.race([ws.send(method, params, isCacheable), throwAfter(timeout, "TIMEOUT")]);
657
+ const timeout = 3e4;
658
+ var response = await Promise.race([
659
+ ws.send(method, params, isCacheable),
660
+ throwAfter(timeout, "TIMEOUT")
661
+ ]);
688
662
  } catch (err) {
689
663
  const error = err;
690
664
  if (error?.message === "TIMEOUT") {
691
- log.error(`ChainConnector timeout`, {
692
- chainId,
693
- endpoint: ws.endpoint,
694
- error
695
- });
665
+ log_default.error(`ChainConnector timeout`, { chainId, endpoint: ws.endpoint, error });
696
666
  await this.updateRpcPriority(chainId, ws.endpoint, "last");
697
667
  await this.reset(chainId);
698
668
  throw new Error("Timeout");
699
669
  }
700
670
  const badRpcError = BAD_RPC_ERRORS[error?.code?.toString() ?? ""];
701
671
  if (badRpcError) {
702
- log.error(`ChainConnector ${badRpcError}`, {
703
- error,
704
- chainId,
705
- endpoint: ws.endpoint
706
- });
672
+ log_default.error(`ChainConnector ${badRpcError}`, { error, chainId, endpoint: ws.endpoint });
707
673
  await this.updateRpcPriority(chainId, ws.endpoint, "last");
708
674
  await this.reset(chainId);
709
675
  throw new Error(badRpcError);
710
676
  }
711
- if (!extraOptions?.expectErrors) log.error(`Failed to send ${method} on chain ${chainId}\nparams: ${JSON.stringify(params)}`, {
712
- error,
713
- endpoint: ws.endpoint
714
- });
677
+ if (!extraOptions?.expectErrors)
678
+ log_default.error(
679
+ `Failed to send ${method} on chain ${chainId}
680
+ params: ${JSON.stringify(params)}`,
681
+ {
682
+ error,
683
+ endpoint: ws.endpoint
684
+ }
685
+ );
715
686
  await this.disconnectChainSocket(chainId, socketUserId);
716
687
  throw error;
717
688
  }
718
689
  await this.disconnectChainSocket(chainId, socketUserId);
719
690
  return response;
720
691
  }
721
- async subscribe(chainId, subscribeMethod, responseMethod, params, callback, timeout = 30_000 // 30 seconds in milliseconds
722
- ) {
692
+ async subscribe(chainId, subscribeMethod, responseMethod, params, callback, timeout = 3e4) {
723
693
  const talismanSub = this.getTalismanSub();
724
- if (talismanSub !== undefined) {
694
+ if (talismanSub !== void 0) {
725
695
  try {
726
696
  const chain = await this.#chaindataChainProvider.getNetworkById(chainId, "polkadot");
727
697
  if (!chain) throw new Error(`Chain ${chainId} not found in store`);
728
- const {
729
- genesisHash
730
- } = chain;
731
- if (typeof genesisHash !== "string") throw new Error(`Chain ${chainId} has no genesisHash in store`);
732
- const subscriptionId = await talismanSub.subscribe(genesisHash, subscribeMethod, responseMethod, params, callback, timeout);
733
- return unsubscribeMethod => talismanSub.unsubscribe(subscriptionId, unsubscribeMethod);
698
+ const { genesisHash } = chain;
699
+ if (typeof genesisHash !== "string")
700
+ throw new Error(`Chain ${chainId} has no genesisHash in store`);
701
+ const subscriptionId = await talismanSub.subscribe(
702
+ genesisHash,
703
+ subscribeMethod,
704
+ responseMethod,
705
+ params,
706
+ callback,
707
+ timeout
708
+ );
709
+ return (unsubscribeMethod) => talismanSub.unsubscribe(subscriptionId, unsubscribeMethod);
734
710
  } catch (error) {
735
- log.warn(`Failed to create wallet-proxied subscription for chain ${chainId}. Falling back to plain websocket`, error);
711
+ log_default.warn(
712
+ `Failed to create wallet-proxied subscription for chain ${chainId}. Falling back to plain websocket`,
713
+ error
714
+ );
736
715
  }
737
716
  }
738
717
  try {
739
- // eslint-disable-next-line no-var
740
718
  var [socketUserId, ws] = await this.connectChainSocket(chainId);
741
719
  } catch (error) {
742
- throw new StaleRpcError(chainId, {
743
- cause: error
744
- });
720
+ throw new StaleRpcError(chainId, { cause: error });
745
721
  }
746
-
747
- // by using this `Deferred` promise
748
- // (a promise which can be resolved or rejected by code outside of the scope of the promise's constructor)
749
- // we can queue up our async cleanup on the promise and then immediately return an unsubscribe method to the caller
750
722
  const unsubDeferred = Deferred();
751
- // we return this to the caller so that they can let us know when they're no longer interested in this subscription
752
- const unsubscribe = unsubscribeMethod => unsubDeferred.reject(new CallerUnsubscribedError(chainId, unsubscribeMethod));
753
- // we queue up our work to clean up our subscription when this promise rejects
723
+ const unsubscribe = (unsubscribeMethod) => unsubDeferred.reject(new CallerUnsubscribedError(chainId, unsubscribeMethod));
754
724
  const callerUnsubscribed = unsubDeferred.promise;
755
-
756
- // used to detect when there are no more websockets available from the browser websocket pool
757
- // in this scenario, we'll be waiting for ws.isReady until some existing sockets are closed
758
- //
759
- // while we're waiting, we'll send an error back to the caller so that they can show some useful
760
- // info to the user
761
- let noMoreSocketsTimeout = undefined
762
-
763
- // create subscription asynchronously so that the caller can unsubscribe without waiting for
764
- // the subscription to be created (which can take some time if e.g. the connection can't be established)
765
- ;
725
+ let noMoreSocketsTimeout;
766
726
  (async () => {
767
- // wait for ws to be ready, but don't wait forever
768
- // if timeout is number, cancel when timeout is reached (or caller unsubscribes)
769
- // if timeout is false, only cancel when the caller unsubscribes
770
727
  let unsubRpcStatus = null;
771
728
  try {
772
- const unsubStale = ws.on("stale-rpcs", ({
773
- nextBackoffInterval
774
- } = {}) => {
775
- callback(new StaleRpcError(chainId), null);
776
- if (this.#connectionMetaDb && nextBackoffInterval) {
777
- const id = chainId;
778
- this.#connectionMetaDb.chainBackoffInterval.put({
779
- id,
780
- interval: nextBackoffInterval
781
- }, id);
729
+ const unsubStale = ws.on(
730
+ "stale-rpcs",
731
+ ({ nextBackoffInterval } = {}) => {
732
+ callback(new StaleRpcError(chainId), null);
733
+ if (this.#connectionMetaDb && nextBackoffInterval) {
734
+ const id = chainId;
735
+ this.#connectionMetaDb.chainBackoffInterval.put(
736
+ { id, interval: nextBackoffInterval },
737
+ id
738
+ );
739
+ }
782
740
  }
783
- });
741
+ );
784
742
  const unsubConnected = ws.on("connected", () => {
785
743
  if (this.#connectionMetaDb) this.#connectionMetaDb.chainBackoffInterval.delete(chainId);
786
744
  });
@@ -788,57 +746,58 @@ class ChainConnectorDot {
788
746
  unsubStale();
789
747
  unsubConnected();
790
748
  };
791
- noMoreSocketsTimeout = setTimeout(() => callback(new WebsocketAllocationExhaustedError(chainId), null), 30_000 // 30 seconds in ms
749
+ noMoreSocketsTimeout = setTimeout(
750
+ () => callback(new WebsocketAllocationExhaustedError(chainId), null),
751
+ 3e4
752
+ // 30 seconds in ms
792
753
  );
793
- if (timeout) await Promise.race([this.waitForWs(ws, timeout), callerUnsubscribed]);else await Promise.race([ws.isReady, callerUnsubscribed]);
754
+ if (timeout) await Promise.race([this.waitForWs(ws, timeout), callerUnsubscribed]);
755
+ else await Promise.race([ws.isReady, callerUnsubscribed]);
794
756
  clearTimeout(noMoreSocketsTimeout);
795
- } catch (error) {
757
+ } catch {
796
758
  clearTimeout(noMoreSocketsTimeout);
797
- unsubRpcStatus && unsubRpcStatus();
759
+ unsubRpcStatus?.();
798
760
  await this.disconnectChainSocket(chainId, socketUserId);
799
761
  return;
800
762
  }
801
-
802
- // create subscription on ws
803
- // handle the scenarios where the caller unsubscribes before the subscription has been created and:
804
- // - the subscriptionId is already set
805
- // - the subscriptionId is not set yet, but will be
806
763
  let subscriptionId = null;
807
764
  let disconnected = false;
808
- let unsubscribeMethod = undefined;
765
+ let unsubscribeMethod;
809
766
  try {
810
- await Promise.race([ws.subscribe(responseMethod, subscribeMethod, params, callback).then(id => {
811
- if (disconnected) {
812
- unsubscribeMethod && ws.unsubscribe(responseMethod, unsubscribeMethod, id);
813
- } else subscriptionId = id;
814
- }), callerUnsubscribed]);
767
+ await Promise.race([
768
+ ws.subscribe(responseMethod, subscribeMethod, params, callback).then((id) => {
769
+ if (disconnected) {
770
+ unsubscribeMethod && ws.unsubscribe(responseMethod, unsubscribeMethod, id);
771
+ } else subscriptionId = id;
772
+ }),
773
+ callerUnsubscribed
774
+ ]);
815
775
  } catch (error) {
816
776
  if (error instanceof CallerUnsubscribedError) unsubscribeMethod = error.unsubscribeMethod;
817
- unsubRpcStatus && unsubRpcStatus();
777
+ unsubRpcStatus?.();
818
778
  disconnected = true;
819
- if (subscriptionId !== null && unsubscribeMethod) await ws.unsubscribe(responseMethod, unsubscribeMethod, subscriptionId);
779
+ if (subscriptionId !== null && unsubscribeMethod)
780
+ await ws.unsubscribe(responseMethod, unsubscribeMethod, subscriptionId);
820
781
  await this.disconnectChainSocket(chainId, socketUserId);
821
782
  return;
822
783
  }
823
-
824
- // unsubscribe from ws subscription when the caller has unsubscribed
825
- callerUnsubscribed.catch(async error => {
826
- let unsubscribeMethod = undefined;
827
- if (error instanceof CallerUnsubscribedError) unsubscribeMethod = error.unsubscribeMethod;
828
- unsubRpcStatus && unsubRpcStatus();
829
- if (subscriptionId !== null && unsubscribeMethod) await ws.unsubscribe(responseMethod, unsubscribeMethod, subscriptionId);
784
+ callerUnsubscribed.catch(async (error) => {
785
+ let unsubscribeMethod2;
786
+ if (error instanceof CallerUnsubscribedError) unsubscribeMethod2 = error.unsubscribeMethod;
787
+ unsubRpcStatus?.();
788
+ if (subscriptionId !== null && unsubscribeMethod2)
789
+ await ws.unsubscribe(responseMethod, unsubscribeMethod2, subscriptionId);
830
790
  await this.disconnectChainSocket(chainId, socketUserId);
831
- }).catch(error => log.warn(error));
791
+ }).catch((error) => log_default.warn(error));
832
792
  })();
833
793
  return unsubscribe;
834
794
  }
835
-
836
795
  /**
837
796
  * Kills current websocket if any
838
797
  * Useful after changing rpc order to make sure it's applied for futher requests
839
798
  */
840
799
  async reset(chainId) {
841
- log.info("ChainConnector reset", chainId);
800
+ log_default.info("ChainConnector reset", chainId);
842
801
  const ws = this.#socketConnections[chainId];
843
802
  if (!ws) return;
844
803
  try {
@@ -847,21 +806,18 @@ class ChainConnectorDot {
847
806
  delete this.#socketUsers[chainId];
848
807
  await ws.disconnect();
849
808
  } catch (error) {
850
- log.warn(`Error occurred reseting socket ${chainId}`, error);
809
+ log_default.warn(`Error occurred reseting socket ${chainId}`, error);
851
810
  }
852
811
  }
853
-
854
812
  /**
855
813
  * Wait for websocket to be ready, but don't wait forever
856
814
  */
857
- async waitForWs(ws, timeout = 30_000 // 30 seconds in milliseconds
858
- ) {
815
+ async waitForWs(ws, timeout = 3e4) {
859
816
  const timer = timeout ? sleep(timeout).then(() => {
860
817
  throw new Error(`RPC connect timeout reached: ${ws.endpoint}`);
861
818
  }) : false;
862
819
  await Promise.race([ws.isReady, timer].filter(isTruthy));
863
820
  }
864
-
865
821
  /**
866
822
  * Connect to an RPC via chainId
867
823
  *
@@ -870,42 +826,45 @@ class ChainConnectorDot {
870
826
  async connectChainSocket(chainId) {
871
827
  const rpcs = await this.getEndpoints(chainId);
872
828
  const socketUserId = this.addSocketUser(chainId);
873
-
874
- // retrieve next rpc backoff interval from connection meta db (if one exists)
875
- let nextBackoffInterval = undefined;
876
- if (this.#connectionMetaDb) nextBackoffInterval = (await this.#connectionMetaDb.chainBackoffInterval.get(chainId))?.interval;
877
-
878
- // NOTE: Make sure there are no calls to `await` between this check and the
879
- // next step where we assign a `new Websocket` to `this.#socketConnections[chainId]`
880
- //
881
- // If there is an `await` between these two steps then there will be a race condition introduced.
882
- // The result of this race condition will be the unnecessary creation of multiple instances of
883
- // `Websocket` per chain, rather than the intended behaviour where every call to send/subscribe
884
- // shares a single `Websocket` per chain.
829
+ let nextBackoffInterval;
830
+ if (this.#connectionMetaDb)
831
+ nextBackoffInterval = (await this.#connectionMetaDb.chainBackoffInterval.get(chainId))?.interval;
885
832
  if (this.#socketConnections[chainId]) return [socketUserId, this.#socketConnections[chainId]];
886
- if (rpcs.length) this.#socketConnections[chainId] = new Websocket(rpcs, undefined, undefined, nextBackoffInterval);else {
833
+ if (rpcs.length)
834
+ this.#socketConnections[chainId] = new Websocket(
835
+ rpcs,
836
+ void 0,
837
+ void 0,
838
+ nextBackoffInterval
839
+ );
840
+ else {
887
841
  throw new Error(`No healthy RPCs available for chain ${chainId}`);
888
842
  }
889
-
890
- // on ws connected event, store current rpc as most recently connected rpc
891
843
  if (this.#connectionMetaDb) {
892
844
  this.#socketConnections[chainId].on("connected", () => {
893
845
  if (!this.#connectionMetaDb) return;
894
846
  const id = chainId;
895
847
  const url = this.#socketConnections[chainId]?.endpoint;
896
848
  if (!url) return;
897
- this.updateRpcPriority(id, url, "first").catch(err => log.warn(`updateRpcPriority failed`, err));
849
+ this.updateRpcPriority(id, url, "first").catch(
850
+ (err) => log_default.warn(`updateRpcPriority failed`, err)
851
+ );
898
852
  });
899
853
  }
854
+ ;
900
855
  (async () => {
901
- if (!this.#socketConnections[chainId]) return log.warn(`ignoring ${chainId} rpc ws healthcheck initialization: ws is not defined`);
856
+ if (!this.#socketConnections[chainId])
857
+ return log_default.warn(`ignoring ${chainId} rpc ws healthcheck initialization: ws is not defined`);
902
858
  await this.#socketConnections[chainId].isReady;
903
- if (this.#socketKeepAliveIntervals[chainId]) clearInterval(this.#socketKeepAliveIntervals[chainId]);
904
- const intervalMs = 10_000; // 10,000ms = 10s
859
+ if (this.#socketKeepAliveIntervals[chainId])
860
+ clearInterval(this.#socketKeepAliveIntervals[chainId]);
861
+ const intervalMs = 1e4;
905
862
  this.#socketKeepAliveIntervals[chainId] = setInterval(() => {
906
- if (!this.#socketConnections[chainId]) return log.warn(`skipping ${chainId} rpc ws healthcheck: ws is not defined`);
907
- if (!this.#socketConnections[chainId].isConnected) return log.warn(`skipping ${chainId} rpc ws healthcheck: ws is not connected`);
908
- this.#socketConnections[chainId].send("system_health", []).catch(error => log.warn(`Failed keep-alive for socket ${chainId}`, error));
863
+ if (!this.#socketConnections[chainId])
864
+ return log_default.warn(`skipping ${chainId} rpc ws healthcheck: ws is not defined`);
865
+ if (!this.#socketConnections[chainId].isConnected)
866
+ return log_default.warn(`skipping ${chainId} rpc ws healthcheck: ws is not connected`);
867
+ this.#socketConnections[chainId].send("system_health", []).catch((error) => log_default.warn(`Failed keep-alive for socket ${chainId}`, error));
909
868
  }, intervalMs);
910
869
  })();
911
870
  return [socketUserId, this.#socketConnections[chainId]];
@@ -913,11 +872,12 @@ class ChainConnectorDot {
913
872
  async disconnectChainSocket(chainId, socketUserId) {
914
873
  this.removeSocketUser(chainId, socketUserId);
915
874
  if (this.#socketUsers[chainId].length > 0) return;
916
- if (!this.#socketConnections[chainId]) return log.warn(`Failed to disconnect socket: socket ${chainId} not found`);
875
+ if (!this.#socketConnections[chainId])
876
+ return log_default.warn(`Failed to disconnect socket: socket ${chainId} not found`);
917
877
  try {
918
878
  this.#socketConnections[chainId].disconnect();
919
879
  } catch (error) {
920
- log.warn(`Error occurred disconnecting socket ${chainId}`, error);
880
+ log_default.warn(`Error occurred disconnecting socket ${chainId}`, error);
921
881
  }
922
882
  delete this.#socketConnections[chainId];
923
883
  clearInterval(this.#socketKeepAliveIntervals[chainId]);
@@ -931,10 +891,12 @@ class ChainConnectorDot {
931
891
  }
932
892
  removeSocketUser(chainId, socketUserId) {
933
893
  const userIndex = this.#socketUsers[chainId].indexOf(socketUserId);
934
- if (userIndex === -1) throw new Error(`Can't remove user ${socketUserId} from socket ${chainId}: user not in list ${this.#socketUsers[chainId].join(", ")}`);
894
+ if (userIndex === -1)
895
+ throw new Error(
896
+ `Can't remove user ${socketUserId} from socket ${chainId}: user not in list ${this.#socketUsers[chainId].join(", ")}`
897
+ );
935
898
  this.#socketUsers[chainId].splice(userIndex, 1);
936
899
  }
937
-
938
900
  /** continues to generate a random number until it finds one which is not present in the exclude list */
939
901
  getExclusiveRandomId(exclude = []) {
940
902
  let id = this.getRandomId();
@@ -945,13 +907,10 @@ class ChainConnectorDot {
945
907
  }
946
908
  /** generates a random number */
947
909
  getRandomId() {
948
- return Math.trunc(Math.random() * Math.pow(10, 8));
910
+ return Math.trunc(Math.random() * 10 ** 8);
949
911
  }
950
912
  getTalismanSub() {
951
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
952
913
  const talismanSub = typeof window !== "undefined" && window.talismanSub;
953
-
954
- /* eslint-disable @typescript-eslint/no-unsafe-function-type */
955
914
  const rpcByGenesisHashSend = talismanSub?.rpcByGenesisHashSend;
956
915
  const rpcByGenesisHashSubscribe = talismanSub?.rpcByGenesisHashSubscribe;
957
916
  const rpcByGenesisHashUnsubscribe = talismanSub?.rpcByGenesisHashUnsubscribe;
@@ -959,9 +918,16 @@ class ChainConnectorDot {
959
918
  if (typeof rpcByGenesisHashSubscribe !== "function") return;
960
919
  if (typeof rpcByGenesisHashUnsubscribe !== "function") return;
961
920
  return {
962
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
921
+ // biome-ignore lint/suspicious/noExplicitAny: legacy
963
922
  send: (genesisHash, method, params) => rpcByGenesisHashSend(genesisHash, method, params),
964
- subscribe: (genesisHash, subscribeMethod, responseMethod, params, callback, timeout) => rpcByGenesisHashSubscribe(genesisHash, subscribeMethod, responseMethod, params, callback, timeout),
923
+ subscribe: (genesisHash, subscribeMethod, responseMethod, params, callback, timeout) => rpcByGenesisHashSubscribe(
924
+ genesisHash,
925
+ subscribeMethod,
926
+ responseMethod,
927
+ params,
928
+ callback,
929
+ timeout
930
+ ),
965
931
  unsubscribe: (subscriptionId, unsubscribeMethod) => rpcByGenesisHashUnsubscribe(subscriptionId, unsubscribeMethod)
966
932
  };
967
933
  }
@@ -969,81 +935,86 @@ class ChainConnectorDot {
969
935
  if (!this.#connectionMetaDb) return;
970
936
  const rpcs = await this.getEndpoints(chainId);
971
937
  if (!rpcs.includes(rpc)) throw new Error(`Unknown rpc for chain ${chainId} : ${rpc}`);
972
- const urls = rpcs.filter(r => r !== rpc);
938
+ const urls = rpcs.filter((r) => r !== rpc);
973
939
  if (priority === "first") urls.unshift(rpc);
974
940
  if (priority === "last") urls.push(rpc);
975
941
  if (!isEqual(urls, rpcs)) {
976
- // order may not change, especially if there is only one
977
- await this.#connectionMetaDb.chainPriorityRpcs.put({
978
- id: chainId,
979
- urls
980
- }, chainId);
942
+ await this.#connectionMetaDb.chainPriorityRpcs.put({ id: chainId, urls }, chainId);
981
943
  }
982
944
  }
983
945
  async getEndpoints(chainId) {
984
946
  const chain = await this.#chaindataChainProvider.getNetworkById(chainId, "polkadot");
985
947
  if (!chain) throw new Error(`Chain ${chainId} not found in store`);
986
- let rpcs = chain.rpcs.concat(); // clone to avoid mutating the original array
987
- const priorityRpcs = this.#connectionMetaDb ? await this.#connectionMetaDb.chainPriorityRpcs.get(chainId) : undefined;
948
+ let rpcs = chain.rpcs.concat();
949
+ const priorityRpcs = this.#connectionMetaDb ? await this.#connectionMetaDb.chainPriorityRpcs.get(chainId) : void 0;
988
950
  if (priorityRpcs) {
989
- // use existing priority list of rpcs that still exist, and include missing ones
990
- rpcs = [...priorityRpcs.urls.filter(rpc => rpcs.includes(rpc)), ...rpcs.filter(rpc => !priorityRpcs.urls.includes(rpc))];
951
+ rpcs = [
952
+ ...priorityRpcs.urls.filter((rpc) => rpcs.includes(rpc)),
953
+ ...rpcs.filter((rpc) => !priorityRpcs.urls.includes(rpc))
954
+ ];
991
955
  }
992
956
  return rpcs;
993
957
  }
994
- }
995
- const isEqual = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
996
-
997
- const AUTO_CONNECT_TIMEOUT = 3_000;
998
- const TIMEOUT = 10_000;
999
- class ChainConnectorDotStub {
958
+ };
959
+ var isEqual = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
960
+
961
+ // src/dot/ChainConnectorDotStub.ts
962
+ import { WsProvider } from "@polkadot/rpc-provider";
963
+ import { throwAfter as throwAfter2 } from "@talismn/util";
964
+ var AUTO_CONNECT_TIMEOUT = 3e3;
965
+ var TIMEOUT = 1e4;
966
+ var ChainConnectorDotStub = class {
967
+ // biome-ignore lint/correctness/noUnusedPrivateClassMembers: legacy
1000
968
  #network;
1001
969
  #provider;
1002
970
  constructor(network) {
1003
971
  this.#network = network;
1004
- this.#provider = new WsProvider(network.rpcs, AUTO_CONNECT_TIMEOUT, undefined, TIMEOUT);
972
+ this.#provider = new WsProvider(network.rpcs, AUTO_CONNECT_TIMEOUT, void 0, TIMEOUT);
1005
973
  }
1006
974
  asProvider() {
1007
975
  return this.#provider;
1008
976
  }
1009
- async send(chainId, method, params, isCacheable) {
977
+ async send(_chainId, method, params, isCacheable) {
1010
978
  await this.#provider.isReady;
1011
979
  return this.#provider.send(method, params, isCacheable);
1012
980
  }
1013
- async subscribe(chainId, subscribeMethod, responseMethod, params, callback, timeout) {
981
+ async subscribe(_chainId, subscribeMethod, responseMethod, params, callback, timeout) {
1014
982
  await this.#provider.isReady;
1015
- const subId = await Promise.race([throwAfter(timeout || TIMEOUT, `Subscription timed out after ${timeout}ms`), this.#provider.subscribe(responseMethod, subscribeMethod, params, callback)]);
1016
- return unsubscribeMethod => {
983
+ const subId = await Promise.race([
984
+ throwAfter2(timeout || TIMEOUT, `Subscription timed out after ${timeout}ms`),
985
+ this.#provider.subscribe(responseMethod, subscribeMethod, params, callback)
986
+ ]);
987
+ return (unsubscribeMethod) => {
1017
988
  this.#provider.unsubscribe(responseMethod, unsubscribeMethod, subId);
1018
989
  };
1019
990
  }
1020
991
  reset() {
1021
992
  throw new Error("ChainConnectorDotStub does not implement reset");
1022
993
  }
1023
- }
1024
-
1025
- // exclude zoraTestnet which uses Hyperliquid's chain id
1026
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1027
- const {
1028
- zoraTestnet,
1029
- ...validViemChains
1030
- } = viemChains;
994
+ };
1031
995
 
1032
- // viem chains benefit from multicall config & other viem goodies
1033
- const VIEM_CHAINS = Object.keys(validViemChains).reduce((acc, curr) => {
1034
- const chain = validViemChains[curr];
1035
- acc[chain.id] = chain;
1036
- return acc;
1037
- }, {});
1038
- const chainsCache = new Map();
1039
- const clearChainsCache = networkId => {
1040
- if (networkId) chainsCache.delete(networkId);else chainsCache.clear();
996
+ // src/eth/getEvmNetworkPublicClient.ts
997
+ import { createPublicClient } from "viem";
998
+
999
+ // src/eth/getChainFromEvmNetwork.ts
1000
+ import { camelCase, fromPairs, toPairs } from "lodash-es";
1001
+ import * as viemChains from "viem/chains";
1002
+ var { zoraTestnet, ...validViemChains } = viemChains;
1003
+ var VIEM_CHAINS = Object.keys(validViemChains).reduce(
1004
+ (acc, curr) => {
1005
+ const chain = validViemChains[curr];
1006
+ acc[chain.id] = chain;
1007
+ return acc;
1008
+ },
1009
+ {}
1010
+ );
1011
+ var chainsCache = /* @__PURE__ */ new Map();
1012
+ var clearChainsCache = (networkId) => {
1013
+ if (networkId) chainsCache.delete(networkId);
1014
+ else chainsCache.clear();
1041
1015
  };
1042
- const getChainFromEvmNetwork = network => {
1043
- const {
1044
- symbol,
1045
- decimals
1046
- } = network.nativeCurrency;
1016
+ var getChainFromEvmNetwork = (network) => {
1017
+ const { symbol, decimals } = network.nativeCurrency;
1047
1018
  if (!chainsCache.has(network.id)) {
1048
1019
  const chainRpcs = network.rpcs ?? [];
1049
1020
  const viemChain = VIEM_CHAINS[Number(network.id)] ?? {};
@@ -1052,12 +1023,8 @@ const getChainFromEvmNetwork = network => {
1052
1023
  id: Number(network.id),
1053
1024
  name: network.name ?? `Ethereum Chain ${network.id}`,
1054
1025
  rpcUrls: {
1055
- public: {
1056
- http: chainRpcs
1057
- },
1058
- default: {
1059
- http: chainRpcs
1060
- }
1026
+ public: { http: chainRpcs },
1027
+ default: { http: chainRpcs }
1061
1028
  },
1062
1029
  nativeCurrency: {
1063
1030
  symbol,
@@ -1066,9 +1033,12 @@ const getChainFromEvmNetwork = network => {
1066
1033
  },
1067
1034
  contracts: {
1068
1035
  ...viemChain.contracts,
1069
- ...(network.contracts ? fromPairs(toPairs(network.contracts).map(([name, address]) => [camelCase(name), {
1070
- address
1071
- }])) : {})
1036
+ ...network.contracts ? fromPairs(
1037
+ toPairs(network.contracts).map(([name, address]) => [
1038
+ camelCase(name),
1039
+ { address }
1040
+ ])
1041
+ ) : {}
1072
1042
  }
1073
1043
  };
1074
1044
  chainsCache.set(network.id, chain);
@@ -1076,41 +1046,34 @@ const getChainFromEvmNetwork = network => {
1076
1046
  return chainsCache.get(network.id);
1077
1047
  };
1078
1048
 
1079
- const getTransportForEvmNetwork = (evmNetwork, options = {}) => {
1049
+ // src/eth/getTransportForEvmNetwork.ts
1050
+ import { fallback, http } from "viem";
1051
+ var getTransportForEvmNetwork = (evmNetwork, options = {}) => {
1080
1052
  if (!evmNetwork.rpcs?.length) throw new Error("No RPCs found for EVM network");
1081
- const {
1082
- batch
1083
- } = options;
1084
- return fallback(evmNetwork.rpcs.map(url => http(url, {
1085
- batch,
1086
- retryCount: 0
1087
- })), {
1088
- retryCount: 0
1089
- });
1053
+ const { batch } = options;
1054
+ return fallback(
1055
+ evmNetwork.rpcs.map((url) => http(url, { batch, retryCount: 0 })),
1056
+ { retryCount: 0 }
1057
+ );
1090
1058
  };
1091
1059
 
1092
- const MUTLICALL_BATCH_WAIT = 25;
1093
- const MUTLICALL_BATCH_SIZE = 100;
1094
- const HTTP_BATCH_WAIT = 25;
1095
- const HTTP_BATCH_SIZE_WITH_MULTICALL = 10;
1096
- const HTTP_BATCH_SIZE_WITHOUT_MULTICALL = 30;
1097
-
1098
- // cache to reuse previously created public clients
1099
- const publicClientCache = new Map();
1100
- const clearPublicClientCache = evmNetworkId => {
1060
+ // src/eth/getEvmNetworkPublicClient.ts
1061
+ var MUTLICALL_BATCH_WAIT = 25;
1062
+ var MUTLICALL_BATCH_SIZE = 100;
1063
+ var HTTP_BATCH_WAIT = 25;
1064
+ var HTTP_BATCH_SIZE_WITH_MULTICALL = 10;
1065
+ var HTTP_BATCH_SIZE_WITHOUT_MULTICALL = 30;
1066
+ var publicClientCache = /* @__PURE__ */ new Map();
1067
+ var clearPublicClientCache = (evmNetworkId) => {
1101
1068
  clearChainsCache(evmNetworkId);
1102
- if (evmNetworkId) publicClientCache.delete(evmNetworkId);else publicClientCache.clear();
1069
+ if (evmNetworkId) publicClientCache.delete(evmNetworkId);
1070
+ else publicClientCache.clear();
1103
1071
  };
1104
- const getEvmNetworkPublicClient = network => {
1072
+ var getEvmNetworkPublicClient = (network) => {
1105
1073
  const chain = getChainFromEvmNetwork(network);
1106
1074
  if (!publicClientCache.has(network.id)) {
1107
1075
  if (!network.rpcs.length) throw new Error("No RPCs found for Ethereum network");
1108
- const batch = chain.contracts?.multicall3 ? {
1109
- multicall: {
1110
- wait: MUTLICALL_BATCH_WAIT,
1111
- batchSize: MUTLICALL_BATCH_SIZE
1112
- }
1113
- } : undefined;
1076
+ const batch = chain.contracts?.multicall3 ? { multicall: { wait: MUTLICALL_BATCH_WAIT, batchSize: MUTLICALL_BATCH_SIZE } } : void 0;
1114
1077
  const transportOptions = {
1115
1078
  batch: {
1116
1079
  batchSize: chain.contracts?.multicall3 ? HTTP_BATCH_SIZE_WITH_MULTICALL : HTTP_BATCH_SIZE_WITHOUT_MULTICALL,
@@ -1118,26 +1081,28 @@ const getEvmNetworkPublicClient = network => {
1118
1081
  }
1119
1082
  };
1120
1083
  const transport = getTransportForEvmNetwork(network, transportOptions);
1121
- publicClientCache.set(network.id, createPublicClient({
1122
- chain,
1123
- transport,
1124
- batch
1125
- }));
1084
+ publicClientCache.set(
1085
+ network.id,
1086
+ createPublicClient({
1087
+ chain,
1088
+ transport,
1089
+ batch
1090
+ })
1091
+ );
1126
1092
  }
1127
1093
  return publicClientCache.get(network.id);
1128
1094
  };
1129
1095
 
1130
- const getEvmNetworkWalletClient = (network, options = {}) => {
1096
+ // src/eth/getEvmNetworkWalletClient.ts
1097
+ import { createWalletClient } from "viem";
1098
+ var getEvmNetworkWalletClient = (network, options = {}) => {
1131
1099
  const chain = getChainFromEvmNetwork(network);
1132
1100
  const transport = getTransportForEvmNetwork(network);
1133
- return createWalletClient({
1134
- chain,
1135
- transport,
1136
- account: options.account
1137
- });
1101
+ return createWalletClient({ chain, transport, account: options.account });
1138
1102
  };
1139
1103
 
1140
- class ChainConnectorEth {
1104
+ // src/eth/ChainConnectorEth.ts
1105
+ var ChainConnectorEth = class {
1141
1106
  #chaindataProvider;
1142
1107
  constructor(chaindataProvider) {
1143
1108
  this.#chaindataProvider = chaindataProvider;
@@ -1150,16 +1115,15 @@ class ChainConnectorEth {
1150
1115
  async getWalletClientForEvmNetwork(evmNetworkId, account) {
1151
1116
  const network = await this.#chaindataProvider.getNetworkById(evmNetworkId, "ethereum");
1152
1117
  if (!network) return null;
1153
- return getEvmNetworkWalletClient(network, {
1154
- account
1155
- });
1118
+ return getEvmNetworkWalletClient(network, { account });
1156
1119
  }
1157
1120
  clearRpcProvidersCache(evmNetworkId) {
1158
1121
  clearPublicClientCache(evmNetworkId);
1159
1122
  }
1160
- }
1123
+ };
1161
1124
 
1162
- class ChainConnectorEthStub {
1125
+ // src/eth/ChainConnectorEthStub.ts
1126
+ var ChainConnectorEthStub = class {
1163
1127
  #network;
1164
1128
  constructor(network) {
1165
1129
  this.#network = network;
@@ -1167,24 +1131,23 @@ class ChainConnectorEthStub {
1167
1131
  async getPublicClientForEvmNetwork() {
1168
1132
  return getEvmNetworkPublicClient(this.#network);
1169
1133
  }
1170
- async getWalletClientForEvmNetwork(networkId, account) {
1171
- return getEvmNetworkWalletClient(this.#network, {
1172
- account
1173
- });
1134
+ async getWalletClientForEvmNetwork(_networkId, account) {
1135
+ return getEvmNetworkWalletClient(this.#network, { account });
1174
1136
  }
1175
1137
  clearRpcProvidersCache() {
1176
- // No-op for stub
1177
1138
  }
1178
- }
1139
+ };
1179
1140
 
1180
- // TODO leverage multiple rpcs with fallback
1181
- const getSolConnection = (networkId, rpcs) => {
1141
+ // src/sol/getSolConnection.ts
1142
+ import { Connection } from "@solana/web3.js";
1143
+ var getSolConnection = (_networkId, rpcs) => {
1182
1144
  return new Connection(rpcs[0], {
1183
1145
  commitment: "confirmed"
1184
1146
  });
1185
1147
  };
1186
1148
 
1187
- class ChainConnectorSol {
1149
+ // src/sol/ChainConnectorSol.ts
1150
+ var ChainConnectorSol = class {
1188
1151
  #chaindataProvider;
1189
1152
  constructor(chaindataProvider) {
1190
1153
  this.#chaindataProvider = chaindataProvider;
@@ -1194,16 +1157,28 @@ class ChainConnectorSol {
1194
1157
  if (!network) throw new Error(`Network not found: ${networkId}`);
1195
1158
  return getSolConnection(networkId, network.rpcs);
1196
1159
  }
1197
- }
1160
+ };
1198
1161
 
1199
- class ChainConnectorSolStub {
1162
+ // src/sol/ChainConnectorSolStub.ts
1163
+ import { Connection as Connection2 } from "@solana/web3.js";
1164
+ var ChainConnectorSolStub = class {
1200
1165
  #connection;
1201
1166
  constructor(networkOrConnection) {
1202
- this.#connection = networkOrConnection instanceof Connection ? networkOrConnection : getSolConnection(networkOrConnection.id, networkOrConnection.rpcs);
1167
+ this.#connection = networkOrConnection instanceof Connection2 ? networkOrConnection : getSolConnection(networkOrConnection.id, networkOrConnection.rpcs);
1203
1168
  }
1204
1169
  async getConnection() {
1205
1170
  return this.#connection;
1206
1171
  }
1207
- }
1208
-
1209
- export { ChainConnectionError, ChainConnectorDot, ChainConnectorDotStub, ChainConnectorEth, ChainConnectorEthStub, ChainConnectorSol, ChainConnectorSolStub, StaleRpcError, WebsocketAllocationExhaustedError };
1172
+ };
1173
+ export {
1174
+ ChainConnectionError,
1175
+ ChainConnectorDot,
1176
+ ChainConnectorDotStub,
1177
+ ChainConnectorEth,
1178
+ ChainConnectorEthStub,
1179
+ ChainConnectorSol,
1180
+ ChainConnectorSolStub,
1181
+ StaleRpcError,
1182
+ WebsocketAllocationExhaustedError
1183
+ };
1184
+ //# sourceMappingURL=index.mjs.map