@solana/rpc-transport-http 2.0.0-20241006045741

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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2023 Solana Labs, Inc
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,261 @@
1
+ [![npm][npm-image]][npm-url]
2
+ [![npm-downloads][npm-downloads-image]][npm-url]
3
+ [![semantic-release][semantic-release-image]][semantic-release-url]
4
+ <br />
5
+ [![code-style-prettier][code-style-prettier-image]][code-style-prettier-url]
6
+
7
+ [code-style-prettier-image]: https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square
8
+ [code-style-prettier-url]: https://github.com/prettier/prettier
9
+ [npm-downloads-image]: https://img.shields.io/npm/dm/@solana/rpc-transport-http/rc.svg?style=flat
10
+ [npm-image]: https://img.shields.io/npm/v/@solana/rpc-transport-http/rc.svg?style=flat
11
+ [npm-url]: https://www.npmjs.com/package/@solana/rpc-transport-http/v/rc
12
+ [semantic-release-image]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg
13
+ [semantic-release-url]: https://github.com/semantic-release/semantic-release
14
+
15
+ # @solana/rpc-transport-http
16
+
17
+ This package allows developers to create custom RPC transports. With this library, one can implement highly specialized functionality for leveraging multiple transports, attempting/handling retries, and more.
18
+
19
+ ## Functions
20
+
21
+ ### `createHttpTransport()`
22
+
23
+ Call this to create a function that conforms to the `RpcTransport` interface (see `@solana/rpc-spec`). You can use that function in your programs to make `POST` requests with headers suitable for sending JSON data to a server.
24
+
25
+ ```ts
26
+ import { createHttpTransport } from '@solana/rpc-transport-http';
27
+
28
+ const transport = createHttpTransport({ url: 'https://api.mainnet-beta.solana.com' });
29
+ const response = await transport({
30
+ payload: { id: 1, jsonrpc: '2.0', method: 'getSlot' },
31
+ });
32
+ const data = await response.json();
33
+ ```
34
+
35
+ #### Config
36
+
37
+ ##### `dispatcher_NODE_ONLY`
38
+
39
+ In Node environments you can tune how requests are dispatched to the network. Use this config parameter to install a [`undici.Dispatcher`](https://undici.nodejs.org/#/docs/api/Agent) in your transport.
40
+
41
+ ```ts
42
+ import { createHttpTransport } from '@solana/rpc-transport-http';
43
+ import { Agent, BalancedPool } from 'undici';
44
+
45
+ // Create a dispatcher that, when called with a special URL, creates a round-robin pool of RPCs.
46
+ const dispatcher = new Agent({
47
+ factory(origin, opts) {
48
+ if (origin === 'https://mypool') {
49
+ const upstreams = [
50
+ 'https://api.mainnet-beta.solana.com',
51
+ 'https://mainnet.helius-rpc.com',
52
+ 'https://several-neat-iguana.quiknode.pro',
53
+ ];
54
+ return new BalancedPool(upstreams, {
55
+ ...opts,
56
+ bodyTimeout: 60e3,
57
+ headersTimeout: 5e3,
58
+ keepAliveTimeout: 19e3,
59
+ });
60
+ } else {
61
+ return new Pool(origin, opts);
62
+ }
63
+ },
64
+ });
65
+ const transport = createHttpTransport({
66
+ dispatcher_NODE_ONLY: dispatcher,
67
+ url: 'https://mypool',
68
+ });
69
+ let id = 0;
70
+ const balances = await Promise.allSettled(
71
+ accounts.map(async account => {
72
+ const response = await transport({
73
+ payload: {
74
+ id: ++id,
75
+ jsonrpc: '2.0',
76
+ method: 'getBalance',
77
+ params: [account],
78
+ },
79
+ });
80
+ return await response.json();
81
+ }),
82
+ );
83
+ ```
84
+
85
+ ##### `fromJson`
86
+
87
+ An optional function that takes the response as a JSON string and converts it to a JSON value. The request payload is also provided as a second argument. When not provided, the JSON value will be accessed via the `response.json()` method of the fetch API.
88
+
89
+ ##### `headers`
90
+
91
+ An object of headers to set on the request. Avoid [forbidden headers](https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name). Additionally, the headers `Accept`, `Content-Length`, and `Content-Type` are disallowed.
92
+
93
+ ```ts
94
+ import { createHttpTransport } from '@solana/rpc-transport-http';
95
+
96
+ const transport = createHttpTransport({
97
+ headers: {
98
+ // Authorize with the RPC using a bearer token
99
+ Authorization: `Bearer ${process.env.RPC_AUTH_TOKEN}`,
100
+ },
101
+ url: 'https://several-neat-iguana.quiknode.pro',
102
+ });
103
+ ```
104
+
105
+ ##### `toJson`
106
+
107
+ An optional function that takes the request payload and converts it to a JSON string. When not provided, `JSON.stringify` will be used.
108
+
109
+ ##### `url`
110
+
111
+ A string representing the target endpoint. In Node, it must be an absolute URL using the `http` or `https` protocol.
112
+
113
+ ### `createHttpTransportForSolanaRpc()`
114
+
115
+ Creates an `RpcTransport` that uses JSON HTTP requests — much like the `createHttpTransport` function — except that it also uses custom `toJson` and `fromJson` functions in order to allow `bigint` values to be serialized and deserialized correctly over the wire.
116
+
117
+ Since this is something specific to the Solana RPC API, these custom JSON functions are only triggered when the request is recognized as a Solana RPC request. Normal RPC APIs should aim to wrap their `bigint` values — e.g. `u64` or `i64` — in special value objects that represent the number as a string to avoid numerical values going above `Number.MAX_SAFE_INTEGER`.
118
+
119
+ It has the same configuration options as `createHttpTransport`, but without the `fromJson` and `toJson` options.
120
+
121
+ ## Augmenting Transports
122
+
123
+ Using this core transport, you can implement specialized functionality for leveraging multiple transports, attempting/handling retries, and more.
124
+
125
+ ### Round Robin
126
+
127
+ Here’s an example of how someone might implement a “round robin” approach to distribute requests to multiple transports:
128
+
129
+ ```ts
130
+ import { RpcResponse, RpcTransport } from '@solana/rpc-spec';
131
+ import { createHttpTransport } from '@solana/rpc-transport-http';
132
+
133
+ // Create a transport for each RPC server
134
+ const transports = [
135
+ createHttpTransport({ url: 'https://mainnet-beta.my-server-1.com' }),
136
+ createHttpTransport({ url: 'https://mainnet-beta.my-server-2.com' }),
137
+ createHttpTransport({ url: 'https://mainnet-beta.my-server-3.com' }),
138
+ ];
139
+
140
+ // Create a wrapper transport that distributes requests to them
141
+ let nextTransport = 0;
142
+ async function roundRobinTransport<TResponse>(...args: Parameters<RpcTransport>): Promise<RpcResponse<TResponse>> {
143
+ const transport = transports[nextTransport];
144
+ nextTransport = (nextTransport + 1) % transports.length;
145
+ return await transport(...args);
146
+ }
147
+ ```
148
+
149
+ ### Sharding
150
+
151
+ Another example of a possible customization for a transport is to shard requests deterministically among a set of servers. Here’s an example:
152
+
153
+ Perhaps your application needs to make a large number of requests, or needs to fan request for different methods out to different servers. Here’s an example of an implementation that does the latter:
154
+
155
+ ```ts
156
+ import { RpcResponse, RpcTransport } from '@solana/rpc-spec';
157
+ import { createHttpTransport } from '@solana/rpc-transport-http';
158
+
159
+ // Create multiple transports
160
+ const transportA = createHttpTransport({ url: 'https://mainnet-beta.my-server-1.com' });
161
+ const transportB = createHttpTransport({ url: 'https://mainnet-beta.my-server-2.com' });
162
+ const transportC = createHttpTransport({ url: 'https://mainnet-beta.my-server-3.com' });
163
+ const transportD = createHttpTransport({ url: 'https://mainnet-beta.my-server-4.com' });
164
+
165
+ // Function to determine which shard to use based on the request method
166
+ function selectShard(method: string): RpcTransport {
167
+ switch (method) {
168
+ case 'getAccountInfo':
169
+ case 'getBalance':
170
+ return transportA;
171
+ case 'getTransaction':
172
+ case 'getRecentBlockhash':
173
+ return transportB;
174
+ case 'sendTransaction':
175
+ return transportC;
176
+ default:
177
+ return transportD;
178
+ }
179
+ }
180
+
181
+ async function shardingTransport<TResponse>(...args: Parameters<RpcTransport>): Promise<RpcResponse<TResponse>> {
182
+ const payload = args[0].payload as { method: string };
183
+ const selectedTransport = selectShard(payload.method);
184
+ return await selectedTransport(...args);
185
+ }
186
+ ```
187
+
188
+ ### Retry Logic
189
+
190
+ The transport library can also be used to implement custom retry logic on any request:
191
+
192
+ ```ts
193
+ import { RpcResponse, RpcTransport } from '@solana/rpc-spec';
194
+ import { createHttpTransport } from '@solana/rpc-transport-http';
195
+
196
+ // Set the maximum number of attempts to retry a request
197
+ const MAX_ATTEMPTS = 4;
198
+
199
+ // Create the default transport
200
+ const defaultTransport = createHttpTransport({ url: 'https://mainnet-beta.my-server-1.com' });
201
+
202
+ // Sleep function to wait for a given number of milliseconds
203
+ function sleep(ms: number): Promise<void> {
204
+ return new Promise(resolve => setTimeout(resolve, ms));
205
+ }
206
+
207
+ // Calculate the delay for a given attempt
208
+ function calculateRetryDelay(attempt: number): number {
209
+ // Exponential backoff with a maximum of 1.5 seconds
210
+ return Math.min(100 * Math.pow(2, attempt), 1500);
211
+ }
212
+
213
+ // A retrying transport that will retry up to `MAX_ATTEMPTS` times before failing
214
+ async function retryingTransport<TResponse>(...args: Parameters<RpcTransport>): Promise<RpcResponse<TResponse>> {
215
+ let requestError;
216
+ for (let attempts = 0; attempts < MAX_ATTEMPTS; attempts++) {
217
+ try {
218
+ return await defaultTransport(...args);
219
+ } catch (err) {
220
+ requestError = err;
221
+ // Only sleep if we have more attempts remaining
222
+ if (attempts < MAX_ATTEMPTS - 1) {
223
+ const retryDelay = calculateRetryDelay(attempts);
224
+ await sleep(retryDelay);
225
+ }
226
+ }
227
+ }
228
+ throw requestError;
229
+ }
230
+ ```
231
+
232
+ ### Failover
233
+
234
+ Here’s an example of some failover logic integrated into a transport:
235
+
236
+ ```ts
237
+ import { RpcResponse, RpcTransport } from '@solana/rpc-spec';
238
+ import { createHttpTransport } from '@solana/rpc-transport-http';
239
+
240
+ // Create a transport for each RPC server
241
+ const transports = [
242
+ createHttpTransport({ url: 'https://mainnet-beta.my-server-1.com' }),
243
+ createHttpTransport({ url: 'https://mainnet-beta.my-server-2.com' }),
244
+ createHttpTransport({ url: 'https://mainnet-beta.my-server-2.com' }),
245
+ ];
246
+
247
+ // A failover transport that will try each transport in order until one succeeds before failing
248
+ async function failoverTransport<TResponse>(...args: Parameters<RpcTransport>): Promise<RpcResponse<TResponse>> {
249
+ let requestError;
250
+
251
+ for (const transport of transports) {
252
+ try {
253
+ return await transport(...args);
254
+ } catch (err) {
255
+ requestError = err;
256
+ console.error(err);
257
+ }
258
+ }
259
+ throw requestError;
260
+ }
261
+ ```
@@ -0,0 +1,265 @@
1
+ 'use strict';
2
+
3
+ var errors = require('@solana/errors');
4
+ var rpcSpec = require('@solana/rpc-spec');
5
+
6
+ // src/http-transport.ts
7
+ var DISALLOWED_HEADERS = {
8
+ accept: true,
9
+ "content-length": true,
10
+ "content-type": true
11
+ };
12
+ var FORBIDDEN_HEADERS = /* @__PURE__ */ Object.assign(
13
+ {
14
+ "accept-charset": true,
15
+ "access-control-request-headers": true,
16
+ "access-control-request-method": true,
17
+ connection: true,
18
+ "content-length": true,
19
+ cookie: true,
20
+ date: true,
21
+ dnt: true,
22
+ expect: true,
23
+ host: true,
24
+ "keep-alive": true,
25
+ origin: true,
26
+ "permissions-policy": true,
27
+ // Prefix matching is implemented in code, below.
28
+ // 'proxy-': true,
29
+ // 'sec-': true,
30
+ referer: true,
31
+ te: true,
32
+ trailer: true,
33
+ "transfer-encoding": true,
34
+ upgrade: true,
35
+ via: true
36
+ },
37
+ { "accept-encoding": true }
38
+ );
39
+ function assertIsAllowedHttpRequestHeaders(headers) {
40
+ const badHeaders = Object.keys(headers).filter((headerName) => {
41
+ const lowercaseHeaderName = headerName.toLowerCase();
42
+ return DISALLOWED_HEADERS[headerName.toLowerCase()] === true || FORBIDDEN_HEADERS[headerName.toLowerCase()] === true || lowercaseHeaderName.startsWith("proxy-") || lowercaseHeaderName.startsWith("sec-");
43
+ });
44
+ if (badHeaders.length > 0) {
45
+ throw new errors.SolanaError(errors.SOLANA_ERROR__RPC__TRANSPORT_HTTP_HEADER_FORBIDDEN, {
46
+ headers: badHeaders
47
+ });
48
+ }
49
+ }
50
+ function normalizeHeaders(headers) {
51
+ const out = {};
52
+ for (const headerName in headers) {
53
+ out[headerName.toLowerCase()] = headers[headerName];
54
+ }
55
+ return out;
56
+ }
57
+
58
+ // src/http-transport.ts
59
+ var didWarnDispatcherWasSuppliedInNonNodeEnvironment = false;
60
+ function warnDispatcherWasSuppliedInNonNodeEnvironment() {
61
+ if (didWarnDispatcherWasSuppliedInNonNodeEnvironment) {
62
+ return;
63
+ }
64
+ didWarnDispatcherWasSuppliedInNonNodeEnvironment = true;
65
+ console.warn(
66
+ "You have supplied a `Dispatcher` to `createHttpTransport()`. It has been ignored because Undici dispatchers only work in Node environments. To eliminate this warning, omit the `dispatcher_NODE_ONLY` property from your config when running in a non-Node environment."
67
+ );
68
+ }
69
+ function createHttpTransport(config) {
70
+ if (process.env.NODE_ENV !== "production" && true && "dispatcher_NODE_ONLY" in config) {
71
+ warnDispatcherWasSuppliedInNonNodeEnvironment();
72
+ }
73
+ const { fromJson, headers, toJson, url } = config;
74
+ if (process.env.NODE_ENV !== "production" && headers) {
75
+ assertIsAllowedHttpRequestHeaders(headers);
76
+ }
77
+ let dispatcherConfig;
78
+ const customHeaders = headers && normalizeHeaders(headers);
79
+ return async function makeHttpRequest({
80
+ payload,
81
+ signal
82
+ }) {
83
+ const body = toJson ? toJson(payload) : JSON.stringify(payload);
84
+ const requestInfo = {
85
+ ...dispatcherConfig,
86
+ body,
87
+ headers: {
88
+ ...customHeaders,
89
+ // Keep these headers lowercase so they will override any user-supplied headers above.
90
+ accept: "application/json",
91
+ "content-length": body.length.toString(),
92
+ "content-type": "application/json; charset=utf-8"
93
+ },
94
+ method: "POST",
95
+ signal
96
+ };
97
+ const response = await fetch(url, requestInfo);
98
+ if (!response.ok) {
99
+ throw new errors.SolanaError(errors.SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR, {
100
+ message: response.statusText,
101
+ statusCode: response.status
102
+ });
103
+ }
104
+ if (fromJson) {
105
+ return fromJson(await response.text(), payload);
106
+ }
107
+ return await response.json();
108
+ };
109
+ }
110
+ var SOLANA_RPC_METHODS = [
111
+ "getAccountInfo",
112
+ "getBalance",
113
+ "getBlock",
114
+ "getBlockCommitment",
115
+ "getBlockHeight",
116
+ "getBlockProduction",
117
+ "getBlocks",
118
+ "getBlocksWithLimit",
119
+ "getBlockTime",
120
+ "getClusterNodes",
121
+ "getEpochInfo",
122
+ "getEpochSchedule",
123
+ "getFeeForMessage",
124
+ "getFirstAvailableBlock",
125
+ "getGenesisHash",
126
+ "getHealth",
127
+ "getHighestSnapshotSlot",
128
+ "getIdentity",
129
+ "getInflationGovernor",
130
+ "getInflationRate",
131
+ "getInflationReward",
132
+ "getLargestAccounts",
133
+ "getLatestBlockhash",
134
+ "getLeaderSchedule",
135
+ "getMaxRetransmitSlot",
136
+ "getMaxShredInsertSlot",
137
+ "getMinimumBalanceForRentExemption",
138
+ "getMultipleAccounts",
139
+ "getProgramAccounts",
140
+ "getRecentPerformanceSamples",
141
+ "getRecentPrioritizationFees",
142
+ "getSignaturesForAddress",
143
+ "getSignatureStatuses",
144
+ "getSlot",
145
+ "getSlotLeader",
146
+ "getSlotLeaders",
147
+ "getStakeActivation",
148
+ "getStakeMinimumDelegation",
149
+ "getSupply",
150
+ "getTokenAccountBalance",
151
+ "getTokenAccountsByDelegate",
152
+ "getTokenAccountsByOwner",
153
+ "getTokenLargestAccounts",
154
+ "getTokenSupply",
155
+ "getTransaction",
156
+ "getTransactionCount",
157
+ "getVersion",
158
+ "getVoteAccounts",
159
+ "index",
160
+ "isBlockhashValid",
161
+ "minimumLedgerSlot",
162
+ "requestAirdrop",
163
+ "sendTransaction",
164
+ "simulateTransaction"
165
+ ];
166
+ function isSolanaRequest(payload) {
167
+ return rpcSpec.isJsonRpcPayload(payload) && SOLANA_RPC_METHODS.includes(payload.method);
168
+ }
169
+
170
+ // src/parse-json-with-bigints.ts
171
+ function parseJsonWithBigInts(json) {
172
+ return JSON.parse(wrapIntegersInBigIntValueObject(json), (_, value) => {
173
+ return isBigIntValueObject(value) ? unwrapBigIntValueObject(value) : value;
174
+ });
175
+ }
176
+ function wrapIntegersInBigIntValueObject(json) {
177
+ const out = [];
178
+ let inQuote = false;
179
+ for (let ii = 0; ii < json.length; ii++) {
180
+ let isEscaped = false;
181
+ if (json[ii] === "\\") {
182
+ out.push(json[ii++]);
183
+ isEscaped = !isEscaped;
184
+ }
185
+ if (json[ii] === '"') {
186
+ out.push(json[ii]);
187
+ if (!isEscaped) {
188
+ inQuote = !inQuote;
189
+ }
190
+ continue;
191
+ }
192
+ if (!inQuote) {
193
+ const consumedNumber = consumeNumber(json, ii);
194
+ if (consumedNumber?.length) {
195
+ ii += consumedNumber.length - 1;
196
+ if (consumedNumber.match(/\.|[eE]-/)) {
197
+ out.push(consumedNumber);
198
+ } else {
199
+ out.push(wrapBigIntValueObject(consumedNumber));
200
+ }
201
+ continue;
202
+ }
203
+ }
204
+ out.push(json[ii]);
205
+ }
206
+ return out.join("");
207
+ }
208
+ function consumeNumber(json, ii) {
209
+ const JSON_NUMBER_REGEX = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/;
210
+ if (!json[ii]?.match(/[-\d]/)) {
211
+ return null;
212
+ }
213
+ const numberMatch = json.slice(ii).match(JSON_NUMBER_REGEX);
214
+ return numberMatch ? numberMatch[0] : null;
215
+ }
216
+ function wrapBigIntValueObject(value) {
217
+ return `{"$n":"${value}"}`;
218
+ }
219
+ function unwrapBigIntValueObject({ $n }) {
220
+ if ($n.match(/[eE]/)) {
221
+ const [units, exponent] = $n.split(/[eE]/);
222
+ return BigInt(units) * BigInt(10) ** BigInt(exponent);
223
+ }
224
+ return BigInt($n);
225
+ }
226
+ function isBigIntValueObject(value) {
227
+ return !!value && typeof value === "object" && "$n" in value && typeof value.$n === "string";
228
+ }
229
+
230
+ // src/stringify-json-with-bigints.ts
231
+ function stringifyJsonWithBigints(value, space) {
232
+ return unwrapBigIntValueObject2(
233
+ JSON.stringify(value, (_, v) => typeof v === "bigint" ? wrapBigIntValueObject2(v) : v, space)
234
+ );
235
+ }
236
+ function wrapBigIntValueObject2(value) {
237
+ return { $n: `${value}` };
238
+ }
239
+ function unwrapBigIntValueObject2(value) {
240
+ return value.replace(/\{\s*"\$n"\s*:\s*"(-?\d+)"\s*\}/g, "$1");
241
+ }
242
+
243
+ // src/http-transport-for-solana-rpc.ts
244
+ function createHttpTransportForSolanaRpc(config) {
245
+ return createHttpTransport({
246
+ ...config,
247
+ fromJson: (rawResponse, payload) => {
248
+ if (!isSolanaRequest(payload)) return JSON.parse(rawResponse);
249
+ const response = parseJsonWithBigInts(rawResponse);
250
+ if (isErrorResponse(response)) {
251
+ return { ...response, error: { ...response.error, code: Number(response.error.code) } };
252
+ }
253
+ return response;
254
+ },
255
+ toJson: (payload) => isSolanaRequest(payload) ? stringifyJsonWithBigints(payload) : JSON.stringify(payload)
256
+ });
257
+ }
258
+ function isErrorResponse(value) {
259
+ return !!value && typeof value === "object" && "error" in value && !!value.error && typeof value.error === "object" && "code" in value.error;
260
+ }
261
+
262
+ exports.createHttpTransport = createHttpTransport;
263
+ exports.createHttpTransportForSolanaRpc = createHttpTransportForSolanaRpc;
264
+ //# sourceMappingURL=index.browser.cjs.map
265
+ //# sourceMappingURL=index.browser.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/http-transport-headers.ts","../src/http-transport.ts","../src/is-solana-request.ts","../src/parse-json-with-bigints.ts","../src/stringify-json-with-bigints.ts","../src/http-transport-for-solana-rpc.ts"],"names":["SolanaError","SOLANA_ERROR__RPC__TRANSPORT_HTTP_HEADER_FORBIDDEN","SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR","isJsonRpcPayload","unwrapBigIntValueObject","wrapBigIntValueObject"],"mappings":"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","file":"index.browser.cjs","sourcesContent":["import { SOLANA_ERROR__RPC__TRANSPORT_HTTP_HEADER_FORBIDDEN, SolanaError } from '@solana/errors';\n\nexport type AllowedHttpRequestHeaders = Readonly<\n {\n // Someone can still sneak a forbidden header past Typescript if they do something like\n // fOo-BaR, but at that point they deserve the runtime failure.\n [K in DisallowedHeaders | ForbiddenHeaders as\n | Capitalize<Lowercase<K>> // `Foo-bar`\n | K // `Foo-Bar`\n | Lowercase<K> // `foo-bar`\n | Uncapitalize<K> // `foo-Bar`\n // `FOO-BAR`\n | Uppercase<K>]?: never;\n } & { [headerName: string]: string }\n>;\n// These are headers that we simply don't allow the developer to override because they're\n// fundamental to the operation of the JSON-RPC transport.\ntype DisallowedHeaders = 'Accept' | 'Content-Length' | 'Content-Type' | 'Solana-Client';\ntype ForbiddenHeaders =\n | 'Accept-Charset'\n /**\n * Though technically forbidden in non-Node environments, we don't have a way to target\n * TypeScript types depending on which platform you are authoring for. `Accept-Encoding` is\n * therefore omitted from the forbidden headers type, but is still a runtime error in dev mode\n * when supplied in a non-Node context.\n */\n // | 'Accept-Encoding'\n | 'Access-Control-Request-Headers'\n | 'Access-Control-Request-Method'\n | 'Connection'\n | 'Content-Length'\n | 'Cookie'\n | 'Date'\n | 'DNT'\n | 'Expect'\n | 'Host'\n | 'Keep-Alive'\n | 'Origin'\n | 'Permissions-Policy'\n | 'Referer'\n | 'TE'\n | 'Trailer'\n | 'Transfer-Encoding'\n | 'Upgrade'\n | 'Via'\n | `Proxy-${string}`\n | `Sec-${string}`;\n\n// These are headers which are fundamental to the JSON-RPC transport, and must not be modified.\nconst DISALLOWED_HEADERS: Record<string, boolean> = {\n accept: true,\n 'content-length': true,\n 'content-type': true,\n};\n// https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name\nconst FORBIDDEN_HEADERS: Record<string, boolean> = /* @__PURE__ */ Object.assign(\n {\n 'accept-charset': true,\n 'access-control-request-headers': true,\n 'access-control-request-method': true,\n connection: true,\n 'content-length': true,\n cookie: true,\n date: true,\n dnt: true,\n expect: true,\n host: true,\n 'keep-alive': true,\n origin: true,\n 'permissions-policy': true,\n // Prefix matching is implemented in code, below.\n // 'proxy-': true,\n // 'sec-': true,\n referer: true,\n te: true,\n trailer: true,\n 'transfer-encoding': true,\n upgrade: true,\n via: true,\n },\n __NODEJS__ ? undefined : { 'accept-encoding': true },\n);\n\nexport function assertIsAllowedHttpRequestHeaders(\n headers: Record<string, string>,\n): asserts headers is AllowedHttpRequestHeaders {\n const badHeaders = Object.keys(headers).filter(headerName => {\n const lowercaseHeaderName = headerName.toLowerCase();\n return (\n DISALLOWED_HEADERS[headerName.toLowerCase()] === true ||\n FORBIDDEN_HEADERS[headerName.toLowerCase()] === true ||\n lowercaseHeaderName.startsWith('proxy-') ||\n lowercaseHeaderName.startsWith('sec-')\n );\n });\n if (badHeaders.length > 0) {\n throw new SolanaError(SOLANA_ERROR__RPC__TRANSPORT_HTTP_HEADER_FORBIDDEN, {\n headers: badHeaders,\n });\n }\n}\n\n/**\n * Lowercasing header names makes it easier to override user-supplied headers, such as those defined\n * in the `DisallowedHeaders` type.\n */\nexport function normalizeHeaders<T extends Record<string, string>>(\n headers: T,\n): { [K in string & keyof T 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 string & keyof T as Lowercase<K>]: T[K] };\n}\n","import { SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR, SolanaError } from '@solana/errors';\nimport { RpcResponse, RpcTransport } from '@solana/rpc-spec';\nimport type Dispatcher from 'undici-types/dispatcher';\n\nimport {\n AllowedHttpRequestHeaders,\n assertIsAllowedHttpRequestHeaders,\n normalizeHeaders,\n} from './http-transport-headers';\n\ntype Config = Readonly<{\n dispatcher_NODE_ONLY?: Dispatcher;\n fromJson?: (rawResponse: string, payload: unknown) => RpcResponse;\n headers?: AllowedHttpRequestHeaders;\n toJson?: (payload: unknown) => string;\n url: string;\n}>;\n\nlet didWarnDispatcherWasSuppliedInNonNodeEnvironment = false;\nfunction warnDispatcherWasSuppliedInNonNodeEnvironment() {\n if (didWarnDispatcherWasSuppliedInNonNodeEnvironment) {\n return;\n }\n didWarnDispatcherWasSuppliedInNonNodeEnvironment = true;\n console.warn(\n 'You have supplied a `Dispatcher` to `createHttpTransport()`. It has been ignored ' +\n 'because Undici dispatchers only work in Node environments. To eliminate this ' +\n 'warning, omit the `dispatcher_NODE_ONLY` property from your config when running in ' +\n 'a non-Node environment.',\n );\n}\n\nexport function createHttpTransport(config: Config): RpcTransport {\n if (process.env.NODE_ENV !== \"production\" && !__NODEJS__ && 'dispatcher_NODE_ONLY' in config) {\n warnDispatcherWasSuppliedInNonNodeEnvironment();\n }\n const { fromJson, headers, toJson, url } = config;\n if (process.env.NODE_ENV !== \"production\" && headers) {\n assertIsAllowedHttpRequestHeaders(headers);\n }\n let dispatcherConfig: { dispatcher: Dispatcher | undefined } | undefined;\n if (__NODEJS__ && 'dispatcher_NODE_ONLY' in config) {\n dispatcherConfig = { dispatcher: config.dispatcher_NODE_ONLY };\n }\n const customHeaders = headers && normalizeHeaders(headers);\n return async function makeHttpRequest<TResponse>({\n payload,\n signal,\n }: Parameters<RpcTransport>[0]): Promise<RpcResponse<TResponse>> {\n const body = toJson ? toJson(payload) : JSON.stringify(payload);\n const requestInfo = {\n ...dispatcherConfig,\n body,\n headers: {\n ...customHeaders,\n // Keep these headers lowercase so they will override any user-supplied headers above.\n accept: 'application/json',\n 'content-length': body.length.toString(),\n 'content-type': 'application/json; charset=utf-8',\n },\n method: 'POST',\n signal,\n };\n const response = await fetch(url, requestInfo);\n if (!response.ok) {\n throw new SolanaError(SOLANA_ERROR__RPC__TRANSPORT_HTTP_ERROR, {\n message: response.statusText,\n statusCode: response.status,\n });\n }\n if (fromJson) {\n return fromJson(await response.text(), payload) as TResponse;\n }\n return await response.json();\n };\n}\n","import { isJsonRpcPayload } from '@solana/rpc-spec';\n\nconst SOLANA_RPC_METHODS = [\n 'getAccountInfo',\n 'getBalance',\n 'getBlock',\n 'getBlockCommitment',\n 'getBlockHeight',\n 'getBlockProduction',\n 'getBlocks',\n 'getBlocksWithLimit',\n 'getBlockTime',\n 'getClusterNodes',\n 'getEpochInfo',\n 'getEpochSchedule',\n 'getFeeForMessage',\n 'getFirstAvailableBlock',\n 'getGenesisHash',\n 'getHealth',\n 'getHighestSnapshotSlot',\n 'getIdentity',\n 'getInflationGovernor',\n 'getInflationRate',\n 'getInflationReward',\n 'getLargestAccounts',\n 'getLatestBlockhash',\n 'getLeaderSchedule',\n 'getMaxRetransmitSlot',\n 'getMaxShredInsertSlot',\n 'getMinimumBalanceForRentExemption',\n 'getMultipleAccounts',\n 'getProgramAccounts',\n 'getRecentPerformanceSamples',\n 'getRecentPrioritizationFees',\n 'getSignaturesForAddress',\n 'getSignatureStatuses',\n 'getSlot',\n 'getSlotLeader',\n 'getSlotLeaders',\n 'getStakeActivation',\n 'getStakeMinimumDelegation',\n 'getSupply',\n 'getTokenAccountBalance',\n 'getTokenAccountsByDelegate',\n 'getTokenAccountsByOwner',\n 'getTokenLargestAccounts',\n 'getTokenSupply',\n 'getTransaction',\n 'getTransactionCount',\n 'getVersion',\n 'getVoteAccounts',\n 'index',\n 'isBlockhashValid',\n 'minimumLedgerSlot',\n 'requestAirdrop',\n 'sendTransaction',\n 'simulateTransaction',\n] as const;\n\n/**\n * Helper function that checks if a given `RpcRequest` comes from the Solana RPC API.\n */\nexport function isSolanaRequest(payload: unknown): payload is Readonly<{\n jsonrpc: '2.0';\n method: (typeof SOLANA_RPC_METHODS)[number];\n params: unknown;\n}> {\n return isJsonRpcPayload(payload) && (SOLANA_RPC_METHODS as readonly string[]).includes(payload.method);\n}\n","/**\n * This function is a replacement for `JSON.parse` that can handle large\n * unsafe integers by parsing them as BigInts. It transforms every\n * numerical value into a BigInt without loss of precision.\n */\nexport function parseJsonWithBigInts(json: string): unknown {\n return JSON.parse(wrapIntegersInBigIntValueObject(json), (_, value) => {\n return isBigIntValueObject(value) ? unwrapBigIntValueObject(value) : value;\n });\n}\n\nfunction wrapIntegersInBigIntValueObject(json: string): string {\n const out = [];\n let inQuote = false;\n for (let ii = 0; ii < json.length; ii++) {\n let isEscaped = false;\n if (json[ii] === '\\\\') {\n out.push(json[ii++]);\n isEscaped = !isEscaped;\n }\n if (json[ii] === '\"') {\n out.push(json[ii]);\n if (!isEscaped) {\n inQuote = !inQuote;\n }\n continue;\n }\n if (!inQuote) {\n const consumedNumber = consumeNumber(json, ii);\n if (consumedNumber?.length) {\n ii += consumedNumber.length - 1;\n // Don't wrap numbers that contain a decimal point or a negative exponent.\n if (consumedNumber.match(/\\.|[eE]-/)) {\n out.push(consumedNumber);\n } else {\n out.push(wrapBigIntValueObject(consumedNumber));\n }\n continue;\n }\n }\n out.push(json[ii]);\n }\n\n return out.join('');\n}\n\nfunction consumeNumber(json: string, ii: number): string | null {\n /** @see https://stackoverflow.com/a/13340826/11440277 */\n const JSON_NUMBER_REGEX = /^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?/;\n\n // Stop early if the first character isn't a digit or a minus sign.\n if (!json[ii]?.match(/[-\\d]/)) {\n return null;\n }\n\n // Otherwise, check if the next characters form a valid JSON number.\n const numberMatch = json.slice(ii).match(JSON_NUMBER_REGEX);\n return numberMatch ? numberMatch[0] : null;\n}\n\ntype BigIntValueObject = {\n // `$` implies 'this is a value object'.\n // `n` implies 'interpret the value as a bigint'.\n $n: string;\n};\n\nfunction wrapBigIntValueObject(value: string): string {\n return `{\"$n\":\"${value}\"}`;\n}\n\nfunction unwrapBigIntValueObject({ $n }: BigIntValueObject): bigint {\n if ($n.match(/[eE]/)) {\n const [units, exponent] = $n.split(/[eE]/);\n return BigInt(units) * BigInt(10) ** BigInt(exponent);\n }\n return BigInt($n);\n}\n\nfunction isBigIntValueObject(value: unknown): value is BigIntValueObject {\n return !!value && typeof value === 'object' && '$n' in value && typeof value.$n === 'string';\n}\n","/**\n * Transforms a value into a JSON string, whilst rendering bigints as large unsafe integers.\n */\nexport function stringifyJsonWithBigints(value: unknown, space?: number | string): string {\n return unwrapBigIntValueObject(\n JSON.stringify(value, (_, v) => (typeof v === 'bigint' ? wrapBigIntValueObject(v) : v), space),\n );\n}\n\ntype BigIntValueObject = {\n // `$` implies 'this is a value object'.\n // `n` implies 'interpret the value as a bigint'.\n $n: string;\n};\n\nfunction wrapBigIntValueObject(value: bigint): BigIntValueObject {\n return { $n: `${value}` };\n}\n\nfunction unwrapBigIntValueObject(value: string): string {\n return value.replace(/\\{\\s*\"\\$n\"\\s*:\\s*\"(-?\\d+)\"\\s*\\}/g, '$1');\n}\n","import { RpcTransport } from '@solana/rpc-spec';\nimport type Dispatcher from 'undici-types/dispatcher';\n\nimport { createHttpTransport } from './http-transport';\nimport { AllowedHttpRequestHeaders } from './http-transport-headers';\nimport { isSolanaRequest } from './is-solana-request';\nimport { parseJsonWithBigInts } from './parse-json-with-bigints';\nimport { stringifyJsonWithBigints } from './stringify-json-with-bigints';\n\ntype Config = Readonly<{\n dispatcher_NODE_ONLY?: Dispatcher;\n headers?: AllowedHttpRequestHeaders;\n url: string;\n}>;\n\nexport function createHttpTransportForSolanaRpc(config: Config): RpcTransport {\n return createHttpTransport({\n ...config,\n fromJson: (rawResponse: string, payload: unknown) => {\n if (!isSolanaRequest(payload)) return JSON.parse(rawResponse);\n const response = parseJsonWithBigInts(rawResponse);\n // Error codes are always numbers.\n if (isErrorResponse(response)) {\n return { ...response, error: { ...response.error, code: Number(response.error.code) } };\n }\n return response;\n },\n toJson: (payload: unknown) =>\n isSolanaRequest(payload) ? stringifyJsonWithBigints(payload) : JSON.stringify(payload),\n });\n}\n\nfunction isErrorResponse(value: unknown): value is { error: { code: bigint } } {\n return (\n !!value &&\n typeof value === 'object' &&\n 'error' in value &&\n !!value.error &&\n typeof value.error === 'object' &&\n 'code' in value.error\n );\n}\n"]}