@dydxprotocol/v4-client-js 1.16.3 → 1.18.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.
Files changed (118) hide show
  1. package/CHANGELOG.md +3 -3
  2. package/build/examples/constants.d.ts +1 -0
  3. package/build/examples/constants.js +3 -2
  4. package/build/examples/permissioned_keys_example.d.ts +1 -0
  5. package/build/examples/permissioned_keys_example.js +85 -0
  6. package/build/examples/websocket_orderbook_example.d.ts +1 -0
  7. package/build/examples/websocket_orderbook_example.js +198 -0
  8. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/cosmos/bundle.d.ts +158 -158
  9. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/cosmos/bundle.js +126 -126
  10. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/affiliates/query.lcd.d.ts +12 -0
  11. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/affiliates/query.lcd.js +34 -0
  12. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/blocktime/params.d.ts +21 -0
  13. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/blocktime/params.js +37 -2
  14. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/blocktime/tx.d.ts +34 -1
  15. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/blocktime/tx.js +72 -2
  16. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/blocktime/tx.rpc.msg.d.ts +4 -1
  17. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/blocktime/tx.rpc.msg.js +7 -1
  18. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/bundle.d.ts +2021 -1711
  19. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/bundle.js +272 -266
  20. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/clob/finalize_block.d.ts +23 -0
  21. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/clob/finalize_block.js +64 -0
  22. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/clob/order_removals.d.ts +5 -0
  23. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/clob/order_removals.js +11 -1
  24. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/clob/query.d.ts +31 -0
  25. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/clob/query.js +94 -5
  26. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/clob/query.lcd.d.ts +2 -1
  27. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/clob/query.lcd.js +7 -1
  28. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/clob/query.rpc.Query.d.ts +5 -1
  29. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/clob/query.rpc.Query.js +10 -1
  30. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/clob/streaming.d.ts +6 -1
  31. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/clob/streaming.js +19 -2
  32. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/indexer/events/events.d.ts +79 -6
  33. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/indexer/events/events.js +78 -2
  34. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/lcd.d.ts +1 -0
  35. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/lcd.js +4 -1
  36. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/listing/genesis.d.ts +4 -0
  37. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/listing/genesis.js +11 -2
  38. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/listing/query.lcd.d.ts +2 -1
  39. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/listing/query.lcd.js +7 -1
  40. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/listing/tx.d.ts +39 -0
  41. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/listing/tx.js +72 -2
  42. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/listing/tx.rpc.msg.d.ts +7 -1
  43. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/listing/tx.rpc.msg.js +7 -1
  44. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/perpetuals/query.d.ts +25 -0
  45. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/perpetuals/query.js +64 -2
  46. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/perpetuals/query.lcd.d.ts +2 -1
  47. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/perpetuals/query.lcd.js +7 -1
  48. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/perpetuals/query.rpc.Query.d.ts +5 -1
  49. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/perpetuals/query.rpc.Query.js +10 -1
  50. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/prices/market_param.d.ts +8 -0
  51. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/prices/market_param.js +1 -1
  52. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/prices/market_price.d.ts +3 -0
  53. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/prices/market_price.js +1 -1
  54. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/prices/query.d.ts +34 -0
  55. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/prices/query.js +64 -2
  56. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/prices/query.lcd.d.ts +2 -1
  57. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/prices/query.lcd.js +7 -1
  58. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/prices/query.rpc.Query.d.ts +5 -1
  59. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/prices/query.rpc.Query.js +10 -1
  60. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/prices/streaming.d.ts +23 -0
  61. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/prices/streaming.js +81 -0
  62. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/revshare/query.d.ts +25 -1
  63. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/revshare/query.js +63 -2
  64. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/revshare/query.lcd.d.ts +2 -1
  65. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/revshare/query.lcd.js +7 -1
  66. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/revshare/query.rpc.Query.d.ts +5 -1
  67. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/revshare/query.rpc.Query.js +10 -1
  68. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/revshare/tx.rpc.msg.d.ts +1 -1
  69. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/rpc.query.d.ts +4 -0
  70. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/subaccounts/streaming.d.ts +1 -1
  71. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/subaccounts/streaming.js +5 -5
  72. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/vault/params.d.ts +21 -0
  73. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/vault/params.js +55 -3
  74. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/vault/query.d.ts +1 -6
  75. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/vault/query.js +4 -12
  76. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/vault/query.lcd.d.ts +1 -2
  77. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/vault/query.lcd.js +1 -13
  78. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/vault/tx.d.ts +51 -24
  79. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/dydxprotocol/vault/tx.js +98 -46
  80. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/gogoproto/bundle.js +2 -2
  81. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/google/bundle.d.ts +174 -174
  82. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/google/bundle.js +12 -12
  83. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/tendermint/bundle.d.ts +365 -365
  84. package/build/node_modules/@dydxprotocol/v4-proto/src/codegen/tendermint/bundle.js +21 -21
  85. package/build/src/clients/composite-client.d.ts +12 -3
  86. package/build/src/clients/composite-client.js +22 -8
  87. package/build/src/clients/constants.d.ts +10 -0
  88. package/build/src/clients/constants.js +17 -4
  89. package/build/src/clients/lib/registry.js +26 -22
  90. package/build/src/clients/modules/composer.d.ts +3 -0
  91. package/build/src/clients/modules/composer.js +23 -1
  92. package/build/src/clients/modules/get.d.ts +2 -0
  93. package/build/src/clients/modules/get.js +9 -1
  94. package/build/src/clients/modules/local-wallet.d.ts +4 -4
  95. package/build/src/clients/modules/local-wallet.js +3 -3
  96. package/build/src/clients/modules/post.d.ts +4 -2
  97. package/build/src/clients/modules/post.js +15 -6
  98. package/build/src/clients/modules/signer.d.ts +5 -3
  99. package/build/src/clients/modules/signer.js +53 -14
  100. package/build/src/clients/modules/utility.d.ts +7 -1
  101. package/build/src/clients/modules/utility.js +10 -1
  102. package/build/src/clients/types.d.ts +22 -0
  103. package/build/src/clients/types.js +19 -2
  104. package/build/tsconfig.tsbuildinfo +1 -1
  105. package/examples/constants.ts +2 -0
  106. package/examples/permissioned_keys_example.ts +110 -0
  107. package/examples/websocket_orderbook_example.ts +252 -0
  108. package/package.json +2 -2
  109. package/src/clients/composite-client.ts +40 -3
  110. package/src/clients/constants.ts +16 -1
  111. package/src/clients/lib/registry.ts +8 -0
  112. package/src/clients/modules/composer.ts +39 -0
  113. package/src/clients/modules/get.ts +16 -0
  114. package/src/clients/modules/local-wallet.ts +6 -6
  115. package/src/clients/modules/post.ts +44 -1
  116. package/src/clients/modules/signer.ts +79 -13
  117. package/src/clients/modules/utility.ts +16 -1
  118. package/src/clients/types.ts +25 -0
@@ -15,6 +15,8 @@ export const DYDX_LOCAL_ADDRESS = 'dydx199tqg4wdlnu4qjlxchpd7seg454937hjrknju4';
15
15
  export const DYDX_LOCAL_MNEMONIC =
16
16
  'merge panther lobster crazy road hollow amused security before critic about cliff exhibit cause coyote talent happy where lion river tobacco option coconut small';
17
17
 
18
+ export const DYDX_TEST_MNEMONIC_2 = 'movie yard still copper exile wear brisk chest ride dizzy novel future menu finish radar lunar claim hub middle force turtle mouse frequent embark';
19
+
18
20
  export const MARKET_BTC_USD: string = 'BTC-USD';
19
21
  export const PERPETUAL_PAIR_BTC_USD: number = 0;
20
22
 
@@ -0,0 +1,110 @@
1
+ import { TextEncoder } from 'util';
2
+
3
+ import { toBase64 } from '@cosmjs/encoding';
4
+ import { Order_TimeInForce } from '@dydxprotocol/v4-proto/src/codegen/dydxprotocol/clob/order';
5
+
6
+ import { BECH32_PREFIX } from '../src';
7
+ import { CompositeClient } from '../src/clients/composite-client';
8
+ import { AuthenticatorType, Network, OrderSide, SelectedGasDenom } from '../src/clients/constants';
9
+ import LocalWallet from '../src/clients/modules/local-wallet';
10
+ import { SubaccountInfo } from '../src/clients/subaccount';
11
+ import { DYDX_TEST_MNEMONIC, DYDX_TEST_MNEMONIC_2 } from './constants';
12
+
13
+ async function test(): Promise<void> {
14
+ const wallet1 = await LocalWallet.fromMnemonic(DYDX_TEST_MNEMONIC, BECH32_PREFIX);
15
+ const wallet2 = await LocalWallet.fromMnemonic(DYDX_TEST_MNEMONIC_2, BECH32_PREFIX);
16
+
17
+ const network = Network.staging();
18
+ const client = await CompositeClient.connect(network);
19
+ client.setSelectedGasDenom(SelectedGasDenom.NATIVE);
20
+
21
+ console.log('**Client**');
22
+ console.log(client);
23
+
24
+ const subaccount1 = new SubaccountInfo(wallet1, 0);
25
+ const subaccount2 = new SubaccountInfo(wallet2, 0);
26
+
27
+ // Change second wallet pubkey
28
+ // Add an authenticator to allow wallet2 to place orders
29
+ console.log("** Adding authenticator **");
30
+ await addAuthenticator(client, subaccount1, wallet2.pubKey!.value);
31
+
32
+ const authenticators = await client.getAuthenticators(wallet1.address!);
33
+ // Last element in authenticators array is the most recently created
34
+ const lastElement = authenticators.accountAuthenticators.length - 1;
35
+ const authenticatorID = authenticators.accountAuthenticators[lastElement].id;
36
+
37
+ // Placing order using subaccount2 for subaccount1 succeeds
38
+ console.log("** Placing order with authenticator **");
39
+ await placeOrder(client, subaccount2, subaccount1, authenticatorID);
40
+
41
+ // Remove authenticator
42
+ console.log("** Removing authenticator **");
43
+ await removeAuthenticator(client, subaccount1, authenticatorID);
44
+
45
+ // Placing an order using subaccount2 will now fail
46
+ console.log("** Placing order with invalid authenticator should fail **");
47
+ await placeOrder(client, subaccount2, subaccount1, authenticatorID);
48
+ }
49
+
50
+ async function removeAuthenticator(client: CompositeClient,subaccount: SubaccountInfo, id: Long): Promise<void> {
51
+ await client.removeAuthenticator(subaccount, id);
52
+ }
53
+
54
+ async function addAuthenticator(client: CompositeClient, subaccount: SubaccountInfo, authedPubKey:string): Promise<void> {
55
+ const subAuthenticators = [{
56
+ type: AuthenticatorType.SIGNATURE_VERIFICATION,
57
+ config: authedPubKey,
58
+ },
59
+ {
60
+ type: AuthenticatorType.MESSAGE_FILTER,
61
+ config: toBase64(new TextEncoder().encode("/dydxprotocol.clob.MsgPlaceOrder")),
62
+ },
63
+ ];
64
+
65
+ const jsonString = JSON.stringify(subAuthenticators);
66
+ const encodedData = new TextEncoder().encode(jsonString);
67
+
68
+ await client.addAuthenticator(subaccount, AuthenticatorType.ALL_OF, encodedData);
69
+ }
70
+
71
+ async function placeOrder(client: CompositeClient, fromAccount: SubaccountInfo, forAccount: SubaccountInfo, authenticatorId: Long): Promise<void> {
72
+ try {
73
+ const side = OrderSide.BUY
74
+ const price = Number("1000");
75
+ const currentBlock = await client.validatorClient.get.latestBlockHeight();
76
+ const nextValidBlockHeight = currentBlock + 5;
77
+ const goodTilBlock = nextValidBlockHeight + 10;
78
+
79
+ const timeInForce = Order_TimeInForce.TIME_IN_FORCE_UNSPECIFIED;
80
+
81
+ const clientId = Math.floor(Math.random() * 10000);
82
+
83
+ const tx = await client.placeShortTermOrder(
84
+ fromAccount,
85
+ 'ETH-USD',
86
+ side,
87
+ price,
88
+ 0.01,
89
+ clientId,
90
+ goodTilBlock,
91
+ timeInForce,
92
+ false,
93
+ undefined,
94
+ {
95
+ authenticators: [authenticatorId],
96
+ accountForOrder: forAccount,
97
+ }
98
+ );
99
+ console.log('**Order Tx**');
100
+ console.log(Buffer.from(tx.hash).toString('hex'));
101
+ } catch (error) {
102
+ console.log(error.message);
103
+ }
104
+ }
105
+
106
+ test()
107
+ .then(() => {})
108
+ .catch((error) => {
109
+ console.log(error.message);
110
+ });
@@ -0,0 +1,252 @@
1
+ import { Network } from '../src/clients/constants';
2
+ import { SocketClient } from '../src/clients/socket-client';
3
+
4
+ function test(): void {
5
+ let orderBookBidList: [number, number, number][] = [];
6
+ let orderBookAskList: [number, number, number][] = [];
7
+
8
+ const mySocket = new SocketClient(
9
+ Network.mainnet().indexerConfig,
10
+ () => {
11
+ console.log('socket opened');
12
+
13
+ mySocket.subscribeToOrderbook('ETH-USD');
14
+ },
15
+ () => {
16
+ console.log('socket closed');
17
+ },
18
+ (message) => {
19
+ try {
20
+ if (typeof message.data === "string") {
21
+ const jsonString = message.data;
22
+ const parsingData = JSON.parse(jsonString);
23
+ const messageId = parsingData.message_id;
24
+ const orderBookDataList = parsingData.contents;
25
+
26
+ if (orderBookDataList instanceof Array) {
27
+ // common orderBook data;
28
+ [orderBookBidList, orderBookAskList] = updateOrderBook(
29
+ orderBookDataList,
30
+ orderBookBidList,
31
+ orderBookAskList,
32
+ messageId,
33
+ );
34
+
35
+ // sort
36
+ orderBookBidList = sortByNthElementDesc(
37
+ orderBookBidList,
38
+ 0,
39
+ );
40
+ orderBookAskList = sortByNthElementAsc(
41
+ orderBookAskList,
42
+ 0,
43
+ );
44
+
45
+ // resolving crossed orderBook
46
+ if (
47
+ orderBookBidList &&
48
+ orderBookAskList &&
49
+ orderBookBidList.length > 0 &&
50
+ orderBookAskList.length > 0 &&
51
+ orderBookBidList[0][0] >= orderBookAskList[0][0]
52
+ ) {
53
+ [orderBookBidList, orderBookAskList] =
54
+ resolveCrossedOrderBook(
55
+ orderBookBidList,
56
+ orderBookAskList,
57
+ );
58
+ }
59
+
60
+ printOrderBook(orderBookBidList, orderBookAskList);
61
+
62
+ if (orderBookBidList.length > 300) {
63
+ orderBookBidList.splice(50);
64
+ }
65
+
66
+ if (orderBookAskList.length > 300) {
67
+ orderBookAskList.splice(50);
68
+ }
69
+ } else if (
70
+ orderBookDataList !== null &&
71
+ orderBookDataList !== undefined
72
+ ) {
73
+ // initial OrderBook data
74
+ setInitialOrderBook(
75
+ orderBookDataList,
76
+ orderBookBidList,
77
+ orderBookAskList,
78
+ messageId,
79
+ );
80
+ }
81
+ }
82
+ } catch (e) {
83
+ console.error('Error parsing JSON message:', e);
84
+ }
85
+ },
86
+ (event) => {
87
+ console.error('Encountered error:', event.message);
88
+ },
89
+ );
90
+
91
+ mySocket.connect();
92
+ }
93
+
94
+ const sortByNthElementAsc = (arr: [number, number, number][], n: number): [number, number, number][] => {
95
+ return arr.sort((a, b) => {
96
+ if (a[n] < b[n]) return -1;
97
+ if (a[n] > b[n]) return 1;
98
+ return 0;
99
+ });
100
+ };
101
+ const sortByNthElementDesc = (arr: [number, number, number][], n: number): [number, number, number][] => {
102
+ return arr.sort((a, b) => {
103
+ if (a[n] > b[n]) return -1;
104
+ if (a[n] < b[n]) return 1;
105
+ return 0;
106
+ });
107
+ };
108
+
109
+ const printOrderBook = (
110
+ orderBookBidList: [number, number, number][],
111
+ orderBookAskList: [number, number, number][],
112
+ ): void => {
113
+ // print
114
+ console.log(`OrderBook for ETH-USD:`);
115
+ console.log(`Price Qty`);
116
+ for (let i = 4; i > -1; i--) {
117
+ const priceStr = String(orderBookAskList[i][0]);
118
+ const spaces = createSpaces(10 - priceStr.length);
119
+ console.log(`${priceStr}${spaces}${orderBookAskList[i][1]}`);
120
+ }
121
+ console.log('---------------------');
122
+ for (let i = 0; i < 5; i++) {
123
+ const priceStr = String(orderBookBidList[i][0]);
124
+ const spaces = createSpaces(10 - priceStr.length);
125
+ console.log(`${priceStr}${spaces}${orderBookBidList[i][1]}`);
126
+ }
127
+ console.log('');
128
+ };
129
+
130
+ function createSpaces(count: number): string {
131
+ if(count <= 0 ){
132
+ return "";
133
+ }
134
+
135
+ let spaces = "";
136
+ for (let i = 0; i < count; i++) {
137
+ spaces += " ";
138
+ }
139
+ return spaces;
140
+ }
141
+
142
+ const resolveCrossedOrderBook = (
143
+ orderBookBidList: [number, number, number][],
144
+ orderBookAskList: [number, number, number][],
145
+ ): [[number, number, number][], [number, number, number][]] => {
146
+ while (orderBookBidList[0][0] >= orderBookAskList[0][0]) {
147
+ if (orderBookBidList[0][2] < orderBookAskList[0][2]) {
148
+ orderBookBidList.shift();
149
+ } else if (orderBookBidList[0][2] > orderBookAskList[0][2]) {
150
+ orderBookAskList.shift();
151
+ } else {
152
+ if (orderBookBidList[0][1] > orderBookAskList[0][1]) {
153
+ orderBookBidList[0][1] -= orderBookAskList[0][1];
154
+ orderBookAskList.shift();
155
+ } else if (orderBookBidList[0][1] < orderBookAskList[0][1]) {
156
+ orderBookAskList[0][1] -= orderBookBidList[0][1];
157
+ orderBookBidList.shift();
158
+ } else {
159
+ orderBookAskList.shift();
160
+ orderBookBidList.shift();
161
+ }
162
+ }
163
+ }
164
+
165
+ return [orderBookBidList, orderBookAskList];
166
+ };
167
+ const setInitialOrderBook = (
168
+ orderBookDataList: { bids: []; asks: [] },
169
+ orderBookBidList: [number, number, number][],
170
+ orderBookAskList: [number, number, number][],
171
+ messageId: number,
172
+ ): void => {
173
+ orderBookDataList.bids.forEach((item: { price: string; size: string }) => {
174
+ orderBookBidList.push([Number(item.price), Number(item.size), messageId]);
175
+ });
176
+
177
+ orderBookDataList.asks.forEach((item: { price: string; size: string }) => {
178
+ orderBookAskList.push([Number(item.price), Number(item.size), messageId]);
179
+ });
180
+ };
181
+
182
+ const updateOrderBook = (
183
+ orderBookDataList: { bids: [[]]; asks: [[]] }[],
184
+ orderBookBidList: [number, number, number][],
185
+ orderBookAskList: [number, number, number][],
186
+ messageId: number,
187
+ ): [[number, number, number][], [number, number, number][]] => {
188
+ orderBookDataList.forEach((entry: { bids: [[]]; asks: [[]] }) => {
189
+ if (entry.bids !== null && entry.bids !== undefined) {
190
+ const flattened = entry.bids.reduce((acc: any[], val: any[]) => acc.concat(val), []);
191
+ const entryBidPrice = Number(flattened[0]);
192
+ const entryBidSize = Number(flattened[1]);
193
+
194
+ // remove prices with zero Qty
195
+ if (entryBidSize === 0) {
196
+ for (let i = orderBookBidList.length - 1; i >= 0; i--) {
197
+ if (orderBookBidList[i][0] === entryBidPrice) {
198
+ orderBookBidList.splice(i, 1);
199
+ }
200
+ }
201
+ } else {
202
+ // The price that already exists in the order book is modified only Qty
203
+ if (
204
+ orderBookBidList.some((innerArray) => innerArray[0] === entryBidPrice)
205
+ ) {
206
+ orderBookBidList.forEach((item, index) => {
207
+ if (item[0] === entryBidPrice) {
208
+ orderBookBidList[index][1] = entryBidSize;
209
+ orderBookBidList[index][2] = messageId;
210
+ }
211
+ });
212
+ } else {
213
+ // Add new data to order book
214
+ orderBookBidList.push([entryBidPrice, entryBidSize, messageId]);
215
+ }
216
+ }
217
+ }
218
+ if (entry.asks !== null && entry.asks !== undefined) {
219
+ const flattened = entry.asks.reduce((acc: any[], val: any[]) => acc.concat(val), []);
220
+ const entryAskPrice = Number(flattened[0]);
221
+ const entryAskSize = Number(flattened[1]);
222
+
223
+ if (entryAskSize === 0) {
224
+ // remove prices with zero Qty
225
+ for (let i = orderBookAskList.length - 1; i >= 0; i--) {
226
+ if (orderBookAskList[i][0] === entryAskPrice) {
227
+ orderBookAskList.splice(i, 1);
228
+ }
229
+ }
230
+ } else {
231
+ // The price that already exists in the order book is modified only Qty
232
+ if (
233
+ orderBookAskList.some((innerArray) => innerArray[0] === entryAskPrice)
234
+ ) {
235
+ orderBookAskList.forEach((item, index) => {
236
+ if (item[0] === entryAskPrice) {
237
+ orderBookAskList[index][1] = entryAskSize;
238
+ orderBookAskList[index][2] = messageId;
239
+ }
240
+ });
241
+ } else {
242
+ // Add new data to order book
243
+ orderBookAskList.push([entryAskPrice, entryAskSize, messageId]);
244
+ }
245
+ }
246
+ }
247
+ });
248
+
249
+ return [orderBookBidList, orderBookAskList];
250
+ };
251
+
252
+ test();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dydxprotocol/v4-client-js",
3
- "version": "1.16.3",
3
+ "version": "1.18.0",
4
4
  "description": "General client library for the new dYdX system (v4 decentralized)",
5
5
  "main": "build/src/index.js",
6
6
  "scripts": {
@@ -38,8 +38,8 @@
38
38
  "@cosmjs/stargate": "^0.32.1",
39
39
  "@cosmjs/tendermint-rpc": "^0.32.1",
40
40
  "@cosmjs/utils": "^0.32.1",
41
+ "@dydxprotocol/v4-proto": "8.0.0",
41
42
  "@osmonauts/lcd": "^0.6.0",
42
- "@dydxprotocol/v4-proto": "7.0.0-dev.0",
43
43
  "@scure/bip32": "^1.1.5",
44
44
  "@scure/bip39": "^1.1.1",
45
45
  "axios": "1.1.3",
@@ -5,6 +5,7 @@ import {
5
5
  BroadcastTxAsyncResponse,
6
6
  BroadcastTxSyncResponse,
7
7
  } from '@cosmjs/tendermint-rpc/build/tendermint37';
8
+ import { GetAuthenticatorsResponse } from '@dydxprotocol/v4-proto/src/codegen/dydxprotocol/accountplus/query';
8
9
  import {
9
10
  Order_ConditionType,
10
11
  Order_TimeInForce,
@@ -17,6 +18,7 @@ import { bigIntToBytes } from '../lib/helpers';
17
18
  import { isStatefulOrder, verifyOrderFlags } from '../lib/validation';
18
19
  import { GovAddNewMarketParams, OrderFlags } from '../types';
19
20
  import {
21
+ AuthenticatorType,
20
22
  Network,
21
23
  OrderExecution,
22
24
  OrderSide,
@@ -66,6 +68,11 @@ export interface OrderBatchWithMarketId {
66
68
  clientIds: number[];
67
69
  }
68
70
 
71
+ export interface PermissionedKeysAccountAuth {
72
+ authenticators: Long[];
73
+ accountForOrder: SubaccountInfo;
74
+ }
75
+
69
76
  export class CompositeClient {
70
77
  public readonly network: Network;
71
78
  public gasDenom: SelectedGasDenom = SelectedGasDenom.USDC;
@@ -151,6 +158,7 @@ export class CompositeClient {
151
158
  memo?: string,
152
159
  broadcastMode?: BroadcastMode,
153
160
  account?: () => Promise<Account>,
161
+ authenticators?: Long[],
154
162
  ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
155
163
  return this.validatorClient.post.send(
156
164
  wallet,
@@ -160,6 +168,8 @@ export class CompositeClient {
160
168
  memo,
161
169
  broadcastMode,
162
170
  account,
171
+ undefined,
172
+ authenticators,
163
173
  );
164
174
  }
165
175
 
@@ -297,10 +307,15 @@ export class CompositeClient {
297
307
  timeInForce: Order_TimeInForce,
298
308
  reduceOnly: boolean,
299
309
  memo?: string,
310
+ permissionedKeysAccountAuth?: PermissionedKeysAccountAuth,
300
311
  ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
312
+ // For permissioned orders, use the permissioning account details instead of the subaccount
313
+ // This allows placing orders on behalf of another account when using permissioned keys
314
+ const accountForOrder = permissionedKeysAccountAuth ? permissionedKeysAccountAuth.accountForOrder : subaccount;
301
315
  const msgs: Promise<EncodeObject[]> = new Promise((resolve, reject) => {
316
+
302
317
  const msg = this.placeShortTermOrderMessage(
303
- subaccount,
318
+ accountForOrder,
304
319
  marketId,
305
320
  side,
306
321
  price,
@@ -311,14 +326,16 @@ export class CompositeClient {
311
326
  reduceOnly,
312
327
  );
313
328
  msg
314
- .then((it) => resolve([it]))
329
+ .then((it) => {
330
+ resolve([it]);
331
+ })
315
332
  .catch((err) => {
316
333
  console.log(err);
317
334
  reject(err);
318
335
  });
319
336
  });
320
337
  const account: Promise<Account> = this.validatorClient.post.account(
321
- subaccount.address,
338
+ accountForOrder.address,
322
339
  undefined,
323
340
  );
324
341
  return this.send(
@@ -329,6 +346,7 @@ export class CompositeClient {
329
346
  memo,
330
347
  undefined,
331
348
  () => account,
349
+ permissionedKeysAccountAuth?.authenticators,
332
350
  );
333
351
  }
334
352
 
@@ -1217,4 +1235,23 @@ export class CompositeClient {
1217
1235
  ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
1218
1236
  return this.validatorClient.post.createMarketPermissionless(ticker, subaccount, broadcastMode, gasAdjustment, memo);
1219
1237
  }
1238
+
1239
+ async addAuthenticator(
1240
+ subaccount: SubaccountInfo,
1241
+ authenticatorType: AuthenticatorType,
1242
+ data: Uint8Array,
1243
+ ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
1244
+ return this.validatorClient.post.addAuthenticator(subaccount, authenticatorType, data)
1245
+ }
1246
+
1247
+ async removeAuthenticator(
1248
+ subaccount: SubaccountInfo,
1249
+ id: Long,
1250
+ ): Promise<BroadcastTxAsyncResponse | BroadcastTxSyncResponse | IndexedTx> {
1251
+ return this.validatorClient.post.removeAuthenticator(subaccount, id)
1252
+ }
1253
+
1254
+ async getAuthenticators(address: string): Promise<GetAuthenticatorsResponse>{
1255
+ return this.validatorClient.get.getAuthenticators(address);
1256
+ }
1220
1257
  }
@@ -116,6 +116,10 @@ export const TYPE_URL_MSG_UNDELEGATE = '/cosmos.staking.v1beta1.MsgUndelegate';
116
116
  export const TYPE_URL_MSG_WITHDRAW_DELEGATOR_REWARD =
117
117
  '/cosmos.distribution.v1beta1.MsgWithdrawDelegatorReward';
118
118
 
119
+ // x/accountplus
120
+ export const TYPE_URL_MSG_ADD_AUTHENTICATOR = '/dydxprotocol.accountplus.MsgAddAuthenticator'
121
+ export const TYPE_URL_MSG_REMOVE_AUTHENTICATOR = '/dydxprotocol.accountplus.MsgRemoveAuthenticator'
122
+
119
123
  // ------------ Chain Constants ------------
120
124
  // The following are same across different networks / deployments.
121
125
  export const GOV_MODULE_ADDRESS = 'dydx10d07y265gmmuvt4z0w9aw880jnsr700jnmapky';
@@ -196,6 +200,17 @@ export enum PnlTickInterval {
196
200
  day = 'day',
197
201
  }
198
202
 
203
+ // ----------- Authenticators -------------
204
+
205
+ export enum AuthenticatorType {
206
+ ALL_OF = 'AllOf',
207
+ ANY_OF = 'AnyOf',
208
+ SIGNATURE_VERIFICATION = 'SignatureVerification',
209
+ MESSAGE_FILTER = 'MessageFilter',
210
+ CLOB_PAIR_ID_FILTER = 'ClobPairIdFilter',
211
+ SUBACCOUNT_FILTER = 'SubaccountFilter',
212
+ }
213
+
199
214
  export enum TradingRewardAggregationPeriod {
200
215
  DAILY = 'DAILY',
201
216
  WEEKLY = 'WEEKLY',
@@ -285,7 +300,7 @@ export class Network {
285
300
  const indexerConfig = new IndexerConfig(IndexerApiHost.STAGING, IndexerWSHost.STAGING);
286
301
  const validatorConfig = new ValidatorConfig(
287
302
  ValidatorApiHost.STAGING,
288
- TESTNET_CHAIN_ID,
303
+ STAGING_CHAIN_ID,
289
304
  {
290
305
  CHAINTOKEN_DENOM: 'adv4tnt',
291
306
  USDC_DENOM: 'ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5',
@@ -1,5 +1,6 @@
1
1
  import { GeneratedType, Registry } from '@cosmjs/proto-signing';
2
2
  import { defaultRegistryTypes } from '@cosmjs/stargate';
3
+ import { MsgAddAuthenticator, MsgRemoveAuthenticator } from '@dydxprotocol/v4-proto/src/codegen/dydxprotocol/accountplus/tx';
3
4
  import { MsgRegisterAffiliate } from '@dydxprotocol/v4-proto/src/codegen/dydxprotocol/affiliates/tx';
4
5
  import {
5
6
  MsgPlaceOrder,
@@ -38,6 +39,8 @@ import {
38
39
  TYPE_URL_MSG_WITHDRAW_FROM_MEGAVAULT,
39
40
  TYPE_URL_MSG_REGISTER_AFFILIATE,
40
41
  TYPE_URL_MSG_CREATE_MARKET_PERMISSIONLESS,
42
+ TYPE_URL_MSG_ADD_AUTHENTICATOR,
43
+ TYPE_URL_MSG_REMOVE_AUTHENTICATOR,
41
44
  } from '../constants';
42
45
 
43
46
  export const registry: ReadonlyArray<[string, GeneratedType]> = [];
@@ -74,6 +77,11 @@ export function generateRegistry(): Registry {
74
77
  // affiliates
75
78
  [TYPE_URL_MSG_REGISTER_AFFILIATE, MsgRegisterAffiliate as GeneratedType],
76
79
 
80
+
81
+ // authentication
82
+ [TYPE_URL_MSG_ADD_AUTHENTICATOR, MsgAddAuthenticator as GeneratedType],
83
+ [TYPE_URL_MSG_REMOVE_AUTHENTICATOR, MsgRemoveAuthenticator as GeneratedType],
84
+
77
85
  // default types
78
86
  ...defaultRegistryTypes,
79
87
  ]);
@@ -7,6 +7,7 @@ import {
7
7
  MsgDelegate,
8
8
  MsgUndelegate,
9
9
  } from '@dydxprotocol/v4-proto/src/codegen/cosmos/staking/v1beta1/tx';
10
+ import { MsgAddAuthenticator, MsgRemoveAuthenticator } from '@dydxprotocol/v4-proto/src/codegen/dydxprotocol/accountplus/tx';
10
11
  import { MsgRegisterAffiliate } from '@dydxprotocol/v4-proto/src/codegen/dydxprotocol/affiliates/tx';
11
12
  import { ClobPair_Status } from '@dydxprotocol/v4-proto/src/codegen/dydxprotocol/clob/clob_pair';
12
13
  import {
@@ -52,6 +53,9 @@ import {
52
53
  TYPE_URL_MSG_DEPOSIT_TO_MEGAVAULT,
53
54
  TYPE_URL_MSG_WITHDRAW_FROM_MEGAVAULT,
54
55
  TYPE_URL_MSG_CREATE_MARKET_PERMISSIONLESS,
56
+ TYPE_URL_MSG_ADD_AUTHENTICATOR,
57
+ TYPE_URL_MSG_REMOVE_AUTHENTICATOR,
58
+ AuthenticatorType,
55
59
  } from '../constants';
56
60
  import { DenomConfig } from '../types';
57
61
  import {
@@ -105,6 +109,7 @@ export class Composer {
105
109
  orderFlags,
106
110
  clobPairId,
107
111
  };
112
+
108
113
  const order: Order = {
109
114
  orderId,
110
115
  side,
@@ -575,6 +580,40 @@ export class Composer {
575
580
  }
576
581
  }
577
582
 
583
+ // ----------- x/accountplus --------
584
+
585
+ public composeMsgAddAuthenticator(
586
+ address: string,
587
+ authenticatorType: AuthenticatorType,
588
+ data: Uint8Array,
589
+ ): EncodeObject {
590
+ const msg: MsgAddAuthenticator = {
591
+ sender: address,
592
+ authenticatorType,
593
+ data,
594
+ }
595
+
596
+ return {
597
+ typeUrl: TYPE_URL_MSG_ADD_AUTHENTICATOR,
598
+ value: msg,
599
+ }
600
+ }
601
+
602
+ public composeMsgRemoveAuthenticator(
603
+ address: string,
604
+ id: Long,
605
+ ): EncodeObject {
606
+ const msg: MsgRemoveAuthenticator = {
607
+ sender: address,
608
+ id,
609
+ }
610
+
611
+ return {
612
+ typeUrl: TYPE_URL_MSG_REMOVE_AUTHENTICATOR,
613
+ value: msg,
614
+ }
615
+ }
616
+
578
617
  // ------------ util ------------
579
618
  public validateGoodTilBlockAndTime(
580
619
  orderFlags: number,
@@ -7,6 +7,7 @@ import {
7
7
  TxExtension,
8
8
  QueryAbciResponse,
9
9
  } from '@cosmjs/stargate';
10
+ import { GetAuthenticatorsRequest, GetAuthenticatorsResponse } from '@dydxprotocol/v4-proto/src/codegen/dydxprotocol/accountplus/query';
10
11
  import * as AuthModule from 'cosmjs-types/cosmos/auth/v1beta1/query';
11
12
  import * as BankModule from 'cosmjs-types/cosmos/bank/v1beta1/query';
12
13
  import { Any } from 'cosmjs-types/google/protobuf/any';
@@ -610,6 +611,21 @@ export class Get {
610
611
  return AffiliateModule.AffiliateWhitelistResponse.decode(data);
611
612
  }
612
613
 
614
+ async getAuthenticators(address: string): Promise<GetAuthenticatorsResponse> {
615
+ const requestData = Uint8Array.from(
616
+ GetAuthenticatorsRequest.encode({
617
+ account: address,
618
+ }).finish(),
619
+ );
620
+
621
+ const data = await this.sendQuery(
622
+ '/dydxprotocol.accountplus.Query/GetAuthenticators',
623
+ requestData,
624
+ );
625
+
626
+ return GetAuthenticatorsResponse.decode(data);
627
+ }
628
+
613
629
  private async sendQuery(requestUrl: string, requestData: Uint8Array): Promise<Uint8Array> {
614
630
  // eslint-disable-next-line max-len
615
631
  const resp: QueryAbciResponse = await this.stargateQueryClient.queryAbci(