@dydxprotocol/v4-client-js 1.6.1 → 1.8.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 +3 -3
- package/__native__/__ios__/v4-native-client.js +123 -19
- package/build/examples/native_examples.js +9 -1
- package/build/src/clients/constants.d.ts +6 -1
- package/build/src/clients/constants.js +17 -2
- package/build/src/clients/modules/post.d.ts +3 -1
- package/build/src/clients/modules/post.js +26 -11
- package/build/src/clients/native.d.ts +4 -0
- package/build/src/clients/native.js +76 -2
- package/build/src/clients/validator-client.js +2 -2
- package/build/tsconfig.tsbuildinfo +1 -1
- package/examples/native_examples.ts +16 -0
- package/package.json +1 -1
- package/src/clients/constants.ts +24 -0
- package/src/clients/modules/post.ts +24 -10
- package/src/clients/native.ts +89 -0
- package/src/clients/validator-client.ts +1 -0
|
@@ -15,6 +15,9 @@ import {
|
|
|
15
15
|
withdraw,
|
|
16
16
|
withdrawToIBC,
|
|
17
17
|
wrappedError,
|
|
18
|
+
getMegavaultOwnerShares,
|
|
19
|
+
depositToMegavault,
|
|
20
|
+
withdrawFromMegavault,
|
|
18
21
|
} from '../src/clients/native';
|
|
19
22
|
import { DYDX_TEST_ADDRESS, DYDX_TEST_MNEMONIC } from './constants';
|
|
20
23
|
|
|
@@ -47,6 +50,19 @@ async function test(): Promise<void> {
|
|
|
47
50
|
const userStats = await getUserStats(payload);
|
|
48
51
|
console.log(userStats);
|
|
49
52
|
|
|
53
|
+
const balances1 = await getAccountBalances();
|
|
54
|
+
console.log(balances1);
|
|
55
|
+
|
|
56
|
+
const vaultOwnerShares = await getMegavaultOwnerShares(payload);
|
|
57
|
+
console.log(vaultOwnerShares);
|
|
58
|
+
|
|
59
|
+
const depositResult = await depositToMegavault(0, 2);
|
|
60
|
+
console.log(depositResult);
|
|
61
|
+
|
|
62
|
+
const withdrawResult = await withdrawFromMegavault(0, 1, 0);
|
|
63
|
+
console.log(withdrawResult);
|
|
64
|
+
|
|
65
|
+
|
|
50
66
|
const sendTokenPayload = {
|
|
51
67
|
subaccountNumber: 0,
|
|
52
68
|
amount: '10', // Dydx Token
|
package/package.json
CHANGED
package/src/clients/constants.ts
CHANGED
|
@@ -23,6 +23,7 @@ export const MAINNET_CHAIN_ID = 'dydx-mainnet-1';
|
|
|
23
23
|
// ------------ API URLs ------------
|
|
24
24
|
export enum IndexerApiHost {
|
|
25
25
|
TESTNET = 'https://indexer.v4testnet.dydx.exchange/',
|
|
26
|
+
STAGING = 'https://indexer.v4staging.dydx.exchange/',
|
|
26
27
|
LOCAL = 'http://localhost:3002',
|
|
27
28
|
// For the deployment by DYDX token holders
|
|
28
29
|
MAINNET = 'https://indexer.dydx.trade',
|
|
@@ -30,6 +31,7 @@ export enum IndexerApiHost {
|
|
|
30
31
|
|
|
31
32
|
export enum IndexerWSHost {
|
|
32
33
|
TESTNET = 'wss://dydx-testnet.imperator.co/v4/ws',
|
|
34
|
+
STAGING = 'wss://indexer.v4staging.dydx.exchange/v4/ws',
|
|
33
35
|
LOCAL = 'ws://localhost:3003',
|
|
34
36
|
// For the deployment by DYDX token holders
|
|
35
37
|
MAINNET = 'wss://indexer.dydx.trade/v4/ws',
|
|
@@ -41,6 +43,7 @@ export enum FaucetApiHost {
|
|
|
41
43
|
|
|
42
44
|
export enum ValidatorApiHost {
|
|
43
45
|
TESTNET = 'https://test-dydx.kingnodes.com',
|
|
46
|
+
STAGING = 'https://validator.v4staging.dydx.exchange',
|
|
44
47
|
LOCAL = 'http://localhost:26657',
|
|
45
48
|
// For the deployment by DYDX token holders
|
|
46
49
|
MAINNET = 'https://dydx-ops-rpc.kingnodes.com:443',
|
|
@@ -220,6 +223,7 @@ export class ValidatorConfig {
|
|
|
220
223
|
public denoms: DenomConfig;
|
|
221
224
|
public broadcastOptions?: BroadcastOptions;
|
|
222
225
|
public defaultClientMemo?: string;
|
|
226
|
+
public useTimestampNonce?: boolean;
|
|
223
227
|
|
|
224
228
|
constructor(
|
|
225
229
|
restEndpoint: string,
|
|
@@ -227,6 +231,7 @@ export class ValidatorConfig {
|
|
|
227
231
|
denoms: DenomConfig,
|
|
228
232
|
broadcastOptions?: BroadcastOptions,
|
|
229
233
|
defaultClientMemo?: string,
|
|
234
|
+
useTimestampNonce?: boolean,
|
|
230
235
|
) {
|
|
231
236
|
this.restEndpoint = restEndpoint?.endsWith('/') ? restEndpoint.slice(0, -1) : restEndpoint;
|
|
232
237
|
this.chainId = chainId;
|
|
@@ -234,6 +239,7 @@ export class ValidatorConfig {
|
|
|
234
239
|
this.denoms = denoms;
|
|
235
240
|
this.broadcastOptions = broadcastOptions;
|
|
236
241
|
this.defaultClientMemo = defaultClientMemo;
|
|
242
|
+
this.useTimestampNonce = useTimestampNonce;
|
|
237
243
|
}
|
|
238
244
|
}
|
|
239
245
|
|
|
@@ -262,6 +268,24 @@ export class Network {
|
|
|
262
268
|
return new Network('testnet', indexerConfig, validatorConfig);
|
|
263
269
|
}
|
|
264
270
|
|
|
271
|
+
static staging(): Network {
|
|
272
|
+
const indexerConfig = new IndexerConfig(IndexerApiHost.STAGING, IndexerWSHost.STAGING);
|
|
273
|
+
const validatorConfig = new ValidatorConfig(
|
|
274
|
+
ValidatorApiHost.STAGING,
|
|
275
|
+
TESTNET_CHAIN_ID,
|
|
276
|
+
{
|
|
277
|
+
CHAINTOKEN_DENOM: 'adv4tnt',
|
|
278
|
+
USDC_DENOM: 'ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5',
|
|
279
|
+
USDC_GAS_DENOM: 'uusdc',
|
|
280
|
+
USDC_DECIMALS: 6,
|
|
281
|
+
CHAINTOKEN_DECIMALS: 18,
|
|
282
|
+
},
|
|
283
|
+
undefined,
|
|
284
|
+
'Client Example',
|
|
285
|
+
);
|
|
286
|
+
return new Network('staging', indexerConfig, validatorConfig);
|
|
287
|
+
}
|
|
288
|
+
|
|
265
289
|
static local(): Network {
|
|
266
290
|
const indexerConfig = new IndexerConfig(IndexerApiHost.LOCAL, IndexerWSHost.LOCAL);
|
|
267
291
|
const validatorConfig = new ValidatorConfig(
|
|
@@ -55,9 +55,10 @@ export class Post {
|
|
|
55
55
|
public readonly defaultGasPrice: GasPrice;
|
|
56
56
|
public readonly defaultDydxGasPrice: GasPrice;
|
|
57
57
|
|
|
58
|
+
public useTimestampNonce: boolean = false;
|
|
58
59
|
private accountNumberCache: Map<string, Account> = new Map();
|
|
59
60
|
|
|
60
|
-
constructor(get: Get, chainId: string, denoms: DenomConfig, defaultClientMemo?: string) {
|
|
61
|
+
constructor(get: Get, chainId: string, denoms: DenomConfig, defaultClientMemo?: string, useTimestampNonce?: boolean) {
|
|
61
62
|
this.get = get;
|
|
62
63
|
this.chainId = chainId;
|
|
63
64
|
this.registry = generateRegistry();
|
|
@@ -74,6 +75,7 @@ export class Post {
|
|
|
74
75
|
: denoms.CHAINTOKEN_DENOM
|
|
75
76
|
}`,
|
|
76
77
|
);
|
|
78
|
+
if (useTimestampNonce === true) this.useTimestampNonce = useTimestampNonce;
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
/**
|
|
@@ -113,14 +115,23 @@ export class Post {
|
|
|
113
115
|
memo?: string,
|
|
114
116
|
account?: () => Promise<Account>,
|
|
115
117
|
): Promise<StdFee> {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
let msgs: EncodeObject[];
|
|
119
|
+
// protocol expects timestamp nonce in UTC milliseconds, which is the unit returned by Date.now()
|
|
120
|
+
let sequence = Date.now();
|
|
121
|
+
|
|
122
|
+
if (this.useTimestampNonce) {
|
|
123
|
+
msgs = await messaging();
|
|
124
|
+
} else {
|
|
125
|
+
const msgsPromise = messaging();
|
|
126
|
+
const accountPromise = account ? await account() : this.account(wallet.address!);
|
|
127
|
+
const msgsAndAccount = await Promise.all([msgsPromise, accountPromise]);
|
|
128
|
+
msgs = msgsAndAccount[0];
|
|
129
|
+
sequence = msgsAndAccount[1].sequence;
|
|
130
|
+
}
|
|
120
131
|
|
|
121
132
|
return this.simulateTransaction(
|
|
122
133
|
wallet.pubKey!,
|
|
123
|
-
|
|
134
|
+
sequence,
|
|
124
135
|
msgs,
|
|
125
136
|
gasPrice,
|
|
126
137
|
memo,
|
|
@@ -225,16 +236,18 @@ export class Post {
|
|
|
225
236
|
gasPrice: GasPrice = this.getGasPrice(),
|
|
226
237
|
memo?: string,
|
|
227
238
|
): Promise<Uint8Array> {
|
|
239
|
+
// protocol expects timestamp nonce in UTC milliseconds, which is the unit returned by Date.now()
|
|
240
|
+
const sequence = this.useTimestampNonce ? Date.now() : account.sequence;
|
|
228
241
|
// Simulate transaction if no fee is specified.
|
|
229
242
|
const fee: StdFee = zeroFee
|
|
230
243
|
? {
|
|
231
244
|
amount: [],
|
|
232
245
|
gas: '1000000',
|
|
233
246
|
}
|
|
234
|
-
: await this.simulateTransaction(wallet.pubKey!,
|
|
247
|
+
: await this.simulateTransaction(wallet.pubKey!, sequence, messages, gasPrice, memo);
|
|
235
248
|
|
|
236
249
|
const txOptions: TransactionOptions = {
|
|
237
|
-
sequence
|
|
250
|
+
sequence,
|
|
238
251
|
accountNumber: account.accountNumber,
|
|
239
252
|
chainId: this.chainId,
|
|
240
253
|
};
|
|
@@ -246,11 +259,12 @@ export class Post {
|
|
|
246
259
|
* @description Retrieve an account structure for transactions.
|
|
247
260
|
* For short term orders, the sequence doesn't matter. Use cached if available.
|
|
248
261
|
* For long term and conditional orders, a round trip to validator must be made.
|
|
262
|
+
* when timestamp nonce is supported, no need to fetch account sequence number
|
|
249
263
|
*/
|
|
250
264
|
public async account(address: string, orderFlags?: OrderFlags): Promise<Account> {
|
|
251
|
-
if (orderFlags === OrderFlags.SHORT_TERM) {
|
|
265
|
+
if (orderFlags === OrderFlags.SHORT_TERM || this.useTimestampNonce) {
|
|
252
266
|
if (this.accountNumberCache.has(address)) {
|
|
253
|
-
//
|
|
267
|
+
// If order is SHORT_TERM or if timestamp nonce is enabled, the sequence doesn't matter
|
|
254
268
|
return this.accountNumberCache.get(address)!;
|
|
255
269
|
}
|
|
256
270
|
}
|
package/src/clients/native.ts
CHANGED
|
@@ -1352,3 +1352,92 @@ export async function setSelectedGasDenom(gasDenom: string): Promise<string> {
|
|
|
1352
1352
|
return wrappedError(error);
|
|
1353
1353
|
}
|
|
1354
1354
|
}
|
|
1355
|
+
|
|
1356
|
+
export async function getMegavaultOwnerShares(payload: string): Promise<string> {
|
|
1357
|
+
try {
|
|
1358
|
+
const client = globalThis.client;
|
|
1359
|
+
if (client === undefined) {
|
|
1360
|
+
throw new UserError('client is not connected. Call connectClient() first');
|
|
1361
|
+
}
|
|
1362
|
+
const json = JSON.parse(payload);
|
|
1363
|
+
const address = json.address;
|
|
1364
|
+
if (address === undefined) {
|
|
1365
|
+
throw new UserError('address is not set');
|
|
1366
|
+
}
|
|
1367
|
+
const response =
|
|
1368
|
+
await globalThis.client?.validatorClient.get.getMegavaultOwnerShares(address);
|
|
1369
|
+
return encodeJson(response);
|
|
1370
|
+
} catch (e) {
|
|
1371
|
+
return wrappedError(e);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
export async function getMegavaultWithdrawalInfo(
|
|
1376
|
+
sharesToWithdraw: bigint
|
|
1377
|
+
): Promise<string> {
|
|
1378
|
+
try {
|
|
1379
|
+
const client = globalThis.client;
|
|
1380
|
+
if (client === undefined) {
|
|
1381
|
+
throw new UserError('client is not connected. Call connectClient() first');
|
|
1382
|
+
}
|
|
1383
|
+
const response =
|
|
1384
|
+
await globalThis.client?.validatorClient.get.getMegavaultWithdrawalInfo(sharesToWithdraw);
|
|
1385
|
+
return encodeJson(response);
|
|
1386
|
+
} catch (e) {
|
|
1387
|
+
return wrappedError(e);
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
export async function depositToMegavault(
|
|
1392
|
+
subaccountNumber: number,
|
|
1393
|
+
amountUsdc: number
|
|
1394
|
+
): Promise<string> {
|
|
1395
|
+
try {
|
|
1396
|
+
const client = globalThis.client;
|
|
1397
|
+
if (client === undefined) {
|
|
1398
|
+
throw new UserError('client is not connected. Call connectNetwork() first');
|
|
1399
|
+
}
|
|
1400
|
+
const wallet = globalThis.wallet;
|
|
1401
|
+
if (wallet === undefined) {
|
|
1402
|
+
throw new UserError('wallet is not set. Call connectWallet() first');
|
|
1403
|
+
}
|
|
1404
|
+
const subaccount = new SubaccountInfo(wallet, subaccountNumber);
|
|
1405
|
+
const tx = await client.depositToMegavault(
|
|
1406
|
+
subaccount,
|
|
1407
|
+
amountUsdc,
|
|
1408
|
+
Method.BroadcastTxCommit,
|
|
1409
|
+
);
|
|
1410
|
+
return encodeJson(tx);
|
|
1411
|
+
} catch (error) {
|
|
1412
|
+
return wrappedError(error);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
export async function withdrawFromMegavault(
|
|
1417
|
+
subaccountNumber: number,
|
|
1418
|
+
shares: number,
|
|
1419
|
+
minAmount: number,
|
|
1420
|
+
): Promise<string> {
|
|
1421
|
+
try {
|
|
1422
|
+
const client = globalThis.client;
|
|
1423
|
+
if (client === undefined) {
|
|
1424
|
+
throw new UserError('client is not connected. Call connectNetwork() first');
|
|
1425
|
+
}
|
|
1426
|
+
const wallet = globalThis.wallet;
|
|
1427
|
+
if (wallet === undefined) {
|
|
1428
|
+
throw new UserError('wallet is not set. Call connectWallet() first');
|
|
1429
|
+
}
|
|
1430
|
+
const subaccount = new SubaccountInfo(wallet, subaccountNumber);
|
|
1431
|
+
const tx = await client.withdrawFromMegavault(
|
|
1432
|
+
subaccount,
|
|
1433
|
+
shares,
|
|
1434
|
+
minAmount,
|
|
1435
|
+
Method.BroadcastTxCommit,
|
|
1436
|
+
);
|
|
1437
|
+
return encodeJson(tx);
|
|
1438
|
+
} catch (error) {
|
|
1439
|
+
return wrappedError(error);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
|