Browse Source

basic support for addresses

- address page
- search-by-address
fix-133-memory-crash
Dan Janosik 7 years ago
parent
commit
1faa91ec3b
  1. 19
      app/rpcApi.js
  2. 1
      package.json
  3. 57
      routes/baseActionsRouter.js
  4. 104
      views/address.pug
  5. 10
      views/includes/block-content.pug
  6. 2
      views/layout.pug
  7. 9
      views/transaction.pug

19
app/rpcApi.js

@ -315,6 +315,22 @@ function getRawTransaction(txid) {
});
}
function getAddress(address) {
return new Promise(function(resolve, reject) {
client.command('validateaddress', address, function(err, result, resHeaders) {
if (err) {
console.log("Error 9234ygf0weg: " + err);
reject(err);
return;
}
resolve(result);
});
});
}
function getRawTransactions(txids) {
console.log("getRawTransactions: " + txids);
@ -590,5 +606,6 @@ module.exports = {
getUptimeSeconds: getUptimeSeconds,
getHelp: getHelp,
getRpcMethodHelp: getRpcMethodHelp,
getHistoricalData: getHistoricalData
getHistoricalData: getHistoricalData,
getAddress: getAddress
};

1
package.json

@ -9,6 +9,7 @@
"body-parser": "~1.18.2",
"cookie-parser": "~1.4.3",
"bitcoin-core": "2.0.0",
"bitcoinjs-lib": "3.3.2",
"crypto-js": "3.1.9-1",
"debug": "~2.6.0",
"decimal.js":"7.2.3",

57
routes/baseActionsRouter.js

@ -7,6 +7,7 @@ var env = require("./../app/env");
var bitcoinCore = require("bitcoin-core");
var rpcApi = require("./../app/rpcApi");
var qrcode = require('qrcode');
var bitcoinjs = require('bitcoinjs-lib');
router.get("/", function(req, res) {
if (req.session.host == null || req.session.host.trim() == "") {
@ -229,6 +230,7 @@ router.post("/search", function(req, res) {
}
var query = req.body.query.toLowerCase().trim();
var rawCaseQuery = req.body.query.trim();
req.session.query = req.body.query;
@ -247,6 +249,14 @@ router.post("/search", function(req, res) {
return;
}
rpcApi.getAddress(rawCaseQuery).then(function(validateaddress) {
if (validateaddress && validateaddress.isvalid) {
res.redirect("/address/" + rawCaseQuery);
return;
}
});
req.session.userMessage = "No results found for query: " + query;
res.redirect("/");
@ -289,14 +299,18 @@ router.post("/search", function(req, res) {
res.redirect("/");
});
} else {
req.session.userMessage = "Invalid query: " + query;
rpcApi.getAddress(rawCaseQuery).then(function(validateaddress) {
if (validateaddress && validateaddress.isvalid) {
res.redirect("/address/" + rawCaseQuery);
res.redirect("/");
return;
}
return;
}
req.session.userMessage = "No results found for query: " + rawCaseQuery;
res.redirect("/");
});
}
});
router.get("/block-height/:blockHeight", function(req, res) {
@ -412,6 +426,39 @@ router.get("/tx/:transactionId", function(req, res) {
});
});
router.get("/address/:address", function(req, res) {
var address = req.params.address;
res.locals.address = address;
res.locals.result = {};
if (address.startsWith("1") || address.startsWith("3")) {
res.locals.addressObj = bitcoinjs.address.fromBase58Check(address);
} else {
res.locals.addressObj = bitcoinjs.address.fromBech32(address);
}
rpcApi.getAddress(address).then(function(result) {
res.locals.result.validateaddress = result;
qrcode.toDataURL(address, function(err, url) {
if (err) {
console.log("Error 93ygfew0ygf2gf2: " + err);
}
res.locals.addressQrCodeUrl = url;
res.render("address");
});
}).catch(function(err) {
res.locals.userMessage = "Failed to load address " + address + " (" + err + ")";
res.render("address");
});
});
router.get("/rpc-terminal", function(req, res) {
if (!env.demoSite) {
var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;

104
views/address.pug

@ -0,0 +1,104 @@
extends layout
block headContent
title Address #{address}
block content
if (result && result.validateaddress)
if (!result.validateaddress.isvalid)
h1(class="h2 text-danger") Invalid Address
br
small(class="monospace") #{address}
else
h1(class="h2") Address
br
small(class="monospace") #{address}
hr
if (false)
pre
code #{JSON.stringify(addressObj, null, 4)}
ul(class='nav nav-tabs mb-3')
li(class="nav-item")
a(data-toggle="tab", href="#tab-summary", class="nav-link active", role="tab") Summary
li(class="nav-item")
a(data-toggle="tab", href="#tab-raw", class="nav-link", role="tab") Raw
div(class="tab-content")
div(id="tab-summary", class="tab-pane active", role="tabpanel")
table(class="table")
if (addressObj.hash)
tr
th(class="table-active properties-header") Hash 160
td(class="monospace") #{addressObj.hash.toString("hex")}
if (result.validateaddress.scriptPubKey)
tr
th(class="table-active properties-header") Script Public Key
td(class="monospace") #{result.validateaddress.scriptPubKey}
if (addressObj.hasOwnProperty("version"))
tr
th(class="table-active properties-header") Version
td(class="monospace") #{addressObj.version}
if (result.validateaddress.hasOwnProperty("witness_version"))
tr
th(class="table-active properties-header") Witness Version
td(class="monospace") #{result.validateaddress.witness_version}
if (result.validateaddress.witness_program)
tr
th(class="table-active properties-header") Witness Program
td(class="monospace") #{result.validateaddress.witness_program}
tr
th(class="table-active properties-header") QR Code
td(class="monospace")
img(src=addressQrCodeUrl, alt=address)
div(class="card mb-3")
div(class="card-header")
span(class="h6") Flags
div(class="card-body")
table(class="table text-center")
thead
tr
th Is Valid?
th Is Script?
th Is Witness?
th Is Mine?
th Is Watch-Only?
tbody
tr
- var x = result.validateaddress;
- var flags = [x.isvalid, x.isscript, x.iswitness, x.ismine, x.iswatchonly];
each flag in flags
td
if (flag)
i(class="fas fa-check text-success")
else
i(class="fas fa-times text-danger")
div(class="card")
div(class="card-header")
span(class="h6") Transactions
div(class="card-body")
table(class="table")
strong
p(class="text-warning") This is a work-in-progress
p Since this app is database-free, displaying a list of transactions involving the current address is tricky. I'm actively researching the best way to implement this.
a(href="https://github.com/janoside/btc-rpc-explorer/issues/8") Suggestions and/or pull requests are welcome!
div(id="tab-raw", class="tab-pane", role="tabpanel")
div(class="highlight")
pre
code(class="language-json", data-lang="json") #{JSON.stringify(result.validateaddress, null, 4)}

10
views/includes/block-content.pug

@ -159,9 +159,11 @@ div(class="tab-content")
td
if (vout.scriptPubKey && vout.scriptPubKey.addresses)
div(class="monospace", style="word-break: break-word;") #{vout.scriptPubKey.addresses[0]}
span(class="monospace text-muted") via tx
a(href=("/tx/" + txInput.txid + "#output-" + tx.vin[txInputIndex].vout), class="monospace") #{txInput.txid.substring(0, 14)}..., Output ##{tx.vin[txInputIndex].vout + 1}
div(class="monospace", style="word-break: break-word;")
a(href=("/address/" + vout.scriptPubKey.addresses[0])) #{vout.scriptPubKey.addresses[0]}
span(class="monospace") via
a(href=("/tx/" + txInput.txid + "#output-" + tx.vin[txInputIndex].vout), class="monospace") tx:#{txInput.txid.substring(0, 14)}...[#{tx.vin[txInputIndex].vout}]
td
if (vout.value)
- totalInputValue = totalInputValue.plus(new Decimal(vout.value));
@ -203,7 +205,7 @@ div(class="tab-content")
td
if (vout.scriptPubKey)
if (vout.scriptPubKey.addresses)
a(id="output-" + voutIndex)
a(id=("output-" + voutIndex), href=("/address/" + vout.scriptPubKey.addresses[0]))
div(class="monospace", style="word-break: break-word;") #{vout.scriptPubKey.addresses[0]}
else if (vout.scriptPubKey.hex && vout.scriptPubKey.hex.startsWith('6a24aa21a9ed'))

2
views/layout.pug

@ -60,7 +60,7 @@ html
form(method="post", action="/search", class="form-inline")
div(class="input-group input-group-sm")
input(type="text", class="form-control form-control-sm", name="query", placeholder="block height, block hash, txid", value=(query), style="width: 300px;")
input(type="text", class="form-control form-control-sm", name="query", placeholder="block height/hash, txid, address", value=(query), style="width: 300px;")
div(class="input-group-append")
button(type="submit", class="btn btn-primary")
i(class="fas fa-search")

9
views/transaction.pug

@ -183,9 +183,10 @@ block content
td
if (vout.scriptPubKey && vout.scriptPubKey.addresses)
div(class="monospace", style="word-break: break-word;") #{vout.scriptPubKey.addresses[0]}
span(class="monospace text-muted") via tx
a(href=("/tx/" + txInput.txid + "#output-" + result.getrawtransaction.vin[txInputIndex].vout), class="monospace") #{txInput.txid.substring(0, 14)}..., Output ##{result.getrawtransaction.vin[txInputIndex].vout + 1}
div(class="monospace", style="word-break: break-word;")
a(href=("/address/" + vout.scriptPubKey.addresses[0])) #{vout.scriptPubKey.addresses[0]}
span(class="monospace") via
a(href=("/tx/" + txInput.txid + "#output-" + result.getrawtransaction.vin[txInputIndex].vout), class="monospace") #{txInput.txid.substring(0, 14)}...[#{result.getrawtransaction.vin[txInputIndex].vout}]
td
if (vout.value)
- var currencyValue = vout.value;
@ -215,7 +216,7 @@ block content
td
if (vout.scriptPubKey)
if (vout.scriptPubKey.addresses)
a(id="output-" + voutIndex)
a(id=("output-" + voutIndex), href=("/address/" + vout.scriptPubKey.addresses[0]))
div(class="monospace", style="word-break: break-word;") #{vout.scriptPubKey.addresses[0]}
else if (vout.scriptPubKey.hex && vout.scriptPubKey.hex.startsWith('6a24aa21a9ed'))

Loading…
Cancel
Save