@dydxprotocol/v4-client-js 1.19.0 → 1.21.0

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.
@@ -47,31 +47,57 @@ async function test(): Promise<void> {
47
47
  await placeOrder(client, subaccount2, subaccount1, authenticatorID);
48
48
  }
49
49
 
50
- async function removeAuthenticator(client: CompositeClient,subaccount: SubaccountInfo, id: Long): Promise<void> {
50
+ async function removeAuthenticator(
51
+ client: CompositeClient,
52
+ subaccount: SubaccountInfo,
53
+ id: Long,
54
+ ): Promise<void> {
51
55
  await client.removeAuthenticator(subaccount, id);
52
56
  }
53
57
 
54
- async function addAuthenticator(client: CompositeClient, subaccount: SubaccountInfo, authedPubKey:string): Promise<void> {
55
- const subAuthenticators = [{
58
+ async function addAuthenticator(
59
+ client: CompositeClient,
60
+ subaccount: SubaccountInfo,
61
+ authedPubKey: string,
62
+ ): Promise<void> {
63
+ const subAuth = [ {
56
64
  type: AuthenticatorType.SIGNATURE_VERIFICATION,
57
65
  config: authedPubKey,
58
66
  },
59
67
  {
60
- type: AuthenticatorType.MESSAGE_FILTER,
61
- config: toBase64(new TextEncoder().encode("/dydxprotocol.clob.MsgPlaceOrder")),
62
- },
68
+ type: AuthenticatorType.ANY_OF,
69
+ config: [
70
+ {
71
+ type: AuthenticatorType.MESSAGE_FILTER,
72
+ config: toBase64(new TextEncoder().encode('/dydxprotocol.clob.MsgPlaceOrder')),
73
+ },
74
+ {
75
+ type: AuthenticatorType.MESSAGE_FILTER,
76
+ config: toBase64(new TextEncoder().encode('/dydxprotocol.clob.MsgPlaceOrder')),
77
+ },
78
+ ]
79
+ }
63
80
  ];
64
81
 
65
- const jsonString = JSON.stringify(subAuthenticators);
82
+ const jsonString = JSON.stringify(subAuth);
66
83
  const encodedData = new TextEncoder().encode(jsonString);
67
84
 
68
- await client.addAuthenticator(subaccount, AuthenticatorType.ALL_OF, encodedData);
85
+ try {
86
+ await client.addAuthenticator(subaccount, AuthenticatorType.ALL_OF, encodedData);
87
+ } catch (error) {
88
+ console.log(error.message);
89
+ }
69
90
  }
70
91
 
71
- async function placeOrder(client: CompositeClient, fromAccount: SubaccountInfo, forAccount: SubaccountInfo, authenticatorId: Long): Promise<void> {
92
+ async function placeOrder(
93
+ client: CompositeClient,
94
+ fromAccount: SubaccountInfo,
95
+ forAccount: SubaccountInfo,
96
+ authenticatorId: Long,
97
+ ): Promise<void> {
72
98
  try {
73
- const side = OrderSide.BUY
74
- const price = Number("1000");
99
+ const side = OrderSide.BUY;
100
+ const price = Number('1000');
75
101
  const currentBlock = await client.validatorClient.get.latestBlockHeight();
76
102
  const nextValidBlockHeight = currentBlock + 5;
77
103
  const goodTilBlock = nextValidBlockHeight + 10;
@@ -94,7 +120,7 @@ async function placeOrder(client: CompositeClient, fromAccount: SubaccountInfo,
94
120
  {
95
121
  authenticators: [authenticatorId],
96
122
  accountForOrder: forAccount,
97
- }
123
+ },
98
124
  );
99
125
  console.log('**Order Tx**');
100
126
  console.log(Buffer.from(tx.hash).toString('hex'));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dydxprotocol/v4-client-js",
3
- "version": "1.19.0",
3
+ "version": "1.21.0",
4
4
  "description": "General client library for the new dYdX system (v4 decentralized)",
5
5
  "main": "build/src/index.js",
6
6
  "scripts": {
@@ -1,3 +1,5 @@
1
+ import { TextDecoder } from 'util';
2
+
1
3
  import { EncodeObject } from '@cosmjs/proto-signing';
2
4
  import { Account, GasPrice, IndexedTx, StdFee } from '@cosmjs/stargate';
3
5
  import { Method } from '@cosmjs/tendermint-rpc';
@@ -18,6 +20,7 @@ import { bigIntToBytes } from '../lib/helpers';
18
20
  import { isStatefulOrder, verifyOrderFlags } from '../lib/validation';
19
21
  import { GovAddNewMarketParams, OrderFlags } from '../types';
20
22
  import {
23
+ Authenticator,
21
24
  AuthenticatorType,
22
25
  Network,
23
26
  OrderExecution,
@@ -169,7 +172,7 @@ export class CompositeClient {
169
172
  broadcastMode,
170
173
  account,
171
174
  undefined,
172
- authenticators,
175
+ authenticators,
173
176
  );
174
177
  }
175
178
 
@@ -311,9 +314,10 @@ export class CompositeClient {
311
314
  ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
312
315
  // For permissioned orders, use the permissioning account details instead of the subaccount
313
316
  // This allows placing orders on behalf of another account when using permissioned keys
314
- const accountForOrder = permissionedKeysAccountAuth ? permissionedKeysAccountAuth.accountForOrder : subaccount;
317
+ const accountForOrder = permissionedKeysAccountAuth
318
+ ? permissionedKeysAccountAuth.accountForOrder
319
+ : subaccount;
315
320
  const msgs: Promise<EncodeObject[]> = new Promise((resolve, reject) => {
316
-
317
321
  const msg = this.placeShortTermOrderMessage(
318
322
  accountForOrder,
319
323
  marketId,
@@ -1233,7 +1237,13 @@ export class CompositeClient {
1233
1237
  gasAdjustment?: number,
1234
1238
  memo?: string,
1235
1239
  ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
1236
- return this.validatorClient.post.createMarketPermissionless(ticker, subaccount, broadcastMode, gasAdjustment, memo);
1240
+ return this.validatorClient.post.createMarketPermissionless(
1241
+ ticker,
1242
+ subaccount,
1243
+ broadcastMode,
1244
+ gasAdjustment,
1245
+ memo,
1246
+ );
1237
1247
  }
1238
1248
 
1239
1249
  async addAuthenticator(
@@ -1241,17 +1251,60 @@ export class CompositeClient {
1241
1251
  authenticatorType: AuthenticatorType,
1242
1252
  data: Uint8Array,
1243
1253
  ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
1244
- return this.validatorClient.post.addAuthenticator(subaccount, authenticatorType, data)
1254
+ // Validate the provided authenticators before sending to the validator
1255
+ const authenticator: Authenticator = {
1256
+ type: authenticatorType,
1257
+ config: JSON.parse(new TextDecoder().decode(data)),
1258
+ };
1259
+ if (!this.validateAuthenticator(authenticator)) {
1260
+ throw new Error(
1261
+ 'Invalid authenticator, please ensure the authenticator permissions are correct',
1262
+ );
1263
+ }
1264
+
1265
+ return this.validatorClient.post.addAuthenticator(subaccount, authenticatorType, data);
1245
1266
  }
1246
1267
 
1247
1268
  async removeAuthenticator(
1248
1269
  subaccount: SubaccountInfo,
1249
1270
  id: Long,
1250
1271
  ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
1251
- return this.validatorClient.post.removeAuthenticator(subaccount, id)
1272
+ return this.validatorClient.post.removeAuthenticator(subaccount, id);
1252
1273
  }
1253
1274
 
1254
- async getAuthenticators(address: string): Promise<GetAuthenticatorsResponse>{
1275
+ async getAuthenticators(address: string): Promise<GetAuthenticatorsResponse> {
1255
1276
  return this.validatorClient.get.getAuthenticators(address);
1256
1277
  }
1278
+
1279
+ validateAuthenticator(authenticator: Authenticator): boolean {
1280
+ function checkAuthenticator(auth: Authenticator): boolean {
1281
+ if (auth.type === AuthenticatorType.SIGNATURE_VERIFICATION) {
1282
+ return true; // A SignatureVerification authenticator is safe.
1283
+ }
1284
+
1285
+ if (!Array.isArray(auth.config)) {
1286
+ return false; // Unsafe case: a non-array config for a composite authenticator
1287
+ }
1288
+
1289
+ if (auth.type === AuthenticatorType.ANY_OF) {
1290
+ // ANY_OF is safe only if ALL sub-authenticators return true
1291
+ return auth.config.every((nestedAuth) => checkAuthenticator(nestedAuth));
1292
+ }
1293
+
1294
+ if (auth.type === AuthenticatorType.ALL_OF) {
1295
+ // ALL_OF is safe if at least one sub-authenticator returns true
1296
+ return auth.config.some((nestedAuth) => checkAuthenticator(nestedAuth));
1297
+ }
1298
+
1299
+ // If it's a base-case authenticator but not SignatureVerification, it's unsafe
1300
+ return false;
1301
+ }
1302
+
1303
+ // The top-level authenticator must pass validation
1304
+ if (!checkAuthenticator(authenticator)) {
1305
+ return false
1306
+ }
1307
+
1308
+ return true;
1309
+ }
1257
1310
  }
@@ -211,6 +211,11 @@ export enum AuthenticatorType {
211
211
  SUBACCOUNT_FILTER = 'SubaccountFilter',
212
212
  }
213
213
 
214
+ export interface Authenticator {
215
+ type: AuthenticatorType;
216
+ config: string | Authenticator[];
217
+ }
218
+
214
219
  export enum TradingRewardAggregationPeriod {
215
220
  DAILY = 'DAILY',
216
221
  WEEKLY = 'WEEKLY',