*Initial merge of rpcproxy
This commit is contained in:
parent
660bb85203
commit
8d95dde848
|
@ -11,27 +11,35 @@
|
|||
"dependencies": {
|
||||
"@hyperswarm/dht": "^6.0.1",
|
||||
"@hyperswarm/dht-relay": "^0.3.0",
|
||||
"@pokt-network/pocket-js": "^0.8.0-rc",
|
||||
"@root/greenlock": "^4.0.5",
|
||||
"@solana/web3.js": "^1.47.3",
|
||||
"@types/node": "^18.0.0",
|
||||
"@types/node-cron": "^3.0.2",
|
||||
"@types/ws": "^8.5.3",
|
||||
"@types/xml2js": "^0.4.11",
|
||||
"async-mutex": "^0.3.2",
|
||||
"dotenv": "^16.0.1",
|
||||
"ethers": "^5.6.9",
|
||||
"express": "^4.18.1",
|
||||
"greenlock-express": "^4.0.3",
|
||||
"jayson": "^3.6.6",
|
||||
"json-stable-stringify": "^1.0.1",
|
||||
"libskynet": "^0.0.48",
|
||||
"libskynetnode": "^0.1.3",
|
||||
"minimatch": "^5.1.0",
|
||||
"msgpackr": "^1.6.1",
|
||||
"node-cache": "^5.1.2",
|
||||
"node-cron": "^3.0.1",
|
||||
"node-fetch": "^3.2.6",
|
||||
"random-access-memory": "^4.1.0",
|
||||
"sprintf-js": "^1.1.2",
|
||||
"xml2js": "^0.4.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/minimatch": "^3.0.5",
|
||||
"@types/sprintf-js": "^1.1.2",
|
||||
"hyper-typings": "^1.0.0",
|
||||
"prettier": "^2.7.1"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,33 @@
|
|||
import fs from "fs";
|
||||
import dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const envPath = path.resolve(__dirname, "..", "lumerelay.env");
|
||||
|
||||
if (fs.existsSync(envPath)) {
|
||||
dotenv.config({ path: envPath });
|
||||
}
|
||||
|
||||
export const RELAY_PORT = process.env.RELAY_PORT ?? 8080;
|
||||
export const RELAY_DOMAIN = process.env.RELAY_DOMAIN;
|
||||
export const AFRAID_USERNAME = process.env.AFRAID_USERNAME;
|
||||
export const AFRAID_PASSWORD = process.env.AFRAID_PASSWORD;
|
||||
export const RELAY_SEED = process.env.RELAY_SEED;
|
||||
export const POCKET_APP_ID = process.env.POCKET_APP_ID || false;
|
||||
export const POCKET_APP_KEY = process.env.POCKET_APP_KEY || false;
|
||||
export const POCKET_ACCOUNT_PUBLIC_KEY =
|
||||
process.env.POCKET_ACCOUNT_PUBLIC_KEY || false;
|
||||
export const POCKET_ACCOUNT_PRIVATE_KEY =
|
||||
process.env.POCKET_ACCOUNT_PRIVATE_KEY || false;
|
||||
|
||||
export const HSD_NETWORK_TYPE = process.env.HSD_NETWORK || "main";
|
||||
export const HSD_HOST = process.env.HSD_HOST || "localhost";
|
||||
export const HSD_PORT = Number(process.env.HSD_PORT) || 12037;
|
||||
export const HSD_API_KEY = process.env.HSD_API_KEY || "foo";
|
||||
|
||||
export const POCKET_HOST = process.env.POCKET_HOST || "localhost";
|
||||
export const POCKET_PORT = process.env.POCKET_PORT || 8081;
|
||||
|
|
|
@ -4,7 +4,7 @@ let error = false;
|
|||
|
||||
for (const constant in CONFIG) {
|
||||
// @ts-ignore
|
||||
if (!CONFIG[constant]) {
|
||||
if (CONFIG[constant] === null || CONFIG[constant] === undefined) {
|
||||
console.error(`Missing constant ${constant}`);
|
||||
error = true;
|
||||
}
|
||||
|
@ -14,4 +14,14 @@ if (error) {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
let usingPocketGateway = true;
|
||||
|
||||
export function usePocketGateway() {
|
||||
return usingPocketGateway;
|
||||
}
|
||||
|
||||
export function updateUsePocketGateway(state: boolean): void {
|
||||
usingPocketGateway = state;
|
||||
}
|
||||
|
||||
export * from "./constant_vars.js";
|
||||
|
|
152
src/rpc.ts
152
src/rpc.ts
|
@ -5,16 +5,41 @@ import { Mutex } from "async-mutex";
|
|||
import { createRequire } from "module";
|
||||
import NodeCache from "node-cache";
|
||||
import { get as getDHT } from "./dht.js";
|
||||
import {
|
||||
POCKET_ACCOUNT_PRIVATE_KEY,
|
||||
POCKET_ACCOUNT_PUBLIC_KEY,
|
||||
POCKET_APP_ID,
|
||||
POCKET_APP_KEY,
|
||||
POCKET_HOST,
|
||||
POCKET_PORT,
|
||||
} from "./constant_vars";
|
||||
import { updateUsePocketGateway, usePocketGateway } from "./constants";
|
||||
import { Server as JSONServer } from "jayson/promise/index.js";
|
||||
import { rpcMethods } from "./rpc/index.js";
|
||||
import {
|
||||
Configuration,
|
||||
HttpRpcProvider,
|
||||
Pocket,
|
||||
PocketAAT,
|
||||
} from "@pokt-network/pocket-js";
|
||||
import {
|
||||
JSONRPCRequest,
|
||||
JSONRPCResponseWithError,
|
||||
JSONRPCResponseWithResult,
|
||||
} from "jayson";
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
const stringify = require("json-stable-stringify");
|
||||
|
||||
const clients: { [chain: string]: any } = {};
|
||||
const pendingRequests = new NodeCache();
|
||||
const processedRequests = new NodeCache({
|
||||
stdTTL: 60 * 60 * 12,
|
||||
});
|
||||
|
||||
let pocketServer: Pocket;
|
||||
let _aat: PocketAAT;
|
||||
let jsonServer: jayson.Server;
|
||||
|
||||
interface RPCRequest {
|
||||
force: boolean;
|
||||
chain: string;
|
||||
|
@ -35,23 +60,6 @@ function hash(data: string): string {
|
|||
return crypto.createHash("sha256").update(data).digest("hex");
|
||||
}
|
||||
|
||||
function getClient(chain: string): Function {
|
||||
chain = chain.replace(/[^a-z0-9\-]/g, "");
|
||||
|
||||
if (!(chain in clients)) {
|
||||
clients[chain] = jayson.Client.http({
|
||||
host: process.env.RPC_PROXY_HOST,
|
||||
port: parseInt(process.env.RPC_PROXY_PORT as string),
|
||||
path: "/",
|
||||
headers: {
|
||||
"X-Chain": chain,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return clients[chain];
|
||||
}
|
||||
|
||||
function getRequestId(request: RPCRequest) {
|
||||
const clonedRequest = Object.assign({}, request);
|
||||
|
||||
|
@ -98,10 +106,13 @@ async function processRequest(request: RPCRequest): Promise<RPCResponse> {
|
|||
|
||||
let error;
|
||||
try {
|
||||
// @ts-ignore
|
||||
rpcResp = await getClient(request.chain).request(
|
||||
request.query,
|
||||
request.data
|
||||
rpcResp = await processRpcRequest(
|
||||
{
|
||||
method: request.query,
|
||||
jsonrpc: "2.0",
|
||||
params: request.data,
|
||||
} as unknown as JSONRPCRequest,
|
||||
request.chain
|
||||
);
|
||||
} catch (e) {
|
||||
error = (e as Error).message;
|
||||
|
@ -113,15 +124,22 @@ async function processRequest(request: RPCRequest): Promise<RPCResponse> {
|
|||
};
|
||||
|
||||
if (rpcResp) {
|
||||
rpcResp = rpcResp as JSONRPCResponseWithResult;
|
||||
if (false === rpcResp.result) {
|
||||
error = true;
|
||||
}
|
||||
|
||||
rpcResp = rpcResp as unknown as JSONRPCResponseWithError;
|
||||
|
||||
if (rpcResp.error) {
|
||||
// @ts-ignore
|
||||
error = rpcResp.error.message;
|
||||
}
|
||||
}
|
||||
|
||||
dbData.data = error ? { error } : rpcResp.result;
|
||||
dbData.data = error
|
||||
? { error }
|
||||
: (rpcResp as unknown as JSONRPCResponseWithResult).result;
|
||||
|
||||
if (!processedRequests.get(reqId) || request.force) {
|
||||
processedRequests.set(reqId, dbData);
|
||||
|
@ -132,7 +150,93 @@ async function processRequest(request: RPCRequest): Promise<RPCResponse> {
|
|||
return dbData;
|
||||
}
|
||||
|
||||
export function updateAat(aat: PocketAAT): void {
|
||||
_aat = aat;
|
||||
}
|
||||
|
||||
export function getAat(): PocketAAT {
|
||||
return _aat;
|
||||
}
|
||||
export function getPocketServer(): Pocket {
|
||||
return pocketServer;
|
||||
}
|
||||
|
||||
export async function unlockAccount(
|
||||
accountPrivateKey: string,
|
||||
accountPublicKey: string,
|
||||
accountPassphrase: string
|
||||
): Promise<PocketAAT> {
|
||||
try {
|
||||
const account = await pocketServer.keybase.importAccount(
|
||||
Buffer.from(accountPrivateKey, "hex"),
|
||||
accountPassphrase
|
||||
);
|
||||
|
||||
if (account instanceof Error) {
|
||||
// noinspection ExceptionCaughtLocallyJS
|
||||
throw account;
|
||||
}
|
||||
|
||||
await pocketServer.keybase.unlockAccount(
|
||||
account.addressHex,
|
||||
accountPassphrase,
|
||||
0
|
||||
);
|
||||
|
||||
return await PocketAAT.from(
|
||||
"0.0.1",
|
||||
accountPublicKey,
|
||||
accountPublicKey,
|
||||
accountPrivateKey
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
export async function processRpcRequest(
|
||||
request: JSONRPCRequest,
|
||||
chain: string
|
||||
): Promise<JSONRPCResponseWithResult | JSONRPCResponseWithError | undefined> {
|
||||
return new Promise((resolve) => {
|
||||
jsonServer.call(
|
||||
request,
|
||||
{ chain },
|
||||
(
|
||||
err?: JSONRPCResponseWithError | null,
|
||||
result?: JSONRPCResponseWithResult
|
||||
): void => {
|
||||
if (err) {
|
||||
return resolve(err);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export async function start() {
|
||||
if (!POCKET_APP_ID || !POCKET_APP_KEY) {
|
||||
const dispatchURL = new URL(`http://${POCKET_HOST}:${POCKET_PORT}`);
|
||||
const rpcProvider = new HttpRpcProvider(dispatchURL);
|
||||
const configuration = new Configuration();
|
||||
pocketServer = new Pocket([dispatchURL], rpcProvider, configuration);
|
||||
updateUsePocketGateway(false);
|
||||
}
|
||||
|
||||
if (!usePocketGateway()) {
|
||||
updateAat(
|
||||
await unlockAccount(
|
||||
<string>POCKET_ACCOUNT_PRIVATE_KEY,
|
||||
<string>POCKET_ACCOUNT_PUBLIC_KEY,
|
||||
"0"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
jsonServer = new JSONServer(rpcMethods, { useContext: true });
|
||||
|
||||
(await getDHT()).on("connection", (socket: any) => {
|
||||
socket.on("data", async (data: any) => {
|
||||
let request: RPCRequest;
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
import { maybeMapChainId, reverseMapChainId } from "../util.js";
|
||||
import minimatch from "minimatch";
|
||||
// @ts-ignore
|
||||
import HTTPClient from "algosdk/dist/cjs/src/client/client.js";
|
||||
import { sprintf } from "sprintf-js";
|
||||
import { RpcMethodList } from "./index.js";
|
||||
import { POCKET_APP_ID } from "../constants.js";
|
||||
|
||||
const allowedEndpoints: { [endpoint: string]: ("GET" | "POST")[] } = {
|
||||
"/v2/teal/compile": ["POST"],
|
||||
"/v2/accounts/*": ["GET"],
|
||||
};
|
||||
|
||||
export function proxyRestMethod(
|
||||
apiServer: string,
|
||||
matchChainId: string
|
||||
): Function {
|
||||
return async function (args: any, context: object) {
|
||||
// @ts-ignore
|
||||
let chain = context.chain;
|
||||
let chainId = maybeMapChainId(chain);
|
||||
|
||||
if (!chainId) {
|
||||
throw new Error("Invalid Chain");
|
||||
}
|
||||
|
||||
chainId = reverseMapChainId(chainId as string);
|
||||
if (!chainId || chainId !== matchChainId) {
|
||||
throw new Error("Invalid Chain");
|
||||
}
|
||||
|
||||
let method = args.method ?? false;
|
||||
let endpoint = args.endpoint ?? false;
|
||||
let data = args.data ?? false;
|
||||
let query = args.query ?? false;
|
||||
let fullHeaders = args.fullHeaders ?? {};
|
||||
|
||||
fullHeaders = { ...fullHeaders, Referer: "lumeweb_dns_relay" };
|
||||
|
||||
if (method) {
|
||||
method = method.toUpperCase();
|
||||
}
|
||||
|
||||
if (!endpoint) {
|
||||
throw new Error("Endpoint Missing");
|
||||
}
|
||||
|
||||
let found = false;
|
||||
|
||||
for (const theEndpoint in allowedEndpoints) {
|
||||
if (minimatch(endpoint, theEndpoint)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
throw new Error("Endpoint Invalid");
|
||||
}
|
||||
|
||||
let apiUrl;
|
||||
try {
|
||||
apiUrl = sprintf(apiServer, chainId, POCKET_APP_ID);
|
||||
} catch (e) {
|
||||
apiUrl = apiServer;
|
||||
}
|
||||
|
||||
const client = new HTTPClient({}, apiUrl);
|
||||
let resp;
|
||||
switch (method) {
|
||||
case "GET":
|
||||
resp = await client.get(endpoint, query, fullHeaders);
|
||||
break;
|
||||
case "POST":
|
||||
if (Array.isArray(data?.data)) {
|
||||
data = new Uint8Array(Buffer.from(data.data));
|
||||
}
|
||||
|
||||
resp = await client.post(endpoint, data, { ...fullHeaders });
|
||||
break;
|
||||
default:
|
||||
throw new Error("Method Invalid");
|
||||
}
|
||||
|
||||
const getCircularReplacer = () => {
|
||||
const seen = new WeakSet();
|
||||
return (key: string, value: any): any => {
|
||||
if (typeof value === "object" && value !== null) {
|
||||
if (seen.has(value)) {
|
||||
return;
|
||||
}
|
||||
seen.add(value);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
};
|
||||
|
||||
return JSON.parse(JSON.stringify(resp, getCircularReplacer()));
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
algorand_rest_request: proxyRestMethod(
|
||||
"http://mainnet-api.algonode.network",
|
||||
"algorand-mainnet"
|
||||
),
|
||||
//'algorand_rest_request': proxyRestMethod("https://%s.gateway.pokt.network/v1/lb/%s", "algorand-mainnet"),
|
||||
algorand_rest_indexer_request: proxyRestMethod(
|
||||
"http://mainnet-idx.algonode.network",
|
||||
"algorand-mainnet-indexer"
|
||||
),
|
||||
} as RpcMethodList;
|
|
@ -0,0 +1,100 @@
|
|||
import { ethers } from "ethers";
|
||||
import { PocketAAT } from "@pokt-network/pocket-js";
|
||||
import { maybeMapChainId, reverseMapChainId } from "../util.js";
|
||||
import { Connection } from "@solana/web3.js";
|
||||
import {
|
||||
POCKET_APP_ID,
|
||||
POCKET_APP_KEY,
|
||||
usePocketGateway,
|
||||
} from "../constants.js";
|
||||
import { getAat, getPocketServer } from "../rpc.js";
|
||||
|
||||
export const chainNetworks = require("../../networks.json");
|
||||
|
||||
type RpcProviderMethod = (method: string, params: Array<any>) => Promise<any>;
|
||||
|
||||
const gatewayProviders: { [name: string]: RpcProviderMethod } = {};
|
||||
|
||||
const gatewayMethods: {
|
||||
[name: string]: (chainId: string) => RpcProviderMethod;
|
||||
} = {
|
||||
default: (chainId: string): RpcProviderMethod => {
|
||||
const provider = new ethers.providers.JsonRpcProvider({
|
||||
url: `https://${chainId}.gateway.pokt.network/v1/lb/${POCKET_APP_ID}`,
|
||||
password: <string>POCKET_APP_KEY,
|
||||
});
|
||||
return provider.send.bind(provider);
|
||||
},
|
||||
"sol-mainnet": (chainId: string): RpcProviderMethod => {
|
||||
const provider = new Connection(
|
||||
`https://solana-mainnet.gateway.pokt.network/v1/lb/${POCKET_APP_ID}`
|
||||
);
|
||||
|
||||
// @ts-ignore
|
||||
return provider._rpcRequest.bind(provider);
|
||||
},
|
||||
};
|
||||
|
||||
export function proxyRpcMethod(
|
||||
method: string,
|
||||
chains: string[] = []
|
||||
): Function {
|
||||
return async function (args: any, context: object) {
|
||||
// @ts-ignore
|
||||
let chain = context.chain;
|
||||
let chainId = maybeMapChainId(chain);
|
||||
|
||||
let chainMatch = true;
|
||||
|
||||
if (
|
||||
chains.length > 0 &&
|
||||
!chains.includes(chain) &&
|
||||
!chains.includes(chainId.toString())
|
||||
) {
|
||||
chainMatch = false;
|
||||
}
|
||||
|
||||
if (!chainId || !chainMatch) {
|
||||
throw new Error("Invalid Chain");
|
||||
}
|
||||
|
||||
if (usePocketGateway()) {
|
||||
chainId = reverseMapChainId(chainId as string);
|
||||
if (!chainId) {
|
||||
throw new Error("Invalid Chain");
|
||||
}
|
||||
|
||||
let provider: RpcProviderMethod | boolean =
|
||||
gatewayProviders[chainId as string] || false;
|
||||
if (!provider) {
|
||||
provider = getRpcProvider(chainId as string);
|
||||
}
|
||||
gatewayProviders[chainId as string] = provider;
|
||||
return await provider(method, args);
|
||||
}
|
||||
|
||||
return await sendRelay(JSON.stringify(args), <string>chainId, getAat());
|
||||
};
|
||||
}
|
||||
|
||||
// Call this every time you want to fetch RPC data
|
||||
async function sendRelay(
|
||||
rpcQuery: string,
|
||||
blockchain: string,
|
||||
pocketAAT: PocketAAT
|
||||
) {
|
||||
try {
|
||||
return await getPocketServer().sendRelay(rpcQuery, blockchain, pocketAAT);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
function getRpcProvider(chain: string): RpcProviderMethod {
|
||||
if (chain in gatewayMethods) {
|
||||
return gatewayMethods[chain](chain);
|
||||
}
|
||||
|
||||
return gatewayMethods.default(chain);
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
import { isIp } from "../util.js";
|
||||
import { RpcMethodList } from "./index.js";
|
||||
|
||||
const bns = require("bns");
|
||||
const { StubResolver, RecursiveResolver } = bns;
|
||||
|
||||
const resolverOpt = {
|
||||
tcp: true,
|
||||
inet6: false,
|
||||
edns: true,
|
||||
dnssec: true,
|
||||
};
|
||||
|
||||
const globalResolver = new RecursiveResolver(resolverOpt);
|
||||
globalResolver.hints.setDefault();
|
||||
globalResolver.open();
|
||||
|
||||
async function resolveNameServer(ns: string): Promise<string | boolean> {
|
||||
if (isIp(ns)) {
|
||||
return ns;
|
||||
}
|
||||
let result = await getDnsRecords(ns, "A");
|
||||
|
||||
if (result.length) {
|
||||
return result[0];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
async function getDnsRecords(
|
||||
domain: string,
|
||||
type: string,
|
||||
authority: boolean = false,
|
||||
resolver = globalResolver
|
||||
): Promise<string[]> {
|
||||
let result;
|
||||
|
||||
try {
|
||||
result = await resolver.lookup(domain, type);
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let prop = authority ? "authority" : "answer";
|
||||
|
||||
if (!result || !result[prop].length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return result[prop].map(
|
||||
(item: object) =>
|
||||
// @ts-ignore
|
||||
item.data.address ?? item.data.target ?? item.data.ns ?? null
|
||||
);
|
||||
}
|
||||
|
||||
export default {
|
||||
dnslookup: async function (args: any) {
|
||||
let dnsResults: string[] = [];
|
||||
let domain = args.domain;
|
||||
let ns = args.nameserver;
|
||||
let dnsResolver = ns ? new StubResolver(resolverOpt) : globalResolver;
|
||||
await dnsResolver.open();
|
||||
|
||||
if (ns) {
|
||||
let nextNs = ns;
|
||||
let prevNs = null;
|
||||
|
||||
while (nextNs) {
|
||||
nextNs = await resolveNameServer(nextNs);
|
||||
if (!nextNs) {
|
||||
nextNs = prevNs;
|
||||
}
|
||||
|
||||
dnsResolver.setServers([nextNs]);
|
||||
|
||||
if (nextNs === prevNs) {
|
||||
break;
|
||||
}
|
||||
let result = await getDnsRecords(domain, "NS", true, dnsResolver);
|
||||
prevNs = nextNs;
|
||||
nextNs = result.length ? result[0] : false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const queryType of ["CNAME", "A"]) {
|
||||
let result = await getDnsRecords(domain, queryType, false, dnsResolver);
|
||||
|
||||
if (result) {
|
||||
dnsResults = dnsResults.concat(result);
|
||||
}
|
||||
}
|
||||
|
||||
await dnsResolver.close();
|
||||
|
||||
dnsResults = dnsResults.filter(Boolean);
|
||||
|
||||
if (dnsResults.length) {
|
||||
return dnsResults[0];
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
} as RpcMethodList;
|
|
@ -0,0 +1,14 @@
|
|||
import { proxyRpcMethod } from "./common.js";
|
||||
import { RpcMethodList } from "./index.js";
|
||||
|
||||
const rpcMethods: RpcMethodList = {};
|
||||
|
||||
function proxyEvmRpcMethod(method: string): Function {
|
||||
return proxyRpcMethod(method);
|
||||
}
|
||||
|
||||
["eth_call", "eth_chainId", "net_version"].forEach((method) => {
|
||||
rpcMethods[method] = proxyEvmRpcMethod(method);
|
||||
});
|
||||
|
||||
export default rpcMethods;
|
|
@ -0,0 +1,27 @@
|
|||
import { RpcMethodList } from "./index.js";
|
||||
import {
|
||||
HSD_API_KEY,
|
||||
HSD_HOST,
|
||||
HSD_NETWORK_TYPE,
|
||||
HSD_PORT,
|
||||
} from "../constant_vars.js";
|
||||
|
||||
const { NodeClient } = require("hs-client");
|
||||
|
||||
const hnsClient = new NodeClient({
|
||||
network: HSD_NETWORK_TYPE,
|
||||
host: HSD_HOST,
|
||||
port: HSD_PORT,
|
||||
apiKey: HSD_API_KEY,
|
||||
});
|
||||
|
||||
export default {
|
||||
getnameresource: async function (args: any, context: object) {
|
||||
// @ts-ignore
|
||||
if ("hns" !== context.chain) {
|
||||
throw new Error("Invalid Chain");
|
||||
}
|
||||
|
||||
return await hnsClient.execute("getnameresource", args);
|
||||
},
|
||||
} as RpcMethodList;
|
|
@ -0,0 +1,18 @@
|
|||
export type RpcMethodList = { [name: string]: Function };
|
||||
|
||||
export * from "./common.js";
|
||||
|
||||
import { default as DnsMethods } from "./dns.js";
|
||||
import { default as EvmMethods } from "./evm.js";
|
||||
import { default as HnsMethods } from "./handshake.js";
|
||||
import { default as SolMethods } from "./solana.js";
|
||||
import { default as AlgoMethods } from "./algorand.js";
|
||||
|
||||
export const rpcMethods: RpcMethodList = Object.assign(
|
||||
{},
|
||||
DnsMethods,
|
||||
EvmMethods,
|
||||
HnsMethods,
|
||||
SolMethods,
|
||||
AlgoMethods
|
||||
);
|
|
@ -0,0 +1,8 @@
|
|||
import { chainNetworks, proxyRpcMethod } from "./common.js";
|
||||
import { RpcMethodList } from "./index.js";
|
||||
|
||||
export default {
|
||||
getAccountInfo: proxyRpcMethod("getAccountInfo", [
|
||||
chainNetworks["sol-mainnet"],
|
||||
]),
|
||||
} as RpcMethodList;
|
33
src/util.ts
33
src/util.ts
|
@ -1,4 +1,37 @@
|
|||
import { chainNetworks } from "./rpc/index.js";
|
||||
|
||||
export function errorExit(msg: string): void {
|
||||
console.error(msg);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
export function maybeMapChainId(chain: string): string | boolean {
|
||||
if (chain in chainNetworks) {
|
||||
return chainNetworks[chain];
|
||||
}
|
||||
|
||||
if (
|
||||
[parseInt(chain, 16).toString(), parseInt(chain, 10).toString()].includes(
|
||||
chain.toLowerCase()
|
||||
)
|
||||
) {
|
||||
return chain;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function reverseMapChainId(chainId: string): string | boolean {
|
||||
let vals = Object.values(chainNetworks);
|
||||
if (!vals.includes(chainId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Object.keys(chainNetworks)[vals.indexOf(chainId)];
|
||||
}
|
||||
|
||||
export function isIp(ip: string) {
|
||||
return /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(
|
||||
ip
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue