@solana/web3.js 2.0.0-experimental.46f8588 → 2.0.0-experimental.4747ac5

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) {
@@ -124,7 +135,7 @@ function normalizeHeaders(headers) {
124
135
  return out;
125
136
  }
126
137
  function createDefaultRpcTransport(config) {
127
- return getRpcTransportWithRequestCoalescing(
138
+ return functional.pipe(
128
139
  rpcTransport.createHttpTransport({
129
140
  ...config,
130
141
  headers: {
@@ -135,17 +146,217 @@ function createDefaultRpcTransport(config) {
135
146
  }
136
147
  }
137
148
  }),
138
- getSolanaRpcPayloadDeduplicationKey
149
+ (transport) => getRpcTransportWithRequestCoalescing(transport, getSolanaRpcPayloadDeduplicationKey)
139
150
  );
140
151
  }
141
152
 
153
+ // src/rpc-websocket-autopinger.ts
154
+ var PING_PAYLOAD = {
155
+ jsonrpc: "2.0",
156
+ method: "ping"
157
+ };
158
+ function getWebSocketTransportWithAutoping({ intervalMs, transport }) {
159
+ const pingableConnections = /* @__PURE__ */ new Map();
160
+ return async (...args) => {
161
+ const connection = await transport(...args);
162
+ let intervalId;
163
+ function sendPing() {
164
+ connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(PING_PAYLOAD);
165
+ }
166
+ function restartPingTimer() {
167
+ clearInterval(intervalId);
168
+ intervalId = setInterval(sendPing, intervalMs);
169
+ }
170
+ if (pingableConnections.has(connection) === false) {
171
+ pingableConnections.set(connection, {
172
+ [Symbol.asyncIterator]: connection[Symbol.asyncIterator].bind(connection),
173
+ send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: (...args2) => {
174
+ restartPingTimer();
175
+ return connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(...args2);
176
+ }
177
+ });
178
+ (async () => {
179
+ try {
180
+ for await (const _ of connection) {
181
+ restartPingTimer();
182
+ }
183
+ } catch {
184
+ } finally {
185
+ pingableConnections.delete(connection);
186
+ clearInterval(intervalId);
187
+ if (handleOffline) {
188
+ globalThis.window.removeEventListener("offline", handleOffline);
189
+ }
190
+ if (handleOnline) {
191
+ globalThis.window.removeEventListener("online", handleOnline);
192
+ }
193
+ }
194
+ })();
195
+ if (globalThis.navigator.onLine) {
196
+ restartPingTimer();
197
+ }
198
+ let handleOffline;
199
+ let handleOnline;
200
+ {
201
+ handleOffline = () => {
202
+ clearInterval(intervalId);
203
+ };
204
+ handleOnline = () => {
205
+ sendPing();
206
+ restartPingTimer();
207
+ };
208
+ globalThis.window.addEventListener("offline", handleOffline);
209
+ globalThis.window.addEventListener("online", handleOnline);
210
+ }
211
+ }
212
+ return pingableConnections.get(connection);
213
+ };
214
+ }
215
+
216
+ // src/rpc-websocket-connection-sharding.ts
217
+ var NULL_SHARD_CACHE_KEY = Symbol(
218
+ __DEV__ ? "Cache key to use when there is no connection sharding strategy" : void 0
219
+ );
220
+ function registerIterableCleanup(iterable, cleanupFn) {
221
+ (async () => {
222
+ try {
223
+ for await (const _ of iterable)
224
+ ;
225
+ } catch {
226
+ } finally {
227
+ cleanupFn();
228
+ }
229
+ })();
230
+ }
231
+ function getWebSocketTransportWithConnectionSharding({ getShard, transport }) {
232
+ const cache = /* @__PURE__ */ new Map();
233
+ function updateCache(shardKey, updater) {
234
+ const currentCacheEntry = cache.get(shardKey);
235
+ if (!currentCacheEntry) {
236
+ throw new Error(`Found no cache entry for connection with shard key \`${shardKey.toString()}\``);
237
+ }
238
+ const nextCacheEntry = updater(currentCacheEntry);
239
+ cache.set(shardKey, nextCacheEntry);
240
+ return nextCacheEntry;
241
+ }
242
+ return async (...args) => {
243
+ const { payload, signal, ...rest } = args[0];
244
+ const shardKey = getShard ? getShard(payload) : NULL_SHARD_CACHE_KEY;
245
+ function cleanup() {
246
+ cache.delete(shardKey);
247
+ signal.removeEventListener("abort", handleAbort);
248
+ }
249
+ function handleAbort() {
250
+ if (cache.get(shardKey)?.purgeScheduled !== true) {
251
+ updateCache(shardKey, (currentCacheEntry) => ({
252
+ ...currentCacheEntry,
253
+ purgeScheduled: true
254
+ }));
255
+ globalThis.queueMicrotask(() => {
256
+ const cacheEntryAtEndOfRunloop = cache.get(shardKey);
257
+ if (!cacheEntryAtEndOfRunloop) {
258
+ return;
259
+ }
260
+ if (cacheEntryAtEndOfRunloop.referenceCount === 0) {
261
+ cacheEntry.abortController.abort();
262
+ cleanup();
263
+ }
264
+ });
265
+ }
266
+ const cacheEntry = updateCache(shardKey, (currentCacheEntry) => ({
267
+ ...currentCacheEntry,
268
+ referenceCount: currentCacheEntry.referenceCount - 1
269
+ }));
270
+ }
271
+ signal.addEventListener("abort", handleAbort);
272
+ try {
273
+ const cacheEntry = cache.get(shardKey);
274
+ if (!cacheEntry) {
275
+ const connectionAbortController = new AbortController();
276
+ const newConnectionPromise = transport({
277
+ payload,
278
+ signal: connectionAbortController.signal,
279
+ ...rest
280
+ });
281
+ const newCacheEntry = {
282
+ abortController: connectionAbortController,
283
+ connection: newConnectionPromise,
284
+ purgeScheduled: false,
285
+ referenceCount: 1
286
+ };
287
+ cache.set(shardKey, newCacheEntry);
288
+ const newConnection = await newConnectionPromise;
289
+ registerIterableCleanup(newConnection, cleanup);
290
+ updateCache(shardKey, (currentCacheEntry) => ({
291
+ ...currentCacheEntry,
292
+ connection: newConnection
293
+ }));
294
+ return newConnection;
295
+ } else {
296
+ updateCache(shardKey, (currentCacheEntry) => ({
297
+ ...currentCacheEntry,
298
+ referenceCount: currentCacheEntry.referenceCount + 1
299
+ }));
300
+ const connectionOrConnectionPromise = cacheEntry.connection;
301
+ const cachedConnection = "then" in connectionOrConnectionPromise ? await connectionOrConnectionPromise : connectionOrConnectionPromise;
302
+ registerIterableCleanup(cachedConnection, cleanup);
303
+ await cachedConnection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload);
304
+ return cachedConnection;
305
+ }
306
+ } catch (e) {
307
+ cleanup();
308
+ throw e;
309
+ }
310
+ };
311
+ }
312
+
313
+ // src/rpc-websocket-transport.ts
314
+ function createDefaultRpcSubscriptionsTransport(config) {
315
+ const { getShard, intervalMs, ...rest } = config;
316
+ return functional.pipe(
317
+ rpcTransport.createWebSocketTransport({
318
+ ...rest,
319
+ sendBufferHighWatermark: config.sendBufferHighWatermark ?? // Let 128KB of data into the WebSocket buffer before buffering it in the app.
320
+ 131072
321
+ }),
322
+ (transport) => getWebSocketTransportWithAutoping({
323
+ intervalMs: intervalMs ?? 5e3,
324
+ transport
325
+ }),
326
+ (transport) => getWebSocketTransportWithConnectionSharding({
327
+ getShard,
328
+ transport
329
+ })
330
+ );
331
+ }
332
+
333
+ exports.createDefaultRpcSubscriptionsTransport = createDefaultRpcSubscriptionsTransport;
142
334
  exports.createDefaultRpcTransport = createDefaultRpcTransport;
143
335
  exports.createSolanaRpc = createSolanaRpc;
336
+ exports.createSolanaRpcSubscriptions = createSolanaRpcSubscriptions;
337
+ Object.keys(addresses).forEach(function (k) {
338
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
339
+ enumerable: true,
340
+ get: function () { return addresses[k]; }
341
+ });
342
+ });
343
+ Object.keys(instructions).forEach(function (k) {
344
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
345
+ enumerable: true,
346
+ get: function () { return instructions[k]; }
347
+ });
348
+ });
144
349
  Object.keys(keys).forEach(function (k) {
145
- if (k !== 'default' && !exports.hasOwnProperty(k)) Object.defineProperty(exports, k, {
350
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
146
351
  enumerable: true,
147
352
  get: function () { return keys[k]; }
148
353
  });
149
354
  });
355
+ Object.keys(transactions).forEach(function (k) {
356
+ if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
357
+ enumerable: true,
358
+ get: function () { return transactions[k]; }
359
+ });
360
+ });
150
361
  //# sourceMappingURL=out.js.map
151
362
  //# 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\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","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) {
@@ -118,7 +129,7 @@ function normalizeHeaders(headers) {
118
129
  return out;
119
130
  }
120
131
  function createDefaultRpcTransport(config) {
121
- return getRpcTransportWithRequestCoalescing(
132
+ return pipe(
122
133
  createHttpTransport({
123
134
  ...config,
124
135
  headers: {
@@ -129,10 +140,190 @@ function createDefaultRpcTransport(config) {
129
140
  }
130
141
  }
131
142
  }),
132
- getSolanaRpcPayloadDeduplicationKey
143
+ (transport) => getRpcTransportWithRequestCoalescing(transport, getSolanaRpcPayloadDeduplicationKey)
144
+ );
145
+ }
146
+
147
+ // src/rpc-websocket-autopinger.ts
148
+ var PING_PAYLOAD = {
149
+ jsonrpc: "2.0",
150
+ method: "ping"
151
+ };
152
+ function getWebSocketTransportWithAutoping({ intervalMs, transport }) {
153
+ const pingableConnections = /* @__PURE__ */ new Map();
154
+ return async (...args) => {
155
+ const connection = await transport(...args);
156
+ let intervalId;
157
+ function sendPing() {
158
+ connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(PING_PAYLOAD);
159
+ }
160
+ function restartPingTimer() {
161
+ clearInterval(intervalId);
162
+ intervalId = setInterval(sendPing, intervalMs);
163
+ }
164
+ if (pingableConnections.has(connection) === false) {
165
+ pingableConnections.set(connection, {
166
+ [Symbol.asyncIterator]: connection[Symbol.asyncIterator].bind(connection),
167
+ send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: (...args2) => {
168
+ restartPingTimer();
169
+ return connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(...args2);
170
+ }
171
+ });
172
+ (async () => {
173
+ try {
174
+ for await (const _ of connection) {
175
+ restartPingTimer();
176
+ }
177
+ } catch {
178
+ } finally {
179
+ pingableConnections.delete(connection);
180
+ clearInterval(intervalId);
181
+ if (handleOffline) {
182
+ globalThis.window.removeEventListener("offline", handleOffline);
183
+ }
184
+ if (handleOnline) {
185
+ globalThis.window.removeEventListener("online", handleOnline);
186
+ }
187
+ }
188
+ })();
189
+ if (globalThis.navigator.onLine) {
190
+ restartPingTimer();
191
+ }
192
+ let handleOffline;
193
+ let handleOnline;
194
+ {
195
+ handleOffline = () => {
196
+ clearInterval(intervalId);
197
+ };
198
+ handleOnline = () => {
199
+ sendPing();
200
+ restartPingTimer();
201
+ };
202
+ globalThis.window.addEventListener("offline", handleOffline);
203
+ globalThis.window.addEventListener("online", handleOnline);
204
+ }
205
+ }
206
+ return pingableConnections.get(connection);
207
+ };
208
+ }
209
+
210
+ // src/rpc-websocket-connection-sharding.ts
211
+ var NULL_SHARD_CACHE_KEY = Symbol(
212
+ __DEV__ ? "Cache key to use when there is no connection sharding strategy" : void 0
213
+ );
214
+ function registerIterableCleanup(iterable, cleanupFn) {
215
+ (async () => {
216
+ try {
217
+ for await (const _ of iterable)
218
+ ;
219
+ } catch {
220
+ } finally {
221
+ cleanupFn();
222
+ }
223
+ })();
224
+ }
225
+ function getWebSocketTransportWithConnectionSharding({ getShard, transport }) {
226
+ const cache = /* @__PURE__ */ new Map();
227
+ function updateCache(shardKey, updater) {
228
+ const currentCacheEntry = cache.get(shardKey);
229
+ if (!currentCacheEntry) {
230
+ throw new Error(`Found no cache entry for connection with shard key \`${shardKey.toString()}\``);
231
+ }
232
+ const nextCacheEntry = updater(currentCacheEntry);
233
+ cache.set(shardKey, nextCacheEntry);
234
+ return nextCacheEntry;
235
+ }
236
+ return async (...args) => {
237
+ const { payload, signal, ...rest } = args[0];
238
+ const shardKey = getShard ? getShard(payload) : NULL_SHARD_CACHE_KEY;
239
+ function cleanup() {
240
+ cache.delete(shardKey);
241
+ signal.removeEventListener("abort", handleAbort);
242
+ }
243
+ function handleAbort() {
244
+ if (cache.get(shardKey)?.purgeScheduled !== true) {
245
+ updateCache(shardKey, (currentCacheEntry) => ({
246
+ ...currentCacheEntry,
247
+ purgeScheduled: true
248
+ }));
249
+ globalThis.queueMicrotask(() => {
250
+ const cacheEntryAtEndOfRunloop = cache.get(shardKey);
251
+ if (!cacheEntryAtEndOfRunloop) {
252
+ return;
253
+ }
254
+ if (cacheEntryAtEndOfRunloop.referenceCount === 0) {
255
+ cacheEntry.abortController.abort();
256
+ cleanup();
257
+ }
258
+ });
259
+ }
260
+ const cacheEntry = updateCache(shardKey, (currentCacheEntry) => ({
261
+ ...currentCacheEntry,
262
+ referenceCount: currentCacheEntry.referenceCount - 1
263
+ }));
264
+ }
265
+ signal.addEventListener("abort", handleAbort);
266
+ try {
267
+ const cacheEntry = cache.get(shardKey);
268
+ if (!cacheEntry) {
269
+ const connectionAbortController = new AbortController();
270
+ const newConnectionPromise = transport({
271
+ payload,
272
+ signal: connectionAbortController.signal,
273
+ ...rest
274
+ });
275
+ const newCacheEntry = {
276
+ abortController: connectionAbortController,
277
+ connection: newConnectionPromise,
278
+ purgeScheduled: false,
279
+ referenceCount: 1
280
+ };
281
+ cache.set(shardKey, newCacheEntry);
282
+ const newConnection = await newConnectionPromise;
283
+ registerIterableCleanup(newConnection, cleanup);
284
+ updateCache(shardKey, (currentCacheEntry) => ({
285
+ ...currentCacheEntry,
286
+ connection: newConnection
287
+ }));
288
+ return newConnection;
289
+ } else {
290
+ updateCache(shardKey, (currentCacheEntry) => ({
291
+ ...currentCacheEntry,
292
+ referenceCount: currentCacheEntry.referenceCount + 1
293
+ }));
294
+ const connectionOrConnectionPromise = cacheEntry.connection;
295
+ const cachedConnection = "then" in connectionOrConnectionPromise ? await connectionOrConnectionPromise : connectionOrConnectionPromise;
296
+ registerIterableCleanup(cachedConnection, cleanup);
297
+ await cachedConnection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload);
298
+ return cachedConnection;
299
+ }
300
+ } catch (e) {
301
+ cleanup();
302
+ throw e;
303
+ }
304
+ };
305
+ }
306
+
307
+ // src/rpc-websocket-transport.ts
308
+ function createDefaultRpcSubscriptionsTransport(config) {
309
+ const { getShard, intervalMs, ...rest } = config;
310
+ return pipe(
311
+ createWebSocketTransport({
312
+ ...rest,
313
+ sendBufferHighWatermark: config.sendBufferHighWatermark ?? // Let 128KB of data into the WebSocket buffer before buffering it in the app.
314
+ 131072
315
+ }),
316
+ (transport) => getWebSocketTransportWithAutoping({
317
+ intervalMs: intervalMs ?? 5e3,
318
+ transport
319
+ }),
320
+ (transport) => getWebSocketTransportWithConnectionSharding({
321
+ getShard,
322
+ transport
323
+ })
133
324
  );
134
325
  }
135
326
 
136
- export { createDefaultRpcTransport, createSolanaRpc };
327
+ export { createDefaultRpcSubscriptionsTransport, createDefaultRpcTransport, createSolanaRpc, createSolanaRpcSubscriptions };
137
328
  //# sourceMappingURL=out.js.map
138
329
  //# sourceMappingURL=index.browser.js.map