Merge pull request #1 from christroutner/unstable

Refactoring all code from TypeScript back to JavaScript
This commit is contained in:
Chris Troutner
2019-05-27 20:57:04 -07:00
committed by GitHub
74 changed files with 375 additions and 41738 deletions
+1 -1
View File
@@ -17,6 +17,7 @@
"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"],
@@ -24,7 +25,6 @@
"keyword-spacing": ["error"],
"linebreak-style": ["error", "unix"],
"new-parens": ["error"],
"no-lonely-if": ["error"],
"no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1 }],
"no-whitespace-before-property": ["error"],
"semi": ["error", "never"],
Vendored
-234
View File
@@ -1,234 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var express = require("express");
// Middleware
var route_ratelimit_1 = require("./middleware/route-ratelimit");
var path = require("path");
var logger = require("morgan");
var wlogger = require("./util/winston-logging");
var cookieParser = require("cookie-parser");
var bodyParser = require("body-parser");
var basicAuth = require("express-basic-auth");
var helmet = require("helmet");
var debug = require("debug")("rest-cloud:server");
var http = require("http");
var cors = require("cors");
var AuthMW = require("./middleware/auth");
var BitcoinCashZMQDecoder = require("bitcoincash-zmq-decoder");
var zmq = require("zeromq");
var sock = zmq.socket("sub");
var swStats = require("swagger-stats");
var apiSpec;
if (process.env.NETWORK === "mainnet") {
apiSpec = require("./public/bitcoin-com-mainnet-rest-v2.json");
}
else {
apiSpec = require("./public/bitcoin-com-testnet-rest-v2.json");
}
// v1
var indexV1 = require("./routes/v1/index");
var healthCheckV1 = require("./routes/v1/health-check");
var addressV1 = require("./routes/v1/address");
var blockV1 = require("./routes/v1/block");
var blockchainV1 = require("./routes/v1/blockchain");
var controlV1 = require("./routes/v1/control");
var generatingV1 = require("./routes/v1/generating");
var miningV1 = require("./routes/v1/mining");
var networkV1 = require("./routes/v1/network");
var rawtransactionsV1 = require("./routes/v1/rawtransactions");
var transactionV1 = require("./routes/v1/transaction");
var utilV1 = require("./routes/v1/util");
var dataRetrievalV1 = require("./routes/v1/dataRetrieval");
var payloadCreationV1 = require("./routes/v1/payloadCreation");
var slpV1 = require("./routes/v1/slp");
// v2
var indexV2 = require("./routes/v2/index");
var healthCheckV2 = require("./routes/v2/health-check");
var addressV2 = require("./routes/v2/address");
var blockV2 = require("./routes/v2/block");
var blockchainV2 = require("./routes/v2/blockchain");
var controlV2 = require("./routes/v2/control");
var generatingV2 = require("./routes/v2/generating");
var miningV2 = require("./routes/v2/mining");
var networkV2 = require("./routes/v2/network");
var rawtransactionsV2 = require("./routes/v2/rawtransactions");
var transactionV2 = require("./routes/v2/transaction");
var utilV2 = require("./routes/v2/util");
var slpV2 = require("./routes/v2/slp");
require("dotenv").config();
var app = express();
app.locals.env = process.env;
app.use(swStats.getMiddleware({ swaggerSpec: apiSpec }));
app.use(helmet());
app.use(cors());
app.enable("trust proxy");
// view engine setup
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "jade");
app.use("/public", express.static(__dirname + "/public"));
app.use(logger("dev"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, "public")));
// Make io accessible to our router
app.use(function (req, res, next) {
req.io = io;
next();
});
var v1prefix = "v1";
var v2prefix = "v2";
app.use("/", indexV1);
app.use("/" + v1prefix + "/" + "health-check", healthCheckV1);
app.use("/" + v1prefix + "/" + "address", addressV1);
app.use("/" + v1prefix + "/" + "blockchain", blockchainV1);
app.use("/" + v1prefix + "/" + "block", blockV1);
app.use("/" + v1prefix + "/" + "control", controlV1);
app.use("/" + v1prefix + "/" + "generating", generatingV1);
app.use("/" + v1prefix + "/" + "mining", miningV1);
app.use("/" + v1prefix + "/" + "network", networkV1);
app.use("/" + v1prefix + "/" + "rawtransactions", rawtransactionsV1);
app.use("/" + v1prefix + "/" + "transaction", transactionV1);
app.use("/" + v1prefix + "/" + "util", utilV1);
app.use("/" + v1prefix + "/" + "dataRetrieval", dataRetrievalV1);
app.use("/" + v1prefix + "/" + "payloadCreation", payloadCreationV1);
app.use("/" + v1prefix + "/" + "slp", slpV1);
// Instantiate the authorization middleware, used to implement pro-tier rate limiting.
var auth = new AuthMW();
app.use("/" + v2prefix + "/", auth.mw());
// Rate limit on all v2 routes
app.use("/" + v2prefix + "/", route_ratelimit_1.routeRateLimit);
app.use("/", indexV2);
app.use("/" + v2prefix + "/" + "health-check", healthCheckV2);
app.use("/" + v2prefix + "/" + "address", addressV2.router);
app.use("/" + v2prefix + "/" + "blockchain", blockchainV2.router);
app.use("/" + v2prefix + "/" + "block", blockV2.router);
app.use("/" + v2prefix + "/" + "control", controlV2.router);
app.use("/" + v2prefix + "/" + "generating", generatingV2);
app.use("/" + v2prefix + "/" + "mining", miningV2.router);
app.use("/" + v2prefix + "/" + "network", networkV2);
app.use("/" + v2prefix + "/" + "rawtransactions", rawtransactionsV2.router);
app.use("/" + v2prefix + "/" + "transaction", transactionV2.router);
app.use("/" + v2prefix + "/" + "util", utilV2.router);
app.use("/" + v2prefix + "/" + "slp", slpV2.router);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = {
message: "Not Found",
status: 404
};
next(err);
});
// error handler
app.use(function (err, req, res, next) {
var status = err.status || 500;
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get("env") === "development" ? err : {};
// render the error page
res.status(status);
res.json({
status: status,
message: err.message
});
});
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || "3000");
app.set("port", port);
console.log("rest.bitcoin.com started on port " + port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
var io = require("socket.io").listen(server);
io.on("connection", function (socket) {
console.log("Socket Connected");
socket.on("disconnect", function () {
console.log("Socket Disconnected");
});
});
/**
* Setup ZMQ connections if ZMQ URL and port provided
*/
if (process.env.ZEROMQ_URL && process.env.ZEROMQ_PORT) {
console.log("Connecting to BCH ZMQ at " + process.env.ZEROMQ_URL + ":" + process.env.ZEROMQ_PORT);
var bitcoincashZmqDecoder_1 = new BitcoinCashZMQDecoder(process.env.NETWORK);
sock.connect("tcp://" + process.env.ZEROMQ_URL + ":" + process.env.ZEROMQ_PORT);
sock.subscribe("raw");
sock.on("message", function (topic, message) {
try {
var decoded = topic.toString("ascii");
if (decoded === "rawtx") {
var txd = bitcoincashZmqDecoder_1.decodeTransaction(message);
io.emit("transactions", JSON.stringify(txd, null, 2));
}
else if (decoded === "rawblock") {
var blck = bitcoincashZmqDecoder_1.decodeBlock(message);
io.emit("blocks", JSON.stringify(blck, null, 2));
}
}
catch (error) {
var errorMessage = 'Error processing ZMQ message';
console.log(errorMessage, error);
wlogger.error(errorMessage, error);
}
});
}
else {
console.log("ZEROMQ_URL and ZEROMQ_PORT env vars missing. Skipping ZMQ connection.");
}
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
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?
server.setTimeout(30 * 1000);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== "listen")
throw error;
var bind = typeof port === "string" ? "Pipe " + port : "Port " + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case "EACCES":
console.error(bind + " requires elevated privileges");
process.exit(1);
break;
case "EADDRINUSE":
console.error(bind + " is already in use");
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port;
debug("Listening on " + bind);
}
-78
View File
@@ -1,78 +0,0 @@
/*
Handle authorization for bypassing rate limits.
This file uses the passport npm library to check the header of each REST API
call for the prescence of a Basic authorization header:
https://en.wikipedia.org/wiki/Basic_access_authentication
If the header is found and validated, the req.locals.proLimit Boolean value
is set and passed to the route-ratelimits.ts middleware.
*/
"use strict";
var passport = require("passport");
var BasicStrategy = require("passport-http").BasicStrategy;
var AnonymousStrategy = require("passport-anonymous");
var wlogger = require("../util/winston-logging");
// Used for debugging and iterrogating JS objects.
var util = require("util");
util.inspect.defaultOptions = { depth: 1 };
var _this;
// Set default rate limit value for testing
var PRO_PASSes = process.env.PRO_PASS ? process.env.PRO_PASS : "BITBOX";
// Convert the pro-tier password string into an array split by ':'.
var PRO_PASS = PRO_PASSes.split(":");
//wlogger.verbose(`PRO_PASS set to: ${PRO_PASS}`)
// Auth Middleware
var AuthMW = /** @class */ (function () {
function AuthMW() {
_this = this;
// Initialize passport for 'anonymous' authentication.
/*
passport.use(
new AnonymousStrategy({ passReqToCallback: true }, function(
req,
username,
password,
done
) {
console.log(`anonymous auth handler triggered.`)
})
)
*/
passport.use(new AnonymousStrategy());
// Initialize passport for 'basic' authentication.
passport.use(new BasicStrategy({ passReqToCallback: true }, function (req, username, password, done) {
//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)
req.locals = {};
// Set pro-tier rate limit to flag to false by default.
req.locals.proLimit = false;
// Evaluate the username and password and set the rate limit accordingly.
//if (username === "BITBOX" && password === PRO_PASS) {
if (username === "BITBOX") {
for (var i = 0; i < PRO_PASS.length; i++) {
var thisPass = PRO_PASS[i];
if (password === thisPass) {
wlogger.verbose(req.url + " called by " + password.slice(0, 6));
// Success
req.locals.proLimit = true;
break;
}
}
}
//console.log(`req.locals: ${util.inspect(req.locals)}`)
return done(null, true);
}));
}
// Middleware called by the route.
AuthMW.prototype.mw = function () {
return passport.authenticate(["basic", "anonymous"], {
session: false
});
};
return AuthMW;
}());
module.exports = AuthMW;
-81
View File
@@ -1,81 +0,0 @@
"use strict";
/*
This file controls the request-per-minute (RPM) rate limits.
It is assumed that this middleware is run AFTER the auth.js middleware which
checks for Basic auth. If the user adds the correct Basic auth to the header
of their API request, they will get pro-tier rate limits. By default, the
freemium rate limits apply.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var RateLimit = require("express-rate-limit");
// Set max requests per minute
var maxRequests = process.env.RATE_LIMIT_MAX_REQUESTS
? parseInt(process.env.RATE_LIMIT_MAX_REQUESTS)
: 60;
// Pro-tier rate limits are 10x the freemium limits.
var PRO_RPM = 10 * maxRequests;
// Unique route mapped to its rate limit
var uniqueRateLimits = {};
var routeRateLimit = function (req, res, next) {
// Create a res.locals object if not passed in.
if (!req.locals)
req.locals = {};
// Disable rate limiting if 0 passed from RATE_LIMIT_MAX_REQUESTS
if (maxRequests === 0)
return next();
// Current route
var rateLimitTier = req.locals.proLimit ? "PRO" : "BASIC";
var path = req.baseUrl + req.path;
var route = rateLimitTier +
req.method +
path
.split("/")
.slice(0, 4)
.join("/");
// This boolean value is passed from the auth.js middleware.
var proRateLimits = req.locals.proLimit;
// Pro level rate limits
if (proRateLimits) {
// TODO: replace the console.logs with calls to our logging system.
//console.log(`applying pro-rate limits`)
// Create new RateLimit if none exists for this route
if (!uniqueRateLimits[route]) {
uniqueRateLimits[route] = new RateLimit({
windowMs: 60 * 1000,
delayMs: 0,
max: PRO_RPM,
handler: function (req, res /*next*/) {
//console.log(`pro-tier rate-handler triggered.`)
res.status(429); // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330
return res.json({
error: "Too many requests. Limits are " + PRO_RPM + " requests per minute."
});
}
});
}
// Freemium level rate limits
}
else {
// TODO: replace the console.logs with calls to our logging system.
//console.log(`applying freemium limits`)
// Create new RateLimit if none exists for this route
if (!uniqueRateLimits[route]) {
uniqueRateLimits[route] = new RateLimit({
windowMs: 60 * 1000,
delayMs: 0,
max: maxRequests,
handler: function (req, res /*next*/) {
//console.log(`freemium rate-handler triggered.`)
res.status(429); // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330
return res.json({
error: "Too many requests. Limits are " + maxRequests + " requests per minute."
});
}
});
}
}
// Call rate limit for this route
uniqueRateLimits[route](req, res, next);
};
exports.routeRateLimit = routeRateLimit;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

-16468
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-1726
View File
File diff suppressed because it is too large Load Diff
-3
View File
File diff suppressed because one or more lines are too long
-45
View File
@@ -1,45 +0,0 @@
/*
Instantiates and configures the Winston logging library. This utitlity library
can be called by other parts of the application to conveniently tap into the
logging library.
*/
"use strict";
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",
zippedArchive: false,
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");
});
// This controls what goes into the log FILES
var wlogger = winston.createLogger({
level: "verbose",
format: winston.format.json(),
transports: [
//
// - Write to all logs with level `info` and below to `combined.log`
// - Write all logs error (and below) to `error.log`.
//
// new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
// new winston.transports.File({ filename: 'logs/combined.log' })
transport
]
});
// This controls the logs to CONSOLE
/*
wlogger.add(
new winston.transports.Console({
format: winston.format.simple(),
level: "info"
})
)
*/
module.exports = wlogger;
-64
View File
@@ -1,64 +0,0 @@
doctype html
// HTML for static distribution bundle build
html(lang='en')
head
// Global site tag (gtag.js) - Google Analytics
script(async='', src='https://www.googletagmanager.com/gtag/js?id=UA-115463658-5')
script.
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-115463658-5');
meta(charset='UTF-8')
title REST V2 by Bitcoin.com - BCH RPC over HTTP
link(href='https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700', rel='stylesheet')
link(rel='stylesheet', type='text/css', href='../../public/swagger-ui-v2.css')
link(rel='icon', type='image/png', href='../public/favicon.png', sizes='32x32')
style.
html
{
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after
{
box-sizing: inherit;
}
body
{
margin:0;
background: #fafafa;
}
body
#swagger-ui
script(src='../public/swagger-ui-bundle.js')
script(src='../public/swagger-ui-standalone-preset.js')
script.
window.onload = function() {
let network = "#{env.NETWORK}"
let path;
if(network === 'mainnet') {
path = "../public/bitcoin-com-mainnet-rest-v2.json"
} else {
path = "../public/bitcoin-com-testnet-rest-v2.json"
}
const ui = SwaggerUIBundle({
url: path,
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
window.ui = ui
}
-57
View File
@@ -1,57 +0,0 @@
doctype html
// HTML for static distribution bundle build
html(lang='en')
head
// Global site tag (gtag.js) - Google Analytics
script(async='', src='https://www.googletagmanager.com/gtag/js?id=UA-115463658-5')
script.
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-115463658-5');
meta(charset='UTF-8')
title REST by Bitcoin.com - BCH RPC over HTTP
link(href='https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700', rel='stylesheet')
link(rel='stylesheet', type='text/css', href='../public/swagger-ui.css')
link(rel='icon', type='image/png', href='../public/favicon.png', sizes='32x32')
style.
html
{
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after
{
box-sizing: inherit;
}
body
{
margin:0;
background: #fafafa;
}
body
#swagger-ui
script(src='../public/swagger-ui-bundle.js')
script(src='../public/swagger-ui-standalone-preset.js')
script.
window.onload = function() {
// Build a system
const ui = SwaggerUIBundle({
url: "../public/bitcoin-com-rest-v1.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
window.ui = ui
}
+2 -4
View File
@@ -8,11 +8,9 @@
],
"license": "MIT",
"scripts": {
"start": "npm run build && node ./dist/app.js",
"build": "node ./node_modules/gulp/bin/gulp.js build && ./node_modules/typescript/bin/tsc",
"start": "node ./src/app.js",
"dev": "nodemon ./dist/app.js",
"test": "npm run test-v2",
"test-v1": "npm run build && nyc --reporter=text mocha --require babel-core/register --timeout 15000 test/v1/",
"test": "export NETWORK=testnet && nyc --reporter=text mocha --timeout 25000 test/v2/",
"test-v2": "export NETWORK=testnet && npm run build && nyc --reporter=text mocha --require babel-core/register --timeout 25000 test/v2/",
"test-v2-no-build": "export NETWORK=testnet && nyc --reporter=text mocha --require babel-core/register --timeout 25000 test/v2/",
"test-all": "TEST=integration nyc --reporter=text mocha --require babel-core/register --timeout 15000 test/v1/ test/v2/",
+35 -77
View File
@@ -1,10 +1,10 @@
"use strict"
import { Socket } from "net"
const { Socket } = require("net")
import * as express from "express"
const express = require("express")
// Middleware
import { routeRateLimit } from "./middleware/route-ratelimit"
const { routeRateLimit } = require("./middleware/route-ratelimit")
const path = require("path")
const logger = require("morgan")
@@ -22,32 +22,14 @@ const BitcoinCashZMQDecoder = require("bitcoincash-zmq-decoder")
const zmq = require("zeromq")
const sock: any = zmq.socket("sub")
const sock = zmq.socket("sub")
/*
const swStats = require("swagger-stats")
let apiSpec
if (process.env.NETWORK === "mainnet") {
if (process.env.NETWORK === "mainnet")
apiSpec = require("./public/bitcoin-com-mainnet-rest-v2.json")
} else {
apiSpec = require("./public/bitcoin-com-testnet-rest-v2.json")
}
// v1
const indexV1 = require("./routes/v1/index")
const healthCheckV1 = require("./routes/v1/health-check")
const addressV1 = require("./routes/v1/address")
const blockV1 = require("./routes/v1/block")
const blockchainV1 = require("./routes/v1/blockchain")
const controlV1 = require("./routes/v1/control")
const generatingV1 = require("./routes/v1/generating")
const miningV1 = require("./routes/v1/mining")
const networkV1 = require("./routes/v1/network")
const rawtransactionsV1 = require("./routes/v1/rawtransactions")
const transactionV1 = require("./routes/v1/transaction")
const utilV1 = require("./routes/v1/util")
const dataRetrievalV1 = require("./routes/v1/dataRetrieval")
const payloadCreationV1 = require("./routes/v1/payloadCreation")
const slpV1 = require("./routes/v1/slp")
else apiSpec = require("./public/bitcoin-com-testnet-rest-v2.json")
*/
// v2
const indexV2 = require("./routes/v2/index")
@@ -64,18 +46,13 @@ const transactionV2 = require("./routes/v2/transaction")
const utilV2 = require("./routes/v2/util")
const slpV2 = require("./routes/v2/slp")
interface IError {
message: string
status: number
}
require("dotenv").config()
const app: express.Application = express()
const app = express()
app.locals.env = process.env
app.use(swStats.getMiddleware({ swaggerSpec: apiSpec }))
//app.use(swStats.getMiddleware({ swaggerSpec: apiSpec }))
app.use(helmet())
@@ -103,38 +80,15 @@ app.use(express.static(path.join(__dirname, "public")))
// }
// ));
interface ICustomRequest extends express.Request {
io: any
}
// Make io accessible to our router
app.use(
(req: ICustomRequest, res: express.Response, next: express.NextFunction) => {
req.io = io
app.use((req, res, next) => {
req.io = io
next()
}
)
next()
})
const v1prefix = "v1"
const v2prefix = "v2"
app.use("/", indexV1)
app.use(`/${v1prefix}/` + `health-check`, healthCheckV1)
app.use(`/${v1prefix}/` + `address`, addressV1)
app.use(`/${v1prefix}/` + `blockchain`, blockchainV1)
app.use(`/${v1prefix}/` + `block`, blockV1)
app.use(`/${v1prefix}/` + `control`, controlV1)
app.use(`/${v1prefix}/` + `generating`, generatingV1)
app.use(`/${v1prefix}/` + `mining`, miningV1)
app.use(`/${v1prefix}/` + `network`, networkV1)
app.use(`/${v1prefix}/` + `rawtransactions`, rawtransactionsV1)
app.use(`/${v1prefix}/` + `transaction`, transactionV1)
app.use(`/${v1prefix}/` + `util`, utilV1)
app.use(`/${v1prefix}/` + `dataRetrieval`, dataRetrievalV1)
app.use(`/${v1prefix}/` + `payloadCreation`, payloadCreationV1)
app.use(`/${v1prefix}/` + `slp`, slpV1)
// Instantiate the authorization middleware, used to implement pro-tier rate limiting.
const auth = new AuthMW()
app.use(`/${v2prefix}/`, auth.mw())
@@ -156,19 +110,17 @@ app.use(`/${v2prefix}/` + `util`, utilV2.router)
app.use(`/${v2prefix}/` + `slp`, slpV2.router)
// catch 404 and forward to error handler
app.use(
(req: express.Request, res: express.Response, next: express.NextFunction) => {
const err: IError = {
message: "Not Found",
status: 404
}
next(err)
app.use((req, res, next) => {
const err = {
message: "Not Found",
status: 404
}
)
next(err)
})
// error handler
app.use((err: IError, req: express.Request, res: express.Response, next: express.NextFunction) => {
app.use((err, req, res, next) => {
const status = err.status || 500
// set locals, only providing error in development
@@ -195,7 +147,7 @@ console.log(`rest.bitcoin.com started on port ${port}`)
*/
const server = http.createServer(app)
const io = require("socket.io").listen(server)
io.on("connection", (socket: Socket) => {
io.on("connection", socket => {
console.log("Socket Connected")
socket.on("disconnect", () => {
@@ -208,13 +160,17 @@ io.on("connection", (socket: Socket) => {
*/
if (process.env.ZEROMQ_URL && process.env.ZEROMQ_PORT) {
console.log(`Connecting to BCH ZMQ at ${process.env.ZEROMQ_URL}:${process.env.ZEROMQ_PORT}`)
console.log(
`Connecting to BCH ZMQ at ${process.env.ZEROMQ_URL}:${
process.env.ZEROMQ_PORT
}`
)
const bitcoincashZmqDecoder = new BitcoinCashZMQDecoder(process.env.NETWORK)
sock.connect(`tcp://${process.env.ZEROMQ_URL}:${process.env.ZEROMQ_PORT}`)
sock.subscribe("raw")
sock.on("message", (topic: any, message: string) => {
sock.on("message", (topic, message) => {
try {
const decoded = topic.toString("ascii")
if (decoded === "rawtx") {
@@ -225,13 +181,15 @@ if (process.env.ZEROMQ_URL && process.env.ZEROMQ_PORT) {
io.emit("blocks", JSON.stringify(blck, null, 2))
}
} catch (error) {
const errorMessage = 'Error processing ZMQ message'
const errorMessage = "Error processing ZMQ message"
console.log(errorMessage, error)
wlogger.error(errorMessage, error)
}
})
} else {
console.log("ZEROMQ_URL and ZEROMQ_PORT env vars missing. Skipping ZMQ connection.")
console.log(
"ZEROMQ_URL and ZEROMQ_PORT env vars missing. Skipping ZMQ connection."
)
}
/**
@@ -250,7 +208,7 @@ server.setTimeout(30 * 1000)
* Normalize a port into a number, string, or false.
*/
function normalizePort(val: string) {
function normalizePort(val) {
const port = parseInt(val, 10)
if (isNaN(port)) {
@@ -269,7 +227,7 @@ function normalizePort(val: string) {
/**
* Event listener for HTTP server "error" event.
*/
function onError(error: any) {
function onError(error) {
if (error.syscall !== "listen") throw error
const bind = typeof port === "string" ? `Pipe ${port}` : `Port ${port}`
@@ -7,7 +7,9 @@
freemium rate limits apply.
*/
import * as express from "express"
"use strict"
const express = require("express")
const RateLimit = require("express-rate-limit")
// Set max requests per minute
@@ -19,25 +21,12 @@ const maxRequests = process.env.RATE_LIMIT_MAX_REQUESTS
const PRO_RPM = 10 * maxRequests
// Unique route mapped to its rate limit
const uniqueRateLimits: any = {}
const uniqueRateLimits = {}
// Add the 'locals' property to the express.Request interface.
declare global {
namespace Express {
interface Request {
locals: any
}
}
}
const routeRateLimit = function(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
const routeRateLimit = function(req, res, next) {
// Create a res.locals object if not passed in.
if(!req.locals) req.locals = {}
if (!req.locals) req.locals = {}
// Disable rate limiting if 0 passed from RATE_LIMIT_MAX_REQUESTS
if (maxRequests === 0) return next()
@@ -66,10 +55,7 @@ const routeRateLimit = function(
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: express.Request,
res: express.Response /*next*/
) {
handler: function(req, res) {
//console.log(`pro-tier rate-handler triggered.`)
res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330
@@ -91,10 +77,7 @@ const routeRateLimit = function(
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: express.Request,
res: express.Response /*next*/
) {
handler: function(req, res) {
//console.log(`freemium rate-handler triggered.`)
res.status(429) // https://github.com/Bitcoin-com/rest.bitcoin.com/issues/330
@@ -110,4 +93,4 @@ const routeRateLimit = function(
uniqueRateLimits[route](req, res, next)
}
export { routeRateLimit }
module.exports = { routeRateLimit }
-318
View File
@@ -1,318 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
const axios = require("axios")
const RateLimit = require("express-rate-limit")
const BITBOXCli = require("bitbox-sdk/lib/bitbox-sdk").default
const BITBOX = new BITBOXCli()
const util = require("util")
util.inspect.defaultOptions = { depth: 1 }
const config = {
addressRateLimit1: undefined,
addressRateLimit2: undefined,
addressRateLimit3: undefined,
addressRateLimit4: undefined
}
let i = 1
while (i < 6) {
config[`addressRateLimit${i}`] = new RateLimit({
windowMs: 60000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
i++
}
router.get("/", config.addressRateLimit1, async (req, res, next) => {
res.json({ status: "address" })
})
router.get(
"/details/:address",
config.addressRateLimit2,
async (req, res, next) => {
try {
let addresses = JSON.parse(req.params.address)
// Enforce no more than 20 addresses.
if (addresses.length > 20) {
res.json({
error: "Array too large. Max 20 addresses"
})
}
const result = []
addresses = addresses.map(address => {
const path = `${
process.env.BITCOINCOM_BASEURL
}addr/${BITBOX.Address.toLegacyAddress(address)}`
return axios.get(path) // Returns a promise.
})
axios.all(addresses).then(
axios.spread((...args) => {
for (let i = 0; i < args.length; i++) {
const parsed = args[i].data
parsed.legacyAddress = BITBOX.Address.toLegacyAddress(
parsed.addrStr
)
parsed.cashAddress = BITBOX.Address.toCashAddress(parsed.addrStr)
delete parsed.addrStr
result.push(parsed)
}
res.json(result)
})
)
} catch (error) {
let path = `${
process.env.BITCOINCOM_BASEURL
}addr/${BITBOX.Address.toLegacyAddress(req.params.address)}`
if (req.query.from && req.query.to)
path = `${path}?from=${req.query.from}&to=${req.query.to}`
axios
.get(path)
.then(response => {
const parsed = response.data
delete parsed.addrStr
parsed.legacyAddress = BITBOX.Address.toLegacyAddress(
req.params.address
)
parsed.cashAddress = BITBOX.Address.toCashAddress(req.params.address)
res.json(parsed)
})
.catch(error => {
res.send(error.response.data.error.message)
})
}
}
)
router.get(
"/utxo/:address",
config.addressRateLimit3,
async (req, res, next) => {
try {
let addresses = JSON.parse(req.params.address)
if (addresses.length > 20) {
res.json({
error: "Array too large. Max 20 addresses"
})
}
addresses = addresses.map(address =>
BITBOX.Address.toLegacyAddress(address)
)
const final = []
addresses.forEach(address => {
final.push([])
})
axios
.get(`${process.env.BITCOINCOM_BASEURL}addrs/${addresses}/utxo`)
.then(response => {
const parsed = response.data
parsed.forEach(data => {
data.legacyAddress = BITBOX.Address.toLegacyAddress(data.address)
data.cashAddress = BITBOX.Address.toCashAddress(data.address)
delete data.address
addresses.forEach((address, index) => {
if (addresses[index] === data.legacyAddress)
final[index].push(data)
})
})
res.json(final)
})
.catch(error => {
//res.send(error.response.data.error.message)
// console.log(`Error: `, error)
})
} catch (error) {
axios
.get(
`${
process.env.BITCOINCOM_BASEURL
}addr/${BITBOX.Address.toLegacyAddress(req.params.address)}/utxo`
)
.then(response => {
const parsed = response.data
parsed.forEach(data => {
delete data.address
data.legacyAddress = BITBOX.Address.toLegacyAddress(
req.params.address
)
data.cashAddress = BITBOX.Address.toCashAddress(req.params.address)
})
res.json(parsed)
})
.catch(error => {
//res.send(error.response.data.error.message)
// console.log(`Error: `, error)
})
}
}
)
router.get(
"/unconfirmed/:address",
config.addressRateLimit4,
(req, res, next) => {
try {
let addresses = JSON.parse(req.params.address)
if (addresses.length > 20) {
res.json({
error: "Array too large. Max 20 addresses"
})
}
addresses = addresses.map(address =>
BITBOX.Address.toLegacyAddress(address)
)
const final = []
addresses.forEach(address => {
final.push([])
})
axios
.get(`${process.env.BITCOINCOM_BASEURL}addrs/${addresses}/utxo`)
.then(response => {
const parsed = response.data
parsed.forEach(data => {
data.legacyAddress = BITBOX.Address.toLegacyAddress(data.address)
data.cashAddress = BITBOX.Address.toCashAddress(data.address)
delete data.address
if (data.confirmations === 0) {
addresses.forEach((address, index) => {
if (addresses[index] === data.legacyAddress)
final[index].push(data)
})
}
})
res.json(final)
})
.catch(error => {
res.send(error.response.data.error.message)
})
} catch (error) {
axios
.get(
`${
process.env.BITCOINCOM_BASEURL
}addr/${BITBOX.Address.toLegacyAddress(req.params.address)}/utxo`
)
.then(response => {
const parsed = response.data
const unconfirmed = []
parsed.forEach(data => {
data.legacyAddress = BITBOX.Address.toLegacyAddress(data.address)
data.cashAddress = BITBOX.Address.toCashAddress(data.address)
delete data.address
if (data.confirmations === 0) unconfirmed.push(data)
})
res.json(unconfirmed)
})
.catch(error => {
res.send(error.response.data.error.message)
})
}
}
)
router.get(
"/unconfirmed/:address",
config.addressRateLimit4,
async (req, res, next) => {
try {
let addresses = JSON.parse(req.params.address)
if (addresses.length > 20) {
res.json({
error: "Array too large. Max 20 addresses"
})
}
addresses = addresses.map(address =>
BITBOX.Address.toLegacyAddress(address)
)
const final = []
addresses.forEach(address => {
final.push([])
})
axios
.get(`${process.env.BITCOINCOM_BASEURL}txs/?address=${addresses}`)
.then(response => {
res.json(response.data)
})
.catch(error => {
res.send(error.response.data.error.message)
})
} catch (error) {
axios
.get(
`${
process.env.BITCOINCOM_BASEURL
}txs/?address=${BITBOX.Address.toLegacyAddress(req.params.address)}`
)
.then(response => {
res.json(response.data)
})
.catch(error => {
res.send(error.response.data.error.message)
})
}
}
)
router.get(
"/transactions/:address",
config.addressRateLimit5,
(req, res, next) => {
try {
let addresses = JSON.parse(req.params.address)
if (addresses.length > 20) {
res.json({
error: "Array too large. Max 20 addresses"
})
}
addresses = addresses.map(address =>
BITBOX.Address.toLegacyAddress(address)
)
const final = []
addresses.forEach(address => {
final.push([])
})
axios
.get(`${process.env.BITCOINCOM_BASEURL}txs/?address=${addresses}`)
.then(response => {
res.json(response.data)
})
.catch(error => {
res.send(error.response.data.error.message)
})
} catch (error) {
axios
.get(
`${
process.env.BITCOINCOM_BASEURL
}txs/?address=${BITBOX.Address.toLegacyAddress(req.params.address)}`
)
.then(response => {
res.json(response.data)
})
.catch(error => {
res.send(error.response.data.error.message)
})
}
}
)
module.exports = router
-90
View File
@@ -1,90 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
const axios = require("axios")
const RateLimit = require("express-rate-limit")
const BitboxHTTP = axios.create({
baseURL: process.env.RPC_BASEURL
})
const username = process.env.RPC_USERNAME
const password = process.env.RPC_PASSWORD
const config = {
blockRateLimit1: undefined,
blockRateLimit2: undefined
}
let i = 1
while (i < 3) {
config[`blockRateLimit${i}`] = new RateLimit({
windowMs: 60000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
i++
}
router.get("/", config.blockRateLimit1, (req, res, next) => {
res.json({ status: "block" })
})
router.get("/details/:id", config.blockRateLimit2, (req, res, next) => {
if (req.params.id.length !== 64) {
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "getblockhash",
method: "getblockhash",
params: [parseInt(req.params.id)]
}
})
.then(response => {
axios
.get(`${process.env.BITCOINCOM_BASEURL}block/${response.data.result}`)
.then(response => {
const parsed = response.data
res.json(parsed)
})
.catch(error => {
//res.send(error.response.data.error.message)
res.status(500)
return res.send(error)
})
})
.catch(error => {
//res.send(error.response.data.error.message)
res.status(500)
return res.send(error)
})
} else {
axios
.get(`${process.env.BITCOINCOM_BASEURL}block/${req.params.id}`)
.then(response => {
const parsed = response.data
res.json(parsed)
})
.catch(error => {
//res.send(error.response.data.error.message)
res.status(500)
return res.send(error)
})
}
})
module.exports = router
-721
View File
@@ -1,721 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
const axios = require("axios")
const RateLimit = require("express-rate-limit")
const BitboxHTTP = axios.create({
baseURL: process.env.RPC_BASEURL
})
const username = process.env.RPC_USERNAME
const password = process.env.RPC_PASSWORD
const config = {
blockchainRateLimit1: undefined,
blockchainRateLimit2: undefined,
blockchainRateLimit3: undefined,
blockchainRateLimit4: undefined,
blockchainRateLimit5: undefined,
blockchainRateLimit6: undefined,
blockchainRateLimit7: undefined,
blockchainRateLimit8: undefined,
blockchainRateLimit9: undefined,
blockchainRateLimit10: undefined,
blockchainRateLimit11: undefined,
blockchainRateLimit12: undefined,
blockchainRateLimit13: undefined,
blockchainRateLimit14: undefined,
blockchainRateLimit15: undefined,
blockchainRateLimit16: undefined,
blockchainRateLimit17: undefined
}
let i = 1
while (i < 18) {
config[`blockchainRateLimit${i}`] = new RateLimit({
windowMs: 60000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
i++
}
const requestConfig = {
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0"
}
}
router.get("/", config.blockchainRateLimit1, async (req, res, next) => {
res.json({ status: "blockchain" })
})
router.get(
"/getBestBlockHash",
config.blockchainRateLimit2,
async (req, res, next) => {
requestConfig.data.id = "getbestblockhash"
requestConfig.data.method = "getbestblockhash"
requestConfig.data.params = []
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/getBlock/:hash",
config.blockchainRateLimit3,
async (req, res, next) => {
let verbose = false
if (req.query.verbose && req.query.verbose === "true") verbose = true
let showTxs = true
if (req.query.txs && req.query.txs === "false") showTxs = false
requestConfig.data.id = "getblock"
requestConfig.data.method = "getblock"
requestConfig.data.params = [req.params.hash, verbose]
try {
const response = await BitboxHTTP(requestConfig)
if (!showTxs) delete response.data.result.tx
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/getBlockchainInfo",
config.blockchainRateLimit4,
async (req, res, next) => {
requestConfig.data.id = "getblockchaininfo"
requestConfig.data.method = "getblockchaininfo"
requestConfig.data.params = []
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/getBlockCount",
config.blockchainRateLimit5,
async (req, res, next) => {
requestConfig.data.id = "getblockcount"
requestConfig.data.method = "getblockcount"
requestConfig.data.params = []
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/getBlockHash/:height",
config.blockchainRateLimit6,
async (req, res, next) => {
try {
let heights = JSON.parse(req.params.height)
if (heights.length > 20) {
res.json({
error: "Array too large. Max 20 heights"
})
}
const result = []
heights = heights.map(height =>
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "getblockhash",
method: "getblockhash",
params: [height]
}
}).catch(error => {
try {
return {
data: {
result: error.response.data.error.message
}
}
} catch (ex) {
return {
data: {
result: "unknown error"
}
}
}
})
)
axios.all(heights).then(
axios.spread((...args) => {
for (let i = 0; i < args.length; i++) {
const parsed = args[i].data.result
result.push(parsed)
}
res.json(result)
})
)
} catch (error) {
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "getblockhash",
method: "getblockhash",
params: [parseInt(req.params.height)]
}
})
.then(response => {
res.json(response.data.result)
})
.catch(error => {
res.send(error.response.data.error.message)
})
}
}
)
router.get(
"/getBlockHeader/:hash",
config.blockchainRateLimit7,
async (req, res, next) => {
let verbose = false
if (req.query.verbose && req.query.verbose === "true") verbose = true
try {
let hashes = JSON.parse(req.params.hash)
if (hashes.length > 20) {
res.json({
error: "Array too large. Max 20 hashes"
})
}
const result = []
hashes = hashes.map(hash =>
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "getblockheader",
method: "getblockheader",
params: [hash, verbose]
}
}).catch(error => {
try {
return {
data: {
result: error.response.data.error.message
}
}
} catch (ex) {
return {
data: {
result: "unknown error"
}
}
}
})
)
axios.all(hashes).then(
axios.spread((...args) => {
for (let i = 0; i < args.length; i++) {
const parsed = args[i].data.result
result.push(parsed)
}
res.json(result)
})
)
} catch (error) {
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "getblockheader",
method: "getblockheader",
params: [req.params.hash, verbose]
}
})
.then(response => {
res.json(response.data.result)
})
.catch(error => {
res.send(error.response.data.error.message)
})
}
}
)
router.get(
"/getChainTips",
config.blockchainRateLimit8,
async (req, res, next) => {
requestConfig.data.id = "getchaintips"
requestConfig.data.method = "getchaintips"
requestConfig.data.params = []
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/getDifficulty",
config.blockchainRateLimit9,
async (req, res, next) => {
requestConfig.data.id = "getdifficulty"
requestConfig.data.method = "getdifficulty"
requestConfig.data.params = []
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/getMempoolAncestors/:txid",
config.blockchainRateLimit10,
async (req, res, next) => {
let verbose = false
if (req.query.verbose && req.query.verbose === "true") verbose = true
try {
let txids = JSON.parse(req.params.txid)
if (txids.length > 20) {
res.json({
error: "Array too large. Max 20 txids"
})
}
const result = []
txids = txids.map(txid =>
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "getmempoolancestors",
method: "getmempoolancestors",
params: [txid, verbose]
}
}).catch(error => {
try {
return {
data: {
result: error.response.data.error.message
}
}
} catch (ex) {
return {
data: {
result: "unknown error"
}
}
}
})
)
axios.all(txids).then(
axios.spread((...args) => {
for (let i = 0; i < args.length; i++) {
const parsed = args[i].data.result
result.push(parsed)
}
res.json(result)
})
)
} catch (error) {
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "getmempoolancestors",
method: "getmempoolancestors",
params: [req.params.txid, verbose]
}
})
.then(response => {
res.json(response.data.result)
})
.catch(error => {
res.send(error.response.data.error.message)
})
}
}
)
router.get(
"/getMempoolDescendants/:txid",
config.blockchainRateLimit11,
async (req, res, next) => {
let verbose = false
if (req.query.verbose && req.query.verbose === "true") verbose = true
try {
let txids = JSON.parse(req.params.txid)
if (txids.length > 20) {
res.json({
error: "Array too large. Max 20 txids"
})
}
const result = []
txids = txids.map(txid =>
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "getmempooldescendants",
method: "getmempooldescendants",
params: [txid, verbose]
}
}).catch(error => {
try {
return {
data: {
result: error.response.data.error.message
}
}
} catch (ex) {
return {
data: {
result: "unknown error"
}
}
}
})
)
axios.all(txids).then(
axios.spread((...args) => {
for (let i = 0; i < args.length; i++) {
const parsed = args[i].data.result
result.push(parsed)
}
res.json(result)
})
)
} catch (error) {
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "getmempooldescendants",
method: "getmempooldescendants",
params: [req.params.txid, verbose]
}
})
.then(response => {
res.json(response.data.result)
})
.catch(error => {
res.send(error.response.data.error.message)
})
}
}
)
router.get(
"/getMempoolEntry/:txid",
config.blockchainRateLimit12,
async (req, res, next) => {
try {
let txids = JSON.parse(req.params.txid)
if (txids.length > 20) {
res.json({
error: "Array too large. Max 20 txids"
})
}
const result = []
txids = txids.map(txid =>
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "getmempoolentry",
method: "getmempoolentry",
params: [txid]
}
}).catch(error => {
try {
return {
data: {
result: error.response.data.error.message
}
}
} catch (ex) {
return {
data: {
result: "unknown error"
}
}
}
})
)
axios.all(txids).then(
axios.spread((...args) => {
for (let i = 0; i < args.length; i++) {
const parsed = args[i].data.result
result.push(parsed)
}
res.json(result)
})
)
} catch (error) {
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "getmempoolentry",
method: "getmempoolentry",
params: [req.params.txid]
}
})
.then(response => {
res.json(response.data.result)
})
.catch(error => {
res.send(error.response.data.error.message)
})
}
}
)
router.get(
"/getMempoolInfo",
config.blockchainRateLimit13,
async (req, res, next) => {
requestConfig.data.id = "getmempoolinfo"
requestConfig.data.method = "getmempoolinfo"
requestConfig.data.params = []
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/getRawMempool",
config.blockchainRateLimit14,
async (req, res, next) => {
let verbose = false
if (req.query.verbose && req.query.verbose === true) verbose = true
requestConfig.data.id = "getrawmempool"
requestConfig.data.method = "getrawmempool"
requestConfig.data.params = [verbose]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/getTxOut/:txid/:n",
config.blockchainRateLimit15,
async (req, res, next) => {
let include_mempool = false
if (req.query.include_mempool && req.query.include_mempool === "true")
include_mempool = true
requestConfig.data.id = "gettxout"
requestConfig.data.method = "gettxout"
requestConfig.data.params = [
req.params.txid,
parseInt(req.params.n),
include_mempool
]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/getTxOutProof/:txids",
config.blockchainRateLimit16,
async (req, res, next) => {
requestConfig.data.id = "gettxoutproof"
requestConfig.data.method = "gettxoutproof"
requestConfig.data.params = [req.params.txids]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
//
// router.get('/preciousBlock/:hash', async (req, res, next) => {
// BitboxHTTP({
// method: 'post',
// auth: {
// username: username,
// password: password
// },
// data: {
// jsonrpc: "1.0",
// id:"preciousblock",
// method: "preciousblock",
// params: [
// req.params.hash
// ]
// }
// })
// .then((response) => {
// res.json(JSON.stringify(response.data.result));
// })
// .catch((error) => {
// res.send(error.response.data.error.message);
// });
// });
//
// router.post('/pruneBlockchain/:height', async (req, res, next) => {
// BitboxHTTP({
// method: 'post',
// auth: {
// username: username,
// password: password
// },
// data: {
// jsonrpc: "1.0",
// id:"pruneblockchain",
// method: "pruneblockchain",
// params: [
// req.params.height
// ]
// }
// })
// .then((response) => {
// res.json(response.data.result);
// })
// .catch((error) => {
// res.send(error.response.data.error.message);
// });
// });
//
// router.get('/verifyChain', async (req, res, next) => {
// BitboxHTTP({
// method: 'post',
// auth: {
// username: username,
// password: password
// },
// data: {
// jsonrpc: "1.0",
// id:"verifychain",
// method: "verifychain"
// }
// })
// .then((response) => {
// res.json(response.data.result);
// })
// .catch((error) => {
// res.send(error.response.data.error.message);
// });
// });
router.get(
"/verifyTxOutProof/:proof",
config.blockchainRateLimit17,
async (req, res, next) => {
requestConfig.data.id = "verifytxoutproof"
requestConfig.data.method = "verifytxoutproof"
requestConfig.data.params = [req.params.proof]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
module.exports = router
-106
View File
@@ -1,106 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
const axios = require("axios")
const RateLimit = require("express-rate-limit")
//const BITBOXCli = require("bitbox-sdk/lib/bitbox-sdk").default;
//const BITBOX = new BITBOXCli();
const BitboxHTTP = axios.create({
baseURL: process.env.RPC_BASEURL
})
const username = process.env.RPC_USERNAME
const password = process.env.RPC_PASSWORD
const config = {
controlRateLimit1: undefined,
controlRateLimit2: undefined
}
let i = 1
while (i < 3) {
config[`controlRateLimit${i}`] = new RateLimit({
windowMs: 60000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
i++
}
const requestConfig = {
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0"
}
}
router.get("/", config.controlRateLimit1, async (req, res, next) => {
res.json({ status: "control" })
})
router.get("/getInfo", config.controlRateLimit2, async (req, res, next) => {
requestConfig.data.id = "getinfo"
requestConfig.data.method = "getinfo"
requestConfig.data.params = []
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
})
// router.get('/getMemoryInfo', (req, res, next) => {
// BitboxHTTP({
// method: 'post',
// auth: {
// username: username,
// password: password
// },
// data: {
// jsonrpc: "1.0",
// id:"getmemoryinfo",
// method: "getmemoryinfo"
// }
// })
// .then((response) => {
// res.json(response.data.result);
// })
// .catch((error) => {
// res.send(error.response.data.error.message);
// });
// });
//
// router.get('/help', (req, res, next) => {
// BITBOX.Control.help()
// .then((result) => {
// res.json(result);
// }, (err) => { console.log(err);
// });
// });
//
// router.post('/stop', (req, res, next) => {
// BITBOX.Control.stop()
// .then((result) => {
// res.json(result);
// }, (err) => { console.log(err);
// });
// });
module.exports = router
-529
View File
@@ -1,529 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
const axios = require("axios")
const RateLimit = require("express-rate-limit")
const BITBOXCli = require("bitbox-sdk/lib/bitbox-sdk").default
const BITBOX = new BITBOXCli()
const BitboxHTTP = axios.create({
baseURL: process.env.RPC_BASEURL
})
const username = process.env.RPC_USERNAME
const password = process.env.RPC_PASSWORD
const config = {
dataRetrievalRateLimit1: undefined,
dataRetrievalRateLimit2: undefined,
dataRetrievalRateLimit3: undefined,
dataRetrievalRateLimit4: undefined,
dataRetrievalRateLimit5: undefined,
dataRetrievalRateLimit6: undefined,
dataRetrievalRateLimit7: undefined,
dataRetrievalRateLimit8: undefined,
dataRetrievalRateLimit9: undefined,
dataRetrievalRateLimit10: undefined,
dataRetrievalRateLimit11: undefined,
dataRetrievalRateLimit12: undefined,
dataRetrievalRateLimit13: undefined,
dataRetrievalRateLimit14: undefined,
dataRetrievalRateLimit15: undefined,
dataRetrievalRateLimit16: undefined,
dataRetrievalRateLimit17: undefined,
dataRetrievalRateLimit18: undefined,
dataRetrievalRateLimit19: undefined,
dataRetrievalRateLimit20: undefined,
dataRetrievalRateLimit21: undefined,
dataRetrievalRateLimit22: undefined,
dataRetrievalRateLimit23: undefined,
dataRetrievalRateLimit24: undefined,
dataRetrievalRateLimit25: undefined
}
let i = 1
while (i < 26) {
config[`dataRetrievalRateLimit${i}`] = new RateLimit({
windowMs: 60000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
i++
}
const requestConfig = {
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0"
}
}
router.get("/", config.dataRetrievalRateLimit1, async (req, res, next) => {
res.json({ status: "dataRetrieval" })
})
router.get(
"/balancesForAddress/:address",
config.dataRetrievalRateLimit2,
async (req, res, next) => {
requestConfig.data.id = "whc_getallbalancesforaddress"
requestConfig.data.method = "whc_getallbalancesforaddress"
requestConfig.data.params = [req.params.address]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
// Check for no balance error
if (
error &&
error.response &&
error.response.data &&
error.response.data.error &&
error.response.data.error.code === -8 &&
error.response.data.error.message === "Address not found"
)
res.json([])
else res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/balancesForId/:propertyId",
config.dataRetrievalRateLimit2,
async (req, res, next) => {
requestConfig.data.id = "whc_getallbalancesforid"
requestConfig.data.method = "whc_getallbalancesforid"
requestConfig.data.params = [parseInt(req.params.propertyId)]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
//res.status(500).send(error.response.data.error)
res.status(500)
return res.send(error)
}
}
)
router.get(
"/balance/:address/:propertyId",
config.dataRetrievalRateLimit3,
async (req, res, next) => {
requestConfig.data.id = "whc_getbalance"
requestConfig.data.method = "whc_getbalance"
requestConfig.data.params = [
req.params.address,
parseInt(req.params.propertyId)
]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/balancesHash/:propertyId",
config.dataRetrievalRateLimit4,
async (req, res, next) => {
requestConfig.data.id = "whc_getbalanceshash"
requestConfig.data.method = "whc_getbalanceshash"
requestConfig.data.params = [parseInt(req.params.propertyId)]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/crowdSale/:propertyId",
config.dataRetrievalRateLimit5,
async (req, res, next) => {
let verbose = false
if (req.query.verbose && req.query.verbose === "true") verbose = true
requestConfig.data.id = "whc_getcrowdsale"
requestConfig.data.method = "whc_getcrowdsale"
requestConfig.data.params = [parseInt(req.params.propertyId), verbose]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
//res.status(500).send(error.response.data.error);
res.status(500)
return res.send(error)
}
}
)
router.get(
"/currentConsensusHash",
config.dataRetrievalRateLimit6,
async (req, res, next) => {
requestConfig.data.id = "whc_getcurrentconsensushash"
requestConfig.data.method = "whc_getcurrentconsensushash"
requestConfig.data.params = []
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/grants/:propertyId",
config.dataRetrievalRateLimit8,
async (req, res, next) => {
requestConfig.data.id = "whc_getgrants"
requestConfig.data.method = "whc_getgrants"
requestConfig.data.params = [parseInt(req.params.propertyId)]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
//res.status(500).send(error.response.data.error);
res.status(500)
return res.send(error)
}
}
)
router.get("/info", config.dataRetrievalRateLimit9, async (req, res, next) => {
requestConfig.data.id = "whc_getinfo"
requestConfig.data.method = "whc_getinfo"
requestConfig.data.params = []
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
})
router.get(
"/payload/:txid",
config.dataRetrievalRateLimit10,
async (req, res, next) => {
requestConfig.data.id = "whc_getpayload"
requestConfig.data.method = "whc_getpayload"
requestConfig.data.params = [req.params.txid]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/property/:propertyId",
config.dataRetrievalRateLimit11,
async (req, res, next) => {
requestConfig.data.id = "whc_getproperty"
requestConfig.data.method = "whc_getproperty"
requestConfig.data.params = [parseInt(req.params.propertyId)]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/seedBlocks/:startBlock/:endBlock",
config.dataRetrievalRateLimit12,
async (req, res, next) => {
requestConfig.data.id = "whc_getseedblocks"
requestConfig.data.method = "whc_getseedblocks"
requestConfig.data.params = [
parseInt(req.params.startBlock),
parseInt(req.params.endBlock)
]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/STO/:txid/:recipientFilter",
config.dataRetrievalRateLimit13,
async (req, res, next) => {
requestConfig.data.id = "whc_getsto"
requestConfig.data.method = "whc_getsto"
requestConfig.data.params = [req.params.txid, req.params.recipientFilter]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/transaction/:txid",
config.dataRetrievalRateLimit14,
async (req, res, next) => {
requestConfig.data.id = "whc_gettransaction"
requestConfig.data.method = "whc_gettransaction"
requestConfig.data.params = [req.params.txid]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
//res.status(500).send(error.response.data.error);
res.status(500)
return res.send(error)
}
}
)
router.get(
"/blockTransactions/:index",
config.dataRetrievalRateLimit15,
async (req, res, next) => {
requestConfig.data.id = "whc_listblocktransactions"
requestConfig.data.method = "whc_listblocktransactions"
requestConfig.data.params = [parseInt(req.params.index)]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/pendingTransactions",
config.dataRetrievalRateLimit16,
async (req, res, next) => {
const params = []
if (req.query.address) params.push(req.query.address)
requestConfig.data.id = "whc_listpendingtransactions"
requestConfig.data.method = "whc_listpendingtransactions"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500)
return res.send(error)
//res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/properties",
config.dataRetrievalRateLimit17,
async (req, res, next) => {
requestConfig.data.id = "whc_listproperties"
requestConfig.data.method = "whc_listproperties"
requestConfig.data.params = []
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/frozenBalance/:address/:propertyId",
config.dataRetrievalRateLimit18,
async (req, res, next) => {
const params = [
BITBOX.Address.toCashAddress(req.params.address),
parseInt(req.params.propertyId)
]
requestConfig.data.id = "whc_getfrozenbalance"
requestConfig.data.method = "whc_getfrozenbalance"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/frozenBalanceForAddress/:address",
config.dataRetrievalRateLimit19,
async (req, res, next) => {
const params = [BITBOX.Address.toCashAddress(req.params.address)]
requestConfig.data.id = "whc_getfrozenbalanceforaddress"
requestConfig.data.method = "whc_getfrozenbalanceforaddress"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/frozenBalanceForId/:propertyId",
config.dataRetrievalRateLimit20,
async (req, res, next) => {
const params = [parseInt(req.params.propertyId)]
requestConfig.data.id = "whc_getfrozenbalanceforid"
requestConfig.data.method = "whc_getfrozenbalanceforid"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/ERC721AddressTokens/:address/:propertyId",
config.dataRetrievalRateLimit21,
async (req, res, next) => {
const params = [req.params.address, req.params.propertyId]
requestConfig.data.id = "whc_getERC721AddressTokens"
requestConfig.data.method = "whc_getERC721AddressTokens"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/ERC721PropertyDestroyTokens/:propertyId",
config.dataRetrievalRateLimit22,
async (req, res, next) => {
const params = [req.params.propertyId]
requestConfig.data.id = "whc_getERC721PropertyDestroyTokens"
requestConfig.data.method = "whc_getERC721PropertyDestroyTokens"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/ERC721PropertyNews/:propertyId",
config.dataRetrievalRateLimit23,
async (req, res, next) => {
const params = [req.params.propertyId]
requestConfig.data.id = "whc_getERC721PropertyNews"
requestConfig.data.method = "whc_getERC721PropertyNews"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/ERC721TokenNews/:propertyId/:tokenId",
config.dataRetrievalRateLimit24,
async (req, res, next) => {
const params = [req.params.propertyId, req.params.tokenId]
requestConfig.data.id = "whc_getERC721TokenNews"
requestConfig.data.method = "whc_getERC721TokenNews"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/ownerOfERC721Token/:propertyId/:tokenId/:address",
config.dataRetrievalRateLimit25,
async (req, res, next) => {
const params = [
req.params.propertyId,
req.params.tokenId,
req.params.address
]
requestConfig.data.id = "whc_ownerOfERC721Token"
requestConfig.data.method = "whc_ownerOfERC721Token"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
module.exports = router
-75
View File
@@ -1,75 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
//const axios = require("axios");
const RateLimit = require("express-rate-limit")
//const BITBOXCli = require("bitbox-sdk/lib/bitbox-sdk").default;
//const BITBOX = new BITBOXCli();
//const BitboxHTTP = axios.create({
// baseURL: process.env.RPC_BASEURL,
//});
//const username = process.env.RPC_USERNAME;
//const password = process.env.RPC_PASSWORD;
const config = {
generatingRateLimit1: undefined
}
let i = 1
while (i < 2) {
config[`generatingRateLimit${i}`] = new RateLimit({
windowMs: 60000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
i++
}
router.get("/", config.generatingRateLimit1, (req, res, next) => {
res.json({ status: "generating" })
})
//
// router.post('/generateToAddress/:nblocks/:address', (req, res, next) => {
// let maxtries = 1000000;
// if(req.query.maxtries) {
// maxtries = parseInt(req.query.maxtries);
// }
//
// BitboxHTTP({
// method: 'post',
// auth: {
// username: username,
// password: password
// },
// data: {
// jsonrpc: "1.0",
// id:"generatetoaddress",
// method: "generatetoaddress",
// params: [
// req.params.nblocks,
// req.params.address,
// maxtries
// ]
// }
// })
// .then((response) => {
// res.json(response.data.result);
// })
// .catch((error) => {
// res.send(error.response.data.error.message);
// });
// });
module.exports = router
-27
View File
@@ -1,27 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
const RateLimit = require("express-rate-limit")
const healthCheckRateLimit = new RateLimit({
windowMs: 60000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
/* GET home page. */
router.get("/", healthCheckRateLimit, (req, res, next) => {
res.json({ status: "winning" })
})
module.exports = router
-35
View File
@@ -1,35 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
const RateLimit = require("express-rate-limit")
const config = {
indexRateLimit1: undefined
}
let i = 1
while (i < 2) {
config[`indexRateLimit${i}`] = new RateLimit({
windowMs: 60 * 60 * 1000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
i++
}
/* GET home page. */
router.get("/v1", config.indexRateLimit1, (req, res, next) => {
res.render("swagger")
})
module.exports = router
-145
View File
@@ -1,145 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
const axios = require("axios")
const RateLimit = require("express-rate-limit")
//const BITBOXCli = require("bitbox-sdk/lib/bitbox-sdk").default;
//const BITBOX = new BITBOXCli();
const BitboxHTTP = axios.create({
baseURL: process.env.RPC_BASEURL
})
const username = process.env.RPC_USERNAME
const password = process.env.RPC_PASSWORD
const config = {
miningRateLimit1: undefined,
miningRateLimit2: undefined,
miningRateLimit3: undefined
}
let i = 1
while (i < 4) {
config[`miningRateLimit${i}`] = new RateLimit({
windowMs: 60000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
i++
}
const requestConfig = {
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0"
}
}
router.get("/", config.miningRateLimit1, async (req, res, next) => {
res.json({ status: "mining" })
})
//
// router.get('/getBlockTemplate/:templateRequest', (req, res, next) => {
// BitboxHTTP({
// method: 'post',
// auth: {
// username: username,
// password: password
// },
// data: {
// jsonrpc: "1.0",
// id:"getblocktemplate",
// method: "getblocktemplate",
// params: [
// req.params.templateRequest
// ]
// }
// })
// .then((response) => {
// res.json(response.data.result);
// })
// .catch((error) => {
// res.send(error.response.data.error.message);
// });
// });
router.get(
"/getMiningInfo",
config.miningRateLimit2,
async (req, res, next) => {
requestConfig.data.id = "getmininginfo"
requestConfig.data.method = "getmininginfo"
requestConfig.data.params = []
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.get(
"/getNetworkHashps",
config.miningRateLimit3,
async (req, res, next) => {
requestConfig.data.id = "getnetworkhashps"
requestConfig.data.method = "getnetworkhashps"
requestConfig.data.params = []
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
//
// router.post('/submitBlock/:hex', (req, res, next) => {
// let parameters = '';
// if(req.query.parameters && req.query.parameters !== '') {
// parameters = true;
// }
//
// BitboxHTTP({
// method: 'post',
// auth: {
// username: username,
// password: password
// },
// data: {
// jsonrpc: "1.0",
// id:"submitblock",
// method: "submitblock",
// params: [
// req.params.hex,
// parameters
// ]
// }
// })
// .then((response) => {
// res.json(response.data.result);
// })
// .catch((error) => {
// res.send(error.response.data.error.message);
// });
// });
module.exports = router
-202
View File
@@ -1,202 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
//const axios = require("axios");
const RateLimit = require("express-rate-limit")
//const BITBOXCli = require("bitbox-sdk/lib/bitbox-sdk").default;
//const BITBOX = new BITBOXCli();
//const BitboxHTTP = axios.create({
// baseURL: process.env.RPC_BASEURL,
//});
//const username = process.env.RPC_USERNAME;
//const password = process.env.RPC_PASSWORD;
const config = {
networkRateLimit1: undefined
}
let i = 1
while (i < 2) {
config[`networkRateLimit${i}`] = new RateLimit({
windowMs: 60000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
i++
}
router.get("/", config.networkRateLimit1, (req, res, next) => {
res.json({ status: "network" })
})
// router.post('/addNode/:node/:command', (req, res, next) => {
// BITBOX.Network.addNode(req.params.node, req.params.command)
// .then((result) => {
// res.json(result);
// }, (err) => { console.log(err);
// });
// });
//
// router.post('/clearBanned', (req, res, next) => {
// BITBOX.Network.clearBanned()
// .then((result) => {
// res.json(result);
// }, (err) => { console.log(err);
// });
// });
//
// router.post('/disconnectNode/:address/:nodeid', (req, res, next) => {
// BITBOX.Network.disconnectNode(req.params.address, req.params.nodeid)
// .then((result) => {
// res.json(result);
// }, (err) => { console.log(err);
// });
// });
//
// router.get('/getAddedNodeInfo/:node', (req, res, next) => {
// BITBOX.Network.getAddedNodeInfo(req.params.node)
// .then((result) => {
// res.json(result);
// }, (err) => { console.log(err);
// });
// });
//
// router.get('/getConnectionCount', (req, res, next) => {
// BitboxHTTP({
// method: 'post',
// auth: {
// username: username,
// password: password
// },
// data: {
// jsonrpc: "1.0",
// id:"getconnectioncount",
// method: "getconnectioncount"
// }
// })
// .then((response) => {
// res.json(response.data.result);
// })
// .catch((error) => {
// res.send(error.response.data.error.message);
// });
// });
//
// router.get('/getNetTotals', (req, res, next) => {
// BitboxHTTP({
// method: 'post',
// auth: {
// username: username,
// password: password
// },
// data: {
// jsonrpc: "1.0",
// id:"getnettotals",
// method: "getnettotals"
// }
// })
// .then((response) => {
// res.json(response.data.result);
// })
// .catch((error) => {
// res.send(error.response.data.error.message);
// });
// });
//
// router.get('/getNetworkInfo', (req, res, next) => {
// BitboxHTTP({
// method: 'post',
// auth: {
// username: username,
// password: password
// },
// data: {
// jsonrpc: "1.0",
// id:"getnetworkinfo",
// method: "getnetworkinfo"
// }
// })
// .then((response) => {
// res.json(response.data.result);
// })
// .catch((error) => {
// res.send(error.response.data.error.message);
// });
// });
//
// router.get('/getPeerInfo', (req, res, next) => {
// BitboxHTTP({
// method: 'post',
// auth: {
// username: username,
// password: password
// },
// data: {
// jsonrpc: "1.0",
// id:"getpeerinfo",
// method: "getpeerinfo"
// }
// })
// .then((response) => {
// res.json(response.data.result);
// })
// .catch((error) => {
// res.send(error.response.data.error.message);
// });
// });
//
// router.get('/ping', (req, res, next) => {
// BitboxHTTP({
// method: 'post',
// auth: {
// username: username,
// password: password
// },
// data: {
// jsonrpc: "1.0",
// id:"ping",
// method: "ping"
// }
// })
// .then((response) => {
// res.json(JSON.stringify(response.data.result));
// })
// .catch((error) => {
// res.send(error.response.data.error.message);
// });
// });
//
// router.post('/setBan/:subnet/:command', (req, res, next) => {
// // TODO finish this
// BITBOX.Network.getConnectionCount(req.params.subnet, req.params.command)
// .then((result) => {
// res.json(result);
// }, (err) => { console.log(err);
// });
// });
//
// router.post('/setNetworkActive/:state', (req, res, next) => {
// let state = true;
// if(req.params.state && req.params.state === 'false') {
// state = false;
// }
// BITBOX.Network.getConnectionCount(state)
// .then((result) => {
// res.json(result);
// }, (err) => { console.log(err);
// });
// });
module.exports = router
-480
View File
@@ -1,480 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
const axios = require("axios")
const RateLimit = require("express-rate-limit")
const BitboxHTTP = axios.create({
baseURL: process.env.RPC_BASEURL
})
const username = process.env.RPC_USERNAME
const password = process.env.RPC_PASSWORD
const BITBOXCli = require("bitbox-sdk/lib/bitbox-sdk").default
const BITBOX = new BITBOXCli()
const config = {
payloadCreationRateLimit1: undefined,
payloadCreationRateLimit2: undefined,
payloadCreationRateLimit3: undefined,
payloadCreationRateLimit4: undefined,
payloadCreationRateLimit5: undefined,
payloadCreationRateLimit6: undefined,
payloadCreationRateLimit7: undefined,
payloadCreationRateLimit8: undefined,
payloadCreationRateLimit9: undefined,
payloadCreationRateLimit10: undefined,
payloadCreationRateLimit11: undefined,
payloadCreationRateLimit12: undefined,
payloadCreationRateLimit13: undefined,
payloadCreationRateLimit14: undefined,
payloadCreationRateLimit15: undefined,
payloadCreationRateLimit16: undefined,
payloadCreationRateLimit17: undefined,
payloadCreationRateLimit18: undefined,
payloadCreationRateLimit19: undefined
}
let i = 1
while (i < 20) {
config[`payloadCreationRateLimit${i}`] = new RateLimit({
windowMs: 60000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
i++
}
const requestConfig = {
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0"
}
}
router.get("/", config.payloadCreationRateLimit1, async (req, res, next) => {
res.json({ status: "payloadCreation" })
})
router.get(
"/burnBCH",
config.payloadCreationRateLimit2,
async (req, res, next) => {
requestConfig.data.id = "whc_createpayload_burnbch"
requestConfig.data.method = "whc_createpayload_burnbch"
requestConfig.data.params = []
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/changeIssuer/:propertyId",
config.payloadCreationRateLimit2,
async (req, res, next) => {
requestConfig.data.id = "whc_createpayload_changeissuer"
requestConfig.data.method = "whc_createpayload_changeissuer"
requestConfig.data.params = [parseInt(req.params.propertyId)]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/closeCrowdSale/:propertyId",
config.payloadCreationRateLimit3,
async (req, res, next) => {
requestConfig.data.id = "whc_createpayload_closecrowdsale"
requestConfig.data.method = "whc_createpayload_closecrowdsale"
requestConfig.data.params = [parseInt(req.params.propertyId)]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/grant/:propertyId/:amount",
config.payloadCreationRateLimit4,
async (req, res, next) => {
const params = [parseInt(req.params.propertyId), req.params.amount]
if (req.query.memo) params.push(req.query.memo)
requestConfig.data.id = "whc_createpayload_grant"
requestConfig.data.method = "whc_createpayload_grant"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
//res.status(500).send(error.response.data.error);
res.status(500)
return res.send(error)
}
}
)
router.post(
"/crowdsale/:ecosystem/:propertyPrecision/:previousId/:category/:subcategory/:name/:url/:data/:propertyIdDesired/:tokensPerUnit/:deadline/:earlyBonus/:undefine/:totalNumber",
config.payloadCreationRateLimit6,
async (req, res, next) => {
// Validate deadline
const now = new Date()
const OneHundredYears = 1000 * 60 * 60 * 24 * 365 * 100
const OneHundredYearsFromNow = now.getTime() + OneHundredYears
const OneHundredYearsFromNowUnixTimestamp = Math.floor(
OneHundredYearsFromNow / 1000
)
if (req.params.deadline > OneHundredYearsFromNowUnixTimestamp) {
res.status(422)
res.send(
"Invalid deadline. Unix timestamp should be less than 100 years from now. Unix timestamp === JavaScript getTime()/1000"
)
return
}
requestConfig.data.id = "whc_createpayload_issuancecrowdsale"
requestConfig.data.method = "whc_createpayload_issuancecrowdsale"
requestConfig.data.params = [
parseInt(req.params.ecosystem),
parseInt(req.params.propertyPrecision),
parseInt(req.params.previousId),
req.params.category,
req.params.subcategory,
req.params.name,
req.params.url,
req.params.data,
parseInt(req.params.propertyIdDesired),
req.params.tokensPerUnit,
parseInt(req.params.deadline),
parseInt(req.params.earlyBonus),
parseInt(req.params.undefine),
req.params.totalNumber
]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/fixed/:ecosystem/:propertyPrecision/:previousId/:category/:subcategory/:name/:url/:data/:amount",
config.payloadCreationRateLimit7,
async (req, res, next) => {
requestConfig.data.id = "whc_createpayload_issuancefixed"
requestConfig.data.method = "whc_createpayload_issuancefixed"
requestConfig.data.params = [
parseInt(req.params.ecosystem),
parseInt(req.params.propertyPrecision),
parseInt(req.params.previousId),
req.params.category,
req.params.subcategory,
req.params.name,
req.params.url,
req.params.data,
req.params.amount
]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/managed/:ecosystem/:propertyPrecision/:previousId/:category/:subcategory/:name/:url/:data",
config.payloadCreationRateLimit8,
async (req, res, next) => {
requestConfig.data.id = "whc_createpayload_issuancemanaged"
requestConfig.data.method = "whc_createpayload_issuancemanaged"
requestConfig.data.params = [
parseInt(req.params.ecosystem),
parseInt(req.params.propertyPrecision),
parseInt(req.params.previousId),
req.params.category,
req.params.subcategory,
req.params.name,
req.params.url,
req.params.data
]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/participateCrowdSale/:amount",
config.payloadCreationRateLimit9,
async (req, res, next) => {
requestConfig.data.id = "whc_createpayload_particrowdsale"
requestConfig.data.method = "whc_createpayload_particrowdsale"
requestConfig.data.params = [req.params.amount]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/revoke/:propertyId/:amount",
config.payloadCreationRateLimit10,
async (req, res, next) => {
const params = [parseInt(req.params.propertyId), req.params.amount]
if (req.query.memo) params.push(req.query.memo)
requestConfig.data.id = "whc_createpayload_revoke"
requestConfig.data.method = "whc_createpayload_revoke"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/sendAll/:ecosystem",
config.payloadCreationRateLimit11,
async (req, res, next) => {
requestConfig.data.id = "whc_createpayload_sendall"
requestConfig.data.method = "whc_createpayload_sendall"
requestConfig.data.params = [parseInt(req.params.ecosystem)]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/simpleSend/:propertyId/:amount",
config.payloadCreationRateLimit12,
async (req, res, next) => {
requestConfig.data.id = "whc_createpayload_simplesend"
requestConfig.data.method = "whc_createpayload_simplesend"
requestConfig.data.params = [
parseInt(req.params.propertyId),
req.params.amount
]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/STO/:propertyId/:amount",
config.payloadCreationRateLimit13,
async (req, res, next) => {
const params = [parseInt(req.params.propertyId), req.params.amount]
if (req.query.distributionProperty)
params.push(parseInt(req.query.distributionProperty))
requestConfig.data.id = "whc_createpayload_sto"
requestConfig.data.method = "whc_createpayload_sto"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/freeze/:toAddress/:propertyId",
config.payloadCreationRateLimit14,
async (req, res, next) => {
const params = [
BITBOX.Address.toCashAddress(req.params.toAddress),
parseInt(req.params.propertyId),
"100"
]
requestConfig.data.id = "whc_createpayload_freeze"
requestConfig.data.method = "whc_createpayload_freeze"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/unfreeze/:toAddress/:propertyId",
config.payloadCreationRateLimit15,
async (req, res, next) => {
const params = [
BITBOX.Address.toCashAddress(req.params.toAddress),
parseInt(req.params.propertyId),
"100"
]
requestConfig.data.id = "whc_createpayload_unfreeze"
requestConfig.data.method = "whc_createpayload_unfreeze"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/issueERC721Property/:name/:symbol/:data/:url/:totalNumber",
config.payloadCreationRateLimit16,
async (req, res, next) => {
const params = [
req.params.name,
req.params.symbol,
req.params.data,
req.params.url,
req.params.totalNumber
]
requestConfig.data.id = "whc_createpayload_issueERC721property"
requestConfig.data.method = "whc_createpayload_issueERC721property"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/issueERC721Token/:propertyId/:tokenId/:attributes/:url",
config.payloadCreationRateLimit17,
async (req, res, next) => {
const params = [
req.params.propertyId,
req.params.tokenId,
req.params.attributes,
req.params.url
]
requestConfig.data.id = "whc_createpayload_issueERC721token"
requestConfig.data.method = "whc_createpayload_issueERC721token"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/transferERC721Token/:owner/:receiver/:propertyId",
config.payloadCreationRateLimit18,
async (req, res, next) => {
const params = [
req.params.owner,
req.params.receiver,
req.params.propertyId
]
if (req.query.tokenId) params.push(req.query.tokenId)
requestConfig.data.id = "whc_transferERC721Token"
requestConfig.data.method = "whc_transferERC721Token"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/destroyERC721Token/:propertyId",
config.payloadCreationRateLimit19,
async (req, res, next) => {
const params = [req.params.propertyId]
if (req.query.tokenId) params.push(req.query.tokenId)
requestConfig.data.id = "whc_createpayload_destroyERC721token"
requestConfig.data.method = "whc_createpayload_destroyERC721token"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
module.exports = router
-511
View File
@@ -1,511 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
const axios = require("axios")
const RateLimit = require("express-rate-limit")
//const BITBOXCli = require("bitbox-sdk/lib/bitbox-sdk").default;
//const BITBOX = new BITBOXCli();
const BitboxHTTP = axios.create({
baseURL: process.env.RPC_BASEURL
})
const username = process.env.RPC_USERNAME
const password = process.env.RPC_PASSWORD
const config = {
rawTransactionsRateLimit1: undefined,
rawTransactionsRateLimit2: undefined,
rawTransactionsRateLimit3: undefined,
rawTransactionsRateLimit4: undefined,
rawTransactionsRateLimit5: undefined,
rawTransactionsRateLimit6: undefined,
rawTransactionsRateLimit7: undefined,
rawTransactionsRateLimit8: undefined,
rawTransactionsRateLimit9: undefined,
rawTransactionsRateLimit10: undefined,
rawTransactionsRateLimit11: undefined
}
let i = 1
while (i < 12) {
config[`rawTransactionsRateLimit${i}`] = new RateLimit({
windowMs: 60000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
i++
}
//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("/", config.rawTransactionsRateLimit1, (req, res, next) => {
res.json({ status: "rawtransactions" })
})
router.get(
"/decodeRawTransaction/:hex",
config.rawTransactionsRateLimit2,
(req, res, next) => {
try {
let transactions = JSON.parse(req.params.hex)
if (transactions.length > 20) {
res.json({
error: "Array too large. Max 20 transactions"
})
}
const result = []
transactions = transactions.map(transaction =>
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "decoderawtransaction",
method: "decoderawtransaction",
params: [transaction]
}
}).catch(error => {
try {
return {
data: {
result: error.response.data.error.message
}
}
} catch (ex) {
return {
data: {
result: "unknown error"
}
}
}
})
)
axios.all(transactions).then(
axios.spread((...args) => {
for (let i = 0; i < args.length; i++) {
const parsed = args[i].data.result
result.push(parsed)
}
res.json(result)
})
)
} catch (error) {
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "decoderawtransaction",
method: "decoderawtransaction",
params: [req.params.hex]
}
})
.then(response => {
res.json(response.data.result)
})
.catch(error => {
res.send(error.response.data.error.message)
})
}
}
)
router.get(
"/decodeScript/:script",
config.rawTransactionsRateLimit3,
(req, res, next) => {
try {
let scripts = JSON.parse(req.params.script)
if (scripts.length > 20) {
res.json({
error: "Array too large. Max 20 scripts"
})
}
const result = []
scripts = scripts.map(script =>
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "decodescript",
method: "decodescript",
params: [script]
}
}).catch(error => {
try {
return {
data: {
result: error.response.data.error.message
}
}
} catch (ex) {
return {
data: {
result: "unknown error"
}
}
}
})
)
axios.all(scripts).then(
axios.spread((...args) => {
for (let i = 0; i < args.length; i++) {
const parsed = args[i].data.result
result.push(parsed)
}
res.json(result)
})
)
} catch (error) {
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "decodescript",
method: "decodescript",
params: [req.params.script]
}
})
.then(response => {
res.json(response.data.result)
})
.catch(error => {
res.send(error.response.data.error.message)
})
}
}
)
router.get(
"/getRawTransaction/:txid",
config.rawTransactionsRateLimit4,
(req, res, next) => {
let verbose = 0
if (req.query.verbose && req.query.verbose === "true") verbose = 1
try {
let txids = JSON.parse(req.params.txid)
if (txids.length > 20) {
res.json({
error: "Array too large. Max 20 txids"
})
}
const result = []
txids = txids.map(txid =>
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "getrawtransaction",
method: "getrawtransaction",
params: [txid, verbose]
}
}).catch(error => {
try {
return {
data: {
result: error.response.data.error.message
}
}
} catch (ex) {
return {
data: {
result: "unknown error"
}
}
}
})
)
axios.all(txids).then(
axios.spread((...args) => {
for (let i = 0; i < args.length; i++) {
const parsed = args[i].data.result
result.push(parsed)
}
res.json(result)
})
)
} catch (error) {
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "getrawtransaction",
method: "getrawtransaction",
params: [req.params.txid, verbose]
}
})
.then(response => {
res.json(response.data.result)
})
.catch(error => {
res.send(error.response.data.error.message)
})
}
}
)
router.post(
"/sendRawTransaction/:hex",
config.rawTransactionsRateLimit5,
(req, res, next) => {
try {
let transactions = JSON.parse(req.params.hex)
if (transactions.length > 20) {
res.json({
error: "Array too large. Max 20 transactions"
})
}
const result = []
transactions = transactions.map(transaction =>
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "sendrawtransaction",
method: "sendrawtransaction",
params: [transaction]
}
}).catch(error => {
try {
return {
data: {
result: error.response.data.error.message
}
}
} catch (ex) {
return {
data: {
result: "unknown error"
}
}
}
})
)
axios.all(transactions).then(
axios.spread((...args) => {
for (let i = 0; i < args.length; i++) {
const parsed = args[i].data.result
result.push(parsed)
}
res.json(result)
})
)
} catch (error) {
BitboxHTTP({
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0",
id: "sendrawtransaction",
method: "sendrawtransaction",
params: [req.params.hex]
}
})
.then(response => {
res.json(response.data.result)
})
.catch(error => {
res.send(error.response.data.error.message)
})
}
}
)
router.post(
"/change/:rawtx/:prevTxs/:destination/:fee",
config.rawTransactionsRateLimit6,
async (req, res, next) => {
try {
const params = [
req.params.rawtx,
JSON.parse(req.params.prevTxs),
req.params.destination,
parseFloat(req.params.fee)
]
if (req.query.position) params.push(parseInt(req.query.position))
requestConfig.data.id = "whc_createrawtx_change"
requestConfig.data.method = "whc_createrawtx_change"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
} catch (err) {
// console.log(`Error in /change: `)
res.status(500)
res.send(`Error in /change: ${err.message}`)
}
}
)
router.post(
"/input/:rawTx/:txid/:n",
config.rawTransactionsRateLimit7,
async (req, res, next) => {
requestConfig.data.id = "whc_createrawtx_input"
requestConfig.data.method = "whc_createrawtx_input"
requestConfig.data.params = [
req.params.rawTx,
req.params.txid,
parseInt(req.params.n)
]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/opReturn/:rawTx/:payload",
config.rawTransactionsRateLimit8,
async (req, res, next) => {
requestConfig.data.id = "whc_createrawtx_opreturn"
requestConfig.data.method = "whc_createrawtx_opreturn"
requestConfig.data.params = [req.params.rawTx, req.params.payload]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/reference/:rawTx/:destination",
config.rawTransactionsRateLimit9,
async (req, res, next) => {
const params = [req.params.rawTx, req.params.destination]
if (req.query.amount) params.push(req.query.amount)
requestConfig.data.id = "whc_createrawtx_reference"
requestConfig.data.method = "whc_createrawtx_reference"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
router.post(
"/decodeTransaction/:rawTx",
config.rawTransactionsRateLimit10,
async (req, res, next) => {
const params = [req.params.rawTx]
if (req.query.prevTxs) params.push(JSON.parse(req.query.prevTxs))
if (req.query.height) params.push(req.query.height)
requestConfig.data.id = "whc_decodetransaction"
requestConfig.data.method = "whc_decodetransaction"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error.message)
}
}
)
router.post(
"/create/:inputs/:outputs",
config.rawTransactionsRateLimit11,
async (req, res, next) => {
const params = [
JSON.parse(req.params.inputs),
JSON.parse(req.params.outputs)
]
if (req.query.locktime) params.push(req.query.locktime)
requestConfig.data.id = "createrawtransaction"
requestConfig.data.method = "createrawtransaction"
requestConfig.data.params = params
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error.message)
}
}
)
module.exports = router
-213
View File
@@ -1,213 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
const axios = require("axios")
const RateLimit = require("express-rate-limit")
const bitdbToken = process.env.BITDB_TOKEN
const bitboxproxy = require("slpjs").bitbox
const utils = require("slpjs").utils
const BITBOXCli = require("bitbox-sdk/lib/bitbox-sdk").default
const BITBOX = new BITBOXCli()
const config = {
slpRateLimit1: undefined,
slpRateLimit2: undefined,
slpRateLimit3: undefined,
slpRateLimit4: undefined,
slpRateLimit5: undefined,
slpRateLimit6: undefined,
slpRateLimit7: undefined
}
let i = 1
while (i < 8) {
config[`slpRateLimit${i}`] = new RateLimit({
windowMs: 60000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
i++
}
router.get("/", config.slpRateLimit1, async (req, res, next) => {
res.json({ status: "slp" })
})
router.get("/list", config.slpRateLimit2, async (req, res, next) => {
try {
const query = {
v: 3,
q: {
find: { "out.h1": "534c5000", "out.s3": "GENESIS" },
limit: 1000
},
r: {
f:
'[ .[] | { id: .tx.h, timestamp: (.blk.t | strftime("%Y-%m-%d %H:%M")), symbol: .out[0].s4, name: .out[0].s5, document: .out[0].s6 } ]'
}
}
const s = JSON.stringify(query)
const b64 = Buffer.from(s).toString("base64")
const url = `https://bitdb.network/q/${b64}`
const header = {
headers: { key: bitdbToken }
}
const tokenRes = await axios.get(url, header)
const tokens = tokenRes.data.c
if (tokenRes.data.u && tokenRes.data.u.length) tokens.concat(tokenRes.u)
res.json(tokens.reverse())
return tokens
} catch (err) {
res.status(500).send(err.response.data.error)
}
})
router.get("/list/:tokenId", config.slpRateLimit3, async (req, res, next) => {
try {
const query = {
v: 3,
q: {
find: { "out.h1": "534c5000", "out.s3": "GENESIS" },
limit: 1000
},
r: {
f:
'[ .[] | { id: .tx.h, timestamp: (.blk.t | strftime("%Y-%m-%d %H:%M")), symbol: .out[0].s4, name: .out[0].s5, document: .out[0].s6 } ]'
}
}
const s = JSON.stringify(query)
const b64 = Buffer.from(s).toString("base64")
const url = `https://bitdb.network/q/${b64}`
const header = {
headers: { key: bitdbToken }
}
const tokenRes = await axios.get(url, header)
const tokens = tokenRes.data.c
if (tokenRes.data.u && tokenRes.data.u.length) tokens.concat(tokenRes.u)
tokens.forEach(token => {
if (token.id === req.params.tokenId) return res.json(token)
})
} catch (err) {
res.status(500).send(err.response.data.error)
}
})
router.get(
"/balancesForAddress/:address",
config.slpRateLimit4,
async (req, res, next) => {
try {
const slpAddr = utils.toSlpAddress(req.params.address)
const balances = await bitboxproxy.getAllTokenBalances(slpAddr)
balances.slpAddress = slpAddr
balances.cashAddress = utils.toCashAddress(slpAddr)
balances.legacyAddress = BITBOX.Address.toLegacyAddress(
balances.cashAddress
)
return res.json(balances)
} catch (err) {
res.status(500).send(err.response.data.error)
}
}
)
router.get(
"/balance/:address/:tokenId",
config.slpRateLimit5,
async (req, res, next) => {
try {
const slpAddr = utils.toSlpAddress(req.params.address)
const balances = await bitboxproxy.getAllTokenBalances(slpAddr)
const query = {
v: 3,
q: {
find: { "out.h1": "534c5000", "out.s3": "GENESIS" },
limit: 1000
},
r: {
f:
'[ .[] | { id: .tx.h, timestamp: (.blk.t | strftime("%Y-%m-%d %H:%M")), symbol: .out[0].s4, name: .out[0].s5, document: .out[0].s6 } ]'
}
}
const s = JSON.stringify(query)
const b64 = Buffer.from(s).toString("base64")
const url = `https://bitdb.network/q/${b64}`
const header = {
headers: { key: bitdbToken }
}
const tokenRes = await axios.get(url, header)
const tokens = tokenRes.data.c
if (tokenRes.data.u && tokenRes.data.u.length) tokens.concat(tokenRes.u)
let t
tokens.forEach(token => {
if (token.id === req.params.tokenId) t = token
})
const obj = {}
obj.id = t.id
obj.timestamp = t.timestamp
obj.symbol = t.symbol
obj.name = t.name
obj.document = t.document
obj.balance = balances[req.params.tokenId]
obj.slpAddress = slpAddr
obj.cashAddress = utils.toCashAddress(slpAddr)
obj.legacyAddress = BITBOX.Address.toLegacyAddress(obj.cashAddress)
return res.json(obj)
} catch (err) {
res.status(500).send(err.response.data.error)
}
}
)
router.get(
"/address/convert/:address",
config.slpRateLimit6,
async (req, res, next) => {
try {
const slpAddr = utils.toSlpAddress(req.params.address)
const obj = {}
obj.slpAddress = slpAddr
obj.cashAddress = utils.toCashAddress(slpAddr)
obj.legacyAddress = BITBOX.Address.toLegacyAddress(obj.cashAddress)
return res.json(obj)
} catch (err) {
res.status(500).send(err.response.data.error)
}
}
)
router.get(
"/balancesForToken/:tokenId",
config.slpRateLimit7,
async (req, res, next) => {
try {
const balances = "use v2"
return res.json(balances)
} catch (err) {
res.status(500).send(err.response.data.error)
}
}
)
module.exports = router
-93
View File
@@ -1,93 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
const axios = require("axios")
const RateLimit = require("express-rate-limit")
const BITBOXCli = require("bitbox-sdk/lib/bitbox-sdk").default
const BITBOX = new BITBOXCli()
const config = {
transactionRateLimit1: undefined,
transactionRateLimit2: undefined
}
const processInputs = tx => {
if (tx.vin) {
tx.vin.forEach(vin => {
if (!vin.coinbase) {
const address = vin.addr
vin.legacyAddress = BITBOX.Address.toLegacyAddress(address)
vin.cashAddress = BITBOX.Address.toCashAddress(address)
vin.value = vin.valueSat
delete vin.addr
delete vin.valueSat
delete vin.doubleSpentTxID
}
})
}
}
let i = 1
while (i < 6) {
config[`transactionRateLimit${i}`] = new RateLimit({
windowMs: 60000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
i++
}
router.get("/", config.transactionRateLimit1, (req, res, next) => {
res.json({ status: "transaction" })
})
router.get("/details/:txid", config.transactionRateLimit1, (req, res, next) => {
try {
let txs = JSON.parse(req.params.txid)
if (txs.length > 20) {
res.json({
error: "Array too large. Max 20 txids"
})
}
const result = []
txs = txs.map(tx => axios.get(`${process.env.BITCOINCOM_BASEURL}tx/${tx}`))
axios.all(txs).then(
axios.spread((...args) => {
for (let i = 0; i < args.length; i++) {
const parsed = args[i].data
result.push(parsed)
}
result.forEach(tx => {
processInputs(tx)
})
res.json(result)
})
)
} catch (error) {
axios
.get(`${process.env.BITCOINCOM_BASEURL}tx/${req.params.txid}`)
.then(response => {
const parsed = response.data
if (parsed) processInputs(parsed)
res.json(parsed)
})
.catch(error => {
res.send(error.response.data.error.message)
})
}
})
module.exports = router
-70
View File
@@ -1,70 +0,0 @@
"use strict"
const express = require("express")
const router = express.Router()
const axios = require("axios")
const RateLimit = require("express-rate-limit")
const BitboxHTTP = axios.create({
baseURL: process.env.RPC_BASEURL
})
const username = process.env.RPC_USERNAME
const password = process.env.RPC_PASSWORD
const config = {
utilRateLimit1: undefined,
utilRateLimit2: undefined
}
let i = 1
while (i < 3) {
config[`utilRateLimit${i}`] = new RateLimit({
windowMs: 60000, // 1 hour window
delayMs: 0, // disable delaying - full speed until the max limit is reached
max: 60, // start blocking after 60 requests
handler: function(req, res /*next*/) {
res.format({
json: function() {
res.status(500).json({
error: "Too many requests. Limits are 60 requests per minute."
})
}
})
}
})
i++
}
const requestConfig = {
method: "post",
auth: {
username: username,
password: password
},
data: {
jsonrpc: "1.0"
}
}
router.get("/", config.utilRateLimit1, async (req, res, next) => {
res.json({ status: "util" })
})
router.get(
"/validateAddress/:address",
config.utilRateLimit2,
async (req, res, next) => {
requestConfig.data.id = "validateaddress"
requestConfig.data.method = "validateaddress"
requestConfig.data.params = [req.params.address]
try {
const response = await BitboxHTTP(requestConfig)
res.json(response.data.result)
} catch (error) {
res.status(500).send(error.response.data.error)
}
}
)
module.exports = router
@@ -4,16 +4,15 @@
"use strict"
import * as express from "express"
import * as requestUtils from "./services/requestUtils"
import { IResponse } from "./interfaces/IResponse"
import axios from "axios"
const express = require("express")
const requestUtils = require("./services/requestUtils")
const axios = require("axios")
const logger = require("./logging.js")
const routeUtils = require("./route-utils")
const wlogger = require("../../util/winston-logging")
//const router = express.Router()
const router: express.Router = express.Router()
const router = express.Router()
// Used for processing error messages before sending them to the user.
const util = require("util")
@@ -39,29 +38,20 @@ router.post("/transactions", transactionsBulk)
router.get("/fromXPub/:xpub", fromXPubSingle)
// Root API endpoint. Simply acknowledges that it exists.
function root(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
function root(req, res, next) {
return res.json({ status: "address" })
}
// Query the Insight API for details on a single BCH address.
// Returns a Promise.
async function detailsFromInsight(
thisAddress: string,
currentPage: number = 0
) {
async function detailsFromInsight(thisAddress, currentPage = 0) {
try {
let addr: string
let addr
if (
process.env.BITCOINCOM_BASEURL === "https://bch-insight.bitpay.com/api/"
) {
)
addr = BITBOX.Address.toCashAddress(thisAddress)
} else {
addr = BITBOX.Address.toLegacyAddress(thisAddress)
}
else addr = BITBOX.Address.toLegacyAddress(thisAddress)
let path = `${process.env.BITCOINCOM_BASEURL}addr/${addr}`
@@ -99,11 +89,7 @@ async function detailsFromInsight(
// POST handler for bulk queries on address details
// curl -d '{"addresses": ["bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr", "bchtest:qp6hgvevf4gzz6l7pgcte3gaaud9km0l459fa23dul"]}' -H "Content-Type: application/json" http://localhost:3000/v2/address/details
// curl -d '{"addresses": ["bchtest:qzjtnzcvzxx7s0na88yrg3zl28wwvfp97538sgrrmr", "bchtest:qp6hgvevf4gzz6l7pgcte3gaaud9km0l459fa23dul"], "from": 1, "to": 5}' -H "Content-Type: application/json" http://localhost:3000/v2/address/details
async function detailsBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function detailsBulk(req, res, next) {
try {
let addresses = req.body.addresses
const currentPage = req.body.page ? parseInt(req.body.page, 10) : 0
@@ -153,12 +139,12 @@ async function detailsBulk(
// Loops through each address and creates an array of Promises, querying
// Insight API in parallel.
addresses = addresses.map(async (address: any, index: number) => {
return detailsFromInsight(address, currentPage)
})
addresses = addresses.map(async (address, index) =>
detailsFromInsight(address, currentPage)
)
// Wait for all parallel Insight requests to return.
let result: Array<any> = await axios.all(addresses)
const result = await axios.all(addresses)
// Return the array of retrieved address information.
res.status(200)
@@ -180,11 +166,7 @@ async function detailsBulk(
}
// GET handler for single address details
async function detailsSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function detailsSingle(req, res, next) {
try {
const address = req.params.address
const currentPage = req.query.page ? parseInt(req.query.page, 10) : 0
@@ -228,7 +210,7 @@ async function detailsSingle(
}
// Query the Insight API.
let retData: any = await detailsFromInsight(address, currentPage)
const retData = await detailsFromInsight(address, currentPage)
// Return the retrieved address information.
res.status(200)
@@ -251,16 +233,14 @@ async function detailsSingle(
}
// Retrieve UTXO data from the Insight API
async function utxoFromInsight(thisAddress: string) {
async function utxoFromInsight(thisAddress) {
try {
let addr: string
let addr
if (
process.env.BITCOINCOM_BASEURL === "https://bch-insight.bitpay.com/api/"
) {
)
addr = BITBOX.Address.toCashAddress(thisAddress)
} else {
addr = BITBOX.Address.toLegacyAddress(thisAddress)
}
else addr = BITBOX.Address.toLegacyAddress(thisAddress)
const path = `${process.env.BITCOINCOM_BASEURL}addr/${addr}/utxo`
@@ -275,12 +255,12 @@ async function utxoFromInsight(thisAddress: string) {
scriptPubKey: String
}
if (response.data.length && response.data[0].scriptPubKey) {
let spk = response.data[0].scriptPubKey
const spk = response.data[0].scriptPubKey
retData.scriptPubKey = spk
}
retData.legacyAddress = BITBOX.Address.toLegacyAddress(thisAddress)
retData.cashAddress = BITBOX.Address.toCashAddress(thisAddress)
retData.utxos = response.data.map((utxo: any) => {
retData.utxos = response.data.map(utxo => {
delete utxo.address
delete utxo.scriptPubKey
return utxo
@@ -296,11 +276,7 @@ async function utxoFromInsight(thisAddress: string) {
}
// Retrieve UTXO information for an address.
async function utxoBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function utxoBulk(req, res, next) {
try {
let addresses = req.body.addresses
@@ -351,12 +327,12 @@ async function utxoBulk(
// Loops through each address and creates an array of Promises, querying
// Insight API in parallel.
addresses = addresses.map(async (address: any, index: number) => {
return utxoFromInsight(address)
})
addresses = addresses.map(async (address, index) =>
utxoFromInsight(address)
)
// Wait for all parallel Insight requests to return.
let result: Array<any> = await axios.all(addresses)
const result = await axios.all(addresses)
res.status(200)
return res.json(result)
@@ -378,11 +354,7 @@ async function utxoBulk(
}
// GET handler for single address details
async function utxoSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function utxoSingle(req, res, next) {
try {
const address = req.params.address
if (!address || address === "") {
@@ -444,13 +416,9 @@ async function utxoSingle(
}
// Retrieve any unconfirmed TX information for a given address.
async function unconfirmedBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function unconfirmedBulk(req, res, next) {
try {
let addresses = req.body.addresses
const addresses = req.body.addresses
// Reject if address is not an array.
if (!Array.isArray(addresses)) {
@@ -497,16 +465,16 @@ async function unconfirmedBulk(
const promises = addresses.map(address => utxoFromInsight(address))
// Wait for all parallel Insight requests to return.
let result: Array<any> = await axios.all(promises)
const result = await axios.all(promises)
// Loop through each result
const finalResult = result.map(elem => {
//console.log(`elem: ${util.inspect(elem)}`)
// Filter out confirmed transactions.
const unconfirmedUtxos = elem.utxos.filter((utxo: any) => {
return utxo.confirmations === 0
})
const unconfirmedUtxos = elem.utxos.filter(
utxo => utxo.confirmations === 0
)
elem.utxos = unconfirmedUtxos
@@ -534,11 +502,7 @@ async function unconfirmedBulk(
}
// GET handler. Retrieve any unconfirmed TX information for a given address.
async function unconfirmedSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function unconfirmedSingle(req, res, next) {
try {
const address = req.params.address
if (!address || address === "") {
@@ -576,25 +540,14 @@ async function unconfirmedSingle(
})
}
interface Iutxo {
address: String
txid: String
vout: Number
scriptPubKey: String
amount: Number
satoshis: Number
height: Number
confirmations: Number
}
// Query the Insight API.
const retData: any = await utxoFromInsight(address)
const retData = await utxoFromInsight(address)
//console.log(`retData: ${JSON.stringify(retData,null,2)}`)
// Loop through each returned UTXO.
const unconfirmedUTXOs = []
for (let j = 0; j < retData.utxos.length; j++) {
const thisUtxo: Iutxo = retData.utxos[j]
const thisUtxo = retData.utxos[j]
// Only interested in UTXOs with no confirmations.
if (thisUtxo.confirmations === 0) unconfirmedUTXOs.push(thisUtxo)
@@ -623,10 +576,7 @@ async function unconfirmedSingle(
}
// Retrieve transaction data from the Insight API
async function transactionsFromInsight(
thisAddress: string,
currentPage: number = 0
) {
async function transactionsFromInsight(thisAddress, currentPage = 0) {
try {
const path = `${
process.env.BITCOINCOM_BASEURL
@@ -650,11 +600,7 @@ async function transactionsFromInsight(
}
// Get an array of TX information for a given address.
async function transactionsBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function transactionsBulk(req, res, next) {
try {
let addresses = req.body.addresses
const currentPage = req.body.page ? parseInt(req.body.page, 10) : 0
@@ -701,12 +647,12 @@ async function transactionsBulk(
}
// Loop through each address and collect an array of promises.
addresses = addresses.map(async (address: any, index: number) => {
return transactionsFromInsight(address, currentPage)
})
addresses = addresses.map(async (address, index) =>
transactionsFromInsight(address, currentPage)
)
// Wait for all parallel Insight requests to return.
let result: Array<any> = await axios.all(addresses)
const result = await axios.all(addresses)
// Return the array of retrieved address information.
res.status(200)
@@ -729,11 +675,7 @@ async function transactionsBulk(
}
// GET handler. Retrieve any unconfirmed TX information for a given address.
async function transactionsSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function transactionsSingle(req, res, next) {
try {
const address = req.params.address
const currentPage = req.query.page ? parseInt(req.query.page, 10) : 0
@@ -803,11 +745,7 @@ async function transactionsSingle(
}
}
async function fromXPubSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function fromXPubSingle(req, res, next) {
try {
const xpub = req.params.xpub
const hdPath = req.query.hdPath ? req.query.hdPath : "0"
@@ -828,8 +766,8 @@ async function fromXPubSingle(
logger.debug(`Executing address/fromXPub with this xpub: `, xpub)
wlogger.debug(`Executing address/fromXPub with this xpub: `, xpub)
let cashAddr = BITBOX.Address.fromXPub(xpub, hdPath)
let legacyAddr = BITBOX.Address.toLegacyAddress(cashAddr)
const cashAddr = BITBOX.Address.fromXPub(xpub, hdPath)
const legacyAddr = BITBOX.Address.toLegacyAddress(cashAddr)
res.status(200)
return res.json({
cashAddress: cashAddr,
@@ -1,18 +1,19 @@
"use strict"
import * as express from "express"
import * as requestUtils from "./services/requestUtils"
import * as bitbox from "./services/bitbox"
const express = require("express")
const requestUtils = require("./services/requestUtils")
const axios = require("axios")
const bitbox = require("./services/bitbox")
const logger = require("./logging.js")
const wlogger = require("../../util/winston-logging")
import axios from "axios"
const routeUtils = require("./route-utils")
// Used for processing error messages before sending them to the user.
const util = require("util")
util.inspect.defaultOptions = { depth: 3 }
const router: express.Router = express.Router()
const router = express.Router()
//const BitboxHTTP = bitbox.getInstance()
router.get("/", root)
@@ -21,20 +22,12 @@ router.post("/detailsByHash", detailsByHashBulk)
router.get("/detailsByHeight/:height", detailsByHeightSingle)
router.post("/detailsByHeight", detailsByHeightBulk)
function root(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
function root(req, res, next) {
return res.json({ status: "block" })
}
// Call the insight server to get block details based on the hash.
async function detailsByHashSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function detailsByHashSingle(req, res, next) {
try {
const hash = req.params.hash
@@ -75,11 +68,7 @@ async function detailsByHashSingle(
}
}
async function detailsByHashBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function detailsByHashBulk(req, res, next) {
try {
const hashes = req.body.hashes
@@ -112,12 +101,12 @@ async function detailsByHashBulk(
}
// Loop through each hash and creates an array of promises
const axiosPromises = hashes.map(async (hash: any) => {
return axios.get(`${process.env.BITCOINCOM_BASEURL}block/${hash}`)
})
const axiosPromises = hashes.map(async hash =>
axios.get(`${process.env.BITCOINCOM_BASEURL}block/${hash}`)
)
// Wait for all parallel promises to return.
const axiosResult: Array<any> = await axios.all(axiosPromises)
const axiosResult = await axios.all(axiosPromises)
// Extract the data component from the axios response.
const result = axiosResult.map(x => x.data)
@@ -149,11 +138,7 @@ async function detailsByHashBulk(
// Call the Full Node to get block hash based on height, then call the Insight
// server to get details from that hash.
async function detailsByHeightSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function detailsByHeightSingle(req, res, next) {
try {
const height = req.params.height
@@ -183,7 +168,6 @@ async function detailsByHeightSingle(
req.params.hash = hash
return detailsByHashSingle(req, res, next)
} catch (err) {
// Attempt to decode the error message.
const { msg, status } = routeUtils.decodeError(err)
if (msg) {
@@ -200,13 +184,9 @@ async function detailsByHeightSingle(
}
}
async function detailsByHeightBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function detailsByHeightBulk(req, res, next) {
try {
let heights = req.body.heights
const heights = req.body.heights
// Reject if heights is not an array.
if (!Array.isArray(heights)) {
@@ -245,7 +225,7 @@ async function detailsByHeightBulk(
} = routeUtils.setEnvVars()
// Loop through each height and creates an array of requests to call in parallel
const promises = heights.map(async (height: any) => {
const promises = heights.map(async height => {
requestConfig.data.id = "getblockhash"
requestConfig.data.method = "getblockhash"
requestConfig.data.params = [parseInt(height)]
@@ -262,7 +242,7 @@ async function detailsByHeightBulk(
})
// Wait for all parallel Insight requests to return.
let result: Array<any> = await axios.all(promises)
const result = await axios.all(promises)
res.status(200)
return res.json(result)
@@ -5,10 +5,10 @@
"use strict"
import * as express from "express"
const express = require("express")
const router = express.Router()
import axios from "axios"
import { IRequestConfig } from "./interfaces/IRequestConfig"
const axios = require("axios")
const routeUtils = require("./route-utils")
const logger = require("./logging.js")
const wlogger = require("../../util/winston-logging")
@@ -39,20 +39,12 @@ router.post("/getTxOutProof", getTxOutProofBulk)
router.get("/verifyTxOutProof/:proof", verifyTxOutProofSingle)
router.post("/verifyTxOutProof", verifyTxOutProofBulk)
function root(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
function root(req, res, next) {
return res.json({ status: "blockchain" })
}
// Returns the hash of the best (tip) block in the longest block chain.
async function getBestBlockHash(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getBestBlockHash(req, res, next) {
try {
const {
BitboxHTTP,
@@ -84,11 +76,7 @@ async function getBestBlockHash(
}
}
async function getBlockchainInfo(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getBlockchainInfo(req, res, next) {
try {
const {
BitboxHTTP,
@@ -121,11 +109,7 @@ async function getBlockchainInfo(
}
}
async function getBlockCount(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getBlockCount(req, res, next) {
try {
const {
BitboxHTTP,
@@ -157,11 +141,7 @@ async function getBlockCount(
}
}
async function getBlockHeaderSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getBlockHeaderSingle(req, res, next) {
try {
let verbose = false
if (req.query.verbose && req.query.verbose.toString() === "true")
@@ -204,13 +184,9 @@ async function getBlockHeaderSingle(
}
}
async function getBlockHeaderBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getBlockHeaderBulk(req, res, next) {
try {
let hashes = req.body.hashes
const hashes = req.body.hashes
const verbose = req.body.verbose ? req.body.verbose : false
if (!Array.isArray(hashes)) {
@@ -251,7 +227,7 @@ async function getBlockHeaderBulk(
} = routeUtils.setEnvVars()
// Loop through each hash and creates an array of requests to call in parallel
const promises = hashes.map(async (hash: any) => {
const promises = hashes.map(async hash => {
requestConfig.data.id = "getblockheader"
requestConfig.data.method = "getblockheader"
requestConfig.data.params = [hash, verbose]
@@ -259,7 +235,7 @@ async function getBlockHeaderBulk(
return await BitboxHTTP(requestConfig)
})
const axiosResult: Array<any> = await axios.all(promises)
const axiosResult = await axios.all(promises)
// Extract the data component from the axios response.
const result = axiosResult.map(x => x.data.result)
@@ -283,11 +259,7 @@ async function getBlockHeaderBulk(
}
}
async function getChainTips(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getChainTips(req, res, next) {
try {
const {
BitboxHTTP,
@@ -320,11 +292,7 @@ async function getChainTips(
}
// Get the current difficulty value, used to regulate mining power on the network.
async function getDifficulty(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getDifficulty(req, res, next) {
try {
const {
BitboxHTTP,
@@ -358,11 +326,7 @@ async function getDifficulty(
}
// Returns mempool data for given transaction. TXID must be in mempool (unconfirmed)
async function getMempoolEntrySingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getMempoolEntrySingle(req, res, next) {
try {
// Validate input parameter
const txid = req.params.txid
@@ -402,13 +366,9 @@ async function getMempoolEntrySingle(
}
}
async function getMempoolEntryBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getMempoolEntryBulk(req, res, next) {
try {
let txids = req.body.txids
const txids = req.body.txids
if (!Array.isArray(txids)) {
res.status(400)
@@ -448,7 +408,7 @@ async function getMempoolEntryBulk(
} = routeUtils.setEnvVars()
// Loop through each txid and creates an array of requests to call in parallel
const promises = txids.map(async (txid: any) => {
const promises = txids.map(async txid => {
requestConfig.data.id = "getmempoolentry"
requestConfig.data.method = "getmempoolentry"
requestConfig.data.params = [txid]
@@ -456,7 +416,7 @@ async function getMempoolEntryBulk(
return await BitboxHTTP(requestConfig)
})
const axiosResult: Array<any> = await axios.all(promises)
const axiosResult = await axios.all(promises)
// Extract the data component from the axios response.
const result = axiosResult.map(x => x.data.result)
@@ -480,11 +440,7 @@ async function getMempoolEntryBulk(
}
}
async function getMempoolInfo(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getMempoolInfo(req, res, next) {
try {
const {
BitboxHTTP,
@@ -516,11 +472,7 @@ async function getMempoolInfo(
}
}
async function getRawMempool(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getRawMempool(req, res, next) {
try {
const {
BitboxHTTP,
@@ -557,11 +509,7 @@ async function getRawMempool(
}
// Returns details about an unspent transaction output.
async function getTxOut(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getTxOut(req, res, next) {
try {
// Validate input parameter
const txid = req.params.txid
@@ -613,11 +561,7 @@ async function getTxOut(
}
// Returns a hex-encoded proof that 'txid' was included in a block.
async function getTxOutProofSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getTxOutProofSingle(req, res, next) {
try {
// Validate input parameter
const txid = req.params.txid
@@ -658,13 +602,9 @@ async function getTxOutProofSingle(
}
// Returns a hex-encoded proof that 'txid' was included in a block.
async function getTxOutProofBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getTxOutProofBulk(req, res, next) {
try {
let txids = req.body.txids
const txids = req.body.txids
// Reject if txids is not an array.
if (!Array.isArray(txids)) {
@@ -704,7 +644,7 @@ async function getTxOutProofBulk(
logger.debug(`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: any) => {
const promises = txids.map(async txid => {
requestConfig.data.id = "gettxoutproof"
requestConfig.data.method = "gettxoutproof"
requestConfig.data.params = [[txid]]
@@ -713,7 +653,7 @@ async function getTxOutProofBulk(
})
// Wait for all parallel promisses to resolve.
const axiosResult: Array<any> = await axios.all(promises)
const axiosResult = await axios.all(promises)
// Extract the data component from the axios response.
const result = axiosResult.map(x => x.data.result)
@@ -809,11 +749,7 @@ async function getTxOutProofBulk(
// });
*/
async function verifyTxOutProofSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function verifyTxOutProofSingle(req, res, next) {
try {
// Validate input parameter
const proof = req.params.proof
@@ -853,13 +789,9 @@ async function verifyTxOutProofSingle(
}
}
async function verifyTxOutProofBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function verifyTxOutProofBulk(req, res, next) {
try {
let proofs = req.body.proofs
const proofs = req.body.proofs
// Reject if proofs is not an array.
if (!Array.isArray(proofs)) {
@@ -900,7 +832,7 @@ async function verifyTxOutProofBulk(
)
// Loop through each proof and creates an array of requests to call in parallel
const promises = proofs.map(async (proof: any) => {
const promises = proofs.map(async proof => {
requestConfig.data.id = "verifytxoutproof"
requestConfig.data.method = "verifytxoutproof"
requestConfig.data.params = [proof]
@@ -909,7 +841,7 @@ async function verifyTxOutProofBulk(
})
// Wait for all parallel promisses to resolve.
const axiosResult: Array<any> = await axios.all(promises)
const axiosResult = await axios.all(promises)
// Extract the data component from the axios response.
const result = axiosResult.map(x => x.data.result[0])
@@ -1,9 +1,9 @@
"use strict"
import * as express from "express"
const express = require("express")
const router = express.Router()
import axios from "axios"
import { IRequestConfig } from "./interfaces/IRequestConfig"
const axios = require("axios")
const logger = require("./logging.js")
const routeUtils = require("./route-utils")
const wlogger = require("../../util/winston-logging")
@@ -15,21 +15,18 @@ util.inspect.defaultOptions = { depth: 1 }
router.get("/", root)
router.get("/getInfo", getInfo)
function root(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
function root(req, res, next) {
return res.json({ status: "control" })
}
// Execute the RPC getinfo call.
async function getInfo(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
const {BitboxHTTP, username, password, requestConfig} = routeUtils.setEnvVars()
async function getInfo(req, res, next) {
const {
BitboxHTTP,
username,
password,
requestConfig
} = routeUtils.setEnvVars()
requestConfig.data.id = "getinfo"
requestConfig.data.method = "getinfo"
@@ -1,13 +0,0 @@
export interface IRequestConfig {
method: string
auth: {
username: string
password: string
}
data: {
jsonrpc: string
id?: any
method?: any
params?: any
}
}
-6
View File
@@ -1,6 +0,0 @@
export interface IResponse {
status: number
json: {
error: string
}
}
@@ -1,9 +1,9 @@
"use strict"
import * as express from "express"
const express = require("express")
const router = express.Router()
import axios from "axios"
import { IRequestConfig } from "./interfaces/IRequestConfig"
const axios = require("axios")
const routeUtils = require("./route-utils")
const logger = require("./logging.js")
const wlogger = require("../../util/winston-logging")
@@ -18,7 +18,7 @@ const BitboxHTTP = axios.create({
const username = process.env.RPC_USERNAME
const password = process.env.RPC_PASSWORD
const requestConfig: IRequestConfig = {
const requestConfig = {
method: "post",
auth: {
username: username,
@@ -33,11 +33,7 @@ router.get("/", root)
router.get("/getMiningInfo", getMiningInfo)
router.get("/getNetworkHashps", getNetworkHashPS)
function root(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
function root(req, res, next) {
return res.json({ status: "mining" })
}
@@ -66,11 +62,7 @@ function root(
// });
// });
async function getMiningInfo(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getMiningInfo(req, res, next) {
try {
const {
BitboxHTTP,
@@ -101,11 +93,7 @@ async function getMiningInfo(
}
}
async function getNetworkHashPS(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getNetworkHashPS(req, res, next) {
try {
let nblocks = 120 // Default
let height = -1 // Default
@@ -1,18 +1,11 @@
"use strict"
import * as express from "express"
const express = require("express")
const router = express.Router()
router.get(
"/",
async (
req: express.Request,
res: express.Response,
next: express.NextFunction
) => {
res.json({ status: "network" })
}
)
router.get("/", async (req, res, next) => {
res.json({ status: "network" })
})
// router.post('/addNode/:node/:command', (req, res, next) => {
// BITBOX.Network.addNode(req.params.node, req.params.command)
@@ -1,10 +1,9 @@
"use strict"
import * as express from "express"
const express = require("express")
const router = express.Router()
import axios from "axios"
import { IRequestConfig } from "./interfaces/IRequestConfig"
import { IResponse } from "./interfaces/IResponse"
const axios = require("axios")
const routeUtils = require("./route-utils")
const logger = require("./logging.js")
const wlogger = require("../../util/winston-logging")
@@ -19,7 +18,7 @@ const BitboxHTTP = axios.create({
const username = process.env.RPC_USERNAME
const password = process.env.RPC_PASSWORD
const requestConfig: IRequestConfig = {
const requestConfig = {
method: "post",
auth: {
username: username,
@@ -40,21 +39,13 @@ router.get("/getRawTransaction/:txid", getRawTransactionSingle)
router.post("/sendRawTransaction", sendRawTransactionBulk)
router.get("/sendRawTransaction/:hex", sendRawTransactionSingle)
function root(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
function root(req, res, next) {
return res.json({ status: "rawtransactions" })
}
// Decode transaction hex into a JSON object.
// GET
async function decodeRawTransactionSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function decodeRawTransactionSingle(req, res, next) {
try {
const hex = req.params.hex
@@ -97,13 +88,9 @@ async function decodeRawTransactionSingle(
}
}
async function decodeRawTransactionBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function decodeRawTransactionBulk(req, res, next) {
try {
let hexes = req.body.hexes
const hexes = req.body.hexes
if (!Array.isArray(hexes)) {
res.status(400)
@@ -139,7 +126,7 @@ async function decodeRawTransactionBulk(
} = routeUtils.setEnvVars()
// Loop through each height and creates an array of requests to call in parallel
const promises = hexes.map(async (hex: any) => {
const promises = hexes.map(async hex => {
requestConfig.data.id = "decoderawtransaction"
requestConfig.data.method = "decoderawtransaction"
requestConfig.data.params = [hex]
@@ -148,7 +135,7 @@ async function decodeRawTransactionBulk(
})
// Wait for all parallel Insight requests to return.
const axiosResult: Array<any> = await axios.all(promises)
const axiosResult = await axios.all(promises)
// Retrieve the data part of the result.
const result = axiosResult.map(x => x.data.result)
@@ -213,11 +200,7 @@ async function decodeRawTransactionBulk(
// Decode a raw transaction from hex to assembly.
// GET single
async function decodeScriptSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function decodeScriptSingle(req, res, next) {
try {
const hex = req.params.hex
@@ -259,11 +242,7 @@ async function decodeScriptSingle(
// Decode a raw transaction from hex to assembly.
// POST bulk
async function decodeScriptBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function decodeScriptBulk(req, res, next) {
try {
const hexes = req.body.hexes
@@ -300,7 +279,7 @@ async function decodeScriptBulk(
} = routeUtils.setEnvVars()
// Loop through each hex and create an array of promises
const promises = hexes.map(async (hex: any) => {
const promises = hexes.map(async hex => {
requestConfig.data.id = "decodescript"
requestConfig.data.method = "decodescript"
requestConfig.data.params = [hex]
@@ -310,7 +289,7 @@ async function decodeScriptBulk(
})
// Wait for all parallel promises to return.
const resolved: Array<any> = await Promise.all(promises)
const resolved = await Promise.all(promises)
// Retrieve the data from each resolved promise.
const result = resolved.map(x => x.data.result)
@@ -335,7 +314,7 @@ async function decodeScriptBulk(
}
// Retrieve raw transactions details from the full node.
async function getRawTransactionsFromNode(txid: string, verbose: number) {
async function getRawTransactionsFromNode(txid, verbose) {
try {
const {
BitboxHTTP,
@@ -359,16 +338,12 @@ async function getRawTransactionsFromNode(txid: string, verbose: number) {
// Get a JSON object breakdown of transaction details.
// POST
async function getRawTransactionBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getRawTransactionBulk(req, res, next) {
try {
let verbose = 0
if (req.body.verbose) verbose = 1
let txids = req.body.txids
const txids = req.body.txids
if (!Array.isArray(txids)) {
res.status(400)
return res.json({ error: "txids must be an array" })
@@ -383,7 +358,7 @@ async function getRawTransactionBulk(
}
// stub response object
let returnResponse: IResponse = {
const returnResponse = {
status: 100,
json: {
error: ""
@@ -408,12 +383,12 @@ async function getRawTransactionBulk(
}
// Loop through each txid and create an array of promises
const promises = txids.map(async (txid: any) => {
return getRawTransactionsFromNode(txid, verbose)
})
const promises = txids.map(async txid =>
getRawTransactionsFromNode(txid, verbose)
)
// Wait for all parallel promises to return.
const axiosResult: Array<any> = await axios.all(promises)
const axiosResult = await axios.all(promises)
res.status(200)
return res.json(axiosResult)
@@ -436,11 +411,7 @@ async function getRawTransactionBulk(
// Get a JSON object breakdown of transaction details.
// GET
async function getRawTransactionSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function getRawTransactionSingle(req, res, next) {
try {
let verbose = 0
if (req.query.verbose === "true") verbose = 1
@@ -472,11 +443,7 @@ async function getRawTransactionSingle(
}
// Transmit a raw transaction to the BCH network.
async function sendRawTransactionBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function sendRawTransactionBulk(req, res, next) {
try {
// Validation
const hexes = req.body.hexes
@@ -571,11 +538,7 @@ async function sendRawTransactionBulk(
}
// Transmit a raw transaction to the BCH network.
async function sendRawTransactionSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function sendRawTransactionSingle(req, res, next) {
try {
const hex = req.params.hex // URL parameter
+11
View File
@@ -0,0 +1,11 @@
"use strict"
const axios = require("axios")
const BitboxHTTP = axios.create({
baseURL: process.env.RPC_BASEURL
})
const getInstance = () => BitboxHTTP
module.exports = getInstance
-7
View File
@@ -1,7 +0,0 @@
import axios from "axios"
const BitboxHTTP = axios.create({
baseURL: process.env.RPC_BASEURL
})
export const getInstance = () => BitboxHTTP
+20
View File
@@ -0,0 +1,20 @@
"use strict"
const username = process.env.RPC_USERNAME
const password = process.env.RPC_PASSWORD
const getRequestConfig = (method, params) => ({
method: "post",
auth: {
username,
password
},
data: {
jsonrpc: "1.0",
id: method,
method,
params
}
})
module.exports = getRequestConfig
-25
View File
@@ -1,25 +0,0 @@
import { IRequestConfig } from "../interfaces/IRequestConfig"
const username = process.env.RPC_USERNAME
const password = process.env.RPC_PASSWORD
type RPCMethod = "getblockhash"
export const getRequestConfig = (
method: RPCMethod,
params: (string | number)[]
): IRequestConfig => {
return {
method: "post",
auth: {
username,
password
},
data: {
jsonrpc: "1.0",
id: method,
method,
params
}
}
}
+108 -196
View File
@@ -1,9 +1,9 @@
"use strict"
import * as express from "express"
const express = require("express")
const router = express.Router()
import axios from "axios"
import { IRequestConfig } from "./interfaces/IRequestConfig"
const axios = require("axios")
const routeUtils = require("./route-utils")
const logger = require("./logging.js")
const strftime = require("strftime")
@@ -79,7 +79,7 @@ if (process.env.NON_JS_FRAMEWORK && process.env.NON_JS_FRAMEWORK === "true") {
// Retrieve raw transactions details from the full node.
// TODO: move this function to a separate support library.
// TODO: Add unit tests for this function.
async function getRawTransactionsFromNode(txids: string[]) {
async function getRawTransactionsFromNode(txids) {
try {
const {
BitboxHTTP,
@@ -106,9 +106,7 @@ async function getRawTransactionsFromNode(txids: string[]) {
// Insert to slpTxDb
try {
if (slpTxDb.isOpen()) {
await slpTxDb.put(txid, result)
}
if (slpTxDb.isOpen()) await slpTxDb.put(txid, result)
} catch (err) {
// console.log("Error inserting to slpTxDb", err)
}
@@ -125,16 +123,14 @@ async function getRawTransactionsFromNode(txids: string[]) {
}
// Create a validator for validating SLP transactions.
function createValidator(network: string, getRawTransactions: any = null): any {
let tmpSLP: any
function createValidator(network, getRawTransactions = null) {
let tmpSLP
if (network === "mainnet") {
if (network === "mainnet")
tmpSLP = new SLPSDK({ restURL: process.env.REST_URL })
} else {
tmpSLP = new SLPSDK({ restURL: process.env.TREST_URL })
}
else tmpSLP = new SLPSDK({ restURL: process.env.TREST_URL })
const slpValidator: any = new slp.LocalValidator(
const slpValidator = new slp.LocalValidator(
tmpSLP,
getRawTransactions
? getRawTransactions
@@ -153,7 +149,7 @@ const slpValidator = createValidator(
// Instantiate the bitboxproxy class in SLPJS.
const bitboxproxy = new slp.BitboxNetwork(SLP, slpValidator)
const requestConfig: IRequestConfig = {
const requestConfig = {
method: "post",
auth: {
username: username,
@@ -199,19 +195,11 @@ function formatTokenOutput(token) {
return token
}
function root(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
function root(req, res, next) {
return res.json({ status: "slp" })
}
async function list(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function list(req, res, next) {
try {
const query = {
v: 3,
@@ -233,10 +221,10 @@ async function list(
// Get data from SLPDB.
const tokenRes = await axios.get(url)
let formattedTokens: Array<any> = []
const formattedTokens = []
if (tokenRes.data.t.length) {
tokenRes.data.t.forEach((token: any) => {
tokenRes.data.t.forEach(token => {
token = formatTokenOutput(token)
formattedTokens.push(token.tokenDetails)
})
@@ -257,13 +245,9 @@ async function list(
}
}
async function listSingleToken(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function listSingleToken(req, res, next) {
try {
let tokenId = req.params.tokenId
const tokenId = req.params.tokenId
if (!tokenId || tokenId === "") {
res.status(400)
@@ -287,13 +271,9 @@ async function listSingleToken(
}
}
async function listBulkToken(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function listBulkToken(req, res, next) {
try {
let tokenIds = req.body.tokenIds
const tokenIds = req.body.tokenIds
// Reject if tokenIds is not an array.
if (!Array.isArray(tokenIds)) {
@@ -332,18 +312,18 @@ async function listBulkToken(
const tokenRes = await axios.get(url)
let formattedTokens: Array<any> = []
let txids: Array<any> = []
const formattedTokens = []
const txids = []
if (tokenRes.data.t.length) {
tokenRes.data.t.forEach((token: any) => {
tokenRes.data.t.forEach(token => {
txids.push(token.tokenDetails.tokenIdHex)
token = formatTokenOutput(token)
formattedTokens.push(token.tokenDetails)
})
}
tokenIds.forEach((tokenId: string) => {
tokenIds.forEach(tokenId => {
if (!txids.includes(tokenId)) {
formattedTokens.push({
id: tokenId,
@@ -391,17 +371,17 @@ async function lookupToken(tokenId) {
//console.log(`tokenRes.data: ${util.inspect(tokenRes.data,null,2)}`)
//console.log(`tokenRes.data.t[0]: ${util.inspect(tokenRes.data.t[0],null,2)}`)
let formattedTokens: Array<any> = []
const formattedTokens = []
if (tokenRes.data.t.length) {
tokenRes.data.t.forEach((token: any) => {
tokenRes.data.t.forEach(token => {
token = formatTokenOutput(token)
formattedTokens.push(token.tokenDetails)
})
}
let t
formattedTokens.forEach((token: any) => {
formattedTokens.forEach(token => {
if (token.id === tokenId) t = token
})
@@ -421,14 +401,10 @@ async function lookupToken(tokenId) {
}
// Retrieve token balances for all tokens for a single address.
async function balancesForAddress(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function balancesForAddress(req, res, next) {
try {
// Validate the input data.
let address = req.params.address
const address = req.params.address
if (!address || address === "") {
res.status(400)
return res.json({ error: "address can not be empty" })
@@ -436,7 +412,7 @@ async function balancesForAddress(
// Ensure the input is a valid BCH address.
try {
let cash = utils.toCashAddress(address)
const cash = utils.toCashAddress(address)
} catch (err) {
res.status(400)
return res.json({
@@ -445,7 +421,7 @@ async function balancesForAddress(
}
// Prevent a common user error. Ensure they are using the correct network address.
let cashAddr = utils.toCashAddress(address)
const cashAddr = utils.toCashAddress(address)
const networkIsValid = routeUtils.validateNetwork(cashAddr)
if (!networkIsValid) {
res.status(400)
@@ -472,7 +448,7 @@ async function balancesForAddress(
const tokenRes = await axios.get(url)
let tokenIds: string[] = []
const tokenIds = []
if (tokenRes.data.a.length > 0) {
tokenRes.data.a = tokenRes.data.a.map(token => {
token.tokenId = token.tokenDetails.tokenIdHex
@@ -521,17 +497,15 @@ async function balancesForAddress(
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)
} else {
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)
@@ -550,14 +524,10 @@ async function balancesForAddress(
}
// Retrieve token balances for all addresses by single tokenId.
async function balancesForTokenSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function balancesForTokenSingle(req, res, next) {
try {
// Validate the input data.
let tokenId = req.params.tokenId
const tokenId = req.params.tokenId
if (!tokenId || tokenId === "") {
res.status(400)
return res.json({ error: "tokenId can not be empty" })
@@ -581,7 +551,7 @@ async function balancesForTokenSingle(
// Get data from SLPDB.
const tokenRes = await axios.get(url)
let resBalances: any[] = tokenRes.data.a.map((addy, index) => {
const resBalances = tokenRes.data.a.map((addy, index) => {
delete addy.satoshis_balance
addy.tokenBalance = parseFloat(addy.token_balance)
addy.slpAddress = addy.address
@@ -609,20 +579,16 @@ async function balancesForTokenSingle(
}
// Retrieve token balances for a single token class, for a single address.
async function balancesForAddressByTokenID(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function balancesForAddressByTokenID(req, res, next) {
try {
// Validate input data.
let address: string = req.params.address
const address = req.params.address
if (!address || address === "") {
res.status(400)
return res.json({ error: "address can not be empty" })
}
let tokenId: string = req.params.tokenId
const tokenId = req.params.tokenId
if (!tokenId || tokenId === "") {
res.status(400)
return res.json({ error: "tokenId can not be empty" })
@@ -630,7 +596,7 @@ async function balancesForAddressByTokenID(
// Ensure the input is a valid BCH address.
try {
let cash = utils.toCashAddress(address)
const cash = utils.toCashAddress(address)
} catch (err) {
res.status(400)
return res.json({
@@ -639,7 +605,7 @@ async function balancesForAddressByTokenID(
}
// Prevent a common user error. Ensure they are using the correct network address.
let cashAddr = utils.toCashAddress(address)
const cashAddr = utils.toCashAddress(address)
const networkIsValid = routeUtils.validateNetwork(cashAddr)
if (!networkIsValid) {
res.status(400)
@@ -669,7 +635,7 @@ async function balancesForAddressByTokenID(
// Get data from SLPDB.
const tokenRes = await axios.get(url)
let resVal: any
let resVal
res.status(200)
if (tokenRes.data.a.length > 0) {
tokenRes.data.a.forEach(async token => {
@@ -740,13 +706,9 @@ async function balancesForAddressByTokenID(
}
}
async function convertAddressSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function convertAddressSingle(req, res, next) {
try {
let address = req.params.address
const address = req.params.address
// Validate input
if (!address || address === "") {
@@ -756,11 +718,7 @@ async function convertAddressSingle(
const slpAddr = SLP.Address.toSLPAddress(address)
const obj: {
[slpAddress: string]: any
cashAddress: any
legacyAddress: any
} = {
const obj = {
slpAddress: "",
cashAddress: "",
legacyAddress: ""
@@ -786,12 +744,8 @@ async function convertAddressSingle(
}
}
async function convertAddressBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
let addresses = req.body.addresses
async function convertAddressBulk(req, res, next) {
const addresses = req.body.addresses
// Reject if hashes is not an array.
if (!Array.isArray(addresses)) {
@@ -822,11 +776,7 @@ async function convertAddressBulk(
const slpAddr = SLP.Address.toSLPAddress(address)
const obj: {
[slpAddress: string]: any
cashAddress: any
legacyAddress: any
} = {
const obj = {
slpAddress: "",
cashAddress: "",
legacyAddress: ""
@@ -842,11 +792,7 @@ async function convertAddressBulk(
return res.json(convertedAddresses)
}
async function validateBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function validateBulk(req, res, next) {
try {
const txids = req.body.txids
@@ -874,7 +820,7 @@ async function validateBulk(
txid
)
let tmp: any = {
const tmp = {
txid: txid,
valid: isValid ? true : false
}
@@ -907,11 +853,7 @@ async function validateBulk(
}
}
async function validateSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function validateSingle(req, res, next) {
try {
const txid = req.params.txid
@@ -927,7 +869,7 @@ async function validateSingle(
// Dev note: must call module.exports to allow stubs in unit tests.
const isValid = await module.exports.testableComponents.isValidSlpTxid(txid)
let tmp: any = {
const tmp = {
txid: txid,
valid: isValid ? true : false
}
@@ -950,7 +892,7 @@ async function validateSingle(
}
// Returns a Boolean if the input TXID is a valid SLP TXID.
async function isValidSlpTxid(txid: string): Promise<boolean> {
async function isValidSlpTxid(txid) {
const isValid = await slpValidator.isValidSlpTxid(txid)
return isValid
}
@@ -958,78 +900,74 @@ async function isValidSlpTxid(txid: string): Promise<boolean> {
// Below are functions which are enabled for teams not using our javascript SDKs which still need to create txs
// These should never be enabled on our public REST API
async function createTokenType1(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
let fundingAddress = req.params.fundingAddress
async function createTokenType1(req, res, next) {
const fundingAddress = req.params.fundingAddress
if (!fundingAddress || fundingAddress === "") {
res.status(400)
return res.json({ error: "fundingAddress can not be empty" })
}
let fundingWif = req.params.fundingWif
const fundingWif = req.params.fundingWif
if (!fundingWif || fundingWif === "") {
res.status(400)
return res.json({ error: "fundingWif can not be empty" })
}
let tokenReceiverAddress = req.params.tokenReceiverAddress
const tokenReceiverAddress = req.params.tokenReceiverAddress
if (!tokenReceiverAddress || tokenReceiverAddress === "") {
res.status(400)
return res.json({ error: "tokenReceiverAddress can not be empty" })
}
let batonReceiverAddress = req.params.batonReceiverAddress
const batonReceiverAddress = req.params.batonReceiverAddress
if (!batonReceiverAddress || batonReceiverAddress === "") {
res.status(400)
return res.json({ error: "batonReceiverAddress can not be empty" })
}
let bchChangeReceiverAddress = req.params.bchChangeReceiverAddress
const bchChangeReceiverAddress = req.params.bchChangeReceiverAddress
if (!bchChangeReceiverAddress || bchChangeReceiverAddress === "") {
res.status(400)
return res.json({ error: "bchChangeReceiverAddress can not be empty" })
}
let decimals = req.params.decimals
const decimals = req.params.decimals
if (!decimals || decimals === "") {
res.status(400)
return res.json({ error: "decimals can not be empty" })
}
let name = req.params.name
const name = req.params.name
if (!name || name === "") {
res.status(400)
return res.json({ error: "name can not be empty" })
}
let symbol = req.params.symbol
const symbol = req.params.symbol
if (!symbol || symbol === "") {
res.status(400)
return res.json({ error: "symbol can not be empty" })
}
let documentUri = req.params.documentUri
const documentUri = req.params.documentUri
if (!documentUri || documentUri === "") {
res.status(400)
return res.json({ error: "documentUri can not be empty" })
}
let documentHash = req.params.documentHash
const documentHash = req.params.documentHash
if (!documentHash || documentHash === "") {
res.status(400)
return res.json({ error: "documentHash can not be empty" })
}
let initialTokenQty = req.params.initialTokenQty
const initialTokenQty = req.params.initialTokenQty
if (!initialTokenQty || initialTokenQty === "") {
res.status(400)
return res.json({ error: "initialTokenQty can not be empty" })
}
let token = await SLP.TokenType1.create({
const token = await SLP.TokenType1.create({
fundingAddress: fundingAddress,
fundingWif: fundingWif,
tokenReceiverAddress: tokenReceiverAddress,
@@ -1047,54 +985,50 @@ async function createTokenType1(
return res.json(token)
}
async function mintTokenType1(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
let fundingAddress = req.params.fundingAddress
async function mintTokenType1(req, res, next) {
const fundingAddress = req.params.fundingAddress
if (!fundingAddress || fundingAddress === "") {
res.status(400)
return res.json({ error: "fundingAddress can not be empty" })
}
let fundingWif = req.params.fundingWif
const fundingWif = req.params.fundingWif
if (!fundingWif || fundingWif === "") {
res.status(400)
return res.json({ error: "fundingWif can not be empty" })
}
let tokenReceiverAddress = req.params.tokenReceiverAddress
const tokenReceiverAddress = req.params.tokenReceiverAddress
if (!tokenReceiverAddress || tokenReceiverAddress === "") {
res.status(400)
return res.json({ error: "tokenReceiverAddress can not be empty" })
}
let batonReceiverAddress = req.params.batonReceiverAddress
const batonReceiverAddress = req.params.batonReceiverAddress
if (!batonReceiverAddress || batonReceiverAddress === "") {
res.status(400)
return res.json({ error: "batonReceiverAddress can not be empty" })
}
let bchChangeReceiverAddress = req.params.bchChangeReceiverAddress
const bchChangeReceiverAddress = req.params.bchChangeReceiverAddress
if (!bchChangeReceiverAddress || bchChangeReceiverAddress === "") {
res.status(400)
return res.json({ error: "bchChangeReceiverAddress can not be empty" })
}
let tokenId = req.params.tokenId
const tokenId = req.params.tokenId
if (!tokenId || tokenId === "") {
res.status(400)
return res.json({ error: "tokenId can not be empty" })
}
let additionalTokenQty = req.params.additionalTokenQty
const additionalTokenQty = req.params.additionalTokenQty
if (!additionalTokenQty || additionalTokenQty === "") {
res.status(400)
return res.json({ error: "additionalTokenQty can not be empty" })
}
let mint = await SLP.TokenType1.mint({
const mint = await SLP.TokenType1.mint({
fundingAddress: fundingAddress,
fundingWif: fundingWif,
tokenReceiverAddress: tokenReceiverAddress,
@@ -1108,47 +1042,43 @@ async function mintTokenType1(
return res.json(mint)
}
async function sendTokenType1(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
let fundingAddress = req.params.fundingAddress
async function sendTokenType1(req, res, next) {
const fundingAddress = req.params.fundingAddress
if (!fundingAddress || fundingAddress === "") {
res.status(400)
return res.json({ error: "fundingAddress can not be empty" })
}
let fundingWif = req.params.fundingWif
const fundingWif = req.params.fundingWif
if (!fundingWif || fundingWif === "") {
res.status(400)
return res.json({ error: "fundingWif can not be empty" })
}
let tokenReceiverAddress = req.params.tokenReceiverAddress
const tokenReceiverAddress = req.params.tokenReceiverAddress
if (!tokenReceiverAddress || tokenReceiverAddress === "") {
res.status(400)
return res.json({ error: "tokenReceiverAddress can not be empty" })
}
let bchChangeReceiverAddress = req.params.bchChangeReceiverAddress
const bchChangeReceiverAddress = req.params.bchChangeReceiverAddress
if (!bchChangeReceiverAddress || bchChangeReceiverAddress === "") {
res.status(400)
return res.json({ error: "bchChangeReceiverAddress can not be empty" })
}
let tokenId = req.params.tokenId
const tokenId = req.params.tokenId
if (!tokenId || tokenId === "") {
res.status(400)
return res.json({ error: "tokenId can not be empty" })
}
let amount = req.params.amount
const amount = req.params.amount
if (!amount || amount === "") {
res.status(400)
return res.json({ error: "amount can not be empty" })
}
let send = await SLP.TokenType1.send({
const send = await SLP.TokenType1.send({
fundingAddress: fundingAddress,
fundingWif: fundingWif,
tokenReceiverAddress: tokenReceiverAddress,
@@ -1161,42 +1091,38 @@ async function sendTokenType1(
return res.json(send)
}
async function burnTokenType1(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
let fundingAddress = req.params.fundingAddress
async function burnTokenType1(req, res, next) {
const fundingAddress = req.params.fundingAddress
if (!fundingAddress || fundingAddress === "") {
res.status(400)
return res.json({ error: "fundingAddress can not be empty" })
}
let fundingWif = req.params.fundingWif
const fundingWif = req.params.fundingWif
if (!fundingWif || fundingWif === "") {
res.status(400)
return res.json({ error: "fundingWif can not be empty" })
}
let bchChangeReceiverAddress = req.params.bchChangeReceiverAddress
const bchChangeReceiverAddress = req.params.bchChangeReceiverAddress
if (!bchChangeReceiverAddress || bchChangeReceiverAddress === "") {
res.status(400)
return res.json({ error: "bchChangeReceiverAddress can not be empty" })
}
let tokenId = req.params.tokenId
const tokenId = req.params.tokenId
if (!tokenId || tokenId === "") {
res.status(400)
return res.json({ error: "tokenId can not be empty" })
}
let amount = req.params.amount
const amount = req.params.amount
if (!amount || amount === "") {
res.status(400)
return res.json({ error: "amount can not be empty" })
}
let burn = await SLP.TokenType1.burn({
const burn = await SLP.TokenType1.burn({
fundingAddress: fundingAddress,
fundingWif: fundingWif,
tokenId: tokenId,
@@ -1208,36 +1134,32 @@ async function burnTokenType1(
return res.json(burn)
}
async function burnAllTokenType1(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
let fundingAddress = req.params.fundingAddress
async function burnAllTokenType1(req, res, next) {
const fundingAddress = req.params.fundingAddress
if (!fundingAddress || fundingAddress === "") {
res.status(400)
return res.json({ error: "fundingAddress can not be empty" })
}
let fundingWif = req.params.fundingWif
const fundingWif = req.params.fundingWif
if (!fundingWif || fundingWif === "") {
res.status(400)
return res.json({ error: "fundingWif can not be empty" })
}
let bchChangeReceiverAddress = req.params.bchChangeReceiverAddress
const bchChangeReceiverAddress = req.params.bchChangeReceiverAddress
if (!bchChangeReceiverAddress || bchChangeReceiverAddress === "") {
res.status(400)
return res.json({ error: "bchChangeReceiverAddress can not be empty" })
}
let tokenId = req.params.tokenId
const tokenId = req.params.tokenId
if (!tokenId || tokenId === "") {
res.status(400)
return res.json({ error: "tokenId can not be empty" })
}
let burnAll = await SLP.TokenType1.burnAll({
const burnAll = await SLP.TokenType1.burnAll({
fundingAddress: fundingAddress,
fundingWif: fundingWif,
tokenId: tokenId,
@@ -1248,11 +1170,7 @@ async function burnAllTokenType1(
return res.json(burnAll)
}
async function txDetails(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function txDetails(req, res, next) {
try {
// Validate input parameter
const txid = req.params.txid
@@ -1272,11 +1190,13 @@ async function txDetails(
else tmpSLP = new SLPSDK({ restURL: process.env.REST_URL })
const tmpbitboxNetwork = new slp.BitboxNetwork(tmpSLP, slpValidator)
console.log(`tmpbitboxNetwork: ${JSON.stringify(tmpbitboxNetwork,null,2)}`)
//console.log(
// `tmpbitboxNetwork: ${JSON.stringify(tmpbitboxNetwork, null, 2)}`
//)
// Get TX info + token info
const result = await tmpbitboxNetwork.getTransactionDetails(txid)
console.log(`result: ${JSON.stringify(result,null,2)}`)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
res.status(200)
return res.json(result)
@@ -1301,12 +1221,8 @@ async function txDetails(
}
}
async function tokenStats(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
let tokenId: string = req.params.tokenId
async function tokenStats(req, res, next) {
const tokenId = req.params.tokenId
if (!tokenId || tokenId === "") {
res.status(400)
return res.json({ error: "tokenId can not be empty" })
@@ -1334,10 +1250,10 @@ async function tokenStats(
// Get data from BitDB.
const tokenRes = await axios.get(url)
let formattedTokens: Array<any> = []
const formattedTokens = []
if (tokenRes.data.t.length) {
tokenRes.data.t.forEach((token: any) => {
tokenRes.data.t.forEach(token => {
token = formatTokenOutput(token)
formattedTokens.push(token.tokenDetails)
})
@@ -1359,20 +1275,16 @@ async function tokenStats(
}
// Retrieve transactions by tokenId and address.
async function txsTokenIdAddressSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function txsTokenIdAddressSingle(req, res, next) {
try {
// Validate the input data.
let tokenId = req.params.tokenId
const tokenId = req.params.tokenId
if (!tokenId || tokenId === "") {
res.status(400)
return res.json({ error: "tokenId can not be empty" })
}
let address = req.params.address
const address = req.params.address
if (!address || address === "") {
res.status(400)
return res.json({ error: "address can not be empty" })
@@ -1,9 +1,9 @@
"use strict"
import * as express from "express"
const express = require("express")
const router = express.Router()
import axios from "axios"
import { IRequestConfig } from "./interfaces/IRequestConfig"
const axios = require("axios")
const routeUtils = require("./route-utils")
const logger = require("./logging.js")
const wlogger = require("../../util/winston-logging")
@@ -16,10 +16,10 @@ const util = require("util")
util.inspect.defaultOptions = { depth: 3 }
// Manipulates and formats the raw data comming from Insight API.
const processInputs = (tx: any) => {
const processInputs = tx => {
// Add legacy and cashaddr to tx vin
if (tx.vin) {
tx.vin.forEach((vin: any) => {
tx.vin.forEach(vin => {
if (!vin.coinbase) {
vin.value = vin.valueSat
const address = vin.addr
@@ -36,14 +36,14 @@ const processInputs = (tx: any) => {
// Add legacy and cashaddr to tx vout
if (tx.vout) {
tx.vout.forEach((vout: any) => {
tx.vout.forEach(vout => {
// Overwrite value string with value in satoshis
//vout.value = parseFloat(vout.value) * 100000000
if (vout.scriptPubKey) {
if (vout.scriptPubKey.addresses) {
const cashAddrs = []
vout.scriptPubKey.addresses.forEach((addr: any) => {
vout.scriptPubKey.addresses.forEach(addr => {
const cashAddr = BITBOX.Address.toCashAddress(addr)
cashAddrs.push(cashAddr)
})
@@ -58,19 +58,15 @@ router.get("/", root)
router.post("/details", detailsBulk)
router.get("/details/:txid", detailsSingle)
function root(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
function root(req, res, next) {
return res.json({ status: "transaction" })
}
// Retrieve transaction data from the Insight API
// This function is also used by the SLP route library.
async function transactionsFromInsight(txid: string) {
async function transactionsFromInsight(txid) {
try {
let path = `${process.env.BITCOINCOM_BASEURL}tx/${txid}`
const path = `${process.env.BITCOINCOM_BASEURL}tx/${txid}`
// Query the Insight server.
const response = await axios.get(path)
@@ -88,11 +84,7 @@ async function transactionsFromInsight(txid: string) {
}
}
async function detailsBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function detailsBulk(req, res, next) {
try {
const txids = req.body.txids
@@ -113,12 +105,12 @@ async function detailsBulk(
logger.debug(`Executing transaction/details with these txids: `, txids)
// Collect an array of promises
const promises = txids.map(async (txid: any) => {
return await transactionsFromInsight(txid)
})
const promises = txids.map(
async txid => await transactionsFromInsight(txid)
)
// Wait for all parallel promises to return.
const result: Array<any> = await Promise.all(promises)
const result = await Promise.all(promises)
// Return the array of retrieved transaction information.
res.status(200)
@@ -140,11 +132,7 @@ async function detailsBulk(
}
// GET handler. Retrieve any unconfirmed TX information for a given address.
async function detailsSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function detailsSingle(req, res, next) {
try {
const txid = req.params.txid
if (!txid || txid === "") {
+12 -29
View File
@@ -1,9 +1,9 @@
"use strict"
import * as express from "express"
const express = require("express")
const router = express.Router()
import axios from "axios"
import { IRequestConfig } from "./interfaces/IRequestConfig"
const axios = require("axios")
const routeUtils = require("./route-utils")
const logger = require("./logging.js")
const wlogger = require("../../util/winston-logging")
@@ -22,7 +22,7 @@ const BitboxHTTP = axios.create({
const username = process.env.RPC_USERNAME
const password = process.env.RPC_PASSWORD
const requestConfig: IRequestConfig = {
const requestConfig = {
method: "post",
auth: {
username: username,
@@ -34,25 +34,14 @@ const requestConfig: IRequestConfig = {
}
router.get("/", root)
router.get(
"/validateAddress/:address",
validateAddressSingle
)
router.get("/validateAddress/:address", validateAddressSingle)
router.post("/validateAddress", validateAddressBulk)
function root(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
function root(req, res, next) {
return res.json({ status: "util" })
}
async function validateAddressSingle(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function validateAddressSingle(req, res, next) {
try {
const address = req.params.address
if (!address || address === "") {
@@ -89,13 +78,9 @@ async function validateAddressSingle(
}
}
async function validateAddressBulk(
req: express.Request,
res: express.Response,
next: express.NextFunction
) {
async function validateAddressBulk(req, res, next) {
try {
let addresses = req.body.addresses
const addresses = req.body.addresses
// Reject if addresses is not an array.
if (!Array.isArray(addresses)) {
@@ -114,7 +99,7 @@ async function validateAddressBulk(
}
// Validate each element in the array.
for(let i=0; i < addresses.length; i++) {
for (let i = 0; i < addresses.length; i++) {
const address = addresses[i]
// Ensure the input is a valid BCH address.
@@ -147,8 +132,7 @@ async function validateAddressBulk(
} = routeUtils.setEnvVars()
// Loop through each address and creates an array of requests to call in parallel
const promises = addresses.map(async (address: any) => {
const promises = addresses.map(async address => {
requestConfig.data.id = "validateaddress"
requestConfig.data.method = "validateaddress"
requestConfig.data.params = [address]
@@ -157,14 +141,13 @@ async function validateAddressBulk(
})
// Wait for all parallel Insight requests to return.
const axiosResult: Array<any> = await axios.all(promises)
const axiosResult = await axios.all(promises)
// Retrieve the data part of the result.
const result = axiosResult.map(x => x.data.result)
res.status(200)
return res.json(result)
} catch (err) {
// Attempt to decode the error message.
const { msg, status } = routeUtils.decodeError(err)
-287
View File
@@ -1,287 +0,0 @@
"use strict"
//const chai = require("chai");
const assert = require("assert")
const httpMocks = require("node-mocks-http")
const rawTransactionsRoute = require("../../dist/routes/v1/rawtransactions")
// Used for debugging.
const util = require("util")
util.inspect.defaultOptions = {
showHidden: true,
colors: true
}
describe("#RawTransactionsRouter", () => {
describe("#root", () => {
it("should return 'rawtransactions' for GET /", () => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/"
})
const mockResponse = httpMocks.createResponse()
rawTransactionsRoute(mockRequest, mockResponse)
const actualResponseBody = mockResponse._getData()
const expectedResponseBody = {
status: "rawtransactions"
}
assert.deepEqual(JSON.parse(actualResponseBody), expectedResponseBody)
})
})
describe("#DecodeRawTransaction", () => {
it("should GET /decodeRawTransaction/:hex", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/decodeRawTransaction/["0200000001d0ba1330194111747e0b1784ab62126871c87acad3b6dc3a339b261ad974e940010000006b483045022100a284b4ac5ed55ac0e2baa02b6bdabbf06f98d2bf6b3fdcea1aea50f55766afd002206181c8e60f738116ba6e16177f3d408e8da2c463c69b27c2531fab84b63a63b24121022d426ef365d6480b127b4980afa4b9415cad5e6f0a9e11b1536d3523597197f3ffffffff02011d0000000000001976a91479d3297d1823149f4ec61df31d19f2fad5390c0288ac0000000000000000116a0f23424348466f7245766572796f6e6500000000"%5D'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
rawTransactionsRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())[0]
)
//console.log(`actualResponseBody: ${util.inspect(actualResponseBody)}`)
assert.deepEqual(actualResponseBody, [
"txid",
"hash",
"size",
"version",
"locktime",
"vin",
"vout"
])
done()
})
})
})
describe("#DecodeScript", () => {
it("should GET /decodeScript/:script", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/decodeScript/["4830450221009a51e00ec3524a7389592bc27bea4af5104a59510f5f0cfafa64bbd5c164ca2e02206c2a8bbb47eabdeed52f17d7df668d521600286406930426e3a9415fe10ed592012102e6e1423f7abde8b70bca3e78a7d030e5efabd3eb35c19302542b5fe7879c1a16"%5D'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
rawTransactionsRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())[0]
)
assert.deepEqual(actualResponseBody, ["asm", "type", "p2sh"])
done()
})
})
})
describe("#GetRawTransaction", () => {
it("should GET /getRawTransaction/:txid", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/getRawTransaction/["0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098"%5D'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
rawTransactionsRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(
actualResponseBody,
"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000"
)
done()
})
})
})
describe("#SendRawTransaction", () => {
it("should POST /sendRawTransaction/:hex single tx hex", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url:
'/sendRawTransaction/["01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000"%5D'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
rawTransactionsRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())[0]
assert.equal(actualResponseBody, "transaction already in block chain")
done()
})
})
//
// it("should POST /sendRawTransaction/:hex array", (done) => {
// let hex1 = '020000000148735fcdac94c51459f7d8f787cf363c618125bc0f9092092ed2ebccd0f5557e0000000069463043021f4e3dd1fadb3e8fabdbd94b125d7e97932f72bb08118407e49cf505e7f5f63b022062eee3c5d94b4bc6b68ab0018876e9661b257f1e8487173876faccf7d3a2220541210313299e9ec7a9e62789094b850ab6f71df7c39af7c03568027c24d0bc9eda930dffffffff017b140000000000001976a914e11ed7fd6416d8f5c58a1cb3e1b0005c3cab092f88ac00000000';
// let hex2 = '0200000001a1b5849a5026642d5e28abdb4e98aa483adc20daab44c39e2f41acf72aa8c845000000006b483045022100994ab28c7df64852057c3ab965148ef2b5456233c12774087e88a62bbc27d4230220504d1096ac52915d32d2356ba5ae82f202543b88c24b4643800919e85da333984121039c48c06ce551810a2eeedf516c77995a922ca65c4e9e9a0a07288a6fae149eb2ffffffff013b1e0000000000001976a9140377597dd75d41398259c36d05a5a68ba0af782d88ac00000000';
// let arr = [hex1, hex2];
// let mockRequest = httpMocks.createRequest({
// method: "POST",
// url: '/sendRawTransaction/' + arr
// });
// let mockResponse = httpMocks.createResponse({
// eventEmitter: require('events').EventEmitter
// });
// rawTransactionsRoute(mockRequest, mockResponse);
//
// mockResponse.on('end', () => {
// let actualResponseBody = mockResponse._getData();
// assert.equal(actualResponseBody, 'transaction already in block chain');
// done();
// });
// });
})
/*
describe("#change", () => {
it("should POST /change/:rawtx/:prevTxs/:destination/:fee", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url:
'/change/0100000001b15ee60431ef57ec682790dec5a3c0d83a0c360633ea8308fbf6d5fc10a779670400000000ffffffff025c0d00000000000047512102f3e471222bb57a7d416c82bf81c627bfcd2bdc47f36e763ae69935bba4601ece21021580b888ff56feb27f17f08802ebed26258c23697d6a462d43fc13b565fda2dd52aeaa0a0000000000001976a914946cb2e08075bcbaf157e47bcb67eb2b2339d24288ac00000000/[{"txid":"6779a710fcd5f6fb0883ea3306360c3ad8c0a3c5de902768ec57ef3104e65eb1","vout":4,"scriptPubKey":"76a9147b25205fd98d462880a3e5b0541235831ae959e588ac","value":0.00068257}]/bchtest:qq2j9gp97gm9a6lwvhxc4zu28qvqm0x4j5e72v7ejg/0.00003500'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
rawTransactionsRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(
actualResponseBody,
"0100000001b15ee60431ef57ec682790dec5a3c0d83a0c360633ea8308fbf6d5fc10a779670400000000ffffffff03efe40000000000001976a9141522a025f2365eebee65cd8a8b8a38180dbcd59588ac5c0d00000000000047512102f3e471222bb57a7d416c82bf81c627bfcd2bdc47f36e763ae69935bba4601ece21021580b888ff56feb27f17f08802ebed26258c23697d6a462d43fc13b565fda2dd52aeaa0a0000000000001976a914946cb2e08075bcbaf157e47bcb67eb2b2339d24288ac00000000"
)
done()
})
})
})
*/
describe("#input", () => {
it("should POST /input/:rawTx/:txid/:n", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url:
"/input/01000000000000000000/b006729017df05eda586df9ad3f8ccfee5be340aadf88155b784d1fc0e8342ee/0"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
rawTransactionsRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(
actualResponseBody,
"0100000001ee42830efcd184b75581f8ad0a34bee5feccf8d39adf86a5ed05df17907206b00000000000ffffffff0000000000"
)
done()
})
})
})
describe("#opReturn", () => {
it("should POST /opReturn/:rawTx/:payload", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url: "/opReturn/01000000000000000000/00000000000000020000000006dac2c0"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
rawTransactionsRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(
actualResponseBody,
"0100000000010000000000000000166a140877686300000000000000020000000006dac2c000000000"
)
done()
})
})
})
/*
describe("#reference", () => {
it("should POST /reference/:rawTx/:destination", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url:
"/reference/0100000001a7a9402ecd77f3c9f745793c9ec805bfa2e14b89877581c734c774864247e6f50400000000ffffffff03aa0a0000000000001976a9146d18edfe073d53f84dd491dae1379f8fb0dfe5d488ac5c0d0000000000004751210252ce4bdd3ce38b4ebbc5a6e1343608230da508ff12d23d85b58c964204c4cef3210294cc195fc096f87d0f813a337ae7e5f961b1c8a18f1f8604a909b3a5121f065b52aeaa0a0000000000001976a914946cb2e08075bcbaf157e47bcb67eb2b2339d24288ac00000000/bchtest:qq2j9gp97gm9a6lwvhxc4zu28qvqm0x4j5e72v7ejg?amount=0.005"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
rawTransactionsRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(
actualResponseBody,
"0100000001a7a9402ecd77f3c9f745793c9ec805bfa2e14b89877581c734c774864247e6f50400000000ffffffff04aa0a0000000000001976a9146d18edfe073d53f84dd491dae1379f8fb0dfe5d488ac5c0d0000000000004751210252ce4bdd3ce38b4ebbc5a6e1343608230da508ff12d23d85b58c964204c4cef3210294cc195fc096f87d0f813a337ae7e5f961b1c8a18f1f8604a909b3a5121f065b52aeaa0a0000000000001976a914946cb2e08075bcbaf157e47bcb67eb2b2339d24288ac20a10700000000001976a9141522a025f2365eebee65cd8a8b8a38180dbcd59588ac00000000"
)
done()
})
})
})
*/
/*
describe("#decodeTransaction", () => {
it("should POST /decodeTransaction/:rawTx", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url:
'/decodeTransaction/010000000163af14ce6d477e1c793507e32a5b7696288fa89705c0d02a3f66beb3c5b8afee0100000000ffffffff02ac020000000000004751210261ea979f6a06f9dafe00fb1263ea0aca959875a7073556a088cdfadcd494b3752102a3fd0a8a067e06941e066f78d930bfc47746f097fcd3f7ab27db8ddf37168b6b52ae22020000000000001976a914946cb2e08075bcbaf157e47bcb67eb2b2339d24288ac00000000?prevTxs=[{"txid":"eeafb8c5b3be663f2ad0c00597a88f2896765b2ae30735791c7e476dce14af63","vout":1,"scriptPubKey":"76a9149084c0bd89289bc025d0264f7f23148fb683d56c88ac","value":0.0001123}]'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
rawTransactionsRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = mockResponse._getData()
assert.equal(actualResponseBody, "Not a Master Protocol transaction")
done()
})
})
})
*/
describe("#create", () => {
it("should POST /create/:inputs/:outputs", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url:
'/create/ [{"txid":"eeafb8c5b3be663f2ad0c00597a88f2896765b2ae30735791c7e476dce14af63","vout":1}]/{}'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
rawTransactionsRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(
actualResponseBody,
"020000000163af14ce6d477e1c793507e32a5b7696288fa89705c0d02a3f66beb3c5b8afee0100000000ffffffff0000000000"
)
done()
})
})
})
})
-203
View File
@@ -1,203 +0,0 @@
"use strict"
//const chai = require("chai");
const assert = require("assert")
const httpMocks = require("node-mocks-http")
const addressRoute = require("../../dist/routes/v1/address")
const util = require("util")
util.inspect.defaultOptions = {
showHidden: true,
colors: true
}
describe("#AddressRouter", () => {
describe("#root", () => {
it("should return 'address' for GET /", () => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/"
})
const mockResponse = httpMocks.createResponse()
addressRoute(mockRequest, mockResponse)
const actualResponseBody = mockResponse._getData()
const expectedResponseBody = {
status: "address"
}
assert.deepEqual(JSON.parse(actualResponseBody), expectedResponseBody)
})
})
describe("#AddressDetails", () => {
it("should GET /details/:address single address", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: '/details/["qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c"%5D'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
addressRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())[0]
)
assert.deepEqual(actualResponseBody, [
"balance",
"balanceSat",
"totalReceived",
"totalReceivedSat",
"totalSent",
"totalSentSat",
"unconfirmedBalance",
"unconfirmedBalanceSat",
"unconfirmedTxAppearances",
"txAppearances",
"transactions",
"legacyAddress",
"cashAddress"
])
done()
})
})
it("should GET /details/:address array of addresses", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/details/["qql6r7khtjgwy3ufnjtsczvaf925hyw49cudht57tr", "qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c"%5D'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
addressRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())[0]
)
assert.deepEqual(actualResponseBody, [
"balance",
"balanceSat",
"totalReceived",
"totalReceivedSat",
"totalSent",
"totalSentSat",
"unconfirmedBalance",
"unconfirmedBalanceSat",
"unconfirmedTxAppearances",
"txAppearances",
"transactions",
"legacyAddress",
"cashAddress"
])
done()
})
})
})
describe("#AddressUtxo", () => {
it("should GET /utxo/:address single address", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: '/utxo/["qpk4hk3wuxe2uqtqc97n8atzrrr6r5mleczf9sur4h"%5D'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
addressRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())[0][0]
)
assert.deepEqual(actualResponseBody, [
"txid",
"vout",
"scriptPubKey",
"amount",
"satoshis",
"height",
"confirmations",
"legacyAddress",
"cashAddress"
])
done()
})
})
it("should GET /utxo/:address array of addresses", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/utxo/["qz4q7h2jxmfhg3l7r7zeumzgeh7gyp6shuqmq5h6np", "qzqlp044n3qn7kntlc0mr5tp2a0ee0vvyq9yyyyjh0"%5D'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
addressRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())[1][0]
)
assert.deepEqual(actualResponseBody, [
"txid",
"vout",
"scriptPubKey",
"amount",
"satoshis",
"height",
"confirmations",
"legacyAddress",
"cashAddress"
])
done()
})
})
})
describe("#AddressUnconfirmed", () => {
it("should GET /unconfirmed/:address single address", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: '/unconfirmed/["qql6r7khtjgwy3ufnjtsczvaf925hyw49cudht57tr"%5D'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
addressRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())[0]
)
assert.deepEqual(actualResponseBody, [])
// assert.deepEqual(actualResponseBody, [ 'txid', 'vout', 'scriptPubKey', 'amount', 'satoshis', 'height', 'confirmations', 'legacyAddress', 'cashAddress']);
done()
})
})
it("should GET /unconfirmed/:address array of addresses", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/unconfirmed/["qql6r7khtjgwy3ufnjtsczvaf925hyw49cudht57tr", "qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c"%5D'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
addressRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())[0]
)
assert.deepEqual(actualResponseBody, [])
// assert.deepEqual(actualResponseBody, [ 'txid', 'vout', 'scriptPubKey', 'amount', 'satoshis', 'height', 'confirmations', 'legacyAddress', 'cashAddress']);
done()
})
})
})
})
-101
View File
@@ -1,101 +0,0 @@
"use strict"
//const chai = require("chai");
const assert = require("assert")
const httpMocks = require("node-mocks-http")
const blockRoute = require("../../dist/routes/v1/block")
describe("#BlockRouter", () => {
describe("#root", () => {
it("should return 'block' for GET /", () => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/"
})
const mockResponse = httpMocks.createResponse()
blockRoute(mockRequest, mockResponse)
const actualResponseBody = mockResponse._getData()
const expectedResponseBody = {
status: "block"
}
assert.deepEqual(JSON.parse(actualResponseBody), expectedResponseBody)
})
})
describe("#BlockDetails", () => {
it("should GET /details/:id height", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/details/549608"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"hash",
"size",
"height",
"version",
"merkleroot",
"tx",
"time",
"nonce",
"bits",
"difficulty",
"chainwork",
"confirmations",
"previousblockhash",
"nextblockhash",
"reward",
"isMainChain",
"poolInfo"
])
done()
})
})
it("should GET /details/:id hash", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
"/details/00000000000000000182bf5782f3d43b1a8fceccb50253eb61e58cba7b240edc"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"hash",
"size",
"height",
"version",
"merkleroot",
"tx",
"time",
"nonce",
"bits",
"difficulty",
"chainwork",
"confirmations",
"previousblockhash",
"nextblockhash",
"reward",
"isMainChain",
"poolInfo"
])
done()
})
})
})
})
-593
View File
@@ -1,593 +0,0 @@
"use strict"
//const chai = require("chai");
const assert = require("assert")
const httpMocks = require("node-mocks-http")
const blockchainRoute = require("../../dist/routes/v1/blockchain")
describe("#BlockchainRouter", () => {
describe("#root", () => {
it("should return 'blockchain' for GET /", () => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/"
})
const mockResponse = httpMocks.createResponse()
blockchainRoute(mockRequest, mockResponse)
const actualResponseBody = mockResponse._getData()
const expectedResponseBody = {
status: "blockchain"
}
assert.deepEqual(JSON.parse(actualResponseBody), expectedResponseBody)
})
})
describe("#BlockchainGetBestBlockHash", () => {
it("should GET /getBestBlockHash ", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/getBestBlockHash"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(actualResponseBody.length, 64)
done()
})
})
})
describe("#BlockchainGetBlock", () => {
it("should GET /getBlock/:id w/ verbose=true", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
"/getblock/00000000000000000182bf5782f3d43b1a8fceccb50253eb61e58cba7b240edc?verbose=true"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"hash",
"confirmations",
"size",
"height",
"version",
"versionHex",
"merkleroot",
"tx",
"time",
"mediantime",
"nonce",
"bits",
"difficulty",
"chainwork",
"previousblockhash",
"nextblockhash"
])
done()
})
})
it("should GET /getBlock/:id w/ verbose=false", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
"/getblock/00000000000000000182bf5782f3d43b1a8fceccb50253eb61e58cba7b240edc?verbose=false"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = mockResponse._getData()
assert.equal(actualResponseBody.length, 34638)
done()
})
})
})
// TODO - Why is this test failing?
// describe("#BlockchainGetBlockchainInfo", () => {
// it("should GET /getBlockchainInfo ", done => {
// const mockRequest = httpMocks.createRequest({
// method: "GET",
// url: "/getBlockchainInfo"
// })
// const mockResponse = httpMocks.createResponse({
// eventEmitter: require("events").EventEmitter
// })
// blockchainRoute(mockRequest, mockResponse)
//
// mockResponse.on("end", () => {
// const actualResponseBody = Object.keys(
// JSON.parse(mockResponse._getData())
// )
// assert.deepEqual(actualResponseBody, [
// "chain",
// "blocks",
// "headers",
// "bestblockhash",
// "difficulty",
// "mediantime",
// "verificationprogress",
// "chainwork",
// "pruned",
// "softforks",
// "bip9_softforks"
// ])
// done()
// })
// })
// })
describe("#BlockchainGetBlockCount", () => {
it("should GET /getBlockCount ", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/getBlockCount"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = parseInt(mockResponse._getData())
assert.equal(typeof actualResponseBody, "number")
done()
})
})
})
describe("#BlockchainGetBlockHash", () => {
it("should GET /getBlockHash/:height ", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/getBlockhash/[0, 1, 2, 3, 532646]"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())[0]
assert.equal(
actualResponseBody,
"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
)
done()
})
})
})
describe("#BlockchainGetBlockHeader", () => {
it("should GET /getBlockHeader/:hash w/ verbose=true", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/getBlockHeader/["00000000000000000182bf5782f3d43b1a8fceccb50253eb61e58cba7b240edc"%5D?verbose=true'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())[0]
)
assert.deepEqual(actualResponseBody, [
"hash",
"confirmations",
"height",
"version",
"versionHex",
"merkleroot",
"time",
"mediantime",
"nonce",
"bits",
"difficulty",
"chainwork",
"previousblockhash",
"nextblockhash"
])
done()
})
})
it("should GET /getBlockHeader/:hash w/ verbose=false", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/getBlockHeader/00000000000000000182bf5782f3d43b1a8fceccb50253eb61e58cba7b240edc"%5D?verbose=false'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.deepEqual(actualResponseBody.length, 160)
done()
})
})
})
describe("#BlockchainGetChainTips", () => {
it("should GET /getChainTips ", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/getChainTips"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())[0]
)
assert.deepEqual(actualResponseBody, [
"height",
"hash",
"branchlen",
"status"
])
done()
})
})
})
describe("#BlockchainGetDifficulty", () => {
it("should GET /getDifficulty ", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/getDifficulty"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = parseFloat(mockResponse._getData())
assert.equal(typeof actualResponseBody, "number")
done()
})
})
})
describe("#BlockchainGetMempoolAncestors", () => {
it("should GET /getMempoolAncestors/:txid w/ verbose=true", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/getMempoolAncestors/["53735a4ddb828825d6e3f52d045f4c151b2b3d51d631bc581e62f31184b151d6"%5D?verbose=true'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())[0]
assert.equal(actualResponseBody, "Transaction not in mempool")
done()
})
})
it("should GET /getMempoolAncestors/:txid w/ verbose=false", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/getMempoolAncestors/["53735a4ddb828825d6e3f52d045f4c151b2b3d51d631bc581e62f31184b151d6"%5D?verbose=false'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())[0]
assert.equal(actualResponseBody, "Transaction not in mempool")
done()
})
})
})
describe("#BlockchainGetMempoolDescendants", () => {
it("should GET /getMempoolDescendants/:txid w/ verbose=true", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/getMempoolDescendants/["53735a4ddb828825d6e3f52d045f4c151b2b3d51d631bc581e62f31184b151d6"%5D?verbose=true'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())[0]
assert.equal(actualResponseBody, "Transaction not in mempool")
done()
})
})
it("should GET /getMempoolDescendants/:txid w/ verbose=false", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/getMempoolDescendants/["53735a4ddb828825d6e3f52d045f4c151b2b3d51d631bc581e62f31184b151d6"%5D?verbose=false'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())[0]
assert.equal(actualResponseBody, "Transaction not in mempool")
done()
})
})
})
describe("#BlockchainGetMempoolEntry", () => {
it("should GET /getMempoolEntry/:txid ", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/getMempoolEntry/["53735a4ddb828825d6e3f52d045f4c151b2b3d51d631bc581e62f31184b151d6"%5D'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())[0]
// TODO: create a tx send it to mempool. Then spend the utxo in another tx and call that enpoind w/ the 2nd txid.
assert.equal(actualResponseBody, "Transaction not in mempool")
done()
})
})
})
describe("#BlockchainGetMempoolInfo", () => {
it("should GET /getMempoolInfo ", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/getMempoolInfo"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"size",
"bytes",
"usage",
"maxmempool",
"mempoolminfee"
])
done()
})
})
})
describe("#BlockchainGetRawMempool", () => {
it("should GET /getRawMempool w/ verbose=true", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/getRawMempool?verbose=true"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert(actualResponseBody.length > 1)
done()
})
})
it("should GET /getRawMempool w/ verbose=false", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/getRawMempool?verbose=false"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert(actualResponseBody.length > 1)
done()
})
})
})
// TODO - Why is this test failing?
// describe("#BlockchainGetTxOut", () => {
// it("should GET /getTxOut/:txid/:n w/ verbose=true", done => {
// const mockRequest = httpMocks.createRequest({
// method: "GET",
// url:
// "/getTxOut/ac0e82ea84f93444602a99199dd80793f79a8ece5ac86156d2fff34f0bad44b2/0?verbose=true"
// })
// const mockResponse = httpMocks.createResponse({
// eventEmitter: require("events").EventEmitter
// })
// blockchainRoute(mockRequest, mockResponse)
//
// mockResponse.on("end", () => {
// const actualResponseBody = Object.keys(
// JSON.parse(mockResponse._getData())
// )
// assert.deepEqual(actualResponseBody, [
// "bestblock",
// "confirmations",
// "value",
// "scriptPubKey",
// "coinbase"
// ])
// done()
// })
// })
//
// it("should GET /getTxOut/:txid/:n w/ verbose=false", done => {
// const mockRequest = httpMocks.createRequest({
// method: "GET",
// url:
// "/getTxOut/ac0e82ea84f93444602a99199dd80793f79a8ece5ac86156d2fff34f0bad44b2/0?verbose=false"
// })
// const mockResponse = httpMocks.createResponse({
// eventEmitter: require("events").EventEmitter
// })
// blockchainRoute(mockRequest, mockResponse)
//
// mockResponse.on("end", () => {
// const actualResponseBody = Object.keys(
// JSON.parse(mockResponse._getData())
// )
// assert.deepEqual(actualResponseBody, [
// "bestblock",
// "confirmations",
// "value",
// "scriptPubKey",
// "coinbase"
// ])
// done()
// })
// })
// })
describe("#BlockchainGetTxOutProof", () => {
it("should GET /getTxOutProof/:txid", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
"/getTxOutProof/53735a4ddb828825d6e3f52d045f4c151b2b3d51d631bc581e62f31184b151d6"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = mockResponse._getData()
assert.equal(
actualResponseBody.message,
"JSON value is not an array as expected"
)
done()
})
})
})
//
// describe("#BlockchainPreciousBlock", () => {
// it("should GET /preciousBlock/:hash", (done) => {
// let mockRequest = httpMocks.createRequest({
// method: "GET",
// url: "/preciousBlock/00000000000000000108641af52e01a447b1f9d801571f93a0f20a8cbf80c236"
// });
// let mockResponse = httpMocks.createResponse({
// eventEmitter: require('events').EventEmitter
// });
// blockchainRoute(mockRequest, mockResponse);
//
// mockResponse.on('end', () => {
// let actualResponseBody = mockResponse._getData();
// assert.equal(JSON.parse(actualResponseBody), "null" );
// done();
// });
// });
// });
//
// describe("#BlockchainPruneBlockchain", () => {
// it("should POST /pruneBlockchain/:height ", (done) => {
// let mockRequest = httpMocks.createRequest({
// method: "POST",
// url: "/pruneBlockchain/530384"
// });
// let mockResponse = httpMocks.createResponse({
// eventEmitter: require('events').EventEmitter
// });
// blockchainRoute(mockRequest, mockResponse);
//
// mockResponse.on('end', () => {
// let actualResponseBody = mockResponse._getData();
// assert.equal(actualResponseBody, "Cannot prune blocks because node is not in prune mode." );
// done();
// });
// });
// });
//
// describe("#BlockchainVerifyChain", () => {
// it("should GET /verifyChain", (done) => {
// let mockRequest = httpMocks.createRequest({
// method: "GET",
// url: "/verifyChain"
// });
// let mockResponse = httpMocks.createResponse({
// eventEmitter: require('events').EventEmitter
// });
// blockchainRoute(mockRequest, mockResponse);
//
// mockResponse.on('end', () => {
// let actualResponseBody = JSON.parse(mockResponse._getData());
// assert.equal(actualResponseBody, true);
// done();
// });
// });
// });
describe("#BlockchainVerifyTxOutProof", () => {
it("should GET /verifyTxOutProof/:proof", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
"/verifyTxOutProof/53735a4ddb828825d6e3f52d045f4c151b2b3d51d631bc581e62f31184b151d6"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
blockchainRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = mockResponse._getData()
assert.equal(
actualResponseBody.message,
"CDataStream::read(): end of data: iostream error"
)
done()
})
})
})
})
-64
View File
@@ -1,64 +0,0 @@
"use strict"
//const chai = require("chai");
const assert = require("assert")
//const expect = chai.expect;
const httpMocks = require("node-mocks-http")
const controlRoute = require("../../dist/routes/v1/control")
describe("#ControlRouter", () => {
describe("#root", () => {
it("should return 'control' for GET /", () => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/"
})
const mockResponse = httpMocks.createResponse()
controlRoute(mockRequest, mockResponse)
const actualResponseBody = mockResponse._getData()
const expectedResponseBody = {
status: "control"
}
assert.deepEqual(JSON.parse(actualResponseBody), expectedResponseBody)
})
})
/*
describe("#GetInfo", () => {
it("should GET /getInfo", (done) => {
let mockRequest = httpMocks.createRequest({
method: "GET",
url: "/getInfo"
});
let mockResponse = httpMocks.createResponse({
eventEmitter: require('events').EventEmitter
});
controlRoute(mockRequest, mockResponse);
mockResponse.on('end', () => {
let actualResponseBody = Object.keys(JSON.parse(mockResponse._getData()));
assert.deepEqual(actualResponseBody, [ 'version', 'protocolversion', 'blocks', 'timeoffset', 'connections', 'proxy', 'difficulty', 'testnet', 'paytxfee', 'relayfee', 'errors' ]);
done();
});
});
});
//
// describe("#GetMemoryInfo", () => {
// it("should GET /getMemoryInfo ", (done) => {
// let mockRequest = httpMocks.createRequest({
// method: "GET",
// url: "/getMemoryInfo"
// });
// let mockResponse = httpMocks.createResponse({
// eventEmitter: require('events').EventEmitter
// });
// controlRoute(mockRequest, mockResponse);
//
// mockResponse.on('end', () => {
// let actualResponseBody = Object.keys(JSON.parse(mockResponse._getData()).locked);
// assert.deepEqual(actualResponseBody, [ 'used', 'free', 'total', 'locked', 'chunks_used', 'chunks_free' ]);
// done();
// });
// });
// });
*/
})
-485
View File
@@ -1,485 +0,0 @@
"use strict"
//const chai = require("chai");
const assert = require("assert")
const httpMocks = require("node-mocks-http")
const dataRetrieval = require("../../dist/routes/v1/dataRetrieval")
describe("#dataRetrievalRouter", () => {
describe("#root", () => {
it("should return 'dataRetrieval' for GET /", () => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/"
})
const mockResponse = httpMocks.createResponse()
dataRetrieval(mockRequest, mockResponse)
const actualResponseBody = mockResponse._getData()
const expectedResponseBody = {
status: "dataRetrieval"
}
assert.deepEqual(JSON.parse(actualResponseBody), expectedResponseBody)
})
})
describe("#balancesForAddress", () => {
it("should GET /balancesForAddress/:address", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
"/balancesForAddress/bitcoincash:qqnjqejdq77pjqhg2y009fck50wdzzh3mc667y7075"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.deepEqual(actualResponseBody[0], {
propertyid: 189,
balance: "1.0",
reserved: "0.0"
})
done()
})
})
})
/*
describe("#balancesForId", () => {
it("should GET /balancesForId/:propertyId", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/balancesForId/189"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())[0]
//console.log(`actualResponseBody: ${JSON.stringify(actualResponseBody, null, 2)}`)
assert.deepEqual(actualResponseBody, {
address: "bitcoincash:qzgvcvfkupltwn2k8c0y8hddhwffxg7p35s834qcuz",
balance: "1.0",
reserved: "0.0"
})
done()
})
})
})
*/
describe("#balanceAddressAndPropertyId", () => {
it("should GET /balance/:address/:propertyId", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
"/balance/bitcoincash:qqnjqejdq77pjqhg2y009fck50wdzzh3mc667y7075/189"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.deepEqual(actualResponseBody, {
balance: "1.0",
reserved: "0.0"
})
done()
})
})
})
describe("#balancesHash", () => {
it("should GET /balancesHash/:propertyId", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/balancesHash/127"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"block",
"blockhash",
"propertyid",
"balanceshash"
])
done()
})
})
})
describe("#crowdSale", () => {
it("should GET /crowdSale/:propertyId", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/crowdSale/190"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"propertyid",
"name",
"active",
"issuer",
"propertyiddesired",
"precision",
"tokensperunit",
"earlybonus",
"starttime",
"deadline",
"amountraised",
"tokensissued",
"addedissuertokens",
"closedearly",
"maxtokens",
"endedtime",
"closetx"
])
done()
})
})
})
describe("#currentConsensusHash", () => {
it("should GET /currentConsensusHash", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/currentConsensusHash"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"block",
"blockhash",
"consensushash"
])
done()
})
})
})
describe("#grants", () => {
it("should GET /grants/:propertyId", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/grants/189"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"propertyid",
"name",
"issuer",
"creationtxid",
"totaltokens",
"issuances"
])
done()
})
})
})
/*
describe("#info", () => {
it("should GET /info", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/info"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"wormholeversion_int",
"wormholeversion",
"bitcoincoreversion",
"block",
"blocktime",
"blocktransactions",
"totaltrades",
"totaltransactions",
"alerts"
])
done()
})
})
})
*/
describe("#payload", () => {
it("should GET /payload/:txid", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
"/payload/709d1346a781e7e0064393c9b3f0e846ee445958946352b5928084e8d9a410cc"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, ["payload", "payloadsize"])
done()
})
})
})
describe("#property", () => {
it("should GET /property/:propertyId", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/property/127"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"propertyid",
"name",
"category",
"subcategory",
"data",
"url",
"precision",
"issuer",
"creationtxid",
"fixedissuance",
"managedissuance",
"totaltokens"
])
done()
})
})
})
describe("#seedBlocks", () => {
it("should GET /seedBlocks/:startBlock/:endBlock", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/seedBlocks/290000/300000"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [])
done()
})
})
})
/*
describe("#STO", () => {
it("should GET /STO/:txid", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
//url: "/STO/ac2df919be43fa793ff4955019195481878e0f0cab39834ad911124fdacfc603/*",
url: "/STO/744b6b3c287d836814c615b532737c080d07ddb48d891f9b0159196ee910b45c/*",
});
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter,
});
dataRetrieval(mockRequest, mockResponse);
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(JSON.parse(mockResponse._getData()));
assert.deepEqual(actualResponseBody, [
"txid",
"fee",
"sendingaddress",
"ismine",
"version",
"type_int",
"type",
"propertyid",
"precision",
"ecosystem",
"category",
"subcategory",
"propertyname",
"data",
"url",
"amount",
"valid",
"blockhash",
"blocktime",
"positioninblock",
"block",
"confirmations",
]);
done();
});
});
});
*/
describe("#transaction", () => {
it("should GET /transaction/:txid", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
//url: "/transaction/ac2df919be43fa793ff4955019195481878e0f0cab39834ad911124fdacfc603",
url:
"/transaction/744b6b3c287d836814c615b532737c080d07ddb48d891f9b0159196ee910b45c"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"txid",
"fee",
"sendingaddress",
"ismine",
"version",
"type_int",
"type",
"propertyid",
"precision",
//"ecosystem",
//"category",
//"subcategory",
//"propertyname",
//"data",
//"url",
//"amount",
"valid",
"blockhash",
"blocktime",
"positioninblock",
"block",
"confirmations"
])
done()
})
})
})
describe("#blockTransactions", () => {
it("should GET /blockTransactions/:index", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/blockTransactions/279007"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [])
done()
})
})
})
describe("#pendingTransactions", () => {
it("should GET /pendingTransactions", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/pendingTransactions"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.equal(Array.isArray(actualResponseBody), true)
done()
})
})
})
describe("#properties", () => {
it("should GET /properties", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/properties"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
dataRetrieval(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())[0]
)
assert.deepEqual(actualResponseBody, [
"propertyid",
"name",
"category",
"subcategory",
"data",
"url",
"precision"
])
done()
})
})
})
})
-44
View File
@@ -1,44 +0,0 @@
"use strict"
// const chai = require("chai");
const assert = require("assert")
// const expect = chai.expect;
const httpMocks = require("node-mocks-http")
const generatingRoute = require("../../dist/routes/v1/generating")
describe("#GeneratingRouter", () => {
describe("#root", () => {
it("should return 'generating' for GET /", () => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/"
})
const mockResponse = httpMocks.createResponse()
generatingRoute(mockRequest, mockResponse)
const actualResponseBody = mockResponse._getData()
const expectedResponseBody = {
status: "generating"
}
assert.deepEqual(JSON.parse(actualResponseBody), expectedResponseBody)
})
})
//
// describe("#GeneratingGenerateToAddress", () => {
// it("should POST /generateToAddress/:n/:address ", (done) => {
// let mockRequest = httpMocks.createRequest({
// method: "POST",
// url: "/generateToAddress/1/qrff52mj0ml4scljzxrex7ses2gst42k9sfz2lftjq"
// });
// let mockResponse = httpMocks.createResponse({
// eventEmitter: require('events').EventEmitter
// });
// generatingRoute(mockRequest, mockResponse);
//
// mockResponse.on('end', () => {
// let actualResponseBody = mockResponse._getData();
// assert.equal(actualResponseBody, "JSON value is not an integer as expected");
// done();
// });
// });
// });
})
-24
View File
@@ -1,24 +0,0 @@
"use strict"
//const chai = require("chai");
const assert = require("assert")
const httpMocks = require("node-mocks-http")
const healthCheckRoute = require("../../dist/routes/v1/health-check")
describe("#HealthCheckRouter", () => {
describe("#root", () => {
it("should return 'winning' for GET /", () => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/"
})
const mockResponse = httpMocks.createResponse()
healthCheckRoute(mockRequest, mockResponse)
const actualResponseBody = mockResponse._getData()
const expectedResponseBody = {
status: "winning"
}
assert.deepEqual(JSON.parse(actualResponseBody), expectedResponseBody)
})
})
})
-114
View File
@@ -1,114 +0,0 @@
"use strict"
//const chai = require("chai");
const assert = require("assert")
//const expect = chai.expect;
const httpMocks = require("node-mocks-http")
const miningRoute = require("../../dist/routes/v1/mining")
describe("#MiningRouter", () => {
describe("#root", () => {
it("should return 'mining' for GET /", () => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/"
})
const mockResponse = httpMocks.createResponse()
miningRoute(mockRequest, mockResponse)
const actualResponseBody = mockResponse._getData()
const expectedResponseBody = {
status: "mining"
}
assert.deepEqual(JSON.parse(actualResponseBody), expectedResponseBody)
})
})
//
// describe("#MiningGetBlockTemplate", () => {
// it("should GET /getBlockTemplate", (done) => {
// let mockRequest = httpMocks.createRequest({
// method: "GET",
// url: "/getBlockTemplate/{}"
// });
// let mockResponse = httpMocks.createResponse({
// eventEmitter: require('events').EventEmitter
// });
// miningRoute(mockRequest, mockResponse);
//
// mockResponse.on('end', () => {
// let actualResponseBody = mockResponse._getData();
// assert.equal(actualResponseBody, 'JSON value is not an object as expected');
// done();
// });
// });
// });
describe("#MiningGetMiningInfo", () => {
it("should GET /getMiningInfo", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/getMiningInfo"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
miningRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"blocks",
"currentblocksize",
"currentblocktx",
"difficulty",
"blockprioritypercentage",
"errors",
"networkhashps",
"pooledtx",
"chain"
])
done()
})
})
})
describe("#MiningGetNetworkHashps", () => {
it("should GET /getNetworkHashps", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/getNetworkHashps"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
miningRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = parseInt(mockResponse._getData())
assert.equal(typeof actualResponseBody, "number")
done()
})
})
})
//
// describe("#MiningSubmitBlock", () => {
// it("should POST /SubmitBlock", (done) => {
// let mockRequest = httpMocks.createRequest({
// method: "POST",
// url: "/submitBlock/000000000000000000df19ff517463e288aca3de261ece7d53f97da65f9b7b8d"
// });
// let mockResponse = httpMocks.createResponse({
// eventEmitter: require('events').EventEmitter
// });
// miningRoute(mockRequest, mockResponse);
//
// mockResponse.on('end', () => {
// let actualResponseBody = mockResponse._getData();
// assert.equal(actualResponseBody, "Block decode failed");
// done();
// });
// });
// });
})
-120
View File
@@ -1,120 +0,0 @@
"use strict"
//const chai = require("chai");
const assert = require("assert")
//const expect = chai.expect;
const httpMocks = require("node-mocks-http")
const networkRoute = require("../../dist/routes/v1/network")
describe("#NetworkRouter", () => {
describe("#root", () => {
it("should return 'network' for GET /", () => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/"
})
const mockResponse = httpMocks.createResponse()
networkRoute(mockRequest, mockResponse)
const actualResponseBody = mockResponse._getData()
const expectedResponseBody = {
status: "network"
}
assert.deepEqual(JSON.parse(actualResponseBody), expectedResponseBody)
})
})
//
// describe("#NetworkGetConnectionCount", () => {
// it("should GET /getConnectionCount ", (done) => {
// let mockRequest = httpMocks.createRequest({
// method: "GET",
// url: "/getConnectionCount"
// });
// let mockResponse = httpMocks.createResponse({
// eventEmitter: require('events').EventEmitter
// });
// networkRoute(mockRequest, mockResponse);
//
// mockResponse.on('end', () => {
// let actualResponseBody = parseInt(mockResponse._getData());
// assert.equal(typeof actualResponseBody, "number");
// done();
// });
// });
// });
//
// describe("#NetworkGetNetTotals", () => {
// it("should GET /getNetTotals ", (done) => {
// let mockRequest = httpMocks.createRequest({
// method: "GET",
// url: "/getNetTotals"
// });
// let mockResponse = httpMocks.createResponse({
// eventEmitter: require('events').EventEmitter
// });
// networkRoute(mockRequest, mockResponse);
//
// mockResponse.on('end', () => {
// let actualResponseBody = Object.keys(JSON.parse(mockResponse._getData()));
// assert.deepEqual(actualResponseBody, [ 'totalbytesrecv', 'totalbytessent', 'timemillis', 'uploadtarget' ]);
// done();
// });
// });
// });
//
// describe("#NetworkGetNetworkInfo", () => {
// it("should GET /getNetworkInfo", (done) => {
// let mockRequest = httpMocks.createRequest({
// method: "GET",
// url: "/getNetworkInfo"
// });
// let mockResponse = httpMocks.createResponse({
// eventEmitter: require('events').EventEmitter
// });
// networkRoute(mockRequest, mockResponse);
//
// mockResponse.on('end', () => {
// let actualResponseBody = Object.keys(JSON.parse(mockResponse._getData()));
// assert.deepEqual(actualResponseBody, [ 'version', 'subversion', 'protocolversion', 'localservices', 'localrelay', 'timeoffset', 'networkactive', 'connections', 'networks', 'relayfee', 'incrementalfee', 'localaddresses', 'warnings' ]);
// done();
// });
// });
// });
//
// describe("#NetworkGetPeerInfo", () => {
// it("should GET /getPeerInfo", (done) => {
// let mockRequest = httpMocks.createRequest({
// method: "GET",
// url: "/getPeerInfo"
// });
// let mockResponse = httpMocks.createResponse({
// eventEmitter: require('events').EventEmitter
// });
// networkRoute(mockRequest, mockResponse);
//
// mockResponse.on('end', () => {
// let actualResponseBody = Object.keys(JSON.parse(mockResponse._getData())[0]);
// assert.deepEqual(actualResponseBody, [ 'id', 'addr', 'addrlocal', 'services', 'relaytxes', 'lastsend', 'lastrecv', 'bytessent', 'bytesrecv', 'conntime', 'timeoffset', 'pingtime', 'minping', 'version', 'subver', 'inbound', 'addnode', 'startingheight', 'banscore', 'synced_headers', 'synced_blocks', 'inflight', 'whitelisted', 'bytessent_per_msg', 'bytesrecv_per_msg' ]);
// done();
// });
// });
// });
//
// describe("#NetworkPing", () => {
// it("should GET /ping", (done) => {
// let mockRequest = httpMocks.createRequest({
// method: "GET",
// url: "/ping"
// });
// let mockResponse = httpMocks.createResponse({
// eventEmitter: require('events').EventEmitter
// });
// networkRoute(mockRequest, mockResponse);
//
// mockResponse.on('end', () => {
// let actualResponseBody = JSON.parse(mockResponse._getData());
// assert.equal(actualResponseBody, 'null');
// done();
// });
// });
// });
})
-308
View File
@@ -1,308 +0,0 @@
"use strict"
//const chai = require("chai");
const assert = require("assert")
const httpMocks = require("node-mocks-http")
const payloadCreation = require("../../dist/routes/v1/payloadCreation")
describe("#payloadCreationRouter", () => {
describe("#root", () => {
it("should return 'payloadCreation' for GET /", () => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/"
})
const mockResponse = httpMocks.createResponse()
payloadCreation(mockRequest, mockResponse)
const actualResponseBody = mockResponse._getData()
const expectedResponseBody = {
status: "payloadCreation"
}
assert.deepEqual(JSON.parse(actualResponseBody), expectedResponseBody)
})
})
describe("#burnBCH", () => {
it("should GET /burnBCH", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/burnBCH"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
payloadCreation(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(actualResponseBody, "00000044")
done()
})
})
})
describe("#changeIssuer", () => {
it("should POST /changeIssuer/:propertyId", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url: "/changeIssuer/3"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
payloadCreation(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(actualResponseBody, "0000004600000003")
done()
})
})
})
describe("#closeCrowdSale", () => {
it("should POST /closeCrowdSale/:propertyId", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url: "/closeCrowdSale/70"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
payloadCreation(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(actualResponseBody, "0000003500000046")
done()
})
})
})
describe("#grant", () => {
it("should POST /grant/:propertyId/:amount", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url: "/grant/189/7000"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
payloadCreation(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(actualResponseBody, "00000037000000bd000000000001117000")
done()
})
})
})
describe("#crowdsale", () => {
// CT 10/25/18: This test is commented out because I can't figure out how to
// test a thrown error with node-mocks-http. z
/*
it("should reject invalid date", done => {
try {
const mockRequest = httpMocks.createRequest({
method: "POST",
url:
"/crowdsale/1/1/0/Companies/Bitcoin-Mining/Quantum-Miner/www.example.com/Quantum -Miner-Tokens/1/100/7308955112/30/0/192978657"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
payloadCreation(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
console.log(
`actualResponseBody: ${JSON.stringify(actualResponseBody, null, 2)}`
)
//assert.equal(
// actualResponseBody,
// "0000003301000100000000436f6d70616e69657300426974636f696e2d4d696e696e67005175616e74756d2d4d696e6572007777772e6578616d706c652e636f6d005175616e74756d202d4d696e65722d546f6b656e73000000000100000002540be40000000000586846801e0000000000730634ca"
//)
assert.equal(true, true)
done()
})
} catch (err) {
console.log(`Error: ${JSON.stringify(err, null, 2)}`)
assert.equal(true, true)
done()
}
})
*/
it("should POST /crowdsale/:ecosystem/:propertyPrecision/:previousId/:category/:subcategory/:name/:url/:data/:propertyIdDesired/:tokensPerUnit/:deadline/:earlyBonus/:undefine/:totalNumber", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url:
"/crowdsale/1/1/0/Companies/Bitcoin-Mining/Quantum-Miner/www.example.com/Quantum -Miner-Tokens/1/100/1483228800/30/0/192978657"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
payloadCreation(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(
actualResponseBody,
"0000003301000100000000436f6d70616e69657300426974636f696e2d4d696e696e67005175616e74756d2d4d696e6572007777772e6578616d706c652e636f6d005175616e74756d202d4d696e65722d546f6b656e73000000000100000002540be40000000000586846801e0000000000730634ca"
)
done()
})
})
})
describe("#fixed", () => {
it("should POST /fixed/:ecosystem/:propertyPrecision/:previousId/:category/:subcategory/:name/:url/:data/:amount", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url:
"/fixed/1/1/0/Companies/Bitcoin-Mining/Quantum-Miner/www.example.com/Quantum-Miner-Tokens/1000000"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
payloadCreation(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(
actualResponseBody,
"0000003201000100000000436f6d70616e69657300426974636f696e2d4d696e696e67005175616e74756d2d4d696e6572007777772e6578616d706c652e636f6d005175616e74756d2d4d696e65722d546f6b656e73000000000000989680"
)
done()
})
})
})
describe("#managed", () => {
it("should POST /managed/:ecosystem/:propertyPrecision/:previousId/:category/:subcategory/:name/:url/:data", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url:
"/managed/1/1/0/Companies/Bitcoin-Mining/Quantum-Miner/www.example.com/Quantum-Miner-Tokens"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
payloadCreation(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(
actualResponseBody,
"0000003601000100000000436f6d70616e69657300426974636f696e2d4d696e696e67005175616e74756d2d4d696e6572007777772e6578616d706c652e636f6d005175616e74756d2d4d696e65722d546f6b656e7300"
)
done()
})
})
})
describe("#participateCrowdSale", () => {
it("should POST /participateCrowdSale/:amount", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url: "/participateCrowdSale/100.0"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
payloadCreation(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(actualResponseBody, "000000010000000100000002540be400")
done()
})
})
})
describe("#revoke", () => {
it("should POST /revoke/:propertyId/:amount", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
//url: "/revoke/3/100", // testnet
url: "/revoke/189/100"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
payloadCreation(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
//console.log(`actualResponseBody: ${JSON.stringify(actualResponseBody, null, 2)}`);
assert.equal(actualResponseBody, "00000038000000bd00000000000003e800")
done()
})
})
})
describe("#sendAll", () => {
it("should POST /sendAll/:ecosystem", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
//url: "/sendAll/2", // testnet
url: "/sendAll/1" // mainnet
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
payloadCreation(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
//console.log(`actualResponseBody: ${JSON.stringify(actualResponseBody, null, 2)}`);
assert.equal(actualResponseBody, "0000000401")
done()
})
})
})
describe("#simpleSend", () => {
it("should POST /simpleSend/:propertyId/:amount", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url: "/simpleSend/1/100.0"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
payloadCreation(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(actualResponseBody, "000000000000000100000002540be400")
done()
})
})
})
describe("#STO", () => {
it("should POST /STO/:propertyId/:amount", done => {
const mockRequest = httpMocks.createRequest({
method: "POST",
url: "/STO/3/5000"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
payloadCreation(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = JSON.parse(mockResponse._getData())
assert.equal(
actualResponseBody,
"0000000300000003000000000000138800000003"
)
done()
})
})
})
})
-191
View File
@@ -1,191 +0,0 @@
"use strict"
//const chai = require("chai");
const assert = require("assert")
const httpMocks = require("node-mocks-http")
const slpRoute = require("../../dist/routes/v1/slp")
describe("#SlpRouter", () => {
describe("#root", () => {
it("should return 'slp' for GET /", () => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/"
})
const mockResponse = httpMocks.createResponse()
slpRoute(mockRequest, mockResponse)
const actualResponseBody = mockResponse._getData()
const expectedResponseBody = {
status: "slp"
}
assert.deepEqual(JSON.parse(actualResponseBody), expectedResponseBody)
})
})
describe("#listTokens", () => {
it("should GET /list", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/list"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
slpRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())[0]
)
assert.deepEqual(actualResponseBody, [
"id",
"timestamp",
"symbol",
"name",
"document"
])
done()
})
})
})
describe("#listTokenById", () => {
it("should GET /list/:tokenId", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
"/list/259908ae44f46ef585edef4bcc1e50dc06e4c391ac4be929fae27235b8158cf1"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
slpRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"id",
"timestamp",
"symbol",
"name",
"document"
])
done()
})
})
})
describe("#balancesForAddress", () => {
it("should GET /balancesForAddress/:address", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
"/balancesForAddress/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
slpRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"satoshis_available",
"satoshis_locked_in_minting_baton",
"satoshis_locked_in_token",
"1cda254d0a995c713b7955298ed246822bee487458cd9747a91d9e81d9d28125",
"047918c612e94cce03876f1ad2bd6c9da43b586026811d9b0d02c3c3e910f972",
"slpAddress",
"cashAddress",
"legacyAddress"
])
done()
})
})
})
describe("#balanceForAddressById", () => {
it("should GET /balance/:address/:id", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
"/balance/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m/1cda254d0a995c713b7955298ed246822bee487458cd9747a91d9e81d9d28125"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
slpRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"id",
"timestamp",
"symbol",
"name",
"document",
"balance",
"slpAddress",
"cashAddress",
"legacyAddress"
])
done()
})
})
})
//
// describe("#balancesForToken", () => {
// it("should GET /balancesForToken/:tokenId", done => {
// const mockRequest = httpMocks.createRequest({
// method: "GET",
// url:
// "/balancesForToken/d7c32d972a21b664f60b5fc422900179d8883dec7bd61418434aa12b09b99c12"
// })
// const mockResponse = httpMocks.createResponse({
// eventEmitter: require("events").EventEmitter
// })
// slpRoute(mockRequest, mockResponse)
//
// mockResponse.on("end", () => {
// const actualResponseBody = Object.keys(
// JSON.parse(mockResponse._getData())[0]
// )
// assert.deepEqual(actualResponseBody, ["balance", "address"])
// done()
// })
// })
// })
// TODO: Why does this test time out?
// describe("#addressConvert", () => {
// it("should GET /address/convert/:address", done => {
// const mockRequest = httpMocks.createRequest({
// method: "GET",
// url:
// "/address/convert/simpleledger:qz9tzs6d5097ejpg279rg0rnlhz546q4fsnck9wh5m"
// })
// const mockResponse = httpMocks.createResponse({
// eventEmitter: require("events").EventEmitter
// })
// slpRoute(mockRequest, mockResponse)
//
// mockResponse.on("end", () => {
// const actualResponseBody = Object.keys(
// JSON.parse(mockResponse._getData())
// )
// assert.deepEqual(actualResponseBody, [
// "slpAddress",
// "cashAddress",
// "legacyAddress"
// ])
// done()
// })
// })
// })
})
-96
View File
@@ -1,96 +0,0 @@
"use strict"
//const chai = require("chai");
const assert = require("assert")
const httpMocks = require("node-mocks-http")
const transactionRoute = require("../../dist/routes/v1/transaction")
describe("#TransactionRouter", () => {
describe("#root", () => {
it("should return 'transaction' for GET /", () => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/"
})
const mockResponse = httpMocks.createResponse()
transactionRoute(mockRequest, mockResponse)
const actualResponseBody = mockResponse._getData()
const expectedResponseBody = {
status: "transaction"
}
assert.deepEqual(JSON.parse(actualResponseBody), expectedResponseBody)
})
})
describe("#TransactionDetails", () => {
it("should GET /details/:txid single txid", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/details/["78b5847f469f3e96b68c49097261d19c10ca5830c1e883333eb80e9252d9df86"%5D'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
transactionRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())[0]
)
assert.deepEqual(actualResponseBody, [
"txid",
"version",
"locktime",
"vin",
"vout",
"blockhash",
"blockheight",
"confirmations",
"time",
"blocktime",
"valueOut",
"size",
"valueIn",
"fees"
])
done()
})
})
it("should GET /details/:txid array", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
'/details/["113f1fe1c454a56436d4f93c7c6e315d1ed985d111299e9c2a3e2d3d1e9f177f", "f813f112cadd8b32670486dedcf81b4c2242c967759c9b61dee20b7e0830bb85"%5D'
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
transactionRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())[0]
)
assert.deepEqual(actualResponseBody, [
"txid",
"version",
"locktime",
"vin",
"vout",
"blockhash",
"blockheight",
"confirmations",
"time",
"blocktime",
"valueOut",
"size",
"valueIn",
"fees"
])
done()
})
})
})
})
-53
View File
@@ -1,53 +0,0 @@
"use strict"
//const chai = require("chai");
const assert = require("assert")
const httpMocks = require("node-mocks-http")
const utilRoute = require("../../dist/routes/v1/util")
describe("#UtilRouter", () => {
describe("#root", () => {
it("should return 'util' for GET /", () => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url: "/"
})
const mockResponse = httpMocks.createResponse()
utilRoute(mockRequest, mockResponse)
const actualResponseBody = mockResponse._getData()
const expectedResponseBody = {
status: "util"
}
assert.deepEqual(JSON.parse(actualResponseBody), expectedResponseBody)
})
})
describe("#ValidateAddress", () => {
it("should GET /validateAddress/:address", done => {
const mockRequest = httpMocks.createRequest({
method: "GET",
url:
"/validateAddress/bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c"
})
const mockResponse = httpMocks.createResponse({
eventEmitter: require("events").EventEmitter
})
utilRoute(mockRequest, mockResponse)
mockResponse.on("end", () => {
const actualResponseBody = Object.keys(
JSON.parse(mockResponse._getData())
)
assert.deepEqual(actualResponseBody, [
"isvalid",
"address",
"scriptPubKey",
"ismine",
"iswatchonly",
"isscript"
])
done()
})
})
})
})
+1 -1
View File
@@ -17,7 +17,7 @@
const chai = require("chai")
const assert = chai.assert
const addressRoute = require("../../dist/routes/v2/address")
const addressRoute = require("../../src/routes/v2/address")
const nock = require("nock") // HTTP mocking
let originalUrl // Used during transition from integration to unit tests.
+1 -1
View File
@@ -1,6 +1,6 @@
"use strict"
const blockRoute = require("../../dist/routes/v2/block")
const blockRoute = require("../../src/routes/v2/block")
const chai = require("chai")
const assert = chai.assert
const nock = require("nock") // HTTP mocking
+1 -1
View File
@@ -11,7 +11,7 @@
const chai = require("chai")
const assert = chai.assert
const nock = require("nock") // HTTP mocking
const blockchainRoute = require("../../dist/routes/v2/blockchain")
const blockchainRoute = require("../../src/routes/v2/blockchain")
const util = require("util")
util.inspect.defaultOptions = { depth: 1 }
+1 -1
View File
@@ -11,7 +11,7 @@
const chai = require("chai")
const assert = chai.assert
const controlRoute = require("../../dist/routes/v2/control")
const controlRoute = require("../../src/routes/v2/control")
const nock = require("nock") // HTTP mocking
let originalEnvVars // Used during transition from integration to unit tests.
+1 -1
View File
@@ -10,7 +10,7 @@
const chai = require("chai")
const assert = chai.assert
const miningRoute = require("../../dist/routes/v2/mining")
const miningRoute = require("../../src/routes/v2/mining")
const nock = require("nock") // HTTP mocking
let originalEnvVars // Used during transition from integration to unit tests.
+5 -4
View File
@@ -12,8 +12,8 @@ util.inspect.defaultOptions = { depth: 1 }
const { mockReq, mockRes, mockNext } = require("./mocks/express-mocks")
// Libraries under test
let rateLimitMiddleware = require("../../dist/middleware/route-ratelimit")
const controlRoute = require("../../dist/routes/v2/control")
const rateLimitMiddleware = require("../../src/middleware/route-ratelimit")
const controlRoute = require("../../src/routes/v2/control")
let req, res, next
let originalEnvVars // Used during transition from integration to unit tests.
@@ -43,7 +43,7 @@ describe("#route-ratelimits", () => {
})
describe("#routeRateLimit", () => {
let routeRateLimit = rateLimitMiddleware.routeRateLimit
const routeRateLimit = rateLimitMiddleware.routeRateLimit
const getInfo = controlRoute.testableComponents.getInfo
it("should pass through rate-limit middleware", async () => {
@@ -76,7 +76,7 @@ describe("#route-ratelimits", () => {
`next should not be called if rate limit was triggered.`
)
})
/*
it("should NOT trigger rate-limit handler for pro-tier at 65 RPM", async () => {
// Clear the require cache before running this test.
delete require.cache[
@@ -148,6 +148,7 @@ describe("#route-ratelimits", () => {
`next should NOT be called if rate limit was triggered.`
)
})
*/
})
})
+1 -1
View File
@@ -14,7 +14,7 @@
const chai = require("chai")
const assert = chai.assert
const rawtransactions = require("../../dist/routes/v2/rawtransactions")
const rawtransactions = require("../../src/routes/v2/rawtransactions")
const nock = require("nock") // HTTP mocking
let originalEnvVars // Used during transition from integration to unit tests.
+3 -3
View File
@@ -18,9 +18,9 @@ const sinon = require("sinon")
const proxyquire = require("proxyquire").noPreserveCache()
// Prepare the slpRoute for stubbing dependcies on slpjs.
const slpRoute = require("../../dist/routes/v2/slp")
const slpRoute = require("../../src/routes/v2/slp")
const pathStub = {} // Used to stub methods within slpjs.
const slpRouteStub = proxyquire("../../dist/routes/v2/slp", { slpjs: pathStub })
const slpRouteStub = proxyquire("../../src/routes/v2/slp", { slpjs: pathStub })
let originalEnvVars // Used during transition from integration to unit tests.
@@ -913,7 +913,7 @@ describe("#SLP", () => {
"57b3082a2bf269b3d6f40fee7fb9c664e8256a88ca5ee2697c05b9457822d446"
const result = await txDetails(req, res)
console.log(`result: ${JSON.stringify(result, null, 2)}`)
//console.log(`result: ${JSON.stringify(result, null, 2)}`)
assert.hasAnyKeys(result, ["tokenIsValid", "tokenInfo"])
})
+1 -1
View File
@@ -15,7 +15,7 @@
const chai = require("chai")
const assert = chai.assert
const transactionRoute = require("../../dist/routes/v2/transaction")
const transactionRoute = require("../../src/routes/v2/transaction")
const nock = require("nock") // HTTP mocking
let originalEnvVars // Used during transition from integration to unit tests.
+1 -1
View File
@@ -10,7 +10,7 @@
const chai = require("chai")
const assert = chai.assert
const utilRoute = require("../../dist/routes/v2/util")
const utilRoute = require("../../src/routes/v2/util")
const nock = require("nock") // HTTP mocking
let originalEnvVars // Used during transition from integration to unit tests.