@bithomp/xrpl-api 3.7.2 → 3.7.4
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/lib/client.d.ts +2 -0
- package/lib/client.js +32 -0
- package/lib/connection.d.ts +1 -0
- package/lib/connection.js +56 -27
- package/lib/ledger/ledger.js +1 -1
- package/package.json +5 -5
package/lib/client.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Connection, ConnectionOptions } from "./connection";
|
|
2
|
+
import { LedgerIndex } from "./models/ledger";
|
|
2
3
|
export * from "./ledger";
|
|
3
4
|
export declare let feeCushion: number;
|
|
4
5
|
export declare let logger: any;
|
|
@@ -21,3 +22,4 @@ export declare function connect(): Promise<void>;
|
|
|
21
22
|
export declare function disconnect(): Promise<void>;
|
|
22
23
|
export declare function getNativeCurrency(): string;
|
|
23
24
|
export declare function findConnection(type?: string, url?: string, strongFilter?: boolean, hash?: string, networkID?: number): Connection | null;
|
|
25
|
+
export declare function findConnectionByLedger(ledgerIndex?: LedgerIndex, ledgerHash?: string, networkID?: number): Connection | null;
|
package/lib/client.js
CHANGED
|
@@ -20,6 +20,7 @@ exports.connect = connect;
|
|
|
20
20
|
exports.disconnect = disconnect;
|
|
21
21
|
exports.getNativeCurrency = getNativeCurrency;
|
|
22
22
|
exports.findConnection = findConnection;
|
|
23
|
+
exports.findConnectionByLedger = findConnectionByLedger;
|
|
23
24
|
const connection_1 = require("./connection");
|
|
24
25
|
const common_1 = require("./common");
|
|
25
26
|
__exportStar(require("./ledger"), exports);
|
|
@@ -149,6 +150,37 @@ function findConnection(type, url, strongFilter, hash, networkID) {
|
|
|
149
150
|
connections = connections.sort(sortHelperConnections);
|
|
150
151
|
return connections[0];
|
|
151
152
|
}
|
|
153
|
+
function findConnectionByLedger(ledgerIndex, ledgerHash, networkID) {
|
|
154
|
+
if (ledgerHash) {
|
|
155
|
+
return findConnection("history", undefined, false, undefined, networkID);
|
|
156
|
+
}
|
|
157
|
+
if (typeof ledgerIndex === "string" || ledgerIndex === undefined) {
|
|
158
|
+
return findConnection(undefined, undefined, false, undefined, networkID);
|
|
159
|
+
}
|
|
160
|
+
const availableConnections = clientConnections.filter((con) => {
|
|
161
|
+
if (!con.isConnected()) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
if (typeof networkID === "number" && typeof con.getNetworkID() === "number") {
|
|
165
|
+
if (con.getNetworkID() !== networkID) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return con.isLedgerIndexPresent(ledgerIndex);
|
|
170
|
+
});
|
|
171
|
+
if (availableConnections.length === 0) {
|
|
172
|
+
return findConnection(undefined, undefined, false, undefined, networkID);
|
|
173
|
+
}
|
|
174
|
+
else if (availableConnections.length === 1) {
|
|
175
|
+
return availableConnections[0];
|
|
176
|
+
}
|
|
177
|
+
if (loadBalancing) {
|
|
178
|
+
const index = Math.floor(Math.random() * availableConnections.length);
|
|
179
|
+
return availableConnections[index];
|
|
180
|
+
}
|
|
181
|
+
const sortedConnections = availableConnections.sort(sortHelperConnections);
|
|
182
|
+
return sortedConnections[0];
|
|
183
|
+
}
|
|
152
184
|
function sortHelperConnections(a, b) {
|
|
153
185
|
if (a.getLatencyMs() < b.getLatencyMs()) {
|
|
154
186
|
return -1;
|
package/lib/connection.d.ts
CHANGED
|
@@ -57,6 +57,7 @@ declare class Connection extends EventEmitter {
|
|
|
57
57
|
getLatencyMs(): number;
|
|
58
58
|
getNetworkID(): number | undefined;
|
|
59
59
|
isLedgerIndexAvailable(ledgerIndex: any): boolean;
|
|
60
|
+
isLedgerIndexPresent(ledgerIndex: any): boolean;
|
|
60
61
|
private updateLatency;
|
|
61
62
|
private reconnect;
|
|
62
63
|
private removeClient;
|
package/lib/connection.js
CHANGED
|
@@ -102,8 +102,9 @@ class Connection extends events_1.EventEmitter {
|
|
|
102
102
|
url: this.url,
|
|
103
103
|
error: err?.message || err?.name || err,
|
|
104
104
|
});
|
|
105
|
+
this.removeClient();
|
|
105
106
|
}
|
|
106
|
-
this.connectionValidation();
|
|
107
|
+
this.connectionValidation("connect");
|
|
107
108
|
}
|
|
108
109
|
async disconnect() {
|
|
109
110
|
this.logger?.debug({
|
|
@@ -125,7 +126,16 @@ class Connection extends events_1.EventEmitter {
|
|
|
125
126
|
const result = await this._request(request, options);
|
|
126
127
|
let validResponse = true;
|
|
127
128
|
if (result?.error) {
|
|
128
|
-
if (result.error === "
|
|
129
|
+
if (result.error === "slowDown" || result.error === "Unexpected server response: 429") {
|
|
130
|
+
this.logger?.debug({
|
|
131
|
+
service: "Bithomp::XRPL::Connection",
|
|
132
|
+
function: "request",
|
|
133
|
+
url: this.url,
|
|
134
|
+
error: `Received slowdown error, reconnecting...`,
|
|
135
|
+
});
|
|
136
|
+
validResponse = false;
|
|
137
|
+
}
|
|
138
|
+
else if (result.error === "timeout") {
|
|
129
139
|
const timeouts = this.latency.filter((info) => info.delta >= this.timeout).length;
|
|
130
140
|
if (timeouts >= 3) {
|
|
131
141
|
this.logger?.debug({
|
|
@@ -135,10 +145,9 @@ class Connection extends events_1.EventEmitter {
|
|
|
135
145
|
error: `Too many timeouts (${timeouts}) in last ${this.latency.length} requests, reconnecting...`,
|
|
136
146
|
});
|
|
137
147
|
validResponse = false;
|
|
138
|
-
this.removeClient();
|
|
139
148
|
}
|
|
140
149
|
}
|
|
141
|
-
else if (result.error.startsWith("websocket was closed")) {
|
|
150
|
+
else if (result.error.toLowerCase().startsWith("websocket was closed")) {
|
|
142
151
|
this.logger?.debug({
|
|
143
152
|
service: "Bithomp::XRPL::Connection",
|
|
144
153
|
function: "request",
|
|
@@ -146,11 +155,13 @@ class Connection extends events_1.EventEmitter {
|
|
|
146
155
|
error: "Websocket was closed, reconnecting...",
|
|
147
156
|
});
|
|
148
157
|
validResponse = false;
|
|
149
|
-
this.removeClient();
|
|
150
158
|
}
|
|
151
159
|
}
|
|
152
160
|
if (validResponse) {
|
|
153
|
-
this.connectionValidation();
|
|
161
|
+
this.connectionValidation("request");
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
this.removeClient();
|
|
154
165
|
}
|
|
155
166
|
return result;
|
|
156
167
|
}
|
|
@@ -259,6 +270,24 @@ class Connection extends events_1.EventEmitter {
|
|
|
259
270
|
}
|
|
260
271
|
return true;
|
|
261
272
|
}
|
|
273
|
+
isLedgerIndexPresent(ledgerIndex) {
|
|
274
|
+
if (typeof ledgerIndex !== "number") {
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
if (!this.serverInfo?.complete_ledgers) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
const completeLedgers = this.serverInfo.complete_ledgers.split("-");
|
|
281
|
+
if (completeLedgers.length !== 2) {
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
completeLedgers[0] = parseInt(completeLedgers[0], 10);
|
|
285
|
+
completeLedgers[1] = parseInt(completeLedgers[1], 10);
|
|
286
|
+
if (ledgerIndex < completeLedgers[0] || ledgerIndex > completeLedgers[1]) {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
262
291
|
updateLatency(delta) {
|
|
263
292
|
this.latency.push({
|
|
264
293
|
timestamp: new Date(),
|
|
@@ -276,7 +305,6 @@ class Connection extends events_1.EventEmitter {
|
|
|
276
305
|
if (!this.shutdown) {
|
|
277
306
|
this.emit("reconnect");
|
|
278
307
|
try {
|
|
279
|
-
this.emit("disconnected", 1000);
|
|
280
308
|
this.removeClient();
|
|
281
309
|
this.resetTypes();
|
|
282
310
|
this.serverInfoUpdating = false;
|
|
@@ -293,15 +321,16 @@ class Connection extends events_1.EventEmitter {
|
|
|
293
321
|
error: e.message,
|
|
294
322
|
});
|
|
295
323
|
}
|
|
296
|
-
this.connectionValidation();
|
|
324
|
+
this.connectionValidation("reconnect");
|
|
297
325
|
}
|
|
298
326
|
}
|
|
299
|
-
removeClient() {
|
|
327
|
+
removeClient(code = 1000) {
|
|
300
328
|
try {
|
|
301
329
|
if (this.client) {
|
|
302
330
|
this.client.removeAllListeners();
|
|
303
331
|
this.client.disconnect();
|
|
304
332
|
this.client = undefined;
|
|
333
|
+
this.emit("disconnected", code);
|
|
305
334
|
}
|
|
306
335
|
}
|
|
307
336
|
catch (_err) {
|
|
@@ -327,9 +356,10 @@ class Connection extends events_1.EventEmitter {
|
|
|
327
356
|
code,
|
|
328
357
|
url: this.url,
|
|
329
358
|
});
|
|
330
|
-
this.
|
|
331
|
-
|
|
332
|
-
|
|
359
|
+
if (this.client) {
|
|
360
|
+
this.client.removeAllListeners();
|
|
361
|
+
this.client = undefined;
|
|
362
|
+
}
|
|
333
363
|
this.emit("disconnected", code);
|
|
334
364
|
});
|
|
335
365
|
this.client.on("error", (source, message, error) => {
|
|
@@ -351,7 +381,6 @@ class Connection extends events_1.EventEmitter {
|
|
|
351
381
|
error: err?.message || err?.name || err,
|
|
352
382
|
});
|
|
353
383
|
}
|
|
354
|
-
this.connectionValidation();
|
|
355
384
|
});
|
|
356
385
|
this.client.on("ledgerClosed", (ledgerStream) => {
|
|
357
386
|
this.onLedgerClosed(ledgerStream);
|
|
@@ -466,7 +495,7 @@ class Connection extends events_1.EventEmitter {
|
|
|
466
495
|
request.accounts = accounts;
|
|
467
496
|
}
|
|
468
497
|
const result = await this.request(request, { skip_subscription_update: true });
|
|
469
|
-
if (result.result) {
|
|
498
|
+
if (result.result && !result.error) {
|
|
470
499
|
this.streamsSubscribed = true;
|
|
471
500
|
}
|
|
472
501
|
return result;
|
|
@@ -510,7 +539,7 @@ class Connection extends events_1.EventEmitter {
|
|
|
510
539
|
else {
|
|
511
540
|
this.updateServerInfo();
|
|
512
541
|
}
|
|
513
|
-
this.connectionValidation();
|
|
542
|
+
this.connectionValidation("ledgerClosed");
|
|
514
543
|
}
|
|
515
544
|
async updateServerInfo() {
|
|
516
545
|
if (this.serverInfoUpdating || this.shutdown) {
|
|
@@ -538,10 +567,11 @@ class Connection extends events_1.EventEmitter {
|
|
|
538
567
|
}
|
|
539
568
|
this.serverInfoUpdating = false;
|
|
540
569
|
}
|
|
541
|
-
connectionValidation() {
|
|
570
|
+
connectionValidation(event) {
|
|
542
571
|
this.logger?.debug({
|
|
543
572
|
service: "Bithomp::XRPL::Connection",
|
|
544
573
|
function: "connectionValidation",
|
|
574
|
+
event,
|
|
545
575
|
url: this.url,
|
|
546
576
|
shutdown: this.shutdown,
|
|
547
577
|
});
|
|
@@ -549,17 +579,16 @@ class Connection extends events_1.EventEmitter {
|
|
|
549
579
|
clearTimeout(this.connectionWatchTimer);
|
|
550
580
|
this.connectionWatchTimer = null;
|
|
551
581
|
}
|
|
552
|
-
if (
|
|
553
|
-
if (this.streamsSubscribed === false) {
|
|
554
|
-
this.subscribe();
|
|
555
|
-
}
|
|
556
|
-
if (this.serverInfo === null && this.isConnected()) {
|
|
557
|
-
this.updateServerInfo();
|
|
558
|
-
}
|
|
559
|
-
this.connectionWatchTimer = setTimeout(this.bindConnectionWatchTimeout, LEDGER_CLOSED_TIMEOUT);
|
|
560
|
-
}
|
|
561
|
-
else {
|
|
582
|
+
if (this.shutdown) {
|
|
562
583
|
this.removeClient();
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
this.connectionWatchTimer = setTimeout(this.bindConnectionWatchTimeout, LEDGER_CLOSED_TIMEOUT);
|
|
587
|
+
if (this.streamsSubscribed === false) {
|
|
588
|
+
this.subscribe();
|
|
589
|
+
}
|
|
590
|
+
if (this.serverInfo === null && this.isConnected()) {
|
|
591
|
+
this.updateServerInfo();
|
|
563
592
|
}
|
|
564
593
|
}
|
|
565
594
|
async connectionWatchTimeout() {
|
|
@@ -582,7 +611,7 @@ class Connection extends events_1.EventEmitter {
|
|
|
582
611
|
url: this.url,
|
|
583
612
|
error: e.message,
|
|
584
613
|
});
|
|
585
|
-
this.connectionValidation();
|
|
614
|
+
this.connectionValidation("connectionWatchTimeout");
|
|
586
615
|
}
|
|
587
616
|
}
|
|
588
617
|
}
|
package/lib/ledger/ledger.js
CHANGED
|
@@ -40,7 +40,7 @@ const ledger_1 = require("../parse/ledger/ledger");
|
|
|
40
40
|
const utils_1 = require("../common/utils");
|
|
41
41
|
async function getLedger(options = {}) {
|
|
42
42
|
const formatted = options.legacy === true || options.formatted === true;
|
|
43
|
-
const connection = options.connection || Client.
|
|
43
|
+
const connection = options.connection || Client.findConnectionByLedger(options.ledgerIndex, options.ledgerHash);
|
|
44
44
|
if (!connection) {
|
|
45
45
|
throw new Error("There is no connection");
|
|
46
46
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bithomp/xrpl-api",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.4",
|
|
4
4
|
"description": "A Bithomp JavaScript/TypeScript library for interacting with the XRP Ledger",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"",
|
|
43
43
|
"lint": "eslint",
|
|
44
44
|
"prepare": "npm run build",
|
|
45
|
-
"prepublishOnly": "npm test && npm run lint",
|
|
45
|
+
"-prepublishOnly": "npm test && npm run lint",
|
|
46
46
|
"preversion": "npm run lint",
|
|
47
47
|
"version": "npm run format && git add -A src",
|
|
48
48
|
"postversion": "git push && git push --tags"
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"lib/**/*"
|
|
52
52
|
],
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"axios": "^1.13.
|
|
54
|
+
"axios": "^1.13.2",
|
|
55
55
|
"base-x": "^5.0.1",
|
|
56
56
|
"bignumber.js": "^9.3.1",
|
|
57
57
|
"elliptic": "^6.6.1",
|
|
@@ -73,13 +73,13 @@
|
|
|
73
73
|
"@typescript-eslint/parser": "^8.46.2",
|
|
74
74
|
"chai": "^6.2.0",
|
|
75
75
|
"chai-as-promised": "^8.0.2",
|
|
76
|
-
"eslint": "^9.39.
|
|
76
|
+
"eslint": "^9.39.1",
|
|
77
77
|
"eslint-config-prettier": "^10.1.8",
|
|
78
78
|
"eslint-plugin-chai-friendly": "^1.1.0",
|
|
79
79
|
"eslint-plugin-import": "^2.32.0",
|
|
80
80
|
"eslint-plugin-n": "^17.23.1",
|
|
81
81
|
"eslint-plugin-promise": "^7.2.1",
|
|
82
|
-
"mocha": "^11.7.
|
|
82
|
+
"mocha": "^11.7.5",
|
|
83
83
|
"nconf": "^0.13.0",
|
|
84
84
|
"ts-jest": "^29.4.5",
|
|
85
85
|
"ts-node": "^10.9.2",
|