@psalomo/jsonrpc-client 0.5.0 → 1.0.1

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/dist/index.js CHANGED
@@ -27,27 +27,44 @@ __export(index_exports, {
27
27
  NearRpcClient: () => NearRpcClient,
28
28
  NearRpcError: () => NearRpcError,
29
29
  RPC_METHODS: () => import_jsonrpc_types3.RPC_METHODS,
30
- default: () => NearRpcClient
30
+ block: () => block,
31
+ broadcastTxAsync: () => broadcastTxAsync,
32
+ broadcastTxCommit: () => broadcastTxCommit,
33
+ changes: () => changes,
34
+ chunk: () => chunk,
35
+ clientConfig: () => clientConfig,
36
+ default: () => NearRpcClient,
37
+ defaultClient: () => defaultClient,
38
+ enableValidation: () => enableValidation,
39
+ experimentalChanges: () => experimentalChanges,
40
+ experimentalChangesInBlock: () => experimentalChangesInBlock,
41
+ experimentalCongestionLevel: () => experimentalCongestionLevel,
42
+ experimentalGenesisConfig: () => experimentalGenesisConfig,
43
+ experimentalLightClientBlockProof: () => experimentalLightClientBlockProof,
44
+ experimentalLightClientProof: () => experimentalLightClientProof,
45
+ experimentalMaintenanceWindows: () => experimentalMaintenanceWindows,
46
+ experimentalProtocolConfig: () => experimentalProtocolConfig,
47
+ experimentalReceipt: () => experimentalReceipt,
48
+ experimentalSplitStorageInfo: () => experimentalSplitStorageInfo,
49
+ experimentalTxStatus: () => experimentalTxStatus,
50
+ experimentalValidatorsOrdered: () => experimentalValidatorsOrdered,
51
+ gasPrice: () => gasPrice,
52
+ health: () => health,
53
+ lightClientProof: () => lightClientProof,
54
+ networkInfo: () => networkInfo,
55
+ nextLightClientBlock: () => nextLightClientBlock,
56
+ query: () => query,
57
+ sendTx: () => sendTx,
58
+ status: () => status,
59
+ tx: () => tx,
60
+ validators: () => validators,
61
+ viewAccessKey: () => viewAccessKey,
62
+ viewAccount: () => viewAccount,
63
+ viewFunction: () => viewFunction
31
64
  });
32
65
  module.exports = __toCommonJS(index_exports);
33
66
 
34
67
  // src/client.ts
35
- var import_jsonrpc_types = require("@psalomo/jsonrpc-types");
36
- var JsonRpcClientError = class extends Error {
37
- constructor(message, code, data) {
38
- super(message);
39
- this.code = code;
40
- this.data = data;
41
- this.name = "JsonRpcClientError";
42
- }
43
- };
44
- var JsonRpcNetworkError = class extends Error {
45
- constructor(message, originalError) {
46
- super(message);
47
- this.originalError = originalError;
48
- this.name = "JsonRpcNetworkError";
49
- }
50
- };
51
68
  function camelToSnake(str) {
52
69
  return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
53
70
  }
@@ -82,59 +99,61 @@ function convertKeysToCamelCase(obj) {
82
99
  }
83
100
  return converted;
84
101
  }
85
- var NearRpcClient = class {
102
+ var REQUEST_ID = "dontcare";
103
+ var JsonRpcClientError = class extends Error {
104
+ constructor(message, code, data) {
105
+ super(message);
106
+ this.code = code;
107
+ this.data = data;
108
+ this.name = "JsonRpcClientError";
109
+ }
110
+ };
111
+ var JsonRpcNetworkError = class extends Error {
112
+ constructor(message, originalError) {
113
+ super(message);
114
+ this.originalError = originalError;
115
+ this.name = "JsonRpcNetworkError";
116
+ }
117
+ };
118
+ var NearRpcClient = class _NearRpcClient {
86
119
  endpoint;
87
120
  headers;
88
121
  timeout;
89
122
  retries;
90
- validateResponses;
123
+ validation;
91
124
  constructor(config) {
92
125
  if (typeof config === "string") {
93
126
  this.endpoint = config;
94
- this.headers = {
95
- "Content-Type": "application/json"
96
- };
127
+ this.headers = {};
97
128
  this.timeout = 3e4;
98
129
  this.retries = 3;
99
- this.validateResponses = true;
100
130
  } else {
101
131
  this.endpoint = config.endpoint;
102
- this.headers = {
103
- "Content-Type": "application/json",
104
- ...config.headers
105
- };
132
+ this.headers = config.headers || {};
106
133
  this.timeout = config.timeout || 3e4;
107
134
  this.retries = config.retries || 3;
108
- this.validateResponses = config.validateResponses ?? true;
135
+ if (config.validation) {
136
+ this.validation = config.validation;
137
+ }
109
138
  }
110
139
  }
111
140
  /**
112
- * Get request ID matching NEAR RPC documentation examples
141
+ * Make a raw JSON-RPC request
142
+ * This is used internally by the standalone RPC functions
113
143
  */
114
- getRequestId() {
115
- return "dontcare";
116
- }
117
- /**
118
- * Make a raw JSON-RPC call
119
- * This method is public to allow dynamic calls to any RPC method
120
- */
121
- async call(method, params) {
122
- const requestId = this.getRequestId();
123
- const snakeCaseParams = params ? convertKeysToSnakeCase(params) : void 0;
144
+ async makeRequest(method, params) {
145
+ const snakeCaseParams = params ? convertKeysToSnakeCase(params) : params;
124
146
  const request = {
125
147
  jsonrpc: "2.0",
126
- id: requestId,
148
+ id: REQUEST_ID,
127
149
  method,
128
150
  params: snakeCaseParams
129
151
  };
130
- if (this.validateResponses) {
131
- try {
132
- import_jsonrpc_types.JsonRpcRequestSchema.parse(request);
133
- } catch (error) {
134
- throw new JsonRpcNetworkError(
135
- `Invalid request format: ${error instanceof Error ? error.message : "Unknown error"}`,
136
- error
137
- );
152
+ if (this.validation) {
153
+ if ("validateMethodRequest" in this.validation) {
154
+ this.validation.validateMethodRequest(method, request);
155
+ } else {
156
+ this.validation.validateRequest(request);
138
157
  }
139
158
  }
140
159
  let lastError = null;
@@ -144,84 +163,81 @@ var NearRpcClient = class {
144
163
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
145
164
  const response = await fetch(this.endpoint, {
146
165
  method: "POST",
147
- headers: this.headers,
166
+ headers: {
167
+ "Content-Type": "application/json",
168
+ ...this.headers
169
+ },
148
170
  body: JSON.stringify(request),
149
171
  signal: controller.signal
150
172
  });
151
173
  clearTimeout(timeoutId);
152
- const jsonResponse = await response.json();
153
- if (this.validateResponses) {
154
- try {
155
- import_jsonrpc_types.JsonRpcResponseSchema.parse(jsonResponse);
156
- } catch (error) {
157
- throw new JsonRpcClientError(
158
- `Invalid response format: ${error instanceof Error ? error.message : "Unknown error"}`
159
- );
160
- }
174
+ if (!response.ok) {
175
+ throw new JsonRpcNetworkError(
176
+ `HTTP error! status: ${response.status}`
177
+ );
178
+ }
179
+ let jsonResponse;
180
+ try {
181
+ jsonResponse = await response.json();
182
+ } catch (parseError) {
183
+ throw new JsonRpcNetworkError(
184
+ "Failed to parse JSON response",
185
+ parseError
186
+ );
161
187
  }
162
- const rpcResponse = jsonResponse;
163
- if (rpcResponse.error) {
188
+ if (this.validation) {
189
+ this.validation.validateResponse(jsonResponse);
190
+ }
191
+ if (jsonResponse.error) {
164
192
  throw new JsonRpcClientError(
165
- rpcResponse.error.message,
166
- rpcResponse.error.code,
167
- rpcResponse.error.data
193
+ jsonResponse.error.message,
194
+ jsonResponse.error.code,
195
+ jsonResponse.error.data
168
196
  );
169
197
  }
170
- if (!response.ok) {
171
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
198
+ const camelCaseResult = jsonResponse.result ? convertKeysToCamelCase(jsonResponse.result) : jsonResponse.result;
199
+ if (this.validation && "validateMethodResponse" in this.validation) {
200
+ const camelCaseResponse = {
201
+ ...jsonResponse,
202
+ result: camelCaseResult
203
+ };
204
+ this.validation.validateMethodResponse(method, camelCaseResponse);
172
205
  }
173
- const camelCaseResult = rpcResponse.result ? convertKeysToCamelCase(rpcResponse.result) : rpcResponse.result;
174
206
  return camelCaseResult;
175
207
  } catch (error) {
176
208
  lastError = error;
177
209
  if (error instanceof JsonRpcClientError) {
178
210
  throw error;
179
211
  }
180
- if (attempt < this.retries) {
181
- const delay = Math.min(1e3 * Math.pow(2, attempt), 1e4);
182
- await new Promise((resolve) => setTimeout(resolve, delay));
183
- continue;
212
+ if (attempt === this.retries) {
213
+ break;
184
214
  }
215
+ await new Promise(
216
+ (resolve) => setTimeout(resolve, Math.pow(2, attempt) * 1e3)
217
+ );
185
218
  }
186
219
  }
187
220
  throw new JsonRpcNetworkError(
188
- `Failed to make RPC call after ${this.retries + 1} attempts: ${lastError?.message}`,
189
- lastError
221
+ lastError?.message || "Request failed after all retries",
222
+ lastError || void 0
190
223
  );
191
224
  }
192
- };
193
- import_jsonrpc_types.RPC_METHODS.forEach((method) => {
194
- let methodName = method;
195
- if (methodName.startsWith("EXPERIMENTAL_")) {
196
- methodName = "experimental" + methodName.substring(13).replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()).replace(/^([a-z])/, (_, letter) => letter.toUpperCase());
197
- } else {
198
- methodName = methodName.replace(
199
- /_([a-z])/g,
200
- (_, letter) => letter.toUpperCase()
201
- );
225
+ /**
226
+ * Create a new client with modified configuration
227
+ */
228
+ withConfig(config) {
229
+ return new _NearRpcClient({
230
+ endpoint: config.endpoint ?? this.endpoint,
231
+ headers: config.headers ?? this.headers,
232
+ timeout: config.timeout ?? this.timeout,
233
+ retries: config.retries ?? this.retries,
234
+ ...config.validation !== void 0 ? { validation: config.validation } : this.validation !== void 0 ? { validation: this.validation } : {}
235
+ });
202
236
  }
203
- NearRpcClient.prototype[methodName] = function(params) {
204
- return this.call(method, params);
205
- };
206
- });
207
- NearRpcClient.prototype.viewAccount = function(params) {
208
- return this.query({
209
- requestType: "view_account",
210
- ...params
211
- });
212
- };
213
- NearRpcClient.prototype.viewFunction = function(params) {
214
- return this.query({
215
- requestType: "call_function",
216
- ...params
217
- });
218
- };
219
- NearRpcClient.prototype.viewAccessKey = function(params) {
220
- return this.query({
221
- requestType: "view_access_key",
222
- ...params
223
- });
224
237
  };
238
+ var defaultClient = new NearRpcClient({
239
+ endpoint: "https://rpc.mainnet.near.org"
240
+ });
225
241
 
226
242
  // src/types.ts
227
243
  var NearRpcError = class extends Error {
@@ -236,6 +252,188 @@ var NearRpcError = class extends Error {
236
252
  // src/index.ts
237
253
  var import_jsonrpc_types2 = require("@psalomo/jsonrpc-types");
238
254
  var import_jsonrpc_types3 = require("@psalomo/jsonrpc-types");
255
+
256
+ // src/generated-types.ts
257
+ async function experimentalChanges(client, params) {
258
+ return client.makeRequest("EXPERIMENTAL_changes", params);
259
+ }
260
+ async function experimentalChangesInBlock(client, params) {
261
+ return client.makeRequest("EXPERIMENTAL_changes_in_block", params);
262
+ }
263
+ async function experimentalCongestionLevel(client, params) {
264
+ return client.makeRequest("EXPERIMENTAL_congestion_level", params);
265
+ }
266
+ async function experimentalGenesisConfig(client, params) {
267
+ return client.makeRequest("EXPERIMENTAL_genesis_config", params);
268
+ }
269
+ async function experimentalLightClientBlockProof(client, params) {
270
+ return client.makeRequest("EXPERIMENTAL_light_client_block_proof", params);
271
+ }
272
+ async function experimentalLightClientProof(client, params) {
273
+ return client.makeRequest("EXPERIMENTAL_light_client_proof", params);
274
+ }
275
+ async function experimentalMaintenanceWindows(client, params) {
276
+ return client.makeRequest("EXPERIMENTAL_maintenance_windows", params);
277
+ }
278
+ async function experimentalProtocolConfig(client, params) {
279
+ return client.makeRequest("EXPERIMENTAL_protocol_config", params);
280
+ }
281
+ async function experimentalReceipt(client, params) {
282
+ return client.makeRequest("EXPERIMENTAL_receipt", params);
283
+ }
284
+ async function experimentalSplitStorageInfo(client, params) {
285
+ return client.makeRequest("EXPERIMENTAL_split_storage_info", params);
286
+ }
287
+ async function experimentalTxStatus(client, params) {
288
+ return client.makeRequest("EXPERIMENTAL_tx_status", params);
289
+ }
290
+ async function experimentalValidatorsOrdered(client, params) {
291
+ return client.makeRequest("EXPERIMENTAL_validators_ordered", params);
292
+ }
293
+ async function block(client, params) {
294
+ return client.makeRequest("block", params);
295
+ }
296
+ async function broadcastTxAsync(client, params) {
297
+ return client.makeRequest("broadcast_tx_async", params);
298
+ }
299
+ async function broadcastTxCommit(client, params) {
300
+ return client.makeRequest("broadcast_tx_commit", params);
301
+ }
302
+ async function changes(client, params) {
303
+ return client.makeRequest("changes", params);
304
+ }
305
+ async function chunk(client, params) {
306
+ return client.makeRequest("chunk", params);
307
+ }
308
+ async function clientConfig(client, params) {
309
+ return client.makeRequest("client_config", params);
310
+ }
311
+ async function gasPrice(client, params) {
312
+ return client.makeRequest("gas_price", params);
313
+ }
314
+ async function health(client, params) {
315
+ return client.makeRequest("health", params);
316
+ }
317
+ async function lightClientProof(client, params) {
318
+ return client.makeRequest("light_client_proof", params);
319
+ }
320
+ async function networkInfo(client, params) {
321
+ return client.makeRequest("network_info", params);
322
+ }
323
+ async function nextLightClientBlock(client, params) {
324
+ return client.makeRequest("next_light_client_block", params);
325
+ }
326
+ async function query(client, params) {
327
+ return client.makeRequest("query", params);
328
+ }
329
+ async function sendTx(client, params) {
330
+ return client.makeRequest("send_tx", params);
331
+ }
332
+ async function status(client, params) {
333
+ return client.makeRequest("status", params);
334
+ }
335
+ async function tx(client, params) {
336
+ return client.makeRequest("tx", params);
337
+ }
338
+ async function validators(client, params) {
339
+ return client.makeRequest("validators", params);
340
+ }
341
+
342
+ // src/convenience.ts
343
+ async function viewAccount(client, params) {
344
+ const queryParams = params.blockId ? {
345
+ requestType: "view_account",
346
+ accountId: params.accountId,
347
+ blockId: params.blockId
348
+ } : {
349
+ requestType: "view_account",
350
+ accountId: params.accountId,
351
+ finality: params.finality || "final"
352
+ };
353
+ return query(client, queryParams);
354
+ }
355
+ async function viewFunction(client, params) {
356
+ const baseParams = {
357
+ requestType: "call_function",
358
+ accountId: params.accountId,
359
+ methodName: params.methodName,
360
+ argsBase64: params.argsBase64 ?? ""
361
+ // Default to empty string if no arguments
362
+ };
363
+ const queryParams = params.blockId ? { ...baseParams, blockId: params.blockId } : { ...baseParams, finality: params.finality || "final" };
364
+ return query(client, queryParams);
365
+ }
366
+ async function viewAccessKey(client, params) {
367
+ const queryParams = params.blockId ? {
368
+ requestType: "view_access_key",
369
+ accountId: params.accountId,
370
+ publicKey: params.publicKey,
371
+ blockId: params.blockId
372
+ } : {
373
+ requestType: "view_access_key",
374
+ accountId: params.accountId,
375
+ publicKey: params.publicKey,
376
+ finality: params.finality || "final"
377
+ };
378
+ return query(client, queryParams);
379
+ }
380
+
381
+ // src/validation.ts
382
+ var import_jsonrpc_types = require("@psalomo/jsonrpc-types");
383
+ function enableValidation() {
384
+ const requestSchema = (0, import_jsonrpc_types.JsonRpcRequestSchema)();
385
+ const responseSchema = (0, import_jsonrpc_types.JsonRpcResponseSchema)();
386
+ return {
387
+ validateRequest: (request) => {
388
+ try {
389
+ requestSchema.parse(request);
390
+ } catch (error) {
391
+ throw new JsonRpcNetworkError(
392
+ `Invalid request format: ${error instanceof Error ? error.message : "Unknown error"}`,
393
+ error
394
+ );
395
+ }
396
+ },
397
+ validateResponse: (response) => {
398
+ try {
399
+ responseSchema.parse(response);
400
+ } catch (error) {
401
+ throw new JsonRpcClientError(
402
+ `Invalid response format: ${error instanceof Error ? error.message : "Unknown error"}`
403
+ );
404
+ }
405
+ },
406
+ validateMethodRequest: (method, request) => {
407
+ try {
408
+ requestSchema.parse(request);
409
+ const methodSchemas = import_jsonrpc_types.VALIDATION_SCHEMA_MAP[method];
410
+ if (methodSchemas?.requestSchema) {
411
+ const methodRequestSchema = methodSchemas.requestSchema();
412
+ methodRequestSchema.parse(request);
413
+ }
414
+ } catch (error) {
415
+ throw new JsonRpcNetworkError(
416
+ `Invalid ${method} request: ${error instanceof Error ? error.message : "Unknown error"}`,
417
+ error
418
+ );
419
+ }
420
+ },
421
+ validateMethodResponse: (method, response) => {
422
+ try {
423
+ responseSchema.parse(response);
424
+ const methodSchemas = import_jsonrpc_types.VALIDATION_SCHEMA_MAP[method];
425
+ if (methodSchemas?.responseSchema) {
426
+ const methodResponseSchema = methodSchemas.responseSchema();
427
+ methodResponseSchema.parse(response);
428
+ }
429
+ } catch (error) {
430
+ throw new JsonRpcClientError(
431
+ `Invalid ${method} response: ${error instanceof Error ? error.message : "Unknown error"}`
432
+ );
433
+ }
434
+ }
435
+ };
436
+ }
239
437
  // Annotate the CommonJS export names for ESM import in node:
240
438
  0 && (module.exports = {
241
439
  JsonRpcClientError,
@@ -244,5 +442,38 @@ var import_jsonrpc_types3 = require("@psalomo/jsonrpc-types");
244
442
  JsonRpcResponseSchema,
245
443
  NearRpcClient,
246
444
  NearRpcError,
247
- RPC_METHODS
445
+ RPC_METHODS,
446
+ block,
447
+ broadcastTxAsync,
448
+ broadcastTxCommit,
449
+ changes,
450
+ chunk,
451
+ clientConfig,
452
+ defaultClient,
453
+ enableValidation,
454
+ experimentalChanges,
455
+ experimentalChangesInBlock,
456
+ experimentalCongestionLevel,
457
+ experimentalGenesisConfig,
458
+ experimentalLightClientBlockProof,
459
+ experimentalLightClientProof,
460
+ experimentalMaintenanceWindows,
461
+ experimentalProtocolConfig,
462
+ experimentalReceipt,
463
+ experimentalSplitStorageInfo,
464
+ experimentalTxStatus,
465
+ experimentalValidatorsOrdered,
466
+ gasPrice,
467
+ health,
468
+ lightClientProof,
469
+ networkInfo,
470
+ nextLightClientBlock,
471
+ query,
472
+ sendTx,
473
+ status,
474
+ tx,
475
+ validators,
476
+ viewAccessKey,
477
+ viewAccount,
478
+ viewFunction
248
479
  });