@dydxprotocol/v4-client-js 0.38.4 → 0.38.6

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.
@@ -5,6 +5,7 @@ import {
5
5
  Registry,
6
6
  } from '@cosmjs/proto-signing';
7
7
  import {
8
+ Account,
8
9
  calculateFee,
9
10
  GasPrice,
10
11
  IndexedTx,
@@ -55,6 +56,8 @@ export class Post {
55
56
  private readonly chainId: string;
56
57
  public readonly get: Get;
57
58
 
59
+ private accountNumberCache: Map<string, Account> = new Map();
60
+
58
61
  constructor(
59
62
  get: Get,
60
63
  chainId: string,
@@ -78,10 +81,20 @@ export class Post {
78
81
  messaging: () => Promise<EncodeObject[]>,
79
82
  gasPrice: GasPrice = GAS_PRICE,
80
83
  memo?: string,
84
+ account?: () => Promise<Account>,
81
85
  ): Promise<StdFee> {
82
- const msgs = await messaging();
83
- const account = await this.get.getAccount(wallet.address!);
84
- return this.simulateTransaction(wallet.pubKey!, account.sequence, msgs, gasPrice, memo);
86
+ const msgsPromise = messaging();
87
+ const accountPromise = account ? (await account()) : this.account(wallet.address!);
88
+ const msgsAndAccount = await Promise.all([msgsPromise, accountPromise]);
89
+ const msgs = msgsAndAccount[0];
90
+
91
+ return this.simulateTransaction(
92
+ wallet.pubKey!,
93
+ msgsAndAccount[1].sequence,
94
+ msgs,
95
+ gasPrice,
96
+ memo,
97
+ );
85
98
  }
86
99
 
87
100
  /**
@@ -98,9 +111,13 @@ export class Post {
98
111
  zeroFee: boolean,
99
112
  gasPrice: GasPrice = GAS_PRICE,
100
113
  memo?: string,
114
+ account?: () => Promise<Account>,
101
115
  ): Promise<Uint8Array> {
102
- const msgs = await messaging();
103
- return this.signTransaction(wallet, msgs, zeroFee, gasPrice, memo);
116
+ const msgsPromise = await messaging();
117
+ const accountPromise = account ? (await account()) : this.account(wallet.address!);
118
+ const msgsAndAccount = await Promise.all([msgsPromise, accountPromise]);
119
+ const msgs = msgsAndAccount[0];
120
+ return this.signTransaction(wallet, msgs, msgsAndAccount[1], zeroFee, gasPrice, memo);
104
121
  }
105
122
 
106
123
  /**
@@ -118,10 +135,16 @@ export class Post {
118
135
  gasPrice: GasPrice = GAS_PRICE,
119
136
  memo?: string,
120
137
  broadcastMode?: BroadcastMode,
138
+ account?: () => Promise<Account>,
121
139
  ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
122
- const msgs = await messaging();
140
+ const msgsPromise = messaging();
141
+ const accountPromise = account ? (await account()) : this.account(wallet.address!);
142
+ const msgsAndAccount = await Promise.all([msgsPromise, accountPromise]);
143
+ const msgs = msgsAndAccount[0];
144
+
123
145
  return this.signAndSendTransaction(
124
146
  wallet,
147
+ msgsAndAccount[1],
125
148
  msgs,
126
149
  zeroFee,
127
150
  gasPrice,
@@ -159,11 +182,11 @@ export class Post {
159
182
  private async signTransaction(
160
183
  wallet: LocalWallet,
161
184
  messages: EncodeObject[],
185
+ account: Account,
162
186
  zeroFee: boolean,
163
187
  gasPrice: GasPrice = GAS_PRICE,
164
188
  memo?: string,
165
189
  ): Promise<Uint8Array> {
166
- const account = await this.get.getAccount(wallet.address!);
167
190
  // Simulate transaction if no fee is specified.
168
191
  const fee: StdFee = zeroFee ? {
169
192
  amount: [],
@@ -190,6 +213,23 @@ export class Post {
190
213
  );
191
214
  }
192
215
 
216
+ /**
217
+ * @description Retrieve an account structure for transactions.
218
+ * For short term orders, the sequence doesn't matter. Use cached if available.
219
+ * For long term and conditional orders, a round trip to validator must be made.
220
+ */
221
+ public async account(address: string, orderFlags?: OrderFlags): Promise<Account> {
222
+ if (orderFlags === OrderFlags.SHORT_TERM) {
223
+ if (this.accountNumberCache.has(address)) {
224
+ // For SHORT_TERM orders, the sequence doesn't matter
225
+ return this.accountNumberCache.get(address)!;
226
+ }
227
+ }
228
+ const account = await this.get.getAccount(address);
229
+ this.accountNumberCache.set(address, account);
230
+ return account;
231
+ }
232
+
193
233
  /**
194
234
  * @description Sign and send a message
195
235
  *
@@ -197,6 +237,7 @@ export class Post {
197
237
  */
198
238
  private async signAndSendTransaction(
199
239
  wallet: LocalWallet,
240
+ account: Account,
200
241
  messages: EncodeObject[],
201
242
  zeroFee: boolean,
202
243
  gasPrice: GasPrice = GAS_PRICE,
@@ -206,6 +247,7 @@ export class Post {
206
247
  const signedTransaction = await this.signTransaction(
207
248
  wallet,
208
249
  messages,
250
+ account,
209
251
  zeroFee,
210
252
  gasPrice,
211
253
  memo,
@@ -329,7 +371,16 @@ export class Post {
329
371
  );
330
372
  resolve([msg]);
331
373
  });
332
- return this.send(subaccount.wallet, () => msgs, true, undefined, undefined, broadcastMode);
374
+ const account: Promise<Account> = this.account(subaccount.address, orderFlags);
375
+ return this.send(
376
+ subaccount.wallet,
377
+ () => msgs,
378
+ true,
379
+ undefined,
380
+ undefined,
381
+ broadcastMode,
382
+ () => account,
383
+ );
333
384
  }
334
385
 
335
386
  async placeOrderObject(
@@ -377,7 +428,13 @@ export class Post {
377
428
  );
378
429
  resolve([msg]);
379
430
  });
380
- return this.send(subaccount.wallet, () => msgs, true, undefined, undefined, broadcastMode);
431
+ return this.send(
432
+ subaccount.wallet,
433
+ () => msgs,
434
+ true,
435
+ undefined,
436
+ undefined,
437
+ broadcastMode);
381
438
  }
382
439
 
383
440
  async cancelOrderObject(
@@ -415,7 +472,14 @@ export class Post {
415
472
  );
416
473
  resolve([msg]);
417
474
  });
418
- return this.send(subaccount.wallet, () => msgs, false, undefined, undefined, broadcastMode);
475
+ return this.send(
476
+ subaccount.wallet,
477
+ () => msgs,
478
+ false,
479
+ undefined,
480
+ undefined,
481
+ broadcastMode,
482
+ );
419
483
  }
420
484
 
421
485
  async deposit(
@@ -433,7 +497,14 @@ export class Post {
433
497
  );
434
498
  resolve([msg]);
435
499
  });
436
- return this.send(subaccount.wallet, () => msgs, false, undefined, undefined, broadcastMode);
500
+ return this.send(
501
+ subaccount.wallet,
502
+ () => msgs,
503
+ false,
504
+ undefined,
505
+ undefined,
506
+ broadcastMode,
507
+ );
437
508
  }
438
509
 
439
510
  async withdraw(
@@ -453,7 +524,14 @@ export class Post {
453
524
  );
454
525
  resolve([msg]);
455
526
  });
456
- return this.send(subaccount.wallet, () => msgs, false, undefined, undefined, broadcastMode);
527
+ return this.send(
528
+ subaccount.wallet,
529
+ () => msgs,
530
+ false,
531
+ undefined,
532
+ undefined,
533
+ broadcastMode,
534
+ );
457
535
  }
458
536
 
459
537
  async sendToken(
@@ -13,7 +13,7 @@ import { UserError } from '../lib/errors';
13
13
  import { encodeJson } from '../lib/helpers';
14
14
  import { deriveHDKeyFromEthereumSignature } from '../lib/onboarding';
15
15
  import { NetworkOptimizer } from '../network_optimizer';
16
- import { CompositeClient } from './composite-client';
16
+ import { CompositeClient, MarketInfo } from './composite-client';
17
17
  import {
18
18
  Network, OrderType, OrderSide, OrderTimeInForce, OrderExecution, IndexerConfig, ValidatorConfig,
19
19
  } from './constants';
@@ -224,6 +224,9 @@ export async function placeOrder(
224
224
  const reduceOnly = json.reduceOnly ?? false;
225
225
  const triggerPrice = json.triggerPrice;
226
226
 
227
+ const marketInfo = json.marketInfo as MarketInfo;
228
+ const currentHeight = json.currentHeight as number;
229
+
227
230
  const subaccount = new Subaccount(wallet, subaccountNumber);
228
231
  const tx = await client.placeOrder(
229
232
  subaccount,
@@ -239,6 +242,8 @@ export async function placeOrder(
239
242
  postOnly,
240
243
  reduceOnly,
241
244
  triggerPrice,
245
+ marketInfo,
246
+ currentHeight,
242
247
  );
243
248
  return encodeJson(tx);
244
249
  } catch (error) {
@@ -580,9 +585,13 @@ export async function simulateDeposit(
580
585
  );
581
586
  const msgs: EncodeObject[] = [msg];
582
587
  const encodeObjects: Promise<EncodeObject[]> = new Promise((resolve) => resolve(msgs));
583
- const stdFee = await client.simulate(globalThis.wallet, () => {
584
- return encodeObjects;
585
- });
588
+
589
+ const stdFee = await client.simulate(
590
+ globalThis.wallet,
591
+ () => {
592
+ return encodeObjects;
593
+ },
594
+ );
586
595
  return JSON.stringify(stdFee);
587
596
  } catch (error) {
588
597
  return wrappedError(error);
@@ -619,9 +628,13 @@ export async function simulateWithdraw(
619
628
  );
620
629
  const msgs: EncodeObject[] = [msg];
621
630
  const encodeObjects: Promise<EncodeObject[]> = new Promise((resolve) => resolve(msgs));
622
- const stdFee = await client.simulate(globalThis.wallet, () => {
623
- return encodeObjects;
624
- });
631
+
632
+ const stdFee = await client.simulate(
633
+ globalThis.wallet,
634
+ () => {
635
+ return encodeObjects;
636
+ },
637
+ );
625
638
  return encodeJson(stdFee);
626
639
  } catch (error) {
627
640
  return wrappedError(error);
@@ -662,6 +675,7 @@ export async function simulateTransferNativeToken(
662
675
  );
663
676
  const msgs: EncodeObject[] = [msg];
664
677
  const encodeObjects: Promise<EncodeObject[]> = new Promise((resolve) => resolve(msgs));
678
+
665
679
  const stdFee = await client.simulate(
666
680
  globalThis.wallet,
667
681
  () => {
@@ -69,8 +69,8 @@ export class NetworkOptimizer {
69
69
  }
70
70
  const maxHeight = Math.max(...responses.map(({ height }) => height));
71
71
  return responses
72
- // Only consider nodes at `maxHeight`
73
- .filter(({ height }) => height === maxHeight)
72
+ // Only consider nodes at `maxHeight` or `maxHeight - 1`
73
+ .filter(({ height }) => height === maxHeight || height === maxHeight - 1)
74
74
  // Return the endpoint with the fastest response time
75
75
  .sort((a, b) => a.time - b.time)[0]
76
76
  .endpoint;
@@ -105,8 +105,8 @@ export class NetworkOptimizer {
105
105
  }
106
106
  const maxHeight = Math.max(...responses.map(({ height }) => height));
107
107
  return responses
108
- // Only consider nodes at `maxHeight`
109
- .filter(({ height }) => height === maxHeight)
108
+ // Only consider nodes at `maxHeight` or `maxHeight - 1`
109
+ .filter(({ height }) => height === maxHeight || height === maxHeight - 1)
110
110
  // Return the endpoint with the fastest response time
111
111
  .sort((a, b) => a.time - b.time)[0]
112
112
  .endpoint;