From 18756c55339e65b2d3ef579b46e2967f1050ac1d Mon Sep 17 00:00:00 2001 From: Derrick Hammer Date: Sun, 28 Aug 2022 13:07:45 -0400 Subject: [PATCH] *Initial version --- LICENSE | 2 +- build.js | 9 ++++ build.sh | 9 ++++ package.json | 17 ++++++++ src/index.ts | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++ tsconfig.json | 14 ++++++ 6 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 build.js create mode 100644 build.sh create mode 100644 package.json create mode 100644 src/index.ts create mode 100644 tsconfig.json diff --git a/LICENSE b/LICENSE index 13a5b6e..8995c8b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Lume Web +Copyright (c) 2022 Hammer Technologies LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/build.js b/build.js new file mode 100644 index 0000000..dafa52b --- /dev/null +++ b/build.js @@ -0,0 +1,9 @@ +import esbuild from 'esbuild' + +esbuild.buildSync({ + entryPoints: ['src/index.ts'], + outfile: 'dist/handshake.js', + format: 'cjs', + bundle: true, + platform: "node" +}) diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..c13ad15 --- /dev/null +++ b/build.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +node build.js +mkdir -p dist/build/Release +cp node_modules/bdb/build/Release/leveldown.node dist/build/Release/leveldown.node +cp node_modules/bcrypto/build/Release/bcrypto.node dist/build/Release/bcrypto.node +cp node_modules/goosig/build/Release/goosig.node dist/build/Release/goosig.node +cp node_modules/mrmr/build/Release/mrmr.node dist/build/Release/mrmr.node +cp node_modules/hsd/lib/covenants/names.db dist diff --git a/package.json b/package.json new file mode 100644 index 0000000..1f10c77 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "@lumeweb/relay-plugin-handshake", + "type": "module", + "version": "0.1.0", + "scripts": { + "build": "bash build.sh" + }, + "devDependencies": { + "@lumeweb/relay": "https://github.com/LumeWeb/relay.git", + "esbuild": "^0.15.5" + }, + "dependencies": { + "hs-client": "^0.0.11", + "hsd": "^4.0.1", + "random-key": "^0.3.2" + } +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..130abdf --- /dev/null +++ b/src/index.ts @@ -0,0 +1,116 @@ +import type { + Plugin, + PluginAPI, + RPCResponse, + RPCRequest, +} from "@lumeweb/relay"; +// @ts-ignore +import rand from "random-key"; +// @ts-ignore +import SPVNode from "hsd/lib/node/spvnode.js"; +// @ts-ignore +import { NodeClient } from "hs-client"; + +async function boot(config: any) { + let hsdServer: SPVNode; + + let clientArgs = { + network: "main", + host: "127.0.0.1", + port: 12037, + apiKey: rand.generate(), + }; + + if (!config.bool("hsd-use-external-node")) { + hsdServer = new SPVNode({ + config: false, + argv: false, + env: true, + noDns: true, + memory: false, + httpHost: "127.0.0.1", + apiKey: clientArgs.apiKey, + logFile: false, + logConsole: true, + logLevel: "info", + workers: true, + network: "main", + }); + hsdServer.on("abort", async (err: any) => { + const timeout = setTimeout(() => { + console.error("Shutdown is taking a long time. Exiting."); + process.exit(3); + }, 5000); + + timeout.unref(); + + try { + console.error("Shutting down..."); + await hsdServer.close(); + clearTimeout(timeout); + console.error((err as Error).stack); + process.exit(2); + } catch (e: any) { + console.error( + `Error occurred during shutdown: ${(e as Error).message}` + ); + process.exit(3); + } + }); + + (async () => { + try { + await hsdServer.ensure(); + await hsdServer.open(); + await hsdServer.connect(); + + hsdServer.startSync(); + } catch (e: any) { + console.error((e as Error).stack); + } + })(); + } else { + clientArgs = { + network: config.str("hsd-network-type"), + host: config.str("hsd-host"), + port: config.uint("hsd-port"), + apiKey: config.str("hsd-api-key"), + }; + } + + return new NodeClient(clientArgs); +} + +const plugin: Plugin = { + name: "handshake", + async plugin(api: PluginAPI): Promise { + const client = await boot(api.config); + + api.registerMethod("getnameresource", { + cacheable: true, + async handler(request: RPCRequest): Promise { + let resp; + try { + resp = await client.execute("getnameresource", request.data); + } catch (e: any) { + e = e as Error; + const eType = e.type.toLowerCase(); + const eMessage = e.message.toLowerCase(); + + if ( + eType === "rpcerror" && + eMessage.includes("chain is not synced") + ) { + throw new Error("NOT_READY"); + } + + throw e; + } + + return resp; + }, + }); + }, +}; + +export default plugin; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e9191d7 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "src", + "outDir": "dist", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "resolveJsonModule": true + } +}