From bb1bac5adaaa64a0b52c33d4224a2ba63d258608 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Sun, 16 Feb 2020 06:38:25 -0800 Subject: [PATCH] fix(linting): Switching to standard linter. Fixed linting errors --- .eslintrc.json | 56 +- package-lock.json | 1448 ++++++++++++++++---- package.json | 5 +- src/app.js | 123 +- src/middleware/auth.js | 42 +- src/middleware/jwt-auth.js | 8 +- src/middleware/route-ratelimit.js | 121 +- src/routes/v3/blockbook.js | 150 +- src/routes/v3/full-node/blockchain.js | 272 ++-- src/routes/v3/full-node/control.js | 37 +- src/routes/v3/full-node/mining.js | 76 +- src/routes/v3/full-node/network.js | 8 +- src/routes/v3/full-node/rawtransactions.js | 238 ++-- src/routes/v3/health-check.js | 6 +- src/routes/v3/ninsight.js | 26 +- src/routes/v3/route-utils.js | 62 +- src/routes/v3/route-utils2.js | 62 +- src/routes/v3/slp.js | 589 ++++---- src/routes/v3/util.js | 181 +-- src/routes/v3/xpub.js | 38 +- src/util/blockbook-path.js | 22 +- src/util/winston-logging.js | 18 +- test/v3/blockbook.js | 616 ++++----- test/v3/blockchain.js | 1072 +++++++-------- test/v3/control.js | 84 +- test/v3/e2e/address.js | 24 +- test/v3/helpers/panda.js | 6 +- test/v3/integration/rate-limits.js | 76 +- test/v3/integration/raw-transactions.js | 112 +- test/v3/mining.js | 98 +- test/v3/mocks/address-mock.js | 66 +- test/v3/mocks/bitcore-mock.js | 16 +- test/v3/mocks/block-mock.js | 26 +- test/v3/mocks/blockbook-mock.js | 50 +- test/v3/mocks/blockchain-mock.js | 210 +-- test/v3/mocks/control-mock.js | 10 +- test/v3/mocks/express-mocks.js | 15 +- test/v3/mocks/mining-mocks.js | 4 +- test/v3/mocks/raw-transactions-mocks.js | 86 +- test/v3/mocks/slp-mocks.js | 198 +-- test/v3/mocks/slpjs-mocks.js | 30 +- test/v3/mocks/transaction-mocks.js | 14 +- test/v3/mocks/util-mocks.js | 76 +- test/v3/rate-limits.js | 445 +++--- test/v3/raw-transactions.js | 584 ++++---- test/v3/slp.js | 373 +++-- test/v3/util.js | 314 ++--- test/v3/xpub.js | 56 +- 48 files changed, 4547 insertions(+), 3702 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index c2c30f5..1cb87bd 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,54 +1,10 @@ { - "root": true, - "parserOptions": { - "ecmaVersion": 2018 + "extends": "standard", + "env": { + "node": true, + "mocha": true }, - "plugins": ["prettier"], - "rules": { - "no-debugger": ["warn"], - "no-regex-spaces": ["error"], - "no-unsafe-negation": ["error"], - "curly": ["error", "multi-or-nest", "consistent"], - "dot-location": ["error", "property"], - "dot-notation": ["error"], - "eqeqeq": ["error", "smart"], - "no-else-return": ["error"], - "no-extra-bind": ["error"], - "no-extra-label": ["error"], - "no-floating-decimal": ["error"], - "no-implicit-coercion": ["error", { "allow": ["!!"] }], - "no-lonely-if": ["off"], - "wrap-iife": ["error", "inside"], - "strict": ["error", "global"], - "func-call-spacing": ["error", "never"], - "comma-style": ["error", "last"], - "keyword-spacing": ["error"], - "linebreak-style": ["error", "unix"], - "new-parens": ["error"], - "no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1 }], - "no-whitespace-before-property": ["error"], - "semi": ["error", "never"], - "arrow-body-style": ["error", "as-needed"], - "arrow-parens": ["error", "as-needed"], - "arrow-spacing": ["error"], - "no-useless-computed-key": ["error"], - "no-useless-rename": ["error"], - "no-var": ["off"], - "prefer-spread": ["error"], - "prefer-template": ["error"], - "rest-spread-spacing": ["error", "never"], - "prefer-const": ["warn", { "destructuring": "all" }], - "no-unreachable": ["warn"], - "no-unused-vars": ["off"], - - "prettier/prettier": [ - "warn", - { - "printWidth": 80, - "trailingComma": "none", - "singleQuote": false, - "semi": false - } - ] + "parserOptions": { + "ecmaVersion": 10 } } diff --git a/package-lock.json b/package-lock.json index dd3088f..595328d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -833,24 +833,16 @@ } }, "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true }, "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "requires": { - "acorn": "^3.0.4" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" - } - } + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true }, "after": { "version": "0.8.2", @@ -883,14 +875,15 @@ } }, "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "dev": true, "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, "ajv-keywords": { @@ -1134,12 +1127,84 @@ "dev": true }, "array-includes": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", - "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.7.0" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==" + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "requires": { + "has": "^1.0.3" + } + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + } } }, "array-union": { @@ -1571,6 +1636,496 @@ "nyc": "*", "standard": "^11.0.1", "tape": "*" + }, + "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "deglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.1.tgz", + "integrity": "sha512-2kjwuGGonL7gWE1XU4Fv79+vVzpoQCl0V+boMwWtOQJV2AGDabCwez++nB1Nli/8BabAfZQ/UuHPlp6AymKdWw==", + "requires": { + "find-root": "^1.0.0", + "glob": "^7.0.5", + "ignore": "^3.0.9", + "pkg-config": "^1.1.0", + "run-parallel": "^1.1.2", + "uniq": "^1.0.1" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "^2.0.2" + } + }, + "eslint": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.18.2.tgz", + "integrity": "sha512-qy4i3wODqKMYfz9LUI8N2qYDkHkoieTbiHpMrYUI/WbjhXJQr7lI4VngixTgaG+yHX+NBCv7nW4hA0ShbvaNKw==", + "requires": { + "ajv": "^5.3.0", + "babel-code-frame": "^6.22.0", + "chalk": "^2.1.0", + "concat-stream": "^1.6.0", + "cross-spawn": "^5.1.0", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.2", + "esquery": "^1.0.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.0.1", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^3.0.6", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.9.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "require-uncached": "^1.0.3", + "semver": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "~2.0.1", + "table": "4.0.2", + "text-table": "~0.2.0" + } + }, + "eslint-config-standard": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz", + "integrity": "sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw==" + }, + "eslint-config-standard-jsx": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-5.0.0.tgz", + "integrity": "sha512-rLToPAEqLMPBfWnYTu6xRhm2OWziS2n40QFqJ8jAM8NSVzeVKTa3nclhsU4DpPJQRY60F34Oo1wi/71PN/eITg==" + }, + "eslint-plugin-import": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.9.0.tgz", + "integrity": "sha1-JgAu+/ylmJtyiKwEdQi9JPIXsWk=", + "requires": { + "builtin-modules": "^1.1.1", + "contains-path": "^0.1.0", + "debug": "^2.6.8", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.1", + "eslint-module-utils": "^2.1.1", + "has": "^1.0.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.3", + "read-pkg-up": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "eslint-plugin-node": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz", + "integrity": "sha512-Q/Cc2sW1OAISDS+Ji6lZS2KV4b7ueA/WydVWd1BECTQwVvfQy5JAi3glhINoKzoMnfnuRgNP+ZWKrGAbp3QDxw==", + "requires": { + "ignore": "^3.3.6", + "minimatch": "^3.0.4", + "resolve": "^1.3.3", + "semver": "^5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "eslint-plugin-promise": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.7.0.tgz", + "integrity": "sha512-2WO+ZFh7vxUKRfR0cOIMrWgYKdR6S1AlOezw6pC52B6oYpd5WFghN+QHxvrRdZMtbo8h3dfUZ2o1rWb0UPbKtg==" + }, + "eslint-plugin-react": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.7.0.tgz", + "integrity": "sha512-KC7Snr4YsWZD5flu6A5c0AcIZidzW3Exbqp7OT67OaD2AppJtlBr/GuPrW/vaQM/yfZotEvKAdrxrO+v8vwYJA==", + "requires": { + "doctrine": "^2.0.2", + "has": "^1.0.1", + "jsx-ast-utils": "^2.0.1", + "prop-types": "^15.6.0" + } + }, + "eslint-plugin-standard": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", + "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=" + }, + "eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "requires": { + "glob": "^7.1.3" + } + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "requires": { + "is-fullwidth-code-point": "^2.0.0" + } + }, + "standard": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/standard/-/standard-11.0.1.tgz", + "integrity": "sha512-nu0jAcHiSc8H+gJCXeiziMVZNDYi8MuqrYJKxTgjP4xKXZMKm311boqQIzDrYI/ktosltxt2CbDjYQs9ANC8IA==", + "requires": { + "eslint": "~4.18.0", + "eslint-config-standard": "11.0.0", + "eslint-config-standard-jsx": "5.0.0", + "eslint-plugin-import": "~2.9.0", + "eslint-plugin-node": "~6.0.0", + "eslint-plugin-promise": "~3.7.0", + "eslint-plugin-react": "~7.7.0", + "eslint-plugin-standard": "~3.0.1", + "standard-engine": "~8.0.0" + } + }, + "standard-engine": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-8.0.1.tgz", + "integrity": "sha512-LA531C3+nljom/XRvdW/hGPXwmilRkaRkENhO3FAGF1Vtq/WtCXzgmnc5S6vUHHsgv534MRy02C1ikMwZXC+tw==", + "requires": { + "deglob": "^2.1.0", + "get-stdin": "^6.0.0", + "minimist": "^1.1.0", + "pkg-conf": "^2.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "requires": { + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + } + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "requires": { + "mkdirp": "^0.5.1" + } + } } }, "bip38": { @@ -2119,9 +2674,10 @@ } }, "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true }, "check-error": { "version": "1.0.2", @@ -3060,16 +3616,25 @@ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" }, "deglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.1.tgz", - "integrity": "sha512-2kjwuGGonL7gWE1XU4Fv79+vVzpoQCl0V+boMwWtOQJV2AGDabCwez++nB1Nli/8BabAfZQ/UuHPlp6AymKdWw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/deglob/-/deglob-4.0.1.tgz", + "integrity": "sha512-/g+RDZ7yf2HvoW+E5Cy+K94YhgcFgr6C8LuHZD1O5HoNPkf3KY6RfXJ0DBGlB/NkLi5gml+G9zqRzk9S0mHZCg==", + "dev": true, "requires": { "find-root": "^1.0.0", "glob": "^7.0.5", - "ignore": "^3.0.9", + "ignore": "^5.0.0", "pkg-config": "^1.1.0", "run-parallel": "^1.1.2", "uniq": "^1.0.1" + }, + "dependencies": { + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + } } }, "delayed-stream": { @@ -3142,9 +3707,10 @@ "integrity": "sha512-hvSnros73+qyZXhHFjx2CMLwoj3Fe7eR9EJsFsqmcI1bB2OBWL/+0YzaEaKssCHnj/6crawNnUyw74Gm2EKe+Q==" }, "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, "requires": { "esutils": "^2.0.2" } @@ -3955,17 +4521,18 @@ "dev": true }, "eslint-config-standard-jsx": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-5.0.0.tgz", - "integrity": "sha512-rLToPAEqLMPBfWnYTu6xRhm2OWziS2n40QFqJ8jAM8NSVzeVKTa3nclhsU4DpPJQRY60F34Oo1wi/71PN/eITg==" + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-8.1.0.tgz", + "integrity": "sha512-ULVC8qH8qCqbU792ZOO6DaiaZyHNS/5CZt3hKqHkEhVlhPEPN3nfBqqxJCyp59XrjIBZPu1chMYe9T2DXZ7TMw==", + "dev": true }, "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz", + "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==", "requires": { "debug": "^2.6.9", - "resolve": "^1.5.0" + "resolve": "^1.13.1" }, "dependencies": { "debug": { @@ -3980,15 +4547,23 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "requires": { + "path-parse": "^1.0.6" + } } } }, "eslint-module-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", - "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz", + "integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==", "requires": { - "debug": "^2.6.8", + "debug": "^2.6.9", "pkg-dir": "^2.0.0" }, "dependencies": { @@ -4053,27 +4628,48 @@ } } }, - "eslint-plugin-import": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.9.0.tgz", - "integrity": "sha1-JgAu+/ylmJtyiKwEdQi9JPIXsWk=", + "eslint-plugin-es": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-2.0.0.tgz", + "integrity": "sha512-f6fceVtg27BR02EYnBhgWLFQfK6bN4Ll0nQFrBHOlCsAyxeZkn0NHns5O0YZOPrV1B3ramd6cgFwaoFLcSkwEQ==", + "dev": true, "requires": { - "builtin-modules": "^1.1.1", + "eslint-utils": "^1.4.2", + "regexpp": "^3.0.0" + }, + "dependencies": { + "regexpp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", + "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.18.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", + "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", "contains-path": "^0.1.0", - "debug": "^2.6.8", + "debug": "^2.6.9", "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.1", - "eslint-module-utils": "^2.1.1", - "has": "^1.0.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.3", - "read-pkg-up": "^2.0.0" + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.11.0" }, "dependencies": { "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { "ms": "2.0.0" } @@ -4082,6 +4678,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, "requires": { "esutils": "^2.0.2", "isarray": "^1.0.0" @@ -4091,6 +4688,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, "requires": { "locate-path": "^2.0.0" } @@ -4099,6 +4697,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", @@ -4110,6 +4709,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -4118,12 +4718,14 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, "requires": { "p-try": "^1.0.0" } @@ -4132,6 +4734,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, "requires": { "p-limit": "^1.1.0" } @@ -4139,12 +4742,14 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, "requires": { "error-ex": "^1.2.0" } @@ -4153,6 +4758,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, "requires": { "pify": "^2.0.0" } @@ -4160,12 +4766,14 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, "requires": { "load-json-file": "^2.0.0", "normalize-package-data": "^2.3.2", @@ -4176,6 +4784,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, "requires": { "find-up": "^2.0.0", "read-pkg": "^2.0.0" @@ -4184,20 +4793,30 @@ } }, "eslint-plugin-node": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-6.0.1.tgz", - "integrity": "sha512-Q/Cc2sW1OAISDS+Ji6lZS2KV4b7ueA/WydVWd1BECTQwVvfQy5JAi3glhINoKzoMnfnuRgNP+ZWKrGAbp3QDxw==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-10.0.0.tgz", + "integrity": "sha512-1CSyM/QCjs6PXaT18+zuAXsjXGIGo5Rw630rSKwokSs2jrYURQc4R5JZpoanNCqwNmepg+0eZ9L7YiRUJb8jiQ==", + "dev": true, "requires": { - "ignore": "^3.3.6", + "eslint-plugin-es": "^2.0.0", + "eslint-utils": "^1.4.2", + "ignore": "^5.1.1", "minimatch": "^3.0.4", - "resolve": "^1.3.3", - "semver": "^5.4.1" + "resolve": "^1.10.1", + "semver": "^6.1.0" }, "dependencies": { + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, @@ -4211,19 +4830,37 @@ } }, "eslint-plugin-promise": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.7.0.tgz", - "integrity": "sha512-2WO+ZFh7vxUKRfR0cOIMrWgYKdR6S1AlOezw6pC52B6oYpd5WFghN+QHxvrRdZMtbo8h3dfUZ2o1rWb0UPbKtg==" + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", + "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "dev": true }, "eslint-plugin-react": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.7.0.tgz", - "integrity": "sha512-KC7Snr4YsWZD5flu6A5c0AcIZidzW3Exbqp7OT67OaD2AppJtlBr/GuPrW/vaQM/yfZotEvKAdrxrO+v8vwYJA==", + "version": "7.14.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.14.3.tgz", + "integrity": "sha512-EzdyyBWC4Uz2hPYBiEJrKCUi2Fn+BJ9B/pJQcjw5X+x/H2Nm59S4MJIvL4O5NEE0+WbnQwEBxWY03oUk+Bc3FA==", + "dev": true, "requires": { - "doctrine": "^2.0.2", - "has": "^1.0.1", - "jsx-ast-utils": "^2.0.1", - "prop-types": "^15.6.0" + "array-includes": "^3.0.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.1.0", + "object.entries": "^1.1.0", + "object.fromentries": "^2.0.0", + "object.values": "^1.1.0", + "prop-types": "^15.7.2", + "resolve": "^1.10.1" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + } } }, "eslint-plugin-standard": { @@ -4233,9 +4870,10 @@ "dev": true }, "eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" @@ -4256,12 +4894,14 @@ "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==" }, "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "dev": true, "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" } }, "esprima": { @@ -4521,12 +5161,13 @@ } }, "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", "tmp": "^0.0.33" } }, @@ -4602,9 +5243,10 @@ "dev": true }, "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true }, "fast-diff": { "version": "1.2.0", @@ -4693,12 +5335,12 @@ } }, "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" + "flat-cache": "^2.0.1" } }, "file-stream-rotator": { @@ -4817,20 +5459,21 @@ } }, "flat-cache": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" }, "dependencies": { "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, "requires": { "glob": "^7.1.3" } @@ -5604,9 +6247,10 @@ "integrity": "sha512-MFs36e/ca6ohEKtinTJ5VvAJ6oDRAYFdYXweUnGY9L9vcoqFOU4n2ZhmJ0C4z/cwGZ3YIQRSB3XZ1+ghZkY5NQ==" }, "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true }, "ignore-by-default": { "version": "1.0.1", @@ -5686,46 +6330,51 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", - "external-editor": "^2.0.4", + "external-editor": "^3.0.3", "figures": "^2.0.0", - "lodash": "^4.3.0", + "lodash": "^4.17.12", "mute-stream": "0.0.7", "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", + "rxjs": "^6.4.0", "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", + "strip-ansi": "^5.1.0", "through": "^2.3.6" }, "dependencies": { "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } } } } @@ -6039,6 +6688,11 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==" + }, "is-symbol": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", @@ -6266,9 +6920,10 @@ "dev": true }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -11420,6 +12075,97 @@ "has": "^1.0.3" } }, + "object.fromentries": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", + "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + } + } + }, "object.getownpropertydescriptors": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", @@ -11509,6 +12255,97 @@ "isobject": "^3.0.1" } }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + } + } + }, "octokit-pagination-methods": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz", @@ -12353,9 +13190,9 @@ } }, "react-is": { - "version": "16.11.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.11.0.tgz", - "integrity": "sha512-gbBVYR2p8mnriqAwWx9LbuUrShnAuSCNnuPGyc7GJrMVQtPDAh8iLpv7FRuMPFb56KkaVZIYSz1PrjI9q0QPCw==" + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", + "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==" }, "read-pkg": { "version": "3.0.0", @@ -13330,10 +14167,13 @@ "dev": true }, "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", "is-fullwidth-code-point": "^2.0.0" } }, @@ -13687,120 +14527,138 @@ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" }, "standard": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/standard/-/standard-11.0.1.tgz", - "integrity": "sha512-nu0jAcHiSc8H+gJCXeiziMVZNDYi8MuqrYJKxTgjP4xKXZMKm311boqQIzDrYI/ktosltxt2CbDjYQs9ANC8IA==", + "version": "14.3.1", + "resolved": "https://registry.npmjs.org/standard/-/standard-14.3.1.tgz", + "integrity": "sha512-TUQwU7znlZLfgKH1Zwn/D84FitWZkUTfbxSiz/vFx+4c9GV+clSfG/qLiLZOlcdyzhw3oF5/pZydNjbNDfHPEw==", + "dev": true, "requires": { - "eslint": "~4.18.0", - "eslint-config-standard": "11.0.0", - "eslint-config-standard-jsx": "5.0.0", - "eslint-plugin-import": "~2.9.0", - "eslint-plugin-node": "~6.0.0", - "eslint-plugin-promise": "~3.7.0", - "eslint-plugin-react": "~7.7.0", - "eslint-plugin-standard": "~3.0.1", - "standard-engine": "~8.0.0" + "eslint": "~6.4.0", + "eslint-config-standard": "14.1.0", + "eslint-config-standard-jsx": "8.1.0", + "eslint-plugin-import": "~2.18.0", + "eslint-plugin-node": "~10.0.0", + "eslint-plugin-promise": "~4.2.1", + "eslint-plugin-react": "~7.14.2", + "eslint-plugin-standard": "~4.0.0", + "standard-engine": "^12.0.0" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, "requires": { - "lru-cache": "^4.0.1", + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - }, - "eslint": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.18.2.tgz", - "integrity": "sha512-qy4i3wODqKMYfz9LUI8N2qYDkHkoieTbiHpMrYUI/WbjhXJQr7lI4VngixTgaG+yHX+NBCv7nW4hA0ShbvaNKw==", - "requires": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", - "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^3.7.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.2", - "esquery": "^1.0.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", - "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", - "progress": "^2.0.0", - "require-uncached": "^1.0.3", - "semver": "^5.3.0", - "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", - "table": "4.0.2", - "text-table": "~0.2.0" }, "dependencies": { - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true } } }, - "eslint-config-standard": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-11.0.0.tgz", - "integrity": "sha512-oDdENzpViEe5fwuRCWla7AXQd++/oyIp8zP+iP9jiUPG6NBj3SHgdgtl/kTn00AjeN+1HNvavTKmYbMo+xMOlw==" + "eslint": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.4.0.tgz", + "integrity": "sha512-WTVEzK3lSFoXUovDHEbkJqCVPEPwbhCq4trDktNI6ygs7aO41d4cDT0JFAT5MivzZeVLWlg7vHL+bgrQv/t3vA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.2", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.4.1", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + } }, - "eslint-plugin-standard": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz", - "integrity": "sha1-NNDJFbRe3G8BA5PH7vOCOwhWXPI=" + "eslint-config-standard": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-14.1.0.tgz", + "integrity": "sha512-EF6XkrrGVbvv8hL/kYa/m6vnvmUT+K82pJJc4JJVMM6+Qgqh0pnwprSxdduDLB9p/7bIxD+YV5O0wfb8lmcPbA==", + "dev": true + }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } }, "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "minimist": "0.0.8" } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true } } }, @@ -13810,20 +14668,63 @@ "integrity": "sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg==" }, "standard-engine": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-8.0.1.tgz", - "integrity": "sha512-LA531C3+nljom/XRvdW/hGPXwmilRkaRkENhO3FAGF1Vtq/WtCXzgmnc5S6vUHHsgv534MRy02C1ikMwZXC+tw==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-12.0.0.tgz", + "integrity": "sha512-gJIIRb0LpL7AHyGbN9+hJ4UJns37lxmNTnMGRLC8CFrzQ+oB/K60IQjKNgPBCB2VP60Ypm6f8DFXvhVWdBOO+g==", + "dev": true, "requires": { - "deglob": "^2.1.0", - "get-stdin": "^6.0.0", + "deglob": "^4.0.0", + "get-stdin": "^7.0.0", "minimist": "^1.1.0", - "pkg-conf": "^2.0.0" + "pkg-conf": "^3.1.0" }, "dependencies": { + "get-stdin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", + "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", + "dev": true + }, + "load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + } + }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pkg-conf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", + "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "load-json-file": "^5.2.0" + } + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true } } }, @@ -13906,11 +14807,6 @@ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" }, - "strftime": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/strftime/-/strftime-0.10.0.tgz", - "integrity": "sha1-s/D6QZKVICpaKJ9ta+n0kJphcZM=" - }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -14019,40 +14915,15 @@ } }, "table": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - } - } + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" } }, "tape": { @@ -14661,6 +15532,12 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -14988,9 +15865,10 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, "requires": { "mkdirp": "^0.5.1" }, @@ -14998,12 +15876,14 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, "requires": { "minimist": "0.0.8" } diff --git a/package.json b/package.json index 9aa4a60..d49dae3 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "start": "node ./src/app.js", "dev": "nodemon ./dist/app.js", "test": "npm run test-v3", + "lint": "standard --env mocha --fix", "test-v3": "export NETWORK=mainnet && nyc --reporter=text mocha --timeout 25000 test/v3/", "test:temp": "export NETWORK=mainnet && mocha --timeout 25000 test/v3/blockchain.js", "test:integration": "mocha test/v3/integration", @@ -48,7 +49,6 @@ "pg": "^7.11.0", "pg-hstore": "^2.3.2", "rate-limiter-flexible": "^2.0.0", - "strftime": "^0.10.0", "winston": "^3.2.1", "winston-daily-rotate-file": "^4.0.0" }, @@ -69,8 +69,9 @@ "proxyquire": "^2.1.0", "request": "^2.88.0", "request-promise": "^4.2.2", - "sinon": "^8.0.0", "semantic-release": "^17.0.0", + "sinon": "^8.0.0", + "standard": "^14.3.1", "typescript": "^3.1.4" }, "release": { diff --git a/src/app.js b/src/app.js index 3e7fad5..b96df5b 100644 --- a/src/app.js +++ b/src/app.js @@ -1,41 +1,41 @@ -"use strict" +'use strict' -const express = require("express") +const express = require('express') // Middleware // const { routeRateLimit } = require("./middleware/route-ratelimit") -const RateLimits = require("./middleware/route-ratelimit") +const RateLimits = require('./middleware/route-ratelimit') const rateLimits = new RateLimits() -const path = require("path") -const logger = require("morgan") -const wlogger = require("./util/winston-logging") -const cookieParser = require("cookie-parser") -const bodyParser = require("body-parser") -const basicAuth = require("express-basic-auth") -const helmet = require("helmet") -const debug = require("debug")("rest-cloud:server") -const http = require("http") -const cors = require("cors") +const path = require('path') +const logger = require('morgan') +const wlogger = require('./util/winston-logging') +const cookieParser = require('cookie-parser') +const bodyParser = require('body-parser') +// const basicAuth = require("express-basic-auth") +const helmet = require('helmet') +const debug = require('debug')('rest-cloud:server') +const http = require('http') +const cors = require('cors') // Auth and rate limiting middleware libraries. -const AuthMW = require("./middleware/auth") -const jwtAuth = require("./middleware/jwt-auth") +const AuthMW = require('./middleware/auth') +const jwtAuth = require('./middleware/jwt-auth') // v3 -const healthCheckV3 = require("./routes/v3/health-check") -const BlockchainV3 = require("./routes/v3/full-node/blockchain") -const controlV3 = require("./routes/v3/full-node/control") -const miningV3 = require("./routes/v3/full-node/mining") -const networkV3 = require("./routes/v3/full-node/network") -const rawtransactionsV3 = require("./routes/v3/full-node/rawtransactions") -const utilV3 = require("./routes/v3/util") -const slpV3 = require("./routes/v3/slp") -const xpubV3 = require("./routes/v3/xpub") -const blockbookV3 = require("./routes/v3/blockbook") -const Ninsight = require("./routes/v3/ninsight") +const healthCheckV3 = require('./routes/v3/health-check') +const BlockchainV3 = require('./routes/v3/full-node/blockchain') +const controlV3 = require('./routes/v3/full-node/control') +const miningV3 = require('./routes/v3/full-node/mining') +const networkV3 = require('./routes/v3/full-node/network') +const rawtransactionsV3 = require('./routes/v3/full-node/rawtransactions') +const utilV3 = require('./routes/v3/util') +const slpV3 = require('./routes/v3/slp') +const xpubV3 = require('./routes/v3/xpub') +const blockbookV3 = require('./routes/v3/blockbook') +const Ninsight = require('./routes/v3/ninsight') -require("dotenv").config() +require('dotenv').config() // Instantiate route libraries. const blockchainV3 = new BlockchainV3() @@ -44,28 +44,29 @@ const app = express() app.locals.env = process.env -//app.use(swStats.getMiddleware({ swaggerSpec: apiSpec })) +// app.use(swStats.getMiddleware({ swaggerSpec: apiSpec })) app.use(helmet()) app.use(cors()) -app.enable("trust proxy") +app.enable('trust proxy') // view engine setup -app.set("views", path.join(__dirname, "views")) -app.set("view engine", "jade") +app.set('views', path.join(__dirname, 'views')) +app.set('view engine', 'jade') // Mount the docs -app.use("/docs", express.static(`${__dirname}/../docs`)) +app.use('/docs', express.static(`${__dirname}/../docs`)) // Log each request to the console with IP addresses. // app.use(logger("dev")) -const morganFormat = `:remote-addr :remote-user :method :url :status :response-time ms - :res[content-length] :user-agent` +const morganFormat = + ':remote-addr :remote-user :method :url :status :response-time ms - :res[content-length] :user-agent' app.use(logger(morganFormat)) // Log the same data to the winston logs. const logStream = { - write: function(message, encoding) { + write: function (message, encoding) { wlogger.info(`request: ${message}`) } } @@ -74,10 +75,10 @@ app.use(logger(morganFormat, { stream: logStream })) app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ extended: false })) app.use(cookieParser()) -app.use(express.static(path.join(__dirname, "public"))) +app.use(express.static(path.join(__dirname, 'public'))) // const v2prefix = "v2" -const v3prefix = "v3" +const v3prefix = 'v3' // Inspect the header for a JWT token. app.use(`/${v3prefix}/`, jwtAuth.getTokenFromHeaders) @@ -92,24 +93,24 @@ app.use(`/${v3prefix}/`, auth.mw()) // app.use(`/${v3prefix}/`, rateLimits.routeRateLimit) app.use(`/${v3prefix}/`, rateLimits.rateLimitByResource) -app.use(`/${v3prefix}/` + `health-check`, healthCheckV3) -app.use(`/${v3prefix}/` + `blockchain`, blockchainV3.router) -app.use(`/${v3prefix}/` + `control`, controlV3.router) -app.use(`/${v3prefix}/` + `mining`, miningV3.router) -app.use(`/${v3prefix}/` + `network`, networkV3) -app.use(`/${v3prefix}/` + `rawtransactions`, rawtransactionsV3.router) -app.use(`/${v3prefix}/` + `util`, utilV3.router) -app.use(`/${v3prefix}/` + `slp`, slpV3.router) -app.use(`/${v3prefix}/` + `xpub`, xpubV3.router) -app.use(`/${v3prefix}/` + `blockbook`, blockbookV3.router) +app.use(`/${v3prefix}/` + 'health-check', healthCheckV3) +app.use(`/${v3prefix}/` + 'blockchain', blockchainV3.router) +app.use(`/${v3prefix}/` + 'control', controlV3.router) +app.use(`/${v3prefix}/` + 'mining', miningV3.router) +app.use(`/${v3prefix}/` + 'network', networkV3) +app.use(`/${v3prefix}/` + 'rawtransactions', rawtransactionsV3.router) +app.use(`/${v3prefix}/` + 'util', utilV3.router) +app.use(`/${v3prefix}/` + 'slp', slpV3.router) +app.use(`/${v3prefix}/` + 'xpub', xpubV3.router) +app.use(`/${v3prefix}/` + 'blockbook', blockbookV3.router) const ninsight = new Ninsight() -app.use(`/${v3prefix}/` + `ninsight`, ninsight.router) +app.use(`/${v3prefix}/` + 'ninsight', ninsight.router) // catch 404 and forward to error handler app.use((req, res, next) => { const err = { - message: "Not Found", + message: 'Not Found', status: 404 } @@ -122,7 +123,7 @@ app.use((err, req, res, next) => { // set locals, only providing error in development res.locals.message = err.message - res.locals.error = req.app.get("env") === "development" ? err : {} + res.locals.error = req.app.get('env') === 'development' ? err : {} // render the error page res.status(status) @@ -135,8 +136,8 @@ app.use((err, req, res, next) => { /** * Get port from environment and store in Express. */ -const port = normalizePort(process.env.PORT || "3000") -app.set("port", port) +const port = normalizePort(process.env.PORT || '3000') +app.set('port', port) console.log(`bch-api started on port ${port}`) /** @@ -149,8 +150,8 @@ const server = http.createServer(app) */ server.listen(port) -server.on("error", onError) -server.on("listening", onListening) +server.on('error', onError) +server.on('listening', onListening) // Set the time before a timeout error is generated. This impacts testing and // the handling of timeout errors. Is 10 seconds too agressive? @@ -160,7 +161,7 @@ server.setTimeout(30 * 1000) * Normalize a port into a number, string, or false. */ -function normalizePort(val) { +function normalizePort (val) { const port = parseInt(val, 10) if (isNaN(port)) { @@ -179,18 +180,18 @@ function normalizePort(val) { /** * Event listener for HTTP server "error" event. */ -function onError(error) { - if (error.syscall !== "listen") throw error +function onError (error) { + if (error.syscall !== 'listen') throw error - const bind = typeof port === "string" ? `Pipe ${port}` : `Port ${port}` + const bind = typeof port === 'string' ? `Pipe ${port}` : `Port ${port}` // handle specific listen errors with friendly messages switch (error.code) { - case "EACCES": + case 'EACCES': console.error(`${bind} requires elevated privileges`) process.exit(1) break - case "EADDRINUSE": + case 'EADDRINUSE': console.error(`${bind} is already in use`) process.exit(1) break @@ -203,9 +204,9 @@ function onError(error) { * Event listener for HTTP server "listening" event. */ -function onListening() { +function onListening () { const addr = server.address() - const bind = typeof addr === "string" ? `pipe ${addr}` : `port ${addr.port}` + const bind = typeof addr === 'string' ? `pipe ${addr}` : `port ${addr.port}` debug(`Listening on ${bind}`) } // diff --git a/src/middleware/auth.js b/src/middleware/auth.js index 77510ff..128e9ba 100644 --- a/src/middleware/auth.js +++ b/src/middleware/auth.js @@ -19,45 +19,45 @@ is set and passed to the route-ratelimits.ts middleware. */ -"use strict" +'use strict' -const passport = require("passport") -const BasicStrategy = require("passport-http").BasicStrategy -const AnonymousStrategy = require("passport-anonymous") -const wlogger = require("../util/winston-logging") +const passport = require('passport') +const BasicStrategy = require('passport-http').BasicStrategy +const AnonymousStrategy = require('passport-anonymous') +const wlogger = require('../util/winston-logging') // Used for debugging and iterrogating JS objects. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -let _this +// let _this // Set default rate limit value for testing -const PRO_PASSes = process.env.PRO_PASS ? process.env.PRO_PASS : "BITBOX" +const PRO_PASSES = process.env.PRO_PASS ? process.env.PRO_PASS : 'BITBOX' // Convert the pro-tier password string into an array split by ':'. -const PRO_PASS = PRO_PASSes.split(":") +const PRO_PASS = PRO_PASSES.split(':') -//wlogger.verbose(`PRO_PASS set to: ${PRO_PASS}`) +// wlogger.verbose(`PRO_PASS set to: ${PRO_PASS}`) // Auth Middleware class AuthMW { - constructor() { - _this = this + constructor () { + // _this = this // Initialize passport for 'anonymous' authentication. passport.use(new AnonymousStrategy()) // Initialize passport for 'basic' authentication. passport.use( - new BasicStrategy({ passReqToCallback: true }, function( + new BasicStrategy({ passReqToCallback: true }, function ( req, username, password, done ) { - //console.log(`req: ${util.inspect(req)}`) - //console.log(`username: ${username}`) - //console.log(`password: ${password}`) + // console.log(`req: ${util.inspect(req)}`) + // console.log(`username: ${username}`) + // console.log(`password: ${password}`) // Create the req.locals property if it does not yet exist. if (!req.locals) { @@ -72,8 +72,8 @@ class AuthMW { req.locals.proLimit = false // Evaluate the username and password and set the rate limit accordingly. - //if (username === "BITBOX" && password === PRO_PASS) { - if (username === "BITBOX") { + // if (username === "BITBOX" && password === PRO_PASS) { + if (username === 'BITBOX') { for (let i = 0; i < PRO_PASS.length; i++) { const thisPass = PRO_PASS[i] @@ -87,7 +87,7 @@ class AuthMW { } } - //console.log(`req.locals: ${util.inspect(req.locals)}`) + // console.log(`req.locals: ${util.inspect(req.locals)}`) return done(null, true) }) @@ -95,8 +95,8 @@ class AuthMW { } // Middleware called by the route. - mw() { - return passport.authenticate(["basic", "anonymous"], { + mw () { + return passport.authenticate(['basic', 'anonymous'], { session: false }) } diff --git a/src/middleware/jwt-auth.js b/src/middleware/jwt-auth.js index 27b90cd..180a743 100644 --- a/src/middleware/jwt-auth.js +++ b/src/middleware/jwt-auth.js @@ -5,7 +5,7 @@ If found, will populate req.locals.jwtToken with the JWT token. */ -"use strict" +'use strict' // This function searches the header for the a JWT token in the authorization header. // If one is found, this middleware passes the JWT token through the @@ -18,8 +18,8 @@ const getTokenFromHeaders = (req, res, next) => { const authStr = req.headers.authorization // If the header is proceeded by the word 'Token' - if (authStr.split(" ")[0] === "Token") { - const token = authStr.split(" ")[1] + if (authStr.split(' ')[0] === 'Token') { + const token = authStr.split(' ')[1] // console.log(`JWT found: ${token}`) @@ -36,7 +36,7 @@ const getTokenFromHeaders = (req, res, next) => { } } } catch (err) { - console.log(`Error in getTokenFromHeaders: `, err) + console.log('Error in getTokenFromHeaders: ', err) } next() diff --git a/src/middleware/route-ratelimit.js b/src/middleware/route-ratelimit.js index 1d71a6c..63978ee 100644 --- a/src/middleware/route-ratelimit.js +++ b/src/middleware/route-ratelimit.js @@ -1,28 +1,28 @@ -"use strict" +'use strict' -const express = require("express") -const RateLimit = require("express-rate-limit") -const axios = require("axios") +// const express = require('express') +const RateLimit = require('express-rate-limit') +const axios = require('axios') -const wlogger = require("../util/winston-logging") +const wlogger = require('../util/winston-logging') -const jwt = require("jsonwebtoken") -const KeyEncoder = require("key-encoder").default -const keyEncoder = new KeyEncoder("secp256k1") +const jwt = require('jsonwebtoken') +const KeyEncoder = require('key-encoder').default +const keyEncoder = new KeyEncoder('secp256k1') // Redis const redisOptions = { enableOfflineQueue: false, port: process.env.REDIS_PORT ? process.env.REDIS_PORT : 6379, - host: process.env.REDIS_HOST ? process.env.REDIS_HOST : "127.0.0.1" + host: process.env.REDIS_HOST ? process.env.REDIS_HOST : '127.0.0.1' } console.log(`redisOptions: ${JSON.stringify(redisOptions, null, 2)}`) -const Redis = require("ioredis") +const Redis = require('ioredis') const redisClient = new Redis(redisOptions) // Rate limiter middleware lib. -const { RateLimiterRedis } = require("rate-limiter-flexible") +const { RateLimiterRedis } = require('rate-limiter-flexible') const rateLimitOptions = { storeClient: redisClient, points: 100, // Number of points @@ -32,7 +32,7 @@ const rateLimitOptions = { // This hard-coded value is temporary. It will be swapped out with an environment // variable when moved to production. const publicKey = - "03e6c358092a459f7da9420de770eef3e16cf3c9c54a3d3d14ac2d7f0b82af4d7d" + '03e6c358092a459f7da9420de770eef3e16cf3c9c54a3d3d14ac2d7f0b82af4d7d' // Set max requests per minute const maxRequests = process.env.RATE_LIMIT_MAX_REQUESTS @@ -48,7 +48,7 @@ const uniqueRateLimits = {} let _this class RateLimits { - constructor() { + constructor () { _this = this this.jwt = jwt @@ -57,7 +57,7 @@ class RateLimits { // Used to disconnect from the Redis DB. // Called by unit tests so that node.js thread doesn't live forever. - closeRedis() { + closeRedis () { redisClient.disconnect() } @@ -79,7 +79,7 @@ class RateLimits { will be downgraded to 0 on-the-fly. Indexer endpoints will effectively be downgraded to the anonymous access tier. */ - async routeRateLimit(req, res, next) { + async routeRateLimit (req, res, next) { // Disable rate limiting if 0 passed from RATE_LIMIT_MAX_REQUESTS if (maxRequests === 0) return next() @@ -87,7 +87,7 @@ class RateLimits { if (!req.locals) { req.locals = { // default values - jwtToken: "", + jwtToken: '', proLimit: false, apiLevel: 0 } @@ -95,9 +95,9 @@ class RateLimits { // Warn if JWT_AUTH_SERVER env var is not set. const authServer = process.env.JWT_AUTH_SERVER - if (!authServer || authServer === "") { + if (!authServer || authServer === '') { console.warn( - "JWT_AUTH_SERVER env var is not set. JWT tokens not being evaluated." + 'JWT_AUTH_SERVER env var is not set. JWT tokens not being evaluated.' ) } else { // If a JWT token is passed in, validate it and enable pro-tier rate limits @@ -129,7 +129,7 @@ class RateLimits { } // Current route - const rateLimitTier = req.locals.proLimit ? "PRO" : "BASIC" + const rateLimitTier = req.locals.proLimit ? 'PRO' : 'BASIC' const path = req.baseUrl + req.path // Create a unique string as a route identifier. @@ -138,10 +138,10 @@ class RateLimits { req.method + req.locals.apiLevel + // Generates new rate limit when user upgrades JWT token. path - .split("/") + .split('/') .slice(0, 4) - .join("/") - //console.log(`route identifier: ${JSON.stringify(route, null, 2)}`) + .join('/') + // console.log(`route identifier: ${JSON.stringify(route, null, 2)}`) // console.log(`req.locals: ${JSON.stringify(req.locals, null, 2)}`) @@ -166,8 +166,8 @@ class RateLimits { windowMs: 60 * 1000, // 1 minute window delayMs: 0, // disable delaying - full speed until the max limit is reached max: PRO_RPM, // start blocking after this many requests per minute - handler: function(req, res) { - //console.log(`pro-tier rate-handler triggered.`) + handler: function (req, res) { + // console.log(`pro-tier rate-handler triggered.`) res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ @@ -188,8 +188,8 @@ class RateLimits { windowMs: 60 * 1000, // 1 minute window delayMs: 0, // disable delaying - full speed until the max limit is reached max: maxRequests, // start blocking after maxRequests - handler: function(req, res) { - //console.log(`freemium rate-handler triggered.`) + handler: function (req, res) { + // console.log(`freemium rate-handler triggered.`) res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ @@ -200,7 +200,7 @@ class RateLimits { } } - //console.log(`calling uniqueRateLimits() on this route: ${route}`) + // console.log(`calling uniqueRateLimits() on this route: ${route}`) // Call rate limit for this route uniqueRateLimits[route](req, res, next) @@ -212,7 +212,7 @@ class RateLimits { // It does fine-grane analysis on the data coming from the auth servers and // uses its output to adjust rate limits on-the-fly based on the users // permission level. - evalUserPermissioins(req, authData) { + evalUserPermissioins (req, authData) { // console.log(`authData: ${JSON.stringify(authData, null, 2)}`) // Return object with default values @@ -224,9 +224,9 @@ class RateLimits { // if apiLevel = 0 (free tier), then return the default values. if (retObj.apiLevel === 0) return retObj - const level20Routes = ["insight", "bitcore", "blockbook"] + const level20Routes = ['insight', 'bitcore', 'blockbook'] - const locals = req.locals + // const locals = req.locals // console.log(`locals: ${JSON.stringify(locals, null, 2)}`) const url = req.url // console.log(`url: ${JSON.stringify(url, null, 2)}`) @@ -249,7 +249,7 @@ class RateLimits { // This is the new rate limit function that uses the rate-limiter-flexible npm // library. It uses fine-grain rate limiting based on the resources being // consumed. - async rateLimitByResource(req, res, next) { + async rateLimitByResource (req, res, next) { try { let userId let decoded = {} @@ -258,7 +258,7 @@ class RateLimits { if (!req.locals) { req.locals = { // default values - jwtToken: "", + jwtToken: '', proLimit: false, apiLevel: 0 } @@ -267,10 +267,10 @@ class RateLimits { // Decode the JWT token if one exists. if (req.locals.jwtToken) { const jwtOptions = { - algorithms: ["ES256"] + algorithms: ['ES256'] } - const pemPublicKey = keyEncoder.encodePublic(publicKey, "raw", "pem") + const pemPublicKey = keyEncoder.encodePublic(publicKey, 'raw', 'pem') // Validate the JWT token. decoded = _this.jwt.verify( @@ -282,7 +282,7 @@ class RateLimits { userId = decoded.id } else { - wlogger.debug(`No JWT token found!`) + wlogger.debug('No JWT token found!') } // Code here for the rate limiter is adapted from this example: @@ -292,7 +292,7 @@ class RateLimits { const resource = _this.getResource(req.url) wlogger.debug(`resource: ${resource}`) - let key = userId ? userId : req.ip + let key = userId || req.ip // const pointsToConsume = userId ? 1 : 30 decoded.resource = resource @@ -316,7 +316,7 @@ class RateLimits { }) } } catch (err) { - wlogger.error(`Error in route-ratelimit.js/newRateLimit(): `, err) + wlogger.error('Error in route-ratelimit.js/newRateLimit(): ', err) // throw err } @@ -325,7 +325,7 @@ class RateLimits { // Calculates the points consumed, based on the jwt information and the route // requested. - calcPoints(jwtInfo) { + calcPoints (jwtInfo) { let retVal = 30 // By default, use anonymous tier. try { @@ -334,8 +334,8 @@ class RateLimits { const apiLevel = jwtInfo.apiLevel const resource = jwtInfo.resource - const level30Routes = ["insight", "bitcore", "blockbook"] - const level40Routes = ["slp"] + const level30Routes = ['insight', 'bitcore', 'blockbook'] + const level40Routes = ['slp'] wlogger.debug(`apiLevel: ${apiLevel}`) @@ -346,28 +346,25 @@ class RateLimits { if (apiLevel >= 40) retVal = 1 // else if (apiLevel >= 10) retVal = 10 else retVal = 10 - } - // Normal indexer routes - else if (level30Routes.includes(resource)) { + // Normal indexer routes + } else if (level30Routes.includes(resource)) { if (apiLevel >= 30) retVal = 1 else retVal = 10 - } - // Full node tier - else if (apiLevel >= 20) { + // Full node tier + } else if (apiLevel >= 20) { retVal = 1 - } - // Free tier, full node only. - else { + // Free tier, full node only. + } else { retVal = 10 } } return retVal } catch (err) { - wlogger.error(`Error in route-ratelimit.js/calcPoints()`) + wlogger.error('Error in route-ratelimit.js/calcPoints()') // throw err retVal = 30 } @@ -379,16 +376,16 @@ class RateLimits { // the user is requesting. // This was created as a function so that it can be unit tested. Not sure // what kind of variations will be seen in production. - getResource(url) { + getResource (url) { try { wlogger.debug(`url: ${JSON.stringify(url, null, 2)}`) - const splitUrl = url.split("/") + const splitUrl = url.split('/') const resource = splitUrl[1] return resource } catch (err) { - wlogger.error(`Error in getResource().`) + wlogger.error('Error in getResource().') throw err } } @@ -397,7 +394,7 @@ class RateLimits { // potentially be used by Bitcoin.com. // Rather than using apiLevel, the rateLimit is explicitly recorded in the // JWT token. - async rateLimitSimple(req, res, next) { + async rateLimitSimple (req, res, next) { try { let userId let decoded = {} @@ -406,7 +403,7 @@ class RateLimits { if (!req.locals) { req.locals = { // default values - jwtToken: "", + jwtToken: '', proLimit: false, rateLimit: 3 } @@ -415,10 +412,10 @@ class RateLimits { // Decode the JWT token if one exists. if (req.locals.jwtToken) { const jwtOptions = { - algorithms: ["ES256"] + algorithms: ['ES256'] } - const pemPublicKey = keyEncoder.encodePublic(publicKey, "raw", "pem") + const pemPublicKey = keyEncoder.encodePublic(publicKey, 'raw', 'pem') // Validate the JWT token. decoded = _this.jwt.verify( @@ -430,14 +427,14 @@ class RateLimits { userId = decoded.id } else { - wlogger.debug(`No JWT token found!`) + wlogger.debug('No JWT token found!') } // Code here for the rate limiter is adapted from this example: // https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#authorized-and-not-authorized-users try { // Key for Redis key/value pair. - const key = userId ? userId : req.ip + const key = userId || req.ip const pointsToConsume = _this.calcPoints2(decoded) @@ -454,7 +451,7 @@ class RateLimits { }) } } catch (err) { - wlogger.error(`Error in route-ratelimit.js/rateLimitSimple(): `, err) + wlogger.error('Error in route-ratelimit.js/rateLimitSimple(): ', err) // throw err } @@ -463,7 +460,7 @@ class RateLimits { // Calculates the points consumed, based on the explicit rateLimit defined // in the JWT token. - calcPoints2(jwtInfo) { + calcPoints2 (jwtInfo) { let retVal = 30 // By default, use anonymous tier. try { @@ -480,7 +477,7 @@ class RateLimits { retVal = points } } catch (err) { - wlogger.error(`Error in route-ratelimit.js/calcPoints2()`) + wlogger.error('Error in route-ratelimit.js/calcPoints2()') // throw err retVal = 30 } diff --git a/src/routes/v3/blockbook.js b/src/routes/v3/blockbook.js index a499fc5..cb4d15c 100644 --- a/src/routes/v3/blockbook.js +++ b/src/routes/v3/blockbook.js @@ -2,49 +2,49 @@ Blockbook API route */ -"use strict" +'use strict' -const express = require("express") -const axios = require("axios") -const routeUtils = require("./route-utils") -const wlogger = require("../../util/winston-logging") +const express = require('express') +const axios = require('axios') +const routeUtils = require('./route-utils') +const wlogger = require('../../util/winston-logging') // Library for easily switching the API paths to use different instances of // Blockbook. -const BlockbookPath = require("../../util/blockbook-path") +const BlockbookPath = require('../../util/blockbook-path') const BLOCKBOOKPATH = new BlockbookPath() // BLOCKBOOKPATH.toOpenBazaar() const router = express.Router() // Used for processing error messages before sending them to the user. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -const BCHJS = require("@chris.troutner/bch-js") +const BCHJS = require('@chris.troutner/bch-js') const bchjs = new BCHJS() -//const BLOCKBOOK_URL = process.env.BLOCKBOOK_URL +// const BLOCKBOOK_URL = process.env.BLOCKBOOK_URL // Connect the route endpoints to their handler functions. -router.get("/", root) -router.get("/balance/:address", balanceSingle) -router.post("/balance", balanceBulk) -router.get("/utxos/:address", utxosSingle) -router.post("/utxos", utxosBulk) -router.get("/tx/:txid", txSingle) -router.post("/tx", txBulk) +router.get('/', root) +router.get('/balance/:address', balanceSingle) +router.post('/balance', balanceBulk) +router.get('/utxos/:address', utxosSingle) +router.post('/utxos', utxosBulk) +router.get('/tx/:txid', txSingle) +router.post('/tx', txBulk) // Root API endpoint. Simply acknowledges that it exists. -function root(req, res, next) { - return res.json({ status: "address" }) +function root (req, res, next) { + return res.json({ status: 'address' }) } // Query the Blockbook Node API for a balance on a single BCH address. // Returns a Promise. -async function balanceFromBlockbook(thisAddress) { +async function balanceFromBlockbook (thisAddress) { try { - //console.log(`BLOCKBOOK_URL: ${BLOCKBOOK_URL}`) + // console.log(`BLOCKBOOK_URL: ${BLOCKBOOK_URL}`) // Convert the address to a cashaddr without a prefix. const addr = bchjs.Address.toCashAddress(thisAddress) @@ -55,12 +55,13 @@ async function balanceFromBlockbook(thisAddress) { // Query the Blockbook Node API. const axiosResponse = await axios.get(path) const retData = axiosResponse.data - //console.log(`retData: ${util.inspect(retData)}`) + // console.log(`retData: ${util.inspect(retData)}`) return retData } catch (err) { // Dev Note: Do not log error messages here. Throw them instead and let the // parent function handle it. + wlogger.debug('Error in blockbook.js/balanceFromBlockbook()') throw err } } @@ -77,31 +78,32 @@ async function balanceFromBlockbook(thisAddress) { * */ // GET handler for single balance -async function balanceSingle(req, res, next) { +async function balanceSingle (req, res, next) { try { const address = req.params.address - if (!address || address === "") { + if (!address || address === '') { res.status(400) - return res.json({ error: "address can not be empty" }) + return res.json({ error: 'address can not be empty' }) } // Reject if address is an array. if (Array.isArray(address)) { res.status(400) return res.json({ - error: "address can not be an array. Use POST for bulk upload." + error: 'address can not be an array. Use POST for bulk upload.' }) } wlogger.debug( - `Executing blockbook/balanceSingle with this address: `, + 'Executing blockbook/balanceSingle with this address: ', address ) // Ensure the input is a valid BCH address. try { - const legacyAddr = bchjs.Address.toLegacyAddress(address) + // const legacyAddr = bchjs.Address.toLegacyAddress(address) + bchjs.Address.toLegacyAddress(address) } catch (err) { res.status(400) return res.json({ @@ -114,7 +116,7 @@ async function balanceSingle(req, res, next) { if (!networkIsValid) { res.status(400) return res.json({ - error: `Invalid network. Trying to use a testnet address on mainnet, or vice versa.` + error: 'Invalid network. Trying to use a testnet address on mainnet, or vice versa.' }) } @@ -133,7 +135,7 @@ async function balanceSingle(req, res, next) { } // Write out error to error log. - wlogger.error(`Error in blockbook.js/balanceSingle().`, err) + wlogger.error('Error in blockbook.js/balanceSingle().', err) res.status(500) return res.json({ error: util.inspect(err) }) @@ -153,16 +155,16 @@ async function balanceSingle(req, res, next) { * */ // POST handler for bulk queries on address details -async function balanceBulk(req, res, next) { +async function balanceBulk (req, res, next) { try { let addresses = req.body.addresses - const currentPage = req.body.page ? parseInt(req.body.page, 10) : 0 + // const currentPage = req.body.page ? parseInt(req.body.page, 10) : 0 // Reject if addresses is not an array. if (!Array.isArray(addresses)) { res.status(400) return res.json({ - error: "addresses needs to be an array. Use GET for single address." + error: 'addresses needs to be an array. Use GET for single address.' }) } @@ -170,12 +172,12 @@ async function balanceBulk(req, res, next) { if (!routeUtils.validateArraySize(req, addresses)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: `Array too large.` + error: 'Array too large.' }) } wlogger.debug( - `Executing blockbook.js/balanceBulk with these addresses: `, + 'Executing blockbook.js/balanceBulk with these addresses: ', addresses ) @@ -206,7 +208,7 @@ async function balanceBulk(req, res, next) { // Loops through each address and creates an array of Promises, querying // Insight API in parallel. addresses = addresses.map(async (address, index) => - //console.log(`address: ${address}`) + // console.log(`address: ${address}`) balanceFromBlockbook(address) ) @@ -224,7 +226,7 @@ async function balanceBulk(req, res, next) { return res.json({ error: msg }) } - wlogger.error(`Error in blockbook.js/balanceBulk().`, err) + wlogger.error('Error in blockbook.js/balanceBulk().', err) res.status(500) return res.json({ error: util.inspect(err) }) @@ -233,9 +235,9 @@ async function balanceBulk(req, res, next) { // Query the Blockbook API for utxos associated with a BCH address. // Returns a Promise. -async function utxosFromBlockbook(thisAddress) { +async function utxosFromBlockbook (thisAddress) { try { - //console.log(`BLOCKBOOK_URL: ${BLOCKBOOK_URL}`) + // console.log(`BLOCKBOOK_URL: ${BLOCKBOOK_URL}`) // Convert the address to a cashaddr without a prefix. const addr = bchjs.Address.toCashAddress(thisAddress) @@ -249,13 +251,13 @@ async function utxosFromBlockbook(thisAddress) { // console.log(`retData: ${util.inspect(retData)}`) // Add the satoshis property to each UTXO. - for (let i = 0; i < retData.length; i++) - retData[i].satoshis = Number(retData[i].value) + for (let i = 0; i < retData.length; i++) { retData[i].satoshis = Number(retData[i].value) } return retData } catch (err) { // Dev Note: Do not log error messages here. Throw them instead and let the // parent function handle it. + wlogger.debug('Error in blockbook.js/utxosFromBlockbook()') throw err } } @@ -272,31 +274,32 @@ async function utxosFromBlockbook(thisAddress) { * */ // GET handler for single balance -async function utxosSingle(req, res, next) { +async function utxosSingle (req, res, next) { try { const address = req.params.address - if (!address || address === "") { + if (!address || address === '') { res.status(400) - return res.json({ error: "address can not be empty" }) + return res.json({ error: 'address can not be empty' }) } // Reject if address is an array. if (Array.isArray(address)) { res.status(400) return res.json({ - error: "address can not be an array. Use POST for bulk upload." + error: 'address can not be an array. Use POST for bulk upload.' }) } wlogger.debug( - `Executing blockbook/utxosSingle with this address: `, + 'Executing blockbook/utxosSingle with this address: ', address ) // Ensure the input is a valid BCH address. try { - const legacyAddr = bchjs.Address.toLegacyAddress(address) + // const legacyAddr = bchjs.Address.toLegacyAddress(address) + bchjs.Address.toLegacyAddress(address) } catch (err) { res.status(400) return res.json({ @@ -309,7 +312,7 @@ async function utxosSingle(req, res, next) { if (!networkIsValid) { res.status(400) return res.json({ - error: `Invalid network. Trying to use a testnet address on mainnet, or vice versa.` + error: 'Invalid network. Trying to use a testnet address on mainnet, or vice versa.' }) } @@ -328,7 +331,7 @@ async function utxosSingle(req, res, next) { } // Write out error to error log. - wlogger.error(`Error in blockbook.js/utxosSingle().`, err) + wlogger.error('Error in blockbook.js/utxosSingle().', err) res.status(500) return res.json({ error: util.inspect(err) }) @@ -348,16 +351,16 @@ async function utxosSingle(req, res, next) { * */ // POST handler for bulk queries on address utxos -async function utxosBulk(req, res, next) { +async function utxosBulk (req, res, next) { try { let addresses = req.body.addresses - const currentPage = req.body.page ? parseInt(req.body.page, 10) : 0 + // const currentPage = req.body.page ? parseInt(req.body.page, 10) : 0 // Reject if addresses is not an array. if (!Array.isArray(addresses)) { res.status(400) return res.json({ - error: "addresses needs to be an array. Use GET for single address." + error: 'addresses needs to be an array. Use GET for single address.' }) } @@ -365,12 +368,12 @@ async function utxosBulk(req, res, next) { if (!routeUtils.validateArraySize(req, addresses)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: `Array too large.` + error: 'Array too large.' }) } wlogger.debug( - `Executing blockbook.js/utxosBulk with these addresses: `, + 'Executing blockbook.js/utxosBulk with these addresses: ', addresses ) @@ -401,7 +404,7 @@ async function utxosBulk(req, res, next) { // Loops through each address and creates an array of Promises, querying // Insight API in parallel. addresses = addresses.map(async (address, index) => - //console.log(`address: ${address}`) + // console.log(`address: ${address}`) utxosFromBlockbook(address) ) @@ -419,7 +422,7 @@ async function utxosBulk(req, res, next) { return res.json({ error: msg }) } - wlogger.error(`Error in blockbook.js/utxosBulk().`, err) + wlogger.error('Error in blockbook.js/utxosBulk().', err) res.status(500) return res.json({ error: util.inspect(err) }) @@ -428,9 +431,9 @@ async function utxosBulk(req, res, next) { // Query the Blockbook Node API for transactions on a single TXID. // Returns a Promise. -async function transactionsFromBlockbook(txid) { +async function transactionsFromBlockbook (txid) { try { - //console.log(`BLOCKBOOK_URL: ${BLOCKBOOK_URL}`) + // console.log(`BLOCKBOOK_URL: ${BLOCKBOOK_URL}`) const path = `${BLOCKBOOKPATH.txPath}${txid}` // console.log(`path: ${path}`) @@ -438,12 +441,13 @@ async function transactionsFromBlockbook(txid) { // Query the Blockbook Node API. const axiosResponse = await axios.get(path) const retPromise = axiosResponse.data - //console.log(`retData: ${util.inspect(retData)}`) + // console.log(`retData: ${util.inspect(retData)}`) return retPromise } catch (err) { // Dev Note: Do not log error messages here. Throw them instead and let the // parent function handle it. + wlogger.debug('Error in blockbook.js/transactionsFromBlockbook()') throw err } } @@ -460,20 +464,20 @@ async function transactionsFromBlockbook(txid) { * */ // GET handler for single transaction details. -async function txSingle(req, res, next) { +async function txSingle (req, res, next) { try { const txid = req.params.txid - if (!txid || txid === "") { + if (!txid || txid === '') { res.status(400) - return res.json({ error: "txid can not be empty" }) + return res.json({ error: 'txid can not be empty' }) } // Reject if address is an array. if (Array.isArray(txid)) { res.status(400) return res.json({ - error: "txid can not be an array. Use POST for bulk upload." + error: 'txid can not be an array. Use POST for bulk upload.' }) } @@ -485,7 +489,7 @@ async function txSingle(req, res, next) { }) } - wlogger.debug(`Executing blockbook/txSingle with this txid: `, txid) + wlogger.debug('Executing blockbook/txSingle with this txid: ', txid) // Query the Blockbook Node API. const retData = await transactionsFromBlockbook(txid) @@ -502,7 +506,7 @@ async function txSingle(req, res, next) { } // Write out error to error log. - wlogger.error(`Error in blockbook.js/txSingle().`, err) + wlogger.error('Error in blockbook.js/txSingle().', err) res.status(500) return res.json({ error: util.inspect(err) }) @@ -522,16 +526,16 @@ async function txSingle(req, res, next) { * */ // POST handler for bulk queries on tx details -async function txBulk(req, res, next) { +async function txBulk (req, res, next) { try { let txids = req.body.txids - const currentPage = req.body.page ? parseInt(req.body.page, 10) : 0 + // const currentPage = req.body.page ? parseInt(req.body.page, 10) : 0 // Reject if txids is not an array. if (!Array.isArray(txids)) { res.status(400) return res.json({ - error: "txids need to be an array. Use GET for single address." + error: 'txids need to be an array. Use GET for single address.' }) } @@ -539,19 +543,19 @@ async function txBulk(req, res, next) { if (!routeUtils.validateArraySize(req, txids)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: `Array too large.` + error: 'Array too large.' }) } - wlogger.debug(`Executing blockbook.js/txBulk with these txids: `, txids) + wlogger.debug('Executing blockbook.js/txBulk with these txids: ', txids) // Validate each element in the txids array. for (let i = 0; i < txids.length; i++) { const thisTxid = txids[i] - if (!thisTxid || thisTxid === "") { + if (!thisTxid || thisTxid === '') { res.status(400) - return res.json({ error: "txid can not be empty" }) + return res.json({ error: 'txid can not be empty' }) } // TODO: Add regex comparison of txid to ensure it's valid. @@ -566,7 +570,7 @@ async function txBulk(req, res, next) { // Loops through each address and creates an array of Promises, querying // Insight API in parallel. txids = txids.map(async (txid, index) => - //console.log(`address: ${address}`) + // console.log(`address: ${address}`) transactionsFromBlockbook(txid) ) @@ -584,7 +588,7 @@ async function txBulk(req, res, next) { return res.json({ error: msg }) } - wlogger.error(`Error in blockbook.js/txBulk().`, err) + wlogger.error('Error in blockbook.js/txBulk().', err) res.status(500) return res.json({ error: util.inspect(err) }) diff --git a/src/routes/v3/full-node/blockchain.js b/src/routes/v3/full-node/blockchain.js index 8c34ff6..46678c0 100644 --- a/src/routes/v3/full-node/blockchain.js +++ b/src/routes/v3/full-node/blockchain.js @@ -2,28 +2,28 @@ A library for interacting with the Full Node */ -"use strict" +'use strict' -const express = require("express") +const express = require('express') const router = express.Router() -const axios = require("axios") -const wlogger = require("../../../util/winston-logging") +const axios = require('axios') +const wlogger = require('../../../util/winston-logging') -const RouteUtils = require("../route-utils2") +const RouteUtils = require('../route-utils2') const routeUtils = new RouteUtils() // Used to convert error messages to strings, to safely pass to users. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -const BCHJS = require("@chris.troutner/bch-js") +const BCHJS = require('@chris.troutner/bch-js') const bchjs = new BCHJS() let _this class Blockchain { - constructor() { + constructor () { _this = this this.bchjs = bchjs @@ -31,35 +31,35 @@ class Blockchain { this.routeUtils = routeUtils this.router = router - this.router.get("/", this.root) - this.router.get("/getBestBlockHash", this.getBestBlockHash) - this.router.get("/getBlockchainInfo", this.getBlockchainInfo) - this.router.get("/getBlockCount", this.getBlockCount) - this.router.get("/getBlockHeader/:hash", this.getBlockHeaderSingle) - this.router.post("/getBlockHeader", this.getBlockHeaderBulk) - this.router.get("/getChainTips", this.getChainTips) - this.router.get("/getDifficulty", this.getDifficulty) - this.router.get("/getMempoolEntry/:txid", this.getMempoolEntrySingle) - this.router.post("/getMempoolEntry", this.getMempoolEntryBulk) + this.router.get('/', this.root) + this.router.get('/getBestBlockHash', this.getBestBlockHash) + this.router.get('/getBlockchainInfo', this.getBlockchainInfo) + this.router.get('/getBlockCount', this.getBlockCount) + this.router.get('/getBlockHeader/:hash', this.getBlockHeaderSingle) + this.router.post('/getBlockHeader', this.getBlockHeaderBulk) + this.router.get('/getChainTips', this.getChainTips) + this.router.get('/getDifficulty', this.getDifficulty) + this.router.get('/getMempoolEntry/:txid', this.getMempoolEntrySingle) + this.router.post('/getMempoolEntry', this.getMempoolEntryBulk) this.router.get( - "/getMempoolAncestors/:txid", + '/getMempoolAncestors/:txid', this.getMempoolAncestorsSingle ) - this.router.get("/getMempoolInfo", this.getMempoolInfo) - this.router.get("/getRawMempool", this.getRawMempool) - this.router.get("/getTxOut/:txid/:n", this.getTxOut) - this.router.get("/getTxOutProof/:txid", this.getTxOutProofSingle) - this.router.post("/getTxOutProof", this.getTxOutProofBulk) - this.router.get("/verifyTxOutProof/:proof", this.verifyTxOutProofSingle) - this.router.post("/verifyTxOutProof", this.verifyTxOutProofBulk) + this.router.get('/getMempoolInfo', this.getMempoolInfo) + this.router.get('/getRawMempool', this.getRawMempool) + this.router.get('/getTxOut/:txid/:n', this.getTxOut) + this.router.get('/getTxOutProof/:txid', this.getTxOutProofSingle) + this.router.post('/getTxOutProof', this.getTxOutProofBulk) + this.router.get('/verifyTxOutProof/:proof', this.verifyTxOutProofSingle) + this.router.post('/verifyTxOutProof', this.verifyTxOutProofBulk) } - root(req, res, next) { - return res.json({ status: "blockchain" }) + root (req, res, next) { + return res.json({ status: 'blockchain' }) } // DRY error handler. - errorHandler(err, res) { + errorHandler (err, res) { // Attempt to decode the error message. const { msg, status } = _this.routeUtils.decodeError(err) if (msg) { @@ -83,12 +83,12 @@ class Blockchain { * * @apiSuccess {String} bestBlockHash 000000000000000002bc884334336d99c9a9c616670a9244c6a8c1fc35aa91a1 */ - async getBestBlockHash(req, res, next) { + async getBestBlockHash (req, res, next) { try { // Axios options const options = _this.routeUtils.getAxiosOptions() - options.data.id = "getbestblockhash" - options.data.method = "getbestblockhash" + options.data.id = 'getbestblockhash' + options.data.method = 'getbestblockhash' options.data.params = [] const response = await _this.axios.request(options) @@ -97,7 +97,7 @@ class Blockchain { return res.json(response.data.result) } catch (err) { // Write out error to error log. - wlogger.error("Error in blockchain.ts/getBestBlockHash().", err) + wlogger.error('Error in blockchain.ts/getBestBlockHash().', err) return _this.errorHandler(err, res) } @@ -128,12 +128,12 @@ class Blockchain { * @apiSuccess {Object} object.softforks.reject * @apiSuccess {String} object.softforks.reject.status true */ - async getBlockchainInfo(req, res, next) { + async getBlockchainInfo (req, res, next) { try { // Axios options const options = _this.routeUtils.getAxiosOptions() - options.data.id = "getblockchaininfo" - options.data.method = "getblockchaininfo" + options.data.id = 'getblockchaininfo' + options.data.method = 'getblockchaininfo' options.data.params = [] const response = await _this.axios.request(options) @@ -141,7 +141,7 @@ class Blockchain { return res.json(response.data.result) } catch (err) { // Write out error to error log. - wlogger.error("Error in blockchain.ts/getBlockchainInfo().", err) + wlogger.error('Error in blockchain.ts/getBlockchainInfo().', err) return _this.errorHandler(err, res) } @@ -158,12 +158,12 @@ class Blockchain { * * @apiSuccess {Number} bestBlockCount 587665 */ - async getBlockCount(req, res, next) { + async getBlockCount (req, res, next) { try { // Axios options const options = _this.routeUtils.getAxiosOptions() - options.data.id = "getblockcount" - options.data.method = "getblockcount" + options.data.id = 'getblockcount' + options.data.method = 'getblockcount' options.data.params = [] const response = await _this.axios.request(options) @@ -172,7 +172,7 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/getBlockCount().", err) + wlogger.error('Error in blockchain.ts/getBlockCount().', err) return _this.errorHandler(err, res) } @@ -208,22 +208,23 @@ class Blockchain { * @apiSuccess {String} object.previousblockhash "0000000000000000043831d6ebb013716f0580287ee5e5687e27d0ed72e6e523" * @apiSuccess {String} object.nextblockhash "00000000000000000568f0a96bf4348847bc84e455cbfec389f27311037a20f3" */ - async getBlockHeaderSingle(req, res, next) { + async getBlockHeaderSingle (req, res, next) { try { let verbose = false - if (req.query.verbose && req.query.verbose.toString() === "true") + if (req.query.verbose && req.query.verbose.toString() === 'true') { verbose = true + } const hash = req.params.hash - if (!hash || hash === "") { + if (!hash || hash === '') { res.status(400) - return res.json({ error: "hash can not be empty" }) + return res.json({ error: 'hash can not be empty' }) } // Axios options const options = _this.routeUtils.getAxiosOptions() - options.data.id = "getblockheader" - options.data.method = "getblockheader" + options.data.id = 'getblockheader' + options.data.method = 'getblockheader' options.data.params = [hash, verbose] const response = await _this.axios.request(options) @@ -232,7 +233,7 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/getBlockHeaderSingle().", err) + wlogger.error('Error in blockchain.ts/getBlockHeaderSingle().', err) return _this.errorHandler(err, res) } @@ -268,7 +269,7 @@ class Blockchain { * @apiSuccess {String} object.previousblockhash "0000000000000000043831d6ebb013716f0580287ee5e5687e27d0ed72e6e523" * @apiSuccess {String} object.nextblockhash "00000000000000000568f0a96bf4348847bc84e455cbfec389f27311037a20f3" */ - async getBlockHeaderBulk(req, res, next) { + async getBlockHeaderBulk (req, res, next) { try { const hashes = req.body.hashes const verbose = req.body.verbose ? req.body.verbose : false @@ -276,7 +277,7 @@ class Blockchain { if (!Array.isArray(hashes)) { res.status(400) return res.json({ - error: "hashes needs to be an array. Use GET for single hash." + error: 'hashes needs to be an array. Use GET for single hash.' }) } @@ -284,12 +285,12 @@ class Blockchain { if (!routeUtils.validateArraySize(req, hashes)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: "Array too large." + error: 'Array too large.' }) } wlogger.debug( - "Executing blockchain/getBlockHeaderBulk with these hashes: ", + 'Executing blockchain/getBlockHeaderBulk with these hashes: ', hashes ) @@ -308,11 +309,11 @@ class Blockchain { // Loop through each hash and creates an array of requests to call in parallel const promises = hashes.map(async hash => { - options.data.id = "getblockheader" - options.data.method = "getblockheader" + options.data.id = 'getblockheader' + options.data.method = 'getblockheader' options.data.params = [hash, verbose] - return await _this.axios.request(options) + return _this.axios.request(options) }) const axiosResult = await _this.axios.all(promises) @@ -325,7 +326,7 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/getBlockHeaderBulk().", err) + wlogger.error('Error in blockchain.ts/getBlockHeaderBulk().', err) return _this.errorHandler(err, res) } @@ -342,13 +343,13 @@ class Blockchain { * curl -X GET "https://mainnet.bchjs.cash/v3/blockchain/getChainTips" -H "accept: application/json" * */ - async getChainTips(req, res, next) { + async getChainTips (req, res, next) { try { // Axios options const options = _this.routeUtils.getAxiosOptions() - options.data.id = "getchaintips" - options.data.method = "getchaintips" + options.data.id = 'getchaintips' + options.data.method = 'getchaintips' options.data.params = [] const response = await _this.axios.request(options) @@ -356,7 +357,7 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/getChainTips().", err) + wlogger.error('Error in blockchain.ts/getChainTips().', err) return _this.errorHandler(err, res) } @@ -373,13 +374,13 @@ class Blockchain { * curl -X GET "https://mainnet.bchjs.cash/v3/blockchain/getDifficulty" -H "accept: application/json" * */ - async getDifficulty(req, res, next) { + async getDifficulty (req, res, next) { try { // Axios options const options = _this.routeUtils.getAxiosOptions() - options.data.id = "getdifficulty" - options.data.method = "getdifficulty" + options.data.id = 'getdifficulty' + options.data.method = 'getdifficulty' options.data.params = [] const response = await _this.axios.request(options) @@ -388,7 +389,7 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/getDifficulty().", err) + wlogger.error('Error in blockchain.ts/getDifficulty().', err) return _this.errorHandler(err, res) } @@ -405,20 +406,20 @@ class Blockchain { * curl -X GET "https://mainnet.bchjs.cash/v3/blockchain/getMempoolEntry/fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33" -H "accept: application/json" * */ - async getMempoolEntrySingle(req, res, next) { + async getMempoolEntrySingle (req, res, next) { try { // Validate input parameter const txid = req.params.txid - if (!txid || txid === "") { + if (!txid || txid === '') { res.status(400) - return res.json({ error: "txid can not be empty" }) + return res.json({ error: 'txid can not be empty' }) } // Axios options const options = _this.routeUtils.getAxiosOptions() - options.data.id = "getmempoolentry" - options.data.method = "getmempoolentry" + options.data.id = 'getmempoolentry' + options.data.method = 'getmempoolentry' options.data.params = [txid] const response = await _this.axios.request(options) @@ -427,7 +428,7 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/getMempoolEntrySingle().", err) + wlogger.error('Error in blockchain.ts/getMempoolEntrySingle().', err) return _this.errorHandler(err, res) } @@ -442,14 +443,14 @@ class Blockchain { * @apiExample Example usage: * curl -X POST https://mainnet.bchjs.cash/v3/blockchain/getMempoolEntry -H "Content-Type: application/json" -d "{\"txids\":[\"a5f972572ee1753e2fd2457dd61ce5f40fa2f8a30173d417e49feef7542c96a1\",\"5165dc531aad05d1149bb0f0d9b7bda99c73e2f05e314bcfb5b4bb9ca5e1af5e\"]}" */ - async getMempoolEntryBulk(req, res, next) { + async getMempoolEntryBulk (req, res, next) { try { const txids = req.body.txids if (!Array.isArray(txids)) { res.status(400) return res.json({ - error: "txids needs to be an array. Use GET for single txid." + error: 'txids needs to be an array. Use GET for single txid.' }) } @@ -457,12 +458,12 @@ class Blockchain { if (!routeUtils.validateArraySize(req, txids)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: "Array too large." + error: 'Array too large.' }) } wlogger.debug( - "Executing blockchain/getMempoolEntry with these txids: ", + 'Executing blockchain/getMempoolEntry with these txids: ', txids ) @@ -472,7 +473,7 @@ class Blockchain { if (txid.length !== 64) { res.status(400) - return res.json({ error: "This is not a txid" }) + return res.json({ error: 'This is not a txid' }) } } @@ -481,11 +482,11 @@ class Blockchain { // Loop through each txid and creates an array of requests to call in parallel const promises = txids.map(async txid => { - options.data.id = "getmempoolentry" - options.data.method = "getmempoolentry" + options.data.id = 'getmempoolentry' + options.data.method = 'getmempoolentry' options.data.params = [txid] - return await _this.axios.request(options) + return _this.axios.request(options) }) const axiosResult = await _this.axios.all(promises) @@ -498,7 +499,7 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/getMempoolEntryBulk().", err) + wlogger.error('Error in blockchain.ts/getMempoolEntryBulk().', err) return _this.errorHandler(err, res) } @@ -516,13 +517,13 @@ class Blockchain { * curl -X GET "https://mainnet.bchjs.cash/v3/blockchain/getMempoolAncestors/fe28050b93faea61fa88c4c630f0e1f0a1c24d0082dd0e10d369e13212128f33" -H "accept: application/json" * */ - async getMempoolAncestorsSingle(req, res, next) { + async getMempoolAncestorsSingle (req, res, next) { try { // Validate input parameter const txid = req.params.txid - if (!txid || txid === "") { + if (!txid || txid === '') { res.status(400) - return res.json({ error: "txid can not be empty" }) + return res.json({ error: 'txid can not be empty' }) } let verbose = req.params.verbose @@ -531,8 +532,8 @@ class Blockchain { // Axios options const options = _this.routeUtils.getAxiosOptions() - options.data.id = "getmempoolancestors" - options.data.method = "getmempoolancestors" + options.data.id = 'getmempoolancestors' + options.data.method = 'getmempoolancestors' options.data.params = [txid, verbose] const response = await _this.axios.request(options) @@ -542,7 +543,7 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/getMempoolAncestorsSingle().", err) + wlogger.error('Error in blockchain.ts/getMempoolAncestorsSingle().', err) return _this.errorHandler(err, res) } @@ -558,13 +559,13 @@ class Blockchain { * curl -X GET https://mainnet.bchjs.cash/v3/getMempoolInfo -H "accept: application/json" * */ - async getMempoolInfo(req, res, next) { + async getMempoolInfo (req, res, next) { try { // Axios options const options = _this.routeUtils.getAxiosOptions() - options.data.id = "getmempoolinfo" - options.data.method = "getmempoolinfo" + options.data.id = 'getmempoolinfo' + options.data.method = 'getmempoolinfo' options.data.params = [] const response = await _this.axios.request(options) @@ -572,7 +573,7 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/getMempoolInfo().", err) + wlogger.error('Error in blockchain.ts/getMempoolInfo().', err) return _this.errorHandler(err, res) } @@ -602,16 +603,16 @@ class Blockchain { * @apiParam {Boolean} verbose Return verbose data * */ - async getRawMempool(req, res, next) { + async getRawMempool (req, res, next) { try { // Axios options const options = _this.routeUtils.getAxiosOptions() let verbose = false - if (req.query.verbose && req.query.verbose === "true") verbose = true + if (req.query.verbose && req.query.verbose === 'true') verbose = true - options.data.id = "getrawmempool" - options.data.method = "getrawmempool" + options.data.id = 'getrawmempool' + options.data.method = 'getrawmempool' options.data.params = [verbose] const response = await _this.axios.request(options) @@ -620,7 +621,7 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/getRawMempool().", err) + wlogger.error('Error in blockchain.ts/getRawMempool().', err) return _this.errorHandler(err, res) } @@ -641,32 +642,33 @@ class Blockchain { * */ // Returns details about an unspent transaction output. - async getTxOut(req, res, next) { + async getTxOut (req, res, next) { try { // Validate input parameter const txid = req.params.txid - if (!txid || txid === "") { + if (!txid || txid === '') { res.status(400) - return res.json({ error: "txid can not be empty" }) + return res.json({ error: 'txid can not be empty' }) } let n = req.params.n - if (n === undefined || n === "") { + if (n === undefined || n === '') { res.status(400) - return res.json({ error: "n can not be empty" }) + return res.json({ error: 'n can not be empty' }) } n = parseInt(n) - let include_mempool = false - if (req.query.include_mempool && req.query.include_mempool === "true") - include_mempool = true + let includeMempool = false + if (req.query.includeMempool && req.query.includeMempool === 'true') { + includeMempool = true + } // Axios options const options = _this.routeUtils.getAxiosOptions() - options.data.id = "gettxout" - options.data.method = "gettxout" - options.data.params = [txid, n, include_mempool] + options.data.id = 'gettxout' + options.data.method = 'gettxout' + options.data.params = [txid, n, includeMempool] // console.log(`requestConfig: ${JSON.stringify(requestConfig, null, 2)}`) @@ -676,7 +678,7 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/getTxOut().", err) + wlogger.error('Error in blockchain.ts/getTxOut().', err) return _this.errorHandler(err, res) } @@ -694,20 +696,20 @@ class Blockchain { * @apiParam {String} txid Transaction id (required) * */ - async getTxOutProofSingle(req, res, next) { + async getTxOutProofSingle (req, res, next) { try { // Validate input parameter const txid = req.params.txid - if (!txid || txid === "") { + if (!txid || txid === '') { res.status(400) - return res.json({ error: "txid can not be empty" }) + return res.json({ error: 'txid can not be empty' }) } // Axios options const options = _this.routeUtils.getAxiosOptions() - options.data.id = "gettxoutproof" - options.data.method = "gettxoutproof" + options.data.id = 'gettxoutproof' + options.data.method = 'gettxoutproof' options.data.params = [[txid]] const response = await _this.axios.request(options) @@ -716,14 +718,14 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/getTxOutProofSingle().", err) + wlogger.error('Error in blockchain.ts/getTxOutProofSingle().', err) return _this.errorHandler(err, res) } } // Returns a hex-encoded proof that 'txid' was included in a block. - async getTxOutProofBulk(req, res, next) { + async getTxOutProofBulk (req, res, next) { try { const txids = req.body.txids @@ -731,7 +733,7 @@ class Blockchain { if (!Array.isArray(txids)) { res.status(400) return res.json({ - error: "txids needs to be an array. Use GET for single txid." + error: 'txids needs to be an array. Use GET for single txid.' }) } @@ -739,7 +741,7 @@ class Blockchain { if (!routeUtils.validateArraySize(req, txids)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: "Array too large." + error: 'Array too large.' }) } @@ -759,17 +761,17 @@ class Blockchain { } wlogger.debug( - "Executing blockchain/getTxOutProof with these txids: ", + 'Executing blockchain/getTxOutProof with these txids: ', txids ) // Loop through each txid and creates an array of requests to call in parallel const promises = txids.map(async txid => { - options.data.id = "gettxoutproof" - options.data.method = "gettxoutproof" + options.data.id = 'gettxoutproof' + options.data.method = 'gettxoutproof' options.data.params = [[txid]] - return await _this.axios.request(options) + return _this.axios.request(options) }) // Wait for all parallel promisses to resolve. @@ -783,26 +785,26 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/getTxOutProofBulk().", err) + wlogger.error('Error in blockchain.ts/getTxOutProofBulk().', err) return _this.errorHandler(err, res) } } - async verifyTxOutProofSingle(req, res, next) { + async verifyTxOutProofSingle (req, res, next) { try { // Validate input parameter const proof = req.params.proof - if (!proof || proof === "") { + if (!proof || proof === '') { res.status(400) - return res.json({ error: "proof can not be empty" }) + return res.json({ error: 'proof can not be empty' }) } // Axios options const options = _this.routeUtils.getAxiosOptions() - options.data.id = "verifytxoutproof" - options.data.method = "verifytxoutproof" + options.data.id = 'verifytxoutproof' + options.data.method = 'verifytxoutproof' options.data.params = [req.params.proof] const response = await _this.axios.request(options) @@ -811,13 +813,13 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/verifyTxOutProofSingle().", err) + wlogger.error('Error in blockchain.ts/verifyTxOutProofSingle().', err) return _this.errorHandler(err, res) } } - async verifyTxOutProofBulk(req, res, next) { + async verifyTxOutProofBulk (req, res, next) { try { const proofs = req.body.proofs @@ -825,7 +827,7 @@ class Blockchain { if (!Array.isArray(proofs)) { res.status(400) return res.json({ - error: "proofs needs to be an array. Use GET for single proof." + error: 'proofs needs to be an array. Use GET for single proof.' }) } @@ -833,7 +835,7 @@ class Blockchain { if (!routeUtils.validateArraySize(req, proofs)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: "Array too large." + error: 'Array too large.' }) } @@ -844,24 +846,24 @@ class Blockchain { for (let i = 0; i < proofs.length; i++) { const proof = proofs[i] - if (!proof || proof === "") { + if (!proof || proof === '') { res.status(400) return res.json({ error: `proof can not be empty: ${proof}` }) } } wlogger.debug( - "Executing blockchain/verifyTxOutProof with these proofs: ", + 'Executing blockchain/verifyTxOutProof with these proofs: ', proofs ) // Loop through each proof and creates an array of requests to call in parallel const promises = proofs.map(async proof => { - options.data.id = "verifytxoutproof" - options.data.method = "verifytxoutproof" + options.data.id = 'verifytxoutproof' + options.data.method = 'verifytxoutproof' options.data.params = [proof] - return await _this.axios.request(options) + return _this.axios.request(options) }) // Wait for all parallel promisses to resolve. @@ -875,7 +877,7 @@ class Blockchain { } catch (err) { // Write out error to error log. // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) - wlogger.error("Error in blockchain.ts/verifyTxOutProofBulk().", err) + wlogger.error('Error in blockchain.ts/verifyTxOutProofBulk().', err) return _this.errorHandler(err, res) } diff --git a/src/routes/v3/full-node/control.js b/src/routes/v3/full-node/control.js index 1a0ae1e..607177e 100644 --- a/src/routes/v3/full-node/control.js +++ b/src/routes/v3/full-node/control.js @@ -1,21 +1,21 @@ -"use strict" +'use strict' -const express = require("express") +const express = require('express') const router = express.Router() -const axios = require("axios") +// const axios = require('axios') -const routeUtils = require("../route-utils") -const wlogger = require("../../../util/winston-logging") +const routeUtils = require('../route-utils') +const wlogger = require('../../../util/winston-logging') // Used for processing error messages before sending them to the user. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -router.get("/", root) -router.get("/getnetworkinfo", getNetworkInfo) +router.get('/', root) +router.get('/getnetworkinfo', getNetworkInfo) -function root(req, res, next) { - return res.json({ status: "control" }) +function root (req, res, next) { + return res.json({ status: 'control' }) } /** @@ -28,16 +28,16 @@ function root(req, res, next) { * curl -X GET "https://mainnet.bchjs.cash/v3/control/getnetworkinfo" -H "accept: application/json" * */ -async function getNetworkInfo(req, res, next) { +async function getNetworkInfo (req, res, next) { const { BitboxHTTP, - username, - password, + // username, + // password, requestConfig } = routeUtils.setEnvVars() - requestConfig.data.id = "getnetworkinfo" - requestConfig.data.method = "getnetworkinfo" + requestConfig.data.id = 'getnetworkinfo' + requestConfig.data.method = 'getnetworkinfo' requestConfig.data.params = [] try { @@ -45,14 +45,13 @@ async function getNetworkInfo(req, res, next) { return res.json(response.data.result) } catch (error) { - wlogger.error(`Error in control.ts/getNetworkInfo().`, error) + wlogger.error('Error in control.ts/getNetworkInfo().', error) // Write out error to error log. - //logger.error(`Error in control/getInfo: `, error) + // logger.error(`Error in control/getInfo: `, error) res.status(500) - if (error.response && error.response.data && error.response.data.error) - return res.json({ error: error.response.data.error }) + if (error.response && error.response.data && error.response.data.error) { return res.json({ error: error.response.data.error }) } return res.json({ error: util.inspect(error) }) } } diff --git a/src/routes/v3/full-node/mining.js b/src/routes/v3/full-node/mining.js index daa6c10..c68ce18 100644 --- a/src/routes/v3/full-node/mining.js +++ b/src/routes/v3/full-node/mining.js @@ -1,39 +1,39 @@ -"use strict" +'use strict' -const express = require("express") +const express = require('express') const router = express.Router() -const axios = require("axios") +// const axios = require('axios') -const routeUtils = require("../route-utils") -const wlogger = require("../../../util/winston-logging") +const routeUtils = require('../route-utils') +const wlogger = require('../../../util/winston-logging') // Used to convert error messages to strings, to safely pass to users. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -const BitboxHTTP = axios.create({ - baseURL: process.env.RPC_BASEURL -}) -const username = process.env.RPC_USERNAME -const password = process.env.RPC_PASSWORD +// const BitboxHTTP = axios.create({ +// baseURL: process.env.RPC_BASEURL +// }) +// const username = process.env.RPC_USERNAME +// const password = process.env.RPC_PASSWORD -const requestConfig = { - method: "post", - auth: { - username: username, - password: password - }, - data: { - jsonrpc: "1.0" - } -} +// const requestConfig = { +// method: 'post', +// auth: { +// username: username, +// password: password +// }, +// data: { +// jsonrpc: '1.0' +// } +// } -router.get("/", root) -router.get("/getMiningInfo", getMiningInfo) -router.get("/getNetworkHashps", getNetworkHashPS) +router.get('/', root) +router.get('/getMiningInfo', getMiningInfo) +router.get('/getNetworkHashps', getNetworkHashPS) -function root(req, res, next) { - return res.json({ status: "mining" }) +function root (req, res, next) { + return res.json({ status: 'mining' }) } // @@ -72,17 +72,17 @@ function root(req, res, next) { * * */ -async function getMiningInfo(req, res, next) { +async function getMiningInfo (req, res, next) { try { const { BitboxHTTP, - username, - password, + // username, + // password, requestConfig } = routeUtils.setEnvVars() - requestConfig.data.id = "getmininginfo" - requestConfig.data.method = "getmininginfo" + requestConfig.data.id = 'getmininginfo' + requestConfig.data.method = 'getmininginfo' requestConfig.data.params = [] const response = await BitboxHTTP(requestConfig) @@ -96,7 +96,7 @@ async function getMiningInfo(req, res, next) { return res.json({ error: msg }) } - wlogger.error(`Error in mining.ts/getMiningInfo().`, err) + wlogger.error('Error in mining.ts/getMiningInfo().', err) res.status(500) return res.json({ error: util.inspect(err) }) @@ -114,7 +114,7 @@ async function getMiningInfo(req, res, next) { * * */ -async function getNetworkHashPS(req, res, next) { +async function getNetworkHashPS (req, res, next) { try { let nblocks = 120 // Default let height = -1 // Default @@ -123,13 +123,13 @@ async function getNetworkHashPS(req, res, next) { const { BitboxHTTP, - username, - password, + // username, + // password, requestConfig } = routeUtils.setEnvVars() - requestConfig.data.id = "getnetworkhashps" - requestConfig.data.method = "getnetworkhashps" + requestConfig.data.id = 'getnetworkhashps' + requestConfig.data.method = 'getnetworkhashps' requestConfig.data.params = [nblocks, height] const response = await BitboxHTTP(requestConfig) @@ -143,7 +143,7 @@ async function getNetworkHashPS(req, res, next) { return res.json({ error: msg }) } - wlogger.error(`Error in mining.ts/getNetworkHashPS().`, err) + wlogger.error('Error in mining.ts/getNetworkHashPS().', err) res.status(500) return res.json({ error: util.inspect(err) }) diff --git a/src/routes/v3/full-node/network.js b/src/routes/v3/full-node/network.js index 0af2366..3e0c2ed 100644 --- a/src/routes/v3/full-node/network.js +++ b/src/routes/v3/full-node/network.js @@ -1,10 +1,10 @@ -"use strict" +'use strict' -const express = require("express") +const express = require('express') const router = express.Router() -router.get("/", async (req, res, next) => { - res.json({ status: "network" }) +router.get('/', async (req, res, next) => { + res.json({ status: 'network' }) }) // router.post('/addNode/:node/:command', (req, res, next) => { diff --git a/src/routes/v3/full-node/rawtransactions.js b/src/routes/v3/full-node/rawtransactions.js index 7ae5998..ac88b0b 100644 --- a/src/routes/v3/full-node/rawtransactions.js +++ b/src/routes/v3/full-node/rawtransactions.js @@ -1,45 +1,45 @@ -"use strict" +'use strict' -const express = require("express") +const express = require('express') const router = express.Router() -const axios = require("axios") +const axios = require('axios') -const routeUtils = require("../route-utils") -const wlogger = require("../../../util/winston-logging") +const routeUtils = require('../route-utils') +const wlogger = require('../../../util/winston-logging') // Used to convert error messages to strings, to safely pass to users. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -const BitboxHTTP = axios.create({ - baseURL: process.env.RPC_BASEURL -}) -const username = process.env.RPC_USERNAME -const password = process.env.RPC_PASSWORD +// const BitboxHTTP = axios.create({ +// baseURL: process.env.RPC_BASEURL +// }) +// const username = process.env.RPC_USERNAME +// const password = process.env.RPC_PASSWORD -const requestConfig = { - method: "post", - auth: { - username: username, - password: password - }, - data: { - jsonrpc: "1.0" - } -} +// const requestConfig = { +// method: 'post', +// auth: { +// username: username, +// password: password +// }, +// data: { +// jsonrpc: '1.0' +// } +// } -router.get("/", root) -router.get("/decodeRawTransaction/:hex", decodeRawTransactionSingle) -router.post("/decodeRawTransaction", decodeRawTransactionBulk) -router.get("/decodeScript/:hex", decodeScriptSingle) -router.post("/decodeScript", decodeScriptBulk) -router.post("/getRawTransaction", getRawTransactionBulk) -router.get("/getRawTransaction/:txid", getRawTransactionSingle) -router.post("/sendRawTransaction", sendRawTransactionBulk) -router.get("/sendRawTransaction/:hex", sendRawTransactionSingle) +router.get('/', root) +router.get('/decodeRawTransaction/:hex', decodeRawTransactionSingle) +router.post('/decodeRawTransaction', decodeRawTransactionBulk) +router.get('/decodeScript/:hex', decodeScriptSingle) +router.post('/decodeScript', decodeScriptBulk) +router.post('/getRawTransaction', getRawTransactionBulk) +router.get('/getRawTransaction/:txid', getRawTransactionSingle) +router.post('/sendRawTransaction', sendRawTransactionBulk) +router.get('/sendRawTransaction/:hex', sendRawTransactionSingle) -function root(req, res, next) { - return res.json({ status: "rawtransactions" }) +function root (req, res, next) { + return res.json({ status: 'rawtransactions' }) } // Decode transaction hex into a JSON object. @@ -56,25 +56,25 @@ function root(req, res, next) { * * */ -async function decodeRawTransactionSingle(req, res, next) { +async function decodeRawTransactionSingle (req, res, next) { try { const hex = req.params.hex // Throw an error if hex is empty. - if (!hex || hex === "") { + if (!hex || hex === '') { res.status(400) - return res.json({ error: "hex can not be empty" }) + return res.json({ error: 'hex can not be empty' }) } const { BitboxHTTP, - username, - password, + // username, + // password, requestConfig } = routeUtils.setEnvVars() - requestConfig.data.id = "decoderawtransaction" - requestConfig.data.method = "decoderawtransaction" + requestConfig.data.id = 'decoderawtransaction' + requestConfig.data.method = 'decoderawtransaction' requestConfig.data.params = [hex] const response = await BitboxHTTP(requestConfig) @@ -88,9 +88,9 @@ async function decodeRawTransactionSingle(req, res, next) { } // Write out error to error log. - //logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) + // logger.error(`Error in rawtransactions/decodeRawTransaction: `, err) wlogger.error( - `Error in rawtransactions.ts/decodeRawTransactionSingle().`, + 'Error in rawtransactions.ts/decodeRawTransactionSingle().', err ) @@ -111,50 +111,50 @@ async function decodeRawTransactionSingle(req, res, next) { * */ -async function decodeRawTransactionBulk(req, res, next) { +async function decodeRawTransactionBulk (req, res, next) { try { const hexes = req.body.hexes if (!Array.isArray(hexes)) { res.status(400) - return res.json({ error: "hexes must be an array" }) + return res.json({ error: 'hexes must be an array' }) } // Enforce array size rate limits if (!routeUtils.validateArraySize(req, hexes)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: `Array too large.` + error: 'Array too large.' }) } - const results = [] + // const results = [] // Validate each element in the address array. for (let i = 0; i < hexes.length; i++) { const thisHex = hexes[i] // Reject if id is empty - if (!thisHex || thisHex === "") { + if (!thisHex || thisHex === '') { res.status(400) - return res.json({ error: "Encountered empty hex" }) + return res.json({ error: 'Encountered empty hex' }) } } const { BitboxHTTP, - username, - password, + // username, + // password, requestConfig } = routeUtils.setEnvVars() // Loop through each height and creates an array of requests to call in parallel const promises = hexes.map(async hex => { - requestConfig.data.id = "decoderawtransaction" - requestConfig.data.method = "decoderawtransaction" + requestConfig.data.id = 'decoderawtransaction' + requestConfig.data.method = 'decoderawtransaction' requestConfig.data.params = [hex] - return await BitboxHTTP(requestConfig) + return BitboxHTTP(requestConfig) }) // Wait for all parallel Insight requests to return. @@ -210,9 +210,9 @@ async function decodeRawTransactionBulk(req, res, next) { } // Write out error to error log. - //logger.error(`Error in rawtransactions/getRawTransaction: `, err) + // logger.error(`Error in rawtransactions/getRawTransaction: `, err) wlogger.error( - `Error in rawtransactions.ts/decodeRawTransactionBulk().`, + 'Error in rawtransactions.ts/decodeRawTransactionBulk().', err ) @@ -235,25 +235,25 @@ async function decodeRawTransactionBulk(req, res, next) { * * */ -async function decodeScriptSingle(req, res, next) { +async function decodeScriptSingle (req, res, next) { try { const hex = req.params.hex // Throw an error if hex is empty. - if (!hex || hex === "") { + if (!hex || hex === '') { res.status(400) - return res.json({ error: "hex can not be empty" }) + return res.json({ error: 'hex can not be empty' }) } const { BitboxHTTP, - username, - password, + // username, + // password, requestConfig } = routeUtils.setEnvVars() - requestConfig.data.id = "decodescript" - requestConfig.data.method = "decodescript" + requestConfig.data.id = 'decodescript' + requestConfig.data.method = 'decodescript' requestConfig.data.params = [hex] const response = await BitboxHTTP(requestConfig) @@ -267,8 +267,8 @@ async function decodeScriptSingle(req, res, next) { } // Write out error to error log. - //logger.error(`Error in rawtransactions/decodeScript: `, err) - wlogger.error(`Error in rawtransactions.ts/decodeScriptSingle().`, err) + // logger.error(`Error in rawtransactions/decodeScript: `, err) + wlogger.error('Error in rawtransactions.ts/decodeScriptSingle().', err) res.status(500) return res.json({ error: util.inspect(err) }) @@ -289,21 +289,21 @@ async function decodeScriptSingle(req, res, next) { * * */ -async function decodeScriptBulk(req, res, next) { +async function decodeScriptBulk (req, res, next) { try { const hexes = req.body.hexes // Validation if (!Array.isArray(hexes)) { res.status(400) - return res.json({ error: "hexes must be an array" }) + return res.json({ error: 'hexes must be an array' }) } // Enforce array size rate limits if (!routeUtils.validateArraySize(req, hexes)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: `Array too large.` + error: 'Array too large.' }) } @@ -312,23 +312,23 @@ async function decodeScriptBulk(req, res, next) { const hex = hexes[i] // Throw an error if hex is empty. - if (!hex || hex === "") { + if (!hex || hex === '') { res.status(400) - return res.json({ error: "Encountered empty hex" }) + return res.json({ error: 'Encountered empty hex' }) } } const { BitboxHTTP, - username, - password, + // username, + // password, requestConfig } = routeUtils.setEnvVars() // Loop through each hex and create an array of promises const promises = hexes.map(async hex => { - requestConfig.data.id = "decodescript" - requestConfig.data.method = "decodescript" + requestConfig.data.id = 'decodescript' + requestConfig.data.method = 'decodescript' requestConfig.data.params = [hex] const response = await BitboxHTTP(requestConfig) @@ -352,8 +352,8 @@ async function decodeScriptBulk(req, res, next) { } // Write out error to error log. - //logger.error(`Error in rawtransactions/decodeScript: `, err) - wlogger.error(`Error in rawtransactions.ts/decodeScriptBulk().`, err) + // logger.error(`Error in rawtransactions/decodeScript: `, err) + wlogger.error('Error in rawtransactions.ts/decodeScriptBulk().', err) res.status(500) return res.json({ error: util.inspect(err) }) @@ -362,24 +362,24 @@ async function decodeScriptBulk(req, res, next) { // Retrieve raw transactions details from the full node. -async function getRawTransactionsFromNode(txid, verbose) { +async function getRawTransactionsFromNode (txid, verbose) { try { const { BitboxHTTP, - username, - password, + // username, + // password, requestConfig } = routeUtils.setEnvVars() - requestConfig.data.id = "getrawtransaction" - requestConfig.data.method = "getrawtransaction" + requestConfig.data.id = 'getrawtransaction' + requestConfig.data.method = 'getrawtransaction' requestConfig.data.params = [txid, verbose] const response = await BitboxHTTP(requestConfig) return response.data.result } catch (err) { - wlogger.error(`Error in rawtransactions.ts/getRawTransactionsFromNode().`) + wlogger.error('Error in rawtransactions.ts/getRawTransactionsFromNode().') throw err } } @@ -397,7 +397,7 @@ async function getRawTransactionsFromNode(txid, verbose) { * curl -X POST "https://mainnet.bchjs.cash/v3/rawtransactions/getRawTransaction" -H "accept: application/json" -H "Content-Type: application/json" -d '{"txids":["a5f972572ee1753e2fd2457dd61ce5f40fa2f8a30173d417e49feef7542c96a1","5165dc531aad05d1149bb0f0d9b7bda99c73e2f05e314bcfb5b4bb9ca5e1af5e"],"verbose":true}' * */ -async function getRawTransactionBulk(req, res, next) { +async function getRawTransactionBulk (req, res, next) { try { let verbose = 0 if (req.body.verbose) verbose = 1 @@ -405,32 +405,32 @@ async function getRawTransactionBulk(req, res, next) { const txids = req.body.txids if (!Array.isArray(txids)) { res.status(400) - return res.json({ error: "txids must be an array" }) + return res.json({ error: 'txids must be an array' }) } // Enforce array size rate limits if (!routeUtils.validateArraySize(req, txids)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: `Array too large.` + error: 'Array too large.' }) } // stub response object - const returnResponse = { - status: 100, - json: { - error: "" - } - } + // const returnResponse = { + // status: 100, + // json: { + // error: '' + // } + // } // Validate each txid in the array. for (let i = 0; i < txids.length; i++) { const txid = txids[i] - if (!txid || txid === "") { + if (!txid || txid === '') { res.status(400) - return res.json({ error: `Encountered empty TXID` }) + return res.json({ error: 'Encountered empty TXID' }) } if (txid.length !== 64) { @@ -460,8 +460,8 @@ async function getRawTransactionBulk(req, res, next) { } // Write out error to error log. - //logger.error(`Error in rawtransactions/getRawTransaction: `, err) - wlogger.error(`Error in rawtransactions.ts/getRawTransactionBulk().`, err) + // logger.error(`Error in rawtransactions/getRawTransaction: `, err) + wlogger.error('Error in rawtransactions.ts/getRawTransactionBulk().', err) res.status(500) return res.json({ error: util.inspect(err) }) @@ -482,15 +482,15 @@ async function getRawTransactionBulk(req, res, next) { * * */ -async function getRawTransactionSingle(req, res, next) { +async function getRawTransactionSingle (req, res, next) { try { let verbose = 0 - if (req.query.verbose === "true") verbose = 1 + if (req.query.verbose === 'true') verbose = 1 const txid = req.params.txid - if (!txid || txid === "") { + if (!txid || txid === '') { res.status(400) - return res.json({ error: "txid can not be empty" }) + return res.json({ error: 'txid can not be empty' }) } const data = await getRawTransactionsFromNode(txid, verbose) @@ -505,8 +505,8 @@ async function getRawTransactionSingle(req, res, next) { } // Write out error to error log. - //logger.error(`Error in rawtransactions/getRawTransaction: `, err) - wlogger.error(`Error in rawtransactions.ts/getRawTransactionSingle().`, err) + // logger.error(`Error in rawtransactions/getRawTransaction: `, err) + wlogger.error('Error in rawtransactions.ts/getRawTransactionSingle().', err) res.status(500) return res.json({ error: util.inspect(err) }) @@ -526,7 +526,7 @@ async function getRawTransactionSingle(req, res, next) { * * */ -async function sendRawTransactionBulk(req, res, next) { +async function sendRawTransactionBulk (req, res, next) { try { // Validation const hexes = req.body.hexes @@ -534,13 +534,13 @@ async function sendRawTransactionBulk(req, res, next) { // Reject if input is not an array if (!Array.isArray(hexes)) { res.status(400) - return res.json({ error: "hex must be an array" }) + return res.json({ error: 'hex must be an array' }) } const { BitboxHTTP, - username, - password, + // username, + // password, requestConfig } = routeUtils.setEnvVars() @@ -548,7 +548,7 @@ async function sendRawTransactionBulk(req, res, next) { if (!routeUtils.validateArraySize(req, hexes)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: `Array too large.` + error: 'Array too large.' }) } @@ -556,10 +556,10 @@ async function sendRawTransactionBulk(req, res, next) { for (let i = 0; i < hexes.length; i++) { const hex = hexes[i] - if (hex === "") { + if (hex === '') { res.status(400) return res.json({ - error: `Encountered empty hex` + error: 'Encountered empty hex' }) } } @@ -594,8 +594,8 @@ async function sendRawTransactionBulk(req, res, next) { for (let i = 0; i < hexes.length; i++) { const hex = hexes[i] - requestConfig.data.id = "sendrawtransaction" - requestConfig.data.method = "sendrawtransaction" + requestConfig.data.id = 'sendrawtransaction' + requestConfig.data.method = 'sendrawtransaction' requestConfig.data.params = [hex] const rpcResult = await BitboxHTTP(requestConfig) @@ -613,7 +613,7 @@ async function sendRawTransactionBulk(req, res, next) { return res.json({ error: msg }) } - wlogger.error(`Error in rawtransactions.ts/sendRawTransactionBulk().`, err) + wlogger.error('Error in rawtransactions.ts/sendRawTransactionBulk().', err) res.status(500) return res.json({ error: util.inspect(err) }) @@ -633,34 +633,34 @@ async function sendRawTransactionBulk(req, res, next) { * * */ -async function sendRawTransactionSingle(req, res, next) { +async function sendRawTransactionSingle (req, res, next) { try { const hex = req.params.hex // URL parameter // Reject if input is not an array or a string - if (typeof hex !== "string") { + if (typeof hex !== 'string') { res.status(400) - return res.json({ error: "hex must be a string" }) + return res.json({ error: 'hex must be a string' }) } // Validation - if (hex === "") { + if (hex === '') { res.status(400) return res.json({ - error: `Encountered empty hex` + error: 'Encountered empty hex' }) } const { BitboxHTTP, - username, - password, + // username, + // password, requestConfig } = routeUtils.setEnvVars() // RPC call - requestConfig.data.id = "sendrawtransaction" - requestConfig.data.method = "sendrawtransaction" + requestConfig.data.id = 'sendrawtransaction' + requestConfig.data.method = 'sendrawtransaction' requestConfig.data.params = [hex] const rpcResult = await BitboxHTTP(requestConfig) @@ -678,7 +678,7 @@ async function sendRawTransactionSingle(req, res, next) { } wlogger.error( - `Error in rawtransactions.ts/sendRawTransactionSingle().`, + 'Error in rawtransactions.ts/sendRawTransactionSingle().', err ) diff --git a/src/routes/v3/health-check.js b/src/routes/v3/health-check.js index 45bb1e7..28262fd 100644 --- a/src/routes/v3/health-check.js +++ b/src/routes/v3/health-check.js @@ -3,13 +3,13 @@ readiness. */ -"use strict" +'use strict' -const express = require("express") +const express = require('express') const router = express.Router() /* GET home page. */ -router.get("/", (req, res, next) => { +router.get('/', (req, res, next) => { res.json({ status: true }) }) diff --git a/src/routes/v3/ninsight.js b/src/routes/v3/ninsight.js index 97ee56c..1a40e66 100644 --- a/src/routes/v3/ninsight.js +++ b/src/routes/v3/ninsight.js @@ -2,30 +2,30 @@ A library for interacting with the Bitcoin.com ninsight (not Insight) indexer. */ -"use strict" +'use strict' -const express = require("express") -const axios = require("axios") -const routeUtils = require("./route-utils") -const wlogger = require("../../util/winston-logging") +const express = require('express') +// const axios = require('axios') +// const routeUtils = require('./route-utils') +// const wlogger = require('../../util/winston-logging') const router = express.Router() -const BCHJS = require("@chris.troutner/bch-js") -const bchjs = new BCHJS() +// const BCHJS = require('@chris.troutner/bch-js') +// const bchjs = new BCHJS() -let _this +// let _this class Ninsight { - constructor() { - _this = this + constructor () { + // _this = this this.router = router - this.router.get("/", this.root) + this.router.get('/', this.root) } - root(req, res, next) { - return res.json({ status: "ninsight" }) + root (req, res, next) { + return res.json({ status: 'ninsight' }) } } diff --git a/src/routes/v3/route-utils.js b/src/routes/v3/route-utils.js index 4f4f580..1a4cba1 100644 --- a/src/routes/v3/route-utils.js +++ b/src/routes/v3/route-utils.js @@ -2,15 +2,15 @@ A private library of utility functions used by several different routes. */ -"use strict" +'use strict' -const axios = require("axios") -const wlogger = require("../../util/winston-logging") +const axios = require('axios') +const wlogger = require('../../util/winston-logging') -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -const BCHJS = require("@chris.troutner/bch-js") +const BCHJS = require('@chris.troutner/bch-js') const bchjs = new BCHJS() module.exports = { @@ -25,7 +25,7 @@ module.exports = { // The array is then validated against freemium and pro-tier rate limiting // requirements. A boolean is returned to indicate if the array size if valid // or not. -function validateArraySize(req, array) { +function validateArraySize (req, array) { const FREEMIUM_INPUT_SIZE = 20 const PRO_INPUT_SIZE = 20 @@ -43,13 +43,13 @@ function validateArraySize(req, array) { // This prevent a common user-error issue that is easy to make: passing a // testnet address into rest.bitcoin.com or passing a mainnet address into // trest.bitcoin.com. -function validateNetwork(addr) { +function validateNetwork (addr) { try { const network = process.env.NETWORK // Return false if NETWORK is not defined. - if (!network || network === "") { - console.log(`Warning: NETWORK environment variable is not defined!`) + if (!network || network === '') { + console.log('Warning: NETWORK environment variable is not defined!') return false } @@ -59,21 +59,21 @@ function validateNetwork(addr) { // Return true if the network and address both match testnet const addrIsTest = bchjs.Address.isTestnetAddress(cashAddr) - if (network === "testnet" && addrIsTest) return true + if (network === 'testnet' && addrIsTest) return true // Return true if the network and address both match mainnet const addrIsMain = bchjs.Address.isMainnetAddress(cashAddr) - if (network === "mainnet" && addrIsMain) return true + if (network === 'mainnet' && addrIsMain) return true return false } catch (err) { - logger.error(`Error in validateNetwork()`) + wlogger.error('Error in validateNetwork()') return false } } // Dynamically set these based on env vars. Allows unit testing. -function setEnvVars() { +function setEnvVars () { const BitboxHTTP = axios.create({ baseURL: process.env.RPC_BASEURL, timeout: 15000 @@ -82,13 +82,13 @@ function setEnvVars() { const password = process.env.RPC_PASSWORD const requestConfig = { - method: "post", + method: 'post', auth: { username: username, password: password }, data: { - jsonrpc: "1.0" + jsonrpc: '1.0' } } @@ -96,9 +96,9 @@ function setEnvVars() { } // Axios options used when calling axios.post() to talk with a full node. -function getAxiosOptions() { +function getAxiosOptions () { return { - method: "post", + method: 'post', baseURL: process.env.RPC_BASEURL, timeout: 15000, auth: { @@ -106,7 +106,7 @@ function getAxiosOptions() { password: process.env.RPC_PASSWORD }, data: { - jsonrpc: "1.0" + jsonrpc: '1.0' } } } @@ -116,7 +116,7 @@ function getAxiosOptions() { // error messages. // Returns an object. If successful, obj.msg is a string. // If there is a failure, obj.msg is false. -function decodeError(err) { +function decodeError (err) { try { // Attempt to extract the full node error message. if ( @@ -124,39 +124,41 @@ function decodeError(err) { err.response.data && err.response.data.error && err.response.data.error.message - ) + ) { return { msg: err.response.data.error.message, status: 400 } + } // Attempt to extract the Insight error message - if (err.response && err.response.data) + if (err.response && err.response.data) { return { msg: err.response.data, status: err.response.status } + } // console.log(`err.message: ${err.message}`) // console.log(`err: `, err) // Attempt to detect a network connection error. - if (err.message && err.message.indexOf("ENOTFOUND") > -1) { + if (err.message && err.message.indexOf('ENOTFOUND') > -1) { return { msg: - "Network error: Could not communicate with full node or other external service.", + 'Network error: Could not communicate with full node or other external service.', status: 503 } } // Different kind of network error - if (err.message && err.message.indexOf("ENETUNREACH") > -1) { + if (err.message && err.message.indexOf('ENETUNREACH') > -1) { return { msg: - "Network error: Could not communicate with full node or other external service.", + 'Network error: Could not communicate with full node or other external service.', status: 503 } } // Different kind of network error - if (err.message && err.message.indexOf("EAI_AGAIN") > -1) { + if (err.message && err.message.indexOf('EAI_AGAIN') > -1) { return { msg: - "Network error: Could not communicate with full node or other external service.", + 'Network error: Could not communicate with full node or other external service.', status: 503 } } @@ -164,18 +166,18 @@ function decodeError(err) { // Axios timeout (aborted) error, or service is down (connection refused). if ( err.code && - (err.code === "ECONNABORTED" || err.code === "ECONNREFUSED") + (err.code === 'ECONNABORTED' || err.code === 'ECONNREFUSED') ) { return { msg: - "Network error: Could not communicate with full node or other external service.", + 'Network error: Could not communicate with full node or other external service.', status: 503 } } return { msg: false, status: 500 } } catch (err) { - wlogger.error(`unhandled error in route-utils.js/decodeError(): `, err) + wlogger.error('unhandled error in route-utils.js/decodeError(): ', err) return { msg: false, status: 500 } } } diff --git a/src/routes/v3/route-utils2.js b/src/routes/v3/route-utils2.js index f7315d3..88720bf 100644 --- a/src/routes/v3/route-utils2.js +++ b/src/routes/v3/route-utils2.js @@ -2,22 +2,22 @@ A private library of utility functions used by several different routes. */ -"use strict" +'use strict' -const axios = require("axios") -const wlogger = require("../../util/winston-logging") +const axios = require('axios') +const wlogger = require('../../util/winston-logging') -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -const BCHJS = require("@chris.troutner/bch-js") +const BCHJS = require('@chris.troutner/bch-js') const bchjs = new BCHJS() -let _this +// let _this class RouteUtils { - constructor() { - _this = this + constructor () { + // _this = this this.bchjs = bchjs this.axios = axios @@ -27,7 +27,7 @@ class RouteUtils { // The array is then validated against freemium and pro-tier rate limiting // requirements. A boolean is returned to indicate if the array size if valid // or not. - validateArraySize(req, array) { + validateArraySize (req, array) { const FREEMIUM_INPUT_SIZE = 20 const PRO_INPUT_SIZE = 20 @@ -41,9 +41,9 @@ class RouteUtils { } // Axios options used when calling axios.post() to talk with a full node. - getAxiosOptions() { + getAxiosOptions () { return { - method: "post", + method: 'post', baseURL: process.env.RPC_BASEURL, timeout: 15000, auth: { @@ -51,7 +51,7 @@ class RouteUtils { password: process.env.RPC_PASSWORD }, data: { - jsonrpc: "1.0" + jsonrpc: '1.0' } } } @@ -61,13 +61,13 @@ class RouteUtils { // This prevent a common user-error issue that is easy to make: passing a // testnet address into rest.bitcoin.com or passing a mainnet address into // trest.bitcoin.com. - validateNetwork(addr) { + validateNetwork (addr) { try { const network = process.env.NETWORK // Return false if NETWORK is not defined. - if (!network || network === "") { - console.log(`Warning: NETWORK environment variable is not defined!`) + if (!network || network === '') { + console.log('Warning: NETWORK environment variable is not defined!') return false } @@ -77,15 +77,15 @@ class RouteUtils { // Return true if the network and address both match testnet const addrIsTest = this.bchjs.Address.isTestnetAddress(cashAddr) - if (network === "testnet" && addrIsTest) return true + if (network === 'testnet' && addrIsTest) return true // Return true if the network and address both match mainnet const addrIsMain = this.bchjs.Address.isMainnetAddress(cashAddr) - if (network === "mainnet" && addrIsMain) return true + if (network === 'mainnet' && addrIsMain) return true return false } catch (err) { - logger.error(`Error in validateNetwork()`) + wlogger.error('Error in validateNetwork()') return false } } @@ -95,7 +95,7 @@ class RouteUtils { // error messages. // Returns an object. If successful, obj.msg is a string. // If there is a failure, obj.msg is false. - decodeError(err) { + decodeError (err) { try { // Attempt to extract the full node error message. if ( @@ -103,39 +103,41 @@ class RouteUtils { err.response.data && err.response.data.error && err.response.data.error.message - ) + ) { return { msg: err.response.data.error.message, status: 400 } + } // Attempt to extract the Insight error message - if (err.response && err.response.data) + if (err.response && err.response.data) { return { msg: err.response.data, status: err.response.status } + } // console.log(`err.message: ${err.message}`) // console.log(`err: `, err) // Attempt to detect a network connection error. - if (err.message && err.message.indexOf("ENOTFOUND") > -1) { + if (err.message && err.message.indexOf('ENOTFOUND') > -1) { return { msg: - "Network error: Could not communicate with full node or other external service.", + 'Network error: Could not communicate with full node or other external service.', status: 503 } } // Different kind of network error - if (err.message && err.message.indexOf("ENETUNREACH") > -1) { + if (err.message && err.message.indexOf('ENETUNREACH') > -1) { return { msg: - "Network error: Could not communicate with full node or other external service.", + 'Network error: Could not communicate with full node or other external service.', status: 503 } } // Different kind of network error - if (err.message && err.message.indexOf("EAI_AGAIN") > -1) { + if (err.message && err.message.indexOf('EAI_AGAIN') > -1) { return { msg: - "Network error: Could not communicate with full node or other external service.", + 'Network error: Could not communicate with full node or other external service.', status: 503 } } @@ -143,18 +145,18 @@ class RouteUtils { // Axios timeout (aborted) error, or service is down (connection refused). if ( err.code && - (err.code === "ECONNABORTED" || err.code === "ECONNREFUSED") + (err.code === 'ECONNABORTED' || err.code === 'ECONNREFUSED') ) { return { msg: - "Network error: Could not communicate with full node or other external service.", + 'Network error: Could not communicate with full node or other external service.', status: 503 } } return { msg: false, status: 500 } } catch (err) { - wlogger.error(`unhandled error in route-utils.js/decodeError(): `, err) + wlogger.error('unhandled error in route-utils.js/decodeError(): ', err) return { msg: false, status: 500 } } } diff --git a/src/routes/v3/slp.js b/src/routes/v3/slp.js index c3eb6eb..0bc7812 100644 --- a/src/routes/v3/slp.js +++ b/src/routes/v3/slp.js @@ -1,69 +1,70 @@ -"use strict" +'use strict' -const express = require("express") +const express = require('express') const router = express.Router() -const axios = require("axios") -const BigNumber = require("bignumber.js") +const axios = require('axios') +const BigNumber = require('bignumber.js') -const routeUtils = require("./route-utils") -const strftime = require("strftime") -const wlogger = require("../../util/winston-logging") +const routeUtils = require('./route-utils') +// const strftime = require('strftime') +const wlogger = require('../../util/winston-logging') -const BCHJS = require("@chris.troutner/bch-js") +const BCHJS = require('@chris.troutner/bch-js') const bchjs = new BCHJS() // Used to convert error messages to strings, to safely pass to users. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 5 } // Setup JSON RPC -const BitboxHTTP = axios.create({ - baseURL: process.env.RPC_BASEURL -}) -const username = process.env.RPC_USERNAME -const password = process.env.RPC_PASSWORD +// const BitboxHTTP = axios.create({ +// baseURL: process.env.RPC_BASEURL +// }) +// const username = process.env.RPC_USERNAME +// const password = process.env.RPC_PASSWORD // Determine the Access password for a private instance of SLPDB. // https://gist.github.com/christroutner/fc717ca704dec3dded8b52fae387eab2 -const SLPDB_PASS = process.env.SLPDB_PASS ? process.env.SLPDB_PASS : "BITBOX" +const SLPDB_PASS = process.env.SLPDB_PASS ? process.env.SLPDB_PASS : 'BITBOX' // const transactions = require("./insight/transaction") -const rawtransactions = require("./full-node/rawtransactions") +const rawtransactions = require('./full-node/rawtransactions') // Setup REST and TREST URLs used by slpjs // Dev note: this allows for unit tests to mock the URL. -if (!process.env.REST_URL) process.env.REST_URL = `https://rest.bitcoin.com/v2/` -if (!process.env.TREST_URL) - process.env.TREST_URL = `https://trest.bitcoin.com/v2/` - -router.get("/", root) -router.get("/list", list) -router.get("/list/:tokenId", listSingleToken) -router.post("/list", listBulkToken) -router.get("/balancesForAddress/:address", balancesForAddress) -router.post("/balancesForAddress", balancesForAddressBulk) -router.get("/balancesForToken/:tokenId", balancesForTokenSingle) -router.get("/balance/:address/:tokenId", balancesForAddressByTokenID) -router.get("/convert/:address", convertAddressSingle) -router.post("/convert", convertAddressBulk) -router.post("/validateTxid", validateBulk) -router.get("/validateTxid/:txid", validateSingle) -router.get("/txDetails/:txid", txDetails) -router.get("/tokenStats/:tokenId", tokenStats) -router.get("/transactions/:tokenId/:address", txsTokenIdAddressSingle) - -const requestConfig = { - method: "post", - auth: { - username: username, - password: password - }, - data: { - jsonrpc: "1.0" - } +if (!process.env.REST_URL) process.env.REST_URL = 'https://rest.bitcoin.com/v2/' +if (!process.env.TREST_URL) { + process.env.TREST_URL = 'https://trest.bitcoin.com/v2/' } -function formatTokenOutput(token) { +router.get('/', root) +router.get('/list', list) +router.get('/list/:tokenId', listSingleToken) +router.post('/list', listBulkToken) +router.get('/balancesForAddress/:address', balancesForAddress) +router.post('/balancesForAddress', balancesForAddressBulk) +router.get('/balancesForToken/:tokenId', balancesForTokenSingle) +router.get('/balance/:address/:tokenId', balancesForAddressByTokenID) +router.get('/convert/:address', convertAddressSingle) +router.post('/convert', convertAddressBulk) +router.post('/validateTxid', validateBulk) +router.get('/validateTxid/:txid', validateSingle) +router.get('/txDetails/:txid', txDetails) +router.get('/tokenStats/:tokenId', tokenStats) +router.get('/transactions/:tokenId/:address', txsTokenIdAddressSingle) + +// const requestConfig = { +// method: 'post', +// auth: { +// username: username, +// password: password +// }, +// data: { +// jsonrpc: '1.0' +// } +// } + +function formatTokenOutput (token) { token.tokenDetails.id = token.tokenDetails.tokenIdHex delete token.tokenDetails.tokenIdHex token.tokenDetails.documentHash = token.tokenDetails.documentSha256Hex @@ -98,8 +99,8 @@ function formatTokenOutput(token) { return token } -function root(req, res, next) { - return res.json({ status: "slp" }) +function root (req, res, next) { + return res.json({ status: 'slp' }) } /** @@ -114,23 +115,23 @@ function root(req, res, next) { * * */ -async function list(req, res, next) { +async function list (req, res, next) { try { const query = { v: 3, q: { - db: ["t"], + db: ['t'], find: { $query: {} }, project: { tokenDetails: 1, tokenStats: 1, _id: 0 }, - sort: { "tokenStats.block_created": -1 }, + sort: { 'tokenStats.block_created': -1 }, limit: 10000 } } const s = JSON.stringify(query) - const b64 = Buffer.from(s).toString("base64") + const b64 = Buffer.from(s).toString('base64') const url = `${process.env.SLPDB_URL}q/${b64}` // Get data from SLPDB. @@ -148,7 +149,7 @@ async function list(req, res, next) { res.status(200) return res.json(formattedTokens) } catch (err) { - wlogger.error(`Error in slp.ts/list().`, err) + wlogger.error('Error in slp.ts/list().', err) const { msg, status } = routeUtils.decodeError(err) if (msg) { @@ -172,13 +173,13 @@ async function list(req, res, next) { * * */ -async function listSingleToken(req, res, next) { +async function listSingleToken (req, res, next) { try { const tokenId = req.params.tokenId - if (!tokenId || tokenId === "") { + if (!tokenId || tokenId === '') { res.status(400) - return res.json({ error: "tokenId can not be empty" }) + return res.json({ error: 'tokenId can not be empty' }) } const t = await lookupToken(tokenId) @@ -186,7 +187,7 @@ async function listSingleToken(req, res, next) { res.status(200) return res.json(t) } catch (err) { - wlogger.error(`Error in slp.ts/listSingleToken().`, err) + wlogger.error('Error in slp.ts/listSingleToken().', err) const { msg, status } = routeUtils.decodeError(err) if (msg) { @@ -210,7 +211,7 @@ async function listSingleToken(req, res, next) { * * */ -async function listBulkToken(req, res, next) { +async function listBulkToken (req, res, next) { try { const tokenIds = req.body.tokenIds @@ -218,7 +219,7 @@ async function listBulkToken(req, res, next) { if (!Array.isArray(tokenIds)) { res.status(400) return res.json({ - error: "tokenIds needs to be an array. Use GET for single tokenId." + error: 'tokenIds needs to be an array. Use GET for single tokenId.' }) } @@ -226,27 +227,27 @@ async function listBulkToken(req, res, next) { if (!routeUtils.validateArraySize(req, tokenIds)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: `Array too large.` + error: 'Array too large.' }) } const query = { v: 3, q: { - db: ["t"], + db: ['t'], find: { - "tokenDetails.tokenIdHex": { + 'tokenDetails.tokenIdHex': { $in: tokenIds } }, project: { tokenDetails: 1, tokenStats: 1, _id: 0 }, - sort: { "tokenStats.block_created": -1 }, + sort: { 'tokenStats.block_created': -1 }, limit: 10000 } } const s = JSON.stringify(query) - const b64 = Buffer.from(s).toString("base64") + const b64 = Buffer.from(s).toString('base64') const url = `${process.env.SLPDB_URL}q/${b64}` const tokenRes = await axios.get(url) @@ -274,7 +275,7 @@ async function listBulkToken(req, res, next) { res.status(200) return res.json(formattedTokens) } catch (err) { - wlogger.error(`Error in slp.ts/listBulkToken().`, err) + wlogger.error('Error in slp.ts/listBulkToken().', err) const { msg, status } = routeUtils.decodeError(err) if (msg) { @@ -286,15 +287,15 @@ async function listBulkToken(req, res, next) { } } -async function lookupToken(tokenId) { +async function lookupToken (tokenId) { try { const query = { v: 3, q: { - db: ["t"], + db: ['t'], find: { $query: { - "tokenDetails.tokenIdHex": tokenId + 'tokenDetails.tokenIdHex': tokenId } }, project: { tokenDetails: 1, tokenStats: 1, _id: 0 }, @@ -303,16 +304,16 @@ async function lookupToken(tokenId) { } const s = JSON.stringify(query) - const b64 = Buffer.from(s).toString("base64") + const b64 = Buffer.from(s).toString('base64') const url = `${process.env.SLPDB_URL}q/${b64}` // console.log(`url: ${url}`) const tokenRes = await axios.get(url) - //console.log(`tokenRes.data: ${util.inspect(tokenRes.data,null,2)}`) - //console.log( + // console.log(`tokenRes.data: ${util.inspect(tokenRes.data,null,2)}`) + // console.log( // `tokenRes.data.t[0]: ${util.inspect(tokenRes.data.t[0], null, 2)}` - //) + // ) const formattedTokens = [] @@ -331,14 +332,14 @@ async function lookupToken(tokenId) { // If token could not be found. if (t === undefined) { t = { - id: "not found" + id: 'not found' } } return t } catch (err) { - wlogger.error(`Error in slp.ts/lookupToken().`, err) - //console.log(`Error in slp.ts/lookupToken()`) + wlogger.error('Error in slp.ts/lookupToken().', err) + // console.log(`Error in slp.ts/lookupToken()`) throw err } } @@ -356,18 +357,18 @@ async function lookupToken(tokenId) { * */ // Retrieve token balances for all tokens for a single address. -async function balancesForAddress(req, res, next) { +async function balancesForAddress (req, res, next) { try { // Validate the input data. const address = req.params.address - if (!address || address === "") { + if (!address || address === '') { res.status(400) - return res.json({ error: "address can not be empty" }) + return res.json({ error: 'address can not be empty' }) } // Ensure the input is a valid BCH address. try { - const cash = bchjs.SLP.Address.toCashAddress(address) + bchjs.SLP.Address.toCashAddress(address) } catch (err) { res.status(400) return res.json({ @@ -381,14 +382,15 @@ async function balancesForAddress(req, res, next) { if (!networkIsValid) { res.status(400) return res.json({ - error: `Invalid network. Trying to use a testnet address on mainnet, or vice versa.` + error: + 'Invalid network. Trying to use a testnet address on mainnet, or vice versa.' }) } const query = { v: 3, q: { - db: ["a"], + db: ['a'], find: { address: bchjs.SLP.Address.toSLPAddress(address), token_balance: { $gte: 0 } @@ -398,7 +400,7 @@ async function balancesForAddress(req, res, next) { } const s = JSON.stringify(query) - const b64 = Buffer.from(s).toString("base64") + const b64 = Buffer.from(s).toString('base64') const url = `${process.env.SLPDB_URL}q/${b64}` const tokenRes = await axios.get(url) @@ -419,50 +421,47 @@ async function balancesForAddress(req, res, next) { }) const promises = tokenIds.map(async tokenId => { - try { - const query2 = { - v: 3, - q: { - db: ["t"], - find: { - $query: { - "tokenDetails.tokenIdHex": tokenId - } - }, - project: { - "tokenDetails.decimals": 1, - "tokenDetails.tokenIdHex": 1, - _id: 0 - }, - limit: 1000 - } + const query2 = { + v: 3, + q: { + db: ['t'], + find: { + $query: { + 'tokenDetails.tokenIdHex': tokenId + } + }, + project: { + 'tokenDetails.decimals': 1, + 'tokenDetails.tokenIdHex': 1, + _id: 0 + }, + limit: 1000 } - - const s2 = JSON.stringify(query2) - const b642 = Buffer.from(s2).toString("base64") - const url2 = `${process.env.SLPDB_URL}q/${b642}` - - const tokenRes2 = await axios.get(url2) - return tokenRes2.data - } catch (err) { - throw err } + + const s2 = JSON.stringify(query2) + const b642 = Buffer.from(s2).toString('base64') + const url2 = `${process.env.SLPDB_URL}q/${b642}` + + const tokenRes2 = await axios.get(url2) + return tokenRes2.data }) const details = await axios.all(promises) tokenRes.data.a = tokenRes.data.a.map(token => { details.forEach(detail => { - if (detail.t[0].tokenDetails.tokenIdHex === token.tokenId) + if (detail.t[0].tokenDetails.tokenIdHex === token.tokenId) { token.decimalCount = detail.t[0].tokenDetails.decimals + } }) return token }) return res.json(tokenRes.data.a) } - return res.json("No balance for this address") + return res.json('No balance for this address') } catch (err) { - wlogger.error(`Error in slp.ts/balancesForAddress().`, err) + wlogger.error('Error in slp.ts/balancesForAddress().', err) // Decode the error message. const { msg, status } = routeUtils.decodeError(err) @@ -490,26 +489,26 @@ async function balancesForAddress(req, res, next) { * * */ -async function balancesForAddressBulk(req, res, next) { +async function balancesForAddressBulk (req, res, next) { try { const addresses = req.body.addresses // Reject if addresses is not an array. if (!Array.isArray(addresses)) { res.status(400) - return res.json({ error: "addresses needs to be an array" }) + return res.json({ error: 'addresses needs to be an array' }) } // Enforce array size rate limits if (!routeUtils.validateArraySize(req, addresses)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: `Array too large.` + error: 'Array too large.' }) } wlogger.debug( - `Executing slp/balancesForAddresss with these addresses: `, + 'Executing slp/balancesForAddresss with these addresses: ', addresses ) @@ -518,9 +517,9 @@ async function balancesForAddressBulk(req, res, next) { const address = addresses[i] // Validate the input data. - if (!address || address === "") { + if (!address || address === '') { res.status(400) - return res.json({ error: "address can not be empty" }) + return res.json({ error: 'address can not be empty' }) } // Ensure the input is a valid BCH address. @@ -539,7 +538,8 @@ async function balancesForAddressBulk(req, res, next) { if (!networkIsValid) { res.status(400) return res.json({ - error: `Invalid network. Trying to use a testnet address on mainnet, or vice versa.` + error: + 'Invalid network. Trying to use a testnet address on mainnet, or vice versa.' }) } } @@ -547,90 +547,83 @@ async function balancesForAddressBulk(req, res, next) { // Collect an array of promises, one for each request to slpserve. // This is a nested array of promises. const balancesPromises = addresses.map(async address => { - try { - const query = { - v: 3, - q: { - db: ["a"], - find: { - address: bchjs.SLP.Address.toSLPAddress(address), - token_balance: { $gte: 0 } - }, - limit: 10000 - } + const query = { + v: 3, + q: { + db: ['a'], + find: { + address: bchjs.SLP.Address.toSLPAddress(address), + token_balance: { $gte: 0 } + }, + limit: 10000 } + } - const s = JSON.stringify(query) - const b64 = Buffer.from(s).toString("base64") - const url = `${process.env.SLPDB_URL}q/${b64}` + const s = JSON.stringify(query) + const b64 = Buffer.from(s).toString('base64') + const url = `${process.env.SLPDB_URL}q/${b64}` - const tokenRes = await axios.get(url) + const tokenRes = await axios.get(url) - const tokenIds = [] - - if (tokenRes.data.a.length > 0) { - tokenRes.data.a = tokenRes.data.a.map(token => { - token.tokenId = token.tokenDetails.tokenIdHex - tokenIds.push(token.tokenId) - token.balance = parseFloat(token.token_balance) - token.balanceString = token.token_balance - token.slpAddress = token.address - delete token.tokenDetails - delete token.satoshis_balance - delete token.token_balance - delete token._id - delete token.address - return token - }) - } - - // Collect another array of promises. - const promises = tokenIds.map(async tokenId => { - try { - const query2 = { - v: 3, - q: { - db: ["t"], - find: { - $query: { - "tokenDetails.tokenIdHex": tokenId - } - }, - project: { - "tokenDetails.decimals": 1, - "tokenDetails.tokenIdHex": 1, - _id: 0 - }, - limit: 1000 - } - } - - const s2 = JSON.stringify(query2) - const b642 = Buffer.from(s2).toString("base64") - const url2 = `${process.env.SLPDB_URL}q/${b642}` - - const tokenRes2 = await axios.get(url2) - return tokenRes2.data - } catch (err) { - throw err - } - }) - - // Wait for all the promises to resolve. - const details = await axios.all(promises) + const tokenIds = [] + if (tokenRes.data.a.length > 0) { tokenRes.data.a = tokenRes.data.a.map(token => { - details.forEach(detail => { - if (detail.t[0].tokenDetails.tokenIdHex === token.tokenId) - token.decimalCount = detail.t[0].tokenDetails.decimals - }) + token.tokenId = token.tokenDetails.tokenIdHex + tokenIds.push(token.tokenId) + token.balance = parseFloat(token.token_balance) + token.balanceString = token.token_balance + token.slpAddress = token.address + delete token.tokenDetails + delete token.satoshis_balance + delete token.token_balance + delete token._id + delete token.address return token }) - - return tokenRes.data.a - } catch (err) { - throw err } + + // Collect another array of promises. + const promises = tokenIds.map(async tokenId => { + const query2 = { + v: 3, + q: { + db: ['t'], + find: { + $query: { + 'tokenDetails.tokenIdHex': tokenId + } + }, + project: { + 'tokenDetails.decimals': 1, + 'tokenDetails.tokenIdHex': 1, + _id: 0 + }, + limit: 1000 + } + } + + const s2 = JSON.stringify(query2) + const b642 = Buffer.from(s2).toString('base64') + const url2 = `${process.env.SLPDB_URL}q/${b642}` + + const tokenRes2 = await axios.get(url2) + return tokenRes2.data + }) + + // Wait for all the promises to resolve. + const details = await axios.all(promises) + + tokenRes.data.a = tokenRes.data.a.map(token => { + details.forEach(detail => { + if (detail.t[0].tokenDetails.tokenIdHex === token.tokenId) { + token.decimalCount = detail.t[0].tokenDetails.decimals + } + }) + return token + }) + + return tokenRes.data.a }) // Wait for all the promises to resolve. @@ -638,7 +631,7 @@ async function balancesForAddressBulk(req, res, next) { return res.json(axiosResult) } catch (err) { - wlogger.error(`Error in slp.js/balancesForAddressBulk().`, err) + wlogger.error('Error in slp.js/balancesForAddressBulk().', err) // Decode the error message. const { msg, status } = routeUtils.decodeError(err) @@ -667,20 +660,20 @@ async function balancesForAddressBulk(req, res, next) { * */ // Retrieve token balances for all addresses by single tokenId. -async function balancesForTokenSingle(req, res, next) { +async function balancesForTokenSingle (req, res, next) { try { // Validate the input data. const tokenId = req.params.tokenId - if (!tokenId || tokenId === "") { + if (!tokenId || tokenId === '') { res.status(400) - return res.json({ error: "tokenId can not be empty" }) + return res.json({ error: 'tokenId can not be empty' }) } const query = { v: 3, q: { find: { - "tokenDetails.tokenIdHex": tokenId, + 'tokenDetails.tokenIdHex': tokenId, token_balance: { $gte: 0 } }, limit: 10000, @@ -689,7 +682,7 @@ async function balancesForTokenSingle(req, res, next) { } const s = JSON.stringify(query) - const b64 = Buffer.from(s).toString("base64") + const b64 = Buffer.from(s).toString('base64') const url = `${process.env.SLPDB_URL}q/${b64}` // Get data from SLPDB. @@ -705,7 +698,7 @@ async function balancesForTokenSingle(req, res, next) { }) return res.json(resBalances) } catch (err) { - wlogger.error(`Error in slp.ts/balancesForTokenSingle().`, err) + wlogger.error('Error in slp.ts/balancesForTokenSingle().', err) // Decode the error message. const { msg, status } = routeUtils.decodeError(err) @@ -734,24 +727,24 @@ async function balancesForTokenSingle(req, res, next) { * */ // Retrieve token balances for a single token class, for a single address. -async function balancesForAddressByTokenID(req, res, next) { +async function balancesForAddressByTokenID (req, res, next) { try { // Validate input data. const address = req.params.address - if (!address || address === "") { + if (!address || address === '') { res.status(400) - return res.json({ error: "address can not be empty" }) + return res.json({ error: 'address can not be empty' }) } const tokenId = req.params.tokenId - if (!tokenId || tokenId === "") { + if (!tokenId || tokenId === '') { res.status(400) - return res.json({ error: "tokenId can not be empty" }) + return res.json({ error: 'tokenId can not be empty' }) } // Ensure the input is a valid BCH address. try { - const cash = utils.toCashAddress(address) + bchjs.SLP.Address.toCashAddress(address) } catch (err) { res.status(400) return res.json({ @@ -760,22 +753,23 @@ async function balancesForAddressByTokenID(req, res, next) { } // Prevent a common user error. Ensure they are using the correct network address. - const cashAddr = utils.toCashAddress(address) + const cashAddr = bchjs.SLP.Address.toCashAddress(address) const networkIsValid = routeUtils.validateNetwork(cashAddr) if (!networkIsValid) { res.status(400) return res.json({ - error: `Invalid network. Trying to use a testnet address on mainnet, or vice versa.` + error: + 'Invalid network. Trying to use a testnet address on mainnet, or vice versa.' }) } // Convert input to an simpleledger: address. - const slpAddr = utils.toSlpAddress(req.params.address) + const slpAddr = bchjs.SLP.Address.toSlpAddress(req.params.address) const query = { v: 3, q: { - db: ["a"], + db: ['a'], find: { address: slpAddr, token_balance: { $gte: 0 } @@ -785,7 +779,7 @@ async function balancesForAddressByTokenID(req, res, next) { } const s = JSON.stringify(query) - const b64 = Buffer.from(s).toString("base64") + const b64 = Buffer.from(s).toString('base64') const url = `${process.env.SLPDB_URL}q/${b64}` // Get data from SLPDB. @@ -814,7 +808,7 @@ async function balancesForAddressByTokenID(req, res, next) { } return res.json(resVal) } catch (err) { - wlogger.error(`Error in slp.ts/balancesForAddressByTokenID().`, err) + wlogger.error('Error in slp.ts/balancesForAddressByTokenID().', err) // Decode the error message. const { msg, status } = routeUtils.decodeError(err) @@ -842,31 +836,31 @@ async function balancesForAddressByTokenID(req, res, next) { * * */ -async function convertAddressSingle(req, res, next) { +async function convertAddressSingle (req, res, next) { try { const address = req.params.address // Validate input - if (!address || address === "") { + if (!address || address === '') { res.status(400) - return res.json({ error: "address can not be empty" }) + return res.json({ error: 'address can not be empty' }) } - const slpAddr = SLP.Address.toSLPAddress(address) + const slpAddr = bchjs.SLP.Address.toSLPAddress(address) const obj = { - slpAddress: "", - cashAddress: "", - legacyAddress: "" + slpAddress: '', + cashAddress: '', + legacyAddress: '' } obj.slpAddress = slpAddr - obj.cashAddress = SLP.Address.toCashAddress(slpAddr) - obj.legacyAddress = SLP.Address.toLegacyAddress(obj.cashAddress) + obj.cashAddress = bchjs.SLP.Address.toCashAddress(slpAddr) + obj.legacyAddress = bchjs.SLP.Address.toLegacyAddress(obj.cashAddress) res.status(200) return res.json(obj) } catch (err) { - wlogger.error(`Error in slp.ts/convertAddressSingle().`, err) + wlogger.error('Error in slp.ts/convertAddressSingle().', err) const { msg, status } = routeUtils.decodeError(err) if (msg) { @@ -892,14 +886,14 @@ async function convertAddressSingle(req, res, next) { * * */ -async function convertAddressBulk(req, res, next) { +async function convertAddressBulk (req, res, next) { const addresses = req.body.addresses // Reject if hashes is not an array. if (!Array.isArray(addresses)) { res.status(400) return res.json({ - error: "addresses needs to be an array. Use GET for single address." + error: 'addresses needs to be an array. Use GET for single address.' }) } @@ -907,7 +901,7 @@ async function convertAddressBulk(req, res, next) { if (!routeUtils.validateArraySize(req, addresses)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: `Array too large.` + error: 'Array too large.' }) } @@ -917,21 +911,21 @@ async function convertAddressBulk(req, res, next) { const address = addresses[i] // Validate input - if (!address || address === "") { + if (!address || address === '') { res.status(400) - return res.json({ error: "address can not be empty" }) + return res.json({ error: 'address can not be empty' }) } - const slpAddr = SLP.Address.toSLPAddress(address) + const slpAddr = bchjs.SLP.Address.toSLPAddress(address) const obj = { - slpAddress: "", - cashAddress: "", - legacyAddress: "" + slpAddress: '', + cashAddress: '', + legacyAddress: '' } obj.slpAddress = slpAddr - obj.cashAddress = SLP.Address.toCashAddress(slpAddr) - obj.legacyAddress = SLP.Address.toLegacyAddress(obj.cashAddress) + obj.cashAddress = bchjs.SLP.Address.toCashAddress(slpAddr) + obj.legacyAddress = bchjs.SLP.Address.toLegacyAddress(obj.cashAddress) convertedAddresses.push(obj) } @@ -952,39 +946,39 @@ async function convertAddressBulk(req, res, next) { * * */ -async function validateBulk(req, res, next) { +async function validateBulk (req, res, next) { try { const txids = req.body.txids // Reject if txids is not an array. if (!Array.isArray(txids)) { res.status(400) - return res.json({ error: "txids needs to be an array" }) + return res.json({ error: 'txids needs to be an array' }) } // Enforce array size rate limits if (!routeUtils.validateArraySize(req, txids)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: `Array too large.` + error: 'Array too large.' }) } - wlogger.debug(`Executing slp/validate with these txids: `, txids) + wlogger.debug('Executing slp/validate with these txids: ', txids) const query = { v: 3, q: { - db: ["c", "u"], + db: ['c', 'u'], find: { - "tx.h": { $in: txids } + 'tx.h': { $in: txids } }, limit: 300, - project: { "slp.valid": 1, "tx.h": 1, "slp.invalidReason": 1 } + project: { 'slp.valid': 1, 'tx.h': 1, 'slp.invalidReason': 1 } } } const s = JSON.stringify(query) - const b64 = Buffer.from(s).toString("base64") + const b64 = Buffer.from(s).toString('base64') const url = `${process.env.SLPDB_URL}q/${b64}` const options = generateCredentials() @@ -1009,8 +1003,9 @@ async function validateBulk(req, res, next) { } // If the txid is invalid, add the reason it's invalid. - if (!validationResult.valid) + if (!validationResult.valid) { validationResult.invalidReason = token.slp.invalidReason + } formattedTokens.push(validationResult) }) @@ -1047,7 +1042,7 @@ async function validateBulk(req, res, next) { res.status(200) return res.json(formattedTokens) } catch (err) { - wlogger.error(`Error in slp.ts/validateBulk().`, err) + wlogger.error('Error in slp.ts/validateBulk().', err) // Attempt to decode the error message. const { msg, status } = routeUtils.decodeError(err) @@ -1073,34 +1068,34 @@ async function validateBulk(req, res, next) { * * */ -async function validateSingle(req, res, next) { +async function validateSingle (req, res, next) { try { const txid = req.params.txid // Validate input - if (!txid || txid === "") { + if (!txid || txid === '') { res.status(400) - return res.json({ error: "txid can not be empty" }) + return res.json({ error: 'txid can not be empty' }) } - wlogger.debug(`Executing slp/validate/:txid with this txid: `, txid) + wlogger.debug('Executing slp/validate/:txid with this txid: ', txid) const query = { v: 3, q: { - db: ["c", "u"], + db: ['c', 'u'], find: { - "tx.h": txid + 'tx.h': txid }, limit: 300, - project: { "slp.valid": 1, "tx.h": 1, "slp.invalidReason": 1 } + project: { 'slp.valid': 1, 'tx.h': 1, 'slp.invalidReason': 1 } } } const options = generateCredentials() const s = JSON.stringify(query) - const b64 = Buffer.from(s).toString("base64") + const b64 = Buffer.from(s).toString('base64') const url = `${process.env.SLPDB_URL}q/${b64}` // Get data from SLPDB. @@ -1123,9 +1118,9 @@ async function validateSingle(req, res, next) { } res.status(200) - return res.json(tmp) + return res.json(result) } catch (err) { - wlogger.error(`Error in slp.ts/validateSingle().`, err) + wlogger.error('Error in slp.ts/validateSingle().', err) // Attempt to decode the error message. const { msg, status } = routeUtils.decodeError(err) @@ -1140,10 +1135,10 @@ async function validateSingle(req, res, next) { } // Returns a Boolean if the input TXID is a valid SLP TXID. -async function isValidSlpTxid(txid) { - const isValid = await slpValidator.isValidSlpTxid(txid) - return isValid -} +// async function isValidSlpTxid (txid) { +// const isValid = await slpValidator.isValidSlpTxid(txid) +// return isValid +// } /** * @api {get} /slp/txDetails/{txid} SLP transaction details. @@ -1157,33 +1152,33 @@ async function isValidSlpTxid(txid) { * * */ -async function txDetails(req, res, next) { +async function txDetails (req, res, next) { try { // Validate input parameter const txid = req.params.txid - if (!txid || txid === "") { + if (!txid || txid === '') { res.status(400) - return res.json({ error: "txid can not be empty" }) + return res.json({ error: 'txid can not be empty' }) } if (txid.length !== 64) { res.status(400) - return res.json({ error: "This is not a txid" }) + return res.json({ error: 'This is not a txid' }) } const query = { v: 3, - db: ["g"], + db: ['g'], q: { find: { - "tx.h": txid + 'tx.h': txid }, limit: 300 } } const s = JSON.stringify(query) - const b64 = Buffer.from(s).toString("base64") + const b64 = Buffer.from(s).toString('base64') const url = `${process.env.SLPDB_URL}q/${b64}` const options = generateCredentials() @@ -1194,7 +1189,7 @@ async function txDetails(req, res, next) { if (tokenRes.data.c.length === 0) { res.status(404) - return res.json({ error: "TXID not found" }) + return res.json({ error: 'TXID not found' }) } // Format the returned data to an object. @@ -1215,7 +1210,7 @@ async function txDetails(req, res, next) { res.status(200) return res.json(response) } catch (err) { - wlogger.error(`Error in slp.ts/txDetails().`, err) + wlogger.error('Error in slp.ts/txDetails().', err) // Attempt to decode the error message. const { msg, status } = routeUtils.decodeError(err) @@ -1225,9 +1220,9 @@ async function txDetails(req, res, next) { } // Handle corner case of mis-typted txid - if (err.error && err.error.indexOf("Not found") > -1) { + if (err.error && err.error.indexOf('Not found') > -1) { res.status(400) - return res.json({ error: "TXID not found" }) + return res.json({ error: 'TXID not found' }) } res.status(500) @@ -1247,21 +1242,21 @@ async function txDetails(req, res, next) { * * */ -async function tokenStats(req, res, next) { +async function tokenStats (req, res, next) { const tokenId = req.params.tokenId - if (!tokenId || tokenId === "") { + if (!tokenId || tokenId === '') { res.status(400) - return res.json({ error: "tokenId can not be empty" }) + return res.json({ error: 'tokenId can not be empty' }) } try { const query = { v: 3, q: { - db: ["t"], + db: ['t'], find: { $query: { - "tokenDetails.tokenIdHex": tokenId + 'tokenDetails.tokenIdHex': tokenId } }, project: { tokenDetails: 1, tokenStats: 1, _id: 0 }, @@ -1270,7 +1265,7 @@ async function tokenStats(req, res, next) { } const s = JSON.stringify(query) - const b64 = Buffer.from(s).toString("base64") + const b64 = Buffer.from(s).toString('base64') const url = `${process.env.SLPDB_URL}q/${b64}` // Get data from BitDB. @@ -1288,7 +1283,7 @@ async function tokenStats(req, res, next) { res.status(200) return res.json(formattedTokens[0]) } catch (err) { - wlogger.error(`Error in slp.ts/tokenStats().`, err) + wlogger.error('Error in slp.ts/tokenStats().', err) const { msg, status } = routeUtils.decodeError(err) if (msg) { @@ -1313,59 +1308,59 @@ async function tokenStats(req, res, next) { * */ // Retrieve transactions by tokenId and address. -async function txsTokenIdAddressSingle(req, res, next) { +async function txsTokenIdAddressSingle (req, res, next) { try { // Validate the input data. const tokenId = req.params.tokenId - if (!tokenId || tokenId === "") { + if (!tokenId || tokenId === '') { res.status(400) - return res.json({ error: "tokenId can not be empty" }) + return res.json({ error: 'tokenId can not be empty' }) } const address = req.params.address - if (!address || address === "") { + if (!address || address === '') { res.status(400) - return res.json({ error: "address can not be empty" }) + return res.json({ error: 'address can not be empty' }) } const query = { v: 3, q: { find: { - db: ["c", "u"], + db: ['c', 'u'], $query: { $or: [ { - "in.e.a": address + 'in.e.a': address }, { - "out.e.a": address + 'out.e.a': address } ], - "slp.detail.tokenIdHex": tokenId + 'slp.detail.tokenIdHex': tokenId }, $orderby: { - "blk.i": -1 + 'blk.i': -1 } }, limit: 100 }, r: { - f: "[.[] | { txid: .tx.h, tokenDetails: .slp } ]" + f: '[.[] | { txid: .tx.h, tokenDetails: .slp } ]' } } const s = JSON.stringify(query) - const b64 = Buffer.from(s).toString("base64") + const b64 = Buffer.from(s).toString('base64') const url = `${process.env.SLPDB_URL}q/${b64}` // Get data from SLPDB. const tokenRes = await axios.get(url) - //console.log(`tokenRes.data: ${JSON.stringify(tokenRes.data,null,2)}`) + // console.log(`tokenRes.data: ${JSON.stringify(tokenRes.data,null,2)}`) return res.json(tokenRes.data.c) } catch (err) { - wlogger.error(`Error in slp.ts/txsTokenIdAddressSingle().`, err) + wlogger.error('Error in slp.ts/txsTokenIdAddressSingle().', err) // Decode the error message. const { msg, status } = routeUtils.decodeError(err) @@ -1382,12 +1377,12 @@ async function txsTokenIdAddressSingle(req, res, next) { } // Generates a Basic Authorization header for slpserve. -function generateCredentials() { +function generateCredentials () { // Generate the Basic Authentication header for a private instance of SLPDB. - const username = "BITBOX" + const username = 'BITBOX' const password = SLPDB_PASS const combined = `${username}:${password}` - var base64Credential = Buffer.from(combined).toString("base64") + var base64Credential = Buffer.from(combined).toString('base64') var readyCredential = `Basic ${base64Credential}` const options = { @@ -1400,7 +1395,7 @@ function generateCredentials() { } // Format the response from SLPDB into an object. -async function formatToRestObject(slpDBFormat) { +async function formatToRestObject (slpDBFormat) { BigNumber.set({ DECIMAL_PLACES: 8 }) // console.log(`slpDBFormat.data: ${JSON.stringify(slpDBFormat.data, null, 2)}`) @@ -1409,12 +1404,12 @@ async function formatToRestObject(slpDBFormat) { ? slpDBFormat.data.u[0] : slpDBFormat.data.c[0] - const inputs = transaction.in + // const inputs = transaction.in - const outputs = transaction.out + // const outputs = transaction.out const tokenOutputs = transaction.slp.detail.outputs - const sendOutputs = ["0"] + const sendOutputs = ['0'] tokenOutputs.map(x => { const string = parseFloat(x.amount) * 100000000 sendOutputs.push(string.toString()) @@ -1446,7 +1441,7 @@ module.exports = { convertAddressSingle, convertAddressBulk, validateBulk, - isValidSlpTxid, + // isValidSlpTxid, txDetails, tokenStats, balancesForTokenSingle, diff --git a/src/routes/v3/util.js b/src/routes/v3/util.js index fda7282..7a41e83 100644 --- a/src/routes/v3/util.js +++ b/src/routes/v3/util.js @@ -1,50 +1,50 @@ -"use strict" +'use strict' -const express = require("express") +const express = require('express') const router = express.Router() -const axios = require("axios") +const axios = require('axios') -const routeUtils = require("./route-utils") -const wlogger = require("../../util/winston-logging") -const blockbook = require("./blockbook") +const routeUtils = require('./route-utils') +const wlogger = require('../../util/winston-logging') +const blockbook = require('./blockbook') -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -const BCHJS = require("@chris.troutner/bch-js") +const BCHJS = require('@chris.troutner/bch-js') const bchjs = new BCHJS() -const BCHJS_TESTNET = `https://testnet.bchjs.cash/v3/` +// const BCHJS_TESTNET = 'https://testnet.bchjs.cash/v3/' -const bchjsHTTP = axios.create({ - baseURL: process.env.RPC_BASEURL -}) +// const bchjsHTTP = axios.create({ +// baseURL: process.env.RPC_BASEURL +// }) -const username = process.env.RPC_USERNAME -const password = process.env.RPC_PASSWORD +// const username = process.env.RPC_USERNAME +// const password = process.env.RPC_PASSWORD -const requestConfig = { - method: "post", - auth: { - username: username, - password: password - }, - data: { - jsonrpc: "1.0" - } -} +// const requestConfig = { +// method: 'post', +// auth: { +// username: username, +// password: password +// }, +// data: { +// jsonrpc: '1.0' +// } +// } let _this class UtilRoute { - constructor() { + constructor () { this.bchjs = bchjs this.blockbook = blockbook _this = this } - root(req, res, next) { - return res.json({ status: "util" }) + root (req, res, next) { + return res.json({ status: 'util' }) } /** @@ -59,23 +59,23 @@ class UtilRoute { * * */ - async validateAddressSingle(req, res, next) { + async validateAddressSingle (req, res, next) { try { const address = req.params.address - if (!address || address === "") { + if (!address || address === '') { res.status(400) - return res.json({ error: "address can not be empty" }) + return res.json({ error: 'address can not be empty' }) } const { BitboxHTTP, - username, - password, + // username, + // password, requestConfig } = routeUtils.setEnvVars() - requestConfig.data.id = "validateaddress" - requestConfig.data.method = "validateaddress" + requestConfig.data.id = 'validateaddress' + requestConfig.data.method = 'validateaddress' requestConfig.data.params = [address] const response = await BitboxHTTP(requestConfig) @@ -89,7 +89,7 @@ class UtilRoute { return res.json({ error: msg }) } - wlogger.error(`Error in util.ts/validateAddressSingle().`, err) + wlogger.error('Error in util.ts/validateAddressSingle().', err) res.status(500) return res.json({ error: util.inspect(err) }) @@ -109,7 +109,7 @@ class UtilRoute { * * */ - async validateAddressBulk(req, res, next) { + async validateAddressBulk (req, res, next) { try { const addresses = req.body.addresses @@ -117,7 +117,7 @@ class UtilRoute { if (!Array.isArray(addresses)) { res.status(400) return res.json({ - error: "addresses needs to be an array. Use GET for single address." + error: 'addresses needs to be an array. Use GET for single address.' }) } @@ -125,7 +125,7 @@ class UtilRoute { if (!routeUtils.validateArraySize(req, addresses)) { res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330 return res.json({ - error: `Array too large.` + error: 'Array too large.' }) } @@ -135,7 +135,7 @@ class UtilRoute { // Ensure the input is a valid BCH address. try { - var legacyAddr = bchjs.Address.toLegacyAddress(address) + bchjs.Address.toLegacyAddress(address) } catch (err) { res.status(400) return res.json({ @@ -148,27 +148,28 @@ class UtilRoute { if (!networkIsValid) { res.status(400) return res.json({ - error: `Invalid network. Trying to use a testnet address on mainnet, or vice versa.` + error: + 'Invalid network. Trying to use a testnet address on mainnet, or vice versa.' }) } } - wlogger.debug(`Executing util/validate with these addresses: `, addresses) + wlogger.debug('Executing util/validate with these addresses: ', addresses) const { BitboxHTTP, - username, - password, + // username, + // password, requestConfig } = routeUtils.setEnvVars() // Loop through each address and creates an array of requests to call in parallel const promises = addresses.map(async address => { - requestConfig.data.id = "validateaddress" - requestConfig.data.method = "validateaddress" + requestConfig.data.id = 'validateaddress' + requestConfig.data.method = 'validateaddress' requestConfig.data.params = [address] - return await BitboxHTTP(requestConfig) + return BitboxHTTP(requestConfig) }) // Wait for all parallel Insight requests to return. @@ -187,7 +188,7 @@ class UtilRoute { return res.json({ error: msg }) } - wlogger.error(`Error in util.ts/validateAddressSingle().`, err) + wlogger.error('Error in util.ts/validateAddressSingle().', err) res.status(500) return res.json({ error: util.inspect(err) }) @@ -212,29 +213,29 @@ class UtilRoute { * */ - async sweepWif(req, res, next) { + async sweepWif (req, res, next) { try { // Validate input const wif = req.body.wif const toAddr = req.body.toAddr const balanceOnly = req.body.balanceOnly - if (typeof wif !== "string" || wif.length !== 52) { + if (typeof wif !== 'string' || wif.length !== 52) { res.status(400) return res.json({ - error: "WIF needs to a proper compressed WIF starting with K or L" + error: 'WIF needs to a proper compressed WIF starting with K or L' }) } if (!balanceOnly) { // Only throw error if balanceOnly is false or undefined. - if (!toAddr || toAddr === "") { + if (!toAddr || toAddr === '') { res.status(400) - return res.json({ error: "address can not be empty" }) + return res.json({ error: 'address can not be empty' }) } } - wlogger.debug(`Executing util/sweepWif with this address: `, toAddr) + wlogger.debug('Executing util/sweepWif with this address: ', toAddr) // Generate a private and public key pair from the WIF. const ecPair = bchjs.ECPair.fromWIF(wif) @@ -253,7 +254,7 @@ class UtilRoute { // Exit if balance is zero. if (isNaN(totalBalance) || totalBalance === 0) { res.status(422) - return res.json({ error: "No balance found at BCH address." }) + return res.json({ error: 'No balance found at BCH address.' }) } // Exit if this is a balance-only call. @@ -274,7 +275,7 @@ class UtilRoute { // Exit if there are no UTXOs. if (utxos.length === 0) { res.status(422) - return res.json({ error: "No utxos found." }) + return res.json({ error: 'No utxos found.' }) } // Figure out which UTXOs are associated with SLP tokens. @@ -295,7 +296,8 @@ class UtilRoute { if (bchUtxos.length === 0 && tokenUtxos.length > 0) { res.status(422) return res.json({ - error: `Tokens found, but no BCH UTXOs found. Add BCH to wallet to move tokens.` + error: + 'Tokens found, but no BCH UTXOs found. Add BCH to wallet to move tokens.' }) } @@ -337,14 +339,14 @@ class UtilRoute { // Catch the specific case of multiple tokens. if ( err.message && - err.message.indexOf("Multiple token classes detected") > -1 + err.message.indexOf('Multiple token classes detected') > -1 ) { res.status(422) return res.json({ error: err.message }) } - wlogger.error(`Error in util.js/sweepWif().`, err) - console.error(`Error in util.js/sweepWif().`, err) + wlogger.error('Error in util.js/sweepWif().', err) + console.error('Error in util.js/sweepWif().', err) res.status(500) return res.json({ error: err.message }) @@ -352,7 +354,7 @@ class UtilRoute { } // Sweep BCH only from a private WIF. - async _sweepBCH(options) { + async _sweepBCH (options) { try { // const wif = flags.wif // const toAddr = flags.address @@ -377,9 +379,9 @@ class UtilRoute { // instance of transaction builder let transactionBuilder - if (options.testnet) - transactionBuilder = new _this.bchjs.TransactionBuilder("testnet") - else transactionBuilder = new _this.bchjs.TransactionBuilder() + if (options.testnet) { + transactionBuilder = new _this.bchjs.TransactionBuilder('testnet') + } else transactionBuilder = new _this.bchjs.TransactionBuilder() let originalAmount = 0 @@ -394,7 +396,7 @@ class UtilRoute { if (originalAmount < 546) { throw new Error( - `Original amount less than the dust limit. Not enough BCH to send.` + 'Original amount less than the dust limit. Not enough BCH to send.' ) } @@ -435,21 +437,24 @@ class UtilRoute { const hex = tx.toHex() return hex } catch (err) { - wlogger.error(`Error in util.js/sweepBCH().`) + wlogger.error('Error in util.js/sweepBCH().') throw err } } // Sweep BCH and tokens from a WIF. - async _sweepTokens(options) { + async _sweepTokens (options) { try { - const { ecPair, utxos, fromAddr, toAddr, bchUtxos, tokenUtxos } = options + // const { ecPair, utxos, fromAddr, toAddr, bchUtxos, tokenUtxos } = options + const { ecPair, utxos, toAddr, bchUtxos, tokenUtxos } = options // Input validation - if (!Array.isArray(bchUtxos) || bchUtxos.length === 0) - throw new Error(`bchUtxos need to be an array with one UTXO.`) - if (!Array.isArray(tokenUtxos) || tokenUtxos.length === 0) - throw new Error(`tokenUtxos need to be an array with one UTXO.`) + if (!Array.isArray(bchUtxos) || bchUtxos.length === 0) { + throw new Error('bchUtxos need to be an array with one UTXO.') + } + if (!Array.isArray(tokenUtxos) || tokenUtxos.length === 0) { + throw new Error('tokenUtxos need to be an array with one UTXO.') + } // if (flags.testnet) // this.BITBOX = new config.BCHLIB({ restURL: config.TESTNET_REST }) @@ -462,15 +467,15 @@ class UtilRoute { const otherTokens = tokenUtxos.filter(x => x.tokenId !== tokenId) if (otherTokens.length > 0) { throw new Error( - `Multiple token classes detected. This function only supports a single class of token.` + 'Multiple token classes detected. This function only supports a single class of token.' ) } // instance of transaction builder let transactionBuilder - if (options.testnet) - transactionBuilder = new _this.bchjs.TransactionBuilder("testnet") - else transactionBuilder = new _this.bchjs.TransactionBuilder() + if (options.testnet) { + transactionBuilder = new _this.bchjs.TransactionBuilder('testnet') + } else transactionBuilder = new _this.bchjs.TransactionBuilder() // Combine all the UTXOs into a single array. const allUtxos = utxos @@ -488,7 +493,7 @@ class UtilRoute { if (originalAmount < 300) { throw new Error( - `Not enough BCH to send. Send more BCH to the wallet to pay miner fees.` + 'Not enough BCH to send. Send more BCH to the wallet to pay miner fees.' ) } @@ -506,18 +511,20 @@ class UtilRoute { // amount to send back to the sending address. It's the original amount - 1 sat/byte for tx size const remainder = originalAmount - txFee - 546 - if (remainder < 1) - throw new Error(`Selected UTXO does not have enough satoshis`) - //console.log(`remainder: ${remainder}`) + if (remainder < 1) { + throw new Error('Selected UTXO does not have enough satoshis') + } + // console.log(`remainder: ${remainder}`) // Tally up the quantity of tokens let tokenQty = 0 - for (let i = 0; i < tokenUtxos.length; i++) + for (let i = 0; i < tokenUtxos.length; i++) { tokenQty += tokenUtxos[i].tokenQty + } // console.log(`tokenQty: ${tokenQty}`) // Generate the OP_RETURN entry for an SLP SEND transaction. - //console.log(`Generating op-return.`) + // console.log(`Generating op-return.`) const { script, outputs @@ -529,7 +536,7 @@ class UtilRoute { // is something unexpected happening. if (outputs > 1) { throw new Error( - `More than one class of token detected. Sweep feature not supported.` + 'More than one class of token detected. Sweep feature not supported.' ) } @@ -575,7 +582,7 @@ class UtilRoute { return hex } catch (err) { - wlogger.error(`Error in util.js/sweepBCH().`) + wlogger.error('Error in util.js/sweepBCH().') throw err } } @@ -583,10 +590,10 @@ class UtilRoute { const utilRoute = new UtilRoute() -router.get("/", utilRoute.root) -router.get("/validateAddress/:address", utilRoute.validateAddressSingle) -router.post("/validateAddress", utilRoute.validateAddressBulk) -router.post("/sweep", utilRoute.sweepWif) +router.get('/', utilRoute.root) +router.get('/validateAddress/:address', utilRoute.validateAddressSingle) +router.post('/validateAddress', utilRoute.validateAddressBulk) +router.post('/sweep', utilRoute.sweepWif) module.exports = { router, diff --git a/src/routes/v3/xpub.js b/src/routes/v3/xpub.js index 142a75e..353158f 100644 --- a/src/routes/v3/xpub.js +++ b/src/routes/v3/xpub.js @@ -2,51 +2,51 @@ xpub route */ -"use strict" +'use strict' -const express = require("express") -const axios = require("axios") -const routeUtils = require("./route-utils") -const wlogger = require("../../util/winston-logging") +const express = require('express') +// const axios = require('axios') +const routeUtils = require('./route-utils') +const wlogger = require('../../util/winston-logging') -//const router = express.Router() +// const router = express.Router() const router = express.Router() // Used for processing error messages before sending them to the user. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -const BCHJS = require("@chris.troutner/bch-js") +const BCHJS = require('@chris.troutner/bch-js') const bchjs = new BCHJS() // Connect the route endpoints to their handler functions. -router.get("/", root) -router.get("/fromXPub/:xpub", fromXPubSingle) +router.get('/', root) +router.get('/fromXPub/:xpub', fromXPubSingle) // Root API endpoint. Simply acknowledges that it exists. -function root(req, res, next) { - return res.json({ status: "address" }) +function root (req, res, next) { + return res.json({ status: 'address' }) } -async function fromXPubSingle(req, res, next) { +async function fromXPubSingle (req, res, next) { try { const xpub = req.params.xpub - const hdPath = req.query.hdPath ? req.query.hdPath : "0" + const hdPath = req.query.hdPath ? req.query.hdPath : '0' - if (!xpub || xpub === "") { + if (!xpub || xpub === '') { res.status(400) - return res.json({ error: "xpub can not be empty" }) + return res.json({ error: 'xpub can not be empty' }) } // Reject if xpub is an array. if (Array.isArray(xpub)) { res.status(400) return res.json({ - error: "xpub can not be an array. Use POST for bulk upload." + error: 'xpub can not be an array. Use POST for bulk upload.' }) } - wlogger.debug(`Executing address/fromXPub with this xpub: `, xpub) + wlogger.debug('Executing address/fromXPub with this xpub: ', xpub) const cashAddr = bchjs.Address.fromXPub(xpub, hdPath) const legacyAddr = bchjs.Address.toLegacyAddress(cashAddr) @@ -64,7 +64,7 @@ async function fromXPubSingle(req, res, next) { } // Write out error to error log. - wlogger.error(`Error in address.ts/fromXPubSingle().`, err) + wlogger.error('Error in address.ts/fromXPubSingle().', err) res.status(500) return res.json({ error: util.inspect(err) }) diff --git a/src/util/blockbook-path.js b/src/util/blockbook-path.js index 60ff0ce..237cdba 100644 --- a/src/util/blockbook-path.js +++ b/src/util/blockbook-path.js @@ -8,29 +8,29 @@ Blockbook. */ -"use strict" +'use strict' class BlockbookPath { - constructor() { + constructor () { // defaults this.addrPath = `${process.env.BLOCKBOOK_URL}api/v2/address/` this.utxoPath = `${process.env.BLOCKBOOK_URL}api/v2/utxo/` this.txPath = `${process.env.BLOCKBOOK_URL}api/v2/tx/` } - toOpenBazaar() { - if (process.env.NETWORK === "testnet") { - this.addrPath = `https://tbch.blockbook.api.openbazaar.org/api/address/` - this.utxoPath = `https://tbch.blockbook.api.openbazaar.org/api/utxo/` - this.txPath = `https://tbch.blockbook.api.openbazaar.org/api/tx/` + toOpenBazaar () { + if (process.env.NETWORK === 'testnet') { + this.addrPath = 'https://tbch.blockbook.api.openbazaar.org/api/address/' + this.utxoPath = 'https://tbch.blockbook.api.openbazaar.org/api/utxo/' + this.txPath = 'https://tbch.blockbook.api.openbazaar.org/api/tx/' } else { - this.addrPath = `https://bch.blockbook.api.openbazaar.org/api/address/` - this.utxoPath = `https://bch.blockbook.api.openbazaar.org/api/utxo/` - this.txPath = `https://bch.blockbook.api.openbazaar.org/api/tx/` + this.addrPath = 'https://bch.blockbook.api.openbazaar.org/api/address/' + this.utxoPath = 'https://bch.blockbook.api.openbazaar.org/api/utxo/' + this.txPath = 'https://bch.blockbook.api.openbazaar.org/api/tx/' } } - toDefault() { + toDefault () { this.addrPath = `${process.env.BLOCKBOOK_URL}api/v2/address/` this.utxoPath = `${process.env.BLOCKBOOK_URL}api/v2/utxo/` this.txPath = `${process.env.BLOCKBOOK_URL}api/v2/tx/` diff --git a/src/util/winston-logging.js b/src/util/winston-logging.js index 14cd908..bf6305a 100644 --- a/src/util/winston-logging.js +++ b/src/util/winston-logging.js @@ -4,33 +4,33 @@ logging library. */ -"use strict" +'use strict' -var winston = require("winston") -require("winston-daily-rotate-file") +var winston = require('winston') +require('winston-daily-rotate-file') var NETWORK = process.env.NETWORK // Configure daily-rotation transport. var transport = new winston.transports.DailyRotateFile({ filename: `${__dirname}/../../logs/rest-${NETWORK}-%DATE%.log`, - datePattern: "YYYY-MM-DD", + datePattern: 'YYYY-MM-DD', zippedArchive: false, - maxSize: "1m", - maxFiles: "5d", + maxSize: '1m', + maxFiles: '5d', format: winston.format.combine( winston.format.timestamp(), winston.format.json() ) }) -transport.on("rotate", function(oldFilename, newFilename) { - wlogger.info("Rotating log files") +transport.on('rotate', function (oldFilename, newFilename) { + wlogger.info('Rotating log files') }) // This controls what goes into the log FILES var wlogger = winston.createLogger({ - level: "verbose", + level: 'verbose', format: winston.format.json(), transports: [ // diff --git a/test/v3/blockbook.js b/test/v3/blockbook.js index 60df68c..d9db4a5 100644 --- a/test/v3/blockbook.js +++ b/test/v3/blockbook.js @@ -8,40 +8,40 @@ To-Do: */ -"use strict" +'use strict' -const chai = require("chai") +const chai = require('chai') const assert = chai.assert -const nock = require("nock") // HTTP mocking +const nock = require('nock') // HTTP mocking let originalUrl, mockServerUrl // Used during transition from integration to unit tests. -originalUrl = process.env.BLOCKBOOK_URL +// originalUrl = process.env.BLOCKBOOK_URL // Set default environment variables for unit tests. -if (!process.env.TEST) process.env.TEST = "unit" -if (process.env.TEST === "unit") { - process.env.BLOCKBOOK_URL = "http://fakeurl/api/" - mockServerUrl = `http://fakeurl` +if (!process.env.TEST) process.env.TEST = 'unit' +if (process.env.TEST === 'unit') { + process.env.BLOCKBOOK_URL = 'http://fakeurl/api/' + mockServerUrl = 'http://fakeurl' } // Only load blockbook library after setting BLOCKBOOK_URL env var. -const blockbookRoute = require("../../src/routes/v3/blockbook") +const blockbookRoute = require('../../src/routes/v3/blockbook') // Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/blockbook-mock") +const { mockReq, mockRes } = require('./mocks/express-mocks') +const mockData = require('./mocks/blockbook-mock') // Used for debugging. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -describe("#Blockbook Router", () => { +describe('#Blockbook Router', () => { let req, res before(() => { // console.log(`Testing type is: ${process.env.TEST}`) - if (!process.env.NETWORK) process.env.NETWORK = "testnet" + if (!process.env.NETWORK) process.env.NETWORK = 'testnet' }) // Setup the mocks before each test. @@ -69,95 +69,95 @@ describe("#Blockbook Router", () => { process.env.BLOCKBOOK_URL = originalUrl }) - describe("#root", () => { + describe('#root', () => { // root route handler. const root = blockbookRoute.testableComponents.root - it("should respond to GET for base route", async () => { + it('should respond to GET for base route', async () => { const result = root(req, res) - assert.equal(result.status, "address", "Returns static string") + assert.equal(result.status, 'address', 'Returns static string') }) }) - describe("#Balance Single", () => { + describe('#Balance Single', () => { // details route handler. const balanceSingle = blockbookRoute.testableComponents.balanceSingle - it("should throw 400 if address is empty", async () => { + it('should throw 400 if address is empty', async () => { const result = await balanceSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'address can not be empty') }) - it("should error on an array", async () => { - req.params.address = [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] + it('should error on an array', async () => { + req.params.address = ['qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c'] const result = await balanceSingle(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "address can not be an array", - "Proper error message" + 'address can not be an array', + 'Proper error message' ) }) - it("should throw an error for an invalid address", async () => { - req.params.address = `02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` + it('should throw an error for an invalid address', async () => { + req.params.address = '02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c' const result = await balanceSingle(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "Invalid BCH address", - "Proper error message" + 'Invalid BCH address', + 'Proper error message' ) }) - it("should detect a network mismatch", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` + it('should detect a network mismatch', async () => { + req.params.address = 'bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4' const result = await balanceSingle(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') + assert.include(result.error, 'Invalid network', 'Proper error message') }) - it("should throw 500 when network issues", async () => { + it('should throw 500 when network issues', async () => { const savedUrl = process.env.BLOCKBOOK_URL try { - req.params.address = `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` + req.params.address = 'qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c' // Switch the Insight URL to something that will error out. - process.env.BLOCKBOOK_URL = "http://fakeurl/api/" + process.env.BLOCKBOOK_URL = 'http://fakeurl/api/' const result = await balanceSingle(req, res) // Restore the saved URL. process.env.BLOCKBOOK_URL = savedUrl - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") + assert.equal(res.statusCode, 500, 'HTTP status code 500 expected.') + assert.include(result.error, 'ENOTFOUND', 'Error message expected') } catch (err) { // Restore the saved URL. process.env.BLOCKBOOK_URL = savedUrl } }) - it("should get balance for a single address", async () => { - req.params.address = `bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf` + it('should get balance for a single address', async () => { + req.params.address = 'bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf' // console.log(`process.env.BLOCKBOOK_URL: ${process.env.BLOCKBOOK_URL}`) // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.BLOCKBOOK_URL}`) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .reply(200, mockData.mockBalance) } @@ -166,118 +166,118 @@ describe("#Blockbook Router", () => { // console.log(`result: ${util.inspect(result)}`) assert.hasAnyKeys(result, [ - "page", - "totalPages", - "itemsOnPage", - "address", - "balance", - "totalReceived", - "totalSent", - "unconfirmedBalance", - "unconfirmedTxs", - "txs", - "txids" + 'page', + 'totalPages', + 'itemsOnPage', + 'address', + 'balance', + 'totalReceived', + 'totalSent', + 'unconfirmedBalance', + 'unconfirmedTxs', + 'txs', + 'txids' ]) assert.isArray(result.txids) }) }) - describe("#Balance Bulk", () => { + describe('#Balance Bulk', () => { // details route handler. const balanceBulk = blockbookRoute.testableComponents.balanceBulk - it("should throw an error for an empty body", async () => { + it('should throw an error for an empty body', async () => { req.body = {} const result = await balanceBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "addresses needs to be an array", - "Proper error message" + 'addresses needs to be an array', + 'Proper error message' ) }) - it("should error on non-array single address", async () => { + it('should error on non-array single address', async () => { req.body = { - address: `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` + address: 'qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c' } const result = await balanceBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "addresses needs to be an array", - "Proper error message" + 'addresses needs to be an array', + 'Proper error message' ) }) - it("should throw an error for an invalid address", async () => { + it('should throw an error for an invalid address', async () => { req.body = { - addresses: [`02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] + addresses: ['02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c'] } const result = await balanceBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "Invalid BCH address", - "Proper error message" + 'Invalid BCH address', + 'Proper error message' ) }) - it("should throw 400 error if addresses array is too large", async () => { + it('should throw 400 error if addresses array is too large', async () => { const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") + for (var i = 0; i < 25; i++) testArray.push('') req.body.addresses = testArray const result = await balanceBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Array too large') }) - it("should detect a network mismatch", async () => { + it('should detect a network mismatch', async () => { req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] + addresses: ['bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4'] } const result = await balanceBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') + assert.include(result.error, 'Invalid network', 'Proper error message') }) - it("should throw 500 when network issues", async () => { + it('should throw 500 when network issues', async () => { const savedUrl = process.env.BLOCKBOOK_URL try { req.body = { - addresses: [`bitcoincash:qqqvv56zepke5k0xeaehlmjtmkv9ly2uzgkxpajdx3`] + addresses: ['bitcoincash:qqqvv56zepke5k0xeaehlmjtmkv9ly2uzgkxpajdx3'] } // Switch the Insight URL to something that will error out. - process.env.BLOCKBOOK_URL = "http://fakeurl/api/" + process.env.BLOCKBOOK_URL = 'http://fakeurl/api/' const result = await balanceBulk(req, res) - //console.log(`network issue result: ${util.inspect(result)}`) + // console.log(`network issue result: ${util.inspect(result)}`) // Restore the saved URL. process.env.BLOCKBOOK_URL = savedUrl - assert.isAbove(res.statusCode, 499, "HTTP status code 500 expected.") - //assert.include(result.error, "ENOTFOUND", "Error message expected") + assert.isAbove(res.statusCode, 499, 'HTTP status code 500 expected.') + // assert.include(result.error, "ENOTFOUND", "Error message expected") assert.include( result.error, - "Network error: Could not communicate", - "Error message expected" + 'Network error: Could not communicate', + 'Error message expected' ) } catch (err) { // Restore the saved URL. @@ -285,15 +285,15 @@ describe("#Blockbook Router", () => { } }) - it("should get details for a single address", async () => { + it('should get details for a single address', async () => { req.body = { - addresses: ["bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf"] + addresses: ['bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf'] } // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(mockServerUrl) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .reply(200, mockData.mockBalance) } @@ -303,237 +303,237 @@ describe("#Blockbook Router", () => { assert.isArray(result) assert.hasAnyKeys(result[0], [ - "page", - "totalPages", - "itemsOnPage", - "address", - "balance", - "totalReceived", - "totalSent", - "unconfirmedBalance", - "unconfirmedTxs", - "txs", - "txids" + 'page', + 'totalPages', + 'itemsOnPage', + 'address', + 'balance', + 'totalReceived', + 'totalSent', + 'unconfirmedBalance', + 'unconfirmedTxs', + 'txs', + 'txids' ]) assert.isArray(result[0].txids) }) - it("should get details for multiple addresses", async () => { + it('should get details for multiple addresses', async () => { req.body = { addresses: [ - "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf", - "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf" + 'bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf', + 'bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf' ] } // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(mockServerUrl) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .times(2) .reply(200, mockData.mockBalance) } // Call the details API. const result = await balanceBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) - assert.equal(result.length, 2, "2 outputs for 2 inputs") + assert.equal(result.length, 2, '2 outputs for 2 inputs') }) }) - describe("#UTXOs Single", () => { + describe('#UTXOs Single', () => { // details route handler. const utxosSingle = blockbookRoute.testableComponents.utxosSingle - it("should throw 400 if address is empty", async () => { + it('should throw 400 if address is empty', async () => { const result = await utxosSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'address can not be empty') }) - it("should error on an array", async () => { - req.params.address = [`qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] + it('should error on an array', async () => { + req.params.address = ['qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c'] const result = await utxosSingle(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "address can not be an array", - "Proper error message" + 'address can not be an array', + 'Proper error message' ) }) - it("should throw an error for an invalid address", async () => { - req.params.address = `02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` + it('should throw an error for an invalid address', async () => { + req.params.address = '02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c' const result = await utxosSingle(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "Invalid BCH address", - "Proper error message" + 'Invalid BCH address', + 'Proper error message' ) }) - it("should detect a network mismatch", async () => { - req.params.address = `bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4` + it('should detect a network mismatch', async () => { + req.params.address = 'bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4' const result = await utxosSingle(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') + assert.include(result.error, 'Invalid network', 'Proper error message') }) - it("should throw 500 when network issues", async () => { + it('should throw 500 when network issues', async () => { const savedUrl = process.env.BLOCKBOOK_URL try { - req.params.address = `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` + req.params.address = 'qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c' // Switch the Insight URL to something that will error out. - process.env.BLOCKBOOK_URL = "http://fakeurl/api/" + process.env.BLOCKBOOK_URL = 'http://fakeurl/api/' const result = await utxosSingle(req, res) // Restore the saved URL. process.env.BLOCKBOOK_URL = savedUrl - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") + assert.equal(res.statusCode, 500, 'HTTP status code 500 expected.') + assert.include(result.error, 'ENOTFOUND', 'Error message expected') } catch (err) { // Restore the saved URL. process.env.BLOCKBOOK_URL = savedUrl } }) - it("should get utxos for a single address", async () => { + it('should get utxos for a single address', async () => { req.params.address = - "bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7" + 'bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7' // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.BLOCKBOOK_URL}`) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .reply(200, mockData.mockUtxos) } // Call the details API. const result = await utxosSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) assert.hasAnyKeys(result[0], [ - "txid", - "vout", - "value", - "height", - "confirmations" + 'txid', + 'vout', + 'value', + 'height', + 'confirmations' ]) }) }) - describe("#UTXO Bulk", () => { + describe('#UTXO Bulk', () => { // details route handler. const utxosBulk = blockbookRoute.testableComponents.utxosBulk - it("should throw an error for an empty body", async () => { + it('should throw an error for an empty body', async () => { req.body = {} const result = await utxosBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "addresses needs to be an array", - "Proper error message" + 'addresses needs to be an array', + 'Proper error message' ) }) - it("should error on non-array single address", async () => { + it('should error on non-array single address', async () => { req.body = { - address: `qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c` + address: 'qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c' } const result = await utxosBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "addresses needs to be an array", - "Proper error message" + 'addresses needs to be an array', + 'Proper error message' ) }) - it("should throw an error for an invalid address", async () => { + it('should throw an error for an invalid address', async () => { req.body = { - addresses: [`02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c`] + addresses: ['02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c'] } const result = await utxosBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "Invalid BCH address", - "Proper error message" + 'Invalid BCH address', + 'Proper error message' ) }) - it("should throw 400 error if addresses array is too large", async () => { + it('should throw 400 error if addresses array is too large', async () => { const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") + for (var i = 0; i < 25; i++) testArray.push('') req.body.addresses = testArray const result = await utxosBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Array too large') }) - it("should detect a network mismatch", async () => { + it('should detect a network mismatch', async () => { req.body = { - addresses: [`bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4`] + addresses: ['bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4'] } const result = await utxosBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "Invalid network", "Proper error message") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') + assert.include(result.error, 'Invalid network', 'Proper error message') }) - it("should throw 500 when network issues", async () => { + it('should throw 500 when network issues', async () => { const savedUrl = process.env.BLOCKBOOK_URL try { req.body = { - addresses: [`bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf`] + addresses: ['bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf'] } // Switch the Insight URL to something that will error out. - process.env.BLOCKBOOK_URL = "http://fakeurl/api/" + process.env.BLOCKBOOK_URL = 'http://fakeurl/api/' const result = await utxosBulk(req, res) - //console.log(`network issue result: ${util.inspect(result)}`) + // console.log(`network issue result: ${util.inspect(result)}`) // Restore the saved URL. process.env.BLOCKBOOK_URL = savedUrl - assert.isAbove(res.statusCode, 499, "HTTP status code 500 expected.") - //assert.include(result.error, "ENOTFOUND", "Error message expected") + assert.isAbove(res.statusCode, 499, 'HTTP status code 500 expected.') + // assert.include(result.error, "ENOTFOUND", "Error message expected") assert.include( result.error, - "Network error: Could not communicate", - "Error message expected" + 'Network error: Could not communicate', + 'Error message expected' ) } catch (err) { // Restore the saved URL. @@ -541,125 +541,125 @@ describe("#Blockbook Router", () => { } }) - it("should get details for a single address", async () => { + it('should get details for a single address', async () => { req.body = { - addresses: [`bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7`] + addresses: ['bitcoincash:qp3sn6vlwz28ntmf3wmyra7jqttfx7z6zgtkygjhc7'] } // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(mockServerUrl) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .reply(200, mockData.mockUtxos) } // Call the details API. const result = await utxosBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) assert.isArray(result[0]) assert.hasAnyKeys(result[0][0], [ - "txid", - "vout", - "value", - "height", - "confirmations" + 'txid', + 'vout', + 'value', + 'height', + 'confirmations' ]) }) - it("should get details for multiple addresses", async () => { + it('should get details for multiple addresses', async () => { req.body = { addresses: [ - `bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf`, - `bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf` + 'bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf', + 'bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf' ] } // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(mockServerUrl) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .times(2) .reply(200, mockData.mockUtxos) } // Call the details API. const result = await utxosBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) assert.isArray(result[0]) - assert.equal(result.length, 2, "2 outputs for 2 inputs") + assert.equal(result.length, 2, '2 outputs for 2 inputs') }) }) - describe("#txSingle", () => { + describe('#txSingle', () => { // route handler const txSingle = blockbookRoute.testableComponents.txSingle - it("should throw 400 if txid is empty", async () => { + it('should throw 400 if txid is empty', async () => { const result = await txSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'txid can not be empty') }) - it("should error on an array", async () => { + it('should error on an array', async () => { req.params.txid = [ - `6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d` + '6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d' ] const result = await txSingle(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "txid can not be an array", - "Proper error message" + 'txid can not be an array', + 'Proper error message' ) }) - it("should throw 400 if txid is not a valid txid", async () => { - req.params.txid = `abc` + it('should throw 400 if txid is not a valid txid', async () => { + req.params.txid = 'abc' const result = await txSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid must be of length 64") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'txid must be of length 64') }) - it("should throw 500 when network issues", async () => { + it('should throw 500 when network issues', async () => { const savedUrl = process.env.BLOCKBOOK_URL try { - req.params.txid = `6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d` + req.params.txid = '6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d' // Switch the Insight URL to something that will error out. - process.env.BLOCKBOOK_URL = "http://fakeurl/api/" + process.env.BLOCKBOOK_URL = 'http://fakeurl/api/' const result = await txSingle(req, res) // Restore the saved URL. process.env.BLOCKBOOK_URL = savedUrl - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") + assert.equal(res.statusCode, 500, 'HTTP status code 500 expected.') + assert.include(result.error, 'ENOTFOUND', 'Error message expected') } catch (err) { // Restore the saved URL. process.env.BLOCKBOOK_URL = savedUrl } }) - it("should get tx details for a single txid", async () => { - req.params.txid = `6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d` + it('should get tx details for a single txid', async () => { + req.params.txid = '6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d' // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.BLOCKBOOK_URL}`) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .reply(200, mockData.mockTx) } @@ -671,130 +671,130 @@ describe("#Blockbook Router", () => { // console.log(`result: ${JSON.stringify(result, null, 2)}`) assert.hasAnyKeys(result, [ - "txid", - "version", - "vin", - "vout", - "blockHash", - "blockHeight", - "confirmations", - "blockTime", - "value", - "valueIn", - "fees", - "hex" + 'txid', + 'version', + 'vin', + 'vout', + 'blockHash', + 'blockHeight', + 'confirmations', + 'blockTime', + 'value', + 'valueIn', + 'fees', + 'hex' ]) // Vin assert.isArray(result.vin) assert.hasAnyKeys(result.vin[0], [ - "txid", - "sequence", - "n", - "addresses", - "value", - "hex" + 'txid', + 'sequence', + 'n', + 'addresses', + 'value', + 'hex' ]) // Vout assert.isArray(result.vout) assert.hasAnyKeys(result.vout[0], [ - "value", - "n", - "spent", - "hex", - "addresses" + 'value', + 'n', + 'spent', + 'hex', + 'addresses' ]) }) }) - describe("#txBulk", () => { + describe('#txBulk', () => { // route handler const txBulk = blockbookRoute.testableComponents.txBulk - it("should throw an error for an empty body", async () => { + it('should throw an error for an empty body', async () => { req.body = {} const result = await txBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "txids need to be an array", - "Proper error message" + 'txids need to be an array', + 'Proper error message' ) }) - it("should error on non-array single address", async () => { - req.body.txids = `6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d` + it('should error on non-array single address', async () => { + req.body.txids = '6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d' const result = await txBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "txids need to be an array", - "Proper error message" + 'txids need to be an array', + 'Proper error message' ) }) - it("should throw 400 error if addresses array is too large", async () => { + it('should throw 400 error if addresses array is too large', async () => { const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") + for (var i = 0; i < 25; i++) testArray.push('') req.body.txids = testArray const result = await txBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Array too large') }) - it("should throw an error for an invalid address", async () => { + it('should throw an error for an invalid address', async () => { req.body = { txids: [ - `5fe9b74056319a8c87f45cc745030715a6180758b94938dbf90d639d55652392`, - `abc` + '5fe9b74056319a8c87f45cc745030715a6180758b94938dbf90d639d55652392', + 'abc' ] } const result = await txBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "txid must be of length 64", - "Proper error message" + 'txid must be of length 64', + 'Proper error message' ) }) - it("should throw 500 when network issues", async () => { + it('should throw 500 when network issues', async () => { const savedUrl = process.env.BLOCKBOOK_URL try { req.body = { txids: [ - `5fe9b74056319a8c87f45cc745030715a6180758b94938dbf90d639d55652392` + '5fe9b74056319a8c87f45cc745030715a6180758b94938dbf90d639d55652392' ] } // Switch the Insight URL to something that will error out. - process.env.BLOCKBOOK_URL = "http://fakeurl/api/" + process.env.BLOCKBOOK_URL = 'http://fakeurl/api/' const result = await txBulk(req, res) - //console.log(`network issue result: ${util.inspect(result)}`) + // console.log(`network issue result: ${util.inspect(result)}`) // Restore the saved URL. process.env.BLOCKBOOK_URL = savedUrl - assert.isAbove(res.statusCode, 499, "HTTP status code 500 expected.") - //assert.include(result.error, "ENOTFOUND", "Error message expected") + assert.isAbove(res.statusCode, 499, 'HTTP status code 500 expected.') + // assert.include(result.error, "ENOTFOUND", "Error message expected") assert.include( result.error, - "Network error: Could not communicate", - "Error message expected" + 'Network error: Could not communicate', + 'Error message expected' ) } catch (err) { // Restore the saved URL. @@ -802,74 +802,74 @@ describe("#Blockbook Router", () => { } }) - it("should get details for a single txid", async () => { + it('should get details for a single txid', async () => { req.body = { txids: [ - `6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d` + '6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d' ] } // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(mockServerUrl) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .reply(200, mockData.mockTx) } // Call the details API. const result = await txBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) assert.hasAnyKeys(result[0], [ - "txid", - "version", - "vin", - "vout", - "blockHash", - "blockHeight", - "confirmations", - "blockTime", - "value", - "valueIn", - "fees", - "hex" + 'txid', + 'version', + 'vin', + 'vout', + 'blockHash', + 'blockHeight', + 'confirmations', + 'blockTime', + 'value', + 'valueIn', + 'fees', + 'hex' ]) // Vin assert.isArray(result[0].vin) assert.hasAnyKeys(result[0].vin[0], [ - "txid", - "sequence", - "n", - "addresses", - "value", - "hex" + 'txid', + 'sequence', + 'n', + 'addresses', + 'value', + 'hex' ]) // Vout assert.isArray(result[0].vout) assert.hasAnyKeys(result[0].vout[0], [ - "value", - "n", - "spent", - "hex", - "addresses" + 'value', + 'n', + 'spent', + 'hex', + 'addresses' ]) }) - it("should get details for multiple txid", async () => { + it('should get details for multiple txid', async () => { req.body = { txids: [ - `6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d`, - `6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d` + '6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d', + '6181c669614fa18039a19b23eb06806bfece1f7514ab457c3bb82a40fe171a6d' ] } // Mock the Insight URL for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(mockServerUrl) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .times(2) .reply(200, mockData.mockTx) } @@ -879,7 +879,7 @@ describe("#Blockbook Router", () => { // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) - assert.equal(result.length, 2, "2 outputs for 2 inputs") + assert.equal(result.length, 2, '2 outputs for 2 inputs') }) }) }) diff --git a/test/v3/blockchain.js b/test/v3/blockchain.js index 8aa718d..3d1d8b4 100644 --- a/test/v3/blockchain.js +++ b/test/v3/blockchain.js @@ -6,27 +6,27 @@ --Needs e2e test to create unconfirmed tx, for real-world test. */ -"use strict" +'use strict' -const chai = require("chai") +const chai = require('chai') const assert = chai.assert -const sinon = require("sinon") +const sinon = require('sinon') -const Blockchain = require("../../src/routes/v3/full-node/blockchain") +const Blockchain = require('../../src/routes/v3/full-node/blockchain') const uut = new Blockchain() -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -if (!process.env.TEST) process.env.TEST = "unit" +if (!process.env.TEST) process.env.TEST = 'unit' // Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/blockchain-mock") +const { mockReq, mockRes } = require('./mocks/express-mocks') +const mockData = require('./mocks/blockchain-mock') let originalEnvVars // Used during transition from integration to unit tests. -describe("#BlockchainRouter", () => { +describe('#BlockchainRouter', () => { let req, res let sandbox @@ -43,11 +43,11 @@ describe("#BlockchainRouter", () => { } // Set default environment variables for unit tests. - if (process.env.TEST === "unit") { - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api" - process.env.RPC_USERNAME = "fakeusername" - process.env.RPC_PASSWORD = "fakepassword" + if (process.env.TEST === 'unit') { + process.env.BITCOINCOM_BASEURL = 'http://fakeurl/api/' + process.env.RPC_BASEURL = 'http://fakeurl/api' + process.env.RPC_USERNAME = 'fakeusername' + process.env.RPC_PASSWORD = 'fakepassword' } }) @@ -79,21 +79,21 @@ describe("#BlockchainRouter", () => { process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD }) - describe("#root", () => { - it("should respond to GET for base route", async () => { + describe('#root', () => { + it('should respond to GET for base route', async () => { const result = uut.root(req, res) - assert.equal(result.status, "blockchain", "Returns static string") + assert.equal(result.status, 'blockchain', 'Returns static string') }) }) - describe("getBestBlockHash()", () => { - it("should throw 503 when network issues", async () => { + describe('getBestBlockHash()', () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' const result = await uut.getBestBlockHash(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -101,49 +101,49 @@ describe("#BlockchainRouter", () => { // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) const result = await uut.getBestBlockHash(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) const result = await uut.getBestBlockHash(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should GET /getBestBlockHash", async () => { + it('should GET /getBestBlockHash', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: mockData.mockBlockHash } }) } @@ -151,17 +151,17 @@ describe("#BlockchainRouter", () => { // console.log(`result: ${JSON.stringify(result, null, 2)}`) assert.isString(result) - assert.equal(result.length, 64, "Hash string is fixed length") + assert.equal(result.length, 64, 'Hash string is fixed length') }) }) - describe("getBlockchainInfo()", () => { - it("should throw 503 when network issues", async () => { + describe('getBlockchainInfo()', () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' const result = await uut.getBlockchainInfo(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -169,49 +169,49 @@ describe("#BlockchainRouter", () => { // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) const result = await uut.getBestBlockHash(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) const result = await uut.getBestBlockHash(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should GET /getBlockchainInfo", async () => { + it('should GET /getBlockchainInfo', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: mockData.mockBlockchainInfo } }) } @@ -219,28 +219,28 @@ describe("#BlockchainRouter", () => { // console.log(`result: ${util.inspect(result)}`) assert.hasAnyKeys(result, [ - "chain", - "blocks", - "headers", - "bestblockhash", - "difficulty", - "mediantime", - "verificationprogress", - "chainwork", - "pruned", - "softforks", - "bip9_softforks" + 'chain', + 'blocks', + 'headers', + 'bestblockhash', + 'difficulty', + 'mediantime', + 'verificationprogress', + 'chainwork', + 'pruned', + 'softforks', + 'bip9_softforks' ]) }) }) - describe("getBlockCount()", () => { - it("should throw 503 when network issues", async () => { + describe('getBlockCount()', () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' const result = await uut.getBlockCount(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -248,48 +248,48 @@ describe("#BlockchainRouter", () => { // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) const result = await uut.getBlockCount(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) const result = await uut.getBlockCount(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should GET /getBlockCount", async () => { + it('should GET /getBlockCount', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: 126769 } }) } @@ -300,23 +300,23 @@ describe("#BlockchainRouter", () => { }) }) - describe("getBlockHeaderSingle()", async () => { - it("should throw 400 error if hash is missing", async () => { + describe('getBlockHeaderSingle()', async () => { + it('should throw 400 error if hash is missing', async () => { const result = await uut.getBlockHeaderSingle(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "hash can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'hash can not be empty') }) - it("should throw 503 when network issues", async () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' req.params.hash = - "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900" + '00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900' const result = await uut.getBlockHeaderSingle(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -324,60 +324,60 @@ describe("#BlockchainRouter", () => { // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Network error: Could not communicate with full node", - "Error message expected" + 'Network error: Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) req.params.hash = - "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900" + '00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900' const result = await uut.getBlockHeaderSingle(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) req.params.hash = - "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900" + '00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900' const result = await uut.getBlockHeaderSingle(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should GET block header", async () => { + it('should GET block header', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - sandbox.stub(uut.axios, "request").resolves({ + if (process.env.TEST === 'unit') { + sandbox.stub(uut.axios, 'request').resolves({ data: { result: - "000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c" + '000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c' } }) } req.params.hash = - "000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0" + '000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0' const result = await uut.getBlockHeaderSingle(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -385,165 +385,165 @@ describe("#BlockchainRouter", () => { assert.isString(result) assert.equal( result, - "000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c" + '000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c' ) }) - it("should GET verbose block header", async () => { + it('should GET verbose block header', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: mockData.mockBlockHeader } }) } req.query.verbose = true req.params.hash = - "000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0" + '000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0' const result = await uut.getBlockHeaderSingle(req, res) // console.log(`result: ${util.inspect(result)}`) assert.hasAllKeys(result, [ - "hash", - "confirmations", - "height", - "version", - "versionHex", - "merkleroot", - "time", - "mediantime", - "nonce", - "bits", - "difficulty", - "chainwork", - "previousblockhash", - "nextblockhash" + 'hash', + 'confirmations', + 'height', + 'version', + 'versionHex', + 'merkleroot', + 'time', + 'mediantime', + 'nonce', + 'bits', + 'difficulty', + 'chainwork', + 'previousblockhash', + 'nextblockhash' ]) }) }) // - describe("#getBlockHeaderBulk", () => { - it("should throw an error for an empty body", async () => { + describe('#getBlockHeaderBulk', () => { + it('should throw an error for an empty body', async () => { req.body = {} const result = await uut.getBlockHeaderBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "hashes needs to be an array", - "Proper error message" + 'hashes needs to be an array', + 'Proper error message' ) }) - it("should error on non-array single hash", async () => { + it('should error on non-array single hash', async () => { req.body.hashes = - "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900" + '00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900' const result = await uut.getBlockHeaderBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "hashes needs to be an array", - "Proper error message" + 'hashes needs to be an array', + 'Proper error message' ) }) - it("should throw 400 error if addresses array is too large", async () => { + it('should throw 400 error if addresses array is too large', async () => { const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") + for (var i = 0; i < 25; i++) testArray.push('') req.body.hashes = testArray const result = await uut.getBlockHeaderBulk(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Array too large') }) - it("should throw a 400 error for an invalid hash", async () => { - req.body.hashes = ["badHash"] + it('should throw a 400 error for an invalid hash', async () => { + req.body.hashes = ['badHash'] await uut.getBlockHeaderBulk(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') }) - it("should throw 500 when network issues", async () => { + it('should throw 500 when network issues', async () => { const savedUrl = process.env.BITCOINCOM_BASEURL try { req.body.hashes = [ - "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900" + '00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900' ] // Switch the Insight URL to something that will error out. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" + process.env.BITCOINCOM_BASEURL = 'http://fakeurl/api/' const result = await uut.getBlockHeaderBulk(req, res) // Restore the saved URL. process.env.BITCOINCOM_BASEURL = savedUrl - assert.equal(res.statusCode, 500, "HTTP status code 500 expected.") - assert.include(result.error, "ENOTFOUND", "Error message expected") + assert.equal(res.statusCode, 500, 'HTTP status code 500 expected.') + assert.include(result.error, 'ENOTFOUND', 'Error message expected') } catch (err) { // Restore the saved URL. process.env.BITCOINCOM_BASEURL = savedUrl } }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) req.body.hashes = [ - "000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0" + '000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0' ] const result = await uut.getBlockHeaderBulk(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) req.body.hashes = [ - "000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0" + '000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0' ] const result = await uut.getBlockHeaderBulk(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should get concise block header for a single hash", async () => { + it('should get concise block header for a single hash', async () => { req.body.hashes = [ - "000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0" + '000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0' ] // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: mockData.mockBlockHeaderConcise } }) } @@ -555,22 +555,22 @@ describe("#BlockchainRouter", () => { assert.isArray(result) assert.equal( result[0], - "000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c" + '000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c' ) }) - it("should get verbose block header for a single hash", async () => { + it('should get verbose block header for a single hash', async () => { req.body = { hashes: [ - "000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0" + '000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0' ], verbose: true } // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: mockData.mockBlockHeader } }) } @@ -581,33 +581,33 @@ describe("#BlockchainRouter", () => { // Assert that required fields exist in the returned object. assert.isArray(result) assert.hasAllKeys(result[0], [ - "hash", - "confirmations", - "height", - "version", - "versionHex", - "merkleroot", - "time", - "mediantime", - "nonce", - "bits", - "difficulty", - "chainwork", - "previousblockhash", - "nextblockhash" + 'hash', + 'confirmations', + 'height', + 'version', + 'versionHex', + 'merkleroot', + 'time', + 'mediantime', + 'nonce', + 'bits', + 'difficulty', + 'chainwork', + 'previousblockhash', + 'nextblockhash' ]) }) - it("should get details for multiple block heights", async () => { + it('should get details for multiple block heights', async () => { req.body.hashes = [ - "000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0", - "000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0" + '000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0', + '000000000000000002fa9d7851b284c53a5831651b04211c266badf2ad2d8ef0' ] // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: mockData.mockBlockHeaderConcise } }) } @@ -616,16 +616,16 @@ describe("#BlockchainRouter", () => { // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) - assert.equal(result.length, 2, "2 outputs for 2 inputs") + assert.equal(result.length, 2, '2 outputs for 2 inputs') }) }) - describe("getChainTips()", () => { - it("should throw 503 when network issues", async () => { + describe('getChainTips()', () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' const result = await uut.getChainTips(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -633,47 +633,47 @@ describe("#BlockchainRouter", () => { // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) const result = await uut.getChainTips(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) const result = await uut.getChainTips(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should GET /getChainTips", async () => { + it('should GET /getChainTips', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: mockData.mockChainTips } }) } @@ -681,16 +681,16 @@ describe("#BlockchainRouter", () => { // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) - assert.hasAnyKeys(result[0], ["height", "hash", "branchlen", "status"]) + assert.hasAnyKeys(result[0], ['height', 'hash', 'branchlen', 'status']) }) }) - describe("getDifficulty()", () => { - it("should throw 503 when network issues", async () => { + describe('getDifficulty()', () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' const result = await uut.getDifficulty(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -698,47 +698,47 @@ describe("#BlockchainRouter", () => { // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) const result = await uut.getDifficulty(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) const result = await uut.getDifficulty(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should GET /getDifficulty", async () => { + it('should GET /getDifficulty', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: 4049809.205246544 } }) } @@ -748,13 +748,13 @@ describe("#BlockchainRouter", () => { assert.isNumber(result) }) }) - describe("getMempoolInfo()", () => { - it("should throw 503 when network issues", async () => { + describe('getMempoolInfo()', () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' const result = await uut.getMempoolInfo(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -762,47 +762,47 @@ describe("#BlockchainRouter", () => { // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) const result = await uut.getMempoolInfo(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) const result = await uut.getMempoolInfo(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should GET /getMempoolInfo", async () => { + it('should GET /getMempoolInfo', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: mockData.mockMempoolInfo } }) } @@ -810,21 +810,21 @@ describe("#BlockchainRouter", () => { // console.log(`result: ${util.inspect(result)}`) assert.hasAnyKeys(result, [ - "result", - "bytes", - "usage", - "maxmempool", - "mempoolminfree" + 'result', + 'bytes', + 'usage', + 'maxmempool', + 'mempoolminfree' ]) }) }) - describe("getRawMempool()", () => { - it("should throw 503 when network issues", async () => { + describe('getRawMempool()', () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' const result = await uut.getRawMempool(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -832,47 +832,47 @@ describe("#BlockchainRouter", () => { // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) const result = await uut.getRawMempool(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) const result = await uut.getRawMempool(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should GET /getMempoolInfo", async () => { + it('should GET /getMempoolInfo', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: mockData.mockRawMempool } }) } @@ -883,24 +883,24 @@ describe("#BlockchainRouter", () => { // Not sure what other assertions should be made here. }) }) - describe("getMempoolEntrySingle()", () => { - it("should throw 400 if txid is empty", async () => { + describe('getMempoolEntrySingle()', () => { + it('should throw 400 if txid is empty', async () => { const result = await uut.getMempoolEntrySingle(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'txid can not be empty') }) - it("should throw 503 when network issues", async () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' req.params.txid = - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' const result = await uut.getMempoolEntrySingle(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -908,197 +908,197 @@ describe("#BlockchainRouter", () => { // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) req.params.txid = - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' const result = await uut.getMempoolEntrySingle(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) req.params.txid = - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' const result = await uut.getMempoolEntrySingle(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should GET /getMempoolEntry", async () => { + it('should GET /getMempoolEntry', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { - sandbox.stub(uut.axios, "request").resolves({ - data: { result: { error: "Transaction not in mempool" } } + if (process.env.TEST === 'unit') { + sandbox.stub(uut.axios, 'request').resolves({ + data: { result: { error: 'Transaction not in mempool' } } }) } req.params.txid = - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' const result = await uut.getMempoolEntrySingle(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) + assert.hasAllKeys(result, ['error']) assert.isString(result.error) - assert.equal(result.error, "Transaction not in mempool") + assert.equal(result.error, 'Transaction not in mempool') }) }) - describe("#getMempoolEntryBulk", () => { - it("should throw an error for an empty body", async () => { + describe('#getMempoolEntryBulk', () => { + it('should throw an error for an empty body', async () => { req.body = {} const result = await uut.getMempoolEntryBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "txids needs to be an array", - "Proper error message" + 'txids needs to be an array', + 'Proper error message' ) }) - it("should error on non-array single txid", async () => { + it('should error on non-array single txid', async () => { req.body.txids = - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' const result = await uut.getMempoolEntryBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "txids needs to be an array", - "Proper error message" + 'txids needs to be an array', + 'Proper error message' ) }) - it("should throw 400 error if addresses array is too large", async () => { + it('should throw 400 error if addresses array is too large', async () => { const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") + for (var i = 0; i < 25; i++) testArray.push('') req.body.txids = testArray const result = await uut.getMempoolEntryBulk(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Array too large') }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) req.body.txids = [ - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' ] const result = await uut.getMempoolEntryBulk(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) req.body.txids = [ - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' ] const result = await uut.getMempoolEntryBulk(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) // Only execute on integration tests. - if (process.env.TEST !== "unit") { + if (process.env.TEST !== 'unit') { // Dev-note: This test passes because it expects an error. TXIDs do not // stay in the mempool for long, so it does not work well for a unit or // integration test. - it("should retrieve single mempool entry", async () => { + it('should retrieve single mempool entry', async () => { req.body.txids = [ - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' ] const result = await uut.getMempoolEntryBulk(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) + assert.hasAllKeys(result, ['error']) assert.isString(result.error) - assert.equal(result.error, "Transaction not in mempool") + assert.equal(result.error, 'Transaction not in mempool') }) // Dev-note: This test passes because it expects an error. TXIDs do not // stay in the mempool for long, so it does not work well for a unit or // integration test. - it("should retrieve multiple mempool entries", async () => { + it('should retrieve multiple mempool entries', async () => { req.body.txids = [ - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde", - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde', + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' ] const result = await uut.getMempoolEntryBulk(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) + assert.hasAllKeys(result, ['error']) assert.isString(result.error) - assert.equal(result.error, "Transaction not in mempool") + assert.equal(result.error, 'Transaction not in mempool') }) } }) - describe("getMempoolAncestorsSingle()", () => { - it("should throw 400 if txid is empty", async () => { + describe('getMempoolAncestorsSingle()', () => { + it('should throw 400 if txid is empty', async () => { const result = await uut.getMempoolAncestorsSingle(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'txid can not be empty') }) - it("should throw 503 when network issues", async () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' req.params.txid = - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' const result = await uut.getMempoolAncestorsSingle(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -1106,54 +1106,54 @@ describe("#BlockchainRouter", () => { // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) req.params.txid = - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' const result = await uut.getMempoolAncestorsSingle(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) req.params.txid = - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' const result = await uut.getMempoolAncestorsSingle(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should GET /getMempoolAncestorsSingle", async () => { + it('should GET /getMempoolAncestorsSingle', async () => { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: mockData.mockAncestors } }) req.params.txid = - "bb0d349892d351da2767f8c45f6f7949713ff09bd12838d53e76158ddee3ce93" + 'bb0d349892d351da2767f8c45f6f7949713ff09bd12838d53e76158ddee3ce93' const result = await uut.getMempoolAncestorsSingle(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -1161,33 +1161,33 @@ describe("#BlockchainRouter", () => { assert.isArray(result) }) }) - describe("getTxOut()", () => { - it("should throw 400 if txid is empty", async () => { + describe('getTxOut()', () => { + it('should throw 400 if txid is empty', async () => { const result = await uut.getTxOut(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'txid can not be empty') }) - it("should throw 400 if n is empty", async () => { - req.params.txid = "sometxid" + it('should throw 400 if n is empty', async () => { + req.params.txid = 'sometxid' const result = await uut.getTxOut(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "n can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'n can not be empty') }) - it("should throw 503 when network issues", async () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' req.params.txid = - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' req.params.n = 0 const result = await uut.getTxOut(req, res) @@ -1196,104 +1196,104 @@ describe("#BlockchainRouter", () => { // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) req.params.txid = - "197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d" + '197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d' req.params.n = 0 - req.query.include_mempool = "true" + req.query.include_mempool = 'true' const result = await uut.getTxOut(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) req.params.txid = - "197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d" + '197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d' req.params.n = 0 - req.query.include_mempool = "true" + req.query.include_mempool = 'true' const result = await uut.getTxOut(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) // This test can only run for unit tests. See TODO at the top of this file. - it("should GET /getTxOut", async () => { + it('should GET /getTxOut', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: mockData.mockTxOut } }) } req.params.txid = - "197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d" + '197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d' req.params.n = 0 - req.query.include_mempool = "true" + req.query.include_mempool = 'true' const result = await uut.getTxOut(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) assert.hasAllKeys(result, [ - "bestblock", - "confirmations", - "value", - "scriptPubKey", - "coinbase" + 'bestblock', + 'confirmations', + 'value', + 'scriptPubKey', + 'coinbase' ]) assert.hasAllKeys(result.scriptPubKey, [ - "asm", - "hex", - "reqSigs", - "type", - "addresses" + 'asm', + 'hex', + 'reqSigs', + 'type', + 'addresses' ]) assert.isArray(result.scriptPubKey.addresses) }) }) - describe("getTxOutProofSingle()", () => { - it("should throw 400 if txid is empty", async () => { + describe('getTxOutProofSingle()', () => { + it('should throw 400 if txid is empty', async () => { const result = await uut.getTxOutProofSingle(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'txid can not be empty') }) - it("should throw 503 when network issues", async () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' req.params.txid = - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' const result = await uut.getTxOutProofSingle(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -1301,62 +1301,62 @@ describe("#BlockchainRouter", () => { // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) req.params.txid = - "197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d" + '197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d' req.params.n = 0 - req.query.include_mempool = "true" + req.query.include_mempool = 'true' const result = await uut.getTxOutProofSingle(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) req.params.txid = - "197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d" + '197dcda59864b1eee05498fd3c52cad787ec56ab7e635503cb39f9ab6f295d5d' req.params.n = 0 - req.query.include_mempool = "true" + req.query.include_mempool = 'true' const result = await uut.getTxOutProofSingle(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should GET /getTxOutProof", async () => { + it('should GET /getTxOutProof', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: mockData.mockTxOutProof } }) } req.params.txid = - "2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266" + '2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266' const result = await uut.getTxOutProofSingle(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) @@ -1364,93 +1364,93 @@ describe("#BlockchainRouter", () => { assert.isString(result) }) }) - describe("#getTxOutProofBulk", () => { - it("should throw an error for an empty body", async () => { + describe('#getTxOutProofBulk', () => { + it('should throw an error for an empty body', async () => { req.body = {} const result = await uut.getTxOutProofBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "txids needs to be an array", - "Proper error message" + 'txids needs to be an array', + 'Proper error message' ) }) - it("should error on non-array single txid", async () => { + it('should error on non-array single txid', async () => { req.body.txids = - "d65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde" + 'd65881582ff2bff36747d7a0d0e273f10281abc8bd5c15df5d72f8f3fa779cde' const result = await uut.getTxOutProofBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "txids needs to be an array", - "Proper error message" + 'txids needs to be an array', + 'Proper error message' ) }) - it("should throw 400 error if addresses array is too large", async () => { + it('should throw 400 error if addresses array is too large', async () => { const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") + for (var i = 0; i < 25; i++) testArray.push('') req.body.txids = testArray const result = await uut.getTxOutProofBulk(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Array too large') }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) req.body.txids = [ - "2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266" + '2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266' ] const result = await uut.getTxOutProofBulk(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) req.body.txids = [ - "2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266" + '2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266' ] const result = await uut.getTxOutProofBulk(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should GET proof for single txid", async () => { + it('should GET proof for single txid', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: mockData.mockTxOutProof } }) } req.body.txids = [ - "2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266" + '2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266' ] const result = await uut.getTxOutProofBulk(req, res) @@ -1460,41 +1460,41 @@ describe("#BlockchainRouter", () => { assert.isString(result[0]) }) - it("should GET proof for multiple txids", async () => { + it('should GET proof for multiple txids', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: mockData.mockTxOutProof } }) } req.body.txids = [ - "2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266", - "2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266" + '2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266', + '2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266' ] const result = await uut.getTxOutProofBulk(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) assert.isArray(result) - assert.equal(result.length, 2, "Correct length of returned array") + assert.equal(result.length, 2, 'Correct length of returned array') }) }) - describe("verifyTxOutProofSingle()", () => { - it("should throw 400 if proof is empty", async () => { + describe('verifyTxOutProofSingle()', () => { + it('should throw 400 if proof is empty', async () => { const result = await uut.verifyTxOutProofSingle(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "proof can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'proof can not be empty') }) - it("should throw 503 when network issues", async () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' req.params.proof = mockData.mockTxOutProof @@ -1504,60 +1504,60 @@ describe("#BlockchainRouter", () => { // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) req.params.proof = - "000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700" + '000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700' const result = await uut.verifyTxOutProofSingle(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) req.params.proof = - "000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700" + '000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700' const result = await uut.verifyTxOutProofSingle(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should GET /verifyTxOutProof", async () => { + it('should GET /verifyTxOutProof', async () => { const expected = - "2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266" + '2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266' // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: [expected] } }) } req.params.proof = - "000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700" + '000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700' const result = await uut.verifyTxOutProofSingle(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) @@ -1567,94 +1567,94 @@ describe("#BlockchainRouter", () => { assert.equal(result[0], expected) }) }) - describe("#verifyTxOutProofBulk", () => { - it("should throw an error for an empty body", async () => { + describe('#verifyTxOutProofBulk', () => { + it('should throw an error for an empty body', async () => { req.body = {} const result = await uut.verifyTxOutProofBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "proofs needs to be an array", - "Proper error message" + 'proofs needs to be an array', + 'Proper error message' ) }) - it("should error on non-array single txid", async () => { + it('should error on non-array single txid', async () => { req.body.proofs = mockData.mockTxOutProof const result = await uut.verifyTxOutProofBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "proofs needs to be an array", - "Proper error message" + 'proofs needs to be an array', + 'Proper error message' ) }) - it("should throw 400 error if addresses array is too large", async () => { + it('should throw 400 error if addresses array is too large', async () => { const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") + for (var i = 0; i < 25; i++) testArray.push('') req.body.proofs = testArray const result = await uut.verifyTxOutProofBulk(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Array too large') }) - it("returns proper error when downstream service stalls", async () => { + it('returns proper error when downstream service stalls', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNABORTED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNABORTED' }) req.body.proofs = [ - "000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700" + '000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700' ] const result = await uut.verifyTxOutProofBulk(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("returns proper error when downstream service is down", async () => { + it('returns proper error when downstream service is down', async () => { // Mock the timeout error. - sandbox.stub(uut.axios, "request").throws({ code: "ECONNREFUSED" }) + sandbox.stub(uut.axios, 'request').throws({ code: 'ECONNREFUSED' }) req.body.proofs = [ - "000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700" + '000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700' ] const result = await uut.verifyTxOutProofBulk(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.isAbove(res.statusCode, 499, "HTTP status code 503 expected.") + assert.isAbove(res.statusCode, 499, 'HTTP status code 503 expected.') assert.include( result.error, - "Could not communicate with full node", - "Error message expected" + 'Could not communicate with full node', + 'Error message expected' ) }) - it("should get single proof", async () => { + it('should get single proof', async () => { const expected = - "2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266" + '2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266' // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: [expected] } }) } req.body.proofs = [ - "000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700" + '000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700' ] const result = await uut.verifyTxOutProofBulk(req, res) @@ -1665,20 +1665,20 @@ describe("#BlockchainRouter", () => { assert.equal(result[0], expected) }) - it("should get multiple proofs", async () => { + it('should get multiple proofs', async () => { const expected = - "2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266" + '2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266' // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox - .stub(uut.axios, "request") + .stub(uut.axios, 'request') .resolves({ data: { result: [expected] } }) } req.body.proofs = [ - "000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700", - "000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700" + '000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700', + '000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c1e000000067139f230701a2819a76795564bd2f67ded7eeae68596f368eddb3dd5bc54e59320e896f71d61cfc3ae3d4a90fca08b1aa35ba91256d8939d2cad11e638c0081f66724abdef55cf7b8b9fed064bce0369171434f8b289c1330ccef765f8e97a2c0d794d81aafb535855f7daa6bb51e40f77c6b59d7af7f62d0eb726a4fc4df82353d56fcbda7c7ea6bd935d61af8fb3b295637e6f323b10231135b3f10a034cfb238f635830c0595e52c6c31247cf677b555f7a287076e20cd0e1d3cc9af7260f02b700' ] const result = await uut.verifyTxOutProofBulk(req, res) diff --git a/test/v3/control.js b/test/v3/control.js index e651b26..313349a 100644 --- a/test/v3/control.js +++ b/test/v3/control.js @@ -7,24 +7,24 @@ */ -"use strict" +'use strict' -const chai = require("chai") +const chai = require('chai') const assert = chai.assert -const controlRoute = require("../../src/routes/v3/full-node/control") -const nock = require("nock") // HTTP mocking +const controlRoute = require('../../src/routes/v3/full-node/control') +const nock = require('nock') // HTTP mocking let originalEnvVars // Used during transition from integration to unit tests. // Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/control-mock") +const { mockReq, mockRes } = require('./mocks/express-mocks') +const mockData = require('./mocks/control-mock') // Used for debugging. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -describe("#ControlRouter", () => { +describe('#ControlRouter', () => { let req, res before(() => { @@ -37,12 +37,12 @@ describe("#ControlRouter", () => { } // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") { - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api" - process.env.RPC_USERNAME = "fakeusername" - process.env.RPC_PASSWORD = "fakepassword" + if (!process.env.TEST) process.env.TEST = 'unit' + if (process.env.TEST === 'unit') { + process.env.BITCOINCOM_BASEURL = 'http://fakeurl/api/' + process.env.RPC_BASEURL = 'http://fakeurl/api' + process.env.RPC_USERNAME = 'fakeusername' + process.env.RPC_PASSWORD = 'fakepassword' } }) @@ -75,30 +75,30 @@ describe("#ControlRouter", () => { process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD }) - describe("#root", async () => { + describe('#root', async () => { // root route handler. const root = controlRoute.testableComponents.root - it("should respond to GET for base route", async () => { + it('should respond to GET for base route', async () => { const result = root(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.equal(result.status, "control", "Returns static string") + assert.equal(result.status, 'control', 'Returns static string') }) }) - describe("#GetNetworkInfo", () => { + describe('#GetNetworkInfo', () => { const getNetworkInfo = controlRoute.testableComponents.getNetworkInfo - it("should throw 500 when network issues", async () => { + it('should throw 500 when network issues', async () => { // Save the existing RPC URL. const savedUrl = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' - const result = await getNetworkInfo(req, res) - //console.log(`result: ${util.inspect(result)}`) + await getNetworkInfo(req, res) + // console.log(`result: ${util.inspect(result)}`) // Restore the saved URL. process.env.RPC_BASEURL = savedUrl @@ -106,36 +106,36 @@ describe("#ControlRouter", () => { assert.isAbove( res.statusCode, 499, - "HTTP status code 500 or greater expected." + 'HTTP status code 500 or greater expected.' ) - //assert.include(result.error, "ENOTFOUND", "Error message expected") + // assert.include(result.error, "ENOTFOUND", "Error message expected") }) - it("should get info on the full node", async () => { + it('should get info on the full node', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: mockData.mockGetNetworkInfo }) } const result = await getNetworkInfo(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.hasAnyKeys(result, [ - "version", - "subversion", - "protocolversion", - "localservices", - "localrelay", - "timeoffset", - "networkactive", - "connections", - "networks", - "relayfee", - "excessutxocharge", - "localaddresses", - "warnings" + 'version', + 'subversion', + 'protocolversion', + 'localservices', + 'localrelay', + 'timeoffset', + 'networkactive', + 'connections', + 'networks', + 'relayfee', + 'excessutxocharge', + 'localaddresses', + 'warnings' ]) }) }) diff --git a/test/v3/e2e/address.js b/test/v3/e2e/address.js index 878ad9e..8656761 100644 --- a/test/v3/e2e/address.js +++ b/test/v3/e2e/address.js @@ -3,11 +3,11 @@ These tests assume that the repo is running locally and pointed at TESTNET */ -"use strict" +'use strict' -const rp = require("request-promise") +const rp = require('request-promise') -const rawtransactions = require("../../../dist/routes/v2/address") +// const rawtransactions = require('../../../dist/routes/v2/address') /* This unconfirmed utxo test needs to be expanded in the future to automatically @@ -19,19 +19,19 @@ const rawtransactions = require("../../../dist/routes/v2/address") 3. Run this program with `node address.js` 4. If successful, it will return the unconfirmed UTXOs. */ -const addr1 = "bchtest:qpdcp5pv7qphu5tsjfgwezld9n9aq9ue6swgqpf45c" -const addr2 = "bchtest:qzpvx999fagau0xqmvu3xvll9evapge7u5hcgeknzv" +const addr1 = 'bchtest:qpdcp5pv7qphu5tsjfgwezld9n9aq9ue6swgqpf45c' +const addr2 = 'bchtest:qzpvx999fagau0xqmvu3xvll9evapge7u5hcgeknzv' -async function testSingleUnconfirmed() { +async function testSingleUnconfirmed () { try { const options = { - method: "GET", + method: 'GET', uri: `http://localhost:3000/v2/address/unconfirmed/${addr1}`, resolveWithFullResponse: true, json: true } - const result = await rp(options) + await rp(options) // console.log(`result.body: ${JSON.stringify(result.body, null, 2)}`) } catch (err) { // console.log(`Error: `, err) @@ -39,11 +39,11 @@ async function testSingleUnconfirmed() { } testSingleUnconfirmed() -async function testDoubleUnconfirmed() { +async function testDoubleUnconfirmed () { try { const options = { - method: "POST", - uri: `http://localhost:3000/v2/address/unconfirmed`, + method: 'POST', + uri: 'http://localhost:3000/v2/address/unconfirmed', resolveWithFullResponse: true, json: true, body: { @@ -51,7 +51,7 @@ async function testDoubleUnconfirmed() { } } - const result = await rp(options) + await rp(options) // console.log(`result.body: ${JSON.stringify(result.body, null, 2)}`) } catch (err) { // console.log(`Error: `, err) diff --git a/test/v3/helpers/panda.js b/test/v3/helpers/panda.js index 48a7d7f..40c584f 100644 --- a/test/v3/helpers/panda.js +++ b/test/v3/helpers/panda.js @@ -1,9 +1,9 @@ -"use strict" +'use strict' /** * Read more about panda here: https://panda-suite.github.io/ */ -const panda = require("pandacash-core") +const panda = require('pandacash-core') const runLocalNode = done => { const server = panda.server({ @@ -16,7 +16,7 @@ const runLocalNode = done => { server.listen({ port: 48332, - walletPort: 48333, + walletPort: 48333 }, (err, pandaCashCore) => { if (err) return console.error(err) diff --git a/test/v3/integration/rate-limits.js b/test/v3/integration/rate-limits.js index 4142369..c26790b 100644 --- a/test/v3/integration/rate-limits.js +++ b/test/v3/integration/rate-limits.js @@ -4,42 +4,42 @@ in the tests below to match the rate limit setting in your own installation. */ -"use strict" +'use strict' -const chai = require("chai") +const chai = require('chai') const assert = chai.assert -const axios = require("axios") +const axios = require('axios') // Used for debugging. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } // const SERVER = `http://192.168.0.36:12400/v3/` -const SERVER = `http://localhost:3000/v3/` +const SERVER = 'http://localhost:3000/v3/' const TEST_JWT = - "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVlM2EwNDE1ZWIyOWE5NjJkYTI3MDhiNCIsImFwaUxldmVsIjowLCJyYXRlTGltaXQiOjEwLCJpYXQiOjE1ODA4NjA0NjcsImV4cCI6MTU4MzQ1MjQ2N30.fuY5S-YrF0J11h5uyMjPe7wiVkYRnIyXi4dL9-V-C6pLJm33p0dSq_pSheVVWw78n5kAvL_9kFHngbnmQiOJYQ" + 'eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVlM2EwNDE1ZWIyOWE5NjJkYTI3MDhiNCIsImFwaUxldmVsIjowLCJyYXRlTGltaXQiOjEwLCJpYXQiOjE1ODA4NjA0NjcsImV4cCI6MTU4MzQ1MjQ2N30.fuY5S-YrF0J11h5uyMjPe7wiVkYRnIyXi4dL9-V-C6pLJm33p0dSq_pSheVVWw78n5kAvL_9kFHngbnmQiOJYQ' -describe("#rate limits", () => { - it("should get control/getNetworkInfo() with no auth", async () => { +describe('#rate limits', () => { + it('should get control/getNetworkInfo() with no auth', async () => { const options = { - method: "GET", + method: 'GET', url: `${SERVER}control/getNetworkInfo` } const result = await axios(options) - //console.log(`result.status: ${result.status}`) + // console.log(`result.status: ${result.status}`) // console.log(`result.data: ${util.inspect(result.data)}`) assert.equal(result.status, 200) - assert.hasAnyKeys(result.data, ["version"]) + assert.hasAnyKeys(result.data, ['version']) }) - it("should trigger rate-limit handler if rate limits exceeds 30 request per minute", async () => { + it('should trigger rate-limit handler if rate limits exceeds 30 request per minute', async () => { try { // Actual rate limit is 60 per minute X 4 nodes = 240 rpm. const options = { - method: "GET", + method: 'GET', url: `${SERVER}control/getNetworkInfo` } @@ -51,29 +51,29 @@ describe("#rate limits", () => { await Promise.all(promises) - assert.equal(true, false, "Unexpected result!") + assert.equal(true, false, 'Unexpected result!') } catch (err) { - //console.log(`err.response: ${util.inspect(err.response)}`) + // console.log(`err.response: ${util.inspect(err.response)}`) assert.equal(err.response.status, 429) - assert.include(err.response.data.error, "Too many requests") + assert.include(err.response.data.error, 'Too many requests') } }) - it("should not trigger rate-limit handler if correct pro-tier password is used", async () => { + it('should not trigger rate-limit handler if correct pro-tier password is used', async () => { try { - const username = "BITBOX" + const username = 'BITBOX' // Pro-tier is accessed by using the right password. - const password = "BITBOX" - //const password = "something" + const password = 'BITBOX' + // const password = "something" const combined = `${username}:${password}` - const base64Credential = Buffer.from(combined).toString("base64") + const base64Credential = Buffer.from(combined).toString('base64') const readyCredential = `Basic ${base64Credential}` const options = { - method: "GET", + method: 'GET', url: `${SERVER}control/getNetworkInfo`, headers: { Authorization: readyCredential } } @@ -86,33 +86,33 @@ describe("#rate limits", () => { await Promise.all(promises) - assert.equal(true, true, "Not throwing an error is a pass!") + assert.equal(true, true, 'Not throwing an error is a pass!') } catch (err) { // console.log(`err.response: ${util.inspect(err.response)}`) assert.equal( true, false, - "This error handler should not have been triggered. Is the password correct?" + 'This error handler should not have been triggered. Is the password correct?' ) } }) - it("should trigger rate-limit handler if rate limits exceeds pro-tier limit", async () => { + it('should trigger rate-limit handler if rate limits exceeds pro-tier limit', async () => { try { - const username = "BITBOX" + const username = 'BITBOX' // Pro-tier is accessed by using the right password. - const password = "BITBOX" - //const password = "something" + const password = 'BITBOX' + // const password = "something" const combined = `${username}:${password}` - const base64Credential = Buffer.from(combined).toString("base64") + const base64Credential = Buffer.from(combined).toString('base64') const readyCredential = `Basic ${base64Credential}` // Actual rate limit is 60 per minute X 4 nodes = 240 rpm. const options = { - method: "GET", + method: 'GET', url: `${SERVER}control/getNetworkInfo`, headers: { Authorization: readyCredential } } @@ -125,20 +125,20 @@ describe("#rate limits", () => { await Promise.all(promises) - assert.equal(true, false, "Unexpected result!") + assert.equal(true, false, 'Unexpected result!') } catch (err) { - //console.log(`err.response: ${util.inspect(err.response)}`) + // console.log(`err.response: ${util.inspect(err.response)}`) assert.equal(err.response.status, 429) - assert.include(err.response.data.error, "Too many requests") + assert.include(err.response.data.error, 'Too many requests') } }) - it("should unlock pro-tier for a valid JWT token", async () => { + it('should unlock pro-tier for a valid JWT token', async () => { try { // Actual rate limit is 60 per minute X 4 nodes = 240 rpm. const options = { - method: "GET", + method: 'GET', url: `${SERVER}control/`, headers: { Authorization: `Token ${TEST_JWT}` @@ -153,12 +153,12 @@ describe("#rate limits", () => { await Promise.all(promises) - //assert.equal(true, false, "Unexpected result!") - assert.equal(true, true, "Not throwing an error is a pass!") + // assert.equal(true, false, "Unexpected result!") + assert.equal(true, true, 'Not throwing an error is a pass!') } catch (err) { console.log(`err.response: ${util.inspect(err.response)}`) - assert.equal(true, false, "Unexpected result!") + assert.equal(true, false, 'Unexpected result!') } // Override default timeout for this test. }).timeout(20000) diff --git a/test/v3/integration/raw-transactions.js b/test/v3/integration/raw-transactions.js index 7c17347..6668957 100644 --- a/test/v3/integration/raw-transactions.js +++ b/test/v3/integration/raw-transactions.js @@ -9,129 +9,129 @@ so it is omitted here. */ -"use strict" +'use strict' -const chai = require("chai") +const chai = require('chai') const assert = chai.assert -const rawtransactions = require("../../../dist/routes/v2/rawtransactions") -const rp = require("request-promise") +// const rawtransactions = require('../../../dist/routes/v2/rawtransactions') +const rp = require('request-promise') // Used for debugging. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -const mockData = require("../mocks/raw-transactions-mocks") +// const mockData = require('../mocks/raw-transactions-mocks') -describe("#Raw-Transactions", () => { - describe("#root", () => { - it(`should return root`, async () => { +describe('#Raw-Transactions', () => { + describe('#root', () => { + it('should return root', async () => { const options = { - method: "GET", - uri: `http://localhost:3000/v2/rawtransactions/`, + method: 'GET', + uri: 'http://localhost:3000/v2/rawtransactions/', resolveWithFullResponse: true, json: true } const result = await rp(options) - //console.log(`result: ${JSON.stringify(result, null, 0)}`) + // console.log(`result: ${JSON.stringify(result, null, 0)}`) - assert.equal(result.body.status, "rawtransactions") + assert.equal(result.body.status, 'rawtransactions') }) }) - describe("#whCreateTx", () => { - it(`should return tx hex`, async () => { + describe('#whCreateTx', () => { + it('should return tx hex', async () => { const minIn = { txid: - "f7ed9cf23dee85910f6269c9a101a75fcfd2f3c6fc81f17fad824ff7aaf99ab2", + 'f7ed9cf23dee85910f6269c9a101a75fcfd2f3c6fc81f17fad824ff7aaf99ab2', vout: 1 } const options = { - method: "PUT", - uri: `http://localhost:3000/v2/rawtransactions/create`, + method: 'PUT', + uri: 'http://localhost:3000/v2/rawtransactions/create', resolveWithFullResponse: true, json: true, body: { - //inputs: [mockData.mockWHCreateInput], + // inputs: [mockData.mockWHCreateInput], inputs: [minIn], outputs: {} } } const result = await rp(options) - //console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) + // console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) assert.equal( result.body, - "0200000001b29af9aaf74f82ad7ff181fcc6f3d2cf5fa701a1c969620f9185ee3df29cedf70100000000ffffffff0000000000" + '0200000001b29af9aaf74f82ad7ff181fcc6f3d2cf5fa701a1c969620f9185ee3df29cedf70100000000ffffffff0000000000' ) }) }) - describe("#whOpReturn", () => { - it(`should return tx hex`, async () => { + describe('#whOpReturn', () => { + it('should return tx hex', async () => { const options = { - method: "PUT", - uri: `http://localhost:3000/v2/rawtransactions/opreturn`, + method: 'PUT', + uri: 'http://localhost:3000/v2/rawtransactions/opreturn', resolveWithFullResponse: true, json: true, body: { - rawtx: "01000000000000000000", - payload: "00000000000000020000000006dac2c0" + rawtx: '01000000000000000000', + payload: '00000000000000020000000006dac2c0' } } const result = await rp(options) - //console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) + // console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) assert.equal( result.body, - "0100000000010000000000000000166a140877686300000000000000020000000006dac2c000000000" + '0100000000010000000000000000166a140877686300000000000000020000000006dac2c000000000' ) }) }) - describe("#whReference", () => { - it(`should return tx hex`, async () => { + describe('#whReference', () => { + it('should return tx hex', async () => { const options = { - method: "PUT", - uri: `http://localhost:3000/v2/rawtransactions/reference`, + method: 'PUT', + uri: 'http://localhost:3000/v2/rawtransactions/reference', resolveWithFullResponse: true, json: true, body: { rawtx: - "0100000001a7a9402ecd77f3c9f745793c9ec805bfa2e14b89877581c734c774864247e6f50400000000ffffffff03aa0a0000000000001976a9146d18edfe073d53f84dd491dae1379f8fb0dfe5d488ac5c0d0000000000004751210252ce4bdd3ce38b4ebbc5a6e1343608230da508ff12d23d85b58c964204c4cef3210294cc195fc096f87d0f813a337ae7e5f961b1c8a18f1f8604a909b3a5121f065b52aeaa0a0000000000001976a914946cb2e08075bcbaf157e47bcb67eb2b2339d24288ac00000000", - destination: "bitcoincash:qrn60nerx5zug4u4hal06atep3lzhtecvy4pxk75lf", + '0100000001a7a9402ecd77f3c9f745793c9ec805bfa2e14b89877581c734c774864247e6f50400000000ffffffff03aa0a0000000000001976a9146d18edfe073d53f84dd491dae1379f8fb0dfe5d488ac5c0d0000000000004751210252ce4bdd3ce38b4ebbc5a6e1343608230da508ff12d23d85b58c964204c4cef3210294cc195fc096f87d0f813a337ae7e5f961b1c8a18f1f8604a909b3a5121f065b52aeaa0a0000000000001976a914946cb2e08075bcbaf157e47bcb67eb2b2339d24288ac00000000', + destination: 'bitcoincash:qrn60nerx5zug4u4hal06atep3lzhtecvy4pxk75lf', amount: 0.005 } } const result = await rp(options) - //console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) + // console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) assert.isString(result.body) }) }) - describe("#whChangeOutput", () => { - it(`should return tx hex`, async () => { + describe('#whChangeOutput', () => { + it('should return tx hex', async () => { const options = { - method: "PUT", - uri: `http://localhost:3000/v2/rawtransactions/change`, + method: 'PUT', + uri: 'http://localhost:3000/v2/rawtransactions/change', resolveWithFullResponse: true, json: true, body: { rawtx: - "0100000001b15ee60431ef57ec682790dec5a3c0d83a0c360633ea8308fbf6d5fc10a779670400000000ffffffff025c0d00000000000047512102f3e471222bb57a7d416c82bf81c627bfcd2bdc47f36e763ae69935bba4601ece21021580b888ff56feb27f17f08802ebed26258c23697d6a462d43fc13b565fda2dd52aeaa0a0000000000001976a914946cb2e08075bcbaf157e47bcb67eb2b2339d24288ac00000000", - destination: "bitcoincash:qrn60nerx5zug4u4hal06atep3lzhtecvy4pxk75lf", + '0100000001b15ee60431ef57ec682790dec5a3c0d83a0c360633ea8308fbf6d5fc10a779670400000000ffffffff025c0d00000000000047512102f3e471222bb57a7d416c82bf81c627bfcd2bdc47f36e763ae69935bba4601ece21021580b888ff56feb27f17f08802ebed26258c23697d6a462d43fc13b565fda2dd52aeaa0a0000000000001976a914946cb2e08075bcbaf157e47bcb67eb2b2339d24288ac00000000', + destination: 'bitcoincash:qrn60nerx5zug4u4hal06atep3lzhtecvy4pxk75lf', prevtxs: [ { txid: - "6779a710fcd5f6fb0883ea3306360c3ad8c0a3c5de902768ec57ef3104e65eb1", + '6779a710fcd5f6fb0883ea3306360c3ad8c0a3c5de902768ec57ef3104e65eb1', vout: 4, scriptPubKey: - "76a9147b25205fd98d462880a3e5b0541235831ae959e588ac", + '76a9147b25205fd98d462880a3e5b0541235831ae959e588ac', value: 0.00068257 } ], @@ -140,43 +140,43 @@ describe("#Raw-Transactions", () => { } const result = await rp(options) - //console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) + // console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) assert.isString(result.body) }) }) - describe("#whInput", () => { - it(`should return tx hex`, async () => { + describe('#whInput', () => { + it('should return tx hex', async () => { const options = { - method: "PUT", - uri: `http://localhost:3000/v2/rawtransactions/input`, + method: 'PUT', + uri: 'http://localhost:3000/v2/rawtransactions/input', resolveWithFullResponse: true, json: true, body: { txid: - "b006729017df05eda586df9ad3f8ccfee5be340aadf88155b784d1fc0e8342ee", + 'b006729017df05eda586df9ad3f8ccfee5be340aadf88155b784d1fc0e8342ee', n: 0 } } const result = await rp(options) - //console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) + // console.log(`result.body: ${JSON.stringify(result.body, null, 0)}`) assert.isString(result.body) }) }) - describe("#getRawTransaction", () => { - it(`should return tx hex`, async () => { + describe('#getRawTransaction', () => { + it('should return tx hex', async () => { const options = { - method: "POST", - uri: `http://localhost:3000/v2/rawtransactions/getRawTransaction`, + method: 'POST', + uri: 'http://localhost:3000/v2/rawtransactions/getRawTransaction', resolveWithFullResponse: true, json: true, body: { txids: [ - "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098" + '0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098' ], verbose: true } diff --git a/test/v3/mining.js b/test/v3/mining.js index 7ba81c4..33a0fca 100644 --- a/test/v3/mining.js +++ b/test/v3/mining.js @@ -6,24 +6,24 @@ to 'integration' to run the tests against BCH mainnet. */ -"use strict" +'use strict' -const chai = require("chai") +const chai = require('chai') const assert = chai.assert -const miningRoute = require("../../src/routes/v3/full-node/mining") -const nock = require("nock") // HTTP mocking +const miningRoute = require('../../src/routes/v3/full-node/mining') +const nock = require('nock') // HTTP mocking let originalEnvVars // Used during transition from integration to unit tests. // Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/mining-mocks") +const { mockReq, mockRes } = require('./mocks/express-mocks') +const mockData = require('./mocks/mining-mocks') // Used for debugging. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -describe("#Mining", () => { +describe('#Mining', () => { let req, res before(() => { @@ -36,12 +36,12 @@ describe("#Mining", () => { } // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") { - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api" - process.env.RPC_USERNAME = "fakeusername" - process.env.RPC_PASSWORD = "fakepassword" + if (!process.env.TEST) process.env.TEST = 'unit' + if (process.env.TEST === 'unit') { + process.env.BITCOINCOM_BASEURL = 'http://fakeurl/api/' + process.env.RPC_BASEURL = 'http://fakeurl/api' + process.env.RPC_USERNAME = 'fakeusername' + process.env.RPC_PASSWORD = 'fakepassword' } }) @@ -74,30 +74,30 @@ describe("#Mining", () => { process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD }) - describe("#root", async () => { + describe('#root', async () => { // root route handler. const root = miningRoute.testableComponents.root - it("should respond to GET for base route", async () => { + it('should respond to GET for base route', async () => { const result = root(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.equal(result.status, "mining", "Returns static string") + assert.equal(result.status, 'mining', 'Returns static string') }) }) - describe("#getMiningInfo", async () => { + describe('#getMiningInfo', async () => { const getMiningInfo = miningRoute.testableComponents.getMiningInfo - it("should throw 503 when network issues", async () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' - const result = await getMiningInfo(req, res) - //console.log(`result: ${util.inspect(result)}`) + await getMiningInfo(req, res) + // console.log(`result: ${util.inspect(result)}`) // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 @@ -105,48 +105,48 @@ describe("#Mining", () => { assert.isAbove( res.statusCode, 499, - "HTTP status code 500 or greater expected." + 'HTTP status code 500 or greater expected.' ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") + // assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") }) - it("should GET mining information", async () => { + it('should GET mining information', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: mockData.mockMiningInfo }) } const result = await getMiningInfo(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.hasAllKeys(result, [ - "blocks", - "currentblocksize", - "currentblocktx", - "difficulty", - "blockprioritypercentage", - "warnings", - "networkhashps", - "pooledtx", - "chain" + 'blocks', + 'currentblocksize', + 'currentblocktx', + 'difficulty', + 'blockprioritypercentage', + 'warnings', + 'networkhashps', + 'pooledtx', + 'chain' ]) }) }) - describe("#getNetworkHashPS", async () => { + describe('#getNetworkHashPS', async () => { const getNetworkHashPS = miningRoute.testableComponents.getNetworkHashPS - it("should throw 503 when network issues", async () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' - const result = await getNetworkHashPS(req, res) - //console.log(`result: ${util.inspect(result)}`) + await getNetworkHashPS(req, res) + // console.log(`result: ${util.inspect(result)}`) // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 @@ -154,21 +154,21 @@ describe("#Mining", () => { assert.isAbove( res.statusCode, 499, - "HTTP status code 500 or greater expected." + 'HTTP status code 500 or greater expected.' ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") + // assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") }) - it("should GET Network Hash per second", async () => { + it('should GET Network Hash per second', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: 517604755.6648782 }) } const result = await getNetworkHashPS(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isNumber(result) }) diff --git a/test/v3/mocks/address-mock.js b/test/v3/mocks/address-mock.js index 7d4e3b9..a2666a2 100644 --- a/test/v3/mocks/address-mock.js +++ b/test/v3/mocks/address-mock.js @@ -2,10 +2,10 @@ This library contains mocking data for running unit tests on the address route. */ -"use strict" +'use strict' const mockAddressDetails = { - addrStr: "1Fg4r9iDrEkCcDmHTy2T79EusNfhyQpu7W", + addrStr: '1Fg4r9iDrEkCcDmHTy2T79EusNfhyQpu7W', balance: 0.00126419, balanceSat: 126419, totalReceived: 0.02175868, @@ -17,17 +17,17 @@ const mockAddressDetails = { unconfirmedTxApperances: 0, txApperances: 3, transactions: [ - "2dc053f55a666a3d2a08b1c680b704d62a55506d14ad884add87edcc56b9277d", - "544c15ce35c0f2e808d28f29d6587f1ec9276233e29856b7f2938cf0daef0026", - "81039b1d7b855b133f359f9dc65f776bd105650153a941675fedc504228ddbd3" + '2dc053f55a666a3d2a08b1c680b704d62a55506d14ad884add87edcc56b9277d', + '544c15ce35c0f2e808d28f29d6587f1ec9276233e29856b7f2938cf0daef0026', + '81039b1d7b855b133f359f9dc65f776bd105650153a941675fedc504228ddbd3' ], - legacyAddress: "1Fg4r9iDrEkCcDmHTy2T79EusNfhyQpu7W", - cashAddress: "bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c" + legacyAddress: '1Fg4r9iDrEkCcDmHTy2T79EusNfhyQpu7W', + cashAddress: 'bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c' } const mockUtxoDetails = [ { - txid: "15f6a584080b04911121fbaca7bfcf3dd64ef2bfa5a01daf31e05a296c3e5e9e", + txid: '15f6a584080b04911121fbaca7bfcf3dd64ef2bfa5a01daf31e05a296c3e5e9e', vout: 286, amount: 0.00001, satoshis: 1000, @@ -35,7 +35,7 @@ const mockUtxoDetails = [ confirmations: 3490 }, { - txid: "15f6a584080b04911121fbaca7bfcf3dd64ef2bfa5a01daf31e05a296c3e5e9e", + txid: '15f6a584080b04911121fbaca7bfcf3dd64ef2bfa5a01daf31e05a296c3e5e9e', vout: 287, amount: 0.00001, satoshis: 1000, @@ -43,7 +43,7 @@ const mockUtxoDetails = [ confirmations: 3490 }, { - txid: "15f6a584080b04911121fbaca7bfcf3dd64ef2bfa5a01daf31e05a296c3e5e9e", + txid: '15f6a584080b04911121fbaca7bfcf3dd64ef2bfa5a01daf31e05a296c3e5e9e', vout: 288, amount: 0.00001, satoshis: 1000, @@ -54,10 +54,10 @@ const mockUtxoDetails = [ const mockUnconfirmed = [ { - address: "1EzdL6TBbkNhnB2fYiBaKmcs5fxaoqwdAp", - txid: "000c00a90fb5031da6e02f7625df2f8b35a4c16e6feb9fc72293e67e5ff75786", + address: '1EzdL6TBbkNhnB2fYiBaKmcs5fxaoqwdAp', + txid: '000c00a90fb5031da6e02f7625df2f8b35a4c16e6feb9fc72293e67e5ff75786', vout: 0, - scriptPubKey: "76a914997fabcd94a1e2aaa13a7664362e5e7b96c169a988ac", + scriptPubKey: '76a914997fabcd94a1e2aaa13a7664362e5e7b96c169a988ac', amount: 0.00999626, satoshis: 999626, confirmations: 0, @@ -69,40 +69,40 @@ const mockTransactions = { pagesTotal: 1, txs: [ { - txid: "000c00a90fb5031da6e02f7625df2f8b35a4c16e6feb9fc72293e67e5ff75786", + txid: '000c00a90fb5031da6e02f7625df2f8b35a4c16e6feb9fc72293e67e5ff75786', version: 2, locktime: 549565, vin: [ { txid: - "45c891c6d44619fc85716ba1b593aa83ebc1e500fe611b1ab98531ea203a0f21", + '45c891c6d44619fc85716ba1b593aa83ebc1e500fe611b1ab98531ea203a0f21', vout: 209, sequence: 4294967294, n: 0, scriptSig: { hex: - "47304402205b136f348bedae61a87c0500979d47ab02c76f0e4aba866b94c4931fccb5d7dc0220757a141660475b0cd4cb8b1f54b1ace95105f5bea775e817b115fb589fe4477541210246daec651c506f353daa7468714399c773df42ac4d663022d0e446a3331ac64a", + '47304402205b136f348bedae61a87c0500979d47ab02c76f0e4aba866b94c4931fccb5d7dc0220757a141660475b0cd4cb8b1f54b1ace95105f5bea775e817b115fb589fe4477541210246daec651c506f353daa7468714399c773df42ac4d663022d0e446a3331ac64a', asm: - "304402205b136f348bedae61a87c0500979d47ab02c76f0e4aba866b94c4931fccb5d7dc0220757a141660475b0cd4cb8b1f54b1ace95105f5bea775e817b115fb589fe44775[ALL|FORKID] 0246daec651c506f353daa7468714399c773df42ac4d663022d0e446a3331ac64a" + '304402205b136f348bedae61a87c0500979d47ab02c76f0e4aba866b94c4931fccb5d7dc0220757a141660475b0cd4cb8b1f54b1ace95105f5bea775e817b115fb589fe44775[ALL|FORKID] 0246daec651c506f353daa7468714399c773df42ac4d663022d0e446a3331ac64a' }, - addr: "14TdovsQUL69xL5g3zSzhLpmDb93d9rU9m", + addr: '14TdovsQUL69xL5g3zSzhLpmDb93d9rU9m', valueSat: 1979534, value: 0.01979534, doubleSpentTxID: null }, { txid: - "6e5fa79547112a912adf6082c975dc80e282045193512ea369adb6bac7420674", + '6e5fa79547112a912adf6082c975dc80e282045193512ea369adb6bac7420674', vout: 147, sequence: 4294967294, n: 1, scriptSig: { hex: - "473044022056674ac83a37d54ffec2c6d33cfc2ae2256f821b8bd818e1b6783356b49f3d28022046d3dd147c8fc51f2da5d16996a3cea1d7314e327aa1ae1017418737ed20136a4121038f23af565f68d8455e07e5c33c5cfc5114de2f478f035db23eb02f8ff5fe7f6e", + '473044022056674ac83a37d54ffec2c6d33cfc2ae2256f821b8bd818e1b6783356b49f3d28022046d3dd147c8fc51f2da5d16996a3cea1d7314e327aa1ae1017418737ed20136a4121038f23af565f68d8455e07e5c33c5cfc5114de2f478f035db23eb02f8ff5fe7f6e', asm: - "3044022056674ac83a37d54ffec2c6d33cfc2ae2256f821b8bd818e1b6783356b49f3d28022046d3dd147c8fc51f2da5d16996a3cea1d7314e327aa1ae1017418737ed20136a[ALL|FORKID] 038f23af565f68d8455e07e5c33c5cfc5114de2f478f035db23eb02f8ff5fe7f6e" + '3044022056674ac83a37d54ffec2c6d33cfc2ae2256f821b8bd818e1b6783356b49f3d28022046d3dd147c8fc51f2da5d16996a3cea1d7314e327aa1ae1017418737ed20136a[ALL|FORKID] 038f23af565f68d8455e07e5c33c5cfc5114de2f478f035db23eb02f8ff5fe7f6e' }, - addr: "1CEtC2fjELvmAzTd6MWuHb1gvuSq8x3Xpb", + addr: '1CEtC2fjELvmAzTd6MWuHb1gvuSq8x3Xpb', valueSat: 10466, value: 0.00010466, doubleSpentTxID: null @@ -110,28 +110,28 @@ const mockTransactions = { ], vout: [ { - value: "0.00999626", + value: '0.00999626', n: 0, scriptPubKey: { - hex: "76a914997fabcd94a1e2aaa13a7664362e5e7b96c169a988ac", + hex: '76a914997fabcd94a1e2aaa13a7664362e5e7b96c169a988ac', asm: - "OP_DUP OP_HASH160 997fabcd94a1e2aaa13a7664362e5e7b96c169a9 OP_EQUALVERIFY OP_CHECKSIG", - addresses: ["1EzdL6TBbkNhnB2fYiBaKmcs5fxaoqwdAp"], - type: "pubkeyhash" + 'OP_DUP OP_HASH160 997fabcd94a1e2aaa13a7664362e5e7b96c169a9 OP_EQUALVERIFY OP_CHECKSIG', + addresses: ['1EzdL6TBbkNhnB2fYiBaKmcs5fxaoqwdAp'], + type: 'pubkeyhash' }, spentTxId: null, spentIndex: null, spentHeight: null }, { - value: "0.00990000", + value: '0.00990000', n: 1, scriptPubKey: { - hex: "76a914e3335e4d6babe61ea58311293c1c6bfe802801cb88ac", + hex: '76a914e3335e4d6babe61ea58311293c1c6bfe802801cb88ac', asm: - "OP_DUP OP_HASH160 e3335e4d6babe61ea58311293c1c6bfe802801cb OP_EQUALVERIFY OP_CHECKSIG", - addresses: ["1MiKvgaQTFCTEZbSDMZgw9ahaB52Cr4ofb"], - type: "pubkeyhash" + 'OP_DUP OP_HASH160 e3335e4d6babe61ea58311293c1c6bfe802801cb OP_EQUALVERIFY OP_CHECKSIG', + addresses: ['1MiKvgaQTFCTEZbSDMZgw9ahaB52Cr4ofb'], + type: 'pubkeyhash' }, spentTxId: null, spentIndex: null, @@ -139,7 +139,7 @@ const mockTransactions = { } ], blockhash: - "00000000000000000158b1a2883688873ec5ea076e3b0f576bcdfe1fd277880f", + '00000000000000000158b1a2883688873ec5ea076e3b0f576bcdfe1fd277880f', blockheight: 549601, confirmations: 5, time: 1537990026, diff --git a/test/v3/mocks/bitcore-mock.js b/test/v3/mocks/bitcore-mock.js index e545917..8a0e32a 100644 --- a/test/v3/mocks/bitcore-mock.js +++ b/test/v3/mocks/bitcore-mock.js @@ -2,7 +2,7 @@ This library contains mocking data for running unit tests on the bitcore route. */ -"use strict" +'use strict' const mockBalance = { confirmed: 10000000, @@ -12,18 +12,18 @@ const mockBalance = { const mockUtxos = [ { - _id: "5cf2c31a33bd46a95ec7e730", - chain: "BCH", - network: "testnet", + _id: '5cf2c31a33bd46a95ec7e730', + chain: 'BCH', + network: 'testnet', coinbase: false, mintIndex: 1, - spentTxid: "", + spentTxid: '', mintTxid: - "5fe9b74056319a8c87f45cc745030715a6180758b94938dbf90d639d55652392", + '5fe9b74056319a8c87f45cc745030715a6180758b94938dbf90d639d55652392', mintHeight: 1265275, spentHeight: -2, - address: "qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4", - script: "76a9140e5b4ad9008bb9a027b7e2d0ef958914e12db20788ac", + address: 'qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4', + script: '76a9140e5b4ad9008bb9a027b7e2d0ef958914e12db20788ac', value: 10000000, confirmations: -1 } diff --git a/test/v3/mocks/block-mock.js b/test/v3/mocks/block-mock.js index 069b90d..616ad41 100644 --- a/test/v3/mocks/block-mock.js +++ b/test/v3/mocks/block-mock.js @@ -2,39 +2,39 @@ This library contains mocking data for running unit tests on the address route. */ -"use strict" +'use strict' const mockBlockDetails = { - hash: "00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79", + hash: '00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79', size: 1319, height: 1267544, version: 536870912, merkleroot: - "c2cd01ec2cf149acc7631385f89ae103d1a2ad212ab810c862d9680a811618ce", + 'c2cd01ec2cf149acc7631385f89ae103d1a2ad212ab810c862d9680a811618ce', tx: [ - "52bfa89d449fef8070ec33e7a61f5ec8b5417ff62b050cd6a144ebce9557e0fa", - "8988e8742d2523f667c2d1374861919e3a82903e059fec75c10795da2303b93b", - "41def004f22b196d675566a6983ecf97611e72c48375b8ba779983d5ccd369d7", - "8ca8efb06abb94395f8331f87e101504dcf66aee828f2111922f056971fa7502", - "9ab409cbb203be7cf22bd6598d787fcdd5b417d885b72207ecc7253470770649" + '52bfa89d449fef8070ec33e7a61f5ec8b5417ff62b050cd6a144ebce9557e0fa', + '8988e8742d2523f667c2d1374861919e3a82903e059fec75c10795da2303b93b', + '41def004f22b196d675566a6983ecf97611e72c48375b8ba779983d5ccd369d7', + '8ca8efb06abb94395f8331f87e101504dcf66aee828f2111922f056971fa7502', + '9ab409cbb203be7cf22bd6598d787fcdd5b417d885b72207ecc7253470770649' ], time: 1542048973, nonce: 3936284753, - bits: "1a03c148", + bits: '1a03c148', difficulty: 4467892.99177529, - chainwork: "00000000000000000000000000000000000000000000003ee27b503a064045bd", + chainwork: '00000000000000000000000000000000000000000000003ee27b503a064045bd', confirmations: 3, previousblockhash: - "00000000000001891202cbe18729a02a8763cf04da0ca7aded6e6c7d9b500785", + '00000000000001891202cbe18729a02a8763cf04da0ca7aded6e6c7d9b500785', nextblockhash: - "000000000000039b93b3f3403a0eb21150904b15229d998cf3788fd8bf192cc2", + '000000000000039b93b3f3403a0eb21150904b15229d998cf3788fd8bf192cc2', reward: 0.78125, isMainChain: true, poolInfo: {} } const mockBlockHash = - "00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79" + '00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79' module.exports = { mockBlockDetails, diff --git a/test/v3/mocks/blockbook-mock.js b/test/v3/mocks/blockbook-mock.js index d8a87db..05edf53 100644 --- a/test/v3/mocks/blockbook-mock.js +++ b/test/v3/mocks/blockbook-mock.js @@ -2,70 +2,70 @@ This library contains mocking data for running unit tests on the blockbook route. */ -"use strict" +'use strict' const mockBalance = { page: 1, totalPages: 1, itemsOnPage: 1000, - address: "bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf", - balance: "10000000", - totalReceived: "10000000", - totalSent: "0", - unconfirmedBalance: "0", + address: 'bitcoincash:qrdka2205f4hyukutc2g0s6lykperc8nsu5u2ddpqf', + balance: '10000000', + totalReceived: '10000000', + totalSent: '0', + unconfirmedBalance: '0', unconfirmedTxs: 0, txs: 1, - txids: ["5fe9b74056319a8c87f45cc745030715a6180758b94938dbf90d639d55652392"] + txids: ['5fe9b74056319a8c87f45cc745030715a6180758b94938dbf90d639d55652392'] } const mockUtxos = [ { - txid: "5fe9b74056319a8c87f45cc745030715a6180758b94938dbf90d639d55652392", + txid: '5fe9b74056319a8c87f45cc745030715a6180758b94938dbf90d639d55652392', vout: 1, - value: "10000000", + value: '10000000', height: 1265275, confirmations: 42704 } ] const mockTx = { - txid: "5fe9b74056319a8c87f45cc745030715a6180758b94938dbf90d639d55652392", + txid: '5fe9b74056319a8c87f45cc745030715a6180758b94938dbf90d639d55652392', version: 2, vin: [ { - txid: "85ddb8215fc3701a493cf1c450644c5ef32c55aaa2f48ae2d008944394f3e4d3", + txid: '85ddb8215fc3701a493cf1c450644c5ef32c55aaa2f48ae2d008944394f3e4d3', sequence: 4294967295, n: 0, - addresses: ["bchtest:qqmd9unmhkpx4pkmr6fkrr8rm6y77vckjvqe8aey35"], - value: "16983000648", + addresses: ['bchtest:qqmd9unmhkpx4pkmr6fkrr8rm6y77vckjvqe8aey35'], + value: '16983000648', hex: - "47304402202378e55f4d02bb932498deef22dfc1f7a4984858c3b55017e225dd567172252e0220373d27710b5d42a72ac9725959f1605a912fee0ae86a7ad36e7d6d796f14ca29412103c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792" + '47304402202378e55f4d02bb932498deef22dfc1f7a4984858c3b55017e225dd567172252e0220373d27710b5d42a72ac9725959f1605a912fee0ae86a7ad36e7d6d796f14ca29412103c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792' } ], vout: [ { - value: "16973000422", + value: '16973000422', n: 0, spent: true, - hex: "76a91436d2f27bbd826a86db1e93618ce3de89ef33169388ac", - addresses: ["bchtest:qqmd9unmhkpx4pkmr6fkrr8rm6y77vckjvqe8aey35"] + hex: '76a91436d2f27bbd826a86db1e93618ce3de89ef33169388ac', + addresses: ['bchtest:qqmd9unmhkpx4pkmr6fkrr8rm6y77vckjvqe8aey35'] }, { - value: "10000000", + value: '10000000', n: 1, - hex: "76a9140e5b4ad9008bb9a027b7e2d0ef958914e12db20788ac", - addresses: ["bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4"] + hex: '76a9140e5b4ad9008bb9a027b7e2d0ef958914e12db20788ac', + addresses: ['bchtest:qq89kjkeqz9mngp8kl3dpmu43y2wztdjqu500gn4c4'] } ], - blockHash: "00000000005242edac4635ac2375a454e801cc1be8b131b622328089731e5e30", + blockHash: '00000000005242edac4635ac2375a454e801cc1be8b131b622328089731e5e30', blockHeight: 1265275, confirmations: 65402, blockTime: 1540912733, - value: "16983000422", - valueIn: "16983000648", - fees: "226", + value: '16983000422', + valueIn: '16983000648', + fees: '226', hex: - "0200000001d3e4f394439408d0e28af4a2aa552cf35e4c6450c4f13c491a70c35f21b8dd85000000006a47304402202378e55f4d02bb932498deef22dfc1f7a4984858c3b55017e225dd567172252e0220373d27710b5d42a72ac9725959f1605a912fee0ae86a7ad36e7d6d796f14ca29412103c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792ffffffff02e66eabf3030000001976a91436d2f27bbd826a86db1e93618ce3de89ef33169388ac80969800000000001976a9140e5b4ad9008bb9a027b7e2d0ef958914e12db20788ac00000000" + '0200000001d3e4f394439408d0e28af4a2aa552cf35e4c6450c4f13c491a70c35f21b8dd85000000006a47304402202378e55f4d02bb932498deef22dfc1f7a4984858c3b55017e225dd567172252e0220373d27710b5d42a72ac9725959f1605a912fee0ae86a7ad36e7d6d796f14ca29412103c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792ffffffff02e66eabf3030000001976a91436d2f27bbd826a86db1e93618ce3de89ef33169388ac80969800000000001976a9140e5b4ad9008bb9a027b7e2d0ef958914e12db20788ac00000000' } module.exports = { diff --git a/test/v3/mocks/blockchain-mock.js b/test/v3/mocks/blockchain-mock.js index 8971637..1030033 100644 --- a/test/v3/mocks/blockchain-mock.js +++ b/test/v3/mocks/blockchain-mock.js @@ -2,30 +2,30 @@ This library contains mocking data for running unit tests on the address route. */ -"use strict" +'use strict' const mockBlockHash = - "00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79" + '00000000000000645dec6503d3f5eafb0d2537a7a28f181d721dec7c44154c79' const mockBlockchainInfo = { - chain: "test", + chain: 'test', blocks: 1267694, headers: 1267694, bestblockhash: - "000000000000013eaf80d1e157e32804c36a58ad0bb26ca59833880c80298780", + '000000000000013eaf80d1e157e32804c36a58ad0bb26ca59833880c80298780', difficulty: 4105763.969035785, mediantime: 1542131305, verificationprogress: 0.9999968911571566, - chainwork: "00000000000000000000000000000000000000000000003f0443b0b5f02ce255", + chainwork: '00000000000000000000000000000000000000000000003f0443b0b5f02ce255', pruned: false, softforks: [ - { id: "bip34", version: 2, reject: { status: true } }, - { id: "bip66", version: 3, reject: { status: true } }, - { id: "bip65", version: 4, reject: { status: true } } + { id: 'bip34', version: 2, reject: { status: true } }, + { id: 'bip66', version: 3, reject: { status: true } }, + { id: 'bip65', version: 4, reject: { status: true } } ], bip9_softforks: { csv: { - status: "active", + status: 'active', startTime: 1456790400, timeout: 1493596800, since: 770112 @@ -36,171 +36,171 @@ const mockBlockchainInfo = { const mockChainTips = [ { height: 1267696, - hash: "000000000000035bfc43a642ebbff8cfc1e88b1d564de8b0a6c7e2797eeafb21", + hash: '000000000000035bfc43a642ebbff8cfc1e88b1d564de8b0a6c7e2797eeafb21', branchlen: 0, - status: "active" + status: 'active' }, { height: 1267581, - hash: "000000000001bd12e4124207682563135b21353ca3087bc6b0c409f7f9e1da91", + hash: '000000000001bd12e4124207682563135b21353ca3087bc6b0c409f7f9e1da91', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1267375, - hash: "00000000702036979df70236bcc45dfc72d43d5d0e6834007afa1fa627e49587", + hash: '00000000702036979df70236bcc45dfc72d43d5d0e6834007afa1fa627e49587', branchlen: 1036, - status: "headers-only" + status: 'headers-only' }, { height: 1266979, - hash: "00000000e851abbde2174ccdc5c2508b909f81f23c4b7abeac864eee1a4891c7", + hash: '00000000e851abbde2174ccdc5c2508b909f81f23c4b7abeac864eee1a4891c7', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1266973, - hash: "000000007e1324d2900ed70947f89ab8fd4a267e87c9244c333215659a7370d5", + hash: '000000007e1324d2900ed70947f89ab8fd4a267e87c9244c333215659a7370d5', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1266967, - hash: "000000000f37f12843d4800f50ec4de44dce0432e4d448242d43ff04a7a2948d", + hash: '000000000f37f12843d4800f50ec4de44dce0432e4d448242d43ff04a7a2948d', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1266963, - hash: "00000000ae11ec99e88898cbd72567cb4cb79e7fc13243357bef79632769deb4", + hash: '00000000ae11ec99e88898cbd72567cb4cb79e7fc13243357bef79632769deb4', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1266962, - hash: "000000004f97851259b4460a049e44fa5bd4beadee04a85bf81bd2e90c4f24f9", + hash: '000000004f97851259b4460a049e44fa5bd4beadee04a85bf81bd2e90c4f24f9', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1266950, - hash: "00000000d12a0e4a827f73ecaadb563df7e99817294939f2be8e943079dc60b2", + hash: '00000000d12a0e4a827f73ecaadb563df7e99817294939f2be8e943079dc60b2', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1266944, - hash: "00000000612d16af273217818e8e7ac5014a19f68ed04e1bc897b1be0a9c744f", + hash: '00000000612d16af273217818e8e7ac5014a19f68ed04e1bc897b1be0a9c744f', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1266941, - hash: "0000000000002b91cdb15cacf3368da2c9ffce511d64092193b507dad75f4a27", + hash: '0000000000002b91cdb15cacf3368da2c9ffce511d64092193b507dad75f4a27', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1266896, - hash: "000000000002745f67a66617b1f9f65c2dfb4c4b8a9ed9b1320b98d3ca46cbe5", + hash: '000000000002745f67a66617b1f9f65c2dfb4c4b8a9ed9b1320b98d3ca46cbe5', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1266481, - hash: "0000000000036babee3ba7654cddb29a9fe5e85c9fbeb44bb53d5ffb694b9670", + hash: '0000000000036babee3ba7654cddb29a9fe5e85c9fbeb44bb53d5ffb694b9670', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1266452, - hash: "00000000502c3ab1490e0839780a4b441bbe21507c454545941e6adcde73c2ff", + hash: '00000000502c3ab1490e0839780a4b441bbe21507c454545941e6adcde73c2ff', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1266336, - hash: "000000001c9a0b7cd9eb2210f69d5a9a3f4546ba3707deb40993d729190582d7", + hash: '000000001c9a0b7cd9eb2210f69d5a9a3f4546ba3707deb40993d729190582d7', branchlen: 10, - status: "headers-only" + status: 'headers-only' }, { height: 1266097, - hash: "000000000028ac0fbd18afe6f001f70cb7549bd2b3082d754dde88ee236368a2", + hash: '000000000028ac0fbd18afe6f001f70cb7549bd2b3082d754dde88ee236368a2', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1265522, - hash: "00000000000000c6df7a2063030e6ce51399e470cc46e4bf6d67aa3f0feca98d", + hash: '00000000000000c6df7a2063030e6ce51399e470cc46e4bf6d67aa3f0feca98d', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1265470, - hash: "0000000000168e6442a595a02340fccf8dc2b0e8912c632d39e1f870685f6d7c", + hash: '0000000000168e6442a595a02340fccf8dc2b0e8912c632d39e1f870685f6d7c', branchlen: 2, - status: "valid-fork" + status: 'valid-fork' }, { height: 1265275, - hash: "000000008bc2b37ae6af1b886b52e7e1c1122c12badc4ae6c13df64f789267cf", + hash: '000000008bc2b37ae6af1b886b52e7e1c1122c12badc4ae6c13df64f789267cf', branchlen: 11027, - status: "headers-only" + status: 'headers-only' }, { height: 1265257, - hash: "00000000005bc3e9973d7273211eab02ae02549c7ebae48764c0bd648d4d7bbe", + hash: '00000000005bc3e9973d7273211eab02ae02549c7ebae48764c0bd648d4d7bbe', branchlen: 114, - status: "valid-fork" + status: 'valid-fork' }, { height: 1265254, - hash: "0000000000e5b909d3541857315e9ee103b042d9ba661f25cc3e8fb25a96c8ce", + hash: '0000000000e5b909d3541857315e9ee103b042d9ba661f25cc3e8fb25a96c8ce', branchlen: 111, - status: "valid-fork" + status: 'valid-fork' }, { height: 1265245, - hash: "000000000066eb8832f6f990baceb379536f437216e22475a6c1b9133d250cb8", + hash: '000000000066eb8832f6f990baceb379536f437216e22475a6c1b9133d250cb8', branchlen: 102, - status: "valid-fork" + status: 'valid-fork' }, { height: 1264455, - hash: "00000000000001befc1bb17a23208d0b77b2449e37093ce8fbb5e346b19cafcc", + hash: '00000000000001befc1bb17a23208d0b77b2449e37093ce8fbb5e346b19cafcc', branchlen: 1, - status: "valid-headers" + status: 'valid-headers' }, { height: 1264373, - hash: "00000000000001ed3747e04fb95054cac0358fb4d8009d1999fc3ea34413e84a", + hash: '00000000000001ed3747e04fb95054cac0358fb4d8009d1999fc3ea34413e84a', branchlen: 175, - status: "valid-fork" + status: 'valid-fork' }, { height: 1263912, - hash: "00000000000004635aecbcb97edcd6f5396483338838cb40da804eb354c68bde", + hash: '00000000000004635aecbcb97edcd6f5396483338838cb40da804eb354c68bde', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1262906, - hash: "00000000b31643d92a3e7c38e9755844fc8607e3f1055580a8ff28854e8a8ece", + hash: '00000000b31643d92a3e7c38e9755844fc8607e3f1055580a8ff28854e8a8ece', branchlen: 1, - status: "valid-fork" + status: 'valid-fork' }, { height: 1255749, - hash: "000000001dde5b015a99137f4cba87871370f4b6fcfbcc8b126547e6c33177da", + hash: '000000001dde5b015a99137f4cba87871370f4b6fcfbcc8b126547e6c33177da', branchlen: 129, - status: "headers-only" + status: 'headers-only' }, { height: 1188789, - hash: "00000000af942ce4eb60b3213cbcb7c98a7330f1f8f1adb4b6376f5e822e15b2", + hash: '00000000af942ce4eb60b3213cbcb7c98a7330f1f8f1adb4b6376f5e822e15b2', branchlen: 92, - status: "headers-only" + status: 'headers-only' } ] @@ -213,76 +213,76 @@ const mockMempoolInfo = { } const mockRawMempool = [ - "db045bc3bd1088fa91f5ebb05c35cb9e2a91a22377f79b465cc6920b9893123c", - "6b3df7febf2b9834f1409155f88b866dd516b36376eae00e2b455df82e290405" + 'db045bc3bd1088fa91f5ebb05c35cb9e2a91a22377f79b465cc6920b9893123c', + '6b3df7febf2b9834f1409155f88b866dd516b36376eae00e2b455df82e290405' ] const mockBlockHeaderConcise = - "000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c" + '000000202ed2723e7590e2b937f6821a99d6764cb8799bf30f8e300000000000000000001d311c02df9a1e3f57b8dbdcf97ec8dbc3109a26779724c63e560b29ad9ea501e2af955d286403183049e39c' const mockBlockHeader = { - hash: "00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900", + hash: '00000000000008c3679777df34f1a09565f98b2400a05b7c8da72525fdca3900', confirmations: 7, height: 1272859, version: 2147418112, - versionHex: "7fff0000", + versionHex: '7fff0000', merkleroot: - "846f45604ec6cde2528933305dba80971e9ff0874f74d2811c7c690b2c32706d", + '846f45604ec6cde2528933305dba80971e9ff0874f74d2811c7c690b2c32706d', time: 1544207139, mediantime: 1544202884, nonce: 641041470, - bits: "1a09faea", + bits: '1a09faea', difficulty: 1681035.704111868, - chainwork: "00000000000000000000000000000000000000000000003fc4752e608403be04", + chainwork: '00000000000000000000000000000000000000000000003fc4752e608403be04', previousblockhash: - "0000000000003e467ebcb7e906645676c2f71b9ac520d6508bea45789b7c217d", + '0000000000003e467ebcb7e906645676c2f71b9ac520d6508bea45789b7c217d', nextblockhash: - "00000000000006899041cdfd6c0b73a97730c362346dde479b77414ad7f25ace" + '00000000000006899041cdfd6c0b73a97730c362346dde479b77414ad7f25ace' } const mockTxOut = { - bestblock: "00000000003a7f19730dd9f172d7466658a5c8833dd03ed8f4ba36e3d857b5e7", + bestblock: '00000000003a7f19730dd9f172d7466658a5c8833dd03ed8f4ba36e3d857b5e7', confirmations: 10, value: 0.0001, scriptPubKey: { asm: - "OP_DUP OP_HASH160 0ee020c07f39526ac5505c54fa1ab98490979b83 OP_EQUALVERIFY OP_CHECKSIG", - hex: "76a9140ee020c07f39526ac5505c54fa1ab98490979b8388ac", + 'OP_DUP OP_HASH160 0ee020c07f39526ac5505c54fa1ab98490979b83 OP_EQUALVERIFY OP_CHECKSIG', + hex: '76a9140ee020c07f39526ac5505c54fa1ab98490979b8388ac', reqSigs: 1, - type: "pubkeyhash", - addresses: ["bchtest:qq8wqgxq0uu4y6k92pw9f7s6hxzfp9umsvtg39pzqf"] + type: 'pubkeyhash', + addresses: ['bchtest:qq8wqgxq0uu4y6k92pw9f7s6hxzfp9umsvtg39pzqf'] }, coinbase: false } const mockTxOutProof = - "000000200798039affceb7a381e15dc62443c286efe7cae852393b656807000000000000cf9a7d6c654fd1c4558229a619a550ff749b373fa0f0027eed68b1abf6175d5c07c50f5cffff001d0452403b34000000070d0765da76980d542b5670d27ccda9e717073270f8921ad017deb7ee83fe6c4c22830a48cc8392197f1742a3d81805bd2aa4eb7469f38c74f674429d682cb87efcff1713fd0c388a50f0d11adf05363397ef79d16cdb786d47c941c2cb89f2588f42aced9c05f4203b4440616a9e4266ec47909b9580a643f402b5d4e82cc3cddd73df05a33abf6af3975d973d3033d10c4168a73d58d01f685a96d5a2519cd0de9c77faf3f8725ddf155cbdc8ab8102f173e2d0a0d74767f3bff22f588158d6d5bc71c079c7659cc864819c43877635007650502eb4060fcc9feec3280a41d602ad0a" + '000000200798039affceb7a381e15dc62443c286efe7cae852393b656807000000000000cf9a7d6c654fd1c4558229a619a550ff749b373fa0f0027eed68b1abf6175d5c07c50f5cffff001d0452403b34000000070d0765da76980d542b5670d27ccda9e717073270f8921ad017deb7ee83fe6c4c22830a48cc8392197f1742a3d81805bd2aa4eb7469f38c74f674429d682cb87efcff1713fd0c388a50f0d11adf05363397ef79d16cdb786d47c941c2cb89f2588f42aced9c05f4203b4440616a9e4266ec47909b9580a643f402b5d4e82cc3cddd73df05a33abf6af3975d973d3033d10c4168a73d58d01f685a96d5a2519cd0de9c77faf3f8725ddf155cbdc8ab8102f173e2d0a0d74767f3bff22f588158d6d5bc71c079c7659cc864819c43877635007650502eb4060fcc9feec3280a41d602ad0a' const mockAncestors = [ - "070504de968fba8a23a1362fd7fc0546a420663f2bcc18099d894a41ecf9cce5", - "20af6b7fcd21a3f38bb65d32fe2d66fb1ae554ed9c00eaf1b17d7e81362381a9", - "227e08663a812cf44d91106b09fc8493fe1a2b7c146f30ca09ebd86c9b84b2a5", - "228833be79d4a833165ea199be160efcaeb9325e71e9455f424b27abc9688ba8", - "2de27df02001e7243435cef6d41ea2312b94a5964912eb21466b936852c0b822", - "2ef76ae690d6f6c9559e20358a75a0ce02250b9b8e80e0aa6f782576239f292a", - "3e314678f52d52694726e6da88b94c9f0ea086d2f9af297b01d014b62247839f", - "4773f840d5255f16c0e5effce48316d8b8824a1d3ddd5da275c5fd99e7b3ee42", - "4804b97112da07e2c187516a915dd4cbd4a3814f3c900b8d08eb1d508ab0ac47", - "4ca69f31081a256cb4711315336fe4358d8f04b67792ca5ee17b5f4089a2446a", - "6ac17dce10ae3a3d1d8e6f42546ad9a4bb981e62cba8d48bab03e01b9ea38ae3", - "6ce71182ef341c481a90d8b081a99d9788bdd91a917f9a6594fdfad2c2024a14", - "8413343ac973fb0968ae1809faa8f0ddf18252975481daa683e88b04afa66ccd", - "9430300f3d7ecdabe39671b6fd0e9c36f763f01a202e619c070554ddc5e8713e", - "94f82b5a2cd1647d8168807ccfdebe41931ea1ab789a050d615f08000a63b624", - "9848db6a7d2835002ca7e1097a685d75eb629f44df94007674635b45d0e97199", - "98d809993353df6c4d55fda5e7b0ed2e383601cef1180a9aa9c87e67e8f4dd94", - "9f5513a35ae8fad3dd061865a97d8127c914e3464527641c089993c06d092535", - "a7201ac90abd2aa42112faa809181c45047b6988a2f649a70a1d5bfb95f46884", - "a9f1284710c655357412a062b01efaeb174820613784ccbfe44b33b86a8bdbc4", - "b814f44c9c8ee24a218b9f295a8c1831106b70c15ffe8aeb7534e10d99935fd0", - "e130ccdcc94dc5eaa4ae37fa50e3ee96283b0e157616bc6e28454b64bae34f48", - "e68dad4a7292105cfa84fcaef7f99e5d4f2ece9613ca625d4d2ebf61efa84118", - "fe94caf5da672be3772d2304a6272eb8bc3d3f5cb4a886f39b7981e1485cf74b" + '070504de968fba8a23a1362fd7fc0546a420663f2bcc18099d894a41ecf9cce5', + '20af6b7fcd21a3f38bb65d32fe2d66fb1ae554ed9c00eaf1b17d7e81362381a9', + '227e08663a812cf44d91106b09fc8493fe1a2b7c146f30ca09ebd86c9b84b2a5', + '228833be79d4a833165ea199be160efcaeb9325e71e9455f424b27abc9688ba8', + '2de27df02001e7243435cef6d41ea2312b94a5964912eb21466b936852c0b822', + '2ef76ae690d6f6c9559e20358a75a0ce02250b9b8e80e0aa6f782576239f292a', + '3e314678f52d52694726e6da88b94c9f0ea086d2f9af297b01d014b62247839f', + '4773f840d5255f16c0e5effce48316d8b8824a1d3ddd5da275c5fd99e7b3ee42', + '4804b97112da07e2c187516a915dd4cbd4a3814f3c900b8d08eb1d508ab0ac47', + '4ca69f31081a256cb4711315336fe4358d8f04b67792ca5ee17b5f4089a2446a', + '6ac17dce10ae3a3d1d8e6f42546ad9a4bb981e62cba8d48bab03e01b9ea38ae3', + '6ce71182ef341c481a90d8b081a99d9788bdd91a917f9a6594fdfad2c2024a14', + '8413343ac973fb0968ae1809faa8f0ddf18252975481daa683e88b04afa66ccd', + '9430300f3d7ecdabe39671b6fd0e9c36f763f01a202e619c070554ddc5e8713e', + '94f82b5a2cd1647d8168807ccfdebe41931ea1ab789a050d615f08000a63b624', + '9848db6a7d2835002ca7e1097a685d75eb629f44df94007674635b45d0e97199', + '98d809993353df6c4d55fda5e7b0ed2e383601cef1180a9aa9c87e67e8f4dd94', + '9f5513a35ae8fad3dd061865a97d8127c914e3464527641c089993c06d092535', + 'a7201ac90abd2aa42112faa809181c45047b6988a2f649a70a1d5bfb95f46884', + 'a9f1284710c655357412a062b01efaeb174820613784ccbfe44b33b86a8bdbc4', + 'b814f44c9c8ee24a218b9f295a8c1831106b70c15ffe8aeb7534e10d99935fd0', + 'e130ccdcc94dc5eaa4ae37fa50e3ee96283b0e157616bc6e28454b64bae34f48', + 'e68dad4a7292105cfa84fcaef7f99e5d4f2ece9613ca625d4d2ebf61efa84118', + 'fe94caf5da672be3772d2304a6272eb8bc3d3f5cb4a886f39b7981e1485cf74b' ] module.exports = { diff --git a/test/v3/mocks/control-mock.js b/test/v3/mocks/control-mock.js index c0dbb5b..7e44cf0 100644 --- a/test/v3/mocks/control-mock.js +++ b/test/v3/mocks/control-mock.js @@ -2,7 +2,7 @@ This library contains mocking data for running unit tests on the address route. */ -"use strict" +'use strict' const mockGetInfo = { version: 170200, @@ -12,21 +12,21 @@ const mockGetInfo = { blocks: 1266726, timeoffset: 0, connections: 8, - proxy: "", + proxy: '', difficulty: 1, testnet: true, keypoololdest: 1536331195, keypoolsize: 2000, paytxfee: 0, relayfee: 0.00001, - errors: "Warning: unknown new rules activated (versionbit 28)" + errors: 'Warning: unknown new rules activated (versionbit 28)' } const mockGetNetworkInfo = { version: 190700, - subversion: "/Bitcoin ABC:0.19.7(EB32.0)/", + subversion: '/Bitcoin ABC:0.19.7(EB32.0)/', protocolversion: 70015, - localservices: "0000000000000425", + localservices: '0000000000000425', localrelay: true, timeoffset: 0, networkactive: true, diff --git a/test/v3/mocks/express-mocks.js b/test/v3/mocks/express-mocks.js index f9202e6..d4753e7 100644 --- a/test/v3/mocks/express-mocks.js +++ b/test/v3/mocks/express-mocks.js @@ -2,27 +2,27 @@ Contains mocks of Express req and res objects. */ -"use strict" +'use strict' -const sinon = require("sinon") +const sinon = require('sinon') // Inspect JS Objects. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { showHidden: true, colors: true } // mock for res.send() -function fakeSend(arg) { - //console.log(`res.send: ${util.inspect(arg)}`); +function fakeSend (arg) { + // console.log(`res.send: ${util.inspect(arg)}`); mockRes.output = arg return arg } // mock for res.json() -function fakeJson(arg) { - //console.log(`res.json: ${util.inspect(arg)}`); +function fakeJson (arg) { + // console.log(`res.json: ${util.inspect(arg)}`); mockRes.output = arg return arg } @@ -55,7 +55,6 @@ const mockRes = { cookie: sinon.stub().returns({}), download: sinon.stub().returns({}), end: sinon.stub().returns({}), - format: {}, get: sinon.stub().returns({}), headersSent: sinon.stub().returns({}), json: sinon.stub().callsFake(fakeJson), diff --git a/test/v3/mocks/mining-mocks.js b/test/v3/mocks/mining-mocks.js index a9ae07f..f1ddca7 100644 --- a/test/v3/mocks/mining-mocks.js +++ b/test/v3/mocks/mining-mocks.js @@ -2,7 +2,7 @@ This library contains mocking data for running unit tests on the address route. */ -"use strict" +'use strict' const mockMiningInfo = { blocks: 1270185, @@ -14,7 +14,7 @@ const mockMiningInfo = { "Warning: Unknown block versions being mined! It's possible unknown rules are in effect", networkhashps: 517410290.9365583, pooledtx: 5, - chain: "test" + chain: 'test' } module.exports = { diff --git a/test/v3/mocks/raw-transactions-mocks.js b/test/v3/mocks/raw-transactions-mocks.js index 08620a3..1649d52 100644 --- a/test/v3/mocks/raw-transactions-mocks.js +++ b/test/v3/mocks/raw-transactions-mocks.js @@ -2,23 +2,23 @@ This library contains mocking data for running unit tests. */ -"use strict" +'use strict' const mockDecodeRawTransaction = { - txid: "a332237d82a2543af1b0e1ae3c8cea1610c290ebcaf084a7e9894a61de0be988", - hash: "a332237d82a2543af1b0e1ae3c8cea1610c290ebcaf084a7e9894a61de0be988", + txid: 'a332237d82a2543af1b0e1ae3c8cea1610c290ebcaf084a7e9894a61de0be988', + hash: 'a332237d82a2543af1b0e1ae3c8cea1610c290ebcaf084a7e9894a61de0be988', size: 226, version: 2, locktime: 0, vin: [ { - txid: "21cced645eab150585ed7ca7c96edebab5793cc0a3b3b286c42fd7d6d798b5b9", + txid: '21cced645eab150585ed7ca7c96edebab5793cc0a3b3b286c42fd7d6d798b5b9', vout: 1, scriptSig: { asm: - "3045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd41390[ALL|FORKID] 0360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413d", + '3045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd41390[ALL|FORKID] 0360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413d', hex: - "483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413d" + '483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413d' }, sequence: 4294967295 } @@ -29,10 +29,10 @@ const mockDecodeRawTransaction = { n: 0, scriptPubKey: { asm: - "OP_DUP OP_HASH160 eb4b180def88e3f5625b2d8ae2c098ff7d85f664 OP_EQUALVERIFY OP_CHECKSIG", - hex: "76a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac", + 'OP_DUP OP_HASH160 eb4b180def88e3f5625b2d8ae2c098ff7d85f664 OP_EQUALVERIFY OP_CHECKSIG', + hex: '76a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac', reqSigs: 1, - type: "pubkeyhash", + type: 'pubkeyhash', addresses: [Array] } }, @@ -41,10 +41,10 @@ const mockDecodeRawTransaction = { n: 1, scriptPubKey: { asm: - "OP_DUP OP_HASH160 eb4b180def88e3f5625b2d8ae2c098ff7d85f664 OP_EQUALVERIFY OP_CHECKSIG", - hex: "76a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac", + 'OP_DUP OP_HASH160 eb4b180def88e3f5625b2d8ae2c098ff7d85f664 OP_EQUALVERIFY OP_CHECKSIG', + hex: '76a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac', reqSigs: 1, - type: "pubkeyhash", + type: 'pubkeyhash', addresses: [Array] } } @@ -53,31 +53,31 @@ const mockDecodeRawTransaction = { const mockDecodeScript = { asm: - "0 0 -57 OP_NOP6 OP_LSHIFT OP_UNKNOWN OP_UNKNOWN OP_UNKNOWN c486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa OP_2OVER OP_NUMEQUALVERIFY OP_OR OP_INVERT OP_UNKNOWN OP_UNKNOWN 2ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab 67c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b [error]", - type: "nonstandard", - p2sh: "bchtest:pzy6dwfy6yf373w0dr05a6flfqksurjhwcl3awhdvm" + '0 0 -57 OP_NOP6 OP_LSHIFT OP_UNKNOWN OP_UNKNOWN OP_UNKNOWN c486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa OP_2OVER OP_NUMEQUALVERIFY OP_OR OP_INVERT OP_UNKNOWN OP_UNKNOWN 2ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab 67c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b [error]', + type: 'nonstandard', + p2sh: 'bchtest:pzy6dwfy6yf373w0dr05a6flfqksurjhwcl3awhdvm' } const mockRawTransactionConcise = - "02000000014e6b52500110b1c30315b85805fb274f0f4afceffc1589f889b27709e59e987d000000006a473044022052762770baa71c1a0b9544ad0f1ea343d32c22aa87c5f8397b6852f464c15b1e02201f4390745cb470e21e0e3c14229f39fef55ea0643a4c997f99d9f3501eae09b7412103c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792ffffffff02d1778f950a0000001976a91436d2f27bbd826a86db1e93618ce3de89ef33169388ac80969800000000001976a914152ea3cd65f18cb8fa9146c84ea1a97af8f051de88ac00000000" + '02000000014e6b52500110b1c30315b85805fb274f0f4afceffc1589f889b27709e59e987d000000006a473044022052762770baa71c1a0b9544ad0f1ea343d32c22aa87c5f8397b6852f464c15b1e02201f4390745cb470e21e0e3c14229f39fef55ea0643a4c997f99d9f3501eae09b7412103c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792ffffffff02d1778f950a0000001976a91436d2f27bbd826a86db1e93618ce3de89ef33169388ac80969800000000001976a914152ea3cd65f18cb8fa9146c84ea1a97af8f051de88ac00000000' const mockRawTransactionVerbose = { hex: - "02000000014e6b52500110b1c30315b85805fb274f0f4afceffc1589f889b27709e59e987d000000006a473044022052762770baa71c1a0b9544ad0f1ea343d32c22aa87c5f8397b6852f464c15b1e02201f4390745cb470e21e0e3c14229f39fef55ea0643a4c997f99d9f3501eae09b7412103c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792ffffffff02d1778f950a0000001976a91436d2f27bbd826a86db1e93618ce3de89ef33169388ac80969800000000001976a914152ea3cd65f18cb8fa9146c84ea1a97af8f051de88ac00000000", - txid: "bd320377db7026a3dd5c7ec444596c0ee18fc25c4f34ee944adc03e432ce1971", - hash: "bd320377db7026a3dd5c7ec444596c0ee18fc25c4f34ee944adc03e432ce1971", + '02000000014e6b52500110b1c30315b85805fb274f0f4afceffc1589f889b27709e59e987d000000006a473044022052762770baa71c1a0b9544ad0f1ea343d32c22aa87c5f8397b6852f464c15b1e02201f4390745cb470e21e0e3c14229f39fef55ea0643a4c997f99d9f3501eae09b7412103c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792ffffffff02d1778f950a0000001976a91436d2f27bbd826a86db1e93618ce3de89ef33169388ac80969800000000001976a914152ea3cd65f18cb8fa9146c84ea1a97af8f051de88ac00000000', + txid: 'bd320377db7026a3dd5c7ec444596c0ee18fc25c4f34ee944adc03e432ce1971', + hash: 'bd320377db7026a3dd5c7ec444596c0ee18fc25c4f34ee944adc03e432ce1971', size: 225, version: 2, locktime: 0, vin: [ { - txid: "7d989ee50977b289f88915fceffc4a0f4f27fb0558b81503c3b1100150526b4e", + txid: '7d989ee50977b289f88915fceffc4a0f4f27fb0558b81503c3b1100150526b4e', vout: 0, scriptSig: { asm: - "3044022052762770baa71c1a0b9544ad0f1ea343d32c22aa87c5f8397b6852f464c15b1e02201f4390745cb470e21e0e3c14229f39fef55ea0643a4c997f99d9f3501eae09b7[ALL|FORKID] 03c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792", + '3044022052762770baa71c1a0b9544ad0f1ea343d32c22aa87c5f8397b6852f464c15b1e02201f4390745cb470e21e0e3c14229f39fef55ea0643a4c997f99d9f3501eae09b7[ALL|FORKID] 03c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792', hex: - "473044022052762770baa71c1a0b9544ad0f1ea343d32c22aa87c5f8397b6852f464c15b1e02201f4390745cb470e21e0e3c14229f39fef55ea0643a4c997f99d9f3501eae09b7412103c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792" + '473044022052762770baa71c1a0b9544ad0f1ea343d32c22aa87c5f8397b6852f464c15b1e02201f4390745cb470e21e0e3c14229f39fef55ea0643a4c997f99d9f3501eae09b7412103c346eee77a77a8d3e073dacc0532ca7a5b9747bc06d88bf091cac9f4bc8bb792' }, sequence: 4294967295 } @@ -88,11 +88,11 @@ const mockRawTransactionVerbose = { n: 0, scriptPubKey: { asm: - "OP_DUP OP_HASH160 36d2f27bbd826a86db1e93618ce3de89ef331693 OP_EQUALVERIFY OP_CHECKSIG", - hex: "76a91436d2f27bbd826a86db1e93618ce3de89ef33169388ac", + 'OP_DUP OP_HASH160 36d2f27bbd826a86db1e93618ce3de89ef331693 OP_EQUALVERIFY OP_CHECKSIG', + hex: '76a91436d2f27bbd826a86db1e93618ce3de89ef33169388ac', reqSigs: 1, - type: "pubkeyhash", - addresses: ["bchtest:qqmd9unmhkpx4pkmr6fkrr8rm6y77vckjvqe8aey35"] + type: 'pubkeyhash', + addresses: ['bchtest:qqmd9unmhkpx4pkmr6fkrr8rm6y77vckjvqe8aey35'] } }, { @@ -100,34 +100,34 @@ const mockRawTransactionVerbose = { n: 1, scriptPubKey: { asm: - "OP_DUP OP_HASH160 152ea3cd65f18cb8fa9146c84ea1a97af8f051de OP_EQUALVERIFY OP_CHECKSIG", - hex: "76a914152ea3cd65f18cb8fa9146c84ea1a97af8f051de88ac", + 'OP_DUP OP_HASH160 152ea3cd65f18cb8fa9146c84ea1a97af8f051de OP_EQUALVERIFY OP_CHECKSIG', + hex: '76a914152ea3cd65f18cb8fa9146c84ea1a97af8f051de88ac', reqSigs: 1, - type: "pubkeyhash", - addresses: ["bchtest:qq2jag7dvhccew86j9rvsn4p49a03uz3mcpw3d6aca"] + type: 'pubkeyhash', + addresses: ['bchtest:qq2jag7dvhccew86j9rvsn4p49a03uz3mcpw3d6aca'] } } ], - blockhash: "000000000000026fa244de975ca89ea08008aa566564ce2e8ebb3144361b601b", + blockhash: '000000000000026fa244de975ca89ea08008aa566564ce2e8ebb3144361b601b', confirmations: 125, time: 1542646373, blocktime: 1542646373 } const mockWHDecode = { - txid: "f8a9857fe3b8a288b5fcafb1b0fc196731f433add6d962f77acd7c10b970ff89", - fee: "500", - sendingaddress: "bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr", - referenceaddress: "bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr", + txid: 'f8a9857fe3b8a288b5fcafb1b0fc196731f433add6d962f77acd7c10b970ff89', + fee: '500', + sendingaddress: 'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr', + referenceaddress: 'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr', ismine: false, version: 0, type_int: 0, - type: "Simple Send", + type: 'Simple Send', propertyid: 368, - precision: "8", - amount: "10.00000000", + precision: '8', + amount: '10.00000000', valid: true, - blockhash: "0000000046ba0bcef78caaa4492622176bbc563cf249ab52340a0449bc8e26f6", + blockhash: '0000000046ba0bcef78caaa4492622176bbc563cf249ab52340a0449bc8e26f6', blocktime: 1542814183, positioninblock: 57, block: 1269008, @@ -135,15 +135,15 @@ const mockWHDecode = { } const mockWHCreateInput = { - txid: "f7ed9cf23dee85910f6269c9a101a75fcfd2f3c6fc81f17fad824ff7aaf99ab2", + txid: 'f7ed9cf23dee85910f6269c9a101a75fcfd2f3c6fc81f17fad824ff7aaf99ab2', vout: 1, - scriptPubKey: "76a914a4b98b0c118de83e7d39c834445f51dce62425f588ac", + scriptPubKey: '76a914a4b98b0c118de83e7d39c834445f51dce62425f588ac', amount: 0.09984138, satoshis: 9984138, height: 1269011, confirmations: 4, - legacyAddress: "mvXwPH74hW2yVTWwDwzsjGoaUAqJvWk7ZJ", - cashAddress: "bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr", + legacyAddress: 'mvXwPH74hW2yVTWwDwzsjGoaUAqJvWk7ZJ', + cashAddress: 'bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr', value: 0.09984138 } diff --git a/test/v3/mocks/slp-mocks.js b/test/v3/mocks/slp-mocks.js index da15193..936600b 100644 --- a/test/v3/mocks/slp-mocks.js +++ b/test/v3/mocks/slp-mocks.js @@ -2,27 +2,27 @@ This library contains mocking data for running unit tests. */ -"use strict" +'use strict' const mockList = { t: [ { tokenDetails: { tokenIdHex: - "df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb", - documentUri: "", - documentSha256: "", - symbol: "NAKAMOTO", - name: "NAKAMOTO", + 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb', + documentUri: '', + documentSha256: '', + symbol: 'NAKAMOTO', + name: 'NAKAMOTO', decimals: 8 }, tokenStats: { qty_valid_txns_since_genesis: 241, qty_valid_token_utxos: 151, qty_valid_token_addresses: 113, - qty_token_circulating_supply: "20995990", - qty_token_burned: "4010", - qty_token_minted: "21000000", + qty_token_circulating_supply: '20995990', + qty_token_burned: '4010', + qty_token_minted: '21000000', qty_satoshis_locked_up: 81900 } } @@ -35,18 +35,18 @@ const mockSingleToken = { tokenDetails: { decimals: 0, tokenIdHex: - "38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0", - timestamp: "2019-06-14 06:31:37", + '38e97c5d7d3585a2cbf3f9580c82ca33985f9cb0845d4dcce220cb709f9538b0', + timestamp: '2019-06-14 06:31:37', timestamp_unix: 1560493897, - transactionType: "GENESIS", + transactionType: 'GENESIS', versionType: 1, - documentUri: "ot@ot.com", + documentUri: 'ot@ot.com', documentSha256Hex: null, - symbol: "OT", - name: "Test First SLP oasis Token", + symbol: 'OT', + name: 'Test First SLP oasis Token', batonVout: 2, containsBaton: true, - genesisOrMintQuantity: "10000", + genesisOrMintQuantity: '10000', sendOutputs: null }, tokenStats: { @@ -56,11 +56,11 @@ const mockSingleToken = { qty_valid_txns_since_genesis: 11, qty_valid_token_utxos: 9, qty_valid_token_addresses: 2, - qty_token_minted: "20000", - qty_token_burned: "0", - qty_token_circulating_supply: "20000", + qty_token_minted: '20000', + qty_token_burned: '0', + qty_token_circulating_supply: '20000', qty_satoshis_locked_up: 4914, - minting_baton_status: "ALIVE" + minting_baton_status: 'ALIVE' } } ] @@ -73,14 +73,14 @@ const mockSingleTokenError = { const mockSingleAddress = { a: [ { - _id: "5c93ed62a19119333d1595bc", + _id: '5c93ed62a19119333d1595bc', tokenDetails: { tokenIdHex: - "6b081fcd1f78b187be1464313dac8ff257251b727a42b613552a4040870aeb29" + '6b081fcd1f78b187be1464313dac8ff257251b727a42b613552a4040870aeb29' }, - address: "slptest:pz0qcslrqn7hr44hsszwl4lw5r6udkg6zqv7sq3kk7", + address: 'slptest:pz0qcslrqn7hr44hsszwl4lw5r6udkg6zqv7sq3kk7', satoshis_balance: 546, - token_balance: "4616984" + token_balance: '4616984' } ], t: [ @@ -88,17 +88,17 @@ const mockSingleAddress = { tokenDetails: { decimals: 8, tokenIdHex: - "6b081fcd1f78b187be1464313dac8ff257251b727a42b613552a4040870aeb29", - timestamp: "2019-02-25 10:05", - transactionType: "GENESIS", + '6b081fcd1f78b187be1464313dac8ff257251b727a42b613552a4040870aeb29', + timestamp: '2019-02-25 10:05', + transactionType: 'GENESIS', versionType: 1, - documentUri: "https://developer.bitcoin.com", - documentSha256Hex: "", - symbol: "DEV", - name: "DEVCOIN", + documentUri: 'https://developer.bitcoin.com', + documentSha256Hex: '', + symbol: 'DEV', + name: 'DEVCOIN', batonVout: 2, containsBaton: true, - genesisOrMintQuantity: "500000000", + genesisOrMintQuantity: '500000000', sendOutputs: null }, tokenStats: { @@ -108,125 +108,125 @@ const mockSingleAddress = { qty_valid_txns_since_genesis: 172, qty_valid_token_utxos: 170, qty_valid_token_addresses: 170, - qty_token_minted: "1000000000", - qty_token_burned: "4.99999995", - qty_token_circulating_supply: "999999995.00000005", + qty_token_minted: '1000000000', + qty_token_burned: '4.99999995', + qty_token_circulating_supply: '999999995.00000005', qty_satoshis_locked_up: 92820, - minting_baton_status: "ALIVE" + minting_baton_status: 'ALIVE' } } ] } const mockTx = { - txid: "57b3082a2bf269b3d6f40fee7fb9c664e8256a88ca5ee2697c05b9457822d446", + txid: '57b3082a2bf269b3d6f40fee7fb9c664e8256a88ca5ee2697c05b9457822d446', version: 2, locktime: 0, vin: [ { - txid: "61e71554a3dc18158f30d9e8f5c9b6641a789690b32302899f81cbea9fe3bb49", + txid: '61e71554a3dc18158f30d9e8f5c9b6641a789690b32302899f81cbea9fe3bb49', vout: 2, sequence: 4294967295, n: 0, scriptSig: { hex: - "4730440220409e79fec552f01203f41d3d621ae3db89c720af261c8268ce5f0453de009f5d022001e7ffefeba7b0716d32ea55cb6ace267b6ee9cbcc8a017bb9c3b6acf7889418412103c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585", + '4730440220409e79fec552f01203f41d3d621ae3db89c720af261c8268ce5f0453de009f5d022001e7ffefeba7b0716d32ea55cb6ace267b6ee9cbcc8a017bb9c3b6acf7889418412103c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585', asm: - "30440220409e79fec552f01203f41d3d621ae3db89c720af261c8268ce5f0453de009f5d022001e7ffefeba7b0716d32ea55cb6ace267b6ee9cbcc8a017bb9c3b6acf7889418[ALL|FORKID] 03c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585" + '30440220409e79fec552f01203f41d3d621ae3db89c720af261c8268ce5f0453de009f5d022001e7ffefeba7b0716d32ea55cb6ace267b6ee9cbcc8a017bb9c3b6acf7889418[ALL|FORKID] 03c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585' }, value: 546, - legacyAddress: "mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL", - cashAddress: "bchtest:qz4qnxcxwvmacgye8wlakhz0835x0w3vtvaga95c09" + legacyAddress: 'mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL', + cashAddress: 'bchtest:qz4qnxcxwvmacgye8wlakhz0835x0w3vtvaga95c09' }, { - txid: "61e71554a3dc18158f30d9e8f5c9b6641a789690b32302899f81cbea9fe3bb49", + txid: '61e71554a3dc18158f30d9e8f5c9b6641a789690b32302899f81cbea9fe3bb49', vout: 1, sequence: 4294967295, n: 1, scriptSig: { hex: - "483045022100a743bee56c99bd103be48a78fa4c7342100815d9d2448dbe6e1d338c3a13b241022066728b5279fc22eef5cd019582ff34771e29175835fc98aa3168a1548fd78ac8412103c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585", + '483045022100a743bee56c99bd103be48a78fa4c7342100815d9d2448dbe6e1d338c3a13b241022066728b5279fc22eef5cd019582ff34771e29175835fc98aa3168a1548fd78ac8412103c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585', asm: - "3045022100a743bee56c99bd103be48a78fa4c7342100815d9d2448dbe6e1d338c3a13b241022066728b5279fc22eef5cd019582ff34771e29175835fc98aa3168a1548fd78ac8[ALL|FORKID] 03c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585" + '3045022100a743bee56c99bd103be48a78fa4c7342100815d9d2448dbe6e1d338c3a13b241022066728b5279fc22eef5cd019582ff34771e29175835fc98aa3168a1548fd78ac8[ALL|FORKID] 03c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585' }, value: 546, - legacyAddress: "mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL", - cashAddress: "bchtest:qz4qnxcxwvmacgye8wlakhz0835x0w3vtvaga95c09" + legacyAddress: 'mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL', + cashAddress: 'bchtest:qz4qnxcxwvmacgye8wlakhz0835x0w3vtvaga95c09' }, { - txid: "61e71554a3dc18158f30d9e8f5c9b6641a789690b32302899f81cbea9fe3bb49", + txid: '61e71554a3dc18158f30d9e8f5c9b6641a789690b32302899f81cbea9fe3bb49', vout: 3, sequence: 4294967295, n: 2, scriptSig: { hex: - "483045022100821473902eec5f1ce7d43b1ba7f9ec453bfe8b8dfc3de3e0723c883ab109922f02206162960e80618531fab2c16aee260fddd7979bab62471c8686af7de75f8732ec412103c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585", + '483045022100821473902eec5f1ce7d43b1ba7f9ec453bfe8b8dfc3de3e0723c883ab109922f02206162960e80618531fab2c16aee260fddd7979bab62471c8686af7de75f8732ec412103c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585', asm: - "3045022100821473902eec5f1ce7d43b1ba7f9ec453bfe8b8dfc3de3e0723c883ab109922f02206162960e80618531fab2c16aee260fddd7979bab62471c8686af7de75f8732ec[ALL|FORKID] 03c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585" + '3045022100821473902eec5f1ce7d43b1ba7f9ec453bfe8b8dfc3de3e0723c883ab109922f02206162960e80618531fab2c16aee260fddd7979bab62471c8686af7de75f8732ec[ALL|FORKID] 03c87f0ec048a0771bdb60533d45cac88c6974afeb055a65edd663c2f947335585' }, value: 9997521, - legacyAddress: "mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL", - cashAddress: "bchtest:qz4qnxcxwvmacgye8wlakhz0835x0w3vtvaga95c09" + legacyAddress: 'mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL', + cashAddress: 'bchtest:qz4qnxcxwvmacgye8wlakhz0835x0w3vtvaga95c09' } ], vout: [ { - value: "0.00000000", + value: '0.00000000', n: 0, scriptPubKey: { hex: - "6a04534c500001010453454e44207ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796080000000049504f80080000001c71e64280", + '6a04534c500001010453454e44207ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796080000000049504f80080000001c71e64280', asm: - "OP_RETURN 5262419 1 1145980243 7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796 0000000049504f80 0000001c71e64280" + 'OP_RETURN 5262419 1 1145980243 7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796 0000000049504f80 0000001c71e64280' }, spentTxId: null, spentIndex: null, spentHeight: null }, { - value: "0.00000546", + value: '0.00000546', n: 1, scriptPubKey: { - hex: "76a914396b8e57ad0cb58d30e2992f22047b3c20377aa688ac", + hex: '76a914396b8e57ad0cb58d30e2992f22047b3c20377aa688ac', asm: - "OP_DUP OP_HASH160 396b8e57ad0cb58d30e2992f22047b3c20377aa6 OP_EQUALVERIFY OP_CHECKSIG", - addresses: ["mkkZf7T3fU3vHSzNPy51HBmM46ghN1gnN9"], - type: "pubkeyhash" + 'OP_DUP OP_HASH160 396b8e57ad0cb58d30e2992f22047b3c20377aa6 OP_EQUALVERIFY OP_CHECKSIG', + addresses: ['mkkZf7T3fU3vHSzNPy51HBmM46ghN1gnN9'], + type: 'pubkeyhash' }, spentTxId: null, spentIndex: null, spentHeight: null }, { - value: "0.00000546", + value: '0.00000546', n: 2, scriptPubKey: { - hex: "76a914aa099b067337dc20993bbfdb5c4f3c6867ba2c5b88ac", + hex: '76a914aa099b067337dc20993bbfdb5c4f3c6867ba2c5b88ac', asm: - "OP_DUP OP_HASH160 aa099b067337dc20993bbfdb5c4f3c6867ba2c5b OP_EQUALVERIFY OP_CHECKSIG", - addresses: ["mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL"], - type: "pubkeyhash" + 'OP_DUP OP_HASH160 aa099b067337dc20993bbfdb5c4f3c6867ba2c5b OP_EQUALVERIFY OP_CHECKSIG', + addresses: ['mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL'], + type: 'pubkeyhash' }, spentTxId: null, spentIndex: null, spentHeight: null }, { - value: "0.09996891", + value: '0.09996891', n: 3, scriptPubKey: { - hex: "76a914aa099b067337dc20993bbfdb5c4f3c6867ba2c5b88ac", + hex: '76a914aa099b067337dc20993bbfdb5c4f3c6867ba2c5b88ac', asm: - "OP_DUP OP_HASH160 aa099b067337dc20993bbfdb5c4f3c6867ba2c5b OP_EQUALVERIFY OP_CHECKSIG", - addresses: ["mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL"], - type: "pubkeyhash" + 'OP_DUP OP_HASH160 aa099b067337dc20993bbfdb5c4f3c6867ba2c5b OP_EQUALVERIFY OP_CHECKSIG', + addresses: ['mw22g57T9YA7MZQQu5eBDKj3PKTdt99oDL'], + type: 'pubkeyhash' }, spentTxId: null, spentIndex: null, spentHeight: null } ], - blockhash: "000000000000ce978accc64a6bb567acf0c653c202309a0f8e220149bf0c6968", + blockhash: '000000000000ce978accc64a6bb567acf0c653c202309a0f8e220149bf0c6968', blockheight: 1287490, confirmations: 746, time: 1550855104, @@ -237,28 +237,28 @@ const mockTx = { fees: 0.0000063, tokenInfo: { versionType: 1, - transactionType: "SEND", + transactionType: 'SEND', tokenIdHex: - "7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796", - sendOutputs: ["0", "1230000000", "122170000000"] + '7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796', + sendOutputs: ['0', '1230000000', '122170000000'] }, tokenIsValid: true } const mockConvert = { - slpAddress: "slptest:qz35h5mfa8w2pqma2jq06lp7dnv5fxkp2shlcycvd5", - cashAddress: "bchtest:qz35h5mfa8w2pqma2jq06lp7dnv5fxkp2svtllzmlf", - legacyAddress: "mvQPGnzRT6gMWASZBMg7NcT3vmvsSKSQtf" + slpAddress: 'slptest:qz35h5mfa8w2pqma2jq06lp7dnv5fxkp2shlcycvd5', + cashAddress: 'bchtest:qz35h5mfa8w2pqma2jq06lp7dnv5fxkp2svtllzmlf', + legacyAddress: 'mvQPGnzRT6gMWASZBMg7NcT3vmvsSKSQtf' } const mockTokenDetails = { tokenIdHex: - "df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb", - documentUri: "", - symbol: "NAKAMOTO", - name: "NAKAMOTO", + 'df808a41672a0a0ae6475b44f272a107bc9961b90f29dc918d71301f24fe92fb', + documentUri: '', + symbol: 'NAKAMOTO', + name: 'NAKAMOTO', decimals: 8, - timestamp: "", + timestamp: '', containsBaton: true, versionType: 1 } @@ -267,29 +267,29 @@ const mockTokenStats = { qty_valid_txns_since_genesis: 241, qty_valid_token_utxos: 151, qty_valid_token_addresses: 113, - qty_token_circulating_supply: "20995990", - qty_token_burned: "4010", - qty_token_minted: "21000000", + qty_token_circulating_supply: '20995990', + qty_token_burned: '4010', + qty_token_minted: '21000000', qty_satoshis_locked_up: 81900 } const mockBalance = { - slpAddress: "simpleledger:qp9d8mn8ypryfvea2mev0ggc3wg6plpn4suuaeuss3", + slpAddress: 'simpleledger:qp9d8mn8ypryfvea2mev0ggc3wg6plpn4suuaeuss3', satoshis_balance: 546, - token_balance: "1000" + token_balance: '1000' } const mockTransactions = [ { - txid: "a302f045be8efa1cd982833a7f187ff4fac8baac36da0c887eb2787d8b45e2af", + txid: 'a302f045be8efa1cd982833a7f187ff4fac8baac36da0c887eb2787d8b45e2af', tokenDetails: { valid: true, detail: { decimals: null, tokenIdHex: - "495322b37d6b2eae81f045eda612b95870a0c2b6069c58f70cf8ef4e6a9fd43a", + '495322b37d6b2eae81f045eda612b95870a0c2b6069c58f70cf8ef4e6a9fd43a', timestamp: null, - transactionType: "MINT", + transactionType: 'MINT', versionType: 1, documentUri: null, documentSha256Hex: null, @@ -298,7 +298,7 @@ const mockTransactions = [ batonVout: 2, containsBaton: true, genesisOrMintQuantity: { - $numberDecimal: "1000" + $numberDecimal: '1000' }, sendOutputs: null }, @@ -316,9 +316,9 @@ const mockFoobar = { const mockSingleValidTxid = { c: [ { - _id: "5d965fc27f1cf2184ca2fe73", + _id: '5d965fc27f1cf2184ca2fe73', tx: { - h: "77872738b6bddee6c0cbdb9509603de20b15d4f6b26602f629417aec2f5d5e8d" + h: '77872738b6bddee6c0cbdb9509603de20b15d4f6b26602f629417aec2f5d5e8d' }, slp: { valid: true, @@ -332,9 +332,9 @@ const mockSingleValidTxid = { const mockTwoValidTxid = { c: [ { - _id: "5d965fc27f1cf2184ca2fe73", + _id: '5d965fc27f1cf2184ca2fe73', tx: { - h: "77872738b6bddee6c0cbdb9509603de20b15d4f6b26602f629417aec2f5d5e8d" + h: '77872738b6bddee6c0cbdb9509603de20b15d4f6b26602f629417aec2f5d5e8d' }, slp: { valid: true, @@ -342,9 +342,9 @@ const mockTwoValidTxid = { } }, { - _id: "5d71e69758380a002c492a90", + _id: '5d71e69758380a002c492a90', tx: { - h: "552112f9e458dc7d1d8b328b0a6685e8af74a64b60b6846e7c86407f27f47e42" + h: '552112f9e458dc7d1d8b328b0a6685e8af74a64b60b6846e7c86407f27f47e42' }, slp: { valid: true, @@ -358,9 +358,9 @@ const mockTwoValidTxid = { const mockTwoRedundentTxid = { c: [ { - _id: "5db99c72a391ae2afd604bde", + _id: '5db99c72a391ae2afd604bde', tx: { - h: "d56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56" + h: 'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56' }, slp: { valid: true, diff --git a/test/v3/mocks/slpjs-mocks.js b/test/v3/mocks/slpjs-mocks.js index c130935..e1294f6 100644 --- a/test/v3/mocks/slpjs-mocks.js +++ b/test/v3/mocks/slpjs-mocks.js @@ -2,18 +2,18 @@ Mocks used for unit tests that interact with slpjs. */ -"use strict" +'use strict' -const sinon = require("sinon") -const proxyquire = require("proxyquire") -const BigNumber = require("bignumber.js") -const slpMocks = require("./slp-mocks") +// const sinon = require('sinon') +// const proxyquire = require('proxyquire') +const BigNumber = require('bignumber.js') +const slpMocks = require('./slp-mocks') // Mock the BitboxNetwork class. class BitboxNetwork { - constructor() {} + // constructor () {} - async getAllSlpBalancesAndUtxos(address) { + async getAllSlpBalancesAndUtxos (address) { return { satoshis_available_bch: 9996891, satoshis_in_slp_baton: 546, @@ -21,15 +21,15 @@ class BitboxNetwork { satoshis_in_invalid_token_dag: 0, satoshis_in_invalid_baton_dag: 0, slpTokenBalances: { - "7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796": new BigNumber( + '7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796': new BigNumber( 123400000000 ) }, slpTokenUtxos: { - "7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796": [] + '7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796': [] }, slpBatonUtxos: { - "7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796": [] + '7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796': [] }, nonSlpUtxos: [{}], invalidTokenUtxos: [], @@ -37,15 +37,15 @@ class BitboxNetwork { } } - async getTokenInformation(txid) { + async getTokenInformation (txid) { BigNumber.set({ DECIMAL_PLACES: 8, ROUNDING_MODE: 4 }) const obj = { versionType: 1, transactionType: 0, - symbol: "SLPSDK", - name: "SLP SDK example using BITBOX", - documentUri: "developer.bitcoin.com", + symbol: 'SLPSDK', + name: 'SLP SDK example using BITBOX', + documentUri: 'developer.bitcoin.com', documentSha256: null, decimals: 8, batonVout: 2, @@ -56,7 +56,7 @@ class BitboxNetwork { return obj } - async getTransactionDetails(txid) { + async getTransactionDetails (txid) { return slpMocks.mockTx } } diff --git a/test/v3/mocks/transaction-mocks.js b/test/v3/mocks/transaction-mocks.js index a8d22e2..89d67bf 100644 --- a/test/v3/mocks/transaction-mocks.js +++ b/test/v3/mocks/transaction-mocks.js @@ -2,7 +2,7 @@ This library contains mocking data for running unit tests on the address route. */ -"use strict" +'use strict' /* const mockDetails = { @@ -24,17 +24,17 @@ const mockDetails = { */ const mockDetails = { - txid: "6f235bd3a689f03c11969cd649ccad592462ca958bc519a30194e7a67b349a40", + txid: '6f235bd3a689f03c11969cd649ccad592462ca958bc519a30194e7a67b349a40', version: 2, locktime: 0, vin: [ { - txid: "273d616d1c48f4b075c497f36ffdc79da5c8d6ed75485808b3599aac504f8525", + txid: '273d616d1c48f4b075c497f36ffdc79da5c8d6ed75485808b3599aac504f8525', vout: 0, sequence: 4294967295, n: 0, scriptSig: [{}], - addr: "bchtest:qqmd9unmhkpx4pkmr6fkrr8rm6y77vckjvqe8aey35", + addr: 'bchtest:qqmd9unmhkpx4pkmr6fkrr8rm6y77vckjvqe8aey35', valueSat: 45078867559, value: 450.78867559, doubleSpentTxID: null @@ -42,7 +42,7 @@ const mockDetails = { ], vout: [ { - value: "450.68867333", + value: '450.68867333', n: 0, scriptPubKey: [{}], spentTxId: null, @@ -50,7 +50,7 @@ const mockDetails = { spentHeight: null }, { - value: "0.10000000", + value: '0.10000000', n: 1, scriptPubKey: [{}], spentTxId: null, @@ -58,7 +58,7 @@ const mockDetails = { spentHeight: null } ], - blockhash: "00000000e7232ff12462dedf9c11985f5b54202515277c337ccc59812758f28b", + blockhash: '00000000e7232ff12462dedf9c11985f5b54202515277c337ccc59812758f28b', blockheight: 1270188, confirmations: 3, time: 1543436253, diff --git a/test/v3/mocks/util-mocks.js b/test/v3/mocks/util-mocks.js index 2692702..6b7f46b 100644 --- a/test/v3/mocks/util-mocks.js +++ b/test/v3/mocks/util-mocks.js @@ -2,12 +2,12 @@ This library contains mocking data for running unit tests on the address route. */ -"use strict" +'use strict' const mockAddress = { isvalid: true, - address: "bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y", - scriptPubKey: "76a914016a935f87e8deeab04501889b22d87e4e52db0988ac", + address: 'bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y', + scriptPubKey: '76a914016a935f87e8deeab04501889b22d87e4e52db0988ac', ismine: false, iswatchonly: false, isscript: false @@ -17,32 +17,32 @@ const mockBalance = { page: 1, totalPages: 1, itemsOnPage: 1000, - address: "bitcoincash:qzp7gdl52edm24xlpkyqnza9rv33u3mdxyc77j3u6k", - balance: "2546", - totalReceived: "2546", - totalSent: "0", - unconfirmedBalance: "0", + address: 'bitcoincash:qzp7gdl52edm24xlpkyqnza9rv33u3mdxyc77j3u6k', + balance: '2546', + totalReceived: '2546', + totalSent: '0', + unconfirmedBalance: '0', unconfirmedTxs: 0, txs: 2, txids: [ - "e190d13b88578132608ab912a4d2be3e55aa2792d6042d481ae21d700639de56", - "44e1f48c4093fc61db1a8fa206aa402fc34e482b3f788cb38c123ca0e1a35db6" + 'e190d13b88578132608ab912a4d2be3e55aa2792d6042d481ae21d700639de56', + '44e1f48c4093fc61db1a8fa206aa402fc34e482b3f788cb38c123ca0e1a35db6' ] } const mockUtxos = [ { - txid: "e190d13b88578132608ab912a4d2be3e55aa2792d6042d481ae21d700639de56", + txid: 'e190d13b88578132608ab912a4d2be3e55aa2792d6042d481ae21d700639de56', vout: 0, - value: "2000", + value: '2000', height: 605873, confirmations: 298, satoshis: 2000 }, { - txid: "44e1f48c4093fc61db1a8fa206aa402fc34e482b3f788cb38c123ca0e1a35db6", + txid: '44e1f48c4093fc61db1a8fa206aa402fc34e482b3f788cb38c123ca0e1a35db6', vout: 1, - value: "546", + value: '546', height: 605873, confirmations: 298, satoshis: 546 @@ -51,25 +51,25 @@ const mockUtxos = [ const mockThreeUtxos = [ { - txid: "e190d13b88578132608ab912a4d2be3e55aa2792d6042d481ae21d700639de56", + txid: 'e190d13b88578132608ab912a4d2be3e55aa2792d6042d481ae21d700639de56', vout: 0, - value: "2000", + value: '2000', height: 605873, confirmations: 298, satoshis: 2000 }, { - txid: "44e1f48c4093fc61db1a8fa206aa402fc34e482b3f788cb38c123ca0e1a35db6", + txid: '44e1f48c4093fc61db1a8fa206aa402fc34e482b3f788cb38c123ca0e1a35db6', vout: 1, - value: "546", + value: '546', height: 605873, confirmations: 298, satoshis: 546 }, { - txid: "44e1f48c4093fc61db1a8fa206aa402fc34e482b3f788cb38c123ca0e1a35db6", + txid: '44e1f48c4093fc61db1a8fa206aa402fc34e482b3f788cb38c123ca0e1a35db6', vout: 1, - value: "546", + value: '546', height: 605873, confirmations: 298, satoshis: 546 @@ -79,38 +79,38 @@ const mockThreeUtxos = [ const mockIsTokenUtxos = [ false, { - txid: "44e1f48c4093fc61db1a8fa206aa402fc34e482b3f788cb38c123ca0e1a35db6", + txid: '44e1f48c4093fc61db1a8fa206aa402fc34e482b3f788cb38c123ca0e1a35db6', vout: 1, - value: "546", + value: '546', height: 605873, confirmations: 298, satoshis: 546, - utxoType: "token", - transactionType: "send", - tokenId: "497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7", - tokenTicker: "TOK-CH", - tokenName: "TokyoCash", - tokenDocumentUrl: "", - tokenDocumentHash: "", + utxoType: 'token', + transactionType: 'send', + tokenId: '497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7', + tokenTicker: 'TOK-CH', + tokenName: 'TokyoCash', + tokenDocumentUrl: '', + tokenDocumentHash: '', decimals: 8, tokenQty: 2 } ] const tapUtxo = { - txid: "2e030df12390186baf817fa2760540b886511e04bc520e88f6b4c2124cc2a7d4", + txid: '2e030df12390186baf817fa2760540b886511e04bc520e88f6b4c2124cc2a7d4', vout: 1, - value: "546", + value: '546', height: 606564, confirmations: 3, satoshis: 546, - utxoType: "token", - transactionType: "send", - tokenId: "dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d", - tokenTicker: "TAP", - tokenName: "Thoughts and Prayers", - tokenDocumentUrl: "", - tokenDocumentHash: "", + utxoType: 'token', + transactionType: 'send', + tokenId: 'dd84ca78db4d617221b58eabc6667af8fe2f7eadbfcc213d35be9f1b419beb8d', + tokenTicker: 'TAP', + tokenName: 'Thoughts and Prayers', + tokenDocumentUrl: '', + tokenDocumentHash: '', decimals: 0, tokenQty: 1 } diff --git a/test/v3/rate-limits.js b/test/v3/rate-limits.js index 2b832a1..8f2e173 100644 --- a/test/v3/rate-limits.js +++ b/test/v3/rate-limits.js @@ -1,45 +1,44 @@ -"use strict" +'use strict' -const chai = require("chai") +const chai = require('chai') const assert = chai.assert -const nock = require("nock") // HTTP mocking -const sinon = require("sinon") +// const nock = require('nock') // HTTP mocking +const sinon = require('sinon') // Used for debugging. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } // Mocking data. -const { mockReq, mockRes, mockNext } = require("./mocks/express-mocks") +const { mockReq, mockRes, mockNext } = require('./mocks/express-mocks') // Libraries under test -const RateLimits = require("../../src/middleware/route-ratelimit") +const RateLimits = require('../../src/middleware/route-ratelimit') let rateLimits = new RateLimits() let rateLimitMiddleware = rateLimits.routeRateLimit -const controlRoute = require("../../src/routes/v3/full-node/control") -const jwtAuth = require("../../src/middleware/jwt-auth") +// const controlRoute = require('../../src/routes/v3/full-node/control') +const jwtAuth = require('../../src/middleware/jwt-auth') let req, res, next -let originalEnvVars // Used during transition from integration to unit tests. +// let originalEnvVars // Used during transition from integration to unit tests. // JWT token used in tests. -const jwt = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVkYWRlM2Y1NzM5ZTZjMGZmMDM0YjlhMSIsImlhdCI6MTU3MTY3NzQ1MCwiZXhwIjoxNTc0MjY5NDUwfQ.SSz7F7ETyBB3eoNG2VKCzPOhddtB-vrtmEoj7PxicrQ` +const jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVkYWRlM2Y1NzM5ZTZjMGZmMDM0YjlhMSIsImlhdCI6MTU3MTY3NzQ1MCwiZXhwIjoxNTc0MjY5NDUwfQ.SSz7F7ETyBB3eoNG2VKCzPOhddtB-vrtmEoj7PxicrQ' -describe("#route-ratelimits & jwt-auth", () => { +describe('#route-ratelimits & jwt-auth', () => { let sandbox before(() => { // Save existing environment variables. - originalEnvVars = { - BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL, - RPC_BASEURL: process.env.RPC_BASEURL, - RPC_USERNAME: process.env.RPC_USERNAME, - RPC_PASSWORD: process.env.RPC_PASSWORD - } + // originalEnvVars = { + // BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL, + // RPC_BASEURL: process.env.RPC_BASEURL, + // RPC_USERNAME: process.env.RPC_USERNAME, + // RPC_PASSWORD: process.env.RPC_PASSWORD + // } - if (!process.env.JWT_AUTH_SERVER) - process.env.JWT_AUTH_SERVER = `http://fakeurl.com/` + if (!process.env.JWT_AUTH_SERVER) { process.env.JWT_AUTH_SERVER = 'http://fakeurl.com/' } }) // Setup the mocks before each test. @@ -66,9 +65,9 @@ describe("#route-ratelimits & jwt-auth", () => { rateLimits.closeRedis() }) - describe("#jwt-auth.js", () => { - describe("#getTokenFromHeaders", () => { - it(`should populate the req.locals object correctly`, () => { + describe('#jwt-auth.js', () => { + describe('#getTokenFromHeaders', () => { + it('should populate the req.locals object correctly', () => { // Initialize req.locals req.locals = { proLimit: false, @@ -82,23 +81,23 @@ describe("#route-ratelimits & jwt-auth", () => { // console.log(`req.locals: ${JSON.stringify(req.locals, null, 2)}`) - assert.property(req.locals, "proLimit") - assert.property(req.locals, "apiLevel") - assert.property(req.locals, "jwtToken") + assert.property(req.locals, 'proLimit') + assert.property(req.locals, 'apiLevel') + assert.property(req.locals, 'jwtToken') assert.equal(req.locals.jwtToken, jwt) }) }) }) - describe("#routeRateLimit", () => { + describe('#routeRateLimit', () => { rateLimitMiddleware = new RateLimits() let routeRateLimit = rateLimitMiddleware.routeRateLimit - const getInfo = controlRoute.testableComponents.getInfo + // const getInfo = controlRoute.testableComponents.getInfo - it("should pass through rate-limit middleware", async () => { - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" - req.method = "GET" + it('should pass through rate-limit middleware', async () => { + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' + req.method = 'GET' // Call the route twice to trigger the rate handling. await routeRateLimit(req, res, next) @@ -108,27 +107,27 @@ describe("#route-ratelimits & jwt-auth", () => { assert.equal(next.called, true) }) - it("should trigger rate-limit handler if rate limits exceeds 5 request per minute", async () => { - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" - req.method = "GET" + it('should trigger rate-limit handler if rate limits exceeds 5 request per minute', async () => { + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' + req.method = 'GET' for (let i = 0; i < 5; i++) { next.reset() // reset the stubbed next() function. await routeRateLimit(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, false, - `next should not be called if rate limit was triggered.` + 'next should not be called if rate limit was triggered.' ) }) - it("should NOT trigger rate-limit for free-tier at 5 RPM", async () => { + it('should NOT trigger rate-limit for free-tier at 5 RPM', async () => { // Clear the require cache before running this test. // delete require.cache[ // require.resolve("../../src/middleware/route-ratelimit") @@ -137,9 +136,9 @@ describe("#route-ratelimits & jwt-auth", () => { rateLimitMiddleware = new RateLimits() routeRateLimit = rateLimitMiddleware.routeRateLimit - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" - req.method = "GET" + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' + req.method = 'GET' req.locals.proLimit = true req.locals.apiLevel = 0 @@ -148,23 +147,23 @@ describe("#route-ratelimits & jwt-auth", () => { next.reset() // reset the stubbed next() function. await routeRateLimit(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } - //console.log(`req.locals after test: ${util.inspect(req.locals)}`) + // console.log(`req.locals after test: ${util.inspect(req.locals)}`) // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, true, - `next should be called if rate limit was not triggered.` + 'next should be called if rate limit was not triggered.' ) }) - it("should trigger rate-limit for free tier after 10 RPM", async () => { - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" - req.method = "GET" + it('should trigger rate-limit for free tier after 10 RPM', async () => { + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' + req.method = 'GET' req.locals.proLimit = true req.locals.apiLevel = 0 @@ -173,18 +172,18 @@ describe("#route-ratelimits & jwt-auth", () => { next.reset() // reset the stubbed next() function. await routeRateLimit(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, false, - `next should not be called if rate limit was triggered.` + 'next should not be called if rate limit was triggered.' ) }) - it("should NOT trigger rate-limit handler for pro-tier at 25 RPM", async () => { + it('should NOT trigger rate-limit handler for pro-tier at 25 RPM', async () => { // Clear the require cache before running this test. // delete require.cache[ // require.resolve("../../src/middleware/route-ratelimit") @@ -193,9 +192,9 @@ describe("#route-ratelimits & jwt-auth", () => { rateLimitMiddleware = new RateLimits() routeRateLimit = rateLimitMiddleware.routeRateLimit - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" - req.method = "GET" + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' + req.method = 'GET' req.locals.proLimit = true req.locals.apiLevel = 10 @@ -204,20 +203,20 @@ describe("#route-ratelimits & jwt-auth", () => { next.reset() // reset the stubbed next() function. await routeRateLimit(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } - //console.log(`req.locals after test: ${util.inspect(req.locals)}`) + // console.log(`req.locals after test: ${util.inspect(req.locals)}`) // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, true, - `next should be called if rate limit was not triggered.` + 'next should be called if rate limit was not triggered.' ) }) - it("rate-limiting should still kick in at a higher RPM for pro-tier", async () => { + it('rate-limiting should still kick in at a higher RPM for pro-tier', async () => { // Clear the require cache before running this test. // delete require.cache[ // require.resolve("../../src/middleware/route-ratelimit") @@ -226,9 +225,9 @@ describe("#route-ratelimits & jwt-auth", () => { rateLimitMiddleware = new RateLimits() routeRateLimit = rateLimitMiddleware.routeRateLimit - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" - req.method = "GET" + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' + req.method = 'GET' req.locals.proLimit = true req.locals.apiLevel = 10 @@ -237,166 +236,166 @@ describe("#route-ratelimits & jwt-auth", () => { next.reset() // reset the stubbed next() function. await routeRateLimit(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } - //console.log(`req.locals after test: ${util.inspect(req.locals)}`) + // console.log(`req.locals after test: ${util.inspect(req.locals)}`) // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, false, - `next should NOT be called if rate limit was triggered.` + 'next should NOT be called if rate limit was triggered.' ) }) }) - describe("#getResource", () => { - it("should decode a blockchain request", () => { + describe('#getResource', () => { + it('should decode a blockchain request', () => { const url = - "/blockchain/getTxOut/62a3ea958a463a372bc0caf2c374a7f60be9c624be63a0db8db78f05809df6d8/0?include_mempool=true" + '/blockchain/getTxOut/62a3ea958a463a372bc0caf2c374a7f60be9c624be63a0db8db78f05809df6d8/0?include_mempool=true' const result = rateLimits.getResource(url) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.equal(result, "blockchain") + assert.equal(result, 'blockchain') }) }) - describe("#calcPoints", () => { - it("should return 30 points for anonymous user", () => { + describe('#calcPoints', () => { + it('should return 30 points for anonymous user', () => { const result = rateLimits.calcPoints() // console.log(`result: ${result}`) assert.equal(result, 30) }) - it("should return 10 points for free tier requesting full node access", () => { + it('should return 10 points for free tier requesting full node access', () => { const jwtInfo = { apiLevel: 10, - resource: "blockchain", - id: "5e3a0415eb29a962da2708b4" + resource: 'blockchain', + id: '5e3a0415eb29a962da2708b4' } const result = rateLimits.calcPoints(jwtInfo) assert.equal(result, 10) }) - it("should return 10 points for free tier requesting indexer access", () => { + it('should return 10 points for free tier requesting indexer access', () => { const jwtInfo = { apiLevel: 10, - resource: "blockbook", - id: "5e3a0415eb29a962da2708b4" + resource: 'blockbook', + id: '5e3a0415eb29a962da2708b4' } const result = rateLimits.calcPoints(jwtInfo) assert.equal(result, 10) }) - it("should return 10 points for free tier requesting SLPDB access", () => { + it('should return 10 points for free tier requesting SLPDB access', () => { const jwtInfo = { apiLevel: 10, - resource: "slp", - id: "5e3a0415eb29a962da2708b4" + resource: 'slp', + id: '5e3a0415eb29a962da2708b4' } const result = rateLimits.calcPoints(jwtInfo) assert.equal(result, 10) }) - it("should return 1 point for full node tier requesting full node access", () => { + it('should return 1 point for full node tier requesting full node access', () => { const jwtInfo = { apiLevel: 20, - resource: "blockchain", - id: "5e3a0415eb29a962da2708b4" + resource: 'blockchain', + id: '5e3a0415eb29a962da2708b4' } const result = rateLimits.calcPoints(jwtInfo) assert.equal(result, 1) }) - it("should return 10 points for full-node tier requesting indexer access", () => { + it('should return 10 points for full-node tier requesting indexer access', () => { const jwtInfo = { apiLevel: 20, - resource: "blockbook", - id: "5e3a0415eb29a962da2708b4" + resource: 'blockbook', + id: '5e3a0415eb29a962da2708b4' } const result = rateLimits.calcPoints(jwtInfo) assert.equal(result, 10) }) - it("should return 10 points for full node tier requesting SLPDB access", () => { + it('should return 10 points for full node tier requesting SLPDB access', () => { const jwtInfo = { apiLevel: 20, - resource: "slp", - id: "5e3a0415eb29a962da2708b4" + resource: 'slp', + id: '5e3a0415eb29a962da2708b4' } const result = rateLimits.calcPoints(jwtInfo) assert.equal(result, 10) }) - it("should return 1 point for indexer tier requesting full node access", () => { + it('should return 1 point for indexer tier requesting full node access', () => { const jwtInfo = { apiLevel: 30, - resource: "blockchain", - id: "5e3a0415eb29a962da2708b4" + resource: 'blockchain', + id: '5e3a0415eb29a962da2708b4' } const result = rateLimits.calcPoints(jwtInfo) assert.equal(result, 1) }) - it("should return 1 points for indexer tier requesting indexer access", () => { + it('should return 1 points for indexer tier requesting indexer access', () => { const jwtInfo = { apiLevel: 30, - resource: "blockbook", - id: "5e3a0415eb29a962da2708b4" + resource: 'blockbook', + id: '5e3a0415eb29a962da2708b4' } const result = rateLimits.calcPoints(jwtInfo) assert.equal(result, 1) }) - it("should return 10 points for indexer tier requesting SLPDB access", () => { + it('should return 10 points for indexer tier requesting SLPDB access', () => { const jwtInfo = { apiLevel: 30, - resource: "slp", - id: "5e3a0415eb29a962da2708b4" + resource: 'slp', + id: '5e3a0415eb29a962da2708b4' } const result = rateLimits.calcPoints(jwtInfo) assert.equal(result, 10) }) - it("should return 1 point for SLP tier requesting full node access", () => { + it('should return 1 point for SLP tier requesting full node access', () => { const jwtInfo = { apiLevel: 40, - resource: "blockchain", - id: "5e3a0415eb29a962da2708b4" + resource: 'blockchain', + id: '5e3a0415eb29a962da2708b4' } const result = rateLimits.calcPoints(jwtInfo) assert.equal(result, 1) }) - it("should return 1 points for SLP tier requesting indexer access", () => { + it('should return 1 points for SLP tier requesting indexer access', () => { const jwtInfo = { apiLevel: 40, - resource: "blockbook", - id: "5e3a0415eb29a962da2708b4" + resource: 'blockbook', + id: '5e3a0415eb29a962da2708b4' } const result = rateLimits.calcPoints(jwtInfo) assert.equal(result, 1) }) - it("should return 1 points for SLP tier requesting SLPDB access", () => { + it('should return 1 points for SLP tier requesting SLPDB access', () => { const jwtInfo = { apiLevel: 40, - resource: "slp", - id: "5e3a0415eb29a962da2708b4" + resource: 'slp', + id: '5e3a0415eb29a962da2708b4' } const result = rateLimits.calcPoints(jwtInfo) @@ -404,28 +403,28 @@ describe("#route-ratelimits & jwt-auth", () => { }) }) - describe("#calcPoints2", () => { - it("should return 30 points for anonymous user", () => { + describe('#calcPoints2', () => { + it('should return 30 points for anonymous user', () => { const result = rateLimits.calcPoints2({}) // console.log(`result: ${result}`) assert.equal(result, 30) }) - it("should return 10 point for free tier", () => { + it('should return 10 point for free tier', () => { const jwtInfo = { rateLimit: 10, - id: "5e3a0415eb29a962da2708b4" + id: '5e3a0415eb29a962da2708b4' } const result = rateLimits.calcPoints2(jwtInfo) assert.equal(result, 10) }) - it("should return 1 point for pro tier", () => { + it('should return 1 point for pro tier', () => { const jwtInfo = { rateLimit: 100, - id: "5e3a0415eb29a962da2708b4" + id: '5e3a0415eb29a962da2708b4' } const result = rateLimits.calcPoints2(jwtInfo) @@ -433,12 +432,12 @@ describe("#route-ratelimits & jwt-auth", () => { }) }) - describe("#rateLimitByResource", () => { - it("should pass through rate-limit middleware", async () => { - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" + describe('#rateLimitByResource', () => { + it('should pass through rate-limit middleware', async () => { + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' req.url = req.path - req.method = "GET" + req.method = 'GET' // Call the route twice to trigger the rate handling. await rateLimits.rateLimitByResource(req, res, next) @@ -448,176 +447,176 @@ describe("#route-ratelimits & jwt-auth", () => { assert.equal(next.called, true) }) - it("should trigger rate-limit handler if rate limits exceeds 5 request per minute", async () => { - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" + it('should trigger rate-limit handler if rate limits exceeds 5 request per minute', async () => { + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' req.url = req.path - req.method = "GET" + req.method = 'GET' for (let i = 0; i < 5; i++) { next.reset() // reset the stubbed next() function. await rateLimits.rateLimitByResource(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, false, - `next should not be called if rate limit was triggered.` + 'next should not be called if rate limit was triggered.' ) }) - it("should NOT trigger rate-limit for free-tier at 5 RPM", async () => { + it('should NOT trigger rate-limit for free-tier at 5 RPM', async () => { // Create a new instance of the rate limit so we start with zeroed tracking. rateLimits = new RateLimits() - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' req.url = req.path - req.method = "GET" + req.method = 'GET' - req.locals.jwtToken = "some-token" + req.locals.jwtToken = 'some-token' const jwtInfo = { apiLevel: 10, - id: "5e3a0415eb29a962da2708b1" + id: '5e3a0415eb29a962da2708b1' } // Mock the call to the jwt library. - sandbox.stub(rateLimits.jwt, "verify").returns(jwtInfo) + sandbox.stub(rateLimits.jwt, 'verify').returns(jwtInfo) for (let i = 0; i < 5; i++) { next.reset() // reset the stubbed next() function. await rateLimits.rateLimitByResource(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } - //console.log(`req.locals after test: ${util.inspect(req.locals)}`) + // console.log(`req.locals after test: ${util.inspect(req.locals)}`) // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, true, - `next should be called if rate limit was not triggered.` + 'next should be called if rate limit was not triggered.' ) }) - it("should trigger rate-limit for free tier after 10 RPM", async () => { + it('should trigger rate-limit for free tier after 10 RPM', async () => { // Create a new instance of the rate limit so we start with zeroed tracking. rateLimits = new RateLimits() - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' req.url = req.path - req.method = "GET" + req.method = 'GET' - req.locals.jwtToken = "some-token" + req.locals.jwtToken = 'some-token' const jwtInfo = { apiLevel: 10, - id: "5e3a0415eb29a962da2708b2" + id: '5e3a0415eb29a962da2708b2' } // Mock the call to the jwt library. - sandbox.stub(rateLimits.jwt, "verify").returns(jwtInfo) + sandbox.stub(rateLimits.jwt, 'verify').returns(jwtInfo) for (let i = 0; i < 12; i++) { next.reset() // reset the stubbed next() function. await rateLimits.rateLimitByResource(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, false, - `next should not be called if rate limit was triggered.` + 'next should not be called if rate limit was triggered.' ) }) - it("should NOT trigger rate-limit handler for indexer-tier at 25 RPM", async () => { + it('should NOT trigger rate-limit handler for indexer-tier at 25 RPM', async () => { // Create a new instance of the rate limit so we start with zeroed tracking. rateLimits = new RateLimits() - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' req.url = req.path - req.method = "GET" + req.method = 'GET' - req.locals.jwtToken = "some-token" + req.locals.jwtToken = 'some-token' const jwtInfo = { apiLevel: 20, - id: "5e3a0415eb29a962da2708b3" + id: '5e3a0415eb29a962da2708b3' } // Mock the call to the jwt library. - sandbox.stub(rateLimits.jwt, "verify").returns(jwtInfo) + sandbox.stub(rateLimits.jwt, 'verify').returns(jwtInfo) for (let i = 0; i < 25; i++) { next.reset() // reset the stubbed next() function. await rateLimits.rateLimitByResource(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } - //console.log(`req.locals after test: ${util.inspect(req.locals)}`) + // console.log(`req.locals after test: ${util.inspect(req.locals)}`) // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, true, - `next should be called if rate limit was not triggered.` + 'next should be called if rate limit was not triggered.' ) }) - it("should still rate-limit at a higher RPM for pro-tier", async () => { + it('should still rate-limit at a higher RPM for pro-tier', async () => { // Create a new instance of the rate limit so we start with zeroed tracking. rateLimits = new RateLimits() - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' req.url = req.path - req.method = "GET" + req.method = 'GET' - req.locals.jwtToken = "some-token" + req.locals.jwtToken = 'some-token' const jwtInfo = { apiLevel: 20, - id: "5e3a0415eb29a962da2708b5" + id: '5e3a0415eb29a962da2708b5' } // Mock the call to the jwt library. - sandbox.stub(rateLimits.jwt, "verify").returns(jwtInfo) + sandbox.stub(rateLimits.jwt, 'verify').returns(jwtInfo) for (let i = 0; i < 150; i++) { next.reset() // reset the stubbed next() function. await rateLimits.rateLimitByResource(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } - //console.log(`req.locals after test: ${util.inspect(req.locals)}`) + // console.log(`req.locals after test: ${util.inspect(req.locals)}`) // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, false, - `next should NOT be called if rate limit was triggered.` + 'next should NOT be called if rate limit was triggered.' ) }) }) - describe("#rateLimitSimple", () => { - it("should pass through rate-limit middleware", async () => { - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" + describe('#rateLimitSimple', () => { + it('should pass through rate-limit middleware', async () => { + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' req.url = req.path - req.method = "GET" + req.method = 'GET' // Call the route twice to trigger the rate handling. await rateLimits.rateLimitSimple(req, res, next) @@ -627,179 +626,179 @@ describe("#route-ratelimits & jwt-auth", () => { assert.equal(next.called, true) }) - it("should trigger rate-limit handler if rate limits exceeds 5 request per minute", async () => { - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" + it('should trigger rate-limit handler if rate limits exceeds 5 request per minute', async () => { + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' req.url = req.path - req.method = "GET" + req.method = 'GET' for (let i = 0; i < 5; i++) { next.reset() // reset the stubbed next() function. await rateLimits.rateLimitSimple(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, false, - `next should not be called if rate limit was triggered.` + 'next should not be called if rate limit was triggered.' ) }) - it("should NOT trigger rate-limit for free-tier at 5 RPM", async () => { + it('should NOT trigger rate-limit for free-tier at 5 RPM', async () => { // Create a new instance of the rate limit so we start with zeroed tracking. rateLimits = new RateLimits() - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' req.url = req.path - req.method = "GET" + req.method = 'GET' - req.locals.jwtToken = "some-token" + req.locals.jwtToken = 'some-token' const jwtInfo = { rateLimit: 10, - id: "5e3a0415eb29a962da2708c1" + id: '5e3a0415eb29a962da2708c1' } // Mock the call to the jwt library. - sandbox.stub(rateLimits.jwt, "verify").returns(jwtInfo) + sandbox.stub(rateLimits.jwt, 'verify').returns(jwtInfo) for (let i = 0; i < 5; i++) { next.reset() // reset the stubbed next() function. await rateLimits.rateLimitSimple(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } - //console.log(`req.locals after test: ${util.inspect(req.locals)}`) + // console.log(`req.locals after test: ${util.inspect(req.locals)}`) // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, true, - `next should be called if rate limit was not triggered.` + 'next should be called if rate limit was not triggered.' ) }) - it("should trigger rate-limit for free tier after 10 RPM", async () => { + it('should trigger rate-limit for free tier after 10 RPM', async () => { // Create a new instance of the rate limit so we start with zeroed tracking. rateLimits = new RateLimits() - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' req.url = req.path - req.method = "GET" + req.method = 'GET' - req.locals.jwtToken = "some-token" + req.locals.jwtToken = 'some-token' const jwtInfo = { rateLimit: 10, - id: "5e3a0415eb29a962da2708c2" + id: '5e3a0415eb29a962da2708c2' } // Mock the call to the jwt library. - sandbox.stub(rateLimits.jwt, "verify").returns(jwtInfo) + sandbox.stub(rateLimits.jwt, 'verify').returns(jwtInfo) for (let i = 0; i < 12; i++) { next.reset() // reset the stubbed next() function. await rateLimits.rateLimitSimple(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, false, - `next should not be called if rate limit was triggered.` + 'next should not be called if rate limit was triggered.' ) }) - it("should NOT trigger rate-limit handler for pro-tier at 25 RPM", async () => { + it('should NOT trigger rate-limit handler for pro-tier at 25 RPM', async () => { // Create a new instance of the rate limit so we start with zeroed tracking. rateLimits = new RateLimits() - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' req.url = req.path - req.method = "GET" + req.method = 'GET' - req.locals.jwtToken = "some-token" + req.locals.jwtToken = 'some-token' const jwtInfo = { rateLimit: 100, - id: "5e3a0415eb29a962da2708c3" + id: '5e3a0415eb29a962da2708c3' } // Mock the call to the jwt library. - sandbox.stub(rateLimits.jwt, "verify").returns(jwtInfo) + sandbox.stub(rateLimits.jwt, 'verify').returns(jwtInfo) for (let i = 0; i < 25; i++) { next.reset() // reset the stubbed next() function. await rateLimits.rateLimitSimple(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } - //console.log(`req.locals after test: ${util.inspect(req.locals)}`) + // console.log(`req.locals after test: ${util.inspect(req.locals)}`) // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, true, - `next should be called if rate limit was not triggered.` + 'next should be called if rate limit was not triggered.' ) }) - it("should still rate-limit at a higher RPM for pro-tier", async () => { + it('should still rate-limit at a higher RPM for pro-tier', async () => { // Create a new instance of the rate limit so we start with zeroed tracking. rateLimits = new RateLimits() - req.baseUrl = "/v3" - req.path = "/control/getNetworkInfo" + req.baseUrl = '/v3' + req.path = '/control/getNetworkInfo' req.url = req.path - req.method = "GET" + req.method = 'GET' - req.locals.jwtToken = "some-token" + req.locals.jwtToken = 'some-token' const jwtInfo = { rateLimit: 100, - id: "5e3a0415eb29a962da2708c4" + id: '5e3a0415eb29a962da2708c4' } // Mock the call to the jwt library. - sandbox.stub(rateLimits.jwt, "verify").returns(jwtInfo) + sandbox.stub(rateLimits.jwt, 'verify').returns(jwtInfo) for (let i = 0; i < 150; i++) { next.reset() // reset the stubbed next() function. await rateLimits.rateLimitSimple(req, res, next) - //console.log(`next() called: ${next.called}`) + // console.log(`next() called: ${next.called}`) } - //console.log(`req.locals after test: ${util.inspect(req.locals)}`) + // console.log(`req.locals after test: ${util.inspect(req.locals)}`) // Note: next() will be called unless the rate-limit kicks in. assert.equal( next.called, false, - `next should NOT be called if rate limit was triggered.` + 'next should NOT be called if rate limit was triggered.' ) }) }) }) // Generates a Basic authorization header. -function generateAuthHeader(pass) { - // https://en.wikipedia.org/wiki/Basic_access_authentication - const username = "BITBOX" - const combined = `${username}:${pass}` - - var base64Credential = Buffer.from(combined).toString("base64") - var readyCredential = `Basic ${base64Credential}` - - return readyCredential -} +// function generateAuthHeader (pass) { +// // https://en.wikipedia.org/wiki/Basic_access_authentication +// const username = 'BITBOX' +// const combined = `${username}:${pass}` +// +// var base64Credential = Buffer.from(combined).toString('base64') +// var readyCredential = `Basic ${base64Credential}` +// +// return readyCredential +// } diff --git a/test/v3/raw-transactions.js b/test/v3/raw-transactions.js index 014f9b5..ff7e3af 100644 --- a/test/v3/raw-transactions.js +++ b/test/v3/raw-transactions.js @@ -10,26 +10,28 @@ */ -"use strict" +'use strict' -const chai = require("chai") +const chai = require('chai') const assert = chai.assert -const rawtransactions = require("../../src/routes/v3/full-node/rawtransactions") -const nock = require("nock") // HTTP mocking +const rawtransactions = require('../../src/routes/v3/full-node/rawtransactions') +const nock = require('nock') // HTTP mocking let originalEnvVars // Used during transition from integration to unit tests. // Mocking data. -//delete require.cache[require.resolve("./mocks/express-mocks")] // Fixes bug -const { mockReq, mockRes, mockNext } = require("./mocks/express-mocks") -const mockData = require("./mocks/raw-transactions-mocks") +// delete require.cache[require.resolve("./mocks/express-mocks")] // Fixes bug +// const { mockReq, mockRes, mockNext } = require('./mocks/express-mocks') +const { mockReq, mockRes } = require('./mocks/express-mocks') +const mockData = require('./mocks/raw-transactions-mocks') // Used for debugging. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 5 } -describe("#Raw-Transactions", () => { - let req, res, next +describe('#Raw-Transactions', () => { + // let req, res, next + let req, res before(() => { // Save existing environment variables. @@ -41,12 +43,12 @@ describe("#Raw-Transactions", () => { } // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") { - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api" - process.env.RPC_USERNAME = "fakeusername" - process.env.RPC_PASSWORD = "fakepassword" + if (!process.env.TEST) process.env.TEST = 'unit' + if (process.env.TEST === 'unit') { + process.env.BITCOINCOM_BASEURL = 'http://fakeurl/api/' + process.env.RPC_BASEURL = 'http://fakeurl/api' + process.env.RPC_USERNAME = 'fakeusername' + process.env.RPC_PASSWORD = 'fakepassword' } }) @@ -55,7 +57,7 @@ describe("#Raw-Transactions", () => { // Mock the req and res objects used by Express routes. req = mockReq res = mockRes - next = mockNext + // next = mockNext // Explicitly reset the parmas and body. req.params = {} @@ -81,43 +83,43 @@ describe("#Raw-Transactions", () => { process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD }) - describe("#root", async () => { + describe('#root', async () => { // root route handler. const root = rawtransactions.testableComponents.root - it("should respond to GET for base route", async () => { + it('should respond to GET for base route', async () => { const result = root(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.equal(result.status, "rawtransactions", "Returns static string") + assert.equal(result.status, 'rawtransactions', 'Returns static string') }) }) - describe("decodeRawTransactionSingle()", () => { + describe('decodeRawTransactionSingle()', () => { // block route handler. const decodeRawTransaction = rawtransactions.testableComponents.decodeRawTransactionSingle - it("should throw error if hex is missing", async () => { + it('should throw error if hex is missing', async () => { const result = await decodeRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "hex can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'hex can not be empty') }) - it("should throw 503 when network issues", async () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' req.params.hex = - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" + '0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000' - const result = await decodeRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) + await decodeRawTransaction(req, res) + // console.log(`result: ${util.inspect(result)}`) // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 @@ -125,174 +127,174 @@ describe("#Raw-Transactions", () => { assert.isAbove( res.statusCode, 499, - "HTTP status code 500 or greater expected." + 'HTTP status code 500 or greater expected.' ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") + // assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") }) - it("should GET /decodeRawTransaction", async () => { + it('should GET /decodeRawTransaction', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: mockData.mockDecodeRawTransaction }) } req.params.hex = - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" + '0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000' const result = await decodeRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.hasAnyKeys(result, [ - "txid", - "hash", - "size", - "version", - "locktime", - "vin", - "vout" + 'txid', + 'hash', + 'size', + 'version', + 'locktime', + 'vin', + 'vout' ]) assert.isArray(result.vin) assert.isArray(result.vout) }) }) - describe("decodeRawTransactionBulk()", () => { + describe('decodeRawTransactionBulk()', () => { const decodeRawTransactionBulk = rawtransactions.testableComponents.decodeRawTransactionBulk - it("should throw 400 error if hexes array is missing", async () => { + it('should throw 400 error if hexes array is missing', async () => { const result = await decodeRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "hexes must be an array") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'hexes must be an array') }) - it("should throw 400 error if hexes array is too large", async () => { + it('should throw 400 error if hexes array is too large', async () => { const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") + for (var i = 0; i < 25; i++) testArray.push('') req.body.hexes = testArray const result = await decodeRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Array too large') }) - it("should throw 400 error if hexes is empty", async () => { - req.body.hexes = [""] + it('should throw 400 error if hexes is empty', async () => { + req.body.hexes = [''] const result = await decodeRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Encountered empty hex") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Encountered empty hex') }) - it("should error on non-array single hex", async () => { + it('should error on non-array single hex', async () => { req.body.hexes = - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" + '0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000' const result = await decodeRawTransactionBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "hexes must be an array", - "Proper error message" + 'hexes must be an array', + 'Proper error message' ) }) - it("should decode an array with a single hex", async () => { + it('should decode an array with a single hex', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: mockData.mockDecodeRawTransaction }) } req.body.hexes = [ - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" + '0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000' ] const result = await decodeRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) assert.hasAnyKeys(result[0], [ - "txid", - "hash", - "size", - "version", - "locktime", - "vin", - "vout" + 'txid', + 'hash', + 'size', + 'version', + 'locktime', + 'vin', + 'vout' ]) assert.isArray(result[0].vin) assert.isArray(result[0].vout) }) - it("should decode an array with multiple hexes", async () => { + it('should decode an array with multiple hexes', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .times(2) .reply(200, { result: mockData.mockDecodeRawTransaction }) } req.body.hexes = [ - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000", - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" + '0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000', + '0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000' ] const result = await decodeRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) assert.hasAnyKeys(result[0], [ - "txid", - "hash", - "size", - "version", - "locktime", - "vin", - "vout" + 'txid', + 'hash', + 'size', + 'version', + 'locktime', + 'vin', + 'vout' ]) assert.isArray(result[0].vin) assert.isArray(result[0].vout) }) }) - describe("decodeScriptSingle()", () => { + describe('decodeScriptSingle()', () => { // block route handler. const decodeScriptSingle = rawtransactions.testableComponents.decodeScriptSingle - it("should throw error if hex is missing", async () => { + it('should throw error if hex is missing', async () => { const result = await decodeScriptSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "hex can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'hex can not be empty') }) - it("should throw 503 when network issues", async () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' req.params.hex = - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" + '0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000' - const result = await decodeScriptSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + await decodeScriptSingle(req, res) + // console.log(`result: ${util.inspect(result)}`) // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 @@ -300,447 +302,447 @@ describe("#Raw-Transactions", () => { assert.isAbove( res.statusCode, 499, - "HTTP status code 500 or greater expected." + 'HTTP status code 500 or greater expected.' ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") + // assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") }) - it("should GET /decodeScriptSingle", async () => { + it('should GET /decodeScriptSingle', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: mockData.mockDecodeScript }) } req.params.hex = - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" + '0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000' const result = await decodeScriptSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["asm", "type", "p2sh"]) + assert.hasAllKeys(result, ['asm', 'type', 'p2sh']) }) }) - describe("decodeScriptBulk()", () => { + describe('decodeScriptBulk()', () => { const decodeScriptBulk = rawtransactions.testableComponents.decodeScriptBulk - it("should throw 400 error if hexes array is missing", async () => { + it('should throw 400 error if hexes array is missing', async () => { const result = await decodeScriptBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "hexes must be an array") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'hexes must be an array') }) - it("should throw 400 error if hexes array is too large", async () => { + it('should throw 400 error if hexes array is too large', async () => { const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") + for (var i = 0; i < 25; i++) testArray.push('') req.body.hexes = testArray const result = await decodeScriptBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Array too large') }) - it("should throw 400 error if hexes is empty", async () => { - req.body.hexes = [""] + it('should throw 400 error if hexes is empty', async () => { + req.body.hexes = [''] const result = await decodeScriptBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Encountered empty hex") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Encountered empty hex') }) - it("should error on non-array single hex", async () => { + it('should error on non-array single hex', async () => { req.body.hexes = - "0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000" + '0200000001b9b598d7d6d72fc486b2b3a3c03c79b5bade6ec9a77ced850515ab5e64edcc21010000006b483045022100a7b1b08956abb8d6f322aa709d8583c8ea492ba0585f1a6f4f9983520af74a5a0220411aee4a9a54effab617b0508c504c31681b15f9b187179b4874257badd4139041210360cfc66fdacb650bc4c83b4e351805181ee696b7d5ab4667c57b2786f51c413dffffffff0210270000000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac786e9800000000001976a914eb4b180def88e3f5625b2d8ae2c098ff7d85f66488ac00000000' const result = await decodeScriptBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "hexes must be an array", - "Proper error message" + 'hexes must be an array', + 'Proper error message' ) }) - it("should decode an array with a single hex", async () => { + it('should decode an array with a single hex', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: mockData.mockDecodeScript }) } req.body.hexes = [ - "4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16" + '4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16' ] const result = await decodeScriptBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) - assert.hasAllKeys(result[0], ["asm", "type", "p2sh"]) + assert.hasAllKeys(result[0], ['asm', 'type', 'p2sh']) }) - it("should decode an array with a multiple hexes", async () => { + it('should decode an array with a multiple hexes', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .times(2) .reply(200, { result: mockData.mockDecodeScript }) } req.body.hexes = [ - "4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16", - "4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16" + '4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16', + '4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16' ] const result = await decodeScriptBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) assert.equal(result.length, 2) - assert.hasAllKeys(result[0], ["asm", "type", "p2sh"]) + assert.hasAllKeys(result[0], ['asm', 'type', 'p2sh']) }) }) - describe("getRawTransactionBulk()", () => { + describe('getRawTransactionBulk()', () => { // block route handler. const getRawTransactionBulk = rawtransactions.testableComponents.getRawTransactionBulk - it("should throw 400 error if txids array is missing", async () => { + it('should throw 400 error if txids array is missing', async () => { const result = await getRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txids must be an array") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'txids must be an array') }) - it("should throw 400 error if txids array is too large", async () => { + it('should throw 400 error if txids array is too large', async () => { const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") + for (var i = 0; i < 25; i++) testArray.push('') req.body.txids = testArray const result = await getRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Array too large') }) - it("should throw 400 error if txid is empty", async () => { - req.body.txids = [""] + it('should throw 400 error if txid is empty', async () => { + req.body.txids = [''] const result = await getRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Encountered empty TXID") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Encountered empty TXID') }) - it("should throw 400 error if txid is invalid", async () => { + it('should throw 400 error if txid is invalid', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(500, { - error: { message: "parameter 1 must be of length 64 (not 6)" } + error: { message: 'parameter 1 must be of length 64 (not 6)' } }) } - req.body.txids = ["abc123"] + req.body.txids = ['abc123'] const result = await getRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "parameter 1 must be of length 64 (not 6)") + assert.hasAllKeys(result, ['error']) + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') + assert.include(result.error, 'parameter 1 must be of length 64 (not 6)') }) - it("should get concise transaction data", async () => { + it('should get concise transaction data', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: mockData.mockRawTransactionConcise }) } req.body.txids = [ - "2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266" + '2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266' ] const result = await getRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) assert.isString(result[0]) }) - it("should get verbose transaction data", async () => { + it('should get verbose transaction data', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: mockData.mockRawTransactionVerbose }) } req.body.txids = [ - "2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266" + '2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266' ] req.body.verbose = true const result = await getRawTransactionBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) assert.hasAnyKeys(result[0], [ - "hex", - "txid", - "hash", - "size", - "version", - "locktime", - "vin", - "vout", - "blockhash", - "confirmations", - "time", - "blocktime" + 'hex', + 'txid', + 'hash', + 'size', + 'version', + 'locktime', + 'vin', + 'vout', + 'blockhash', + 'confirmations', + 'time', + 'blocktime' ]) assert.isArray(result[0].vin) assert.isArray(result[0].vout) }) }) - describe("getRawTransactionSingle()", () => { + describe('getRawTransactionSingle()', () => { // block route handler. const getRawTransactionSingle = rawtransactions.testableComponents.getRawTransactionSingle - it("should throw 400 error if txid is missing", async () => { + it('should throw 400 error if txid is missing', async () => { const result = await getRawTransactionSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'txid can not be empty') }) - it("should throw 400 error if txid is invalid", async () => { + it('should throw 400 error if txid is invalid', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(500, { - error: { message: "parameter 1 must be of length 64 (not 6)" } + error: { message: 'parameter 1 must be of length 64 (not 6)' } }) } - req.params.txid = "abc123" + req.params.txid = 'abc123' const result = await getRawTransactionSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "parameter 1 must be of length 64 (not 6)") + assert.hasAllKeys(result, ['error']) + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') + assert.include(result.error, 'parameter 1 must be of length 64 (not 6)') }) - it("should get concise transaction data", async () => { + it('should get concise transaction data', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: mockData.mockRawTransactionConcise }) } req.params.txid = - "2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266" + '2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266' const result = await getRawTransactionSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isString(result) }) - it("should get verbose transaction data", async () => { + it('should get verbose transaction data', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: mockData.mockRawTransactionVerbose }) } req.params.txid = - "2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266" - req.query.verbose = "true" + '2c7ae9f865f7ce0c33c189b2f83414176903ce4b06ed9f8b7bcf55efbd4a7266' + req.query.verbose = 'true' const result = await getRawTransactionSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.hasAnyKeys(result, [ - "hex", - "txid", - "hash", - "size", - "version", - "locktime", - "vin", - "vout", - "blockhash", - "confirmations", - "time", - "blocktime" + 'hex', + 'txid', + 'hash', + 'size', + 'version', + 'locktime', + 'vin', + 'vout', + 'blockhash', + 'confirmations', + 'time', + 'blocktime' ]) assert.isArray(result.vin) assert.isArray(result.vout) }) }) - describe("sendRawTransactionBulk()", () => { + describe('sendRawTransactionBulk()', () => { const sendRawTransaction = rawtransactions.testableComponents.sendRawTransactionBulk - it("should throw 400 error if hexs array is missing", async () => { + it('should throw 400 error if hexs array is missing', async () => { const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "hex must be an array") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'hex must be an array') }) - it("should throw 400 error if hexs array is too large", async () => { + it('should throw 400 error if hexs array is too large', async () => { const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") + for (var i = 0; i < 25; i++) testArray.push('') req.body.hexes = testArray const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Array too large') }) - it("should throw 400 error if hex array element is empty", async () => { - req.body.hexes = [""] + it('should throw 400 error if hex array element is empty', async () => { + req.body.hexes = [''] const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Encountered empty hex") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Encountered empty hex') }) - it("should throw 500 error if hex is invalid", async () => { + it('should throw 500 error if hex is invalid', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(500, { - error: { message: "TX decode failed" } + error: { message: 'TX decode failed' } }) } - req.body.hexes = ["abc123"] + req.body.hexes = ['abc123'] const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "TX decode failed") + assert.hasAllKeys(result, ['error']) + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') + assert.include(result.error, 'TX decode failed') }) - it("should submit hex encoded transaction", async () => { + it('should submit hex encoded transaction', async () => { // This is a difficult test to run as transaction hex is invalid after a // block confirmation. So the unit tests simulates what the output 'should' // be, but the integration asserts an expected failure. // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: - "aef8848396e67532b42008b9d75b5a5a3459a6717740f31f0553b74102b4b118" + 'aef8848396e67532b42008b9d75b5a5a3459a6717740f31f0553b74102b4b118' }) } req.body.hexes = [ - "020000000136697692fed77bc4f5b6885295d0c56d1d0280fb578f445ce42be4eb6db381f2010000006a4730440220473adba0e7da14f0abf4817bbd591741ecb8da6544b998f10341f6704f5f05280220405221c626cb7edcf333367ebd469aff3f5a2169e37ee58eebb811ffc2fbc9e0412102202ff86325c5d903171fa5a2895c4efb3765105115460dc96f113048ddb69b47feffffff027a621b00000000001976a914e0a8ffc3b91e35f46618d6db90f66397989abf0588ac38041300000000001976a914a741f282af390bc7ea8c4375a3a56401d668564288ac2c330900" + '020000000136697692fed77bc4f5b6885295d0c56d1d0280fb578f445ce42be4eb6db381f2010000006a4730440220473adba0e7da14f0abf4817bbd591741ecb8da6544b998f10341f6704f5f05280220405221c626cb7edcf333367ebd469aff3f5a2169e37ee58eebb811ffc2fbc9e0412102202ff86325c5d903171fa5a2895c4efb3765105115460dc96f113048ddb69b47feffffff027a621b00000000001976a914e0a8ffc3b91e35f46618d6db90f66397989abf0588ac38041300000000001976a914a741f282af390bc7ea8c4375a3a56401d668564288ac2c330900' ] const result = await sendRawTransaction(req, res) // console.log(`result: ${util.inspect(result)}`) - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { assert.isArray(result) assert.isString(result[0]) // Integration test } else { - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Missing inputs") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Missing inputs') } }) }) - describe("sendRawTransactionSingle()", () => { + describe('sendRawTransactionSingle()', () => { // block route handler. const sendRawTransaction = rawtransactions.testableComponents.sendRawTransactionSingle - it("should throw an error for an empty hex", async () => { - req.params.hex = "" + it('should throw an error for an empty hex', async () => { + req.params.hex = '' const result = await sendRawTransaction(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "Encountered empty hex", - "Proper error message" + 'Encountered empty hex', + 'Proper error message' ) }) - it("should throw an error for a non-string", async () => { + it('should throw an error for a non-string', async () => { req.params.hex = 456 const result = await sendRawTransaction(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "hex must be a string", - "Proper error message" + 'hex must be a string', + 'Proper error message' ) }) - it("should throw 500 when network issues", async () => { + it('should throw 500 when network issues', async () => { // Save the existing RPC URL. const savedUrl = process.env.BITCOINCOM_BASEURL const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.BITCOINCOM_BASEURL = 'http://fakeurl/api/' + process.env.RPC_BASEURL = 'http://fakeurl/api/' req.params.hex = - "020000000136697692fed77bc4f5b6885295d0c56d1d0280fb578f445ce42be4eb6db381f2010000006a4730440220473adba0e7da14f0abf4817bbd591741ecb8da6544b998f10341f6704f5f05280220405221c626cb7edcf333367ebd469aff3f5a2169e37ee58eebb811ffc2fbc9e0412102202ff86325c5d903171fa5a2895c4efb3765105115460dc96f113048ddb69b47feffffff027a621b00000000001976a914e0a8ffc3b91e35f46618d6db90f66397989abf0588ac38041300000000001976a914a741f282af390bc7ea8c4375a3a56401d668564288ac2c330900" - const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) + '020000000136697692fed77bc4f5b6885295d0c56d1d0280fb578f445ce42be4eb6db381f2010000006a4730440220473adba0e7da14f0abf4817bbd591741ecb8da6544b998f10341f6704f5f05280220405221c626cb7edcf333367ebd469aff3f5a2169e37ee58eebb811ffc2fbc9e0412102202ff86325c5d903171fa5a2895c4efb3765105115460dc96f113048ddb69b47feffffff027a621b00000000001976a914e0a8ffc3b91e35f46618d6db90f66397989abf0588ac38041300000000001976a914a741f282af390bc7ea8c4375a3a56401d668564288ac2c330900' + await sendRawTransaction(req, res) + // console.log(`result: ${util.inspect(result)}`) // Restore the saved URL. process.env.BITCOINCOM_BASEURL = savedUrl @@ -749,58 +751,58 @@ describe("#Raw-Transactions", () => { assert.isAbove( res.statusCode, 499, - "HTTP status code 500 or great expected." + 'HTTP status code 500 or great expected.' ) }) - it("should throw an error for invalid hex", async () => { - req.params.hex = "abc123" + it('should throw an error for invalid hex', async () => { + req.params.hex = 'abc123' // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(500, { - error: { message: "TX decode failed" } + error: { message: 'TX decode failed' } }) } const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") - assert.include(result.error, "TX decode failed") + assert.hasAllKeys(result, ['error']) + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') + assert.include(result.error, 'TX decode failed') }) - it("should GET /sendRawTransaction/:hex", async () => { + it('should GET /sendRawTransaction/:hex', async () => { // This is a difficult test to run as transaction hex is invalid after a // block confirmation. So the unit tests simulates what the output 'should' // be, but the integration asserts an expected failure. // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: - "aef8848396e67532b42008b9d75b5a5a3459a6717740f31f0553b74102b4b118" + 'aef8848396e67532b42008b9d75b5a5a3459a6717740f31f0553b74102b4b118' }) } req.params.hex = - "020000000136697692fed77bc4f5b6885295d0c56d1d0280fb578f445ce42be4eb6db381f2010000006a4730440220473adba0e7da14f0abf4817bbd591741ecb8da6544b998f10341f6704f5f05280220405221c626cb7edcf333367ebd469aff3f5a2169e37ee58eebb811ffc2fbc9e0412102202ff86325c5d903171fa5a2895c4efb3765105115460dc96f113048ddb69b47feffffff027a621b00000000001976a914e0a8ffc3b91e35f46618d6db90f66397989abf0588ac38041300000000001976a914a741f282af390bc7ea8c4375a3a56401d668564288ac2c330900" + '020000000136697692fed77bc4f5b6885295d0c56d1d0280fb578f445ce42be4eb6db381f2010000006a4730440220473adba0e7da14f0abf4817bbd591741ecb8da6544b998f10341f6704f5f05280220405221c626cb7edcf333367ebd469aff3f5a2169e37ee58eebb811ffc2fbc9e0412102202ff86325c5d903171fa5a2895c4efb3765105115460dc96f113048ddb69b47feffffff027a621b00000000001976a914e0a8ffc3b91e35f46618d6db90f66397989abf0588ac38041300000000001976a914a741f282af390bc7ea8c4375a3a56401d668564288ac2c330900' const result = await sendRawTransaction(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { assert.isString(result) // Integration test } else { - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Missing inputs") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Missing inputs') } }) }) diff --git a/test/v3/slp.js b/test/v3/slp.js index 88f70ae..93729b3 100644 --- a/test/v3/slp.js +++ b/test/v3/slp.js @@ -9,50 +9,50 @@ -See listSingleToken() tests. */ -"use strict" +'use strict' -const chai = require("chai") +const chai = require('chai') const assert = chai.assert -const nock = require("nock") // HTTP mocking -const sinon = require("sinon") -const proxyquire = require("proxyquire").noPreserveCache() -const axios = require("axios") +const nock = require('nock') // HTTP mocking +const sinon = require('sinon') +// const proxyquire = require('proxyquire').noPreserveCache() +// const axios = require('axios') // Save existing environment variables. // Used during transition from integration to unit tests. -let originalEnvVars, mockServerUrl -originalEnvVars = { +let mockServerUrl +const originalEnvVars = { BITDB_URL: process.env.BITDB_URL, BITCOINCOM_BASEURL: process.env.BITCOINCOM_BASEURL, SLPDB_URL: process.env.SLPDB_URL } // Set default environment variables for unit tests. -if (!process.env.TEST) process.env.TEST = "unit" +if (!process.env.TEST) process.env.TEST = 'unit' // Block network connections for unit tests. -if (process.env.TEST === "unit") { - process.env.BITDB_URL = "http://fakeurl/" - process.env.BITCOINCOM_BASEURL = "http://fakeurl/" - process.env.SLPDB_URL = "http://fakeurl/" - mockServerUrl = `http://fakeurl` +if (process.env.TEST === 'unit') { + process.env.BITDB_URL = 'http://fakeurl/' + process.env.BITCOINCOM_BASEURL = 'http://fakeurl/' + process.env.SLPDB_URL = 'http://fakeurl/' + mockServerUrl = 'http://fakeurl' } // Prepare the slpRoute for stubbing dependcies on slpjs. -const slpRoute = require("../../src/routes/v3/slp") -const pathStub = {} // Used to stub methods within slpjs. -const slpRouteStub = proxyquire("../../src/routes/v3/slp", { slpjs: pathStub }) +const slpRoute = require('../../src/routes/v3/slp') +// const pathStub = {} // Used to stub methods within slpjs. +// const slpRouteStub = proxyquire('../../src/routes/v3/slp', { slpjs: pathStub }) // Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/slp-mocks") -const slpjsMock = require("./mocks/slpjs-mocks") +const { mockReq, mockRes } = require('./mocks/express-mocks') +const mockData = require('./mocks/slp-mocks') +// const slpjsMock = require('./mocks/slpjs-mocks') // Used for debugging. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -describe("#SLP", () => { +describe('#SLP', () => { let req, res let sandbox @@ -65,7 +65,7 @@ describe("#SLP", () => { res = mockRes // Explicitly reset the parmas and body. - //req.params = {} + // req.params = {} req.body = {} req.query = {} req.locals = {} @@ -91,15 +91,15 @@ describe("#SLP", () => { process.env.SLPDB_URL = originalEnvVars.SLPDB_URL }) - describe("#root", async () => { + describe('#root', async () => { // root route handler. const root = slpRoute.testableComponents.root - it("should respond to GET for base route", async () => { + it('should respond to GET for base route', async () => { const result = root(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.equal(result.status, "slp", "Returns static string") + assert.equal(result.status, 'slp', 'Returns static string') }) }) /* @@ -430,46 +430,46 @@ describe("#SLP", () => { }) }) */ - describe("balancesForAddress()", () => { + describe('balancesForAddress()', () => { const balancesForAddress = slpRoute.testableComponents.balancesForAddress - it("should throw 400 if address is empty", async () => { + it('should throw 400 if address is empty', async () => { const result = await balancesForAddress(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'address can not be empty') }) - it("should throw 400 if address is invalid", async () => { - req.params.address = "badAddress" - - const result = await balancesForAddress(req, res) - //console.log(`result: ${util.inspect(result)}`) - - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Invalid BCH address.") - }) - - it("should throw 400 if address network mismatch", async () => { - req.params.address = "slptest:qzcvpw3ah7r880d49wsqzrsl90pg0rqjjurmj3g4nk" + it('should throw 400 if address is invalid', async () => { + req.params.address = 'badAddress' const result = await balancesForAddress(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Invalid") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Invalid BCH address.') }) - it("should throw 5XX error when network issues", async () => { + it('should throw 400 if address network mismatch', async () => { + req.params.address = 'slptest:qzcvpw3ah7r880d49wsqzrsl90pg0rqjjurmj3g4nk' + + const result = await balancesForAddress(req, res) + // console.log(`result: ${util.inspect(result)}`) + + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Invalid') + }) + + it('should throw 5XX error when network issues', async () => { // Save the existing SLPDB_URL. const savedUrl2 = process.env.SLPDB_URL // Manipulate the URL to cause a 500 network error. - process.env.SLPDB_URL = "http://fakeurl/api/" + process.env.SLPDB_URL = 'http://fakeurl/api/' req.params.address = - "simpleledger:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5me5fdrdn" + 'simpleledger:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5me5fdrdn' const result = await balancesForAddress(req, res) // console.log(`result: ${util.inspect(result)}`) @@ -480,83 +480,83 @@ describe("#SLP", () => { assert.isAbove( res.statusCode, 499, - "HTTP status code 500 or greater expected." + 'HTTP status code 500 or greater expected.' ) assert.include( result.error, - "Network error: Could not communicate", - "Error message expected" + 'Network error: Could not communicate', + 'Error message expected' ) }) - it("should get token balance for an address", async () => { + it('should get token balance for an address', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(mockServerUrl) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .times(2) .reply(200, mockData.mockSingleAddress) } req.params.address = - "simpleledger:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5me5fdrdn" + 'simpleledger:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5me5fdrdn' const result = await balancesForAddress(req, res) // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) assert.hasAllKeys(result[0], [ - "tokenId", - "balance", - "slpAddress", - "decimalCount" + 'tokenId', + 'balance', + 'slpAddress', + 'decimalCount' ]) }) }) - describe("balancesForAddressBulk()", () => { + describe('balancesForAddressBulk()', () => { const balancesForAddressBulk = slpRoute.testableComponents.balancesForAddressBulk - it("should throw 400 if addresses is empty", async () => { + it('should throw 400 if addresses is empty', async () => { const result = await balancesForAddressBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "addresses needs to be an array") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'addresses needs to be an array') }) - it("should throw 400 if address is invalid", async () => { - req.body.addresses = ["badAddress"] + it('should throw 400 if address is invalid', async () => { + req.body.addresses = ['badAddress'] const result = await balancesForAddressBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Invalid BCH address.") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Invalid BCH address.') }) - it("should throw 400 if address network mismatch", async () => { + it('should throw 400 if address network mismatch', async () => { req.body.addresses = [ - "slptest:qzcvpw3ah7r880d49wsqzrsl90pg0rqjjurmj3g4nk" + 'slptest:qzcvpw3ah7r880d49wsqzrsl90pg0rqjjurmj3g4nk' ] const result = await balancesForAddressBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Invalid") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Invalid') }) - it("should throw 5XX error when network issues", async () => { + it('should throw 5XX error when network issues', async () => { // Save the existing SLPDB_URL. const savedUrl2 = process.env.SLPDB_URL // Manipulate the URL to cause a 500 network error. - process.env.SLPDB_URL = "http://fakeurl/api/" + process.env.SLPDB_URL = 'http://fakeurl/api/' req.body.addresses = [ - "simpleledger:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5me5fdrdn" + 'simpleledger:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5me5fdrdn' ] const result = await balancesForAddressBulk(req, res) @@ -568,20 +568,20 @@ describe("#SLP", () => { assert.isAbove( res.statusCode, 499, - "HTTP status code 500 or greater expected." + 'HTTP status code 500 or greater expected.' ) assert.include( result.error, - "Network error: Could not communicate", - "Error message expected" + 'Network error: Could not communicate', + 'Error message expected' ) }) // Only run as an integration test. Too complex to stub accurately. - if (process.env.TEST !== "unit") { - it("should get token balance for an address", async () => { + if (process.env.TEST !== 'unit') { + it('should get token balance for an address', async () => { req.body.addresses = [ - "simpleledger:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5me5fdrdn" + 'simpleledger:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5me5fdrdn' ] const result = await balancesForAddressBulk(req, res) @@ -590,11 +590,11 @@ describe("#SLP", () => { assert.isArray(result) assert.isArray(result[0]) assert.hasAnyKeys(result[0][0], [ - "tokenId", - "balance", - "balanceString", - "slpAddress", - "decimalCount" + 'tokenId', + 'balance', + 'balanceString', + 'slpAddress', + 'decimalCount' ]) }) } @@ -807,112 +807,112 @@ describe("#SLP", () => { }) }) */ - describe("validateBulk()", () => { + describe('validateBulk()', () => { const validateBulk = slpRoute.testableComponents.validateBulk - it("should throw 400 if txid array is empty", async () => { + it('should throw 400 if txid array is empty', async () => { const result = await validateBulk(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txids needs to be an array") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'txids needs to be an array') assert.equal(res.statusCode, 400) }) - it("should throw 400 error if array is too large", async () => { + it('should throw 400 error if array is too large', async () => { const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") + for (var i = 0; i < 25; i++) testArray.push('') req.body.txids = testArray const result = await validateBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Array too large') }) - it("should validate array with single element", async () => { + it('should validate array with single element', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.SLPDB_URL}`) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .reply(200, mockData.mockSingleValidTxid) } req.body.txids = [ - "77872738b6bddee6c0cbdb9509603de20b15d4f6b26602f629417aec2f5d5e8d" + '77872738b6bddee6c0cbdb9509603de20b15d4f6b26602f629417aec2f5d5e8d' ] const result = await validateBulk(req, res) // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) - assert.hasAllKeys(result[0], ["txid", "valid"]) + assert.hasAllKeys(result[0], ['txid', 'valid']) }) - it("should validate array with two elements", async () => { + it('should validate array with two elements', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.SLPDB_URL}`) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .reply(200, mockData.mockTwoValidTxid) } req.body.txids = [ - "77872738b6bddee6c0cbdb9509603de20b15d4f6b26602f629417aec2f5d5e8d", - "552112f9e458dc7d1d8b328b0a6685e8af74a64b60b6846e7c86407f27f47e42" + '77872738b6bddee6c0cbdb9509603de20b15d4f6b26602f629417aec2f5d5e8d', + '552112f9e458dc7d1d8b328b0a6685e8af74a64b60b6846e7c86407f27f47e42' ] const result = await validateBulk(req, res) // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) - assert.hasAllKeys(result[0], ["txid", "valid"]) + assert.hasAllKeys(result[0], ['txid', 'valid']) assert.equal(result.length, 2) }) // Captures a regression bug that went out to production, captured in this // GitHub Issue: https://github.com/Bitcoin-com/rest.bitcoin.com/issues/518 - it("should return two elements if given two elements", async () => { + it('should return two elements if given two elements', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.SLPDB_URL}`) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .reply(200, mockData.mockTwoRedundentTxid) } req.body.txids = [ - "d56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56", - "d56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56" + 'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56', + 'd56a2b446d8149c39ca7e06163fe8097168c3604915f631bc58777d669135a56' ] const result = await validateBulk(req, res) // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) - assert.hasAllKeys(result[0], ["txid", "valid"]) + assert.hasAllKeys(result[0], ['txid', 'valid']) assert.equal(result.length, 2) }) }) - describe("tokenStatsSingle()", () => { + describe('tokenStatsSingle()', () => { const tokenStatsSingle = slpRoute.testableComponents.tokenStats - it("should throw 400 if tokenID is empty", async () => { - req.params.tokenId = "" + it('should throw 400 if tokenID is empty', async () => { + req.params.tokenId = '' const result = await tokenStatsSingle(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "tokenId can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'tokenId can not be empty') }) // - it("should get token stats for tokenId", async () => { + it('should get token stats for tokenId', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.SLPDB_URL}`) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .reply(200, { t: [ { @@ -924,106 +924,106 @@ describe("#SLP", () => { } req.params.tokenId = - "497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7" + '497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7' const result = await tokenStatsSingle(req, res) // console.log(`result: ${util.inspect(result)}`) assert.hasAnyKeys(result, [ - "blockCreated", - "blockLastActiveMint", - "blockLastActiveSend", - "containsBaton", - "initialTokenQty", - "mintingBatonStatus", - "circulatingSupply", - "decimals", - "documentHash", - "versionType", - "timestamp", - "documentUri", - "name", - "symbol", - "id", - "totalBurned", - "totalMinted", - "txnsSinceGenesis", - "validAddresses" + 'blockCreated', + 'blockLastActiveMint', + 'blockLastActiveSend', + 'containsBaton', + 'initialTokenQty', + 'mintingBatonStatus', + 'circulatingSupply', + 'decimals', + 'documentHash', + 'versionType', + 'timestamp', + 'documentUri', + 'name', + 'symbol', + 'id', + 'totalBurned', + 'totalMinted', + 'txnsSinceGenesis', + 'validAddresses' ]) }) }) - describe("balancesForTokenSingle()", () => { + describe('balancesForTokenSingle()', () => { const balancesForTokenSingle = slpRoute.testableComponents.balancesForTokenSingle - it("should throw 400 if tokenID is empty", async () => { - req.params.tokenId = "" + it('should throw 400 if tokenID is empty', async () => { + req.params.tokenId = '' const result = await balancesForTokenSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "tokenId can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'tokenId can not be empty') }) - it("should get balances for tokenId", async () => { + it('should get balances for tokenId', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.SLPDB_URL}`) - .get(uri => uri.includes("/")) + .get(uri => uri.includes('/')) .reply(200, { a: [mockData.mockBalance] }) } req.params.tokenId = - "497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7" + '497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7' const result = await balancesForTokenSingle(req, res) // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result[0], ["tokenId", "slpAddress", "tokenBalance"]) + assert.hasAllKeys(result[0], ['tokenId', 'slpAddress', 'tokenBalance']) }) }) - describe("txDetails()", () => { + describe('txDetails()', () => { const txDetails = slpRoute.testableComponents.txDetails - it("should throw 400 if txid is empty", async () => { + it('should throw 400 if txid is empty', async () => { const result = await txDetails(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "txid can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'txid can not be empty') }) - it("should throw 400 for malformed txid", async () => { + it('should throw 400 for malformed txid', async () => { req.params.txid = - "57b3082a2bf269b3d6f40fee7fb9c664e8256a88ca5ee2697c05b9457" + '57b3082a2bf269b3d6f40fee7fb9c664e8256a88ca5ee2697c05b9457' const result = await txDetails(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "This is not a txid") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'This is not a txid') }) - it("should throw 400 for non-existant txid", async () => { + it('should throw 400 for non-existant txid', async () => { // Integration test - if (process.env.TEST !== "unit") { + if (process.env.TEST !== 'unit') { req.params.txid = - "57b3082a2bf269b3d6f40fee7fb9c664e8256a88ca5ee2697c05b94578223333" + '57b3082a2bf269b3d6f40fee7fb9c664e8256a88ca5ee2697c05b94578223333' const result = await txDetails(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "TXID not found") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'TXID not found') } }) - if (process.env.TEST === "integration") { - it("should get tx details with token info", async () => { + if (process.env.TEST === 'integration') { + it('should get tx details with token info', async () => { // TODO: add mocking for unit testing. How do I mock reponse form SLPDB // since it's not an object? @@ -1034,38 +1034,38 @@ describe("#SLP", () => { // } req.params.txid = - "497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7" + '497291b8a1dfe69c8daea50677a3d31a5ef0e9484d8bebb610dac64bbc202fb7' const result = await txDetails(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.hasAnyKeys(result, ["tokenIsValid", "tokenInfo"]) + assert.hasAnyKeys(result, ['tokenIsValid', 'tokenInfo']) }) } }) - describe("txsTokenIdAddressSingle()", () => { + describe('txsTokenIdAddressSingle()', () => { const txsTokenIdAddressSingle = slpRoute.testableComponents.txsTokenIdAddressSingle - it("should throw 400 if tokenId is empty", async () => { - req.params.tokenId = "" + it('should throw 400 if tokenId is empty', async () => { + req.params.tokenId = '' const result = await txsTokenIdAddressSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "tokenId can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'tokenId can not be empty') }) - it("should throw 400 if address is empty", async () => { + it('should throw 400 if address is empty', async () => { req.params.tokenId = - "495322b37d6b2eae81f045eda612b95870a0c2b6069c58f70cf8ef4e6a9fd43a" - req.params.address = "" + '495322b37d6b2eae81f045eda612b95870a0c2b6069c58f70cf8ef4e6a9fd43a' + req.params.address = '' const result = await txsTokenIdAddressSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "address can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'address can not be empty') }) /* it("should get tx details with tokenId and address", async () => { @@ -1085,7 +1085,6 @@ describe("#SLP", () => { "7ac7f4bb50b019fe0f5c81e3fc13fc0720e130282ea460768cafb49785eb2796" req.params.address = "slptest:qpwa35xq0q0cnmdu0rwzkct369hddzsqpsqdzw6h9h" - const result = await txsTokenIdAddressSingle(req, res) console.log(`result: ${JSON.stringify(result, null, 2)}`) diff --git a/test/v3/util.js b/test/v3/util.js index 9028d23..dcef3f8 100644 --- a/test/v3/util.js +++ b/test/v3/util.js @@ -6,27 +6,27 @@ to 'integration' to run the tests against BCH mainnet. */ -"use strict" +'use strict' -const chai = require("chai") +const chai = require('chai') const assert = chai.assert -const utilRoute = require("../../src/routes/v3/util") -const nock = require("nock") // HTTP mocking -const sinon = require("sinon") +const utilRoute = require('../../src/routes/v3/util') +const nock = require('nock') // HTTP mocking +const sinon = require('sinon') let originalEnvVars // Used during transition from integration to unit tests. // Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/util-mocks") +const { mockReq, mockRes } = require('./mocks/express-mocks') +const mockData = require('./mocks/util-mocks') -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -const UtilRoute = utilRoute.UtilRoute +// const UtilRoute = utilRoute.UtilRoute const utilRouteInst = new utilRoute.UtilRoute() -describe("#Util", () => { +describe('#Util', () => { let req, res let sandbox @@ -40,12 +40,12 @@ describe("#Util", () => { } // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - if (process.env.TEST === "unit") { - process.env.BITCOINCOM_BASEURL = "http://fakeurl/api/" - process.env.RPC_BASEURL = "http://fakeurl/api" - process.env.RPC_USERNAME = "fakeusername" - process.env.RPC_PASSWORD = "fakepassword" + if (!process.env.TEST) process.env.TEST = 'unit' + if (process.env.TEST === 'unit') { + process.env.BITCOINCOM_BASEURL = 'http://fakeurl/api/' + process.env.RPC_BASEURL = 'http://fakeurl/api' + process.env.RPC_USERNAME = 'fakeusername' + process.env.RPC_PASSWORD = 'fakepassword' } }) @@ -82,43 +82,43 @@ describe("#Util", () => { process.env.RPC_PASSWORD = originalEnvVars.RPC_PASSWORD }) - describe("#root", async () => { + describe('#root', async () => { // root route handler. const root = utilRouteInst.root - it("should respond to GET for base route", async () => { + it('should respond to GET for base route', async () => { const result = root(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.equal(result.status, "util", "Returns static string") + assert.equal(result.status, 'util', 'Returns static string') }) }) - describe("#validateAddressSingle", async () => { + describe('#validateAddressSingle', async () => { const validateAddress = utilRouteInst.validateAddressSingle - it("should throw an error for an empty address", async () => { + it('should throw an error for an empty address', async () => { const result = await validateAddress(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "address can not be empty", - "Proper error message" + 'address can not be empty', + 'Proper error message' ) }) - it("should throw 503 when network issues", async () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' - req.params.address = `bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y` + req.params.address = 'bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y' - const result = await validateAddress(req, res) - //console.log(`result: ${util.inspect(result)}`) + await validateAddress(req, res) + // console.log(`result: ${util.inspect(result)}`) // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 @@ -126,120 +126,120 @@ describe("#Util", () => { assert.isAbove( res.statusCode, 499, - "HTTP status code 500 or greater expected." + 'HTTP status code 500 or greater expected.' ) - //assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") + // assert.include(result.error,"Network error: Could not communicate with full node","Error message expected") }) - it("should validate address", async () => { + it('should validate address', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: mockData.mockAddress }) } - req.params.address = `bitcoincash:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5hzljcrnd` + req.params.address = 'bitcoincash:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5hzljcrnd' const result = await validateAddress(req, res) // console.log(`result: ${util.inspect(result)}`) assert.hasAnyKeys(result, [ - "isvalid", - "address", - "scriptPubKey", - "ismine", - "iswatchonly", - "isscript" + 'isvalid', + 'address', + 'scriptPubKey', + 'ismine', + 'iswatchonly', + 'isscript' ]) }) }) - describe("#validateAddressBulk", async () => { + describe('#validateAddressBulk', async () => { const validateAddressBulk = utilRouteInst.validateAddressBulk - it("should throw an error for an empty body", async () => { + it('should throw an error for an empty body', async () => { const result = await validateAddressBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "addresses needs to be an array. Use GET for single address.", - "Proper error message" + 'addresses needs to be an array. Use GET for single address.', + 'Proper error message' ) }) - it("should error on non-array single address", async () => { + it('should error on non-array single address', async () => { req.body = { - addresses: `bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y` + addresses: 'bchtest:qqqk4y6lsl5da64sg5qc3xezmplyu5kmpyz2ysaa5y' } const result = await validateAddressBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "addresses needs to be an array. Use GET for single address.", - "Proper error message" + 'addresses needs to be an array. Use GET for single address.', + 'Proper error message' ) }) - it("should throw 400 error if addresses array is too large", async () => { + it('should throw 400 error if addresses array is too large', async () => { const testArray = [] - for (var i = 0; i < 25; i++) testArray.push("") + for (var i = 0; i < 25; i++) testArray.push('') req.body.addresses = testArray const result = await validateAddressBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "Array too large") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'Array too large') }) - it("should error on invalid address", async () => { + it('should error on invalid address', async () => { req.body = { - addresses: [`bchtest:qqqk4y6lsl5da64sg5qc3xezmpl`] + addresses: ['bchtest:qqqk4y6lsl5da64sg5qc3xezmpl'] } const result = await validateAddressBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "Invalid BCH address. Double check your address is valid", - "Proper error message" + 'Invalid BCH address. Double check your address is valid', + 'Proper error message' ) }) - it("should error on mainnet address when using testnet", async () => { + it('should error on mainnet address when using testnet', async () => { req.body = { - addresses: [`bchtest:qrls6vzjkkxlds7aqv9075u0fttwc7u9jvczn5fdt9`] + addresses: ['bchtest:qrls6vzjkkxlds7aqv9075u0fttwc7u9jvczn5fdt9'] } const result = await validateAddressBulk(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "Invalid network. Trying to use a testnet address on mainnet, or vice versa.", - "Proper error message" + 'Invalid network. Trying to use a testnet address on mainnet, or vice versa.', + 'Proper error message' ) }) - it("should throw 503 when network issues", async () => { + it('should throw 503 when network issues', async () => { // Save the existing RPC URL. const savedUrl2 = process.env.RPC_BASEURL // Manipulate the URL to cause a 500 network error. - process.env.RPC_BASEURL = "http://fakeurl/api/" + process.env.RPC_BASEURL = 'http://fakeurl/api/' req.body.addresses = [ - `bitcoincash:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5hzljcrnd` + 'bitcoincash:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5hzljcrnd' ] - const result = await validateAddressBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + await validateAddressBulk(req, res) + // console.log(`result: ${util.inspect(result)}`) // Restore the saved URL. process.env.RPC_BASEURL = savedUrl2 @@ -247,157 +247,157 @@ describe("#Util", () => { assert.isAbove( res.statusCode, 499, - "HTTP status code 500 or greater expected." + 'HTTP status code 500 or greater expected.' ) }) - it("should validate a single address", async () => { + it('should validate a single address', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .reply(200, { result: mockData.mockAddress }) } req.body.addresses = [ - `bitcoincash:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5hzljcrnd` + 'bitcoincash:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5hzljcrnd' ] const result = await validateAddressBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) assert.hasAnyKeys(result[0], [ - "isvalid", - "address", - "scriptPubKey", - "ismine", - "iswatchonly", - "isscript" + 'isvalid', + 'address', + 'scriptPubKey', + 'ismine', + 'iswatchonly', + 'isscript' ]) }) - it("should validate a multiple addresses", async () => { + it('should validate a multiple addresses', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { nock(`${process.env.RPC_BASEURL}`) - .post(uri => uri.includes("/")) + .post(uri => uri.includes('/')) .times(2) .reply(200, { result: mockData.mockAddress }) } req.body.addresses = [ - `bitcoincash:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5hzljcrnd`, - `bitcoincash:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5hzljcrnd` + 'bitcoincash:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5hzljcrnd', + 'bitcoincash:qpujxqra3jmdlzzapwmmt7uspr7q0c9ff5hzljcrnd' ] const result = await validateAddressBulk(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) assert.isArray(result) assert.hasAnyKeys(result[0], [ - "isvalid", - "address", - "scriptPubKey", - "ismine", - "iswatchonly", - "isscript" + 'isvalid', + 'address', + 'scriptPubKey', + 'ismine', + 'iswatchonly', + 'isscript' ]) }) }) - describe("#sweepWif", () => { - it("should throw 400 if WIF is not included", async () => { + describe('#sweepWif', () => { + it('should throw 400 if WIF is not included', async () => { req.body = {} const result = await utilRouteInst.sweepWif(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "WIF needs to a proper compressed WIF starting with K or L", - "Proper error message" + 'WIF needs to a proper compressed WIF starting with K or L', + 'Proper error message' ) }) - it("should throw 400 if WIF is malformed", async () => { + it('should throw 400 if WIF is malformed', async () => { req.body = { - wif: `abc123` + wif: 'abc123' } const result = await utilRouteInst.sweepWif(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "WIF needs to a proper compressed WIF starting with K or L", - "Proper error message" + 'WIF needs to a proper compressed WIF starting with K or L', + 'Proper error message' ) }) - it("should throw 400 if destination address is not included", async () => { + it('should throw 400 if destination address is not included', async () => { req.body = { - wif: "L5GEFg1tETLWBugmhSo9Zc4ms968qVmfmTroDxsJ982AiudAQGyt" + wif: 'L5GEFg1tETLWBugmhSo9Zc4ms968qVmfmTroDxsJ982AiudAQGyt' } const result = await utilRouteInst.sweepWif(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "address can not be empty", - "Proper error message" + 'address can not be empty', + 'Proper error message' ) }) // Unit test only. - if (process.env.TEST === "unit") { - it("should generate transaction for valid token sweep", async () => { + if (process.env.TEST === 'unit') { + it('should generate transaction for valid token sweep', async () => { // Mock the RPC call for unit tests. sandbox .stub( utilRouteInst.blockbook.testableComponents, - "balanceFromBlockbook" + 'balanceFromBlockbook' ) .resolves(mockData.mockBalance) sandbox .stub( utilRouteInst.blockbook.testableComponents, - "utxosFromBlockbook" + 'utxosFromBlockbook' ) .resolves(mockData.mockUtxos) sandbox - .stub(utilRouteInst.bchjs.SLP.Utils, "tokenUtxoDetails") + .stub(utilRouteInst.bchjs.SLP.Utils, 'tokenUtxoDetails') .resolves(mockData.mockIsTokenUtxos) // Mock sendRawTransaction() so that the hex does not actually get broadcast // to the network. sandbox - .stub(utilRouteInst.bchjs.RawTransactions, "sendRawTransaction") - .resolves("test-txid") + .stub(utilRouteInst.bchjs.RawTransactions, 'sendRawTransaction') + .resolves('test-txid') req.body = { - wif: "L5GEFg1tETLWBugmhSo9Zc4ms968qVmfmTroDxsJ982AiudAQGyt", - toAddr: "bitcoincash:qz2qn6zt4qmacf4r6c0e2pdcqsgnkxaa3ql2xpee6p" + wif: 'L5GEFg1tETLWBugmhSo9Zc4ms968qVmfmTroDxsJ982AiudAQGyt', + toAddr: 'bitcoincash:qz2qn6zt4qmacf4r6c0e2pdcqsgnkxaa3ql2xpee6p' } const result = await utilRouteInst.sweepWif(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.equal(result, "test-txid") + assert.equal(result, 'test-txid') }) } - it("should return balance if balance-only is true", async () => { + it('should return balance if balance-only is true', async () => { // Mock the RPC call for unit tests. - if (process.env.TEST === "unit") { + if (process.env.TEST === 'unit') { sandbox .stub( utilRouteInst.blockbook.testableComponents, - "balanceFromBlockbook" + 'balanceFromBlockbook' ) .resolves(mockData.mockBalance) } @@ -405,11 +405,11 @@ describe("#Util", () => { // Mock sendRawTransaction() so that the hex does not actually get broadcast // to the network. sandbox - .stub(utilRouteInst.bchjs.RawTransactions, "sendRawTransaction") - .resolves("test-txid") + .stub(utilRouteInst.bchjs.RawTransactions, 'sendRawTransaction') + .resolves('test-txid') req.body = { - wif: "L5GEFg1tETLWBugmhSo9Zc4ms968qVmfmTroDxsJ982AiudAQGyt", + wif: 'L5GEFg1tETLWBugmhSo9Zc4ms968qVmfmTroDxsJ982AiudAQGyt', balanceOnly: true } @@ -420,125 +420,125 @@ describe("#Util", () => { }) // Unit tests only - if (process.env.TEST === "unit") { - it("should generate transaction for valid BCH-only sweep", async () => { + if (process.env.TEST === 'unit') { + it('should generate transaction for valid BCH-only sweep', async () => { sandbox .stub( utilRouteInst.blockbook.testableComponents, - "balanceFromBlockbook" + 'balanceFromBlockbook' ) .resolves(mockData.mockBalance) sandbox .stub( utilRouteInst.blockbook.testableComponents, - "utxosFromBlockbook" + 'utxosFromBlockbook' ) .resolves(mockData.mockUtxos) // Force token utxo to appear as regular BCH utxo. sandbox - .stub(utilRouteInst.bchjs.SLP.Utils, "tokenUtxoDetails") + .stub(utilRouteInst.bchjs.SLP.Utils, 'tokenUtxoDetails') .resolves([false, false]) // Mock sendRawTransaction() so that the hex does not actually get broadcast // to the network. sandbox - .stub(utilRouteInst.bchjs.RawTransactions, "sendRawTransaction") - .resolves("test-txid") + .stub(utilRouteInst.bchjs.RawTransactions, 'sendRawTransaction') + .resolves('test-txid') req.body = { - wif: "L5GEFg1tETLWBugmhSo9Zc4ms968qVmfmTroDxsJ982AiudAQGyt", - toAddr: "bitcoincash:qz2qn6zt4qmacf4r6c0e2pdcqsgnkxaa3ql2xpee6p" + wif: 'L5GEFg1tETLWBugmhSo9Zc4ms968qVmfmTroDxsJ982AiudAQGyt', + toAddr: 'bitcoincash:qz2qn6zt4qmacf4r6c0e2pdcqsgnkxaa3ql2xpee6p' } const result = await utilRouteInst.sweepWif(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) - assert.equal(result, "test-txid") + assert.equal(result, 'test-txid') }) - it("should throw 422 error if no non-token UTXOs", async () => { + it('should throw 422 error if no non-token UTXOs', async () => { sandbox .stub( utilRouteInst.blockbook.testableComponents, - "balanceFromBlockbook" + 'balanceFromBlockbook' ) .resolves(mockData.mockBalance) sandbox .stub( utilRouteInst.blockbook.testableComponents, - "utxosFromBlockbook" + 'utxosFromBlockbook' ) .resolves(mockData.mockUtxos) // Force token utxo to appear as regular BCH utxo. sandbox - .stub(utilRouteInst.bchjs.SLP.Utils, "tokenUtxoDetails") + .stub(utilRouteInst.bchjs.SLP.Utils, 'tokenUtxoDetails') .resolves(mockData.tokensOnly) // Mock sendRawTransaction() so that the hex does not actually get broadcast // to the network. sandbox - .stub(utilRouteInst.bchjs.RawTransactions, "sendRawTransaction") - .resolves("test-txid") + .stub(utilRouteInst.bchjs.RawTransactions, 'sendRawTransaction') + .resolves('test-txid') req.body = { - wif: "L5GEFg1tETLWBugmhSo9Zc4ms968qVmfmTroDxsJ982AiudAQGyt", - toAddr: "bitcoincash:qz2qn6zt4qmacf4r6c0e2pdcqsgnkxaa3ql2xpee6p" + wif: 'L5GEFg1tETLWBugmhSo9Zc4ms968qVmfmTroDxsJ982AiudAQGyt', + toAddr: 'bitcoincash:qz2qn6zt4qmacf4r6c0e2pdcqsgnkxaa3ql2xpee6p' } const result = await utilRouteInst.sweepWif(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) assert.equal(res.statusCode, 422) - assert.property(result, "error") + assert.property(result, 'error') assert.include( result.error, - "Tokens found, but no BCH UTXOs found. Add BCH to wallet to move tokens" + 'Tokens found, but no BCH UTXOs found. Add BCH to wallet to move tokens' ) }) - it("should detect and throw error for multiple token classes", async () => { + it('should detect and throw error for multiple token classes', async () => { sandbox .stub( utilRouteInst.blockbook.testableComponents, - "balanceFromBlockbook" + 'balanceFromBlockbook' ) .resolves(mockData.mockBalance) sandbox .stub( utilRouteInst.blockbook.testableComponents, - "utxosFromBlockbook" + 'utxosFromBlockbook' ) .resolves(mockData.mockThreeUtxos) // Force token utxo to appear as regular BCH utxo. sandbox - .stub(utilRouteInst.bchjs.SLP.Utils, "tokenUtxoDetails") + .stub(utilRouteInst.bchjs.SLP.Utils, 'tokenUtxoDetails') .resolves(mockData.multipleTokens) // Mock sendRawTransaction() so that the hex does not actually get broadcast // to the network. sandbox - .stub(utilRouteInst.bchjs.RawTransactions, "sendRawTransaction") - .resolves("test-txid") + .stub(utilRouteInst.bchjs.RawTransactions, 'sendRawTransaction') + .resolves('test-txid') req.body = { - wif: "L5GEFg1tETLWBugmhSo9Zc4ms968qVmfmTroDxsJ982AiudAQGyt", - toAddr: "bitcoincash:qz2qn6zt4qmacf4r6c0e2pdcqsgnkxaa3ql2xpee6p" + wif: 'L5GEFg1tETLWBugmhSo9Zc4ms968qVmfmTroDxsJ982AiudAQGyt', + toAddr: 'bitcoincash:qz2qn6zt4qmacf4r6c0e2pdcqsgnkxaa3ql2xpee6p' } const result = await utilRouteInst.sweepWif(req, res) // console.log(`result: ${JSON.stringify(result, null, 2)}`) assert.equal(res.statusCode, 422) - assert.property(result, "error") + assert.property(result, 'error') assert.include( result.error, - "Multiple token classes detected. This function only supports a single class of token" + 'Multiple token classes detected. This function only supports a single class of token' ) }) } diff --git a/test/v3/xpub.js b/test/v3/xpub.js index 0bb50a4..e921d83 100644 --- a/test/v3/xpub.js +++ b/test/v3/xpub.js @@ -6,30 +6,30 @@ to 'integration' to run the tests against BCH mainnet. */ -"use strict" +'use strict' -const chai = require("chai") +const chai = require('chai') const assert = chai.assert -const xpubRoute = require("../../src/routes/v3/xpub") -const nock = require("nock") // HTTP mocking +const xpubRoute = require('../../src/routes/v3/xpub') +const nock = require('nock') // HTTP mocking -let originalUrl // Used during transition from integration to unit tests. +// let originalUrl // Used during transition from integration to unit tests. // Mocking data. -const { mockReq, mockRes } = require("./mocks/express-mocks") -const mockData = require("./mocks/address-mock") +const { mockReq, mockRes } = require('./mocks/express-mocks') +// const mockData = require('./mocks/address-mock') // Used for debugging. -const util = require("util") +const util = require('util') util.inspect.defaultOptions = { depth: 1 } -describe("#XPUBRouter", () => { +describe('#XPUBRouter', () => { let req, res before(() => { // Set default environment variables for unit tests. - if (!process.env.TEST) process.env.TEST = "unit" - //if (process.env.TEST === "unit") + if (!process.env.TEST) process.env.TEST = 'unit' + // if (process.env.TEST === "unit") // process.env.BITCOINCOM_BASEURL = "http://fakeurl/api }) @@ -55,44 +55,44 @@ describe("#XPUBRouter", () => { }) after(() => { - //process.env.BITCOINCOM_BASEURL = originalUrl + // process.env.BITCOINCOM_BASEURL = originalUrl }) - describe("#root", () => { + describe('#root', () => { // root route handler. const root = xpubRoute.testableComponents.root - it("should respond to GET for base route", async () => { + it('should respond to GET for base route', async () => { const result = root(req, res) - assert.equal(result.status, "address", "Returns static string") + assert.equal(result.status, 'address', 'Returns static string') }) }) - describe("#FromXPubSingle", () => { + describe('#FromXPubSingle', () => { // details route handler. const fromXPubSingle = xpubRoute.testableComponents.fromXPubSingle - it("should throw 400 if xpub is empty", async () => { + it('should throw 400 if xpub is empty', async () => { const result = await fromXPubSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) - assert.hasAllKeys(result, ["error"]) - assert.include(result.error, "xpub can not be empty") + assert.hasAllKeys(result, ['error']) + assert.include(result.error, 'xpub can not be empty') }) - it("should error on an array", async () => { + it('should error on an array', async () => { req.params.xpub = [ - `tpubDHTK2jqg73w3GwoiHfAMbMYML1HN8FhrUxD9rFgbSgHXdwwrY6pAFqKDfUHhqw7vreaZty5hPGjb1S7ZPQeMmu6TFHAKfY9tJpYbvaGjPRM` + 'tpubDHTK2jqg73w3GwoiHfAMbMYML1HN8FhrUxD9rFgbSgHXdwwrY6pAFqKDfUHhqw7vreaZty5hPGjb1S7ZPQeMmu6TFHAKfY9tJpYbvaGjPRM' ] const result = await fromXPubSingle(req, res) - assert.equal(res.statusCode, 400, "HTTP status code 400 expected.") + assert.equal(res.statusCode, 400, 'HTTP status code 400 expected.') assert.include( result.error, - "xpub can not be an array", - "Proper error message" + 'xpub can not be an array', + 'Proper error message' ) }) /* @@ -118,8 +118,8 @@ describe("#XPUBRouter", () => { } }) */ - it("should create an address from xpub", async () => { - req.params.xpub = `tpubDHTK2jqg73w3GwoiHfAMbMYML1HN8FhrUxD9rFgbSgHXdwwrY6pAFqKDfUHhqw7vreaZty5hPGjb1S7ZPQeMmu6TFHAKfY9tJpYbvaGjPRM` + it('should create an address from xpub', async () => { + req.params.xpub = 'tpubDHTK2jqg73w3GwoiHfAMbMYML1HN8FhrUxD9rFgbSgHXdwwrY6pAFqKDfUHhqw7vreaZty5hPGjb1S7ZPQeMmu6TFHAKfY9tJpYbvaGjPRM' // Mock the Insight URL for unit tests. // TODO add unit test @@ -133,7 +133,7 @@ describe("#XPUBRouter", () => { // Call the details API. const result = await fromXPubSingle(req, res) - //console.log(`result: ${util.inspect(result)}`) + // console.log(`result: ${util.inspect(result)}`) // Assert that required fields exist in the returned object. assert.exists(result.legacyAddress)