@solana/web3.js 2.0.0-experimental.d6c5c0e → 2.0.0-experimental.da22638
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -13
- package/dist/index.browser.cjs +297 -9
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +277 -11
- package/dist/index.browser.js.map +1 -1
- package/dist/index.development.js +2567 -195
- package/dist/index.development.js.map +1 -1
- package/dist/index.native.js +264 -11
- package/dist/index.native.js.map +1 -1
- package/dist/index.node.cjs +288 -9
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.js +266 -11
- package/dist/index.node.js.map +1 -1
- package/dist/index.production.min.js +38 -4
- package/dist/types/cached-abortable-iterable.d.ts +11 -0
- package/dist/types/cached-abortable-iterable.d.ts.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/rpc-default-config.d.ts.map +1 -1
- package/dist/types/rpc-request-coalescer.d.ts +5 -0
- package/dist/types/rpc-request-coalescer.d.ts.map +1 -0
- package/dist/types/rpc-request-deduplication.d.ts +3 -0
- package/dist/types/rpc-request-deduplication.d.ts.map +1 -0
- package/dist/types/rpc-transport.d.ts.map +1 -1
- package/dist/types/rpc-websocket-autopinger.d.ts +8 -0
- package/dist/types/rpc-websocket-autopinger.d.ts.map +1 -0
- package/dist/types/rpc-websocket-connection-sharding.d.ts +13 -0
- package/dist/types/rpc-websocket-connection-sharding.d.ts.map +1 -0
- package/dist/types/rpc-websocket-transport.d.ts +13 -0
- package/dist/types/rpc-websocket-transport.d.ts.map +1 -0
- package/dist/types/rpc.d.ts +4 -3
- package/dist/types/rpc.d.ts.map +1 -1
- package/package.json +23 -21
package/dist/index.browser.js
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
export * from '@solana/addresses';
|
|
2
|
+
export * from '@solana/instructions';
|
|
1
3
|
export * from '@solana/keys';
|
|
2
|
-
|
|
3
|
-
import {
|
|
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';
|
|
8
|
+
import fastStableStringify from 'fast-stable-stringify';
|
|
4
9
|
|
|
5
|
-
//
|
|
10
|
+
// ../build-scripts/env-shim.ts
|
|
11
|
+
var __DEV__ = /* @__PURE__ */ (() => process["env"].NODE_ENV === "development")();
|
|
6
12
|
|
|
7
13
|
// src/rpc-integer-overflow-error.ts
|
|
8
14
|
var SolanaJsonRpcIntegerOverflowError = class extends Error {
|
|
@@ -39,12 +45,83 @@ var DEFAULT_RPC_CONFIG = {
|
|
|
39
45
|
throw new SolanaJsonRpcIntegerOverflowError(methodName, keyPath, value);
|
|
40
46
|
}
|
|
41
47
|
};
|
|
48
|
+
|
|
49
|
+
// src/rpc.ts
|
|
42
50
|
function createSolanaRpc(config) {
|
|
43
51
|
return createJsonRpc({
|
|
44
52
|
...config,
|
|
45
53
|
api: createSolanaRpcApi(DEFAULT_RPC_CONFIG)
|
|
46
54
|
});
|
|
47
55
|
}
|
|
56
|
+
function createSolanaRpcSubscriptions(config) {
|
|
57
|
+
return createJsonSubscriptionRpc({
|
|
58
|
+
...config,
|
|
59
|
+
api: createSolanaRpcSubscriptionsApi(DEFAULT_RPC_CONFIG)
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/rpc-request-coalescer.ts
|
|
64
|
+
function getRpcTransportWithRequestCoalescing(transport, getDeduplicationKey) {
|
|
65
|
+
let coalescedRequestsByDeduplicationKey;
|
|
66
|
+
return async function makeCoalescedHttpRequest(config) {
|
|
67
|
+
const { payload, signal } = config;
|
|
68
|
+
const deduplicationKey = getDeduplicationKey(payload);
|
|
69
|
+
if (deduplicationKey === void 0) {
|
|
70
|
+
return await transport(config);
|
|
71
|
+
}
|
|
72
|
+
if (!coalescedRequestsByDeduplicationKey) {
|
|
73
|
+
Promise.resolve().then(() => {
|
|
74
|
+
coalescedRequestsByDeduplicationKey = void 0;
|
|
75
|
+
});
|
|
76
|
+
coalescedRequestsByDeduplicationKey = {};
|
|
77
|
+
}
|
|
78
|
+
if (coalescedRequestsByDeduplicationKey[deduplicationKey] == null) {
|
|
79
|
+
const abortController = new AbortController();
|
|
80
|
+
coalescedRequestsByDeduplicationKey[deduplicationKey] = {
|
|
81
|
+
abortController,
|
|
82
|
+
numConsumers: 0,
|
|
83
|
+
responsePromise: transport({
|
|
84
|
+
...config,
|
|
85
|
+
signal: abortController.signal
|
|
86
|
+
})
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const coalescedRequest = coalescedRequestsByDeduplicationKey[deduplicationKey];
|
|
90
|
+
coalescedRequest.numConsumers++;
|
|
91
|
+
if (signal) {
|
|
92
|
+
const responsePromise = coalescedRequest.responsePromise;
|
|
93
|
+
return await new Promise((resolve, reject) => {
|
|
94
|
+
const handleAbort = (e) => {
|
|
95
|
+
signal.removeEventListener("abort", handleAbort);
|
|
96
|
+
coalescedRequest.numConsumers -= 1;
|
|
97
|
+
if (coalescedRequest.numConsumers === 0) {
|
|
98
|
+
const abortController = coalescedRequest.abortController;
|
|
99
|
+
abortController.abort();
|
|
100
|
+
}
|
|
101
|
+
const abortError = new DOMException(e.target.reason, "AbortError");
|
|
102
|
+
reject(abortError);
|
|
103
|
+
};
|
|
104
|
+
signal.addEventListener("abort", handleAbort);
|
|
105
|
+
responsePromise.then(resolve).finally(() => {
|
|
106
|
+
signal.removeEventListener("abort", handleAbort);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
} else {
|
|
110
|
+
return await coalescedRequest.responsePromise;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function isJsonRpcPayload(payload) {
|
|
115
|
+
if (payload == null || typeof payload !== "object" || Array.isArray(payload)) {
|
|
116
|
+
return false;
|
|
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;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// src/rpc-transport.ts
|
|
48
125
|
function normalizeHeaders(headers) {
|
|
49
126
|
const out = {};
|
|
50
127
|
for (const headerName in headers) {
|
|
@@ -53,16 +130,205 @@ function normalizeHeaders(headers) {
|
|
|
53
130
|
return out;
|
|
54
131
|
}
|
|
55
132
|
function createDefaultRpcTransport(config) {
|
|
56
|
-
return
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
133
|
+
return pipe(
|
|
134
|
+
createHttpTransport({
|
|
135
|
+
...config,
|
|
136
|
+
headers: {
|
|
137
|
+
...config.headers ? normalizeHeaders(config.headers) : void 0,
|
|
138
|
+
...{
|
|
139
|
+
// Keep these headers lowercase so they will override any user-supplied headers above.
|
|
140
|
+
"solana-client": `js/${"2.0.0-development"}` ?? "UNKNOWN"
|
|
141
|
+
}
|
|
63
142
|
}
|
|
143
|
+
}),
|
|
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);
|
|
64
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/cached-abortable-iterable.ts
|
|
212
|
+
function registerIterableCleanup(iterable, cleanupFn) {
|
|
213
|
+
(async () => {
|
|
214
|
+
try {
|
|
215
|
+
for await (const _ of iterable)
|
|
216
|
+
;
|
|
217
|
+
} catch {
|
|
218
|
+
} finally {
|
|
219
|
+
cleanupFn();
|
|
220
|
+
}
|
|
221
|
+
})();
|
|
222
|
+
}
|
|
223
|
+
function getCachedAbortableIterableFactory({
|
|
224
|
+
getAbortSignalFromInputArgs,
|
|
225
|
+
getCacheEntryMissingError,
|
|
226
|
+
getCacheKeyFromInputArgs,
|
|
227
|
+
onCacheHit,
|
|
228
|
+
onCreateIterable
|
|
229
|
+
}) {
|
|
230
|
+
const cache = /* @__PURE__ */ new Map();
|
|
231
|
+
function getCacheEntryOrThrow(cacheKey) {
|
|
232
|
+
const currentCacheEntry = cache.get(cacheKey);
|
|
233
|
+
if (!currentCacheEntry) {
|
|
234
|
+
throw getCacheEntryMissingError(cacheKey);
|
|
235
|
+
}
|
|
236
|
+
return currentCacheEntry;
|
|
237
|
+
}
|
|
238
|
+
return async (...args) => {
|
|
239
|
+
const cacheKey = getCacheKeyFromInputArgs(...args);
|
|
240
|
+
const signal = getAbortSignalFromInputArgs(...args);
|
|
241
|
+
if (cacheKey === void 0) {
|
|
242
|
+
return await onCreateIterable(signal, ...args);
|
|
243
|
+
}
|
|
244
|
+
const cleanup = () => {
|
|
245
|
+
cache.delete(cacheKey);
|
|
246
|
+
signal.removeEventListener("abort", handleAbort);
|
|
247
|
+
};
|
|
248
|
+
const handleAbort = () => {
|
|
249
|
+
const cacheEntry = getCacheEntryOrThrow(cacheKey);
|
|
250
|
+
if (cacheEntry.purgeScheduled !== true) {
|
|
251
|
+
cacheEntry.purgeScheduled = true;
|
|
252
|
+
globalThis.queueMicrotask(() => {
|
|
253
|
+
cacheEntry.purgeScheduled = false;
|
|
254
|
+
if (cacheEntry.referenceCount === 0) {
|
|
255
|
+
cacheEntry.abortController.abort();
|
|
256
|
+
cleanup();
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
cacheEntry.referenceCount--;
|
|
261
|
+
};
|
|
262
|
+
signal.addEventListener("abort", handleAbort);
|
|
263
|
+
try {
|
|
264
|
+
const cacheEntry = cache.get(cacheKey);
|
|
265
|
+
if (!cacheEntry) {
|
|
266
|
+
const singletonAbortController = new AbortController();
|
|
267
|
+
const newIterablePromise = onCreateIterable(singletonAbortController.signal, ...args);
|
|
268
|
+
const newCacheEntry = {
|
|
269
|
+
abortController: singletonAbortController,
|
|
270
|
+
iterable: newIterablePromise,
|
|
271
|
+
purgeScheduled: false,
|
|
272
|
+
referenceCount: 1
|
|
273
|
+
};
|
|
274
|
+
cache.set(cacheKey, newCacheEntry);
|
|
275
|
+
const newIterable = await newIterablePromise;
|
|
276
|
+
registerIterableCleanup(newIterable, cleanup);
|
|
277
|
+
newCacheEntry.iterable = newIterable;
|
|
278
|
+
return newIterable;
|
|
279
|
+
} else {
|
|
280
|
+
cacheEntry.referenceCount++;
|
|
281
|
+
const iterableOrIterablePromise = cacheEntry.iterable;
|
|
282
|
+
const cachedIterable = "then" in iterableOrIterablePromise ? await iterableOrIterablePromise : iterableOrIterablePromise;
|
|
283
|
+
await onCacheHit(cachedIterable, ...args);
|
|
284
|
+
return cachedIterable;
|
|
285
|
+
}
|
|
286
|
+
} catch (e) {
|
|
287
|
+
cleanup();
|
|
288
|
+
throw e;
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// src/rpc-websocket-connection-sharding.ts
|
|
294
|
+
var NULL_SHARD_CACHE_KEY = Symbol(
|
|
295
|
+
__DEV__ ? "Cache key to use when there is no connection sharding strategy" : void 0
|
|
296
|
+
);
|
|
297
|
+
function getWebSocketTransportWithConnectionSharding({ getShard, transport }) {
|
|
298
|
+
return getCachedAbortableIterableFactory({
|
|
299
|
+
getAbortSignalFromInputArgs: ({ signal }) => signal,
|
|
300
|
+
getCacheEntryMissingError(shardKey) {
|
|
301
|
+
return new Error(`Found no cache entry for connection with shard key \`${shardKey?.toString()}\``);
|
|
302
|
+
},
|
|
303
|
+
getCacheKeyFromInputArgs: ({ payload }) => getShard ? getShard(payload) : NULL_SHARD_CACHE_KEY,
|
|
304
|
+
onCacheHit: (connection, { payload }) => connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload),
|
|
305
|
+
onCreateIterable: (abortSignal, config) => transport({
|
|
306
|
+
...config,
|
|
307
|
+
signal: abortSignal
|
|
308
|
+
})
|
|
65
309
|
});
|
|
66
310
|
}
|
|
67
311
|
|
|
68
|
-
|
|
312
|
+
// src/rpc-websocket-transport.ts
|
|
313
|
+
function createDefaultRpcSubscriptionsTransport(config) {
|
|
314
|
+
const { getShard, intervalMs, ...rest } = config;
|
|
315
|
+
return pipe(
|
|
316
|
+
createWebSocketTransport({
|
|
317
|
+
...rest,
|
|
318
|
+
sendBufferHighWatermark: config.sendBufferHighWatermark ?? // Let 128KB of data into the WebSocket buffer before buffering it in the app.
|
|
319
|
+
131072
|
|
320
|
+
}),
|
|
321
|
+
(transport) => getWebSocketTransportWithAutoping({
|
|
322
|
+
intervalMs: intervalMs ?? 5e3,
|
|
323
|
+
transport
|
|
324
|
+
}),
|
|
325
|
+
(transport) => getWebSocketTransportWithConnectionSharding({
|
|
326
|
+
getShard,
|
|
327
|
+
transport
|
|
328
|
+
})
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export { createDefaultRpcSubscriptionsTransport, createDefaultRpcTransport, createSolanaRpc, createSolanaRpcSubscriptions };
|
|
333
|
+
//# sourceMappingURL=out.js.map
|
|
334
|
+
//# sourceMappingURL=index.browser.js.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"],"names":[],"mappings":";AAAA,cAAc;;;ACAd,SAA2B,0BAA0B;;;ACA9C,IAAM,oCAAN,cAAgD,MAAM;AAAA,EAIzD,YAAY,YAAoB,SAA8B,OAAe;AACzE,UAAM,eAAe,OAAO,QAAQ,CAAC,MAAM,WAAW,QAAQ,CAAC,IAAI,SAAS,QAAQ,CAAC,GAAG,EAAE,KAAK;AAC/F,QAAI,UAAU;AACd,UAAM,YAAY,cAAc;AAChC,UAAM,gBAAgB,cAAc;AACpC,QAAI,aAAa,KAAK,iBAAiB,IAAI;AACvC,gBAAU,cAAc;AAAA,IAC5B,WAAW,aAAa,KAAK,iBAAiB,IAAI;AAC9C,gBAAU,cAAc;AAAA,IAC5B,WAAW,aAAa,KAAK,iBAAiB,IAAI;AAC9C,gBAAU,cAAc;AAAA,IAC5B,OAAO;AACH,gBAAU,cAAc;AAAA,IAC5B;AACA,UAAM,OACF,QAAQ,SAAS,IACX,QACK,MAAM,CAAC,EACP,IAAI,cAAa,OAAO,aAAa,WAAW,IAAI,cAAc,QAAS,EAC3E,KAAK,GAAG,IACb;AACV;AAAA,MACI,OAAO,6BAA6B,0BAC7B,OAAO,cAAc,WAAW,YAAY;AAAA,IAGvD;AACA,SAAK,UAAU;AACf,SAAK,aAAa;AAClB,SAAK,QAAQ;AAAA,EACjB;AAAA,EACA,IAAI,OAAO;AACP,WAAO;AAAA,EACX;AACJ;;;ACnCO,IAAM,qBAAwE;AAAA,EACjF,kBAAkB,YAAY,SAAS,OAAO;AAC1C,UAAM,IAAI,kCAAkC,YAAY,SAAS,KAAK;AAAA,EAC1E;AACJ;;;AFJA,SAAS,qBAAqB;AAGvB,SAAS,gBAAgB,QAAiF;AAC7G,SAAO,cAAgC;AAAA,IACnC,GAAG;AAAA,IACH,KAAK,mBAAmB,kBAAkB;AAAA,EAC9C,CAAC;AACL;;;AGXA,SAAS,2BAA2B;AAMpC,SAAS,iBACL,SACiD;AACjD,QAAM,MAA8B,CAAC;AACrC,aAAW,cAAc,SAAS;AAC9B,QAAI,WAAW,YAAY,CAAC,IAAI,QAAQ,UAAU;AAAA,EACtD;AACA,SAAO;AACX;AAEO,SAAS,0BAA0B,QAAkE;AACxG,SAAO,oBAAoB;AAAA,IACvB,GAAG;AAAA,IACH,SAAS;AAAA,MACL,GAAI,OAAO,UAAU,iBAAiB,OAAO,OAAO,IAAI;AAAA,MACxD,GAAI;AAAA;AAAA,QAEA,iBAAiB,MAAM,yBAAiB;AAAA,MAC5C;AAAA,IACJ;AAAA,EACJ,CAAC;AACL","sourcesContent":["export * from '@solana/keys';\nexport * from './rpc';\nexport * from './rpc-transport';\n","import { SolanaRpcMethods, createSolanaRpcApi } from '@solana/rpc-core';\nimport { DEFAULT_RPC_CONFIG } from './rpc-default-config';\n\nimport { createJsonRpc } from '@solana/rpc-transport';\nimport type { Rpc } from '@solana/rpc-transport/dist/types/json-rpc-types';\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';\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\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 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}\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/cached-abortable-iterable.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","type CacheEntry<TIterable extends AsyncIterable<unknown>> = {\n abortController: AbortController;\n iterable: Promise<TIterable> | TIterable;\n purgeScheduled: boolean;\n referenceCount: number;\n};\ntype CacheKey = string | symbol;\ntype Config<TInput extends unknown[], TIterable extends AsyncIterable<unknown>> = Readonly<{\n getAbortSignalFromInputArgs: (...args: TInput) => AbortSignal;\n getCacheEntryMissingError: (cacheKey: CacheKey) => Error;\n getCacheKeyFromInputArgs: (...args: TInput) =>\n | CacheKey\n // `undefined` implies 'do not cache'\n | undefined;\n onCacheHit: (iterable: TIterable, ...args: TInput) => Promise<void>;\n onCreateIterable: (abortSignal: AbortSignal, ...args: TInput) => Promise<TIterable>;\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 getCachedAbortableIterableFactory<TInput extends unknown[], TIterable extends AsyncIterable<unknown>>({\n getAbortSignalFromInputArgs,\n getCacheEntryMissingError,\n getCacheKeyFromInputArgs,\n onCacheHit,\n onCreateIterable,\n}: Config<TInput, TIterable>): (...args: TInput) => Promise<TIterable> {\n const cache = new Map<CacheKey, CacheEntry<TIterable>>();\n function getCacheEntryOrThrow(cacheKey: CacheKey) {\n const currentCacheEntry = cache.get(cacheKey);\n if (!currentCacheEntry) {\n throw getCacheEntryMissingError(cacheKey);\n }\n return currentCacheEntry;\n }\n return async (...args: TInput) => {\n const cacheKey = getCacheKeyFromInputArgs(...args);\n const signal = getAbortSignalFromInputArgs(...args);\n if (cacheKey === undefined) {\n return await onCreateIterable(signal, ...args);\n }\n const cleanup = () => {\n cache.delete(cacheKey);\n signal.removeEventListener('abort', handleAbort);\n };\n const handleAbort = () => {\n const cacheEntry = getCacheEntryOrThrow(cacheKey);\n if (cacheEntry.purgeScheduled !== true) {\n cacheEntry.purgeScheduled = true;\n globalThis.queueMicrotask(() => {\n cacheEntry.purgeScheduled = false;\n if (cacheEntry.referenceCount === 0) {\n cacheEntry.abortController.abort();\n cleanup();\n }\n });\n }\n cacheEntry.referenceCount--;\n };\n signal.addEventListener('abort', handleAbort);\n try {\n const cacheEntry = cache.get(cacheKey);\n if (!cacheEntry) {\n const singletonAbortController = new AbortController();\n const newIterablePromise = onCreateIterable(singletonAbortController.signal, ...args);\n const newCacheEntry: CacheEntry<TIterable> = {\n abortController: singletonAbortController,\n iterable: newIterablePromise,\n purgeScheduled: false,\n referenceCount: 1,\n };\n cache.set(cacheKey, newCacheEntry);\n const newIterable = await newIterablePromise;\n registerIterableCleanup(newIterable, cleanup);\n newCacheEntry.iterable = newIterable;\n return newIterable;\n } else {\n cacheEntry.referenceCount++;\n const iterableOrIterablePromise = cacheEntry.iterable;\n const cachedIterable =\n 'then' in iterableOrIterablePromise ? await iterableOrIterablePromise : iterableOrIterablePromise;\n await onCacheHit(cachedIterable, ...args);\n return cachedIterable;\n }\n } catch (e) {\n cleanup();\n throw e;\n }\n };\n}\n","import { IRpcWebSocketTransport } from '@solana/rpc-transport/dist/types/transports/transport-types';\n\nimport { getCachedAbortableIterableFactory } from './cached-abortable-iterable';\n\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 | symbol;\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\nexport function getWebSocketTransportWithConnectionSharding({ getShard, transport }: Config): IRpcWebSocketTransport {\n return getCachedAbortableIterableFactory({\n getAbortSignalFromInputArgs: ({ signal }) => signal,\n getCacheEntryMissingError(shardKey) {\n // TODO: Coded error.\n return new Error(`Found no cache entry for connection with shard key \\`${shardKey?.toString()}\\``);\n },\n getCacheKeyFromInputArgs: ({ payload }) => (getShard ? getShard(payload) : NULL_SHARD_CACHE_KEY),\n onCacheHit: (connection, { payload }) => connection.send_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(payload),\n onCreateIterable: (abortSignal, config) =>\n transport({\n ...config,\n signal: abortSignal,\n }),\n });\n}\n"]}
|