@solana/web3.js 2.0.0-experimental.4480ae1 → 2.0.0-experimental.461b4ce

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.
@@ -1,15 +1,20 @@
1
1
  'use strict';
2
2
 
3
+ var addresses = require('@solana/addresses');
4
+ var instructions = require('@solana/instructions');
3
5
  var keys = require('@solana/keys');
6
+ var transactions = require('@solana/transactions');
4
7
  var rpcCore = require('@solana/rpc-core');
5
8
  var rpcTransport = require('@solana/rpc-transport');
9
+ var functional = require('@solana/functional');
6
10
  var fastStableStringify = require('fast-stable-stringify');
7
11
 
8
12
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
13
 
10
14
  var fastStableStringify__default = /*#__PURE__*/_interopDefault(fastStableStringify);
11
15
 
12
- // src/index.ts
16
+ // ../build-scripts/env-shim.ts
17
+ var __DEV__ = /* @__PURE__ */ (() => process["env"].NODE_ENV === "development")();
13
18
 
14
19
  // src/rpc-integer-overflow-error.ts
15
20
  var SolanaJsonRpcIntegerOverflowError = class extends Error {
@@ -54,6 +59,12 @@ function createSolanaRpc(config) {
54
59
  api: rpcCore.createSolanaRpcApi(DEFAULT_RPC_CONFIG)
55
60
  });
56
61
  }
62
+ function createSolanaRpcSubscriptions(config) {
63
+ return rpcTransport.createJsonSubscriptionRpc({
64
+ ...config,
65
+ api: rpcCore.createSolanaRpcSubscriptionsApi(DEFAULT_RPC_CONFIG)
66
+ });
67
+ }
57
68
 
58
69
  // src/rpc-request-coalescer.ts
59
70
  function getRpcTransportWithRequestCoalescing(transport, getDeduplicationKey) {
@@ -106,13 +117,14 @@ function getRpcTransportWithRequestCoalescing(transport, getDeduplicationKey) {
106
117
  }
107
118
  };
108
119
  }
109
- function getSolanaRpcPayloadDeduplicationKey(payload) {
120
+ function isJsonRpcPayload(payload) {
110
121
  if (payload == null || typeof payload !== "object" || Array.isArray(payload)) {
111
- return;
112
- }
113
- if ("jsonrpc" in payload && payload.jsonrpc === "2.0" && "method" in payload && "params" in payload) {
114
- return fastStableStringify__default.default([payload.method, payload.params]);
122
+ return false;
115
123
  }
124
+ return "jsonrpc" in payload && payload.jsonrpc === "2.0" && "method" in payload && typeof payload.method === "string" && "params" in payload;
125
+ }
126
+ function getSolanaRpcPayloadDeduplicationKey(payload) {
127
+ return isJsonRpcPayload(payload) ? fastStableStringify__default.default([payload.method, payload.params]) : void 0;
116
128
  }
117
129
 
118
130
  // src/rpc-transport.ts
@@ -124,7 +136,7 @@ function normalizeHeaders(headers) {
124
136
  return out;
125
137
  }
126
138
  function createDefaultRpcTransport(config) {
127
- return getRpcTransportWithRequestCoalescing(
139
+ return functional.pipe(
128
140
  rpcTransport.createHttpTransport({
129
141
  ...config,
130
142
  headers: {
@@ -135,17 +147,217 @@ function createDefaultRpcTransport(config) {
135
147
  }
136
148
  }
137
149
  }),
138
- getSolanaRpcPayloadDeduplicationKey
150
+ (transport) => getRpcTransportWithRequestCoalescing(transport, getSolanaRpcPayloadDeduplicationKey)
139
151
  );
140
152
  }
141
153
 
154
+ // src/rpc-websocket-autopinger.ts
155
+ var PING_PAYLOAD = {
156
+ jsonrpc: "2.0",
157
+ method: "ping"
158
+ };
159
+ function getWebSocketTransportWithAutoping({ intervalMs, transport }) {
160
+ const pingableConnections = /* @__PURE__ */ new Map();
161
+ return async (...args) => {
162
+ const connection = await transport(...args);
163
+ let intervalId;
164
+ function sendPing() {
165
+ connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(PING_PAYLOAD);
166
+ }
167
+ function restartPingTimer() {
168
+ clearInterval(intervalId);
169
+ intervalId = setInterval(sendPing, intervalMs);
170
+ }
171
+ if (pingableConnections.has(connection) === false) {
172
+ pingableConnections.set(connection, {
173
+ [Symbol.asyncIterator]: connection[Symbol.asyncIterator].bind(connection),
174
+ send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: (...args2) => {
175
+ restartPingTimer();
176
+ return connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(...args2);
177
+ }
178
+ });
179
+ (async () => {
180
+ try {
181
+ for await (const _ of connection) {
182
+ restartPingTimer();
183
+ }
184
+ } catch {
185
+ } finally {
186
+ pingableConnections.delete(connection);
187
+ clearInterval(intervalId);
188
+ if (handleOffline) {
189
+ globalThis.window.removeEventListener("offline", handleOffline);
190
+ }
191
+ if (handleOnline) {
192
+ globalThis.window.removeEventListener("online", handleOnline);
193
+ }
194
+ }
195
+ })();
196
+ if (globalThis.navigator.onLine) {
197
+ restartPingTimer();
198
+ }
199
+ let handleOffline;
200
+ let handleOnline;
201
+ {
202
+ handleOffline = () => {
203
+ clearInterval(intervalId);
204
+ };
205
+ handleOnline = () => {
206
+ sendPing();
207
+ restartPingTimer();
208
+ };
209
+ globalThis.window.addEventListener("offline", handleOffline);
210
+ globalThis.window.addEventListener("online", handleOnline);
211
+ }
212
+ }
213
+ return pingableConnections.get(connection);
214
+ };
215
+ }
216
+
217
+ // src/rpc-websocket-connection-sharding.ts
218
+ var NULL_SHARD_CACHE_KEY = Symbol(
219
+ __DEV__ ? "Cache key to use when there is no connection sharding strategy" : void 0
220
+ );
221
+ function registerIterableCleanup(iterable, cleanupFn) {
222
+ (async () => {
223
+ try {
224
+ for await (const _ of iterable)
225
+ ;
226
+ } catch {
227
+ } finally {
228
+ cleanupFn();
229
+ }
230
+ })();
231
+ }
232
+ function getWebSocketTransportWithConnectionSharding({ getShard, transport }) {
233
+ const cache = /* @__PURE__ */ new Map();
234
+ function updateCache(shardKey, updater) {
235
+ const currentCacheEntry = cache.get(shardKey);
236
+ if (!currentCacheEntry) {
237
+ throw new Error(`Found no cache entry for connection with shard key \`${shardKey.toString()}\``);
238
+ }
239
+ const nextCacheEntry = updater(currentCacheEntry);
240
+ cache.set(shardKey, nextCacheEntry);
241
+ return nextCacheEntry;
242
+ }
243
+ return async (...args) => {
244
+ const { payload, signal, ...rest } = args[0];
245
+ const shardKey = getShard ? getShard(payload) : NULL_SHARD_CACHE_KEY;
246
+ function cleanup() {
247
+ cache.delete(shardKey);
248
+ signal.removeEventListener("abort", handleAbort);
249
+ }
250
+ function handleAbort() {
251
+ if (cache.get(shardKey)?.purgeScheduled !== true) {
252
+ updateCache(shardKey, (currentCacheEntry) => ({
253
+ ...currentCacheEntry,
254
+ purgeScheduled: true
255
+ }));
256
+ globalThis.queueMicrotask(() => {
257
+ const cacheEntryAtEndOfRunloop = cache.get(shardKey);
258
+ if (!cacheEntryAtEndOfRunloop) {
259
+ return;
260
+ }
261
+ if (cacheEntryAtEndOfRunloop.referenceCount === 0) {
262
+ cacheEntry.abortController.abort();
263
+ cleanup();
264
+ }
265
+ });
266
+ }
267
+ const cacheEntry = updateCache(shardKey, (currentCacheEntry) => ({
268
+ ...currentCacheEntry,
269
+ referenceCount: currentCacheEntry.referenceCount - 1
270
+ }));
271
+ }
272
+ signal.addEventListener("abort", handleAbort);
273
+ try {
274
+ const cacheEntry = cache.get(shardKey);
275
+ if (!cacheEntry) {
276
+ const connectionAbortController = new AbortController();
277
+ const newConnectionPromise = transport({
278
+ payload,
279
+ signal: connectionAbortController.signal,
280
+ ...rest
281
+ });
282
+ const newCacheEntry = {
283
+ abortController: connectionAbortController,
284
+ connection: newConnectionPromise,
285
+ purgeScheduled: false,
286
+ referenceCount: 1
287
+ };
288
+ cache.set(shardKey, newCacheEntry);
289
+ const newConnection = await newConnectionPromise;
290
+ registerIterableCleanup(newConnection, cleanup);
291
+ updateCache(shardKey, (currentCacheEntry) => ({
292
+ ...currentCacheEntry,
293
+ connection: newConnection
294
+ }));
295
+ return newConnection;
296
+ } else {
297
+ updateCache(shardKey, (currentCacheEntry) => ({
298
+ ...currentCacheEntry,
299
+ referenceCount: currentCacheEntry.referenceCount + 1
300
+ }));
301
+ const connectionOrConnectionPromise = cacheEntry.connection;
302
+ const cachedConnection = "then" in connectionOrConnectionPromise ? await connectionOrConnectionPromise : connectionOrConnectionPromise;
303
+ registerIterableCleanup(cachedConnection, cleanup);
304
+ await cachedConnection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload);
305
+ return cachedConnection;
306
+ }
307
+ } catch (e) {
308
+ cleanup();
309
+ throw e;
310
+ }
311
+ };
312
+ }
313
+
314
+ // src/rpc-websocket-transport.ts
315
+ function createDefaultRpcSubscriptionsTransport(config) {
316
+ const { getShard, intervalMs, ...rest } = config;
317
+ return functional.pipe(
318
+ rpcTransport.createWebSocketTransport({
319
+ ...rest,
320
+ sendBufferHighWatermark: config.sendBufferHighWatermark ?? // Let 128KB of data into the WebSocket buffer before buffering it in the app.
321
+ 131072
322
+ }),
323
+ (transport) => getWebSocketTransportWithAutoping({
324
+ intervalMs: intervalMs ?? 5e3,
325
+ transport
326
+ }),
327
+ (transport) => getWebSocketTransportWithConnectionSharding({
328
+ getShard,
329
+ transport
330
+ })
331
+ );
332
+ }
333
+
334
+ exports.createDefaultRpcSubscriptionsTransport = createDefaultRpcSubscriptionsTransport;
142
335
  exports.createDefaultRpcTransport = createDefaultRpcTransport;
143
336
  exports.createSolanaRpc = createSolanaRpc;
337
+ exports.createSolanaRpcSubscriptions = createSolanaRpcSubscriptions;
338
+ Object.keys(addresses).forEach(function (k) {
339
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
340
+ enumerable: true,
341
+ get: function () { return addresses[k]; }
342
+ });
343
+ });
344
+ Object.keys(instructions).forEach(function (k) {
345
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
346
+ enumerable: true,
347
+ get: function () { return instructions[k]; }
348
+ });
349
+ });
144
350
  Object.keys(keys).forEach(function (k) {
145
- if (k !== 'default' && !exports.hasOwnProperty(k)) Object.defineProperty(exports, k, {
351
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
146
352
  enumerable: true,
147
353
  get: function () { return keys[k]; }
148
354
  });
149
355
  });
356
+ Object.keys(transactions).forEach(function (k) {
357
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
358
+ enumerable: true,
359
+ get: function () { return transactions[k]; }
360
+ });
361
+ });
150
362
  //# sourceMappingURL=out.js.map
151
363
  //# sourceMappingURL=index.browser.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/rpc.ts","../src/rpc-integer-overflow-error.ts","../src/rpc-default-config.ts","../src/rpc-transport.ts","../src/rpc-request-coalescer.ts","../src/rpc-request-deduplication.ts"],"names":[],"mappings":"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","sourcesContent":["export * from '@solana/keys';\nexport * from './rpc';\nexport * from './rpc-transport';\n","import { createSolanaRpcApi, SolanaRpcMethods } from '@solana/rpc-core';\nimport { createJsonRpc } from '@solana/rpc-transport';\nimport type { Rpc } from '@solana/rpc-transport/dist/types/json-rpc-types';\n\nimport { DEFAULT_RPC_CONFIG } from './rpc-default-config';\n\nexport function createSolanaRpc(config: Omit<Parameters<typeof createJsonRpc>[0], 'api'>): Rpc<SolanaRpcMethods> {\n return createJsonRpc<SolanaRpcMethods>({\n ...config,\n api: createSolanaRpcApi(DEFAULT_RPC_CONFIG),\n });\n}\n","export class SolanaJsonRpcIntegerOverflowError extends Error {\n readonly methodName: string;\n readonly keyPath: (number | string)[];\n readonly value: bigint;\n constructor(methodName: string, keyPath: (number | string)[], value: bigint) {\n const argPosition = (typeof keyPath[0] === 'number' ? keyPath[0] : parseInt(keyPath[0], 10)) + 1;\n let ordinal = '';\n const lastDigit = argPosition % 10;\n const lastTwoDigits = argPosition % 100;\n if (lastDigit == 1 && lastTwoDigits != 11) {\n ordinal = argPosition + 'st';\n } else if (lastDigit == 2 && lastTwoDigits != 12) {\n ordinal = argPosition + 'nd';\n } else if (lastDigit == 3 && lastTwoDigits != 13) {\n ordinal = argPosition + 'rd';\n } else {\n ordinal = argPosition + 'th';\n }\n const path =\n keyPath.length > 1\n ? keyPath\n .slice(1)\n .map(pathPart => (typeof pathPart === 'number' ? `[${pathPart}]` : pathPart))\n .join('.')\n : null;\n super(\n `The ${ordinal} argument to the \\`${methodName}\\` RPC method` +\n `${path ? ` at path \\`${path}\\`` : ''} was \\`${value}\\`. This number is ` +\n 'unsafe for use with the Solana JSON-RPC because it exceeds ' +\n '`Number.MAX_SAFE_INTEGER`.'\n );\n this.keyPath = keyPath;\n this.methodName = methodName;\n this.value = value;\n }\n get name() {\n return 'SolanaJsonRpcIntegerOverflowError';\n }\n}\n","import { createSolanaRpcApi } from '@solana/rpc-core';\n\nimport { SolanaJsonRpcIntegerOverflowError } from './rpc-integer-overflow-error';\n\nexport const DEFAULT_RPC_CONFIG: Partial<Parameters<typeof createSolanaRpcApi>[0]> = {\n onIntegerOverflow(methodName, keyPath, value) {\n throw new SolanaJsonRpcIntegerOverflowError(methodName, keyPath, value);\n },\n};\n","import { createHttpTransport } from '@solana/rpc-transport';\nimport { IRpcTransport } from '@solana/rpc-transport/dist/types/transports/transport-types';\n\nimport { getRpcTransportWithRequestCoalescing } from './rpc-request-coalescer';\nimport { getSolanaRpcPayloadDeduplicationKey } from './rpc-request-deduplication';\n\n/**\n * Lowercasing header names makes it easier to override user-supplied headers.\n */\nfunction normalizeHeaders<T extends Record<string, string>>(\n headers: T\n): { [K in keyof T & string as Lowercase<K>]: T[K] } {\n const out: Record<string, string> = {};\n for (const headerName in headers) {\n out[headerName.toLowerCase()] = headers[headerName];\n }\n return out as { [K in keyof T & string as Lowercase<K>]: T[K] };\n}\n\nexport function createDefaultRpcTransport(config: Parameters<typeof createHttpTransport>[0]): IRpcTransport {\n return getRpcTransportWithRequestCoalescing(\n createHttpTransport({\n ...config,\n headers: {\n ...(config.headers ? normalizeHeaders(config.headers) : undefined),\n ...({\n // Keep these headers lowercase so they will override any user-supplied headers above.\n 'solana-client': `js/${__VERSION__}` ?? 'UNKNOWN',\n } as { [overrideHeader: string]: string }),\n },\n }),\n getSolanaRpcPayloadDeduplicationKey\n );\n}\n","import { IRpcTransport } from '@solana/rpc-transport/dist/types/transports/transport-types';\n\ntype CoalescedRequest = {\n readonly abortController: AbortController;\n numConsumers: number;\n readonly responsePromise: Promise<unknown>;\n};\n\ntype GetDeduplicationKeyFn = (payload: unknown) => string | undefined;\n\nexport function getRpcTransportWithRequestCoalescing(\n transport: IRpcTransport,\n getDeduplicationKey: GetDeduplicationKeyFn\n): IRpcTransport {\n let coalescedRequestsByDeduplicationKey: Record<string, CoalescedRequest> | undefined;\n return async function makeCoalescedHttpRequest<TResponse>(\n config: Parameters<IRpcTransport>[0]\n ): Promise<TResponse> {\n const { payload, signal } = config;\n const deduplicationKey = getDeduplicationKey(payload);\n if (deduplicationKey === undefined) {\n return await transport(config);\n }\n if (!coalescedRequestsByDeduplicationKey) {\n Promise.resolve().then(() => {\n coalescedRequestsByDeduplicationKey = undefined;\n });\n coalescedRequestsByDeduplicationKey = {};\n }\n if (coalescedRequestsByDeduplicationKey[deduplicationKey] == null) {\n const abortController = new AbortController();\n coalescedRequestsByDeduplicationKey[deduplicationKey] = {\n abortController,\n numConsumers: 0,\n responsePromise: transport<TResponse>({\n ...config,\n signal: abortController.signal,\n }),\n };\n }\n const coalescedRequest = coalescedRequestsByDeduplicationKey[deduplicationKey];\n coalescedRequest.numConsumers++;\n if (signal) {\n const responsePromise = coalescedRequest.responsePromise as Promise<TResponse>;\n return await new Promise<TResponse>((resolve, reject) => {\n const handleAbort = (e: AbortSignalEventMap['abort']) => {\n signal.removeEventListener('abort', handleAbort);\n coalescedRequest.numConsumers -= 1;\n if (coalescedRequest.numConsumers === 0) {\n const abortController = coalescedRequest.abortController;\n abortController.abort();\n }\n const abortError = new DOMException((e.target as AbortSignal).reason, 'AbortError');\n reject(abortError);\n };\n signal.addEventListener('abort', handleAbort);\n responsePromise.then(resolve).finally(() => {\n signal.removeEventListener('abort', handleAbort);\n });\n });\n } else {\n return (await coalescedRequest.responsePromise) as TResponse;\n }\n };\n}\n","// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport fastStableStringify from 'fast-stable-stringify';\n\nexport function getSolanaRpcPayloadDeduplicationKey(payload: unknown): string | undefined {\n if (payload == null || typeof payload !== 'object' || Array.isArray(payload)) {\n return;\n }\n if ('jsonrpc' in payload && payload.jsonrpc === '2.0' && 'method' in payload && 'params' in payload) {\n return fastStableStringify([payload.method, payload.params]);\n }\n}\n"]}
1
+ {"version":3,"sources":["../../build-scripts/env-shim.ts","../src/index.ts","../src/rpc.ts","../src/rpc-integer-overflow-error.ts","../src/rpc-default-config.ts","../src/rpc-transport.ts","../src/rpc-request-coalescer.ts","../src/rpc-request-deduplication.ts","../src/rpc-websocket-transport.ts","../src/rpc-websocket-autopinger.ts","../src/rpc-websocket-connection-sharding.ts"],"names":["pipe","args"],"mappings":"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","sourcesContent":["// Clever obfuscation to prevent the build system from inlining the value of `NODE_ENV`\nexport const __DEV__ = /* @__PURE__ */ (() => (process as any)['en' + 'v'].NODE_ENV === 'development')();\n","export * from '@solana/addresses';\nexport * from '@solana/instructions';\nexport * from '@solana/keys';\nexport * from '@solana/transactions';\nexport * from './rpc';\nexport * from './rpc-transport';\nexport * from './rpc-websocket-transport';\n","import {\n createSolanaRpcApi,\n createSolanaRpcSubscriptionsApi,\n SolanaRpcMethods,\n SolanaRpcSubscriptions,\n} from '@solana/rpc-core';\nimport { createJsonRpc, createJsonSubscriptionRpc } from '@solana/rpc-transport';\nimport type { Rpc, RpcSubscriptions } from '@solana/rpc-transport/dist/types/json-rpc-types';\n\nimport { DEFAULT_RPC_CONFIG } from './rpc-default-config';\n\nexport function createSolanaRpc(config: Omit<Parameters<typeof createJsonRpc>[0], 'api'>): Rpc<SolanaRpcMethods> {\n return createJsonRpc({\n ...config,\n api: createSolanaRpcApi(DEFAULT_RPC_CONFIG),\n });\n}\n\nexport function createSolanaRpcSubscriptions(\n config: Omit<Parameters<typeof createJsonSubscriptionRpc>[0], 'api'>\n): RpcSubscriptions<SolanaRpcSubscriptions> {\n return createJsonSubscriptionRpc({\n ...config,\n api: createSolanaRpcSubscriptionsApi(DEFAULT_RPC_CONFIG),\n });\n}\n","export class SolanaJsonRpcIntegerOverflowError extends Error {\n readonly methodName: string;\n readonly keyPath: (number | string)[];\n readonly value: bigint;\n constructor(methodName: string, keyPath: (number | string)[], value: bigint) {\n const argPosition = (typeof keyPath[0] === 'number' ? keyPath[0] : parseInt(keyPath[0], 10)) + 1;\n let ordinal = '';\n const lastDigit = argPosition % 10;\n const lastTwoDigits = argPosition % 100;\n if (lastDigit == 1 && lastTwoDigits != 11) {\n ordinal = argPosition + 'st';\n } else if (lastDigit == 2 && lastTwoDigits != 12) {\n ordinal = argPosition + 'nd';\n } else if (lastDigit == 3 && lastTwoDigits != 13) {\n ordinal = argPosition + 'rd';\n } else {\n ordinal = argPosition + 'th';\n }\n const path =\n keyPath.length > 1\n ? keyPath\n .slice(1)\n .map(pathPart => (typeof pathPart === 'number' ? `[${pathPart}]` : pathPart))\n .join('.')\n : null;\n super(\n `The ${ordinal} argument to the \\`${methodName}\\` RPC method` +\n `${path ? ` at path \\`${path}\\`` : ''} was \\`${value}\\`. This number is ` +\n 'unsafe for use with the Solana JSON-RPC because it exceeds ' +\n '`Number.MAX_SAFE_INTEGER`.'\n );\n this.keyPath = keyPath;\n this.methodName = methodName;\n this.value = value;\n }\n get name() {\n return 'SolanaJsonRpcIntegerOverflowError';\n }\n}\n","import { createSolanaRpcApi } from '@solana/rpc-core';\n\nimport { SolanaJsonRpcIntegerOverflowError } from './rpc-integer-overflow-error';\n\nexport const DEFAULT_RPC_CONFIG: Partial<Parameters<typeof createSolanaRpcApi>[0]> = {\n onIntegerOverflow(methodName, keyPath, value) {\n throw new SolanaJsonRpcIntegerOverflowError(methodName, keyPath, value);\n },\n};\n","import { pipe } from '@solana/functional';\nimport { createHttpTransport } from '@solana/rpc-transport';\nimport { IRpcTransport } from '@solana/rpc-transport/dist/types/transports/transport-types';\n\nimport { getRpcTransportWithRequestCoalescing } from './rpc-request-coalescer';\nimport { getSolanaRpcPayloadDeduplicationKey } from './rpc-request-deduplication';\n\n/**\n * Lowercasing header names makes it easier to override user-supplied headers.\n */\nfunction normalizeHeaders<T extends Record<string, string>>(\n headers: T\n): { [K in keyof T & string as Lowercase<K>]: T[K] } {\n const out: Record<string, string> = {};\n for (const headerName in headers) {\n out[headerName.toLowerCase()] = headers[headerName];\n }\n return out as { [K in keyof T & string as Lowercase<K>]: T[K] };\n}\n\nexport function createDefaultRpcTransport(config: Parameters<typeof createHttpTransport>[0]): IRpcTransport {\n return pipe(\n createHttpTransport({\n ...config,\n headers: {\n ...(config.headers ? normalizeHeaders(config.headers) : undefined),\n ...({\n // Keep these headers lowercase so they will override any user-supplied headers above.\n 'solana-client': `js/${__VERSION__}` ?? 'UNKNOWN',\n } as { [overrideHeader: string]: string }),\n },\n }),\n transport => getRpcTransportWithRequestCoalescing(transport, getSolanaRpcPayloadDeduplicationKey)\n );\n}\n","import { IRpcTransport } from '@solana/rpc-transport/dist/types/transports/transport-types';\n\ntype CoalescedRequest = {\n readonly abortController: AbortController;\n numConsumers: number;\n readonly responsePromise: Promise<unknown>;\n};\n\ntype GetDeduplicationKeyFn = (payload: unknown) => string | undefined;\n\nexport function getRpcTransportWithRequestCoalescing(\n transport: IRpcTransport,\n getDeduplicationKey: GetDeduplicationKeyFn\n): IRpcTransport {\n let coalescedRequestsByDeduplicationKey: Record<string, CoalescedRequest> | undefined;\n return async function makeCoalescedHttpRequest<TResponse>(\n config: Parameters<IRpcTransport>[0]\n ): Promise<TResponse> {\n const { payload, signal } = config;\n const deduplicationKey = getDeduplicationKey(payload);\n if (deduplicationKey === undefined) {\n return await transport(config);\n }\n if (!coalescedRequestsByDeduplicationKey) {\n Promise.resolve().then(() => {\n coalescedRequestsByDeduplicationKey = undefined;\n });\n coalescedRequestsByDeduplicationKey = {};\n }\n if (coalescedRequestsByDeduplicationKey[deduplicationKey] == null) {\n const abortController = new AbortController();\n coalescedRequestsByDeduplicationKey[deduplicationKey] = {\n abortController,\n numConsumers: 0,\n responsePromise: transport<TResponse>({\n ...config,\n signal: abortController.signal,\n }),\n };\n }\n const coalescedRequest = coalescedRequestsByDeduplicationKey[deduplicationKey];\n coalescedRequest.numConsumers++;\n if (signal) {\n const responsePromise = coalescedRequest.responsePromise as Promise<TResponse>;\n return await new Promise<TResponse>((resolve, reject) => {\n const handleAbort = (e: AbortSignalEventMap['abort']) => {\n signal.removeEventListener('abort', handleAbort);\n coalescedRequest.numConsumers -= 1;\n if (coalescedRequest.numConsumers === 0) {\n const abortController = coalescedRequest.abortController;\n abortController.abort();\n }\n const abortError = new DOMException((e.target as AbortSignal).reason, 'AbortError');\n reject(abortError);\n };\n signal.addEventListener('abort', handleAbort);\n responsePromise.then(resolve).finally(() => {\n signal.removeEventListener('abort', handleAbort);\n });\n });\n } else {\n return (await coalescedRequest.responsePromise) as TResponse;\n }\n };\n}\n","// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport fastStableStringify from 'fast-stable-stringify';\n\nfunction isJsonRpcPayload(payload: unknown): payload is Readonly<{ method: string; params: unknown }> {\n if (payload == null || typeof payload !== 'object' || Array.isArray(payload)) {\n return false;\n }\n return (\n 'jsonrpc' in payload &&\n payload.jsonrpc === '2.0' &&\n 'method' in payload &&\n typeof payload.method === 'string' &&\n 'params' in payload\n );\n}\n\nexport function getSolanaRpcPayloadDeduplicationKey(payload: unknown): string | undefined {\n return isJsonRpcPayload(payload) ? fastStableStringify([payload.method, payload.params]) : undefined;\n}\n\nexport function getSolanaRpcSubscriptionPayloadDeduplicationKey(payload: unknown): string | undefined {\n return isJsonRpcPayload(payload) && payload.method.endsWith('Subscribe')\n ? fastStableStringify([payload.method, payload.params])\n : undefined;\n}\n","import { pipe } from '@solana/functional';\nimport { createWebSocketTransport } from '@solana/rpc-transport';\nimport { IRpcWebSocketTransport } from '@solana/rpc-transport/dist/types/transports/transport-types';\n\nimport { getWebSocketTransportWithAutoping } from './rpc-websocket-autopinger';\nimport { getWebSocketTransportWithConnectionSharding } from './rpc-websocket-connection-sharding';\n\nexport function createDefaultRpcSubscriptionsTransport(\n config: Omit<Parameters<typeof createWebSocketTransport>[0], 'sendBufferHighWatermark'> & {\n /**\n * You might like to open more subscriptions per connection than your RPC provider allows\n * for. Using the initial payload as input, return a shard key from this method to assign\n * subscriptions to separate connections. One socket will be opened per shard key.\n */\n getShard?: (payload: unknown) => string;\n intervalMs?: number;\n sendBufferHighWatermark?: number;\n }\n): IRpcWebSocketTransport {\n const { getShard, intervalMs, ...rest } = config;\n return pipe(\n createWebSocketTransport({\n ...rest,\n sendBufferHighWatermark:\n config.sendBufferHighWatermark ??\n // Let 128KB of data into the WebSocket buffer before buffering it in the app.\n 131_072,\n }),\n transport =>\n getWebSocketTransportWithAutoping({\n intervalMs: intervalMs ?? 5_000,\n transport,\n }),\n transport =>\n getWebSocketTransportWithConnectionSharding({\n getShard,\n transport,\n })\n );\n}\n","import { IRpcWebSocketTransport } from '@solana/rpc-transport/dist/types/transports/transport-types';\n\ntype Config = Readonly<{\n intervalMs: number;\n transport: IRpcWebSocketTransport;\n}>;\n\nconst PING_PAYLOAD = {\n jsonrpc: '2.0',\n method: 'ping',\n} as const;\n\nexport function getWebSocketTransportWithAutoping({ intervalMs, transport }: Config): IRpcWebSocketTransport {\n const pingableConnections = new Map<\n Awaited<ReturnType<IRpcWebSocketTransport>>,\n Awaited<ReturnType<IRpcWebSocketTransport>>\n >();\n return async (...args) => {\n const connection = await transport(...args);\n let intervalId: string | number | NodeJS.Timeout | undefined;\n function sendPing() {\n connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(PING_PAYLOAD);\n }\n function restartPingTimer() {\n clearInterval(intervalId);\n intervalId = setInterval(sendPing, intervalMs);\n }\n if (pingableConnections.has(connection) === false) {\n pingableConnections.set(connection, {\n [Symbol.asyncIterator]: connection[Symbol.asyncIterator].bind(connection),\n send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: (\n ...args: Parameters<typeof connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED>\n ) => {\n restartPingTimer();\n return connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(...args);\n },\n });\n (async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _ of connection) {\n restartPingTimer();\n }\n } catch {\n /* empty */\n } finally {\n pingableConnections.delete(connection);\n clearInterval(intervalId);\n if (handleOffline) {\n globalThis.window.removeEventListener('offline', handleOffline);\n }\n if (handleOnline) {\n globalThis.window.removeEventListener('online', handleOnline);\n }\n }\n })();\n if (!__BROWSER__ || globalThis.navigator.onLine) {\n restartPingTimer();\n }\n let handleOffline;\n let handleOnline;\n if (__BROWSER__) {\n handleOffline = () => {\n clearInterval(intervalId);\n };\n handleOnline = () => {\n sendPing();\n restartPingTimer();\n };\n globalThis.window.addEventListener('offline', handleOffline);\n globalThis.window.addEventListener('online', handleOnline);\n }\n }\n return pingableConnections.get(connection)!;\n };\n}\n","import { IRpcWebSocketTransport } from '@solana/rpc-transport/dist/types/transports/transport-types';\n\ntype CacheEntry = Readonly<{\n abortController: AbortController;\n connection: Awaited<ReturnType<IRpcWebSocketTransport>> | ReturnType<IRpcWebSocketTransport>;\n purgeScheduled: boolean;\n referenceCount: number;\n}>;\ntype CacheKey = string | typeof NULL_SHARD_CACHE_KEY;\ntype Config = Readonly<{\n /**\n * You might like to open more subscriptions per connection than your RPC provider allows for.\n * Using the initial payload as input, return a shard key from this method to assign\n * subscriptions to separate connections. One socket will be opened per shard key.\n */\n getShard?: (payload: unknown) => string;\n transport: IRpcWebSocketTransport;\n}>;\n\nconst NULL_SHARD_CACHE_KEY = Symbol(\n __DEV__ ? 'Cache key to use when there is no connection sharding strategy' : undefined\n);\n\nfunction registerIterableCleanup(iterable: AsyncIterable<unknown>, cleanupFn: CallableFunction) {\n (async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for await (const _ of iterable);\n } catch {\n /* empty */\n } finally {\n // Run the cleanup function.\n cleanupFn();\n }\n })();\n}\n\nexport function getWebSocketTransportWithConnectionSharding({ getShard, transport }: Config): IRpcWebSocketTransport {\n const cache = new Map<CacheKey, CacheEntry>();\n function updateCache(shardKey: CacheKey, updater: (currentCacheEntry: CacheEntry) => CacheEntry) {\n const currentCacheEntry = cache.get(shardKey);\n if (!currentCacheEntry) {\n // TODO: Coded error.\n throw new Error(`Found no cache entry for connection with shard key \\`${shardKey.toString()}\\``);\n }\n const nextCacheEntry = updater(currentCacheEntry);\n cache.set(shardKey, nextCacheEntry);\n return nextCacheEntry;\n }\n return async (...args) => {\n const { payload, signal, ...rest } = args[0];\n const shardKey = getShard ? getShard(payload) : NULL_SHARD_CACHE_KEY;\n function cleanup() {\n cache.delete(shardKey);\n signal.removeEventListener('abort', handleAbort);\n }\n function handleAbort() {\n if (cache.get(shardKey)?.purgeScheduled !== true) {\n updateCache(shardKey, currentCacheEntry => ({\n ...currentCacheEntry,\n purgeScheduled: true,\n }));\n globalThis.queueMicrotask(() => {\n const cacheEntryAtEndOfRunloop = cache.get(shardKey);\n if (!cacheEntryAtEndOfRunloop) {\n return;\n }\n if (cacheEntryAtEndOfRunloop.referenceCount === 0) {\n cacheEntry.abortController.abort();\n cleanup();\n }\n });\n }\n const cacheEntry = updateCache(shardKey, currentCacheEntry => ({\n ...currentCacheEntry,\n referenceCount: currentCacheEntry.referenceCount - 1,\n }));\n }\n signal.addEventListener('abort', handleAbort);\n try {\n const cacheEntry = cache.get(shardKey);\n if (!cacheEntry) {\n const connectionAbortController = new AbortController();\n const newConnectionPromise = transport({\n payload,\n signal: connectionAbortController.signal,\n ...rest,\n });\n const newCacheEntry = {\n abortController: connectionAbortController,\n connection: newConnectionPromise,\n purgeScheduled: false,\n referenceCount: 1,\n };\n cache.set(shardKey, newCacheEntry);\n const newConnection = await newConnectionPromise;\n registerIterableCleanup(newConnection, cleanup);\n updateCache(shardKey, currentCacheEntry => ({\n ...currentCacheEntry,\n connection: newConnection,\n }));\n return newConnection;\n } else {\n updateCache(shardKey, currentCacheEntry => ({\n ...currentCacheEntry,\n referenceCount: currentCacheEntry.referenceCount + 1,\n }));\n const connectionOrConnectionPromise = cacheEntry.connection;\n const cachedConnection =\n 'then' in connectionOrConnectionPromise\n ? await connectionOrConnectionPromise\n : connectionOrConnectionPromise;\n registerIterableCleanup(cachedConnection, cleanup);\n await cachedConnection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload);\n return cachedConnection;\n }\n } catch (e) {\n cleanup();\n throw e;\n }\n };\n}\n"]}
@@ -1,9 +1,14 @@
1
+ export * from '@solana/addresses';
2
+ export * from '@solana/instructions';
1
3
  export * from '@solana/keys';
2
- import { createSolanaRpcApi } from '@solana/rpc-core';
3
- import { createJsonRpc, createHttpTransport } from '@solana/rpc-transport';
4
+ export * from '@solana/transactions';
5
+ import { createSolanaRpcApi, createSolanaRpcSubscriptionsApi } from '@solana/rpc-core';
6
+ import { createJsonRpc, createJsonSubscriptionRpc, createHttpTransport, createWebSocketTransport } from '@solana/rpc-transport';
7
+ import { pipe } from '@solana/functional';
4
8
  import fastStableStringify from 'fast-stable-stringify';
5
9
 
6
- // src/index.ts
10
+ // ../build-scripts/env-shim.ts
11
+ var __DEV__ = /* @__PURE__ */ (() => process["env"].NODE_ENV === "development")();
7
12
 
8
13
  // src/rpc-integer-overflow-error.ts
9
14
  var SolanaJsonRpcIntegerOverflowError = class extends Error {
@@ -48,6 +53,12 @@ function createSolanaRpc(config) {
48
53
  api: createSolanaRpcApi(DEFAULT_RPC_CONFIG)
49
54
  });
50
55
  }
56
+ function createSolanaRpcSubscriptions(config) {
57
+ return createJsonSubscriptionRpc({
58
+ ...config,
59
+ api: createSolanaRpcSubscriptionsApi(DEFAULT_RPC_CONFIG)
60
+ });
61
+ }
51
62
 
52
63
  // src/rpc-request-coalescer.ts
53
64
  function getRpcTransportWithRequestCoalescing(transport, getDeduplicationKey) {
@@ -100,13 +111,14 @@ function getRpcTransportWithRequestCoalescing(transport, getDeduplicationKey) {
100
111
  }
101
112
  };
102
113
  }
103
- function getSolanaRpcPayloadDeduplicationKey(payload) {
114
+ function isJsonRpcPayload(payload) {
104
115
  if (payload == null || typeof payload !== "object" || Array.isArray(payload)) {
105
- return;
106
- }
107
- if ("jsonrpc" in payload && payload.jsonrpc === "2.0" && "method" in payload && "params" in payload) {
108
- return fastStableStringify([payload.method, payload.params]);
116
+ return false;
109
117
  }
118
+ return "jsonrpc" in payload && payload.jsonrpc === "2.0" && "method" in payload && typeof payload.method === "string" && "params" in payload;
119
+ }
120
+ function getSolanaRpcPayloadDeduplicationKey(payload) {
121
+ return isJsonRpcPayload(payload) ? fastStableStringify([payload.method, payload.params]) : void 0;
110
122
  }
111
123
 
112
124
  // src/rpc-transport.ts
@@ -118,7 +130,7 @@ function normalizeHeaders(headers) {
118
130
  return out;
119
131
  }
120
132
  function createDefaultRpcTransport(config) {
121
- return getRpcTransportWithRequestCoalescing(
133
+ return pipe(
122
134
  createHttpTransport({
123
135
  ...config,
124
136
  headers: {
@@ -129,10 +141,190 @@ function createDefaultRpcTransport(config) {
129
141
  }
130
142
  }
131
143
  }),
132
- getSolanaRpcPayloadDeduplicationKey
144
+ (transport) => getRpcTransportWithRequestCoalescing(transport, getSolanaRpcPayloadDeduplicationKey)
145
+ );
146
+ }
147
+
148
+ // src/rpc-websocket-autopinger.ts
149
+ var PING_PAYLOAD = {
150
+ jsonrpc: "2.0",
151
+ method: "ping"
152
+ };
153
+ function getWebSocketTransportWithAutoping({ intervalMs, transport }) {
154
+ const pingableConnections = /* @__PURE__ */ new Map();
155
+ return async (...args) => {
156
+ const connection = await transport(...args);
157
+ let intervalId;
158
+ function sendPing() {
159
+ connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(PING_PAYLOAD);
160
+ }
161
+ function restartPingTimer() {
162
+ clearInterval(intervalId);
163
+ intervalId = setInterval(sendPing, intervalMs);
164
+ }
165
+ if (pingableConnections.has(connection) === false) {
166
+ pingableConnections.set(connection, {
167
+ [Symbol.asyncIterator]: connection[Symbol.asyncIterator].bind(connection),
168
+ send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: (...args2) => {
169
+ restartPingTimer();
170
+ return connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(...args2);
171
+ }
172
+ });
173
+ (async () => {
174
+ try {
175
+ for await (const _ of connection) {
176
+ restartPingTimer();
177
+ }
178
+ } catch {
179
+ } finally {
180
+ pingableConnections.delete(connection);
181
+ clearInterval(intervalId);
182
+ if (handleOffline) {
183
+ globalThis.window.removeEventListener("offline", handleOffline);
184
+ }
185
+ if (handleOnline) {
186
+ globalThis.window.removeEventListener("online", handleOnline);
187
+ }
188
+ }
189
+ })();
190
+ if (globalThis.navigator.onLine) {
191
+ restartPingTimer();
192
+ }
193
+ let handleOffline;
194
+ let handleOnline;
195
+ {
196
+ handleOffline = () => {
197
+ clearInterval(intervalId);
198
+ };
199
+ handleOnline = () => {
200
+ sendPing();
201
+ restartPingTimer();
202
+ };
203
+ globalThis.window.addEventListener("offline", handleOffline);
204
+ globalThis.window.addEventListener("online", handleOnline);
205
+ }
206
+ }
207
+ return pingableConnections.get(connection);
208
+ };
209
+ }
210
+
211
+ // src/rpc-websocket-connection-sharding.ts
212
+ var NULL_SHARD_CACHE_KEY = Symbol(
213
+ __DEV__ ? "Cache key to use when there is no connection sharding strategy" : void 0
214
+ );
215
+ function registerIterableCleanup(iterable, cleanupFn) {
216
+ (async () => {
217
+ try {
218
+ for await (const _ of iterable)
219
+ ;
220
+ } catch {
221
+ } finally {
222
+ cleanupFn();
223
+ }
224
+ })();
225
+ }
226
+ function getWebSocketTransportWithConnectionSharding({ getShard, transport }) {
227
+ const cache = /* @__PURE__ */ new Map();
228
+ function updateCache(shardKey, updater) {
229
+ const currentCacheEntry = cache.get(shardKey);
230
+ if (!currentCacheEntry) {
231
+ throw new Error(`Found no cache entry for connection with shard key \`${shardKey.toString()}\``);
232
+ }
233
+ const nextCacheEntry = updater(currentCacheEntry);
234
+ cache.set(shardKey, nextCacheEntry);
235
+ return nextCacheEntry;
236
+ }
237
+ return async (...args) => {
238
+ const { payload, signal, ...rest } = args[0];
239
+ const shardKey = getShard ? getShard(payload) : NULL_SHARD_CACHE_KEY;
240
+ function cleanup() {
241
+ cache.delete(shardKey);
242
+ signal.removeEventListener("abort", handleAbort);
243
+ }
244
+ function handleAbort() {
245
+ if (cache.get(shardKey)?.purgeScheduled !== true) {
246
+ updateCache(shardKey, (currentCacheEntry) => ({
247
+ ...currentCacheEntry,
248
+ purgeScheduled: true
249
+ }));
250
+ globalThis.queueMicrotask(() => {
251
+ const cacheEntryAtEndOfRunloop = cache.get(shardKey);
252
+ if (!cacheEntryAtEndOfRunloop) {
253
+ return;
254
+ }
255
+ if (cacheEntryAtEndOfRunloop.referenceCount === 0) {
256
+ cacheEntry.abortController.abort();
257
+ cleanup();
258
+ }
259
+ });
260
+ }
261
+ const cacheEntry = updateCache(shardKey, (currentCacheEntry) => ({
262
+ ...currentCacheEntry,
263
+ referenceCount: currentCacheEntry.referenceCount - 1
264
+ }));
265
+ }
266
+ signal.addEventListener("abort", handleAbort);
267
+ try {
268
+ const cacheEntry = cache.get(shardKey);
269
+ if (!cacheEntry) {
270
+ const connectionAbortController = new AbortController();
271
+ const newConnectionPromise = transport({
272
+ payload,
273
+ signal: connectionAbortController.signal,
274
+ ...rest
275
+ });
276
+ const newCacheEntry = {
277
+ abortController: connectionAbortController,
278
+ connection: newConnectionPromise,
279
+ purgeScheduled: false,
280
+ referenceCount: 1
281
+ };
282
+ cache.set(shardKey, newCacheEntry);
283
+ const newConnection = await newConnectionPromise;
284
+ registerIterableCleanup(newConnection, cleanup);
285
+ updateCache(shardKey, (currentCacheEntry) => ({
286
+ ...currentCacheEntry,
287
+ connection: newConnection
288
+ }));
289
+ return newConnection;
290
+ } else {
291
+ updateCache(shardKey, (currentCacheEntry) => ({
292
+ ...currentCacheEntry,
293
+ referenceCount: currentCacheEntry.referenceCount + 1
294
+ }));
295
+ const connectionOrConnectionPromise = cacheEntry.connection;
296
+ const cachedConnection = "then" in connectionOrConnectionPromise ? await connectionOrConnectionPromise : connectionOrConnectionPromise;
297
+ registerIterableCleanup(cachedConnection, cleanup);
298
+ await cachedConnection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload);
299
+ return cachedConnection;
300
+ }
301
+ } catch (e) {
302
+ cleanup();
303
+ throw e;
304
+ }
305
+ };
306
+ }
307
+
308
+ // src/rpc-websocket-transport.ts
309
+ function createDefaultRpcSubscriptionsTransport(config) {
310
+ const { getShard, intervalMs, ...rest } = config;
311
+ return pipe(
312
+ createWebSocketTransport({
313
+ ...rest,
314
+ sendBufferHighWatermark: config.sendBufferHighWatermark ?? // Let 128KB of data into the WebSocket buffer before buffering it in the app.
315
+ 131072
316
+ }),
317
+ (transport) => getWebSocketTransportWithAutoping({
318
+ intervalMs: intervalMs ?? 5e3,
319
+ transport
320
+ }),
321
+ (transport) => getWebSocketTransportWithConnectionSharding({
322
+ getShard,
323
+ transport
324
+ })
133
325
  );
134
326
  }
135
327
 
136
- export { createDefaultRpcTransport, createSolanaRpc };
328
+ export { createDefaultRpcSubscriptionsTransport, createDefaultRpcTransport, createSolanaRpc, createSolanaRpcSubscriptions };
137
329
  //# sourceMappingURL=out.js.map
138
330
  //# sourceMappingURL=index.browser.js.map