From df77bb4ffa60ca98c81dccd0fa7d4242079bad44 Mon Sep 17 00:00:00 2001 From: JP Lomas Date: Sat, 18 Jul 2020 12:15:45 +0100 Subject: [PATCH 1/6] Prep for new qrl-proto-sha256 --- package-lock.json | 10 ++++++++++ package.json | 2 ++ src/index.js | 43 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index ef9acdb..62dc68b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1464,6 +1464,11 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" }, + "@theqrl/qrl-proto-sha256": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@theqrl/qrl-proto-sha256/-/qrl-proto-sha256-2.0.3.tgz", + "integrity": "sha512-WJKkvZqwOdW8Mt6jDjKes948kNgA6PE5Kxvi1t+LNqeMDY1NjEyoB/MHXRo8iEzAz5BQSWKamyk5UNjaBtb2sA==" + }, "@theqrl/qrlbase.proto": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@theqrl/qrlbase.proto/-/qrlbase.proto-1.0.0.tgz", @@ -2387,6 +2392,11 @@ "which": "^1.2.9" } }, + "crypto-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz", + "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==" + }, "crypto-random-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", diff --git a/package.json b/package.json index 8e6b50e..bd52a49 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,9 @@ "@babel/polyfill": "^7.10.4", "@grpc/grpc-js": "^1.1.2", "@grpc/proto-loader": "^0.5.5", + "@theqrl/qrl-proto-sha256": "^2.0.3", "@theqrl/qrlbase.proto": "^1.0.0", + "crypto-js": "^4.0.0", "google-protobuf": "^3.12.2", "grpc-js-kit": "^0.1.0", "tmp": "^0.2.1" diff --git a/src/index.js b/src/index.js index eedaa4e..8e023ab 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,10 @@ require("@babel/polyfill") const grpc = require('@grpc/grpc-js') const protoLoader = require('@grpc/proto-loader') -const {createClient} = require('grpc-js-kit') +const CryptoJS = require('crypto-js') +const { createClient } = require('grpc-js-kit') const { promisify } = require('util') +const { QRLPROTO_SHA256 } = require('@theqrl/qrl-proto-sha256') const tmp = require('tmp') const fs = require('fs') const util = require('util') @@ -22,6 +24,22 @@ const clientGetNodeInfo = client => { }) } +async function checkProtoHash(file) { + return readFile(file).then(async contents => { + const protoFileWordArray = CryptoJS.lib.WordArray.create(contents.toString()) + const calculatedProtoHash = CryptoJS.SHA256(protoFileWordArray).toString(CryptoJS.enc.Hex) + let verified = false + QRLPROTO_SHA256.forEach(value => { + if (value.protoSha256 === calculatedProtoHash) { + verified = true + } + }) + return verified + }).catch(error => { + throw new Error(error) + }) +} + async function loadGrpcBaseProto(grpcEndpoint) { return protoLoader.load(PROTO_PATH, {}).then(async packageDefinition => { const packageObject = grpc.loadPackageDefinition(packageDefinition) @@ -47,12 +65,15 @@ async function loadGrpcProto(protofile, endpoint) { } const packageDefinition = await protoLoader.load(protofile, options) const grpcObject = await grpc.loadPackageDefinition(packageDefinition) - let verified = true - // QRLPROTO_SHA256.forEach(value => { - // if (value.memoryHash === calculatedObjectHash) { - // verified = true - // } - // }) + const grpcObjectString = JSON.stringify(grpcObject.qrl) + const protoObjectWordArray = CryptoJS.lib.WordArray.create(grpcObjectString) + const calculatedObjectHash = CryptoJS.SHA256(protoObjectWordArray).toString(CryptoJS.enc.Hex) + let verified = false + QRLPROTO_SHA256.forEach(value => { + if (value.memoryHash === calculatedObjectHash) { + verified = true + } + }) // If the grpc object shasum matches, establish the grpc connection. if (verified) { try { @@ -80,8 +101,12 @@ async function loadGrpcProto(protofile, endpoint) { async function makeClient (grpcEndpoint) { const proto = await loadGrpcBaseProto(grpcEndpoint) - const client = await loadGrpcProto(proto, grpcEndpoint) - return client + const validHash = await checkProtoHash(proto) + if (validHash) { + const client = await loadGrpcProto(proto, grpcEndpoint) + return client + } + return null } class QrlNode { From 5c080bde7625a12223172c428862860529066dfa Mon Sep 17 00:00:00 2001 From: JP Lomas Date: Sat, 18 Jul 2020 22:23:59 +0100 Subject: [PATCH 2/6] Redo some async code and new proto validation method WIP --- package-lock.json | 6 +- package.json | 2 +- src/index.js | 172 ++++++++++++++++++++++++++-------------------- 3 files changed, 103 insertions(+), 77 deletions(-) diff --git a/package-lock.json b/package-lock.json index 62dc68b..f63ac44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1465,9 +1465,9 @@ "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" }, "@theqrl/qrl-proto-sha256": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@theqrl/qrl-proto-sha256/-/qrl-proto-sha256-2.0.3.tgz", - "integrity": "sha512-WJKkvZqwOdW8Mt6jDjKes948kNgA6PE5Kxvi1t+LNqeMDY1NjEyoB/MHXRo8iEzAz5BQSWKamyk5UNjaBtb2sA==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@theqrl/qrl-proto-sha256/-/qrl-proto-sha256-3.0.0.tgz", + "integrity": "sha512-s0WDPIcTfMsflt8cb2+KsHOBWdghftEtRr6NFnW5f8cdxNUEeKHYGvLAKb7VtZAZFbfruUHBChsS/NSwBPmbuA==" }, "@theqrl/qrlbase.proto": { "version": "1.0.0", diff --git a/package.json b/package.json index bd52a49..321c3de 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "@babel/polyfill": "^7.10.4", "@grpc/grpc-js": "^1.1.2", "@grpc/proto-loader": "^0.5.5", - "@theqrl/qrl-proto-sha256": "^2.0.3", + "@theqrl/qrl-proto-sha256": "^3.0.0", "@theqrl/qrlbase.proto": "^1.0.0", "crypto-js": "^4.0.0", "google-protobuf": "^3.12.2", diff --git a/src/index.js b/src/index.js index 8e023ab..d76a4d1 100644 --- a/src/index.js +++ b/src/index.js @@ -13,7 +13,7 @@ const writeFile = util.promisify(fs.writeFile) const PROTO_PATH = 'node_modules/@theqrl/qrlbase.proto/qrlbase.proto' let qrlClient = null -const clientGetNodeInfo = client => { +const clientGetNodeInfo = async client => { return new Promise((resolve, reject) => { client.getNodeInfo({}, (error, response) => { if (error) { @@ -21,92 +21,113 @@ const clientGetNodeInfo = client => { } resolve(response) }) + }).catch(error => { + throw new Error('Unable to get valid proto file (' + error + ')') }) } async function checkProtoHash(file) { - return readFile(file).then(async contents => { - const protoFileWordArray = CryptoJS.lib.WordArray.create(contents.toString()) - const calculatedProtoHash = CryptoJS.SHA256(protoFileWordArray).toString(CryptoJS.enc.Hex) - let verified = false - QRLPROTO_SHA256.forEach(value => { - if (value.protoSha256 === calculatedProtoHash) { - verified = true - } + return new Promise((resolve, reject) => { + return readFile(file).then(async contents => { + const protoFileWordArray = CryptoJS.lib.WordArray.create(contents.toString()) + const calculatedProtoHash = CryptoJS.SHA256(protoFileWordArray).toString(CryptoJS.enc.Hex) + let verified = false + QRLPROTO_SHA256.forEach(value => { + if (value.protoHash) { + if (value.protoHash === calculatedProtoHash) { + verified = true + } + } + }) + resolve(verified) + }).catch(error => { + reject(error) }) - return verified }).catch(error => { - throw new Error(error) + throw new Error('Unable to check proto file hash (' + error + ')') }) } async function loadGrpcBaseProto(grpcEndpoint) { - return protoLoader.load(PROTO_PATH, {}).then(async packageDefinition => { - const packageObject = grpc.loadPackageDefinition(packageDefinition) - const client = await new packageObject.qrl.Base(grpcEndpoint, grpc.credentials.createInsecure()) - const res = await clientGetNodeInfo(client) - const qrlProtoFilePath = tmp.fileSync({mode: '0644', prefix: 'qrl-', postfix: '.proto'}).name - await writeFile(qrlProtoFilePath, res.grpcProto).then(fsErr => { - if (fsErr) { - throw new TypeError('tmp filesystem error') - } + return new Promise(async (resolve, reject) => { + return protoLoader.load(PROTO_PATH, {}).then(async packageDefinition => { + const packageObject = grpc.loadPackageDefinition(packageDefinition) + const client = await new packageObject.qrl.Base(grpcEndpoint, grpc.credentials.createInsecure()) + const res = await clientGetNodeInfo(client) + const qrlProtoFilePath = tmp.fileSync({mode: '0644', prefix: 'qrl-', postfix: '.proto'}).name + await writeFile(qrlProtoFilePath, res.grpcProto).then(fsErr => { + if (fsErr) { + reject('tmp filesystem error') + } + }) + resolve(qrlProtoFilePath) }) - return qrlProtoFilePath + }).catch(error => { + throw new Error('Unable to load grpc base proto (' + error + ')') }) } async function loadGrpcProto(protofile, endpoint) { - const options = { - keepCase: true, - longs: String, - enums: String, - defaults: true, - oneofs: true, - } - const packageDefinition = await protoLoader.load(protofile, options) - const grpcObject = await grpc.loadPackageDefinition(packageDefinition) - const grpcObjectString = JSON.stringify(grpcObject.qrl) - const protoObjectWordArray = CryptoJS.lib.WordArray.create(grpcObjectString) - const calculatedObjectHash = CryptoJS.SHA256(protoObjectWordArray).toString(CryptoJS.enc.Hex) - let verified = false - QRLPROTO_SHA256.forEach(value => { - if (value.memoryHash === calculatedObjectHash) { - verified = true + return new Promise(async (resolve, reject) => { + const options = { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, } - }) - // If the grpc object shasum matches, establish the grpc connection. - if (verified) { - try { - qrlClient = createClient({ - protoPath: protofile, - packageName: 'qrl', - serviceName: 'PublicAPI', - options: { - keepCase: true, - longs: String, - enums: String, - defaults: true, - oneofs: true, - }, - }, endpoint) - return qrlClient - } catch (error) { - throw new TypeError(error) + const packageDefinition = await protoLoader.load(protofile, options) + const grpcObject = await grpc.loadPackageDefinition(packageDefinition) + const grpcObjectString = JSON.stringify(grpcObject.qrl) + const protoObjectWordArray = CryptoJS.lib.WordArray.create(grpcObjectString) + const calculatedObjectHash = CryptoJS.SHA256(protoObjectWordArray).toString(CryptoJS.enc.Hex) + let verified = false + QRLPROTO_SHA256.forEach(value => { + if (value.objectHash) { + if (value.objectHash === calculatedObjectHash) { + verified = true + } + } + }) + // If the grpc object shasum matches, establish the grpc connection. + if (verified) { + try { + qrlClient = createClient({ + protoPath: protofile, + packageName: 'qrl', + serviceName: 'PublicAPI', + options: { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, + }, + }, endpoint) + resolve(qrlClient) + } catch (error) { + reject(error) + } } - - } - console.log('Unable to verifty proto file - have hashes changed?') // eslint-disable-line no-console - throw new TypeError('Unable to verify proto file') + console.log('Unable to verifty proto file - have hashes changed?') // eslint-disable-line no-console + reject('Unable to verify proto file') + }).catch(error => { + throw new Error('Unable to load grpc proto file (' + error + ')') + }) } async function makeClient (grpcEndpoint) { - const proto = await loadGrpcBaseProto(grpcEndpoint) - const validHash = await checkProtoHash(proto) - if (validHash) { - const client = await loadGrpcProto(proto, grpcEndpoint) - return client - } - return null + return new Promise(async (resolve, reject) => { + const proto = await loadGrpcBaseProto(grpcEndpoint) + const validHash = await checkProtoHash(proto) + if (validHash) { + const client = await loadGrpcProto(proto, grpcEndpoint) + resolve(client) + } + reject(null) + }).catch(error => { + throw new Error('Unable to make client (' + error + ')') + }) } class QrlNode { @@ -118,15 +139,17 @@ class QrlNode { this.client = null } - connect() { - return new Promise((resolve, reject) => { + async connect() { + return new Promise(async (resolve, reject) => { if (this.connection === false) { - const client = makeClient(`${this.ipAddress}:${this.port}`) + const client = await makeClient(`${this.ipAddress}:${this.port}`) this.connection = true this.client = client resolve(client) } reject('Already connected... disconnect first or create a new connection') + }).catch(error => { + throw new Error('Unable to connect (' + error + ')') }) } @@ -135,8 +158,8 @@ class QrlNode { this.connection = false } - validApi(apiCall) { - const client = this.client + async validApi(apiCall) { + const client = await this.client return client.then(result => { try { if (result[apiCall].path.substr(0,5) === '/qrl.') { @@ -158,8 +181,11 @@ class QrlNode { } resolve(response) }) + }).catch(error => { + throw new Error('Unable to make API call (' + error + ')') }) - } + } } + module.exports = QrlNode From a3a9d475ccb7290192dad64802318221d5313636 Mon Sep 17 00:00:00 2001 From: JP Lomas Date: Sun, 19 Jul 2020 21:34:58 +0100 Subject: [PATCH 3/6] Tidy async code --- package-lock.json | 124 ++++++++++++++++++++++++++++ package.json | 3 +- src/index.js | 206 +++++++++++++++++++++++----------------------- test/test.js | 37 ++++++--- 4 files changed, 256 insertions(+), 114 deletions(-) diff --git a/package-lock.json b/package-lock.json index f63ac44..1101c93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1464,6 +1464,51 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" }, + "@sinonjs/commons": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", + "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@sinonjs/formatio": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", + "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^5.0.2" + } + }, + "@sinonjs/samsam": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.0.3.tgz", + "integrity": "sha512-QucHkc2uMJ0pFGjJUDP3F9dq5dx8QIaqISl9QgwLOh6P9yv877uONPGXh/OH/0zmM3tW1JjuJltAZV2l7zU+uQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, "@theqrl/qrl-proto-sha256": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@theqrl/qrl-proto-sha256/-/qrl-proto-sha256-3.0.0.tgz", @@ -2533,6 +2578,11 @@ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, + "dns-lookup": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dns-lookup/-/dns-lookup-0.1.0.tgz", + "integrity": "sha1-lb089R+s+xXNrUjP40TWczqGAzE=" + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -4624,6 +4674,12 @@ "verror": "1.10.0" } }, + "just-extend": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.0.tgz", + "integrity": "sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==", + "dev": true + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -4716,6 +4772,12 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, "log-driver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", @@ -5130,6 +5192,19 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "nise": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", + "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, "node-environment-flags": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", @@ -5826,6 +5901,23 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", @@ -6427,6 +6519,38 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "sinon": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.2.tgz", + "integrity": "sha512-0uF8Q/QHkizNUmbK3LRFqx5cpTttEVXudywY9Uwzy8bTfZUhljZ7ARzSxnRHWYWtVTeh4Cw+tTb3iU21FQVO9A==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.2", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/formatio": "^5.0.1", + "@sinonjs/samsam": "^5.0.3", + "diff": "^4.0.2", + "nise": "^4.0.1", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", diff --git a/package.json b/package.json index 321c3de..f20f863 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,8 @@ "mocha-lcov-reporter": "^1.3.0", "nodemon": "^1.18.4", "npm-run-all": "^4.1.5", - "nyc": "^15.1.0" + "nyc": "^15.1.0", + "sinon": "^9.0.2" }, "dependencies": { "@babel/polyfill": "^7.10.4", diff --git a/src/index.js b/src/index.js index d76a4d1..0fa113c 100644 --- a/src/index.js +++ b/src/index.js @@ -2,9 +2,15 @@ require("@babel/polyfill") const grpc = require('@grpc/grpc-js') const protoLoader = require('@grpc/proto-loader') const CryptoJS = require('crypto-js') -const { createClient } = require('grpc-js-kit') -const { promisify } = require('util') -const { QRLPROTO_SHA256 } = require('@theqrl/qrl-proto-sha256') +const { + createClient +} = require('grpc-js-kit') +const { + promisify +} = require('util') +const { + QRLPROTO_SHA256 +} = require('@theqrl/qrl-proto-sha256') const tmp = require('tmp') const fs = require('fs') const util = require('util') @@ -13,62 +19,70 @@ const writeFile = util.promisify(fs.writeFile) const PROTO_PATH = 'node_modules/@theqrl/qrlbase.proto/qrlbase.proto' let qrlClient = null -const clientGetNodeInfo = async client => { - return new Promise((resolve, reject) => { - client.getNodeInfo({}, (error, response) => { - if (error) { - reject(error) - } - resolve(response) - }) +async function clientGetNodeInfo (client) { + return new Promise(async (resolve, reject) => { + try { + await client.getNodeInfo({}, (error, response) => { + if (error) { + throw new Error(error) + } + resolve(response) + }) + } catch (error) { + throw new Error(error) + } }).catch(error => { throw new Error('Unable to get valid proto file (' + error + ')') }) } async function checkProtoHash(file) { - return new Promise((resolve, reject) => { - return readFile(file).then(async contents => { - const protoFileWordArray = CryptoJS.lib.WordArray.create(contents.toString()) - const calculatedProtoHash = CryptoJS.SHA256(protoFileWordArray).toString(CryptoJS.enc.Hex) - let verified = false - QRLPROTO_SHA256.forEach(value => { - if (value.protoHash) { - if (value.protoHash === calculatedProtoHash) { - verified = true - } + return readFile(file).then(async contents => { + const protoFileWordArray = CryptoJS.lib.WordArray.create(contents.toString()) + const calculatedProtoHash = CryptoJS.SHA256(protoFileWordArray).toString(CryptoJS.enc.Hex) + let verified = false + QRLPROTO_SHA256.forEach(value => { + if (value.protoHash) { + if (value.protoHash === calculatedProtoHash) { + verified = true } - }) - resolve(verified) - }).catch(error => { - reject(error) + } }) - }).catch(error => { - throw new Error('Unable to check proto file hash (' + error + ')') + return verified }) } async function loadGrpcBaseProto(grpcEndpoint) { - return new Promise(async (resolve, reject) => { + return new Promise((resolve, reject) => { return protoLoader.load(PROTO_PATH, {}).then(async packageDefinition => { - const packageObject = grpc.loadPackageDefinition(packageDefinition) - const client = await new packageObject.qrl.Base(grpcEndpoint, grpc.credentials.createInsecure()) - const res = await clientGetNodeInfo(client) - const qrlProtoFilePath = tmp.fileSync({mode: '0644', prefix: 'qrl-', postfix: '.proto'}).name - await writeFile(qrlProtoFilePath, res.grpcProto).then(fsErr => { - if (fsErr) { - reject('tmp filesystem error') - } - }) - resolve(qrlProtoFilePath) + try { + const packageObject = grpc.loadPackageDefinition(packageDefinition) + const client = await new packageObject.qrl.Base(grpcEndpoint, grpc.credentials.createInsecure()) + const res = await clientGetNodeInfo(client) + const qrlProtoFilePath = tmp.fileSync({ + mode: '0644', + prefix: 'qrl-', + postfix: '.proto' + }).name + await writeFile(qrlProtoFilePath, res.grpcProto).then(fsErr => { + if (fsErr) { + reject('tmp filesystem error') + } + }).catch(error => { + // throw new Error('Unable to load grpc base proto (' + error + ')') + }) + resolve(qrlProtoFilePath) + } catch (error) { + throw new Error('Unable to load grpc base proto (' + error + ')') + } }) }).catch(error => { throw new Error('Unable to load grpc base proto (' + error + ')') }) -} +} async function loadGrpcProto(protofile, endpoint) { - return new Promise(async (resolve, reject) => { + try { const options = { keepCase: true, longs: String, @@ -91,66 +105,56 @@ async function loadGrpcProto(protofile, endpoint) { }) // If the grpc object shasum matches, establish the grpc connection. if (verified) { - try { - qrlClient = createClient({ - protoPath: protofile, - packageName: 'qrl', - serviceName: 'PublicAPI', - options: { - keepCase: true, - longs: String, - enums: String, - defaults: true, - oneofs: true, - }, - }, endpoint) - resolve(qrlClient) - } catch (error) { - reject(error) - } + qrlClient = await createClient({ + protoPath: protofile, + packageName: 'qrl', + serviceName: 'PublicAPI', + options: { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true, + }, + }, endpoint) + return qrlClient } - console.log('Unable to verifty proto file - have hashes changed?') // eslint-disable-line no-console - reject('Unable to verify proto file') - }).catch(error => { + } catch (error) { throw new Error('Unable to load grpc proto file (' + error + ')') - }) + } } -async function makeClient (grpcEndpoint) { - return new Promise(async (resolve, reject) => { +async function makeClient(grpcEndpoint) { + try { const proto = await loadGrpcBaseProto(grpcEndpoint) const validHash = await checkProtoHash(proto) if (validHash) { const client = await loadGrpcProto(proto, grpcEndpoint) - resolve(client) + return client } - reject(null) - }).catch(error => { + return null + } catch (error) { throw new Error('Unable to make client (' + error + ')') - }) + } } class QrlNode { constructor(ipAddress, port) { this.version = '0.5.2' - this.ipAddress = ipAddress - this.port = port this.connection = false this.client = null + this.ipAddress = ipAddress + this.port = port } - + async connect() { - return new Promise(async (resolve, reject) => { - if (this.connection === false) { - const client = await makeClient(`${this.ipAddress}:${this.port}`) - this.connection = true - this.client = client - resolve(client) - } - reject('Already connected... disconnect first or create a new connection') - }).catch(error => { - throw new Error('Unable to connect (' + error + ')') - }) + if (this.connection === false) { + const client = await makeClient(`${this.ipAddress}:${this.port}`) + this.connection = true + this.client = client + return client + } + throw new Error('Already connected... disconnect first or create a new connection') } disconnect() { @@ -160,32 +164,30 @@ class QrlNode { async validApi(apiCall) { const client = await this.client - return client.then(result => { - try { - if (result[apiCall].path.substr(0,5) === '/qrl.') { - return true - } - return false - } catch (error) { - return false + try { + if (client[apiCall].path.substr(0, 5) === '/qrl.') { + return true } - }) + return false + } catch (error) { + return false + } } api(apiCall, request = {}) { - return new Promise(async (resolve, reject) => { - const client = await this.client - client[apiCall](request, async (error, response) => { - if (error) { - reject(error) - } - resolve(response) - }) - }).catch(error => { - throw new Error('Unable to make API call (' + error + ')') + return new Promise(async (resolve, reject) => { + const client = await this.client + client[apiCall](request, async (error, response) => { + if (error) { + reject(error) + } + resolve(response) }) - } + }).catch(error => { + throw new Error('Unable to make API call (' + error + ')') + }) + } } -module.exports = QrlNode +module.exports = QrlNode \ No newline at end of file diff --git a/test/test.js b/test/test.js index 95a9174..e4ad213 100644 --- a/test/test.js +++ b/test/test.js @@ -5,12 +5,18 @@ var chai = require("chai") chai.use(chaiAsPromised) var expect = chai.expect var assert = chai.assert - +var sinon = require("sinon") var ip = 'mainnet-1.automated.theqrl.org' var port = '19009' -var mainnet = new QrlNode(ip, port) -describe('#mainnet', async function() { +describe('#mainnet', function() { + before(() => { + // sinon.stub(console, 'log') // disable console.log + // sinon.stub(console, 'info') // disable console.info + // sinon.stub(console, 'warn') // disable console.warn + // sinon.stub(console, 'error') // disable console.error +}) + var mainnet = new QrlNode(ip, port) // *may* need to increase the time between tests if network is slow // beforeEach(done => setTimeout(done, 500)) this.timeout(20000) // 20 second timeout on tests @@ -70,16 +76,25 @@ describe('#mainnet', async function() { await expect(node()).to.eventually.be.rejected }) - it('an invalid node ip/port should have its Promise rejected', async function() { + // this test is broken! + /* + it('an invalid node ip/port should throw an error', async function() { async function node() { - ip = 'fake.theqrl.org' - port = '19009' - const badhelpers = new QrlNode(ip, port) - const badclient = await badhelpers.connect() - return badclient + const badip = 'bad-ip.automated.theqrl.org' + const badport = '19009' + let id = null + var testnet = await new QrlNode(badip, badport) + // console.log(testnet) + try { + var client = await testnet.connect() + } catch (error) { + console.log('er:', error) + } + console.log(testnet.connection) } - await expect(node()).to.eventually.be.rejected - }) + const x = await node() + await expect(x).to + }) */ it('testnet node should have \'The Random Genesis\' as its network_id', async function() { async function node() { From 34a3df584cc59d95a49f616b97bfecfbb37a1bcc Mon Sep 17 00:00:00 2001 From: JP Lomas Date: Tue, 21 Jul 2020 21:30:42 +0100 Subject: [PATCH 4/6] Validate dns of nodes prior to creating client object --- package-lock.json | 124 ---------------------------------------------- package.json | 3 +- src/index.js | 14 ++++++ test/test.js | 23 ++++----- 4 files changed, 24 insertions(+), 140 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1101c93..f63ac44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1464,51 +1464,6 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" }, - "@sinonjs/commons": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", - "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "@sinonjs/formatio": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", - "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^5.0.2" - } - }, - "@sinonjs/samsam": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.0.3.tgz", - "integrity": "sha512-QucHkc2uMJ0pFGjJUDP3F9dq5dx8QIaqISl9QgwLOh6P9yv877uONPGXh/OH/0zmM3tW1JjuJltAZV2l7zU+uQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, "@theqrl/qrl-proto-sha256": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@theqrl/qrl-proto-sha256/-/qrl-proto-sha256-3.0.0.tgz", @@ -2578,11 +2533,6 @@ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, - "dns-lookup": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dns-lookup/-/dns-lookup-0.1.0.tgz", - "integrity": "sha1-lb089R+s+xXNrUjP40TWczqGAzE=" - }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -4674,12 +4624,6 @@ "verror": "1.10.0" } }, - "just-extend": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.0.tgz", - "integrity": "sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==", - "dev": true - }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -4772,12 +4716,6 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, "log-driver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", @@ -5192,19 +5130,6 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, - "nise": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", - "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, "node-environment-flags": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", @@ -5901,23 +5826,6 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - } - } - }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", @@ -6519,38 +6427,6 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, - "sinon": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.2.tgz", - "integrity": "sha512-0uF8Q/QHkizNUmbK3LRFqx5cpTttEVXudywY9Uwzy8bTfZUhljZ7ARzSxnRHWYWtVTeh4Cw+tTb3iU21FQVO9A==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.2", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/formatio": "^5.0.1", - "@sinonjs/samsam": "^5.0.3", - "diff": "^4.0.2", - "nise": "^4.0.1", - "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", diff --git a/package.json b/package.json index f20f863..321c3de 100644 --- a/package.json +++ b/package.json @@ -68,8 +68,7 @@ "mocha-lcov-reporter": "^1.3.0", "nodemon": "^1.18.4", "npm-run-all": "^4.1.5", - "nyc": "^15.1.0", - "sinon": "^9.0.2" + "nyc": "^15.1.0" }, "dependencies": { "@babel/polyfill": "^7.10.4", diff --git a/src/index.js b/src/index.js index 0fa113c..2f64677 100644 --- a/src/index.js +++ b/src/index.js @@ -16,6 +16,7 @@ const fs = require('fs') const util = require('util') const readFile = util.promisify(fs.readFile) const writeFile = util.promisify(fs.writeFile) +const dns = require('dns').promises const PROTO_PATH = 'node_modules/@theqrl/qrlbase.proto/qrlbase.proto' let qrlClient = null @@ -138,6 +139,12 @@ async function makeClient(grpcEndpoint) { } } +async function validate(node) { + return dns.lookup(node).catch(error => { + throw new Error(error) + }) +} + class QrlNode { constructor(ipAddress, port) { this.version = '0.5.2' @@ -145,6 +152,13 @@ class QrlNode { this.client = null this.ipAddress = ipAddress this.port = port + validate(ipAddress).then((err, res) => { + if (err) { + throw new Error(err) + } + }).catch(error => { + throw new Error(error) + }) } async connect() { diff --git a/test/test.js b/test/test.js index e4ad213..e118a0e 100644 --- a/test/test.js +++ b/test/test.js @@ -5,17 +5,15 @@ var chai = require("chai") chai.use(chaiAsPromised) var expect = chai.expect var assert = chai.assert -var sinon = require("sinon") var ip = 'mainnet-1.automated.theqrl.org' var port = '19009' -describe('#mainnet', function() { - before(() => { - // sinon.stub(console, 'log') // disable console.log - // sinon.stub(console, 'info') // disable console.info - // sinon.stub(console, 'warn') // disable console.warn - // sinon.stub(console, 'error') // disable console.error +process.on('unhandledRejection', error => { + // uncomment to review unhandled Promise rejections to debug + // console.log('unhandledRejection', error.message) }) + +describe('#mainnet', function() { var mainnet = new QrlNode(ip, port) // *may* need to increase the time between tests if network is slow // beforeEach(done => setTimeout(done, 500)) @@ -75,15 +73,13 @@ describe('#mainnet', function() { } await expect(node()).to.eventually.be.rejected }) - - // this test is broken! - /* + it('an invalid node ip/port should throw an error', async function() { async function node() { const badip = 'bad-ip.automated.theqrl.org' const badport = '19009' let id = null - var testnet = await new QrlNode(badip, badport) + var testnet = new QrlNode(badip, badport) // console.log(testnet) try { var client = await testnet.connect() @@ -92,9 +88,8 @@ describe('#mainnet', function() { } console.log(testnet.connection) } - const x = await node() - await expect(x).to - }) */ + await expect(node()).to.eventually.throw + }) it('testnet node should have \'The Random Genesis\' as its network_id', async function() { async function node() { From 6642f6e3aad5178b3ff7f5baf2d575fd0aed0fe0 Mon Sep 17 00:00:00 2001 From: JP Lomas Date: Wed, 22 Jul 2020 10:28:05 +0100 Subject: [PATCH 5/6] Reworked example, begin removing throws for cleaner async code --- .eslintignore | 3 +- README.md | 16 +- dist/index.js | 538 ++++++++++++++++++++++++++++++++++------------ dist/index.js.map | 2 +- example.js | 14 ++ src/index.js | 25 +-- 6 files changed, 436 insertions(+), 162 deletions(-) create mode 100644 example.js diff --git a/.eslintignore b/.eslintignore index dda0746..607ac0a 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,3 @@ coverage/** -dist/** \ No newline at end of file +dist/** +example.js \ No newline at end of file diff --git a/README.md b/README.md index 3bb0b3c..34412d0 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ testnet.connect().then(() => { }) ``` -make an API call: +make an API call (needs a node connection): ```javascript testnet.api('GetStats').then((result) => { @@ -53,12 +53,14 @@ var port = '19009' var testnet = new QrlNode(ip, port) testnet.connect().then(() => { -console.log(testnet.connection) // true if connection successful -}) - -testnet.api('GetStats').then((result) => { - console.log(result) -}) + console.log(testnet.connection); // true if connection successful + + // we can now start using the API + testnet.api('GetStats').then((result) => { + console.log(result); + }); + +}); ``` ## Development of this module diff --git a/dist/index.js b/dist/index.js index 300793b..d43b78c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -16,12 +16,17 @@ var grpc = require('@grpc/grpc-js'); var protoLoader = require('@grpc/proto-loader'); +var CryptoJS = require('crypto-js'); + var _require = require('grpc-js-kit'), createClient = _require.createClient; var _require2 = require('util'), promisify = _require2.promisify; +var _require3 = require('@theqrl/qrl-proto-sha256'), + QRLPROTO_SHA256 = _require3.QRLPROTO_SHA256; + var tmp = require('tmp'); var fs = require('fs'); @@ -30,98 +35,215 @@ var util = require('util'); var readFile = util.promisify(fs.readFile); var writeFile = util.promisify(fs.writeFile); -var PROTO_PATH = 'node_modules/@theqrl/qrlbase.proto/qrlbase.proto'; -var qrlClient = null; -var clientGetNodeInfo = function clientGetNodeInfo(client) { - return new Promise(function (resolve, reject) { - client.getNodeInfo({}, function (error, response) { - if (error) { - reject(error); - } +var dns = require('dns').promises; - resolve(response); - }); - }); -}; +var PROTO_PATH = 'node_modules/@theqrl/qrlbase.proto/qrlbase.proto'; +var qrlClient = null; -function loadGrpcBaseProto(_x) { - return _loadGrpcBaseProto.apply(this, arguments); +function clientGetNodeInfo(_x) { + return _clientGetNodeInfo.apply(this, arguments); } -function _loadGrpcBaseProto() { - _loadGrpcBaseProto = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4(grpcEndpoint) { - return regeneratorRuntime.wrap(function _callee4$(_context4) { +function _clientGetNodeInfo() { + _clientGetNodeInfo = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7(client) { + return regeneratorRuntime.wrap(function _callee7$(_context7) { while (1) { - switch (_context4.prev = _context4.next) { + switch (_context7.prev = _context7.next) { case 0: - return _context4.abrupt("return", protoLoader.load(PROTO_PATH, {}).then( /*#__PURE__*/function () { - var _ref3 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(packageDefinition) { - var packageObject, client, res, qrlProtoFilePath; - return regeneratorRuntime.wrap(function _callee3$(_context3) { + return _context7.abrupt("return", new Promise( /*#__PURE__*/function () { + var _ref4 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee6(resolve, reject) { + return regeneratorRuntime.wrap(function _callee6$(_context6) { while (1) { - switch (_context3.prev = _context3.next) { + switch (_context6.prev = _context6.next) { case 0: - packageObject = grpc.loadPackageDefinition(packageDefinition); - _context3.next = 3; - return new packageObject.qrl.Base(grpcEndpoint, grpc.credentials.createInsecure()); + _context6.prev = 0; + _context6.next = 3; + return client.getNodeInfo({}, function (error, response) { + if (error) { + throw new Error(error); + } + + resolve(response); + }); case 3: - client = _context3.sent; - _context3.next = 6; - return clientGetNodeInfo(client); - - case 6: - res = _context3.sent; - qrlProtoFilePath = tmp.fileSync({ - mode: '0644', - prefix: 'qrl-', - postfix: '.proto' - }).name; - _context3.next = 10; - return writeFile(qrlProtoFilePath, res.grpcProto).then(function (fsErr) { - if (fsErr) { - throw new TypeError('tmp filesystem error'); + _context6.next = 8; + break; + + case 5: + _context6.prev = 5; + _context6.t0 = _context6["catch"](0); + throw new Error(_context6.t0); + + case 8: + case "end": + return _context6.stop(); + } + } + }, _callee6, null, [[0, 5]]); + })); + + return function (_x15, _x16) { + return _ref4.apply(this, arguments); + }; + }())["catch"](function (error) { + throw new Error('Unable to get valid proto file (' + error + ')'); + })); + + case 1: + case "end": + return _context7.stop(); + } + } + }, _callee7); + })); + return _clientGetNodeInfo.apply(this, arguments); +} + +function checkProtoHash(_x2) { + return _checkProtoHash.apply(this, arguments); +} + +function _checkProtoHash() { + _checkProtoHash = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee9(file) { + return regeneratorRuntime.wrap(function _callee9$(_context9) { + while (1) { + switch (_context9.prev = _context9.next) { + case 0: + return _context9.abrupt("return", readFile(file).then( /*#__PURE__*/function () { + var _ref5 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee8(contents) { + var protoFileWordArray, calculatedProtoHash, verified; + return regeneratorRuntime.wrap(function _callee8$(_context8) { + while (1) { + switch (_context8.prev = _context8.next) { + case 0: + protoFileWordArray = CryptoJS.lib.WordArray.create(contents.toString()); + calculatedProtoHash = CryptoJS.SHA256(protoFileWordArray).toString(CryptoJS.enc.Hex); + verified = false; + QRLPROTO_SHA256.forEach(function (value) { + if (value.protoHash) { + if (value.protoHash === calculatedProtoHash) { + verified = true; + } } }); + return _context8.abrupt("return", verified); - case 10: - return _context3.abrupt("return", qrlProtoFilePath); - - case 11: + case 5: case "end": - return _context3.stop(); + return _context8.stop(); } } - }, _callee3); + }, _callee8); })); - return function (_x9) { - return _ref3.apply(this, arguments); + return function (_x17) { + return _ref5.apply(this, arguments); }; }())); case 1: case "end": - return _context4.stop(); + return _context9.stop(); + } + } + }, _callee9); + })); + return _checkProtoHash.apply(this, arguments); +} + +function loadGrpcBaseProto(_x3) { + return _loadGrpcBaseProto.apply(this, arguments); +} + +function _loadGrpcBaseProto() { + _loadGrpcBaseProto = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee11(grpcEndpoint) { + return regeneratorRuntime.wrap(function _callee11$(_context11) { + while (1) { + switch (_context11.prev = _context11.next) { + case 0: + return _context11.abrupt("return", new Promise(function (resolve, reject) { + return protoLoader.load(PROTO_PATH, {}).then( /*#__PURE__*/function () { + var _ref6 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee10(packageDefinition) { + var packageObject, client, res, qrlProtoFilePath; + return regeneratorRuntime.wrap(function _callee10$(_context10) { + while (1) { + switch (_context10.prev = _context10.next) { + case 0: + _context10.prev = 0; + packageObject = grpc.loadPackageDefinition(packageDefinition); + _context10.next = 4; + return new packageObject.qrl.Base(grpcEndpoint, grpc.credentials.createInsecure()); + + case 4: + client = _context10.sent; + _context10.next = 7; + return clientGetNodeInfo(client); + + case 7: + res = _context10.sent; + qrlProtoFilePath = tmp.fileSync({ + mode: '0644', + prefix: 'qrl-', + postfix: '.proto' + }).name; + _context10.next = 11; + return writeFile(qrlProtoFilePath, res.grpcProto).then(function (fsErr) { + if (fsErr) { + reject('tmp filesystem error'); + } + })["catch"](function (error) {// throw new Error('Unable to load grpc base proto (' + error + ')') + }); + + case 11: + resolve(qrlProtoFilePath); + _context10.next = 17; + break; + + case 14: + _context10.prev = 14; + _context10.t0 = _context10["catch"](0); + throw new Error('Unable to load grpc base proto (' + _context10.t0 + ')'); + + case 17: + case "end": + return _context10.stop(); + } + } + }, _callee10, null, [[0, 14]]); + })); + + return function (_x18) { + return _ref6.apply(this, arguments); + }; + }()); + })["catch"](function (error) { + throw new Error('Unable to load grpc base proto (' + error + ')'); + })); + + case 1: + case "end": + return _context11.stop(); } } - }, _callee4); + }, _callee11); })); return _loadGrpcBaseProto.apply(this, arguments); } -function loadGrpcProto(_x2, _x3) { +function loadGrpcProto(_x4, _x5) { return _loadGrpcProto.apply(this, arguments); } function _loadGrpcProto() { - _loadGrpcProto = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(protofile, endpoint) { - var options, packageDefinition, grpcObject, verified; - return regeneratorRuntime.wrap(function _callee5$(_context5) { + _loadGrpcProto = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee12(protofile, endpoint) { + var options, packageDefinition, grpcObject, grpcObjectString, protoObjectWordArray, calculatedObjectHash, verified; + return regeneratorRuntime.wrap(function _callee12$(_context12) { while (1) { - switch (_context5.prev = _context5.next) { + switch (_context12.prev = _context12.next) { case 0: + _context12.prev = 0; options = { keepCase: true, longs: String, @@ -129,30 +251,35 @@ function _loadGrpcProto() { defaults: true, oneofs: true }; - _context5.next = 3; + _context12.next = 4; return protoLoader.load(protofile, options); - case 3: - packageDefinition = _context5.sent; - _context5.next = 6; + case 4: + packageDefinition = _context12.sent; + _context12.next = 7; return grpc.loadPackageDefinition(packageDefinition); - case 6: - grpcObject = _context5.sent; - verified = true; // QRLPROTO_SHA256.forEach(value => { - // if (value.memoryHash === calculatedObjectHash) { - // verified = true - // } - // }) - // If the grpc object shasum matches, establish the grpc connection. + case 7: + grpcObject = _context12.sent; + grpcObjectString = JSON.stringify(grpcObject.qrl); + protoObjectWordArray = CryptoJS.lib.WordArray.create(grpcObjectString); + calculatedObjectHash = CryptoJS.SHA256(protoObjectWordArray).toString(CryptoJS.enc.Hex); + verified = false; + QRLPROTO_SHA256.forEach(function (value) { + if (value.objectHash) { + if (value.objectHash === calculatedObjectHash) { + verified = true; + } + } + }); // If the grpc object shasum matches, establish the grpc connection. if (!verified) { - _context5.next = 17; + _context12.next = 18; break; } - _context5.prev = 9; - qrlClient = createClient({ + _context12.next = 16; + return createClient({ protoPath: protofile, packageName: 'qrl', serviceName: 'PublicAPI', @@ -164,88 +291,186 @@ function _loadGrpcProto() { oneofs: true } }, endpoint); - return _context5.abrupt("return", qrlClient); - case 14: - _context5.prev = 14; - _context5.t0 = _context5["catch"](9); - throw new TypeError(_context5.t0); + case 16: + qrlClient = _context12.sent; + return _context12.abrupt("return", qrlClient); - case 17: - console.log('Unable to verifty proto file - have hashes changed?'); // eslint-disable-line no-console + case 18: + _context12.next = 23; + break; - throw new TypeError('Unable to verify proto file'); + case 20: + _context12.prev = 20; + _context12.t0 = _context12["catch"](0); + throw new Error('Unable to load grpc proto file (' + _context12.t0 + ')'); - case 19: + case 23: case "end": - return _context5.stop(); + return _context12.stop(); } } - }, _callee5, null, [[9, 14]]); + }, _callee12, null, [[0, 20]]); })); return _loadGrpcProto.apply(this, arguments); } -function makeClient(_x4) { +function makeClient(_x6) { return _makeClient.apply(this, arguments); } function _makeClient() { - _makeClient = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee6(grpcEndpoint) { - var proto, client; - return regeneratorRuntime.wrap(function _callee6$(_context6) { + _makeClient = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee13(grpcEndpoint) { + var proto, validHash, client; + return regeneratorRuntime.wrap(function _callee13$(_context13) { while (1) { - switch (_context6.prev = _context6.next) { + switch (_context13.prev = _context13.next) { case 0: - _context6.next = 2; + _context13.prev = 0; + _context13.next = 3; return loadGrpcBaseProto(grpcEndpoint); - case 2: - proto = _context6.sent; - _context6.next = 5; + case 3: + proto = _context13.sent; + _context13.next = 6; + return checkProtoHash(proto); + + case 6: + validHash = _context13.sent; + + if (!validHash) { + _context13.next = 12; + break; + } + + _context13.next = 10; return loadGrpcProto(proto, grpcEndpoint); - case 5: - client = _context6.sent; - return _context6.abrupt("return", client); + case 10: + client = _context13.sent; + return _context13.abrupt("return", client); - case 7: + case 12: + return _context13.abrupt("return", null); + + case 15: + _context13.prev = 15; + _context13.t0 = _context13["catch"](0); + throw new Error('Unable to make client (' + _context13.t0 + ')'); + + case 18: case "end": - return _context6.stop(); + return _context13.stop(); } } - }, _callee6); + }, _callee13, null, [[0, 15]]); })); return _makeClient.apply(this, arguments); } +function validate(_x7) { + return _validate.apply(this, arguments); +} + +function _validate() { + _validate = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee14(node) { + return regeneratorRuntime.wrap(function _callee14$(_context14) { + while (1) { + switch (_context14.prev = _context14.next) { + case 0: + return _context14.abrupt("return", dns.lookup(node)); + + case 1: + case "end": + return _context14.stop(); + } + } + }, _callee14); + })); + return _validate.apply(this, arguments); +} + var QrlNode = /*#__PURE__*/function () { function QrlNode(ipAddress, port) { _classCallCheck(this, QrlNode); this.version = '0.5.2'; - this.ipAddress = ipAddress; - this.port = port; this.connection = false; this.client = null; + this.ipAddress = ipAddress; + this.port = port; + validate(ipAddress).then(function (err, res) { + if (err) { + return false; + } + + return true; + })["catch"](function (error) { + console.log(error); + }); } _createClass(QrlNode, [{ key: "connect", - value: function connect() { - var _this = this; - - return new Promise(function (resolve, reject) { - if (_this.connection === false) { - var client = makeClient("".concat(_this.ipAddress, ":").concat(_this.port)); - _this.connection = true; - _this.client = client; - resolve(client); - } + value: function () { + var _connect = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() { + var _this = this; + + return regeneratorRuntime.wrap(function _callee2$(_context2) { + while (1) { + switch (_context2.prev = _context2.next) { + case 0: + return _context2.abrupt("return", new Promise( /*#__PURE__*/function () { + var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(resolve, reject) { + var client; + return regeneratorRuntime.wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + if (!(_this.connection === false)) { + _context.next = 7; + break; + } + + _context.next = 3; + return makeClient("".concat(_this.ipAddress, ":").concat(_this.port)); + + case 3: + client = _context.sent; + _this.connection = true; + _this.client = client; + resolve(client); + + case 7: + reject('Already connected... disconnect first or create a new connection'); + + case 8: + case "end": + return _context.stop(); + } + } + }, _callee); + })); + + return function (_x8, _x9) { + return _ref.apply(this, arguments); + }; + }())); + + case 1: + case "end": + return _context2.stop(); + } + } + }, _callee2); + })); - reject('Already connected... disconnect first or create a new connection'); - }); - } + function connect() { + return _connect.apply(this, arguments); + } + + return connect; + }() }, { key: "disconnect", value: function disconnect() { @@ -254,20 +479,49 @@ var QrlNode = /*#__PURE__*/function () { } }, { key: "validApi", - value: function validApi(apiCall) { - var client = this.client; - return client.then(function (result) { - try { - if (result[apiCall].path.substr(0, 5) === '/qrl.') { - return true; + value: function () { + var _validApi = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee3(apiCall) { + var client; + return regeneratorRuntime.wrap(function _callee3$(_context3) { + while (1) { + switch (_context3.prev = _context3.next) { + case 0: + _context3.next = 2; + return this.client; + + case 2: + client = _context3.sent; + _context3.prev = 3; + + if (!(client[apiCall].path.substr(0, 5) === '/qrl.')) { + _context3.next = 6; + break; + } + + return _context3.abrupt("return", true); + + case 6: + return _context3.abrupt("return", false); + + case 9: + _context3.prev = 9; + _context3.t0 = _context3["catch"](3); + return _context3.abrupt("return", false); + + case 12: + case "end": + return _context3.stop(); + } } + }, _callee3, this, [[3, 9]]); + })); - return false; - } catch (error) { - return false; - } - }); - } + function validApi(_x10) { + return _validApi.apply(this, arguments); + } + + return validApi; + }() }, { key: "api", value: function api(apiCall) { @@ -275,22 +529,22 @@ var QrlNode = /*#__PURE__*/function () { var request = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return new Promise( /*#__PURE__*/function () { - var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(resolve, reject) { + var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(resolve, reject) { var client; - return regeneratorRuntime.wrap(function _callee2$(_context2) { + return regeneratorRuntime.wrap(function _callee5$(_context5) { while (1) { - switch (_context2.prev = _context2.next) { + switch (_context5.prev = _context5.next) { case 0: - _context2.next = 2; + _context5.next = 2; return _this2.client; case 2: - client = _context2.sent; + client = _context5.sent; client[apiCall](request, /*#__PURE__*/function () { - var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(error, response) { - return regeneratorRuntime.wrap(function _callee$(_context) { + var _ref3 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4(error, response) { + return regeneratorRuntime.wrap(function _callee4$(_context4) { while (1) { - switch (_context.prev = _context.next) { + switch (_context4.prev = _context4.next) { case 0: if (error) { reject(error); @@ -300,29 +554,31 @@ var QrlNode = /*#__PURE__*/function () { case 2: case "end": - return _context.stop(); + return _context4.stop(); } } - }, _callee); + }, _callee4); })); - return function (_x7, _x8) { - return _ref2.apply(this, arguments); + return function (_x13, _x14) { + return _ref3.apply(this, arguments); }; }()); case 4: case "end": - return _context2.stop(); + return _context5.stop(); } } - }, _callee2); + }, _callee5); })); - return function (_x5, _x6) { - return _ref.apply(this, arguments); + return function (_x11, _x12) { + return _ref2.apply(this, arguments); }; - }()); + }())["catch"](function (error) { + throw new Error('Unable to make API call (' + error + ')'); + }); } }]); diff --git a/dist/index.js.map b/dist/index.js.map index 5b0b5a4..81c6a6f 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/index.js"],"names":["require","grpc","protoLoader","createClient","promisify","tmp","fs","util","readFile","writeFile","PROTO_PATH","qrlClient","clientGetNodeInfo","client","Promise","resolve","reject","getNodeInfo","error","response","loadGrpcBaseProto","grpcEndpoint","load","then","packageDefinition","packageObject","loadPackageDefinition","qrl","Base","credentials","createInsecure","res","qrlProtoFilePath","fileSync","mode","prefix","postfix","name","grpcProto","fsErr","TypeError","loadGrpcProto","protofile","endpoint","options","keepCase","longs","String","enums","defaults","oneofs","grpcObject","verified","protoPath","packageName","serviceName","console","log","makeClient","proto","QrlNode","ipAddress","port","version","connection","apiCall","result","path","substr","request","module","exports"],"mappings":"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","sourcesContent":["require(\"@babel/polyfill\")\nconst grpc = require('@grpc/grpc-js')\nconst protoLoader = require('@grpc/proto-loader')\nconst {createClient} = require('grpc-js-kit')\nconst { promisify } = require('util')\nconst tmp = require('tmp')\nconst fs = require('fs')\nconst util = require('util')\nconst readFile = util.promisify(fs.readFile)\nconst writeFile = util.promisify(fs.writeFile)\nconst PROTO_PATH = 'node_modules/@theqrl/qrlbase.proto/qrlbase.proto'\nlet qrlClient = null\n\nconst clientGetNodeInfo = client => {\n return new Promise((resolve, reject) => {\n client.getNodeInfo({}, (error, response) => {\n if (error) {\n reject(error)\n }\n resolve(response)\n })\n })\n}\n\nasync function loadGrpcBaseProto(grpcEndpoint) {\n return protoLoader.load(PROTO_PATH, {}).then(async packageDefinition => {\n const packageObject = grpc.loadPackageDefinition(packageDefinition)\n const client = await new packageObject.qrl.Base(grpcEndpoint, grpc.credentials.createInsecure())\n const res = await clientGetNodeInfo(client)\n const qrlProtoFilePath = tmp.fileSync({mode: '0644', prefix: 'qrl-', postfix: '.proto'}).name\n await writeFile(qrlProtoFilePath, res.grpcProto).then(fsErr => {\n if (fsErr) {\n throw new TypeError('tmp filesystem error')\n }\n })\n return qrlProtoFilePath\n })\n} \n\nasync function loadGrpcProto(protofile, endpoint) {\n const options = {\n keepCase: true,\n longs: String,\n enums: String,\n defaults: true,\n oneofs: true,\n }\n const packageDefinition = await protoLoader.load(protofile, options)\n const grpcObject = await grpc.loadPackageDefinition(packageDefinition)\n let verified = true\n // QRLPROTO_SHA256.forEach(value => {\n // if (value.memoryHash === calculatedObjectHash) {\n // verified = true\n // }\n // })\n // If the grpc object shasum matches, establish the grpc connection.\n if (verified) {\n try {\n qrlClient = createClient({\n protoPath: protofile,\n packageName: 'qrl',\n serviceName: 'PublicAPI',\n options: {\n keepCase: true,\n longs: String,\n enums: String,\n defaults: true,\n oneofs: true,\n },\n }, endpoint)\n return qrlClient\n } catch (error) {\n throw new TypeError(error)\n }\n\n }\n console.log('Unable to verifty proto file - have hashes changed?') // eslint-disable-line no-console\n throw new TypeError('Unable to verify proto file')\n}\n\nasync function makeClient (grpcEndpoint) {\n const proto = await loadGrpcBaseProto(grpcEndpoint)\n const client = await loadGrpcProto(proto, grpcEndpoint)\n return client\n}\n\nclass QrlNode {\n constructor(ipAddress, port) {\n this.version = '0.5.2'\n this.ipAddress = ipAddress\n this.port = port\n this.connection = false\n this.client = null\n }\n \n connect() {\n return new Promise((resolve, reject) => {\n if (this.connection === false) {\n const client = makeClient(`${this.ipAddress}:${this.port}`)\n this.connection = true\n this.client = client\n resolve(client)\n }\n reject('Already connected... disconnect first or create a new connection')\n })\n }\n\n disconnect() {\n this.client = null\n this.connection = false\n }\n\n validApi(apiCall) {\n const client = this.client\n return client.then(result => {\n try {\n if (result[apiCall].path.substr(0,5) === '/qrl.') {\n return true\n }\n return false\n } catch (error) {\n return false\n }\n })\n }\n\n api(apiCall, request = {}) {\n return new Promise(async (resolve, reject) => {\n const client = await this.client\n client[apiCall](request, async (error, response) => {\n if (error) {\n reject(error)\n }\n resolve(response)\n })\n })\n }\n\n}\nmodule.exports = QrlNode\n"],"file":"index.js"} \ No newline at end of file +{"version":3,"sources":["../src/index.js"],"names":["require","grpc","protoLoader","CryptoJS","createClient","promisify","QRLPROTO_SHA256","tmp","fs","util","readFile","writeFile","dns","promises","PROTO_PATH","qrlClient","clientGetNodeInfo","client","Promise","resolve","reject","getNodeInfo","error","response","Error","checkProtoHash","file","then","contents","protoFileWordArray","lib","WordArray","create","toString","calculatedProtoHash","SHA256","enc","Hex","verified","forEach","value","protoHash","loadGrpcBaseProto","grpcEndpoint","load","packageDefinition","packageObject","loadPackageDefinition","qrl","Base","credentials","createInsecure","res","qrlProtoFilePath","fileSync","mode","prefix","postfix","name","grpcProto","fsErr","loadGrpcProto","protofile","endpoint","options","keepCase","longs","String","enums","defaults","oneofs","grpcObject","grpcObjectString","JSON","stringify","protoObjectWordArray","calculatedObjectHash","objectHash","protoPath","packageName","serviceName","makeClient","proto","validHash","validate","node","lookup","QrlNode","ipAddress","port","version","connection","err","console","log","apiCall","path","substr","request","module","exports"],"mappings":";;;;;;;;;;;;AAAAA,OAAO,CAAC,iBAAD,CAAP;;AACA,IAAMC,IAAI,GAAGD,OAAO,CAAC,eAAD,CAApB;;AACA,IAAME,WAAW,GAAGF,OAAO,CAAC,oBAAD,CAA3B;;AACA,IAAMG,QAAQ,GAAGH,OAAO,CAAC,WAAD,CAAxB;;eAGIA,OAAO,CAAC,aAAD,C;IADTI,Y,YAAAA,Y;;gBAIEJ,OAAO,CAAC,MAAD,C;IADTK,S,aAAAA,S;;gBAIEL,OAAO,CAAC,0BAAD,C;IADTM,e,aAAAA,e;;AAEF,IAAMC,GAAG,GAAGP,OAAO,CAAC,KAAD,CAAnB;;AACA,IAAMQ,EAAE,GAAGR,OAAO,CAAC,IAAD,CAAlB;;AACA,IAAMS,IAAI,GAAGT,OAAO,CAAC,MAAD,CAApB;;AACA,IAAMU,QAAQ,GAAGD,IAAI,CAACJ,SAAL,CAAeG,EAAE,CAACE,QAAlB,CAAjB;AACA,IAAMC,SAAS,GAAGF,IAAI,CAACJ,SAAL,CAAeG,EAAE,CAACG,SAAlB,CAAlB;;AACA,IAAMC,GAAG,GAAGZ,OAAO,CAAC,KAAD,CAAP,CAAea,QAA3B;;AACA,IAAMC,UAAU,GAAG,kDAAnB;AACA,IAAIC,SAAS,GAAG,IAAhB;;SAEeC,iB;;;;;+EAAf,kBAAkCC,MAAlC;AAAA;AAAA;AAAA;AAAA;AAAA,8CACS,IAAIC,OAAJ;AAAA,kFAAY,kBAAOC,OAAP,EAAgBC,MAAhB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAETH,MAAM,CAACI,WAAP,CAAmB,EAAnB,EAAuB,UAACC,KAAD,EAAQC,QAAR,EAAqB;AAChD,8BAAID,KAAJ,EAAW;AACT,kCAAM,IAAIE,KAAJ,CAAUF,KAAV,CAAN;AACD;;AACDH,0BAAAA,OAAO,CAACI,QAAD,CAAP;AACD,yBALK,CAFS;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,8BAST,IAAIC,KAAJ,cATS;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAAZ;;AAAA;AAAA;AAAA;AAAA,0BAWE,UAAAF,KAAK,EAAI;AAChB,oBAAM,IAAIE,KAAJ,CAAU,qCAAqCF,KAArC,GAA6C,GAAvD,CAAN;AACD,aAbM,CADT;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,G;;;;SAiBeG,c;;;;;4EAAf,kBAA8BC,IAA9B;AAAA;AAAA;AAAA;AAAA;AAAA,8CACShB,QAAQ,CAACgB,IAAD,CAAR,CAAeC,IAAf;AAAA,kFAAoB,kBAAMC,QAAN;AAAA;AAAA;AAAA;AAAA;AAAA;AACnBC,wBAAAA,kBADmB,GACE1B,QAAQ,CAAC2B,GAAT,CAAaC,SAAb,CAAuBC,MAAvB,CAA8BJ,QAAQ,CAACK,QAAT,EAA9B,CADF;AAEnBC,wBAAAA,mBAFmB,GAEG/B,QAAQ,CAACgC,MAAT,CAAgBN,kBAAhB,EAAoCI,QAApC,CAA6C9B,QAAQ,CAACiC,GAAT,CAAaC,GAA1D,CAFH;AAGrBC,wBAAAA,QAHqB,GAGV,KAHU;AAIzBhC,wBAAAA,eAAe,CAACiC,OAAhB,CAAwB,UAAAC,KAAK,EAAI;AAC/B,8BAAIA,KAAK,CAACC,SAAV,EAAqB;AACnB,gCAAID,KAAK,CAACC,SAAN,KAAoBP,mBAAxB,EAA6C;AAC3CI,8BAAAA,QAAQ,GAAG,IAAX;AACD;AACF;AACF,yBAND;AAJyB,0DAWlBA,QAXkB;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAApB;;AAAA;AAAA;AAAA;AAAA,gBADT;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,G;;;;SAgBeI,iB;;;;;+EAAf,mBAAiCC,YAAjC;AAAA;AAAA;AAAA;AAAA;AAAA,+CACS,IAAIzB,OAAJ,CAAY,UAACC,OAAD,EAAUC,MAAV,EAAqB;AACtC,qBAAOlB,WAAW,CAAC0C,IAAZ,CAAiB9B,UAAjB,EAA6B,EAA7B,EAAiCa,IAAjC;AAAA,oFAAsC,mBAAMkB,iBAAN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEnCC,0BAAAA,aAFmC,GAEnB7C,IAAI,CAAC8C,qBAAL,CAA2BF,iBAA3B,CAFmB;AAAA;AAAA,iCAGpB,IAAIC,aAAa,CAACE,GAAd,CAAkBC,IAAtB,CAA2BN,YAA3B,EAAyC1C,IAAI,CAACiD,WAAL,CAAiBC,cAAjB,EAAzC,CAHoB;;AAAA;AAGnClC,0BAAAA,MAHmC;AAAA;AAAA,iCAIvBD,iBAAiB,CAACC,MAAD,CAJM;;AAAA;AAInCmC,0BAAAA,GAJmC;AAKnCC,0BAAAA,gBALmC,GAKhB9C,GAAG,CAAC+C,QAAJ,CAAa;AACpCC,4BAAAA,IAAI,EAAE,MAD8B;AAEpCC,4BAAAA,MAAM,EAAE,MAF4B;AAGpCC,4BAAAA,OAAO,EAAE;AAH2B,2BAAb,EAItBC,IATsC;AAAA;AAAA,iCAUnC/C,SAAS,CAAC0C,gBAAD,EAAmBD,GAAG,CAACO,SAAvB,CAAT,CAA2ChC,IAA3C,CAAgD,UAAAiC,KAAK,EAAI;AAC7D,gCAAIA,KAAJ,EAAW;AACTxC,8BAAAA,MAAM,CAAC,sBAAD,CAAN;AACD;AACF,2BAJK,WAIG,UAAAE,KAAK,EAAI,CAChB;AACD,2BANK,CAVmC;;AAAA;AAiBzCH,0BAAAA,OAAO,CAACkC,gBAAD,CAAP;AAjByC;AAAA;;AAAA;AAAA;AAAA;AAAA,gCAmBnC,IAAI7B,KAAJ,CAAU,qDAA6C,GAAvD,CAnBmC;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAtC;;AAAA;AAAA;AAAA;AAAA,kBAAP;AAsBD,aAvBM,WAuBE,UAAAF,KAAK,EAAI;AAChB,oBAAM,IAAIE,KAAJ,CAAU,qCAAqCF,KAArC,GAA6C,GAAvD,CAAN;AACD,aAzBM,CADT;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,G;;;;SA6BeuC,a;;;;;2EAAf,mBAA6BC,SAA7B,EAAwCC,QAAxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEUC,YAAAA,OAFV,GAEoB;AACdC,cAAAA,QAAQ,EAAE,IADI;AAEdC,cAAAA,KAAK,EAAEC,MAFO;AAGdC,cAAAA,KAAK,EAAED,MAHO;AAIdE,cAAAA,QAAQ,EAAE,IAJI;AAKdC,cAAAA,MAAM,EAAE;AALM,aAFpB;AAAA;AAAA,mBASoCpE,WAAW,CAAC0C,IAAZ,CAAiBkB,SAAjB,EAA4BE,OAA5B,CATpC;;AAAA;AASUnB,YAAAA,iBATV;AAAA;AAAA,mBAU6B5C,IAAI,CAAC8C,qBAAL,CAA2BF,iBAA3B,CAV7B;;AAAA;AAUU0B,YAAAA,UAVV;AAWUC,YAAAA,gBAXV,GAW6BC,IAAI,CAACC,SAAL,CAAeH,UAAU,CAACvB,GAA1B,CAX7B;AAYU2B,YAAAA,oBAZV,GAYiCxE,QAAQ,CAAC2B,GAAT,CAAaC,SAAb,CAAuBC,MAAvB,CAA8BwC,gBAA9B,CAZjC;AAaUI,YAAAA,oBAbV,GAaiCzE,QAAQ,CAACgC,MAAT,CAAgBwC,oBAAhB,EAAsC1C,QAAtC,CAA+C9B,QAAQ,CAACiC,GAAT,CAAaC,GAA5D,CAbjC;AAcQC,YAAAA,QAdR,GAcmB,KAdnB;AAeIhC,YAAAA,eAAe,CAACiC,OAAhB,CAAwB,UAAAC,KAAK,EAAI;AAC/B,kBAAIA,KAAK,CAACqC,UAAV,EAAsB;AACpB,oBAAIrC,KAAK,CAACqC,UAAN,KAAqBD,oBAAzB,EAA+C;AAC7CtC,kBAAAA,QAAQ,GAAG,IAAX;AACD;AACF;AACF,aAND,EAfJ,CAsBI;;AAtBJ,iBAuBQA,QAvBR;AAAA;AAAA;AAAA;;AAAA;AAAA,mBAwBwBlC,YAAY,CAAC;AAC7B0E,cAAAA,SAAS,EAAEhB,SADkB;AAE7BiB,cAAAA,WAAW,EAAE,KAFgB;AAG7BC,cAAAA,WAAW,EAAE,WAHgB;AAI7BhB,cAAAA,OAAO,EAAE;AACPC,gBAAAA,QAAQ,EAAE,IADH;AAEPC,gBAAAA,KAAK,EAAEC,MAFA;AAGPC,gBAAAA,KAAK,EAAED,MAHA;AAIPE,gBAAAA,QAAQ,EAAE,IAJH;AAKPC,gBAAAA,MAAM,EAAE;AALD;AAJoB,aAAD,EAW3BP,QAX2B,CAxBpC;;AAAA;AAwBMhD,YAAAA,SAxBN;AAAA,+CAoCaA,SApCb;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,kBAuCU,IAAIS,KAAJ,CAAU,qDAA6C,GAAvD,CAvCV;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,G;;;;SA2CeyD,U;;;;;wEAAf,mBAA0BtC,YAA1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAEwBD,iBAAiB,CAACC,YAAD,CAFzC;;AAAA;AAEUuC,YAAAA,KAFV;AAAA;AAAA,mBAG4BzD,cAAc,CAACyD,KAAD,CAH1C;;AAAA;AAGUC,YAAAA,SAHV;;AAAA,iBAIQA,SAJR;AAAA;AAAA;AAAA;;AAAA;AAAA,mBAK2BtB,aAAa,CAACqB,KAAD,EAAQvC,YAAR,CALxC;;AAAA;AAKY1B,YAAAA,MALZ;AAAA,+CAMaA,MANb;;AAAA;AAAA,+CAQW,IARX;;AAAA;AAAA;AAAA;AAAA,kBAUU,IAAIO,KAAJ,CAAU,4CAAoC,GAA9C,CAVV;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,G;;;;SAce4D,Q;;;;;sEAAf,mBAAwBC,IAAxB;AAAA;AAAA;AAAA;AAAA;AAAA,+CACSzE,GAAG,CAAC0E,MAAJ,CAAWD,IAAX,CADT;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,G;;;;IAIME,O;AACJ,mBAAYC,SAAZ,EAAuBC,IAAvB,EAA6B;AAAA;;AAC3B,SAAKC,OAAL,GAAe,OAAf;AACA,SAAKC,UAAL,GAAkB,KAAlB;AACA,SAAK1E,MAAL,GAAc,IAAd;AACA,SAAKuE,SAAL,GAAiBA,SAAjB;AACA,SAAKC,IAAL,GAAYA,IAAZ;AACAL,IAAAA,QAAQ,CAACI,SAAD,CAAR,CAAoB7D,IAApB,CAAyB,UAACiE,GAAD,EAAMxC,GAAN,EAAc;AACrC,UAAIwC,GAAJ,EAAS;AACP,eAAO,KAAP;AACD;;AACD,aAAO,IAAP;AACD,KALD,WAKS,UAAAtE,KAAK,EAAI;AAChBuE,MAAAA,OAAO,CAACC,GAAR,CAAYxE,KAAZ;AACD,KAPD;AAQD;;;;;;;;;;;;kDAGQ,IAAIJ,OAAJ;AAAA,qFAAY,iBAAOC,OAAP,EAAgBC,MAAhB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kCACb,KAAI,CAACuE,UAAL,KAAoB,KADP;AAAA;AAAA;AAAA;;AAAA;AAAA,mCAEMV,UAAU,WAAI,KAAI,CAACO,SAAT,cAAsB,KAAI,CAACC,IAA3B,EAFhB;;AAAA;AAETxE,4BAAAA,MAFS;AAGf,4BAAA,KAAI,CAAC0E,UAAL,GAAkB,IAAlB;AACA,4BAAA,KAAI,CAAC1E,MAAL,GAAcA,MAAd;AACAE,4BAAAA,OAAO,CAACF,MAAD,CAAP;;AALe;AAOjBG,4BAAAA,MAAM,CAAC,kEAAD,CAAN;;AAPiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAZ;;AAAA;AAAA;AAAA;AAAA,oB;;;;;;;;;;;;;;;;;;iCAWI;AACX,WAAKH,MAAL,GAAc,IAAd;AACA,WAAK0E,UAAL,GAAkB,KAAlB;AACD;;;;gGAEcI,O;;;;;;;uBACQ,KAAK9E,M;;;AAApBA,gBAAAA,M;;;sBAEAA,MAAM,CAAC8E,OAAD,CAAN,CAAgBC,IAAhB,CAAqBC,MAArB,CAA4B,CAA5B,EAA+B,CAA/B,MAAsC,O;;;;;kDACjC,I;;;kDAEF,K;;;;;kDAEA,K;;;;;;;;;;;;;;;;;;wBAIPF,O,EAAuB;AAAA;;AAAA,UAAdG,OAAc,uEAAJ,EAAI;AACzB,aAAO,IAAIhF,OAAJ;AAAA,4EAAY,kBAAOC,OAAP,EAAgBC,MAAhB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBACI,MAAI,CAACH,MADT;;AAAA;AACXA,kBAAAA,MADW;AAEjBA,kBAAAA,MAAM,CAAC8E,OAAD,CAAN,CAAgBG,OAAhB;AAAA,wFAAyB,kBAAO5E,KAAP,EAAcC,QAAd;AAAA;AAAA;AAAA;AAAA;AACvB,kCAAID,KAAJ,EAAW;AACTF,gCAAAA,MAAM,CAACE,KAAD,CAAN;AACD;;AACDH,8BAAAA,OAAO,CAACI,QAAD,CAAP;;AAJuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAzB;;AAAA;AAAA;AAAA;AAAA;;AAFiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAZ;;AAAA;AAAA;AAAA;AAAA,oBAQE,UAAAD,KAAK,EAAI;AAChB,cAAM,IAAIE,KAAJ,CAAU,8BAA8BF,KAA9B,GAAsC,GAAhD,CAAN;AACD,OAVM,CAAP;AAWD;;;;;;AAIH6E,MAAM,CAACC,OAAP,GAAiBb,OAAjB","sourcesContent":["require(\"@babel/polyfill\")\nconst grpc = require('@grpc/grpc-js')\nconst protoLoader = require('@grpc/proto-loader')\nconst CryptoJS = require('crypto-js')\nconst {\n createClient\n} = require('grpc-js-kit')\nconst {\n promisify\n} = require('util')\nconst {\n QRLPROTO_SHA256\n} = require('@theqrl/qrl-proto-sha256')\nconst tmp = require('tmp')\nconst fs = require('fs')\nconst util = require('util')\nconst readFile = util.promisify(fs.readFile)\nconst writeFile = util.promisify(fs.writeFile)\nconst dns = require('dns').promises\nconst PROTO_PATH = 'node_modules/@theqrl/qrlbase.proto/qrlbase.proto'\nlet qrlClient = null\n\nasync function clientGetNodeInfo (client) {\n return new Promise(async (resolve, reject) => {\n try {\n await client.getNodeInfo({}, (error, response) => {\n if (error) {\n throw new Error(error)\n }\n resolve(response)\n })\n } catch (error) {\n throw new Error(error)\n }\n }).catch(error => {\n throw new Error('Unable to get valid proto file (' + error + ')')\n })\n}\n\nasync function checkProtoHash(file) {\n return readFile(file).then(async contents => {\n const protoFileWordArray = CryptoJS.lib.WordArray.create(contents.toString())\n const calculatedProtoHash = CryptoJS.SHA256(protoFileWordArray).toString(CryptoJS.enc.Hex)\n let verified = false\n QRLPROTO_SHA256.forEach(value => {\n if (value.protoHash) {\n if (value.protoHash === calculatedProtoHash) {\n verified = true\n }\n }\n })\n return verified\n })\n}\n\nasync function loadGrpcBaseProto(grpcEndpoint) {\n return new Promise((resolve, reject) => {\n return protoLoader.load(PROTO_PATH, {}).then(async packageDefinition => {\n try {\n const packageObject = grpc.loadPackageDefinition(packageDefinition)\n const client = await new packageObject.qrl.Base(grpcEndpoint, grpc.credentials.createInsecure())\n const res = await clientGetNodeInfo(client)\n const qrlProtoFilePath = tmp.fileSync({\n mode: '0644',\n prefix: 'qrl-',\n postfix: '.proto'\n }).name\n await writeFile(qrlProtoFilePath, res.grpcProto).then(fsErr => {\n if (fsErr) {\n reject('tmp filesystem error')\n }\n }).catch(error => {\n // throw new Error('Unable to load grpc base proto (' + error + ')')\n })\n resolve(qrlProtoFilePath)\n } catch (error) {\n throw new Error('Unable to load grpc base proto (' + error + ')')\n }\n })\n }).catch(error => {\n throw new Error('Unable to load grpc base proto (' + error + ')')\n })\n}\n\nasync function loadGrpcProto(protofile, endpoint) {\n try {\n const options = {\n keepCase: true,\n longs: String,\n enums: String,\n defaults: true,\n oneofs: true,\n }\n const packageDefinition = await protoLoader.load(protofile, options)\n const grpcObject = await grpc.loadPackageDefinition(packageDefinition)\n const grpcObjectString = JSON.stringify(grpcObject.qrl)\n const protoObjectWordArray = CryptoJS.lib.WordArray.create(grpcObjectString)\n const calculatedObjectHash = CryptoJS.SHA256(protoObjectWordArray).toString(CryptoJS.enc.Hex)\n let verified = false\n QRLPROTO_SHA256.forEach(value => {\n if (value.objectHash) {\n if (value.objectHash === calculatedObjectHash) {\n verified = true\n }\n }\n })\n // If the grpc object shasum matches, establish the grpc connection.\n if (verified) {\n qrlClient = await createClient({\n protoPath: protofile,\n packageName: 'qrl',\n serviceName: 'PublicAPI',\n options: {\n keepCase: true,\n longs: String,\n enums: String,\n defaults: true,\n oneofs: true,\n },\n }, endpoint)\n return qrlClient\n }\n } catch (error) {\n throw new Error('Unable to load grpc proto file (' + error + ')')\n }\n}\n\nasync function makeClient(grpcEndpoint) {\n try {\n const proto = await loadGrpcBaseProto(grpcEndpoint)\n const validHash = await checkProtoHash(proto)\n if (validHash) {\n const client = await loadGrpcProto(proto, grpcEndpoint)\n return client\n }\n return null\n } catch (error) {\n throw new Error('Unable to make client (' + error + ')')\n }\n}\n\nasync function validate(node) {\n return dns.lookup(node)\n}\n\nclass QrlNode {\n constructor(ipAddress, port) {\n this.version = '0.5.2'\n this.connection = false\n this.client = null\n this.ipAddress = ipAddress\n this.port = port\n validate(ipAddress).then((err, res) => {\n if (err) {\n return false\n }\n return true\n }).catch(error => {\n console.log(error)\n }) \n }\n\n async connect() {\n return new Promise(async (resolve, reject) => {\n if (this.connection === false) {\n const client = await makeClient(`${this.ipAddress}:${this.port}`)\n this.connection = true\n this.client = client\n resolve(client)\n }\n reject('Already connected... disconnect first or create a new connection')\n })\n }\n\n disconnect() {\n this.client = null\n this.connection = false\n }\n\n async validApi(apiCall) {\n const client = await this.client\n try {\n if (client[apiCall].path.substr(0, 5) === '/qrl.') {\n return true\n }\n return false\n } catch (error) {\n return false\n }\n }\n\n api(apiCall, request = {}) {\n return new Promise(async (resolve, reject) => {\n const client = await this.client\n client[apiCall](request, async (error, response) => {\n if (error) {\n reject(error)\n }\n resolve(response)\n })\n }).catch(error => {\n throw new Error('Unable to make API call (' + error + ')')\n })\n }\n\n}\n\nmodule.exports = QrlNode"],"file":"index.js"} \ No newline at end of file diff --git a/example.js b/example.js new file mode 100644 index 0000000..4606d61 --- /dev/null +++ b/example.js @@ -0,0 +1,14 @@ +var QrlNode = require('./dist/index.js') + +var ip = 'testnet-1.automated.theqrl.org'; +var port = '19009'; +var testnet = new QrlNode(ip, port); + +testnet.connect().then(() => { + console.log(testnet.connection); // true if connection successful + // we can now start using the API + testnet.api('GetStats').then((result) => { + console.log(result); + }); +}); + diff --git a/src/index.js b/src/index.js index 2f64677..25b7424 100644 --- a/src/index.js +++ b/src/index.js @@ -140,9 +140,7 @@ async function makeClient(grpcEndpoint) { } async function validate(node) { - return dns.lookup(node).catch(error => { - throw new Error(error) - }) + return dns.lookup(node) } class QrlNode { @@ -154,21 +152,24 @@ class QrlNode { this.port = port validate(ipAddress).then((err, res) => { if (err) { - throw new Error(err) + return false } + return true }).catch(error => { - throw new Error(error) + console.log(error) }) } async connect() { - if (this.connection === false) { - const client = await makeClient(`${this.ipAddress}:${this.port}`) - this.connection = true - this.client = client - return client - } - throw new Error('Already connected... disconnect first or create a new connection') + return new Promise(async (resolve, reject) => { + if (this.connection === false) { + const client = await makeClient(`${this.ipAddress}:${this.port}`) + this.connection = true + this.client = client + resolve(client) + } + reject('Already connected... disconnect first or create a new connection') + }) } disconnect() { From dc1018237e88f8ad899142d5b17ceeccf50c8f97 Mon Sep 17 00:00:00 2001 From: JP Lomas Date: Fri, 24 Jul 2020 16:33:03 +0100 Subject: [PATCH 6/6] Refactor async code and tests --- dist/index.js | 629 +++++++++++++++++++--------------------------- dist/index.js.map | 2 +- src/index.js | 141 +++++------ test/test.js | 18 +- 4 files changed, 328 insertions(+), 462 deletions(-) diff --git a/dist/index.js b/dist/index.js index d43b78c..b33400d 100644 --- a/dist/index.js +++ b/dist/index.js @@ -10,7 +10,7 @@ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } -require("@babel/polyfill"); +require('@babel/polyfill'); var grpc = require('@grpc/grpc-js'); @@ -35,215 +35,109 @@ var util = require('util'); var readFile = util.promisify(fs.readFile); var writeFile = util.promisify(fs.writeFile); - -var dns = require('dns').promises; - var PROTO_PATH = 'node_modules/@theqrl/qrlbase.proto/qrlbase.proto'; var qrlClient = null; -function clientGetNodeInfo(_x) { - return _clientGetNodeInfo.apply(this, arguments); -} - -function _clientGetNodeInfo() { - _clientGetNodeInfo = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7(client) { - return regeneratorRuntime.wrap(function _callee7$(_context7) { - while (1) { - switch (_context7.prev = _context7.next) { - case 0: - return _context7.abrupt("return", new Promise( /*#__PURE__*/function () { - var _ref4 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee6(resolve, reject) { - return regeneratorRuntime.wrap(function _callee6$(_context6) { - while (1) { - switch (_context6.prev = _context6.next) { - case 0: - _context6.prev = 0; - _context6.next = 3; - return client.getNodeInfo({}, function (error, response) { - if (error) { - throw new Error(error); - } - - resolve(response); - }); - - case 3: - _context6.next = 8; - break; - - case 5: - _context6.prev = 5; - _context6.t0 = _context6["catch"](0); - throw new Error(_context6.t0); - - case 8: - case "end": - return _context6.stop(); - } - } - }, _callee6, null, [[0, 5]]); - })); - - return function (_x15, _x16) { - return _ref4.apply(this, arguments); - }; - }())["catch"](function (error) { - throw new Error('Unable to get valid proto file (' + error + ')'); - })); - - case 1: - case "end": - return _context7.stop(); +function clientGetNodeInfo(client) { + try { + return new Promise(function (resolve, reject) { + client.getNodeInfo({}, function (error, response) { + if (error) { + reject(error); } - } - }, _callee7); - })); - return _clientGetNodeInfo.apply(this, arguments); -} -function checkProtoHash(_x2) { - return _checkProtoHash.apply(this, arguments); + resolve(response); + }); + }); + } catch (error) { + console.log(error); + } } -function _checkProtoHash() { - _checkProtoHash = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee9(file) { - return regeneratorRuntime.wrap(function _callee9$(_context9) { - while (1) { - switch (_context9.prev = _context9.next) { - case 0: - return _context9.abrupt("return", readFile(file).then( /*#__PURE__*/function () { - var _ref5 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee8(contents) { - var protoFileWordArray, calculatedProtoHash, verified; - return regeneratorRuntime.wrap(function _callee8$(_context8) { - while (1) { - switch (_context8.prev = _context8.next) { - case 0: - protoFileWordArray = CryptoJS.lib.WordArray.create(contents.toString()); - calculatedProtoHash = CryptoJS.SHA256(protoFileWordArray).toString(CryptoJS.enc.Hex); - verified = false; - QRLPROTO_SHA256.forEach(function (value) { - if (value.protoHash) { - if (value.protoHash === calculatedProtoHash) { - verified = true; - } - } - }); - return _context8.abrupt("return", verified); - - case 5: - case "end": - return _context8.stop(); - } - } - }, _callee8); - })); - - return function (_x17) { - return _ref5.apply(this, arguments); - }; - }())); - - case 1: - case "end": - return _context9.stop(); +function checkProtoHash(file) { + return readFile(file).then(function (contents) { + // console.log(contents) + var protoFileWordArray = CryptoJS.lib.WordArray.create(contents.toString()); + var calculatedProtoHash = CryptoJS.SHA256(protoFileWordArray).toString(CryptoJS.enc.Hex); + var verified = false; + QRLPROTO_SHA256.forEach(function (value) { + if (value.protoHash) { + if (value.protoHash === calculatedProtoHash) { + verified = true; } } - }, _callee9); - })); - return _checkProtoHash.apply(this, arguments); + }); + return verified; + }); } -function loadGrpcBaseProto(_x3) { - return _loadGrpcBaseProto.apply(this, arguments); -} +function loadGrpcBaseProto(grpcEndpoint) { + return protoLoader.load(PROTO_PATH, {}).then( /*#__PURE__*/function () { + var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(packageDefinition) { + var packageObject, client, res, qrlProtoFilePath; + return regeneratorRuntime.wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + _context.prev = 0; + _context.next = 3; + return grpc.loadPackageDefinition(packageDefinition); + + case 3: + packageObject = _context.sent; + _context.next = 6; + return new packageObject.qrl.Base(grpcEndpoint, grpc.credentials.createInsecure()); + + case 6: + client = _context.sent; + _context.next = 9; + return clientGetNodeInfo(client); + + case 9: + res = _context.sent; + qrlProtoFilePath = tmp.fileSync({ + mode: '0644', + prefix: 'qrl-', + postfix: '.proto' + }).name; + writeFile(qrlProtoFilePath, res.grpcProto).then(function (fsErr) { + if (fsErr) { + console.log('tmp filesystem error'); + } + }); + return _context.abrupt("return", qrlProtoFilePath); -function _loadGrpcBaseProto() { - _loadGrpcBaseProto = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee11(grpcEndpoint) { - return regeneratorRuntime.wrap(function _callee11$(_context11) { - while (1) { - switch (_context11.prev = _context11.next) { - case 0: - return _context11.abrupt("return", new Promise(function (resolve, reject) { - return protoLoader.load(PROTO_PATH, {}).then( /*#__PURE__*/function () { - var _ref6 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee10(packageDefinition) { - var packageObject, client, res, qrlProtoFilePath; - return regeneratorRuntime.wrap(function _callee10$(_context10) { - while (1) { - switch (_context10.prev = _context10.next) { - case 0: - _context10.prev = 0; - packageObject = grpc.loadPackageDefinition(packageDefinition); - _context10.next = 4; - return new packageObject.qrl.Base(grpcEndpoint, grpc.credentials.createInsecure()); - - case 4: - client = _context10.sent; - _context10.next = 7; - return clientGetNodeInfo(client); - - case 7: - res = _context10.sent; - qrlProtoFilePath = tmp.fileSync({ - mode: '0644', - prefix: 'qrl-', - postfix: '.proto' - }).name; - _context10.next = 11; - return writeFile(qrlProtoFilePath, res.grpcProto).then(function (fsErr) { - if (fsErr) { - reject('tmp filesystem error'); - } - })["catch"](function (error) {// throw new Error('Unable to load grpc base proto (' + error + ')') - }); - - case 11: - resolve(qrlProtoFilePath); - _context10.next = 17; - break; - - case 14: - _context10.prev = 14; - _context10.t0 = _context10["catch"](0); - throw new Error('Unable to load grpc base proto (' + _context10.t0 + ')'); - - case 17: - case "end": - return _context10.stop(); - } - } - }, _callee10, null, [[0, 14]]); - })); - - return function (_x18) { - return _ref6.apply(this, arguments); - }; - }()); - })["catch"](function (error) { - throw new Error('Unable to load grpc base proto (' + error + ')'); - })); - - case 1: - case "end": - return _context11.stop(); + case 15: + _context.prev = 15; + _context.t0 = _context["catch"](0); + console.log('Unable to load grpc base proto (' + _context.t0 + ')'); + + case 18: + case "end": + return _context.stop(); + } } - } - }, _callee11); - })); - return _loadGrpcBaseProto.apply(this, arguments); + }, _callee, null, [[0, 15]]); + })); + + return function (_x) { + return _ref.apply(this, arguments); + }; + }()); } -function loadGrpcProto(_x4, _x5) { +function loadGrpcProto(_x2, _x3) { return _loadGrpcProto.apply(this, arguments); } function _loadGrpcProto() { - _loadGrpcProto = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee12(protofile, endpoint) { + _loadGrpcProto = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee7(protofile, endpoint) { var options, packageDefinition, grpcObject, grpcObjectString, protoObjectWordArray, calculatedObjectHash, verified; - return regeneratorRuntime.wrap(function _callee12$(_context12) { + return regeneratorRuntime.wrap(function _callee7$(_context7) { while (1) { - switch (_context12.prev = _context12.next) { + switch (_context7.prev = _context7.next) { case 0: - _context12.prev = 0; + _context7.prev = 0; options = { keepCase: true, longs: String, @@ -251,16 +145,12 @@ function _loadGrpcProto() { defaults: true, oneofs: true }; - _context12.next = 4; + _context7.next = 4; return protoLoader.load(protofile, options); case 4: - packageDefinition = _context12.sent; - _context12.next = 7; - return grpc.loadPackageDefinition(packageDefinition); - - case 7: - grpcObject = _context12.sent; + packageDefinition = _context7.sent; + grpcObject = grpc.loadPackageDefinition(packageDefinition); grpcObjectString = JSON.stringify(grpcObject.qrl); protoObjectWordArray = CryptoJS.lib.WordArray.create(grpcObjectString); calculatedObjectHash = CryptoJS.SHA256(protoObjectWordArray).toString(CryptoJS.enc.Hex); @@ -274,11 +164,11 @@ function _loadGrpcProto() { }); // If the grpc object shasum matches, establish the grpc connection. if (!verified) { - _context12.next = 18; + _context7.next = 16; break; } - _context12.next = 16; + _context7.next = 14; return createClient({ protoPath: protofile, packageName: 'qrl', @@ -292,104 +182,88 @@ function _loadGrpcProto() { } }, endpoint); - case 16: - qrlClient = _context12.sent; - return _context12.abrupt("return", qrlClient); + case 14: + qrlClient = _context7.sent; + return _context7.abrupt("return", qrlClient); - case 18: - _context12.next = 23; + case 16: + _context7.next = 21; break; - case 20: - _context12.prev = 20; - _context12.t0 = _context12["catch"](0); - throw new Error('Unable to load grpc proto file (' + _context12.t0 + ')'); + case 18: + _context7.prev = 18; + _context7.t0 = _context7["catch"](0); + console.log('Unable to load grpc proto file (' + _context7.t0 + ')'); - case 23: + case 21: case "end": - return _context12.stop(); + return _context7.stop(); } } - }, _callee12, null, [[0, 20]]); + }, _callee7, null, [[0, 18]]); })); return _loadGrpcProto.apply(this, arguments); } -function makeClient(_x6) { +function makeClient(_x4) { return _makeClient.apply(this, arguments); } function _makeClient() { - _makeClient = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee13(grpcEndpoint) { + _makeClient = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee8(grpcEndpoint) { var proto, validHash, client; - return regeneratorRuntime.wrap(function _callee13$(_context13) { + return regeneratorRuntime.wrap(function _callee8$(_context8) { while (1) { - switch (_context13.prev = _context13.next) { + switch (_context8.prev = _context8.next) { case 0: - _context13.prev = 0; - _context13.next = 3; + _context8.prev = 0; + _context8.next = 3; return loadGrpcBaseProto(grpcEndpoint); case 3: - proto = _context13.sent; - _context13.next = 6; + proto = _context8.sent; + + if (!proto) { + _context8.next = 13; + break; + } + + _context8.next = 7; return checkProtoHash(proto); - case 6: - validHash = _context13.sent; + case 7: + validHash = _context8.sent; if (!validHash) { - _context13.next = 12; + _context8.next = 13; break; } - _context13.next = 10; + _context8.next = 11; return loadGrpcProto(proto, grpcEndpoint); - case 10: - client = _context13.sent; - return _context13.abrupt("return", client); + case 11: + client = _context8.sent; + return _context8.abrupt("return", client); - case 12: - return _context13.abrupt("return", null); + case 13: + return _context8.abrupt("return", null); - case 15: - _context13.prev = 15; - _context13.t0 = _context13["catch"](0); - throw new Error('Unable to make client (' + _context13.t0 + ')'); + case 16: + _context8.prev = 16; + _context8.t0 = _context8["catch"](0); + console.log('Unable to make client (' + _context8.t0 + ')'); - case 18: + case 19: case "end": - return _context13.stop(); + return _context8.stop(); } } - }, _callee13, null, [[0, 15]]); + }, _callee8, null, [[0, 16]]); })); return _makeClient.apply(this, arguments); } -function validate(_x7) { - return _validate.apply(this, arguments); -} - -function _validate() { - _validate = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee14(node) { - return regeneratorRuntime.wrap(function _callee14$(_context14) { - while (1) { - switch (_context14.prev = _context14.next) { - case 0: - return _context14.abrupt("return", dns.lookup(node)); - - case 1: - case "end": - return _context14.stop(); - } - } - }, _callee14); - })); - return _validate.apply(this, arguments); -} - var QrlNode = /*#__PURE__*/function () { function QrlNode(ipAddress, port) { _classCallCheck(this, QrlNode); @@ -399,78 +273,60 @@ var QrlNode = /*#__PURE__*/function () { this.client = null; this.ipAddress = ipAddress; this.port = port; - validate(ipAddress).then(function (err, res) { - if (err) { - return false; - } - - return true; - })["catch"](function (error) { - console.log(error); - }); } _createClass(QrlNode, [{ key: "connect", - value: function () { - var _connect = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2() { - var _this = this; - - return regeneratorRuntime.wrap(function _callee2$(_context2) { - while (1) { - switch (_context2.prev = _context2.next) { - case 0: - return _context2.abrupt("return", new Promise( /*#__PURE__*/function () { - var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(resolve, reject) { - var client; - return regeneratorRuntime.wrap(function _callee$(_context) { - while (1) { - switch (_context.prev = _context.next) { - case 0: - if (!(_this.connection === false)) { - _context.next = 7; - break; - } - - _context.next = 3; - return makeClient("".concat(_this.ipAddress, ":").concat(_this.port)); + value: function connect() { + var _this = this; + + try { + return new Promise( /*#__PURE__*/function () { + var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(resolve, reject) { + var client; + return regeneratorRuntime.wrap(function _callee2$(_context2) { + while (1) { + switch (_context2.prev = _context2.next) { + case 0: + if (!(_this.connection === false)) { + _context2.next = 7; + break; + } - case 3: - client = _context.sent; - _this.connection = true; - _this.client = client; - resolve(client); + _context2.next = 3; + return makeClient("".concat(_this.ipAddress, ":").concat(_this.port)); - case 7: - reject('Already connected... disconnect first or create a new connection'); + case 3: + client = _context2.sent; - case 8: - case "end": - return _context.stop(); - } - } - }, _callee); - })); + if (client === null) { + _this.connection = false; + } else { + _this.connection = true; + } - return function (_x8, _x9) { - return _ref.apply(this, arguments); - }; - }())); + _this.client = client; + resolve(client); - case 1: - case "end": - return _context2.stop(); - } - } - }, _callee2); - })); + case 7: + reject('Already connected... disconnect first or create a new connection'); - function connect() { - return _connect.apply(this, arguments); + case 8: + case "end": + return _context2.stop(); + } + } + }, _callee2); + })); + + return function (_x5, _x6) { + return _ref2.apply(this, arguments); + }; + }()); + } catch (error) { + console.log(error); } - - return connect; - }() + } }, { key: "disconnect", value: function disconnect() { @@ -486,12 +342,12 @@ var QrlNode = /*#__PURE__*/function () { while (1) { switch (_context3.prev = _context3.next) { case 0: - _context3.next = 2; + _context3.prev = 0; + _context3.next = 3; return this.client; - case 2: + case 3: client = _context3.sent; - _context3.prev = 3; if (!(client[apiCall].path.substr(0, 5) === '/qrl.')) { _context3.next = 6; @@ -505,7 +361,7 @@ var QrlNode = /*#__PURE__*/function () { case 9: _context3.prev = 9; - _context3.t0 = _context3["catch"](3); + _context3.t0 = _context3["catch"](0); return _context3.abrupt("return", false); case 12: @@ -513,10 +369,10 @@ var QrlNode = /*#__PURE__*/function () { return _context3.stop(); } } - }, _callee3, this, [[3, 9]]); + }, _callee3, this, [[0, 9]]); })); - function validApi(_x10) { + function validApi(_x7) { return _validApi.apply(this, arguments); } @@ -524,62 +380,87 @@ var QrlNode = /*#__PURE__*/function () { }() }, { key: "api", - value: function api(apiCall) { - var _this2 = this; - - var request = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - return new Promise( /*#__PURE__*/function () { - var _ref2 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(resolve, reject) { - var client; - return regeneratorRuntime.wrap(function _callee5$(_context5) { - while (1) { - switch (_context5.prev = _context5.next) { - case 0: - _context5.next = 2; - return _this2.client; - - case 2: - client = _context5.sent; - client[apiCall](request, /*#__PURE__*/function () { - var _ref3 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4(error, response) { - return regeneratorRuntime.wrap(function _callee4$(_context4) { - while (1) { - switch (_context4.prev = _context4.next) { - case 0: - if (error) { - reject(error); - } - - resolve(response); - - case 2: - case "end": - return _context4.stop(); - } + value: function () { + var _api = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee6(apiCall) { + var _this2 = this; + + var request, + _args6 = arguments; + return regeneratorRuntime.wrap(function _callee6$(_context6) { + while (1) { + switch (_context6.prev = _context6.next) { + case 0: + request = _args6.length > 1 && _args6[1] !== undefined ? _args6[1] : {}; + _context6.prev = 1; + return _context6.abrupt("return", new Promise( /*#__PURE__*/function () { + var _ref3 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5(resolve, reject) { + var client; + return regeneratorRuntime.wrap(function _callee5$(_context5) { + while (1) { + switch (_context5.prev = _context5.next) { + case 0: + _context5.next = 2; + return _this2.client; + + case 2: + client = _context5.sent; + client[apiCall](request, /*#__PURE__*/function () { + var _ref4 = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4(error, response) { + return regeneratorRuntime.wrap(function _callee4$(_context4) { + while (1) { + switch (_context4.prev = _context4.next) { + case 0: + if (error) { + reject(error); + } + + resolve(response); + + case 2: + case "end": + return _context4.stop(); + } + } + }, _callee4); + })); + + return function (_x11, _x12) { + return _ref4.apply(this, arguments); + }; + }()); + + case 4: + case "end": + return _context5.stop(); } - }, _callee4); - })); + } + }, _callee5); + })); - return function (_x13, _x14) { - return _ref3.apply(this, arguments); - }; - }()); + return function (_x9, _x10) { + return _ref3.apply(this, arguments); + }; + }())); - case 4: - case "end": - return _context5.stop(); - } + case 5: + _context6.prev = 5; + _context6.t0 = _context6["catch"](1); + console.log('Unable to make API call (' + _context6.t0 + ')'); + + case 8: + case "end": + return _context6.stop(); } - }, _callee5); - })); - - return function (_x11, _x12) { - return _ref2.apply(this, arguments); - }; - }())["catch"](function (error) { - throw new Error('Unable to make API call (' + error + ')'); - }); - } + } + }, _callee6, null, [[1, 5]]); + })); + + function api(_x8) { + return _api.apply(this, arguments); + } + + return api; + }() }]); return QrlNode; diff --git a/dist/index.js.map b/dist/index.js.map index 81c6a6f..c969787 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/index.js"],"names":["require","grpc","protoLoader","CryptoJS","createClient","promisify","QRLPROTO_SHA256","tmp","fs","util","readFile","writeFile","dns","promises","PROTO_PATH","qrlClient","clientGetNodeInfo","client","Promise","resolve","reject","getNodeInfo","error","response","Error","checkProtoHash","file","then","contents","protoFileWordArray","lib","WordArray","create","toString","calculatedProtoHash","SHA256","enc","Hex","verified","forEach","value","protoHash","loadGrpcBaseProto","grpcEndpoint","load","packageDefinition","packageObject","loadPackageDefinition","qrl","Base","credentials","createInsecure","res","qrlProtoFilePath","fileSync","mode","prefix","postfix","name","grpcProto","fsErr","loadGrpcProto","protofile","endpoint","options","keepCase","longs","String","enums","defaults","oneofs","grpcObject","grpcObjectString","JSON","stringify","protoObjectWordArray","calculatedObjectHash","objectHash","protoPath","packageName","serviceName","makeClient","proto","validHash","validate","node","lookup","QrlNode","ipAddress","port","version","connection","err","console","log","apiCall","path","substr","request","module","exports"],"mappings":"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","sourcesContent":["require(\"@babel/polyfill\")\nconst grpc = require('@grpc/grpc-js')\nconst protoLoader = require('@grpc/proto-loader')\nconst CryptoJS = require('crypto-js')\nconst {\n createClient\n} = require('grpc-js-kit')\nconst {\n promisify\n} = require('util')\nconst {\n QRLPROTO_SHA256\n} = require('@theqrl/qrl-proto-sha256')\nconst tmp = require('tmp')\nconst fs = require('fs')\nconst util = require('util')\nconst readFile = util.promisify(fs.readFile)\nconst writeFile = util.promisify(fs.writeFile)\nconst dns = require('dns').promises\nconst PROTO_PATH = 'node_modules/@theqrl/qrlbase.proto/qrlbase.proto'\nlet qrlClient = null\n\nasync function clientGetNodeInfo (client) {\n return new Promise(async (resolve, reject) => {\n try {\n await client.getNodeInfo({}, (error, response) => {\n if (error) {\n throw new Error(error)\n }\n resolve(response)\n })\n } catch (error) {\n throw new Error(error)\n }\n }).catch(error => {\n throw new Error('Unable to get valid proto file (' + error + ')')\n })\n}\n\nasync function checkProtoHash(file) {\n return readFile(file).then(async contents => {\n const protoFileWordArray = CryptoJS.lib.WordArray.create(contents.toString())\n const calculatedProtoHash = CryptoJS.SHA256(protoFileWordArray).toString(CryptoJS.enc.Hex)\n let verified = false\n QRLPROTO_SHA256.forEach(value => {\n if (value.protoHash) {\n if (value.protoHash === calculatedProtoHash) {\n verified = true\n }\n }\n })\n return verified\n })\n}\n\nasync function loadGrpcBaseProto(grpcEndpoint) {\n return new Promise((resolve, reject) => {\n return protoLoader.load(PROTO_PATH, {}).then(async packageDefinition => {\n try {\n const packageObject = grpc.loadPackageDefinition(packageDefinition)\n const client = await new packageObject.qrl.Base(grpcEndpoint, grpc.credentials.createInsecure())\n const res = await clientGetNodeInfo(client)\n const qrlProtoFilePath = tmp.fileSync({\n mode: '0644',\n prefix: 'qrl-',\n postfix: '.proto'\n }).name\n await writeFile(qrlProtoFilePath, res.grpcProto).then(fsErr => {\n if (fsErr) {\n reject('tmp filesystem error')\n }\n }).catch(error => {\n // throw new Error('Unable to load grpc base proto (' + error + ')')\n })\n resolve(qrlProtoFilePath)\n } catch (error) {\n throw new Error('Unable to load grpc base proto (' + error + ')')\n }\n })\n }).catch(error => {\n throw new Error('Unable to load grpc base proto (' + error + ')')\n })\n}\n\nasync function loadGrpcProto(protofile, endpoint) {\n try {\n const options = {\n keepCase: true,\n longs: String,\n enums: String,\n defaults: true,\n oneofs: true,\n }\n const packageDefinition = await protoLoader.load(protofile, options)\n const grpcObject = await grpc.loadPackageDefinition(packageDefinition)\n const grpcObjectString = JSON.stringify(grpcObject.qrl)\n const protoObjectWordArray = CryptoJS.lib.WordArray.create(grpcObjectString)\n const calculatedObjectHash = CryptoJS.SHA256(protoObjectWordArray).toString(CryptoJS.enc.Hex)\n let verified = false\n QRLPROTO_SHA256.forEach(value => {\n if (value.objectHash) {\n if (value.objectHash === calculatedObjectHash) {\n verified = true\n }\n }\n })\n // If the grpc object shasum matches, establish the grpc connection.\n if (verified) {\n qrlClient = await createClient({\n protoPath: protofile,\n packageName: 'qrl',\n serviceName: 'PublicAPI',\n options: {\n keepCase: true,\n longs: String,\n enums: String,\n defaults: true,\n oneofs: true,\n },\n }, endpoint)\n return qrlClient\n }\n } catch (error) {\n throw new Error('Unable to load grpc proto file (' + error + ')')\n }\n}\n\nasync function makeClient(grpcEndpoint) {\n try {\n const proto = await loadGrpcBaseProto(grpcEndpoint)\n const validHash = await checkProtoHash(proto)\n if (validHash) {\n const client = await loadGrpcProto(proto, grpcEndpoint)\n return client\n }\n return null\n } catch (error) {\n throw new Error('Unable to make client (' + error + ')')\n }\n}\n\nasync function validate(node) {\n return dns.lookup(node)\n}\n\nclass QrlNode {\n constructor(ipAddress, port) {\n this.version = '0.5.2'\n this.connection = false\n this.client = null\n this.ipAddress = ipAddress\n this.port = port\n validate(ipAddress).then((err, res) => {\n if (err) {\n return false\n }\n return true\n }).catch(error => {\n console.log(error)\n }) \n }\n\n async connect() {\n return new Promise(async (resolve, reject) => {\n if (this.connection === false) {\n const client = await makeClient(`${this.ipAddress}:${this.port}`)\n this.connection = true\n this.client = client\n resolve(client)\n }\n reject('Already connected... disconnect first or create a new connection')\n })\n }\n\n disconnect() {\n this.client = null\n this.connection = false\n }\n\n async validApi(apiCall) {\n const client = await this.client\n try {\n if (client[apiCall].path.substr(0, 5) === '/qrl.') {\n return true\n }\n return false\n } catch (error) {\n return false\n }\n }\n\n api(apiCall, request = {}) {\n return new Promise(async (resolve, reject) => {\n const client = await this.client\n client[apiCall](request, async (error, response) => {\n if (error) {\n reject(error)\n }\n resolve(response)\n })\n }).catch(error => {\n throw new Error('Unable to make API call (' + error + ')')\n })\n }\n\n}\n\nmodule.exports = QrlNode"],"file":"index.js"} \ No newline at end of file +{"version":3,"sources":["../src/index.js"],"names":["require","grpc","protoLoader","CryptoJS","createClient","promisify","QRLPROTO_SHA256","tmp","fs","util","readFile","writeFile","PROTO_PATH","qrlClient","clientGetNodeInfo","client","Promise","resolve","reject","getNodeInfo","error","response","console","log","checkProtoHash","file","then","contents","protoFileWordArray","lib","WordArray","create","toString","calculatedProtoHash","SHA256","enc","Hex","verified","forEach","value","protoHash","loadGrpcBaseProto","grpcEndpoint","load","packageDefinition","loadPackageDefinition","packageObject","qrl","Base","credentials","createInsecure","res","qrlProtoFilePath","fileSync","mode","prefix","postfix","name","grpcProto","fsErr","loadGrpcProto","protofile","endpoint","options","keepCase","longs","String","enums","defaults","oneofs","grpcObject","grpcObjectString","JSON","stringify","protoObjectWordArray","calculatedObjectHash","objectHash","protoPath","packageName","serviceName","makeClient","proto","validHash","QrlNode","ipAddress","port","version","connection","apiCall","path","substr","request","module","exports"],"mappings":";;;;;;;;;;;;AAAAA,OAAO,CAAC,iBAAD,CAAP;;AACA,IAAMC,IAAI,GAAGD,OAAO,CAAC,eAAD,CAApB;;AACA,IAAME,WAAW,GAAGF,OAAO,CAAC,oBAAD,CAA3B;;AACA,IAAMG,QAAQ,GAAGH,OAAO,CAAC,WAAD,CAAxB;;eACyBA,OAAO,CAAC,aAAD,C;IAAxBI,Y,YAAAA,Y;;gBACcJ,OAAO,CAAC,MAAD,C;IAArBK,S,aAAAA,S;;gBACoBL,OAAO,CAAC,0BAAD,C;IAA3BM,e,aAAAA,e;;AACR,IAAMC,GAAG,GAAGP,OAAO,CAAC,KAAD,CAAnB;;AACA,IAAMQ,EAAE,GAAGR,OAAO,CAAC,IAAD,CAAlB;;AACA,IAAMS,IAAI,GAAGT,OAAO,CAAC,MAAD,CAApB;;AACA,IAAMU,QAAQ,GAAGD,IAAI,CAACJ,SAAL,CAAeG,EAAE,CAACE,QAAlB,CAAjB;AACA,IAAMC,SAAS,GAAGF,IAAI,CAACJ,SAAL,CAAeG,EAAE,CAACG,SAAlB,CAAlB;AACA,IAAMC,UAAU,GAAG,kDAAnB;AACA,IAAIC,SAAS,GAAG,IAAhB;;AAEA,SAASC,iBAAT,CAA4BC,MAA5B,EAAoC;AAClC,MAAI;AACF,WAAO,IAAIC,OAAJ,CAAY,UAACC,OAAD,EAAUC,MAAV,EAAqB;AACtCH,MAAAA,MAAM,CAACI,WAAP,CAAmB,EAAnB,EAAuB,UAACC,KAAD,EAAQC,QAAR,EAAqB;AAC1C,YAAID,KAAJ,EAAW;AACTF,UAAAA,MAAM,CAACE,KAAD,CAAN;AACD;;AACDH,QAAAA,OAAO,CAACI,QAAD,CAAP;AACD,OALD;AAMD,KAPM,CAAP;AAQD,GATD,CASE,OAAOD,KAAP,EAAc;AACdE,IAAAA,OAAO,CAACC,GAAR,CAAYH,KAAZ;AACD;AACF;;AAED,SAASI,cAAT,CAAwBC,IAAxB,EAA8B;AAC5B,SAAOf,QAAQ,CAACe,IAAD,CAAR,CAAeC,IAAf,CAAoB,UAAAC,QAAQ,EAAI;AACrC;AACA,QAAMC,kBAAkB,GAAGzB,QAAQ,CAAC0B,GAAT,CAAaC,SAAb,CAAuBC,MAAvB,CAA8BJ,QAAQ,CAACK,QAAT,EAA9B,CAA3B;AACA,QAAMC,mBAAmB,GAAG9B,QAAQ,CAAC+B,MAAT,CAAgBN,kBAAhB,EAAoCI,QAApC,CAA6C7B,QAAQ,CAACgC,GAAT,CAAaC,GAA1D,CAA5B;AACA,QAAIC,QAAQ,GAAG,KAAf;AACA/B,IAAAA,eAAe,CAACgC,OAAhB,CAAwB,UAAAC,KAAK,EAAI;AAC/B,UAAIA,KAAK,CAACC,SAAV,EAAqB;AACnB,YAAID,KAAK,CAACC,SAAN,KAAoBP,mBAAxB,EAA6C;AAC3CI,UAAAA,QAAQ,GAAG,IAAX;AACD;AACF;AACF,KAND;AAOA,WAAOA,QAAP;AACD,GAbM,CAAP;AAcD;;AAED,SAASI,iBAAT,CAA2BC,YAA3B,EAAyC;AACrC,SAAOxC,WAAW,CAACyC,IAAZ,CAAiB/B,UAAjB,EAA6B,EAA7B,EAAiCc,IAAjC;AAAA,uEAAsC,iBAAMkB,iBAAN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAEb3C,IAAI,CAAC4C,qBAAL,CAA2BD,iBAA3B,CAFa;;AAAA;AAEnCE,cAAAA,aAFmC;AAAA;AAAA,qBAGpB,IAAIA,aAAa,CAACC,GAAd,CAAkBC,IAAtB,CAA2BN,YAA3B,EAAyCzC,IAAI,CAACgD,WAAL,CAAiBC,cAAjB,EAAzC,CAHoB;;AAAA;AAGnCnC,cAAAA,MAHmC;AAAA;AAAA,qBAKvBD,iBAAiB,CAACC,MAAD,CALM;;AAAA;AAKnCoC,cAAAA,GALmC;AAMnCC,cAAAA,gBANmC,GAMhB7C,GAAG,CAAC8C,QAAJ,CAAa;AACpCC,gBAAAA,IAAI,EAAE,MAD8B;AAEpCC,gBAAAA,MAAM,EAAE,MAF4B;AAGpCC,gBAAAA,OAAO,EAAE;AAH2B,eAAb,EAItBC,IAVsC;AAWzC9C,cAAAA,SAAS,CAACyC,gBAAD,EAAmBD,GAAG,CAACO,SAAvB,CAAT,CAA2ChC,IAA3C,CAAgD,UAAAiC,KAAK,EAAI;AACvD,oBAAIA,KAAJ,EAAW;AACTrC,kBAAAA,OAAO,CAACC,GAAR,CAAY,sBAAZ;AACD;AACF,eAJD;AAXyC,+CAgBlC6B,gBAhBkC;;AAAA;AAAA;AAAA;AAkBzC9B,cAAAA,OAAO,CAACC,GAAR,CAAY,mDAA6C,GAAzD;;AAlByC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAAtC;;AAAA;AAAA;AAAA;AAAA,MAAP;AAqBH;;SAEcqC,a;;;;;2EAAf,kBAA6BC,SAA7B,EAAwCC,QAAxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEUC,YAAAA,OAFV,GAEoB;AACdC,cAAAA,QAAQ,EAAE,IADI;AAEdC,cAAAA,KAAK,EAAEC,MAFO;AAGdC,cAAAA,KAAK,EAAED,MAHO;AAIdE,cAAAA,QAAQ,EAAE,IAJI;AAKdC,cAAAA,MAAM,EAAE;AALM,aAFpB;AAAA;AAAA,mBASoCnE,WAAW,CAACyC,IAAZ,CAAiBkB,SAAjB,EAA4BE,OAA5B,CATpC;;AAAA;AASUnB,YAAAA,iBATV;AAUU0B,YAAAA,UAVV,GAUuBrE,IAAI,CAAC4C,qBAAL,CAA2BD,iBAA3B,CAVvB;AAWU2B,YAAAA,gBAXV,GAW6BC,IAAI,CAACC,SAAL,CAAeH,UAAU,CAACvB,GAA1B,CAX7B;AAYU2B,YAAAA,oBAZV,GAYiCvE,QAAQ,CAAC0B,GAAT,CAAaC,SAAb,CAAuBC,MAAvB,CAA8BwC,gBAA9B,CAZjC;AAaUI,YAAAA,oBAbV,GAaiCxE,QAAQ,CAAC+B,MAAT,CAAgBwC,oBAAhB,EAAsC1C,QAAtC,CAA+C7B,QAAQ,CAACgC,GAAT,CAAaC,GAA5D,CAbjC;AAcQC,YAAAA,QAdR,GAcmB,KAdnB;AAeI/B,YAAAA,eAAe,CAACgC,OAAhB,CAAwB,UAAAC,KAAK,EAAI;AAC/B,kBAAIA,KAAK,CAACqC,UAAV,EAAsB;AACpB,oBAAIrC,KAAK,CAACqC,UAAN,KAAqBD,oBAAzB,EAA+C;AAC7CtC,kBAAAA,QAAQ,GAAG,IAAX;AACD;AACF;AACF,aAND,EAfJ,CAsBI;;AAtBJ,iBAuBQA,QAvBR;AAAA;AAAA;AAAA;;AAAA;AAAA,mBAwBwBjC,YAAY,CAAC;AAC7ByE,cAAAA,SAAS,EAAEhB,SADkB;AAE7BiB,cAAAA,WAAW,EAAE,KAFgB;AAG7BC,cAAAA,WAAW,EAAE,WAHgB;AAI7BhB,cAAAA,OAAO,EAAE;AACPC,gBAAAA,QAAQ,EAAE,IADH;AAEPC,gBAAAA,KAAK,EAAEC,MAFA;AAGPC,gBAAAA,KAAK,EAAED,MAHA;AAIPE,gBAAAA,QAAQ,EAAE,IAJH;AAKPC,gBAAAA,MAAM,EAAE;AALD;AAJoB,aAAD,EAW3BP,QAX2B,CAxBpC;;AAAA;AAwBMjD,YAAAA,SAxBN;AAAA,8CAoCaA,SApCb;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAuCIS,YAAAA,OAAO,CAACC,GAAR,CAAY,oDAA6C,GAAzD;;AAvCJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,G;;;;SA2CeyD,U;;;;;wEAAf,kBAA0BtC,YAA1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAEwBD,iBAAiB,CAACC,YAAD,CAFzC;;AAAA;AAEUuC,YAAAA,KAFV;;AAAA,iBAGQA,KAHR;AAAA;AAAA;AAAA;;AAAA;AAAA,mBAI8BzD,cAAc,CAACyD,KAAD,CAJ5C;;AAAA;AAIYC,YAAAA,SAJZ;;AAAA,iBAKUA,SALV;AAAA;AAAA;AAAA;;AAAA;AAAA,mBAM6BtB,aAAa,CAACqB,KAAD,EAAQvC,YAAR,CAN1C;;AAAA;AAMc3B,YAAAA,MANd;AAAA,8CAOeA,MAPf;;AAAA;AAAA,8CAUW,IAVX;;AAAA;AAAA;AAAA;AAYIO,YAAAA,OAAO,CAACC,GAAR,CAAY,2CAAoC,GAAhD;;AAZJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,G;;;;IAiBM4D,O;AACJ,mBAAYC,SAAZ,EAAuBC,IAAvB,EAA6B;AAAA;;AAC3B,SAAKC,OAAL,GAAe,OAAf;AACA,SAAKC,UAAL,GAAkB,KAAlB;AACA,SAAKxE,MAAL,GAAc,IAAd;AACA,SAAKqE,SAAL,GAAiBA,SAAjB;AACA,SAAKC,IAAL,GAAYA,IAAZ;AACD;;;;8BAES;AAAA;;AACR,UAAI;AACF,eAAO,IAAIrE,OAAJ;AAAA,8EAAY,kBAAOC,OAAP,EAAgBC,MAAhB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BACb,KAAI,CAACqE,UAAL,KAAoB,KADP;AAAA;AAAA;AAAA;;AAAA;AAAA,2BAEMP,UAAU,WAAI,KAAI,CAACI,SAAT,cAAsB,KAAI,CAACC,IAA3B,EAFhB;;AAAA;AAETtE,oBAAAA,MAFS;;AAGf,wBAAIA,MAAM,KAAK,IAAf,EAAqB;AACnB,sBAAA,KAAI,CAACwE,UAAL,GAAkB,KAAlB;AACD,qBAFD,MAEO;AACL,sBAAA,KAAI,CAACA,UAAL,GAAkB,IAAlB;AACD;;AACD,oBAAA,KAAI,CAACxE,MAAL,GAAcA,MAAd;AACAE,oBAAAA,OAAO,CAACF,MAAD,CAAP;;AATe;AAWjBG,oBAAAA,MAAM,CAAC,kEAAD,CAAN;;AAXiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAAZ;;AAAA;AAAA;AAAA;AAAA,YAAP;AAaD,OAdD,CAcE,OAAOE,KAAP,EAAc;AACdE,QAAAA,OAAO,CAACC,GAAR,CAAYH,KAAZ;AACD;AACF;;;iCAEY;AACX,WAAKL,MAAL,GAAc,IAAd;AACA,WAAKwE,UAAL,GAAkB,KAAlB;AACD;;;;gGAEcC,O;;;;;;;;uBAEU,KAAKzE,M;;;AAApBA,gBAAAA,M;;sBACFA,MAAM,CAACyE,OAAD,CAAN,CAAgBC,IAAhB,CAAqBC,MAArB,CAA4B,CAA5B,EAA+B,CAA/B,MAAsC,O;;;;;kDACjC,I;;;kDAEF,K;;;;;kDAEA,K;;;;;;;;;;;;;;;;;;;2FAIDF,O;;;;;;;;;AAASG,gBAAAA,O,8DAAU,E;;kDAElB,IAAI3E,OAAJ;AAAA,sFAAY,kBAAOC,OAAP,EAAgBC,MAAhB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mCACI,MAAI,CAACH,MADT;;AAAA;AACXA,4BAAAA,MADW;AAEjBA,4BAAAA,MAAM,CAACyE,OAAD,CAAN,CAAgBG,OAAhB;AAAA,kGAAyB,kBAAOvE,KAAP,EAAcC,QAAd;AAAA;AAAA;AAAA;AAAA;AACvB,4CAAID,KAAJ,EAAW;AACTF,0CAAAA,MAAM,CAACE,KAAD,CAAN;AACD;;AACDH,wCAAAA,OAAO,CAACI,QAAD,CAAP;;AAJuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAAzB;;AAAA;AAAA;AAAA;AAAA;;AAFiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAZ;;AAAA;AAAA;AAAA;AAAA,oB;;;;;AAUPC,gBAAAA,OAAO,CAACC,GAAR,CAAY,6CAAsC,GAAlD;;;;;;;;;;;;;;;;;;;;;AAKNqE,MAAM,CAACC,OAAP,GAAiBV,OAAjB","sourcesContent":["require('@babel/polyfill')\nconst grpc = require('@grpc/grpc-js')\nconst protoLoader = require('@grpc/proto-loader')\nconst CryptoJS = require('crypto-js')\nconst { createClient } = require('grpc-js-kit')\nconst { promisify } = require('util')\nconst { QRLPROTO_SHA256 } = require('@theqrl/qrl-proto-sha256')\nconst tmp = require('tmp')\nconst fs = require('fs')\nconst util = require('util')\nconst readFile = util.promisify(fs.readFile)\nconst writeFile = util.promisify(fs.writeFile)\nconst PROTO_PATH = 'node_modules/@theqrl/qrlbase.proto/qrlbase.proto'\nlet qrlClient = null\n\nfunction clientGetNodeInfo (client) {\n try {\n return new Promise((resolve, reject) => {\n client.getNodeInfo({}, (error, response) => {\n if (error) {\n reject(error)\n }\n resolve(response)\n })\n })\n } catch (error) {\n console.log(error)\n }\n}\n\nfunction checkProtoHash(file) {\n return readFile(file).then(contents => {\n // console.log(contents)\n const protoFileWordArray = CryptoJS.lib.WordArray.create(contents.toString())\n const calculatedProtoHash = CryptoJS.SHA256(protoFileWordArray).toString(CryptoJS.enc.Hex)\n let verified = false\n QRLPROTO_SHA256.forEach(value => {\n if (value.protoHash) {\n if (value.protoHash === calculatedProtoHash) {\n verified = true\n }\n }\n })\n return verified\n })\n}\n\nfunction loadGrpcBaseProto(grpcEndpoint) {\n return protoLoader.load(PROTO_PATH, {}).then(async packageDefinition => {\n try {\n const packageObject = await grpc.loadPackageDefinition(packageDefinition)\n const client = await new packageObject.qrl.Base(grpcEndpoint, grpc.credentials.createInsecure())\n // console.log(client)\n const res = await clientGetNodeInfo(client)\n const qrlProtoFilePath = tmp.fileSync({\n mode: '0644',\n prefix: 'qrl-',\n postfix: '.proto'\n }).name\n writeFile(qrlProtoFilePath, res.grpcProto).then(fsErr => {\n if (fsErr) {\n console.log('tmp filesystem error')\n }\n })\n return(qrlProtoFilePath)\n } catch (error) {\n console.log('Unable to load grpc base proto (' + error + ')')\n }\n })\n}\n\nasync function loadGrpcProto(protofile, endpoint) {\n try {\n const options = {\n keepCase: true,\n longs: String,\n enums: String,\n defaults: true,\n oneofs: true,\n }\n const packageDefinition = await protoLoader.load(protofile, options)\n const grpcObject = grpc.loadPackageDefinition(packageDefinition)\n const grpcObjectString = JSON.stringify(grpcObject.qrl)\n const protoObjectWordArray = CryptoJS.lib.WordArray.create(grpcObjectString)\n const calculatedObjectHash = CryptoJS.SHA256(protoObjectWordArray).toString(CryptoJS.enc.Hex)\n let verified = false\n QRLPROTO_SHA256.forEach(value => {\n if (value.objectHash) {\n if (value.objectHash === calculatedObjectHash) {\n verified = true\n }\n }\n })\n // If the grpc object shasum matches, establish the grpc connection.\n if (verified) {\n qrlClient = await createClient({\n protoPath: protofile,\n packageName: 'qrl',\n serviceName: 'PublicAPI',\n options: {\n keepCase: true,\n longs: String,\n enums: String,\n defaults: true,\n oneofs: true,\n },\n }, endpoint)\n return qrlClient\n }\n } catch (error) {\n console.log('Unable to load grpc proto file (' + error + ')')\n }\n}\n\nasync function makeClient(grpcEndpoint) {\n try {\n const proto = await loadGrpcBaseProto(grpcEndpoint)\n if (proto) {\n const validHash = await checkProtoHash(proto)\n if (validHash) {\n const client = await loadGrpcProto(proto, grpcEndpoint)\n return client\n }\n }\n return null\n } catch (error) {\n console.log('Unable to make client (' + error + ')')\n }\n}\n\n\nclass QrlNode {\n constructor(ipAddress, port) {\n this.version = '0.5.2'\n this.connection = false\n this.client = null\n this.ipAddress = ipAddress\n this.port = port\n }\n\n connect() {\n try {\n return new Promise(async (resolve, reject) => {\n if (this.connection === false) {\n const client = await makeClient(`${this.ipAddress}:${this.port}`)\n if (client === null) {\n this.connection = false\n } else {\n this.connection = true\n }\n this.client = client\n resolve(client)\n }\n reject('Already connected... disconnect first or create a new connection')\n })\n } catch (error) {\n console.log(error)\n }\n }\n\n disconnect() {\n this.client = null\n this.connection = false\n }\n\n async validApi(apiCall) {\n try {\n const client = await this.client\n if (client[apiCall].path.substr(0, 5) === '/qrl.') {\n return true\n }\n return false\n } catch (error) {\n return false\n }\n }\n\n async api(apiCall, request = {}) {\n try {\n return new Promise(async (resolve, reject) => {\n const client = await this.client\n client[apiCall](request, async (error, response) => {\n if (error) {\n reject(error)\n }\n resolve(response)\n })\n })\n } catch (error) {\n console.log('Unable to make API call (' + error + ')')\n }\n }\n}\n\nmodule.exports = QrlNode"],"file":"index.js"} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 25b7424..9677310 100644 --- a/src/index.js +++ b/src/index.js @@ -1,44 +1,36 @@ -require("@babel/polyfill") +require('@babel/polyfill') const grpc = require('@grpc/grpc-js') const protoLoader = require('@grpc/proto-loader') const CryptoJS = require('crypto-js') -const { - createClient -} = require('grpc-js-kit') -const { - promisify -} = require('util') -const { - QRLPROTO_SHA256 -} = require('@theqrl/qrl-proto-sha256') +const { createClient } = require('grpc-js-kit') +const { promisify } = require('util') +const { QRLPROTO_SHA256 } = require('@theqrl/qrl-proto-sha256') const tmp = require('tmp') const fs = require('fs') const util = require('util') const readFile = util.promisify(fs.readFile) const writeFile = util.promisify(fs.writeFile) -const dns = require('dns').promises const PROTO_PATH = 'node_modules/@theqrl/qrlbase.proto/qrlbase.proto' let qrlClient = null -async function clientGetNodeInfo (client) { - return new Promise(async (resolve, reject) => { - try { - await client.getNodeInfo({}, (error, response) => { +function clientGetNodeInfo (client) { + try { + return new Promise((resolve, reject) => { + client.getNodeInfo({}, (error, response) => { if (error) { - throw new Error(error) + reject(error) } resolve(response) }) - } catch (error) { - throw new Error(error) - } - }).catch(error => { - throw new Error('Unable to get valid proto file (' + error + ')') - }) + }) + } catch (error) { + console.log(error) + } } -async function checkProtoHash(file) { - return readFile(file).then(async contents => { +function checkProtoHash(file) { + return readFile(file).then(contents => { + // console.log(contents) const protoFileWordArray = CryptoJS.lib.WordArray.create(contents.toString()) const calculatedProtoHash = CryptoJS.SHA256(protoFileWordArray).toString(CryptoJS.enc.Hex) let verified = false @@ -53,33 +45,28 @@ async function checkProtoHash(file) { }) } -async function loadGrpcBaseProto(grpcEndpoint) { - return new Promise((resolve, reject) => { +function loadGrpcBaseProto(grpcEndpoint) { return protoLoader.load(PROTO_PATH, {}).then(async packageDefinition => { try { - const packageObject = grpc.loadPackageDefinition(packageDefinition) + const packageObject = await grpc.loadPackageDefinition(packageDefinition) const client = await new packageObject.qrl.Base(grpcEndpoint, grpc.credentials.createInsecure()) + // console.log(client) const res = await clientGetNodeInfo(client) const qrlProtoFilePath = tmp.fileSync({ mode: '0644', prefix: 'qrl-', postfix: '.proto' }).name - await writeFile(qrlProtoFilePath, res.grpcProto).then(fsErr => { + writeFile(qrlProtoFilePath, res.grpcProto).then(fsErr => { if (fsErr) { - reject('tmp filesystem error') + console.log('tmp filesystem error') } - }).catch(error => { - // throw new Error('Unable to load grpc base proto (' + error + ')') }) - resolve(qrlProtoFilePath) + return(qrlProtoFilePath) } catch (error) { - throw new Error('Unable to load grpc base proto (' + error + ')') + console.log('Unable to load grpc base proto (' + error + ')') } }) - }).catch(error => { - throw new Error('Unable to load grpc base proto (' + error + ')') - }) } async function loadGrpcProto(protofile, endpoint) { @@ -92,7 +79,7 @@ async function loadGrpcProto(protofile, endpoint) { oneofs: true, } const packageDefinition = await protoLoader.load(protofile, options) - const grpcObject = await grpc.loadPackageDefinition(packageDefinition) + const grpcObject = grpc.loadPackageDefinition(packageDefinition) const grpcObjectString = JSON.stringify(grpcObject.qrl) const protoObjectWordArray = CryptoJS.lib.WordArray.create(grpcObjectString) const calculatedObjectHash = CryptoJS.SHA256(protoObjectWordArray).toString(CryptoJS.enc.Hex) @@ -121,27 +108,26 @@ async function loadGrpcProto(protofile, endpoint) { return qrlClient } } catch (error) { - throw new Error('Unable to load grpc proto file (' + error + ')') + console.log('Unable to load grpc proto file (' + error + ')') } } async function makeClient(grpcEndpoint) { try { const proto = await loadGrpcBaseProto(grpcEndpoint) - const validHash = await checkProtoHash(proto) - if (validHash) { - const client = await loadGrpcProto(proto, grpcEndpoint) - return client + if (proto) { + const validHash = await checkProtoHash(proto) + if (validHash) { + const client = await loadGrpcProto(proto, grpcEndpoint) + return client + } } return null } catch (error) { - throw new Error('Unable to make client (' + error + ')') + console.log('Unable to make client (' + error + ')') } } -async function validate(node) { - return dns.lookup(node) -} class QrlNode { constructor(ipAddress, port) { @@ -150,26 +136,26 @@ class QrlNode { this.client = null this.ipAddress = ipAddress this.port = port - validate(ipAddress).then((err, res) => { - if (err) { - return false - } - return true - }).catch(error => { - console.log(error) - }) } - async connect() { - return new Promise(async (resolve, reject) => { - if (this.connection === false) { - const client = await makeClient(`${this.ipAddress}:${this.port}`) - this.connection = true - this.client = client - resolve(client) - } - reject('Already connected... disconnect first or create a new connection') - }) + connect() { + try { + return new Promise(async (resolve, reject) => { + if (this.connection === false) { + const client = await makeClient(`${this.ipAddress}:${this.port}`) + if (client === null) { + this.connection = false + } else { + this.connection = true + } + this.client = client + resolve(client) + } + reject('Already connected... disconnect first or create a new connection') + }) + } catch (error) { + console.log(error) + } } disconnect() { @@ -178,8 +164,8 @@ class QrlNode { } async validApi(apiCall) { - const client = await this.client try { + const client = await this.client if (client[apiCall].path.substr(0, 5) === '/qrl.') { return true } @@ -189,20 +175,21 @@ class QrlNode { } } - api(apiCall, request = {}) { - return new Promise(async (resolve, reject) => { - const client = await this.client - client[apiCall](request, async (error, response) => { - if (error) { - reject(error) - } - resolve(response) + async api(apiCall, request = {}) { + try { + return new Promise(async (resolve, reject) => { + const client = await this.client + client[apiCall](request, async (error, response) => { + if (error) { + reject(error) + } + resolve(response) + }) }) - }).catch(error => { - throw new Error('Unable to make API call (' + error + ')') - }) + } catch (error) { + console.log('Unable to make API call (' + error + ')') + } } - } module.exports = QrlNode \ No newline at end of file diff --git a/test/test.js b/test/test.js index e118a0e..855579e 100644 --- a/test/test.js +++ b/test/test.js @@ -8,10 +8,10 @@ var assert = chai.assert var ip = 'mainnet-1.automated.theqrl.org' var port = '19009' -process.on('unhandledRejection', error => { +// process.on('unhandledRejection', error => { // uncomment to review unhandled Promise rejections to debug // console.log('unhandledRejection', error.message) -}) +// }) describe('#mainnet', function() { var mainnet = new QrlNode(ip, port) @@ -36,9 +36,8 @@ describe('#mainnet', function() { it('mainnet node should report SYNCED', async function() { async function node() { return new Promise(async (resolve, reject) => { - let id = null const client = await mainnet.connect() - client.GetStats({}, async (error, response) => { + return await client.GetStats({}, async (error, response) => { if (error) { throw new Error(error) } @@ -46,7 +45,7 @@ describe('#mainnet', function() { }) }) } - await expect(node()).to.eventually.equal('SYNCED') + await expect(await node()).to.equal('SYNCED') }) it('expect GetOTS to function if called from existing client connection', async function() { @@ -74,21 +73,20 @@ describe('#mainnet', function() { await expect(node()).to.eventually.be.rejected }) - it('an invalid node ip/port should throw an error', async function() { + it('an invalid node ip/port should result in a null connecion', async function() { async function node() { const badip = 'bad-ip.automated.theqrl.org' const badport = '19009' let id = null var testnet = new QrlNode(badip, badport) - // console.log(testnet) try { var client = await testnet.connect() } catch (error) { - console.log('er:', error) + // consolse.log('er:', error) } - console.log(testnet.connection) + return testnet.connection } - await expect(node()).to.eventually.throw + await expect(node()).to.eventually.equal(false) }) it('testnet node should have \'The Random Genesis\' as its network_id', async function() {