*add dist
This commit is contained in:
parent
289cd2f5cc
commit
e0d836f2ff
|
@ -0,0 +1,4 @@
|
||||||
|
export * from "./rpcNetwork.js";
|
||||||
|
export * from "./rpcQuery.js";
|
||||||
|
export * from "./types";
|
||||||
|
//# sourceMappingURL=index.d.ts.map
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC"}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export * from "./rpcNetwork.js";
|
||||||
|
export * from "./rpcQuery.js";
|
||||||
|
export * from "./types";
|
|
@ -0,0 +1,25 @@
|
||||||
|
import RpcQuery from "./rpcQuery.js";
|
||||||
|
export default class RpcNetwork {
|
||||||
|
private _dht;
|
||||||
|
private _majorityThreshold;
|
||||||
|
private _maxTtl;
|
||||||
|
private _queryTimeout;
|
||||||
|
private _relays;
|
||||||
|
private _ready;
|
||||||
|
private _force;
|
||||||
|
constructor(dht?: any);
|
||||||
|
get ready(): Promise<void>;
|
||||||
|
get relays(): string[];
|
||||||
|
get dht(): any;
|
||||||
|
get maxTtl(): number;
|
||||||
|
set maxTtl(value: number);
|
||||||
|
get queryTimeout(): number;
|
||||||
|
set queryTimeout(value: number);
|
||||||
|
get majorityThreshold(): number;
|
||||||
|
set majorityThreshold(value: number);
|
||||||
|
get force(): boolean;
|
||||||
|
set force(value: boolean);
|
||||||
|
addRelay(pubkey: string): void;
|
||||||
|
query(query: string, chain: string, data?: object | any[], force?: boolean): RpcQuery;
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=rpcNetwork.d.ts.map
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"rpcNetwork.d.ts","sourceRoot":"","sources":["../src/rpcNetwork.ts"],"names":[],"mappings":"AAEA,OAAO,QAAQ,MAAM,eAAe,CAAC;AAMrC,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,MAAM,CAAkB;gBAEpB,GAAG,MAAY;IAK3B,IAAI,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAEzB;IAED,IAAI,MAAM,IAAI,MAAM,EAAE,CAErB;IAED,IAAI,GAAG,QAEN;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAEvB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,YAAY,CAAC,KAAK,EAAE,MAAM,EAE7B;IAED,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED,IAAI,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAElC;IAED,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,OAAO,EAEvB;IAEM,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAK9B,KAAK,CACV,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,MAAM,GAAG,GAAG,EAAO,EACzB,KAAK,GAAE,OAAe,GACrB,QAAQ;CAQZ"}
|
|
@ -0,0 +1,61 @@
|
||||||
|
// tslint:disable:no-var-requires
|
||||||
|
import { createRequire } from "module";
|
||||||
|
import RpcQuery from "./rpcQuery.js";
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
|
const DHT = require("@hyperswarm/dht");
|
||||||
|
export default class RpcNetwork {
|
||||||
|
constructor(dht = new DHT()) {
|
||||||
|
this._majorityThreshold = 0.75;
|
||||||
|
this._maxTtl = 12 * 60 * 60;
|
||||||
|
this._queryTimeout = 30;
|
||||||
|
this._relays = [];
|
||||||
|
this._force = false;
|
||||||
|
this._dht = dht;
|
||||||
|
this._ready = this._dht.ready();
|
||||||
|
}
|
||||||
|
get ready() {
|
||||||
|
return this._ready;
|
||||||
|
}
|
||||||
|
get relays() {
|
||||||
|
return this._relays;
|
||||||
|
}
|
||||||
|
get dht() {
|
||||||
|
return this._dht;
|
||||||
|
}
|
||||||
|
get maxTtl() {
|
||||||
|
return this._maxTtl;
|
||||||
|
}
|
||||||
|
set maxTtl(value) {
|
||||||
|
this._maxTtl = value;
|
||||||
|
}
|
||||||
|
get queryTimeout() {
|
||||||
|
return this._queryTimeout;
|
||||||
|
}
|
||||||
|
set queryTimeout(value) {
|
||||||
|
this._queryTimeout = value;
|
||||||
|
}
|
||||||
|
get majorityThreshold() {
|
||||||
|
return this._majorityThreshold;
|
||||||
|
}
|
||||||
|
set majorityThreshold(value) {
|
||||||
|
this._majorityThreshold = value;
|
||||||
|
}
|
||||||
|
get force() {
|
||||||
|
return this._force;
|
||||||
|
}
|
||||||
|
set force(value) {
|
||||||
|
this._force = value;
|
||||||
|
}
|
||||||
|
addRelay(pubkey) {
|
||||||
|
this._relays.push(pubkey);
|
||||||
|
this._relays = [...new Set(this._relays)];
|
||||||
|
}
|
||||||
|
query(query, chain, data = {}, force = false) {
|
||||||
|
return new RpcQuery(this, {
|
||||||
|
query,
|
||||||
|
chain,
|
||||||
|
data,
|
||||||
|
force: force || this._force,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
import RpcNetwork from "./rpcNetwork.js";
|
||||||
|
import { RPCRequest } from "./types";
|
||||||
|
export default class RpcQuery {
|
||||||
|
private _network;
|
||||||
|
private _query;
|
||||||
|
private _promise?;
|
||||||
|
private _timeoutTimer?;
|
||||||
|
private _timeout;
|
||||||
|
private _completed;
|
||||||
|
private _responses;
|
||||||
|
private _promiseResolve?;
|
||||||
|
constructor(network: RpcNetwork, query: RPCRequest);
|
||||||
|
get promise(): Promise<any>;
|
||||||
|
private handeTimeout;
|
||||||
|
private resolve;
|
||||||
|
private init;
|
||||||
|
private queryRelay;
|
||||||
|
private checkResponses;
|
||||||
|
private retry;
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=rpcQuery.d.ts.map
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"rpcQuery.d.ts","sourceRoot":"","sources":["../src/rpcQuery.ts"],"names":[],"mappings":"AACA,OAAO,UAAU,MAAM,iBAAiB,CAAC;AAEzC,OAAO,EAAC,UAAU,EAAc,MAAM,SAAS,CAAC;AAEhD,MAAM,CAAC,OAAO,OAAO,QAAQ;IAC3B,OAAO,CAAC,QAAQ,CAAa;IAC7B,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,QAAQ,CAAC,CAAe;IAChC,OAAO,CAAC,aAAa,CAAC,CAAM;IAC5B,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,UAAU,CAAwC;IAC1D,OAAO,CAAC,eAAe,CAAC,CAAsB;gBAElC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU;IAMlD,IAAI,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,CAE1B;IAED,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,OAAO;YAQD,IAAI;YA2BJ,UAAU;IAiBxB,OAAO,CAAC,cAAc;IA6BtB,OAAO,CAAC,KAAK;CASd"}
|
|
@ -0,0 +1,88 @@
|
||||||
|
import { clearTimeout, setTimeout } from "timers";
|
||||||
|
import { pack, unpack } from "msgpackr";
|
||||||
|
export default class RpcQuery {
|
||||||
|
constructor(network, query) {
|
||||||
|
this._timeout = false;
|
||||||
|
this._completed = false;
|
||||||
|
this._responses = {};
|
||||||
|
this._network = network;
|
||||||
|
this._query = query;
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
get promise() {
|
||||||
|
return this._promise;
|
||||||
|
}
|
||||||
|
handeTimeout() {
|
||||||
|
this.resolve(false, true);
|
||||||
|
}
|
||||||
|
resolve(data, timeout = false) {
|
||||||
|
clearTimeout(this._timeoutTimer);
|
||||||
|
this._timeout = timeout;
|
||||||
|
this._completed = true;
|
||||||
|
// @ts-ignore
|
||||||
|
this._promiseResolve(data);
|
||||||
|
}
|
||||||
|
async init() {
|
||||||
|
this._promise =
|
||||||
|
this._promise ??
|
||||||
|
new Promise((resolve) => {
|
||||||
|
this._promiseResolve = resolve;
|
||||||
|
});
|
||||||
|
this._timeoutTimer =
|
||||||
|
this._timeoutTimer ??
|
||||||
|
setTimeout(this.handeTimeout.bind(this), this._network.queryTimeout * 1000);
|
||||||
|
await this._network.ready;
|
||||||
|
const promises = [];
|
||||||
|
// tslint:disable-next-line:forin
|
||||||
|
for (const relay of this._network.relays) {
|
||||||
|
promises.push(this.queryRelay(relay));
|
||||||
|
}
|
||||||
|
await Promise.allSettled(promises);
|
||||||
|
this.checkResponses();
|
||||||
|
}
|
||||||
|
async queryRelay(relay) {
|
||||||
|
const socket = this._network.dht.connect(Buffer.from(relay, "hex"));
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
socket.on("data", (res) => {
|
||||||
|
socket.end();
|
||||||
|
const response = unpack(res);
|
||||||
|
if (response && response.error) {
|
||||||
|
return reject(response);
|
||||||
|
}
|
||||||
|
this._responses[relay] = response;
|
||||||
|
resolve(null);
|
||||||
|
});
|
||||||
|
socket.on("error", (error) => reject({ error }));
|
||||||
|
socket.write(pack(this._query));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
checkResponses() {
|
||||||
|
const responses = {};
|
||||||
|
const responseStore = this._responses;
|
||||||
|
const responseStoreKeys = Object.keys(responseStore);
|
||||||
|
// tslint:disable-next-line:forin
|
||||||
|
for (const peer in responseStore) {
|
||||||
|
const responseIndex = responseStoreKeys.indexOf(peer);
|
||||||
|
responses[responseIndex] = responses[responseIndex] ?? 0;
|
||||||
|
responses[responseIndex]++;
|
||||||
|
}
|
||||||
|
for (const responseIndex in responses) {
|
||||||
|
if (responses[responseIndex] / responseStoreKeys.length >= this._network.majorityThreshold) {
|
||||||
|
const response = responseStore[responseStoreKeys[parseInt(responseIndex, 10)]];
|
||||||
|
// @ts-ignore
|
||||||
|
if (null === response || null === response?.data) {
|
||||||
|
this.retry();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.resolve(response?.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retry() {
|
||||||
|
this._responses = {};
|
||||||
|
if (this._completed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
export interface RPCRequest {
|
||||||
|
force: boolean;
|
||||||
|
chain: string;
|
||||||
|
query: string;
|
||||||
|
data: any;
|
||||||
|
}
|
||||||
|
export interface RPCResponse {
|
||||||
|
updated: number;
|
||||||
|
data: any | {
|
||||||
|
error: string | boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=types.d.ts.map
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACvB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,GAAG,CAAC;CACb;AAED,MAAM,WAAW,WAAW;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EACE,GAAG,GACH;QACF,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;KAC3B,CAAC;CACL"}
|
|
@ -0,0 +1 @@
|
||||||
|
export {};
|
Loading…
Reference in New Issue