rpc-client/dist/network.js

121 lines
3.5 KiB
JavaScript
Raw Normal View History

2022-08-28 06:33:49 +00:00
// @ts-ignore
2023-03-18 16:11:41 +00:00
import Hyperswarm from "hyperswarm";
2022-12-04 11:37:24 +00:00
import RpcNetworkQueryFactory from "./query/index.js";
2023-03-18 16:11:41 +00:00
import b4a from "b4a";
2023-03-25 14:51:42 +00:00
import { createHash, maybeGetAsyncProperty } from "./util.js";
2022-08-28 06:33:49 +00:00
export default class RpcNetwork {
2023-03-18 16:11:41 +00:00
_relaysAvailablePromise;
_relaysAvailableResolve;
constructor(swarm = new Hyperswarm()) {
this._swarm = swarm;
this.init();
}
_methods = new Map();
get methods() {
return this._methods;
2022-08-28 06:33:49 +00:00
}
2022-12-04 11:37:24 +00:00
_factory = new RpcNetworkQueryFactory(this);
get factory() {
return this._factory;
}
2023-03-18 16:11:41 +00:00
_swarm;
get swarm() {
return this._swarm;
2022-08-28 06:33:49 +00:00
}
_majorityThreshold = 0.75;
get majorityThreshold() {
return this._majorityThreshold;
}
set majorityThreshold(value) {
this._majorityThreshold = value;
}
_queryTimeout = 30;
get queryTimeout() {
return this._queryTimeout;
}
set queryTimeout(value) {
this._queryTimeout = value;
}
_relayTimeout = 2;
get relayTimeout() {
return this._relayTimeout;
}
set relayTimeout(value) {
this._relayTimeout = value;
}
2023-03-18 16:11:41 +00:00
_relays = new Map();
2022-08-28 06:33:49 +00:00
get relays() {
return this._relays;
}
_ready;
get ready() {
if (!this._ready) {
2023-03-25 14:51:42 +00:00
this._ready = maybeGetAsyncProperty(this._swarm.dht).then((dht) => dht.ready());
2022-08-28 06:33:49 +00:00
}
return this._ready;
}
2023-03-18 16:11:41 +00:00
get readyWithRelays() {
return this.ready.then(() => this._relaysAvailablePromise);
}
2022-08-28 06:33:49 +00:00
_bypassCache = false;
get bypassCache() {
return this._bypassCache;
}
set bypassCache(value) {
this._bypassCache = value;
}
2023-03-18 16:11:41 +00:00
getAvailableRelay(module, method) {
method = `${module}.${method}`;
let relays = this._methods.get(method) ?? new Set();
if (!relays.size) {
throw Error("no available relay");
2022-08-28 06:33:49 +00:00
}
2023-03-19 19:11:34 +00:00
return this._relays.get(Array.from(relays)[Math.floor(Math.random() * relays.size)]);
2022-08-28 06:33:49 +00:00
}
2023-03-18 16:11:41 +00:00
getRelay(pubkey) {
if (this._relays.has(pubkey)) {
return this._relays.get(pubkey);
}
return undefined;
}
init() {
this._swarm.join(createHash("lumeweb"));
this.setupRelayPromise();
this._swarm.on("connection", async (relay) => {
2023-03-25 14:51:42 +00:00
const pubkey = b4a
.from(await maybeGetAsyncProperty(relay.remotePublicKey))
.toString("hex");
2023-03-18 18:49:36 +00:00
relay.once("close", () => {
this._methods.forEach((item) => {
if (item.has(pubkey)) {
item.delete(pubkey);
}
});
this.relays.delete(pubkey);
if (!this._relays.size) {
this.setupRelayPromise();
}
});
2023-03-18 16:11:41 +00:00
const query = this._factory.simple({
relay,
query: { module: "core", method: "get_methods", data: null },
});
const resp = await query.result;
if (resp.data) {
this._relays.set(pubkey, relay);
resp.data.forEach((item) => {
const methods = this._methods.get(item) ?? new Set();
methods.add(pubkey);
this._methods.set(item, methods);
});
this._relaysAvailableResolve?.();
}
});
}
setupRelayPromise() {
this._relaysAvailablePromise = new Promise((resolve) => {
this._relaysAvailableResolve = resolve;
});
2022-08-28 06:33:49 +00:00
}
}