@n1xyz/nord-ts 0.1.0 → 0.1.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.
@@ -136,6 +136,14 @@ export interface paths {
136
136
  "application/octet-stream": unknown;
137
137
  };
138
138
  };
139
+ 413: {
140
+ headers: {
141
+ [name: string]: unknown;
142
+ };
143
+ content: {
144
+ "application/json": components["schemas"]["PayloadTooLarge"];
145
+ };
146
+ };
139
147
  415: {
140
148
  headers: {
141
149
  /**
@@ -1910,6 +1918,10 @@ export interface components {
1910
1918
  AcceptedMediaType: {
1911
1919
  expected: string;
1912
1920
  };
1921
+ PayloadTooLarge: {
1922
+ /** Format: uint */
1923
+ limit: number;
1924
+ };
1913
1925
  ActionsQuery: {
1914
1926
  /** Format: uint64 */
1915
1927
  from: number;
@@ -66,7 +66,7 @@ function createAction(currentTimestamp, nonce, kind) {
66
66
  kind,
67
67
  });
68
68
  }
69
- async function sendAction(serverUrl, makeSignedMessage, action, actionErrorDesc) {
69
+ async function sendAction(serverUrl, makeSignedMessage, action) {
70
70
  const body = await prepareAction(action, makeSignedMessage);
71
71
  // NOTE: restructure and reuse client as it is in Nord.ts
72
72
  const client = (0, openapi_fetch_1.default)({ baseUrl: serverUrl });
@@ -77,14 +77,18 @@ async function sendAction(serverUrl, makeSignedMessage, action, actionErrorDesc)
77
77
  },
78
78
  },
79
79
  body: body,
80
+ // NOTE: openapi-fetch ignores headers and types/const headers in schema, and always assume all things are JSON
81
+ // to handle multi type bodies, need these overrides and later adhoc parsing
82
+ bodySerializer: (body) => body,
83
+ parseAs: "stream",
80
84
  });
81
85
  if (response.error) {
82
- throw new Error(`Failed to ${actionErrorDesc}, HTTP status ${response}`);
86
+ throw new Error(`Failed to ${action.kind.case}, HTTP status ${JSON.stringify(response.error)}`);
83
87
  }
84
- const rawResp = new Uint8Array(await response.response.arrayBuffer());
88
+ const rawResp = new Uint8Array(await response.response.bytes());
85
89
  const resp = (0, utils_1.decodeLengthDelimited)(rawResp, proto.ReceiptSchema);
86
90
  if (resp.kind?.case === "err") {
87
- throw new Error(`Could not ${actionErrorDesc}, reason: ${proto.Error[resp.kind.value]}`);
91
+ throw new Error(`Could not execute ${action.kind.case}, reason: ${proto.Error[resp.kind.value]}`);
88
92
  }
89
93
  return resp;
90
94
  }
@@ -92,12 +96,17 @@ async function sendAction(serverUrl, makeSignedMessage, action, actionErrorDesc)
92
96
  // `makeSignedMessage` must include the original message and signature.
93
97
  async function prepareAction(action, makeSignedMessage) {
94
98
  const encoded = (0, wire_1.sizeDelimitedEncode)(proto.ActionSchema, action);
95
- // NOTE(agent): keep in sync with MAX_HTTP_REQUEST_BODY_SIZE in rust code
96
- const MAX_HTTP_REQUEST_BODY_SIZE = 1024;
97
- if (encoded.byteLength > MAX_HTTP_REQUEST_BODY_SIZE) {
98
- throw new Error(`Encoded message size (${encoded.byteLength} bytes) is greater than max payload size (${MAX_HTTP_REQUEST_BODY_SIZE} bytes).`);
99
+ // NOTE(agent): keep in sync with MAX_ENCODED_ACTION_SIZE in Rust code
100
+ const MAX_ENCODED_ACTION_SIZE = 1024;
101
+ if (encoded.byteLength > MAX_ENCODED_ACTION_SIZE) {
102
+ console.warn("Encoded message:", encoded);
103
+ throw new Error(`Encoded message size (${encoded.byteLength} bytes) is greater than max payload size (${MAX_ENCODED_ACTION_SIZE} bytes).`);
99
104
  }
100
105
  const body = await makeSignedMessage(encoded);
106
+ if (body.byteLength > MAX_ENCODED_ACTION_SIZE) {
107
+ console.warn("Encoded length:", encoded.byteLength);
108
+ throw new Error(`Signed message size (${body.byteLength} bytes) is greater than max payload size (${MAX_ENCODED_ACTION_SIZE} bytes).`);
109
+ }
101
110
  return body;
102
111
  }
103
112
  async function createSession(serverUrl, walletSignFn, currentTimestamp, nonce, params) {
@@ -119,7 +128,7 @@ async function createSession(serverUrl, walletSignFn, currentTimestamp, nonce, p
119
128
  expiryTimestamp: expiry,
120
129
  }),
121
130
  });
122
- const resp = await sendAction(serverUrl, (m) => walletSign(walletSignFn, m), action, "create a new session");
131
+ const resp = await sendAction(serverUrl, (m) => walletSign(walletSignFn, m), action);
123
132
  if (resp.kind?.case === "createSessionResult") {
124
133
  return {
125
134
  actionId: resp.actionId,
@@ -137,7 +146,7 @@ async function revokeSession(serverUrl, walletSignFn, currentTimestamp, nonce, p
137
146
  sessionId: BigInt(params.sessionId),
138
147
  }),
139
148
  });
140
- const resp = await sendAction(serverUrl, (m) => walletSign(walletSignFn, m), action, "revoke session");
149
+ const resp = await sendAction(serverUrl, (m) => walletSign(walletSignFn, m), action);
141
150
  return { actionId: resp.actionId };
142
151
  }
143
152
  async function withdraw(serverUrl, signFn, currentTimestamp, nonce, params) {
@@ -153,7 +162,7 @@ async function withdraw(serverUrl, signFn, currentTimestamp, nonce, params) {
153
162
  amount,
154
163
  }),
155
164
  });
156
- const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action, "withdraw");
165
+ const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action);
157
166
  if (resp.kind?.case === "withdrawResult") {
158
167
  return { actionId: resp.actionId, ...resp.kind.value };
159
168
  }
@@ -191,7 +200,7 @@ async function placeOrder(serverUrl, signFn, currentTimestamp, nonce, params) {
191
200
  delegatorAccountId: params.liquidateeId,
192
201
  }),
193
202
  });
194
- const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action, "place order");
203
+ const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action);
195
204
  if (resp.kind?.case === "placeOrderResult") {
196
205
  return {
197
206
  actionId: resp.actionId,
@@ -213,7 +222,7 @@ async function cancelOrder(serverUrl, signFn, currentTimestamp, nonce, params) {
213
222
  delegatorAccountId: params.liquidateeId,
214
223
  }),
215
224
  });
216
- const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action, "cancel order");
225
+ const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action);
217
226
  if (resp.kind?.case === "cancelOrderResult") {
218
227
  return {
219
228
  actionId: resp.actionId,
@@ -236,7 +245,7 @@ async function transfer(serverUrl, signFn, currentTimestamp, nonce, params) {
236
245
  amount: (0, utils_1.toScaledU64)(params.amount ?? 0, params.tokenDecimals),
237
246
  }),
238
247
  });
239
- const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action, "transfer");
248
+ const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action);
240
249
  if (resp.kind?.case === "transferred") {
241
250
  return {
242
251
  actionId: resp.actionId,
@@ -300,7 +309,7 @@ async function atomic(serverUrl, signFn, currentTimestamp, nonce, params) {
300
309
  actions: subactions,
301
310
  }),
302
311
  });
303
- const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action, "execute atomic action");
312
+ const resp = await sendAction(serverUrl, (m) => sessionSign(signFn, m), action);
304
313
  if (resp.kind?.case === "atomic") {
305
314
  return {
306
315
  actionId: resp.actionId,
package/dist/utils.js CHANGED
@@ -31,6 +31,7 @@ const bs58_1 = __importDefault(require("bs58"));
31
31
  exports.SESSION_TTL = 60n * 60n * 24n * 30n;
32
32
  exports.ZERO_DECIMAL = new decimal_js_1.Decimal(0);
33
33
  exports.MAX_BUFFER_LEN = 10000;
34
+ // Max size of data returned from Nord endpoints
34
35
  const MAX_PAYLOAD_SIZE = 100 * 1024; // 100 kB
35
36
  function panic(message) {
36
37
  throw new Error(message);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@n1xyz/nord-ts",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Typescript for Nord",
5
5
  "keywords": [],
6
6
  "author": "",
@@ -137,6 +137,14 @@ export interface paths {
137
137
  "application/octet-stream": unknown;
138
138
  };
139
139
  };
140
+ 413: {
141
+ headers: {
142
+ [name: string]: unknown;
143
+ };
144
+ content: {
145
+ "application/json": components["schemas"]["PayloadTooLarge"];
146
+ };
147
+ };
140
148
  415: {
141
149
  headers: {
142
150
  /**
@@ -1911,6 +1919,10 @@ export interface components {
1911
1919
  AcceptedMediaType: {
1912
1920
  expected: string;
1913
1921
  };
1922
+ PayloadTooLarge: {
1923
+ /** Format: uint */
1924
+ limit: number;
1925
+ };
1914
1926
  ActionsQuery: {
1915
1927
  /** Format: uint64 */
1916
1928
  from: number;
@@ -1,6 +1,6 @@
1
1
  import Decimal from "decimal.js";
2
2
  import * as proto from "../../gen/nord_pb";
3
- import { paths, components } from "../../gen/openapi";
3
+ import { paths } from "../../gen/openapi";
4
4
  import createClient from "openapi-fetch";
5
5
 
6
6
  import { create } from "@bufbuild/protobuf";
@@ -14,7 +14,6 @@ import {
14
14
  import {
15
15
  assert,
16
16
  BigIntValue,
17
- checkedFetch,
18
17
  checkPubKeyLength,
19
18
  decodeLengthDelimited,
20
19
  SESSION_TTL,
@@ -55,7 +54,6 @@ async function sendAction(
55
54
  serverUrl: string,
56
55
  makeSignedMessage: (message: Uint8Array) => Promise<Uint8Array>,
57
56
  action: proto.Action,
58
- actionErrorDesc: string,
59
57
  ): Promise<proto.Receipt> {
60
58
  const body = await prepareAction(action, makeSignedMessage);
61
59
  // NOTE: restructure and reuse client as it is in Nord.ts
@@ -67,13 +65,19 @@ async function sendAction(
67
65
  },
68
66
  },
69
67
  body: body,
68
+ // NOTE: openapi-fetch ignores headers and types/const headers in schema, and always assume all things are JSON
69
+ // to handle multi type bodies, need these overrides and later adhoc parsing
70
+ bodySerializer: (body) => body,
71
+ parseAs: "stream",
70
72
  });
71
73
 
72
74
  if (response.error) {
73
- throw new Error(`Failed to ${actionErrorDesc}, HTTP status ${response}`);
75
+ throw new Error(
76
+ `Failed to ${action.kind.case}, HTTP status ${JSON.stringify(response.error)}`,
77
+ );
74
78
  }
75
79
 
76
- const rawResp = new Uint8Array(await response.response.arrayBuffer());
80
+ const rawResp = new Uint8Array(await response.response.bytes());
77
81
 
78
82
  const resp: proto.Receipt = decodeLengthDelimited(
79
83
  rawResp,
@@ -82,7 +86,7 @@ async function sendAction(
82
86
 
83
87
  if (resp.kind?.case === "err") {
84
88
  throw new Error(
85
- `Could not ${actionErrorDesc}, reason: ${proto.Error[resp.kind.value]}`,
89
+ `Could not execute ${action.kind.case}, reason: ${proto.Error[resp.kind.value]}`,
86
90
  );
87
91
  }
88
92
 
@@ -96,14 +100,21 @@ export async function prepareAction(
96
100
  makeSignedMessage: (message: Uint8Array) => Promise<Uint8Array>,
97
101
  ) {
98
102
  const encoded = sizeDelimitedEncode(proto.ActionSchema, action);
99
- // NOTE(agent): keep in sync with MAX_HTTP_REQUEST_BODY_SIZE in rust code
100
- const MAX_HTTP_REQUEST_BODY_SIZE = 1024;
101
- if (encoded.byteLength > MAX_HTTP_REQUEST_BODY_SIZE) {
103
+ // NOTE(agent): keep in sync with MAX_ENCODED_ACTION_SIZE in Rust code
104
+ const MAX_ENCODED_ACTION_SIZE = 1024;
105
+ if (encoded.byteLength > MAX_ENCODED_ACTION_SIZE) {
106
+ console.warn("Encoded message:", encoded);
102
107
  throw new Error(
103
- `Encoded message size (${encoded.byteLength} bytes) is greater than max payload size (${MAX_HTTP_REQUEST_BODY_SIZE} bytes).`,
108
+ `Encoded message size (${encoded.byteLength} bytes) is greater than max payload size (${MAX_ENCODED_ACTION_SIZE} bytes).`,
104
109
  );
105
110
  }
106
111
  const body = await makeSignedMessage(encoded);
112
+ if (body.byteLength > MAX_ENCODED_ACTION_SIZE) {
113
+ console.warn("Encoded length:", encoded.byteLength);
114
+ throw new Error(
115
+ `Signed message size (${body.byteLength} bytes) is greater than max payload size (${MAX_ENCODED_ACTION_SIZE} bytes).`,
116
+ );
117
+ }
107
118
  return body;
108
119
  }
109
120
 
@@ -147,7 +158,6 @@ export async function createSession(
147
158
  serverUrl,
148
159
  (m) => walletSign(walletSignFn, m),
149
160
  action,
150
- "create a new session",
151
161
  );
152
162
 
153
163
  if (resp.kind?.case === "createSessionResult") {
@@ -180,7 +190,6 @@ export async function revokeSession(
180
190
  serverUrl,
181
191
  (m) => walletSign(walletSignFn, m),
182
192
  action,
183
- "revoke session",
184
193
  );
185
194
 
186
195
  return { actionId: resp.actionId };
@@ -217,7 +226,6 @@ export async function withdraw(
217
226
  serverUrl,
218
227
  (m) => sessionSign(signFn, m),
219
228
  action,
220
- "withdraw",
221
229
  );
222
230
 
223
231
  if (resp.kind?.case === "withdrawResult") {
@@ -295,7 +303,6 @@ export async function placeOrder(
295
303
  serverUrl,
296
304
  (m) => sessionSign(signFn, m),
297
305
  action,
298
- "place order",
299
306
  );
300
307
 
301
308
  if (resp.kind?.case === "placeOrderResult") {
@@ -339,7 +346,6 @@ export async function cancelOrder(
339
346
  serverUrl,
340
347
  (m) => sessionSign(signFn, m),
341
348
  action,
342
- "cancel order",
343
349
  );
344
350
 
345
351
  if (resp.kind?.case === "cancelOrderResult") {
@@ -389,7 +395,6 @@ export async function transfer(
389
395
  serverUrl,
390
396
  (m) => sessionSign(signFn, m),
391
397
  action,
392
- "transfer",
393
398
  );
394
399
 
395
400
  if (resp.kind?.case === "transferred") {
@@ -510,7 +515,6 @@ export async function atomic(
510
515
  serverUrl,
511
516
  (m) => sessionSign(signFn, m),
512
517
  action,
513
- "execute atomic action",
514
518
  );
515
519
  if (resp.kind?.case === "atomic") {
516
520
  return {
package/src/utils.ts CHANGED
@@ -17,6 +17,7 @@ export const SESSION_TTL: bigint = 60n * 60n * 24n * 30n;
17
17
  export const ZERO_DECIMAL = new Decimal(0);
18
18
  export const MAX_BUFFER_LEN = 10_000;
19
19
 
20
+ // Max size of data returned from Nord endpoints
20
21
  const MAX_PAYLOAD_SIZE = 100 * 1024; // 100 kB
21
22
 
22
23
  /** Any type convertible to bigint */