@n1xyz/nord-ts 0.1.6 → 0.1.8

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.
Files changed (85) hide show
  1. package/dist/actions.d.ts +57 -0
  2. package/dist/actions.js +186 -0
  3. package/dist/bundle.js +79181 -0
  4. package/dist/{nord/client → client}/Nord.d.ts +90 -107
  5. package/dist/{nord/client → client}/Nord.js +157 -218
  6. package/dist/{nord/client → client}/NordAdmin.d.ts +68 -102
  7. package/dist/{nord/client → client}/NordAdmin.js +109 -140
  8. package/dist/{nord/client → client}/NordUser.d.ts +86 -98
  9. package/dist/{nord/client → client}/NordUser.js +204 -271
  10. package/dist/const.js +5 -8
  11. package/dist/{nord/utils/NordError.js → error.js} +7 -5
  12. package/dist/gen/nord_pb.js +88 -92
  13. package/dist/gen/openapi.d.ts +39 -0
  14. package/dist/gen/openapi.js +1 -2
  15. package/dist/index.d.ts +6 -1
  16. package/dist/index.js +10 -21
  17. package/dist/types.d.ts +5 -50
  18. package/dist/types.js +21 -83
  19. package/dist/utils.d.ts +8 -11
  20. package/dist/utils.js +55 -90
  21. package/dist/websocket/NordWebSocketClient.js +12 -17
  22. package/dist/{nord/models → websocket}/Subscriber.d.ts +1 -1
  23. package/dist/{nord/models → websocket}/Subscriber.js +6 -7
  24. package/dist/websocket/events.js +1 -2
  25. package/dist/websocket/index.d.ts +19 -2
  26. package/dist/websocket/index.js +80 -5
  27. package/package.json +2 -3
  28. package/dist/api/client.d.ts +0 -14
  29. package/dist/api/client.js +0 -45
  30. package/dist/bridge/client.d.ts +0 -151
  31. package/dist/bridge/client.js +0 -434
  32. package/dist/bridge/const.d.ts +0 -23
  33. package/dist/bridge/const.js +0 -47
  34. package/dist/bridge/index.d.ts +0 -4
  35. package/dist/bridge/index.js +0 -23
  36. package/dist/bridge/types.d.ts +0 -120
  37. package/dist/bridge/types.js +0 -18
  38. package/dist/bridge/utils.d.ts +0 -64
  39. package/dist/bridge/utils.js +0 -131
  40. package/dist/gen/common.d.ts +0 -68
  41. package/dist/gen/common.js +0 -215
  42. package/dist/gen/nord.d.ts +0 -882
  43. package/dist/gen/nord.js +0 -6520
  44. package/dist/idl/bridge.d.ts +0 -569
  45. package/dist/idl/bridge.js +0 -8
  46. package/dist/idl/bridge.json +0 -1506
  47. package/dist/idl/index.d.ts +0 -607
  48. package/dist/idl/index.js +0 -8
  49. package/dist/nord/api/actions.d.ts +0 -126
  50. package/dist/nord/api/actions.js +0 -397
  51. package/dist/nord/api/core.d.ts +0 -16
  52. package/dist/nord/api/core.js +0 -81
  53. package/dist/nord/api/market.d.ts +0 -36
  54. package/dist/nord/api/market.js +0 -96
  55. package/dist/nord/api/metrics.d.ts +0 -67
  56. package/dist/nord/api/metrics.js +0 -229
  57. package/dist/nord/api/queries.d.ts +0 -46
  58. package/dist/nord/api/queries.js +0 -109
  59. package/dist/nord/api/triggers.d.ts +0 -7
  60. package/dist/nord/api/triggers.js +0 -38
  61. package/dist/nord/client/NordClient.d.ts +0 -33
  62. package/dist/nord/client/NordClient.js +0 -45
  63. package/dist/nord/index.d.ts +0 -11
  64. package/dist/nord/index.js +0 -36
  65. package/src/const.ts +0 -34
  66. package/src/gen/.gitkeep +0 -0
  67. package/src/gen/nord_pb.ts +0 -5053
  68. package/src/gen/openapi.ts +0 -2864
  69. package/src/index.ts +0 -5
  70. package/src/nord/api/actions.ts +0 -648
  71. package/src/nord/api/core.ts +0 -96
  72. package/src/nord/api/metrics.ts +0 -269
  73. package/src/nord/client/Nord.ts +0 -937
  74. package/src/nord/client/NordAdmin.ts +0 -514
  75. package/src/nord/client/NordClient.ts +0 -79
  76. package/src/nord/client/NordUser.ts +0 -1211
  77. package/src/nord/index.ts +0 -25
  78. package/src/nord/models/Subscriber.ts +0 -56
  79. package/src/nord/utils/NordError.ts +0 -76
  80. package/src/types.ts +0 -377
  81. package/src/utils.ts +0 -269
  82. package/src/websocket/NordWebSocketClient.ts +0 -316
  83. package/src/websocket/events.ts +0 -31
  84. package/src/websocket/index.ts +0 -2
  85. /package/dist/{nord/utils/NordError.d.ts → error.d.ts} +0 -0
package/src/index.ts DELETED
@@ -1,5 +0,0 @@
1
- export * from "./types";
2
- export * from "./utils";
3
- export * from "./const";
4
- export * from "./nord";
5
- export * from "./websocket/index";
@@ -1,648 +0,0 @@
1
- import Decimal from "decimal.js";
2
- import * as proto from "../../gen/nord_pb";
3
- import { paths } from "../../gen/openapi";
4
- import createClient from "openapi-fetch";
5
- import { create } from "@bufbuild/protobuf";
6
- import {
7
- FillMode,
8
- fillModeToProtoFillMode,
9
- KeyType,
10
- Side,
11
- QuoteSize,
12
- TriggerKind,
13
- } from "../../types";
14
- import {
15
- assert,
16
- BigIntValue,
17
- checkPubKeyLength,
18
- decodeLengthDelimited,
19
- SESSION_TTL,
20
- toScaledU64,
21
- } from "../../utils";
22
- import { sizeDelimitedEncode } from "@bufbuild/protobuf/wire";
23
- import { NordError } from "../utils/NordError";
24
-
25
- type ReceiptKind = NonNullable<proto.Receipt["kind"]>;
26
- type ExtractReceiptKind<K extends ReceiptKind["case"]> = Extract<
27
- ReceiptKind,
28
- { case: K }
29
- >;
30
-
31
- export function formatReceiptError(receipt: proto.Receipt): string {
32
- if (receipt.kind?.case === "err") {
33
- const err = receipt.kind.value;
34
- return proto.Error[err] ?? err.toString();
35
- }
36
- return receipt.kind?.case ?? "unknown";
37
- }
38
-
39
- export function expectReceiptKind<K extends ReceiptKind["case"]>(
40
- receipt: proto.Receipt,
41
- expected: K,
42
- action: string,
43
- ): asserts receipt is proto.Receipt & { kind: ExtractReceiptKind<K> } {
44
- if (receipt.kind?.case !== expected) {
45
- const label = formatReceiptError(receipt);
46
- throw new NordError(`Failed to ${action}: ${label}`);
47
- }
48
- }
49
-
50
- async function sessionSign(
51
- signFn: (message: Uint8Array) => Promise<Uint8Array>,
52
- message: Uint8Array,
53
- ): Promise<Uint8Array> {
54
- const signature = await signFn(message);
55
- return new Uint8Array([...message, ...signature]);
56
- }
57
-
58
- async function walletSign(
59
- walletSignFn: (message: string | Uint8Array) => Promise<Uint8Array>,
60
- message: Uint8Array,
61
- ): Promise<Uint8Array> {
62
- const signature = await walletSignFn(message);
63
- return new Uint8Array([...message, ...signature]);
64
- }
65
-
66
- // Helper to create an action with common fields
67
- export function createAction(
68
- currentTimestamp: bigint,
69
- nonce: number,
70
- kind: proto.Action["kind"],
71
- ): proto.Action {
72
- return create(proto.ActionSchema, {
73
- currentTimestamp,
74
- nonce,
75
- kind,
76
- });
77
- }
78
-
79
- export async function sendAction(
80
- serverUrl: string,
81
- makeSignedMessage: (message: Uint8Array) => Promise<Uint8Array>,
82
- action: proto.Action,
83
- ): Promise<proto.Receipt> {
84
- const body = await prepareAction(action, makeSignedMessage);
85
- // NOTE: restructure and reuse client as it is in Nord.ts
86
- const client = createClient<paths>({ baseUrl: serverUrl });
87
- const response = await client.POST("/action", {
88
- params: {
89
- header: {
90
- "content-type": "application/octet-stream",
91
- },
92
- },
93
- body: body,
94
- // NOTE: openapi-fetch ignores headers and types/const headers in schema, and always assume all things are JSON
95
- // to handle multi type bodies, need these overrides and later adhoc parsing
96
- bodySerializer: (body) => body,
97
- parseAs: "stream",
98
- });
99
-
100
- if (response.error) {
101
- throw new Error(
102
- `Failed to ${action.kind.case}, HTTP status ${JSON.stringify(response.error)}`,
103
- );
104
- }
105
-
106
- const rawResp = new Uint8Array(await response.response.bytes());
107
-
108
- const resp: proto.Receipt = decodeLengthDelimited(
109
- rawResp,
110
- proto.ReceiptSchema,
111
- );
112
-
113
- if (resp.kind?.case === "err") {
114
- throw new Error(
115
- `Could not execute ${action.kind.case}, reason: ${proto.Error[resp.kind.value]}`,
116
- );
117
- }
118
-
119
- return resp;
120
- }
121
-
122
- // Given action and signature function, prepare the signed message to send to server as `body`.
123
- // `makeSignedMessage` must include the original message and signature.
124
- export async function prepareAction(
125
- action: proto.Action,
126
- makeSignedMessage: (message: Uint8Array) => Promise<Uint8Array>,
127
- ) {
128
- const encoded = sizeDelimitedEncode(proto.ActionSchema, action);
129
- // NOTE(agent): keep in sync with MAX_ENCODED_ACTION_SIZE in Rust code
130
- const MAX_ENCODED_ACTION_SIZE = 1024;
131
- if (encoded.byteLength > MAX_ENCODED_ACTION_SIZE) {
132
- console.warn("Encoded message:", encoded);
133
- throw new Error(
134
- `Encoded message size (${encoded.byteLength} bytes) is greater than max payload size (${MAX_ENCODED_ACTION_SIZE} bytes).`,
135
- );
136
- }
137
- const body = await makeSignedMessage(encoded);
138
- if (body.byteLength > MAX_ENCODED_ACTION_SIZE) {
139
- console.warn("Encoded length:", encoded.byteLength);
140
- throw new Error(
141
- `Signed message size (${body.byteLength} bytes) is greater than max payload size (${MAX_ENCODED_ACTION_SIZE} bytes).`,
142
- );
143
- }
144
- return body;
145
- }
146
-
147
- export async function createSession(
148
- serverUrl: string,
149
- walletSignFn: (message: string | Uint8Array) => Promise<Uint8Array>,
150
- currentTimestamp: bigint,
151
- nonce: number,
152
- params: {
153
- userPubkey: Uint8Array;
154
- sessionPubkey: Uint8Array;
155
- // If not specified, set to current moment plus default session TTL
156
- expiryTimestamp?: bigint;
157
- },
158
- ): Promise<{ actionId: bigint; sessionId: bigint }> {
159
- checkPubKeyLength(KeyType.Ed25519, params.userPubkey.length);
160
- checkPubKeyLength(KeyType.Ed25519, params.sessionPubkey.length);
161
-
162
- let expiry = 0n;
163
-
164
- if (params.expiryTimestamp !== undefined) {
165
- expiry = params.expiryTimestamp;
166
- assert(
167
- expiry > currentTimestamp,
168
- "Cannot set expiry timestamp in the past",
169
- );
170
- } else {
171
- expiry = currentTimestamp + SESSION_TTL;
172
- }
173
-
174
- const action = createAction(currentTimestamp, nonce, {
175
- case: "createSession",
176
- value: create(proto.Action_CreateSessionSchema, {
177
- userPubkey: params.userPubkey,
178
- blstPubkey: params.sessionPubkey,
179
- expiryTimestamp: expiry,
180
- }),
181
- });
182
-
183
- const resp = await sendAction(
184
- serverUrl,
185
- (m) => walletSign(walletSignFn, m),
186
- action,
187
- );
188
-
189
- if (resp.kind?.case === "createSessionResult") {
190
- return {
191
- actionId: resp.actionId,
192
- sessionId: resp.kind.value.sessionId,
193
- };
194
- } else {
195
- throw new Error(`Unexpected receipt kind ${resp.kind?.case}`);
196
- }
197
- }
198
-
199
- export async function revokeSession(
200
- serverUrl: string,
201
- walletSignFn: (message: string | Uint8Array) => Promise<Uint8Array>,
202
- currentTimestamp: bigint,
203
- nonce: number,
204
- params: {
205
- sessionId: BigIntValue;
206
- },
207
- ): Promise<{ actionId: bigint }> {
208
- const action = createAction(currentTimestamp, nonce, {
209
- case: "revokeSession",
210
- value: create(proto.Action_RevokeSessionSchema, {
211
- sessionId: BigInt(params.sessionId),
212
- }),
213
- });
214
-
215
- const resp = await sendAction(
216
- serverUrl,
217
- (m) => walletSign(walletSignFn, m),
218
- action,
219
- );
220
-
221
- return { actionId: resp.actionId };
222
- }
223
-
224
- export async function withdraw(
225
- serverUrl: string,
226
- signFn: (message: Uint8Array) => Promise<Uint8Array>,
227
- currentTimestamp: bigint,
228
- nonce: number,
229
- params: {
230
- sizeDecimals: number;
231
- sessionId: BigIntValue;
232
- tokenId: number;
233
- amount: Decimal.Value;
234
- },
235
- ): Promise<{ actionId: bigint } & proto.Receipt_WithdrawResult> {
236
- const amount = toScaledU64(params.amount, params.sizeDecimals);
237
-
238
- if (amount <= 0) {
239
- throw new Error("Withdraw amount must be positive");
240
- }
241
-
242
- const action = createAction(currentTimestamp, nonce, {
243
- case: "withdraw",
244
- value: create(proto.Action_WithdrawSchema, {
245
- sessionId: BigInt(params.sessionId),
246
- tokenId: params.tokenId,
247
- amount,
248
- }),
249
- });
250
-
251
- const resp = await sendAction(
252
- serverUrl,
253
- (m) => sessionSign(signFn, m),
254
- action,
255
- );
256
-
257
- if (resp.kind?.case === "withdrawResult") {
258
- return { actionId: resp.actionId, ...resp.kind.value };
259
- } else {
260
- throw new Error(`Unexpected receipt kind ${resp.kind?.case}`);
261
- }
262
- }
263
-
264
- export async function placeOrder(
265
- serverUrl: string,
266
- signFn: (message: Uint8Array) => Promise<Uint8Array>,
267
- currentTimestamp: bigint,
268
- nonce: number,
269
- params: {
270
- sessionId: BigIntValue;
271
- senderId?: number;
272
- sizeDecimals: number;
273
- priceDecimals: number;
274
- marketId: number;
275
- side: Side;
276
- fillMode: FillMode;
277
- isReduceOnly: boolean;
278
- // NOTE: if `size` equals 1.0, it will sell whole unit, for example 1.0 BTC
279
- size?: Decimal.Value;
280
- price?: Decimal.Value;
281
- quoteSize?: QuoteSize;
282
- liquidateeId?: number;
283
- clientOrderId?: BigIntValue;
284
- },
285
- ): Promise<{
286
- actionId: bigint;
287
- orderId?: bigint;
288
- fills: proto.Receipt_Trade[];
289
- }> {
290
- const price = toScaledU64(params.price ?? 0, params.priceDecimals);
291
- const size = toScaledU64(params.size ?? 0, params.sizeDecimals);
292
-
293
- const scaledQuote = params.quoteSize
294
- ? params.quoteSize.toWire(params.priceDecimals, params.sizeDecimals)
295
- : undefined;
296
-
297
- assert(
298
- price > 0n || size > 0n || scaledQuote !== undefined,
299
- "OrderLimit must include at least one of: size, price, or quoteSize",
300
- );
301
-
302
- const action = createAction(currentTimestamp, nonce, {
303
- case: "placeOrder",
304
- value: create(proto.Action_PlaceOrderSchema, {
305
- sessionId: BigInt(params.sessionId),
306
- senderAccountId: params.senderId,
307
- marketId: params.marketId,
308
- side: params.side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
309
- fillMode: fillModeToProtoFillMode(params.fillMode),
310
- isReduceOnly: params.isReduceOnly,
311
- price,
312
- size,
313
- quoteSize:
314
- scaledQuote === undefined
315
- ? undefined
316
- : create(proto.QuoteSizeSchema, {
317
- size: scaledQuote.size,
318
- price: scaledQuote.price,
319
- }),
320
- clientOrderId:
321
- params.clientOrderId === undefined
322
- ? undefined
323
- : BigInt(params.clientOrderId),
324
- delegatorAccountId: params.liquidateeId,
325
- }),
326
- });
327
-
328
- const resp = await sendAction(
329
- serverUrl,
330
- (m) => sessionSign(signFn, m),
331
- action,
332
- );
333
-
334
- if (resp.kind?.case === "placeOrderResult") {
335
- return {
336
- actionId: resp.actionId,
337
- orderId: resp.kind.value.posted?.orderId,
338
- fills: resp.kind.value.fills,
339
- };
340
- } else {
341
- throw new Error(`Unexpected receipt kind ${resp.kind?.case}`);
342
- }
343
- }
344
-
345
- export async function cancelOrder(
346
- serverUrl: string,
347
- signFn: (message: Uint8Array) => Promise<Uint8Array>,
348
- currentTimestamp: bigint,
349
- nonce: number,
350
- params: {
351
- sessionId: BigIntValue;
352
- senderId?: number;
353
- orderId: BigIntValue;
354
- liquidateeId?: number;
355
- },
356
- ): Promise<{
357
- actionId: bigint;
358
- orderId: bigint;
359
- accountId: number;
360
- }> {
361
- const action = createAction(currentTimestamp, nonce, {
362
- case: "cancelOrderById",
363
- value: create(proto.Action_CancelOrderByIdSchema, {
364
- orderId: BigInt(params.orderId),
365
- sessionId: BigInt(params.sessionId),
366
- senderAccountId: params.senderId,
367
- delegatorAccountId: params.liquidateeId,
368
- }),
369
- });
370
-
371
- const resp = await sendAction(
372
- serverUrl,
373
- (m) => sessionSign(signFn, m),
374
- action,
375
- );
376
-
377
- if (resp.kind?.case === "cancelOrderResult") {
378
- return {
379
- actionId: resp.actionId,
380
- orderId: resp.kind.value.orderId,
381
- accountId: resp.kind.value.accountId,
382
- };
383
- } else {
384
- throw new Error(`Unexpected receipt kind ${resp.kind?.case}`);
385
- }
386
- }
387
-
388
- export async function transfer(
389
- serverUrl: string,
390
- signFn: (message: Uint8Array) => Promise<Uint8Array>,
391
- currentTimestamp: bigint,
392
- nonce: number,
393
- params: {
394
- sessionId: BigIntValue;
395
- fromAccountId: number;
396
- toAccountId?: number;
397
- tokenId: number;
398
- tokenDecimals: number;
399
- amount: Decimal.Value;
400
- },
401
- ): Promise<{
402
- actionId: bigint;
403
- fromAccountId: number;
404
- toAccountId?: number;
405
- tokenId: number;
406
- amount: bigint;
407
- accountCreated: boolean;
408
- }> {
409
- const action = createAction(currentTimestamp, nonce, {
410
- case: "transfer",
411
- value: create(proto.Action_TransferSchema, {
412
- sessionId: BigInt(params.sessionId),
413
- fromAccountId: params.fromAccountId,
414
- toAccountId: params.toAccountId,
415
- tokenId: params.tokenId,
416
- amount: toScaledU64(params.amount ?? 0, params.tokenDecimals),
417
- }),
418
- });
419
-
420
- const resp = await sendAction(
421
- serverUrl,
422
- (m) => sessionSign(signFn, m),
423
- action,
424
- );
425
-
426
- if (resp.kind?.case === "transferred") {
427
- return {
428
- actionId: resp.actionId,
429
- fromAccountId: resp.kind.value.fromAccountId,
430
- toAccountId: resp.kind.value.toUserAccount,
431
- tokenId: resp.kind.value.tokenId,
432
- amount: resp.kind.value.amount,
433
- accountCreated: resp.kind.value.accountCreated,
434
- };
435
- } else {
436
- throw new Error(`Unexpected receipt kind ${resp.kind?.case}`);
437
- }
438
- }
439
-
440
- export async function addTrigger(
441
- serverUrl: string,
442
- signFn: (message: Uint8Array) => Promise<Uint8Array>,
443
- currentTimestamp: bigint,
444
- nonce: number,
445
- params: {
446
- sessionId: BigIntValue;
447
- marketId: number;
448
- side: Side;
449
- kind: TriggerKind;
450
- priceDecimals: number;
451
- triggerPrice: Decimal.Value;
452
- limitPrice?: Decimal.Value;
453
- accountId?: number;
454
- },
455
- ): Promise<{ actionId: bigint }> {
456
- const triggerPrice = toScaledU64(params.triggerPrice, params.priceDecimals);
457
- assert(triggerPrice > 0n, "Trigger price must be positive");
458
- const limitPrice =
459
- params.limitPrice === undefined
460
- ? undefined
461
- : toScaledU64(params.limitPrice, params.priceDecimals);
462
- if (limitPrice !== undefined) {
463
- assert(limitPrice > 0n, "Limit price must be positive");
464
- }
465
- const key = create(proto.TriggerKeySchema, {
466
- kind:
467
- params.kind === TriggerKind.StopLoss
468
- ? proto.TriggerKind.STOP_LOSS
469
- : proto.TriggerKind.TAKE_PROFIT,
470
- side: params.side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
471
- });
472
- const prices = create(proto.Action_TriggerPricesSchema, {
473
- triggerPrice,
474
- limitPrice,
475
- });
476
- const action = createAction(currentTimestamp, nonce, {
477
- case: "addTrigger",
478
- value: create(proto.Action_AddTriggerSchema, {
479
- sessionId: BigInt(params.sessionId),
480
- marketId: params.marketId,
481
- key,
482
- prices,
483
- accountId: params.accountId,
484
- }),
485
- });
486
- const resp = await sendAction(
487
- serverUrl,
488
- (m) => sessionSign(signFn, m),
489
- action,
490
- );
491
- if (resp.kind?.case === "triggerAdded") {
492
- return { actionId: resp.actionId };
493
- }
494
- throw new Error(`Unexpected receipt kind ${resp.kind?.case}`);
495
- }
496
-
497
- export async function removeTrigger(
498
- serverUrl: string,
499
- signFn: (message: Uint8Array) => Promise<Uint8Array>,
500
- currentTimestamp: bigint,
501
- nonce: number,
502
- params: {
503
- sessionId: BigIntValue;
504
- marketId: number;
505
- side: Side;
506
- kind: TriggerKind;
507
- accountId?: number;
508
- },
509
- ): Promise<{ actionId: bigint }> {
510
- const key = create(proto.TriggerKeySchema, {
511
- kind:
512
- params.kind === TriggerKind.StopLoss
513
- ? proto.TriggerKind.STOP_LOSS
514
- : proto.TriggerKind.TAKE_PROFIT,
515
- side: params.side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
516
- });
517
- const action = createAction(currentTimestamp, nonce, {
518
- case: "removeTrigger",
519
- value: create(proto.Action_RemoveTriggerSchema, {
520
- sessionId: BigInt(params.sessionId),
521
- marketId: params.marketId,
522
- key,
523
- accountId: params.accountId,
524
- }),
525
- });
526
- const resp = await sendAction(
527
- serverUrl,
528
- (m) => sessionSign(signFn, m),
529
- action,
530
- );
531
- if (resp.kind?.case === "triggerRemoved") {
532
- return { actionId: resp.actionId };
533
- }
534
- throw new Error(`Unexpected receipt kind ${resp.kind?.case}`);
535
- }
536
- export type AtomicSubaction =
537
- | {
538
- kind: "place";
539
- // Market and order parameters – identical semantics to placeOrder()
540
- marketId: number;
541
- side: Side;
542
- fillMode: FillMode;
543
- isReduceOnly: boolean;
544
- // decimals for scaling
545
- sizeDecimals: number;
546
- priceDecimals: number;
547
- // at least one of the three has to be specified; 0 treated as "not set"
548
- size?: Decimal.Value;
549
- price?: Decimal.Value;
550
- quoteSize?: QuoteSize;
551
- clientOrderId?: BigIntValue;
552
- }
553
- | {
554
- kind: "cancel";
555
- orderId: BigIntValue;
556
- };
557
-
558
- export async function atomic(
559
- serverUrl: string,
560
- signFn: (message: Uint8Array) => Promise<Uint8Array>,
561
- currentTimestamp: bigint,
562
- nonce: number,
563
- params: {
564
- sessionId: BigIntValue;
565
- accountId?: number;
566
- actions: AtomicSubaction[];
567
- },
568
- ): Promise<{
569
- actionId: bigint;
570
- results: proto.Receipt_AtomicSubactionResultKind[];
571
- }> {
572
- assert(
573
- params.actions.length > 0 && params.actions.length <= 4,
574
- "Atomic action must contain between 1 and 4 sub-actions",
575
- );
576
-
577
- const subactions: proto.AtomicSubactionKind[] = params.actions.map((a) => {
578
- if (a.kind === "place") {
579
- const price = toScaledU64(a.price ?? 0, a.priceDecimals);
580
- const size = toScaledU64(a.size ?? 0, a.sizeDecimals);
581
- const scaledQuote = a.quoteSize
582
- ? a.quoteSize.toWire(a.priceDecimals, a.sizeDecimals)
583
- : undefined;
584
-
585
- // Require at least one limit to be set (non-zero size, non-zero price, or quoteSize)
586
- assert(
587
- price > 0n || size > 0n || scaledQuote !== undefined,
588
- "OrderLimit must include at least one of: size, price, or quoteSize",
589
- );
590
-
591
- const tradeOrPlace: proto.TradeOrPlace = create(
592
- proto.TradeOrPlaceSchema,
593
- {
594
- marketId: a.marketId,
595
- orderType: create(proto.OrderTypeSchema, {
596
- side: a.side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
597
- fillMode: fillModeToProtoFillMode(a.fillMode),
598
- isReduceOnly: a.isReduceOnly,
599
- }),
600
- limit: create(proto.OrderLimitSchema, {
601
- price,
602
- size,
603
- quoteSize:
604
- scaledQuote === undefined
605
- ? undefined
606
- : create(proto.QuoteSizeSchema, {
607
- size: scaledQuote.size,
608
- price: scaledQuote.price,
609
- }),
610
- }),
611
- clientOrderId:
612
- a.clientOrderId === undefined ? undefined : BigInt(a.clientOrderId),
613
- },
614
- );
615
- return create(proto.AtomicSubactionKindSchema, {
616
- inner: { case: "tradeOrPlace", value: tradeOrPlace },
617
- });
618
- }
619
- return create(proto.AtomicSubactionKindSchema, {
620
- inner: {
621
- case: "cancelOrder",
622
- value: create(proto.CancelOrderSchema, { orderId: BigInt(a.orderId) }),
623
- },
624
- });
625
- });
626
-
627
- const action = createAction(currentTimestamp, nonce, {
628
- case: "atomic",
629
- value: create(proto.AtomicSchema, {
630
- sessionId: BigInt(params.sessionId),
631
- accountId: params.accountId, // optional
632
- actions: subactions,
633
- }),
634
- });
635
-
636
- const resp = await sendAction(
637
- serverUrl,
638
- (m) => sessionSign(signFn, m),
639
- action,
640
- );
641
- if (resp.kind?.case === "atomic") {
642
- return {
643
- actionId: resp.actionId,
644
- results: resp.kind.value.results,
645
- };
646
- }
647
- throw new Error(`Unexpected receipt kind ${resp.kind?.case}`);
648
- }