@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.
- package/CHANGELOG.md +9 -2
- package/README.md +1 -1
- package/__tests__/clients/composite-client.test.ts +140 -0
- package/build/__tests__/clients/composite-client.test.d.ts +1 -0
- package/build/__tests__/clients/composite-client.test.js +130 -0
- package/build/examples/permissioned_keys_example.js +22 -8
- package/build/src/clients/composite-client.d.ts +2 -1
- package/build/src/clients/composite-client.js +38 -2
- package/build/src/clients/constants.d.ts +4 -0
- package/build/src/clients/constants.js +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/examples/permissioned_keys_example.ts +38 -12
- package/package.json +1 -1
- package/src/clients/composite-client.ts +60 -7
- package/src/clients/constants.ts +5 -0
|
@@ -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(
|
|
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(
|
|
55
|
-
|
|
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.
|
|
61
|
-
config:
|
|
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(
|
|
82
|
+
const jsonString = JSON.stringify(subAuth);
|
|
66
83
|
const encodedData = new TextEncoder().encode(jsonString);
|
|
67
84
|
|
|
68
|
-
|
|
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(
|
|
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(
|
|
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,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
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
}
|
package/src/clients/constants.ts
CHANGED
|
@@ -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',
|