@dydxprotocol/v4-client-js 0.32.0 → 0.32.1
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/__native__/__ios__/v4-native-client.js +70 -7
- package/build/examples/optimal_node.js +31 -3
- package/build/src/clients/native.d.ts +1 -0
- package/build/src/clients/native.js +27 -2
- package/build/src/network_optimizer.d.ts +2 -0
- package/build/src/network_optimizer.js +43 -5
- package/examples/optimal_node.ts +31 -2
- package/package.json +1 -1
- package/src/clients/native.ts +24 -0
- package/src/network_optimizer.ts +52 -8
- package/__native__/__ios__/v4-native-client.js.map +0 -1
package/examples/optimal_node.ts
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from '../src/clients/constants';
|
|
4
4
|
import { NetworkOptimizer } from '../src/network_optimizer';
|
|
5
5
|
|
|
6
|
-
async function
|
|
6
|
+
async function testNodes(): Promise<void> {
|
|
7
7
|
// all valid endpoints
|
|
8
8
|
try {
|
|
9
9
|
const optimizer = new NetworkOptimizer();
|
|
@@ -48,4 +48,33 @@ async function test(): Promise<void> {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
async function testIndexers(): Promise<void> {
|
|
52
|
+
// all valid endpoints
|
|
53
|
+
try {
|
|
54
|
+
const optimizer = new NetworkOptimizer();
|
|
55
|
+
const endpoints = [
|
|
56
|
+
'https://indexer.v4testnet2.dydx.exchange',
|
|
57
|
+
];
|
|
58
|
+
const optimal = await optimizer.findOptimalIndexer(endpoints);
|
|
59
|
+
console.log(optimal);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.log(error.message);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// all invalid endpoints
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const optimizer = new NetworkOptimizer();
|
|
68
|
+
const endpoints = [
|
|
69
|
+
'https://example.com',
|
|
70
|
+
'https://example.org',
|
|
71
|
+
];
|
|
72
|
+
const optimal = await optimizer.findOptimalIndexer(endpoints);
|
|
73
|
+
console.log(optimal);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.log(error.message);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
testNodes().catch(console.log);
|
|
80
|
+
testIndexers().catch(console.log);
|
package/package.json
CHANGED
package/src/clients/native.ts
CHANGED
|
@@ -862,3 +862,27 @@ export async function getOptimalNode(endpointUrlsAsJson: string): Promise<string
|
|
|
862
862
|
return wrappedError(error);
|
|
863
863
|
}
|
|
864
864
|
}
|
|
865
|
+
|
|
866
|
+
export async function getOptimalIndexer(endpointUrlsAsJson: string): Promise<string> {
|
|
867
|
+
/*
|
|
868
|
+
param:
|
|
869
|
+
endpointUrlsAsJson:
|
|
870
|
+
{
|
|
871
|
+
"endpointUrls": [
|
|
872
|
+
"https://api.example.org"
|
|
873
|
+
]
|
|
874
|
+
}
|
|
875
|
+
*/
|
|
876
|
+
try {
|
|
877
|
+
const param = JSON.parse(endpointUrlsAsJson);
|
|
878
|
+
const endpointUrls = param.endpointUrls;
|
|
879
|
+
const networkOptimizer = new NetworkOptimizer();
|
|
880
|
+
const optimalUrl = await networkOptimizer.findOptimalIndexer(endpointUrls);
|
|
881
|
+
const url = {
|
|
882
|
+
url: optimalUrl,
|
|
883
|
+
};
|
|
884
|
+
return encodeJson(url);
|
|
885
|
+
} catch (error) {
|
|
886
|
+
return wrappedError(error);
|
|
887
|
+
}
|
|
888
|
+
}
|
package/src/network_optimizer.ts
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { IndexerClient } from './clients/indexer-client';
|
|
3
2
|
import { ValidatorClient } from './clients/validator-client';
|
|
4
3
|
import { encodeJson } from './lib/helpers';
|
|
5
|
-
import { ValidatorConfig } from './types';
|
|
4
|
+
import { IndexerConfig, ValidatorConfig } from './types';
|
|
6
5
|
|
|
7
6
|
class PingResponse {
|
|
8
|
-
public readonly
|
|
7
|
+
public readonly height: number;
|
|
9
8
|
public readonly responseTime: Date;
|
|
10
9
|
public endpoint?: string;
|
|
11
10
|
|
|
12
11
|
constructor(
|
|
13
|
-
|
|
12
|
+
height: number,
|
|
14
13
|
) {
|
|
15
|
-
this.
|
|
14
|
+
this.height = height;
|
|
16
15
|
this.responseTime = new Date();
|
|
17
16
|
}
|
|
18
17
|
}
|
|
@@ -32,6 +31,15 @@ export class NetworkOptimizer {
|
|
|
32
31
|
)).filter(isTruthy);
|
|
33
32
|
}
|
|
34
33
|
|
|
34
|
+
private indexerClients(
|
|
35
|
+
endpointUrls: string[],
|
|
36
|
+
): IndexerClient[] {
|
|
37
|
+
return endpointUrls.map((endpointUrl) => new IndexerClient(
|
|
38
|
+
// socket is not used for finding optimal indexer, but required as a parameter to the config
|
|
39
|
+
new IndexerConfig(endpointUrl, endpointUrl.replace('https://', 'wss://').replace('http://', 'ws://')),
|
|
40
|
+
)).filter(isTruthy);
|
|
41
|
+
}
|
|
42
|
+
|
|
35
43
|
async findOptimalNode(endpointUrls: string[], chainId: string): Promise<string> {
|
|
36
44
|
if (endpointUrls.length === 0) {
|
|
37
45
|
const errorResponse = {
|
|
@@ -46,10 +54,46 @@ export class NetworkOptimizer {
|
|
|
46
54
|
clients
|
|
47
55
|
.map(async (client) => {
|
|
48
56
|
const block = await client.get.latestBlock();
|
|
49
|
-
const response = new PingResponse(block);
|
|
57
|
+
const response = new PingResponse(block.header.height);
|
|
58
|
+
return {
|
|
59
|
+
endpoint: client.config.restEndpoint,
|
|
60
|
+
height: response.height,
|
|
61
|
+
time: response.responseTime.getTime(),
|
|
62
|
+
};
|
|
63
|
+
})
|
|
64
|
+
.map((promise) => promise.catch((_) => undefined)),
|
|
65
|
+
)).filter(isTruthy);
|
|
66
|
+
|
|
67
|
+
if (responses.length === 0) {
|
|
68
|
+
throw new Error('Could not connect to endpoints');
|
|
69
|
+
}
|
|
70
|
+
const maxHeight = Math.max(...responses.map(({ height }) => height));
|
|
71
|
+
return responses
|
|
72
|
+
// Only consider nodes at `maxHeight`
|
|
73
|
+
.filter(({ height }) => height === maxHeight)
|
|
74
|
+
// Return the endpoint with the fastest response time
|
|
75
|
+
.sort((a, b) => a.time - b.time)[0]
|
|
76
|
+
.endpoint;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async findOptimalIndexer(endpointUrls: string[]): Promise<string> {
|
|
80
|
+
if (endpointUrls.length === 0) {
|
|
81
|
+
const errorResponse = {
|
|
82
|
+
error: {
|
|
83
|
+
message: 'No URL provided',
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
return encodeJson(errorResponse);
|
|
87
|
+
}
|
|
88
|
+
const clients = this.indexerClients(endpointUrls);
|
|
89
|
+
const responses = (await Promise.all(
|
|
90
|
+
clients
|
|
91
|
+
.map(async (client) => {
|
|
92
|
+
const block = await client.markets.getHeight();
|
|
93
|
+
const response = new PingResponse(+block.height);
|
|
50
94
|
return {
|
|
51
95
|
endpoint: client.config.restEndpoint,
|
|
52
|
-
height: response.
|
|
96
|
+
height: response.height,
|
|
53
97
|
time: response.responseTime.getTime(),
|
|
54
98
|
};
|
|
55
99
|
})
|