@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.mjs CHANGED
@@ -1,24 +1,4 @@
1
1
  // src/client.ts
2
- import {
3
- JsonRpcRequestSchema,
4
- JsonRpcResponseSchema,
5
- RPC_METHODS
6
- } from "@psalomo/jsonrpc-types";
7
- var JsonRpcClientError = class extends Error {
8
- constructor(message, code, data) {
9
- super(message);
10
- this.code = code;
11
- this.data = data;
12
- this.name = "JsonRpcClientError";
13
- }
14
- };
15
- var JsonRpcNetworkError = class extends Error {
16
- constructor(message, originalError) {
17
- super(message);
18
- this.originalError = originalError;
19
- this.name = "JsonRpcNetworkError";
20
- }
21
- };
22
2
  function camelToSnake(str) {
23
3
  return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
24
4
  }
@@ -53,59 +33,61 @@ function convertKeysToCamelCase(obj) {
53
33
  }
54
34
  return converted;
55
35
  }
56
- var NearRpcClient = class {
36
+ var REQUEST_ID = "dontcare";
37
+ var JsonRpcClientError = class extends Error {
38
+ constructor(message, code, data) {
39
+ super(message);
40
+ this.code = code;
41
+ this.data = data;
42
+ this.name = "JsonRpcClientError";
43
+ }
44
+ };
45
+ var JsonRpcNetworkError = class extends Error {
46
+ constructor(message, originalError) {
47
+ super(message);
48
+ this.originalError = originalError;
49
+ this.name = "JsonRpcNetworkError";
50
+ }
51
+ };
52
+ var NearRpcClient = class _NearRpcClient {
57
53
  endpoint;
58
54
  headers;
59
55
  timeout;
60
56
  retries;
61
- validateResponses;
57
+ validation;
62
58
  constructor(config) {
63
59
  if (typeof config === "string") {
64
60
  this.endpoint = config;
65
- this.headers = {
66
- "Content-Type": "application/json"
67
- };
61
+ this.headers = {};
68
62
  this.timeout = 3e4;
69
63
  this.retries = 3;
70
- this.validateResponses = true;
71
64
  } else {
72
65
  this.endpoint = config.endpoint;
73
- this.headers = {
74
- "Content-Type": "application/json",
75
- ...config.headers
76
- };
66
+ this.headers = config.headers || {};
77
67
  this.timeout = config.timeout || 3e4;
78
68
  this.retries = config.retries || 3;
79
- this.validateResponses = config.validateResponses ?? true;
69
+ if (config.validation) {
70
+ this.validation = config.validation;
71
+ }
80
72
  }
81
73
  }
82
74
  /**
83
- * Get request ID matching NEAR RPC documentation examples
75
+ * Make a raw JSON-RPC request
76
+ * This is used internally by the standalone RPC functions
84
77
  */
85
- getRequestId() {
86
- return "dontcare";
87
- }
88
- /**
89
- * Make a raw JSON-RPC call
90
- * This method is public to allow dynamic calls to any RPC method
91
- */
92
- async call(method, params) {
93
- const requestId = this.getRequestId();
94
- const snakeCaseParams = params ? convertKeysToSnakeCase(params) : void 0;
78
+ async makeRequest(method, params) {
79
+ const snakeCaseParams = params ? convertKeysToSnakeCase(params) : params;
95
80
  const request = {
96
81
  jsonrpc: "2.0",
97
- id: requestId,
82
+ id: REQUEST_ID,
98
83
  method,
99
84
  params: snakeCaseParams
100
85
  };
101
- if (this.validateResponses) {
102
- try {
103
- JsonRpcRequestSchema.parse(request);
104
- } catch (error) {
105
- throw new JsonRpcNetworkError(
106
- `Invalid request format: ${error instanceof Error ? error.message : "Unknown error"}`,
107
- error
108
- );
86
+ if (this.validation) {
87
+ if ("validateMethodRequest" in this.validation) {
88
+ this.validation.validateMethodRequest(method, request);
89
+ } else {
90
+ this.validation.validateRequest(request);
109
91
  }
110
92
  }
111
93
  let lastError = null;
@@ -115,84 +97,81 @@ var NearRpcClient = class {
115
97
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
116
98
  const response = await fetch(this.endpoint, {
117
99
  method: "POST",
118
- headers: this.headers,
100
+ headers: {
101
+ "Content-Type": "application/json",
102
+ ...this.headers
103
+ },
119
104
  body: JSON.stringify(request),
120
105
  signal: controller.signal
121
106
  });
122
107
  clearTimeout(timeoutId);
123
- const jsonResponse = await response.json();
124
- if (this.validateResponses) {
125
- try {
126
- JsonRpcResponseSchema.parse(jsonResponse);
127
- } catch (error) {
128
- throw new JsonRpcClientError(
129
- `Invalid response format: ${error instanceof Error ? error.message : "Unknown error"}`
130
- );
131
- }
108
+ if (!response.ok) {
109
+ throw new JsonRpcNetworkError(
110
+ `HTTP error! status: ${response.status}`
111
+ );
112
+ }
113
+ let jsonResponse;
114
+ try {
115
+ jsonResponse = await response.json();
116
+ } catch (parseError) {
117
+ throw new JsonRpcNetworkError(
118
+ "Failed to parse JSON response",
119
+ parseError
120
+ );
121
+ }
122
+ if (this.validation) {
123
+ this.validation.validateResponse(jsonResponse);
132
124
  }
133
- const rpcResponse = jsonResponse;
134
- if (rpcResponse.error) {
125
+ if (jsonResponse.error) {
135
126
  throw new JsonRpcClientError(
136
- rpcResponse.error.message,
137
- rpcResponse.error.code,
138
- rpcResponse.error.data
127
+ jsonResponse.error.message,
128
+ jsonResponse.error.code,
129
+ jsonResponse.error.data
139
130
  );
140
131
  }
141
- if (!response.ok) {
142
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
132
+ const camelCaseResult = jsonResponse.result ? convertKeysToCamelCase(jsonResponse.result) : jsonResponse.result;
133
+ if (this.validation && "validateMethodResponse" in this.validation) {
134
+ const camelCaseResponse = {
135
+ ...jsonResponse,
136
+ result: camelCaseResult
137
+ };
138
+ this.validation.validateMethodResponse(method, camelCaseResponse);
143
139
  }
144
- const camelCaseResult = rpcResponse.result ? convertKeysToCamelCase(rpcResponse.result) : rpcResponse.result;
145
140
  return camelCaseResult;
146
141
  } catch (error) {
147
142
  lastError = error;
148
143
  if (error instanceof JsonRpcClientError) {
149
144
  throw error;
150
145
  }
151
- if (attempt < this.retries) {
152
- const delay = Math.min(1e3 * Math.pow(2, attempt), 1e4);
153
- await new Promise((resolve) => setTimeout(resolve, delay));
154
- continue;
146
+ if (attempt === this.retries) {
147
+ break;
155
148
  }
149
+ await new Promise(
150
+ (resolve) => setTimeout(resolve, Math.pow(2, attempt) * 1e3)
151
+ );
156
152
  }
157
153
  }
158
154
  throw new JsonRpcNetworkError(
159
- `Failed to make RPC call after ${this.retries + 1} attempts: ${lastError?.message}`,
160
- lastError
155
+ lastError?.message || "Request failed after all retries",
156
+ lastError || void 0
161
157
  );
162
158
  }
163
- };
164
- RPC_METHODS.forEach((method) => {
165
- let methodName = method;
166
- if (methodName.startsWith("EXPERIMENTAL_")) {
167
- methodName = "experimental" + methodName.substring(13).replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()).replace(/^([a-z])/, (_, letter) => letter.toUpperCase());
168
- } else {
169
- methodName = methodName.replace(
170
- /_([a-z])/g,
171
- (_, letter) => letter.toUpperCase()
172
- );
159
+ /**
160
+ * Create a new client with modified configuration
161
+ */
162
+ withConfig(config) {
163
+ return new _NearRpcClient({
164
+ endpoint: config.endpoint ?? this.endpoint,
165
+ headers: config.headers ?? this.headers,
166
+ timeout: config.timeout ?? this.timeout,
167
+ retries: config.retries ?? this.retries,
168
+ ...config.validation !== void 0 ? { validation: config.validation } : this.validation !== void 0 ? { validation: this.validation } : {}
169
+ });
173
170
  }
174
- NearRpcClient.prototype[methodName] = function(params) {
175
- return this.call(method, params);
176
- };
177
- });
178
- NearRpcClient.prototype.viewAccount = function(params) {
179
- return this.query({
180
- requestType: "view_account",
181
- ...params
182
- });
183
- };
184
- NearRpcClient.prototype.viewFunction = function(params) {
185
- return this.query({
186
- requestType: "call_function",
187
- ...params
188
- });
189
- };
190
- NearRpcClient.prototype.viewAccessKey = function(params) {
191
- return this.query({
192
- requestType: "view_access_key",
193
- ...params
194
- });
195
171
  };
172
+ var defaultClient = new NearRpcClient({
173
+ endpoint: "https://rpc.mainnet.near.org"
174
+ });
196
175
 
197
176
  // src/types.ts
198
177
  var NearRpcError = class extends Error {
@@ -209,7 +188,193 @@ import {
209
188
  JsonRpcRequestSchema as JsonRpcRequestSchema2,
210
189
  JsonRpcResponseSchema as JsonRpcResponseSchema2
211
190
  } from "@psalomo/jsonrpc-types";
212
- import { RPC_METHODS as RPC_METHODS2 } from "@psalomo/jsonrpc-types";
191
+ import { RPC_METHODS } from "@psalomo/jsonrpc-types";
192
+
193
+ // src/generated-types.ts
194
+ async function experimentalChanges(client, params) {
195
+ return client.makeRequest("EXPERIMENTAL_changes", params);
196
+ }
197
+ async function experimentalChangesInBlock(client, params) {
198
+ return client.makeRequest("EXPERIMENTAL_changes_in_block", params);
199
+ }
200
+ async function experimentalCongestionLevel(client, params) {
201
+ return client.makeRequest("EXPERIMENTAL_congestion_level", params);
202
+ }
203
+ async function experimentalGenesisConfig(client, params) {
204
+ return client.makeRequest("EXPERIMENTAL_genesis_config", params);
205
+ }
206
+ async function experimentalLightClientBlockProof(client, params) {
207
+ return client.makeRequest("EXPERIMENTAL_light_client_block_proof", params);
208
+ }
209
+ async function experimentalLightClientProof(client, params) {
210
+ return client.makeRequest("EXPERIMENTAL_light_client_proof", params);
211
+ }
212
+ async function experimentalMaintenanceWindows(client, params) {
213
+ return client.makeRequest("EXPERIMENTAL_maintenance_windows", params);
214
+ }
215
+ async function experimentalProtocolConfig(client, params) {
216
+ return client.makeRequest("EXPERIMENTAL_protocol_config", params);
217
+ }
218
+ async function experimentalReceipt(client, params) {
219
+ return client.makeRequest("EXPERIMENTAL_receipt", params);
220
+ }
221
+ async function experimentalSplitStorageInfo(client, params) {
222
+ return client.makeRequest("EXPERIMENTAL_split_storage_info", params);
223
+ }
224
+ async function experimentalTxStatus(client, params) {
225
+ return client.makeRequest("EXPERIMENTAL_tx_status", params);
226
+ }
227
+ async function experimentalValidatorsOrdered(client, params) {
228
+ return client.makeRequest("EXPERIMENTAL_validators_ordered", params);
229
+ }
230
+ async function block(client, params) {
231
+ return client.makeRequest("block", params);
232
+ }
233
+ async function broadcastTxAsync(client, params) {
234
+ return client.makeRequest("broadcast_tx_async", params);
235
+ }
236
+ async function broadcastTxCommit(client, params) {
237
+ return client.makeRequest("broadcast_tx_commit", params);
238
+ }
239
+ async function changes(client, params) {
240
+ return client.makeRequest("changes", params);
241
+ }
242
+ async function chunk(client, params) {
243
+ return client.makeRequest("chunk", params);
244
+ }
245
+ async function clientConfig(client, params) {
246
+ return client.makeRequest("client_config", params);
247
+ }
248
+ async function gasPrice(client, params) {
249
+ return client.makeRequest("gas_price", params);
250
+ }
251
+ async function health(client, params) {
252
+ return client.makeRequest("health", params);
253
+ }
254
+ async function lightClientProof(client, params) {
255
+ return client.makeRequest("light_client_proof", params);
256
+ }
257
+ async function networkInfo(client, params) {
258
+ return client.makeRequest("network_info", params);
259
+ }
260
+ async function nextLightClientBlock(client, params) {
261
+ return client.makeRequest("next_light_client_block", params);
262
+ }
263
+ async function query(client, params) {
264
+ return client.makeRequest("query", params);
265
+ }
266
+ async function sendTx(client, params) {
267
+ return client.makeRequest("send_tx", params);
268
+ }
269
+ async function status(client, params) {
270
+ return client.makeRequest("status", params);
271
+ }
272
+ async function tx(client, params) {
273
+ return client.makeRequest("tx", params);
274
+ }
275
+ async function validators(client, params) {
276
+ return client.makeRequest("validators", params);
277
+ }
278
+
279
+ // src/convenience.ts
280
+ async function viewAccount(client, params) {
281
+ const queryParams = params.blockId ? {
282
+ requestType: "view_account",
283
+ accountId: params.accountId,
284
+ blockId: params.blockId
285
+ } : {
286
+ requestType: "view_account",
287
+ accountId: params.accountId,
288
+ finality: params.finality || "final"
289
+ };
290
+ return query(client, queryParams);
291
+ }
292
+ async function viewFunction(client, params) {
293
+ const baseParams = {
294
+ requestType: "call_function",
295
+ accountId: params.accountId,
296
+ methodName: params.methodName,
297
+ argsBase64: params.argsBase64 ?? ""
298
+ // Default to empty string if no arguments
299
+ };
300
+ const queryParams = params.blockId ? { ...baseParams, blockId: params.blockId } : { ...baseParams, finality: params.finality || "final" };
301
+ return query(client, queryParams);
302
+ }
303
+ async function viewAccessKey(client, params) {
304
+ const queryParams = params.blockId ? {
305
+ requestType: "view_access_key",
306
+ accountId: params.accountId,
307
+ publicKey: params.publicKey,
308
+ blockId: params.blockId
309
+ } : {
310
+ requestType: "view_access_key",
311
+ accountId: params.accountId,
312
+ publicKey: params.publicKey,
313
+ finality: params.finality || "final"
314
+ };
315
+ return query(client, queryParams);
316
+ }
317
+
318
+ // src/validation.ts
319
+ import {
320
+ JsonRpcRequestSchema,
321
+ JsonRpcResponseSchema,
322
+ VALIDATION_SCHEMA_MAP
323
+ } from "@psalomo/jsonrpc-types";
324
+ function enableValidation() {
325
+ const requestSchema = JsonRpcRequestSchema();
326
+ const responseSchema = JsonRpcResponseSchema();
327
+ return {
328
+ validateRequest: (request) => {
329
+ try {
330
+ requestSchema.parse(request);
331
+ } catch (error) {
332
+ throw new JsonRpcNetworkError(
333
+ `Invalid request format: ${error instanceof Error ? error.message : "Unknown error"}`,
334
+ error
335
+ );
336
+ }
337
+ },
338
+ validateResponse: (response) => {
339
+ try {
340
+ responseSchema.parse(response);
341
+ } catch (error) {
342
+ throw new JsonRpcClientError(
343
+ `Invalid response format: ${error instanceof Error ? error.message : "Unknown error"}`
344
+ );
345
+ }
346
+ },
347
+ validateMethodRequest: (method, request) => {
348
+ try {
349
+ requestSchema.parse(request);
350
+ const methodSchemas = VALIDATION_SCHEMA_MAP[method];
351
+ if (methodSchemas?.requestSchema) {
352
+ const methodRequestSchema = methodSchemas.requestSchema();
353
+ methodRequestSchema.parse(request);
354
+ }
355
+ } catch (error) {
356
+ throw new JsonRpcNetworkError(
357
+ `Invalid ${method} request: ${error instanceof Error ? error.message : "Unknown error"}`,
358
+ error
359
+ );
360
+ }
361
+ },
362
+ validateMethodResponse: (method, response) => {
363
+ try {
364
+ responseSchema.parse(response);
365
+ const methodSchemas = VALIDATION_SCHEMA_MAP[method];
366
+ if (methodSchemas?.responseSchema) {
367
+ const methodResponseSchema = methodSchemas.responseSchema();
368
+ methodResponseSchema.parse(response);
369
+ }
370
+ } catch (error) {
371
+ throw new JsonRpcClientError(
372
+ `Invalid ${method} response: ${error instanceof Error ? error.message : "Unknown error"}`
373
+ );
374
+ }
375
+ }
376
+ };
377
+ }
213
378
  export {
214
379
  JsonRpcClientError,
215
380
  JsonRpcNetworkError,
@@ -217,6 +382,39 @@ export {
217
382
  JsonRpcResponseSchema2 as JsonRpcResponseSchema,
218
383
  NearRpcClient,
219
384
  NearRpcError,
220
- RPC_METHODS2 as RPC_METHODS,
221
- NearRpcClient as default
385
+ RPC_METHODS,
386
+ block,
387
+ broadcastTxAsync,
388
+ broadcastTxCommit,
389
+ changes,
390
+ chunk,
391
+ clientConfig,
392
+ NearRpcClient as default,
393
+ defaultClient,
394
+ enableValidation,
395
+ experimentalChanges,
396
+ experimentalChangesInBlock,
397
+ experimentalCongestionLevel,
398
+ experimentalGenesisConfig,
399
+ experimentalLightClientBlockProof,
400
+ experimentalLightClientProof,
401
+ experimentalMaintenanceWindows,
402
+ experimentalProtocolConfig,
403
+ experimentalReceipt,
404
+ experimentalSplitStorageInfo,
405
+ experimentalTxStatus,
406
+ experimentalValidatorsOrdered,
407
+ gasPrice,
408
+ health,
409
+ lightClientProof,
410
+ networkInfo,
411
+ nextLightClientBlock,
412
+ query,
413
+ sendTx,
414
+ status,
415
+ tx,
416
+ validators,
417
+ viewAccessKey,
418
+ viewAccount,
419
+ viewFunction
222
420
  };
@@ -1,12 +1,14 @@
1
- import { JsonRpcRequest, JsonRpcResponse } from './client.mini.js';
1
+ import { JsonRpcRequest, JsonRpcResponse } from './client.js';
2
2
  export interface ValidationResult {
3
3
  validateRequest: (request: JsonRpcRequest) => void;
4
4
  validateResponse: (response: JsonRpcResponse) => void;
5
+ validateMethodRequest?: (method: string, request: JsonRpcRequest) => void;
6
+ validateMethodResponse?: (method: string, response: JsonRpcResponse) => void;
5
7
  }
6
8
  /**
7
- * Enable validation for the mini client
9
+ * Enable validation for the client
8
10
  * This function should only be called if you want to include schema validation
9
11
  * Calling this function will include Zod schemas in your bundle
10
12
  */
11
13
  export declare function enableValidation(): ValidationResult;
12
- //# sourceMappingURL=validation.mini.d.ts.map
14
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,cAAc,EACd,eAAe,EAGhB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IACnD,gBAAgB,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,IAAI,CAAC;IACtD,qBAAqB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IAC1E,sBAAsB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,KAAK,IAAI,CAAC;CAC9E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,gBAAgB,CA+DnD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@psalomo/jsonrpc-client",
3
- "version": "0.5.0",
3
+ "version": "1.0.1",
4
4
  "description": "TypeScript client for NEAR Protocol JSON-RPC API",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -10,11 +10,6 @@
10
10
  "types": "./dist/index.d.ts",
11
11
  "import": "./dist/index.mjs",
12
12
  "require": "./dist/index.js"
13
- },
14
- "./mini": {
15
- "types": "./dist/index.mini.d.ts",
16
- "import": "./dist/index.mini.mjs",
17
- "require": "./dist/index.mini.cjs"
18
13
  }
19
14
  },
20
15
  "files": [
@@ -35,7 +30,7 @@
35
30
  "test:coverage": "vitest run --coverage"
36
31
  },
37
32
  "dependencies": {
38
- "@psalomo/jsonrpc-types": "^0.1.0"
33
+ "@psalomo/jsonrpc-types": "^1.0.1"
39
34
  },
40
35
  "devDependencies": {
41
36
  "@rollup/plugin-node-resolve": "^16.0.1",