@midnightntwrk/wallet-sdk-node-client 2.0.0-beta.3 → 2.0.0-beta.4

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.
@@ -40,7 +40,19 @@ export class PolkadotNodeClient {
40
40
  // Disconnect immediately after loading metadata to avoid keeping the WebSocket open.
41
41
  // The health-check timer (10s interval) and timeout handler (5s interval) are cleared on disconnect.
42
42
  // Metadata and type registry remain cached in memory for subsequent on-demand connections.
43
- await api.disconnect();
43
+ //
44
+ // WsProvider.disconnect() is fire-and-forget: it dispatches the close frame and returns while the socket is
45
+ // still CLOSING. `isConnected` only flips false once #onSocketClose fires, so returning here without waiting
46
+ // leaves ensureConnection() reading a stale `true`, skipping the reconnect, and sending on a dying socket.
47
+ // Locally the close-ack lands fast enough to hide this; against a remote node it does not.
48
+ await new Promise((resolve) => {
49
+ if (!api.isConnected) {
50
+ resolve();
51
+ return;
52
+ }
53
+ api.once('disconnected', () => resolve());
54
+ void api.disconnect();
55
+ });
44
56
  return api;
45
57
  }), (api) => Effect.promise(() => api.disconnect())).pipe(Effect.map((api) => new PolkadotNodeClient(config, api)));
46
58
  }
@@ -49,6 +61,8 @@ export class PolkadotNodeClient {
49
61
  }
50
62
  config;
51
63
  api;
64
+ /** Operations currently holding the shared connection open. */
65
+ #activeOperations = 0;
52
66
  constructor(config, api) {
53
67
  this.config = config;
54
68
  this.api = api;
@@ -71,10 +85,30 @@ export class PolkadotNodeClient {
71
85
  until: (value) => value,
72
86
  schedule: Schedule.spaced(this.config.reconnectionDelay),
73
87
  }), Effect.timeout(this.config.reconnectionTimeout), Effect.asVoid, Effect.mapError((timeout) => new NodeClientError.ConnectionError({
74
- message: 'Could not connect within specified time range (5s)',
88
+ message: `Could not establish a usable connection within ${Duration.format(this.config.reconnectionTimeout)}`,
75
89
  cause: timeout,
76
90
  })));
77
91
  }
92
+ /** Takes a hold on the shared connection for the duration of one operation. */
93
+ #acquire() {
94
+ return pipe(this.ensureConnection(), Effect.tap(() => Effect.sync(() => {
95
+ this.#activeOperations += 1;
96
+ })));
97
+ }
98
+ /**
99
+ * Drops one hold, disconnecting only once the last operation finishes.
100
+ *
101
+ * The api instance is shared, so an unconditional `disconnect()` in a per-operation finalizer closes the transport
102
+ * out from under any operation still in flight.
103
+ */
104
+ #release() {
105
+ return Effect.promise(async () => {
106
+ this.#activeOperations = Math.max(0, this.#activeOperations - 1);
107
+ if (this.#activeOperations === 0) {
108
+ await this.api.disconnect();
109
+ }
110
+ });
111
+ }
78
112
  sendMidnightTransaction(serializedTransaction) {
79
113
  const outputStream = Stream.async((emit) => {
80
114
  const callUnsubscribe = () => unsubscribeP.then((thunk) => thunk());
@@ -92,10 +126,10 @@ export class PolkadotNodeClient {
92
126
  });
93
127
  return Effect.promise(callUnsubscribe);
94
128
  });
95
- return pipe(Stream.fromEffect(this.ensureConnection()), Stream.flatMap(() => outputStream), Stream.ensuring(Effect.promise(() => this.api.disconnect())));
129
+ return pipe(Stream.fromEffect(this.#acquire()), Stream.flatMap(() => outputStream), Stream.ensuring(this.#release()));
96
130
  }
97
131
  getGenesis() {
98
- return pipe(this.ensureConnection(), Effect.andThen(() => Effect.promise(() => this.api.rpc.chain.getBlock(this.api.genesisHash))),
132
+ return pipe(this.#acquire(), Effect.andThen(() => Effect.promise(() => this.api.rpc.chain.getBlock(this.api.genesisHash))),
99
133
  // https://polkadot.js.org/docs/api/cookbook/blocks/#how-do-i-view-extrinsic-information
100
134
  Effect.map(({ block }) => ({
101
135
  transactions: block.extrinsics
@@ -105,7 +139,7 @@ export class PolkadotNodeClient {
105
139
  })), Effect.mapError((error) => new NodeClientError.ConnectionError({
106
140
  message: 'Failed to retrieve genesis transactions',
107
141
  cause: error,
108
- })), Effect.ensuring(Effect.promise(() => this.api.disconnect())));
142
+ })), Effect.ensuring(this.#release()));
109
143
  }
110
144
  #handleSubmissionResult = (serializedTransaction, emit, unsubscribe) => {
111
145
  const WithBNBlockNumber = Schema.Struct({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midnightntwrk/wallet-sdk-node-client",
3
- "version": "2.0.0-beta.3",
3
+ "version": "2.0.0-beta.4",
4
4
  "type": "module",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -33,7 +33,7 @@
33
33
  }
34
34
  },
35
35
  "dependencies": {
36
- "@midnightntwrk/wallet-sdk-abstractions": "3.0.0-beta.1",
36
+ "@midnightntwrk/wallet-sdk-abstractions": "3.0.0-beta.2",
37
37
  "@midnightntwrk/wallet-sdk-utilities": "1.2.2-beta.0",
38
38
  "@polkadot/api": "^16.5.4",
39
39
  "@polkadot/types": "^16.5.4",
@@ -43,8 +43,8 @@
43
43
  "effect": "^3.19.19"
44
44
  },
45
45
  "peerDependencies": {
46
- "@midnightntwrk/ledger-v9": "1.0.0-rc.4",
47
- "@midnightntwrk/wallet-sdk-prover-client": "2.0.0-beta.3"
46
+ "@midnightntwrk/ledger-v9": "1.0.0-rc.5",
47
+ "@midnightntwrk/wallet-sdk-prover-client": "2.0.0-beta.4"
48
48
  },
49
49
  "peerDependenciesMeta": {
50
50
  "@midnightntwrk/ledger-v9": {
@@ -55,18 +55,18 @@
55
55
  }
56
56
  },
57
57
  "devDependencies": {
58
- "@effect/cluster": "0.59.0",
59
- "@effect/experimental": "0.60.0",
60
- "@effect/platform": "0.96.2",
61
- "@effect/platform-node": "0.107.0",
62
- "@effect/rpc": "0.75.1",
63
- "@effect/sql": "0.51.1",
64
- "@effect/workflow": "0.18.2",
65
- "@midnightntwrk/ledger-v9": "1.0.0-rc.4",
66
- "@midnightntwrk/wallet-sdk-prover-client": "^2.0.0-beta.3",
58
+ "@effect/cluster": "0.60.2",
59
+ "@effect/experimental": "0.61.1",
60
+ "@effect/platform": "0.97.1",
61
+ "@effect/platform-node": "0.108.1",
62
+ "@effect/rpc": "0.76.2",
63
+ "@effect/sql": "0.52.1",
64
+ "@effect/workflow": "0.19.1",
65
+ "@midnightntwrk/ledger-v9": "1.0.0-rc.5",
66
+ "@midnightntwrk/wallet-sdk-prover-client": "^2.0.0-beta.4",
67
67
  "@types/tar-stream": "3.1.4",
68
68
  "tar-stream": "3.2.0",
69
- "tsx": "4.22.4"
69
+ "tsx": "4.23.13"
70
70
  },
71
71
  "scripts": {
72
72
  "typecheck-script": "tsc -b ./tsconfig.script.json --noEmit",