@dydxprotocol/v4-client-js 3.0.1 → 3.0.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dydxprotocol/v4-client-js",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "General client library for the new dYdX system (v4 decentralized)",
5
5
  "main": "build/cjs/src/index.js",
6
6
  "module": "build/esm/src/index.js",
@@ -1011,7 +1011,7 @@ export class Post {
1011
1011
  undefined,
1012
1012
  Method.BroadcastTxSync,
1013
1013
  undefined,
1014
- undefined,
1014
+ 3,
1015
1015
  );
1016
1016
  }
1017
1017
  }
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@ export * from './types';
4
4
  // Utility functions.
5
5
  export * as helpers from './lib/helpers';
6
6
  export * as onboarding from './lib/onboarding';
7
+ export * as tradingKeyUtils from './lib/trading-key-utils';
7
8
  export * as utils from './lib/utils';
8
9
  export * as validation from './lib/validation';
9
10
 
@@ -0,0 +1,136 @@
1
+ import { fromBase64, toBase64, toBech32, toHex } from '@cosmjs/encoding';
2
+ import { rawSecp256k1PubkeyToRawAddress } from '@cosmjs/tendermint-rpc';
3
+ import { generateMnemonic } from '@scure/bip39';
4
+ import { wordlist } from '@scure/bip39/wordlists/english';
5
+
6
+ import {
7
+ Authenticator,
8
+ AuthenticatorType,
9
+ TYPE_URL_BATCH_CANCEL,
10
+ TYPE_URL_MSG_CANCEL_ORDER,
11
+ TYPE_URL_MSG_PLACE_ORDER,
12
+ } from '../clients/constants';
13
+ import { type Get } from '../clients/modules/get';
14
+ import LocalWallet from '../clients/modules/local-wallet';
15
+ import { BECH32_PREFIX } from './constants';
16
+ import { deriveHDKeyFromMnemonic } from './onboarding';
17
+
18
+ export const createNewRandomDydxWallet = async (): Promise<
19
+ { privateKeyHex: string; mnemonic: string; publicKey: string; address: string } | undefined
20
+ > => {
21
+ const mnemonic = generateMnemonic(wordlist, 128);
22
+ const { privateKey: privateKeyRaw } = deriveHDKeyFromMnemonic(mnemonic);
23
+ const wallet = await LocalWallet.fromMnemonic(mnemonic, BECH32_PREFIX);
24
+
25
+ const privateKeyHex = privateKeyRaw != null ? `0x${toHex(privateKeyRaw)}` : undefined;
26
+ const publicKey = wallet.pubKey;
27
+ const address = wallet.address;
28
+
29
+ if (privateKeyHex == null || publicKey == null || address == null) {
30
+ return undefined;
31
+ }
32
+
33
+ return {
34
+ // 12 english words
35
+ mnemonic,
36
+ // toHex of the raw private key bits
37
+ privateKeyHex,
38
+ // base64, not hex
39
+ publicKey: publicKey.value,
40
+ // valid dydx address corresponding to the key pair
41
+ address,
42
+ };
43
+ };
44
+
45
+ // arguments to authorize a given wallet public key to trade on behalf of the user.
46
+ // allows place order, cancel order, batch cancel on subaccount 0 only.
47
+ export const getAuthorizeNewTradingKeyArguments = ({
48
+ generatedWalletPubKey,
49
+ }: {
50
+ generatedWalletPubKey: string;
51
+ }): { type: AuthenticatorType; data: Uint8Array } => {
52
+ const wrapAndEncode64 = (s: string): string => toBase64(new TextEncoder().encode(s));
53
+
54
+ const messageFilterSubAuth = [
55
+ {
56
+ type: AuthenticatorType.MESSAGE_FILTER,
57
+ config: wrapAndEncode64(TYPE_URL_MSG_PLACE_ORDER),
58
+ },
59
+ {
60
+ type: AuthenticatorType.MESSAGE_FILTER,
61
+ config: wrapAndEncode64(TYPE_URL_MSG_CANCEL_ORDER),
62
+ },
63
+ {
64
+ type: AuthenticatorType.MESSAGE_FILTER,
65
+ config: wrapAndEncode64(TYPE_URL_BATCH_CANCEL),
66
+ },
67
+ ];
68
+
69
+ const anyOfMessageFilterConfigB64 = wrapAndEncode64(JSON.stringify(messageFilterSubAuth));
70
+
71
+ const subAuth = [
72
+ {
73
+ type: AuthenticatorType.SIGNATURE_VERIFICATION,
74
+ config: generatedWalletPubKey,
75
+ },
76
+ {
77
+ type: AuthenticatorType.ANY_OF,
78
+ config: anyOfMessageFilterConfigB64,
79
+ },
80
+ // we limit to cross markets to make it slightly harder to drain user funds on low liquidity markets with trading keys
81
+ // could undo this in the future if people are angry about it
82
+ {
83
+ type: AuthenticatorType.SUBACCOUNT_FILTER,
84
+ config: wrapAndEncode64('0'),
85
+ },
86
+ ];
87
+
88
+ const jsonString = JSON.stringify(subAuth);
89
+ const encodedData = new TextEncoder().encode(jsonString);
90
+ const topLevelType = AuthenticatorType.ALL_OF;
91
+
92
+ return {
93
+ type: topLevelType,
94
+ data: encodedData,
95
+ };
96
+ };
97
+
98
+ // redeclared to keep sub bundle size small
99
+ type Awaited<T> = T extends Promise<infer U> ? U : T;
100
+ const isTruthy = <T>(n?: T | false | null | undefined | 0): n is T => Boolean(n);
101
+
102
+ // just parses out keys that match the format created in getAuthorizeNewTradingKeyArguments
103
+ export const getAuthorizedTradingKeysMetadata = (
104
+ authorizedKeys: Awaited<ReturnType<Get['getAuthenticators']>>['accountAuthenticators'],
105
+ ): Array<{ id: string; publicKey: string; address: string }> => {
106
+ return authorizedKeys
107
+ .map(({ config, id, type }) => {
108
+ if (type !== AuthenticatorType.ALL_OF) {
109
+ return null;
110
+ }
111
+ const parsedConfig = JSON.parse(new TextDecoder().decode(config)) as
112
+ | Authenticator[]
113
+ | undefined;
114
+ if (parsedConfig == null) {
115
+ return null;
116
+ }
117
+
118
+ const publicKey = parsedConfig.find(
119
+ (t) => t.type === AuthenticatorType.SIGNATURE_VERIFICATION,
120
+ )?.config;
121
+ if (publicKey == null || typeof publicKey !== 'string') {
122
+ return null;
123
+ }
124
+
125
+ const address = toBech32(
126
+ BECH32_PREFIX,
127
+ rawSecp256k1PubkeyToRawAddress(fromBase64(publicKey)),
128
+ );
129
+ return {
130
+ id: id.toString(),
131
+ publicKey,
132
+ address,
133
+ };
134
+ })
135
+ .filter(isTruthy);
136
+ };