Remove /explorer part from URL, blockbook status with external explorer
parent
5f0b4e5c5a
commit
8ad6d1d52c
|
@ -44,7 +44,7 @@
|
|||
"system_user": "blockbook-bcash",
|
||||
"internal_binding_template": ":{{.Ports.BlockbookInternal}}",
|
||||
"public_binding_template": ":{{.Ports.BlockbookPublic}}",
|
||||
"explorer_url": "/explorer",
|
||||
"explorer_url": "",
|
||||
"additional_params": "",
|
||||
"block_chain": {
|
||||
"parse": true,
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
"system_user": "blockbook-bcash",
|
||||
"internal_binding_template": ":{{.Ports.BlockbookInternal}}",
|
||||
"public_binding_template": ":{{.Ports.BlockbookPublic}}",
|
||||
"explorer_url": "/explorer",
|
||||
"explorer_url": "",
|
||||
"additional_params": "",
|
||||
"block_chain": {
|
||||
"parse": true,
|
||||
|
|
|
@ -239,7 +239,7 @@
|
|||
"system_user": "blockbook-bgold",
|
||||
"internal_binding_template": ":{{.Ports.BlockbookInternal}}",
|
||||
"public_binding_template": ":{{.Ports.BlockbookPublic}}",
|
||||
"explorer_url": "/explorer",
|
||||
"explorer_url": "",
|
||||
"additional_params": "-dbmaxopenfiles=128",
|
||||
"block_chain": {
|
||||
"parse": true,
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
"system_user": "blockbook-bitcoin",
|
||||
"internal_binding_template": ":{{.Ports.BlockbookInternal}}",
|
||||
"public_binding_template": ":{{.Ports.BlockbookPublic}}",
|
||||
"explorer_url": "/explorer",
|
||||
"explorer_url": "",
|
||||
"additional_params": "-dbcache=1073741824",
|
||||
"block_chain": {
|
||||
"parse": true,
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
"system_user": "blockbook-bitcoin",
|
||||
"internal_binding_template": ":{{.Ports.BlockbookInternal}}",
|
||||
"public_binding_template": ":{{.Ports.BlockbookPublic}}",
|
||||
"explorer_url": "/explorer",
|
||||
"explorer_url": "",
|
||||
"additional_params": "",
|
||||
"block_chain": {
|
||||
"parse": true,
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
"system_user": "blockbook-zcash",
|
||||
"internal_binding_template": ":{{.Ports.BlockbookInternal}}",
|
||||
"public_binding_template": ":{{.Ports.BlockbookPublic}}",
|
||||
"explorer_url": "/explorer",
|
||||
"explorer_url": "",
|
||||
"additional_params": "",
|
||||
"block_chain": {
|
||||
"parse": true,
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
"system_user": "blockbook-zcash",
|
||||
"internal_binding_template": ":{{.Ports.BlockbookInternal}}",
|
||||
"public_binding_template": ":{{.Ports.BlockbookPublic}}",
|
||||
"explorer_url": "/explorer",
|
||||
"explorer_url": "",
|
||||
"additional_params": "",
|
||||
"block_chain": {
|
||||
"parse": true,
|
||||
|
|
|
@ -79,7 +79,7 @@ Good examples of coin configuration are
|
|||
* `system_user` – User used to run Blockbook service. See convention note in [build guide](/docs/build.md#on-naming-conventions-and-versioning).
|
||||
* `internal_binding_template` – Template for *-internal* parameter. See note on templates below.
|
||||
* `public_binding_template` – Template for *-public* parameter. See note on templates below.
|
||||
* `explorer_url` – URL of blockchain explorer.
|
||||
* `explorer_url` – URL of blockchain explorer. Leave empty for internal explorer.
|
||||
* `additional_params` – Additional params of exec command (see [Dogecoin definition](configs/coins/dogecoin.json)).
|
||||
* `block_chain` – Configuration of BlockChain type that ensures communication with back-end service. All options
|
||||
must be tweaked for each individual coin separely.
|
||||
|
|
127
server/public.go
127
server/public.go
|
@ -25,20 +25,21 @@ const txsInAPI = 1000
|
|||
|
||||
// PublicServer is a handle to public http server
|
||||
type PublicServer struct {
|
||||
binding string
|
||||
certFiles string
|
||||
socketio *SocketIoServer
|
||||
https *http.Server
|
||||
db *db.RocksDB
|
||||
txCache *db.TxCache
|
||||
chain bchain.BlockChain
|
||||
chainParser bchain.BlockChainParser
|
||||
api *api.Worker
|
||||
explorerURL string
|
||||
metrics *common.Metrics
|
||||
is *common.InternalState
|
||||
templates []*template.Template
|
||||
debug bool
|
||||
binding string
|
||||
certFiles string
|
||||
socketio *SocketIoServer
|
||||
https *http.Server
|
||||
db *db.RocksDB
|
||||
txCache *db.TxCache
|
||||
chain bchain.BlockChain
|
||||
chainParser bchain.BlockChainParser
|
||||
api *api.Worker
|
||||
explorerURL string
|
||||
internalExplorer bool
|
||||
metrics *common.Metrics
|
||||
is *common.InternalState
|
||||
templates []*template.Template
|
||||
debug bool
|
||||
}
|
||||
|
||||
// NewPublicServer creates new public server http interface to blockbook and returns its handle
|
||||
|
@ -63,19 +64,20 @@ func NewPublicServer(binding string, certFiles string, db *db.RocksDB, chain bch
|
|||
}
|
||||
|
||||
s := &PublicServer{
|
||||
binding: binding,
|
||||
certFiles: certFiles,
|
||||
https: https,
|
||||
api: api,
|
||||
socketio: socketio,
|
||||
db: db,
|
||||
txCache: txCache,
|
||||
chain: chain,
|
||||
chainParser: chain.GetChainParser(),
|
||||
explorerURL: explorerURL,
|
||||
metrics: metrics,
|
||||
is: is,
|
||||
debug: debugMode,
|
||||
binding: binding,
|
||||
certFiles: certFiles,
|
||||
https: https,
|
||||
api: api,
|
||||
socketio: socketio,
|
||||
db: db,
|
||||
txCache: txCache,
|
||||
chain: chain,
|
||||
chainParser: chain.GetChainParser(),
|
||||
explorerURL: explorerURL,
|
||||
internalExplorer: explorerURL == "",
|
||||
metrics: metrics,
|
||||
is: is,
|
||||
debug: debugMode,
|
||||
}
|
||||
s.templates = parseTemplates()
|
||||
|
||||
|
@ -106,15 +108,18 @@ func (s *PublicServer) ConnectFullPublicInterface() {
|
|||
_, path := splitBinding(s.binding)
|
||||
// support for tests of socket.io interface
|
||||
serveMux.Handle(path+"test.html", http.FileServer(http.Dir("./static/")))
|
||||
// redirect to wallet requests for tx and address, possibly to external site
|
||||
serveMux.HandleFunc(path+"tx/", s.txRedirect)
|
||||
serveMux.HandleFunc(path+"address/", s.addressRedirect)
|
||||
// explorer
|
||||
serveMux.HandleFunc(path+"explorer/tx/", s.htmlTemplateHandler(s.explorerTx))
|
||||
serveMux.HandleFunc(path+"explorer/address/", s.htmlTemplateHandler(s.explorerAddress))
|
||||
serveMux.HandleFunc(path+"explorer/search/", s.htmlTemplateHandler(s.explorerSearch))
|
||||
serveMux.HandleFunc(path+"explorer/blocks", s.htmlTemplateHandler(s.explorerBlocks))
|
||||
serveMux.HandleFunc(path+"explorer/block/", s.htmlTemplateHandler(s.explorerBlock))
|
||||
if s.internalExplorer {
|
||||
// internal explorer handlers
|
||||
serveMux.HandleFunc(path+"tx/", s.htmlTemplateHandler(s.explorerTx))
|
||||
serveMux.HandleFunc(path+"address/", s.htmlTemplateHandler(s.explorerAddress))
|
||||
serveMux.HandleFunc(path+"search/", s.htmlTemplateHandler(s.explorerSearch))
|
||||
serveMux.HandleFunc(path+"blocks", s.htmlTemplateHandler(s.explorerBlocks))
|
||||
serveMux.HandleFunc(path+"block/", s.htmlTemplateHandler(s.explorerBlock))
|
||||
} else {
|
||||
// redirect to wallet requests for tx and address, possibly to external site
|
||||
serveMux.HandleFunc(path+"tx/", s.txRedirect)
|
||||
serveMux.HandleFunc(path+"address/", s.addressRedirect)
|
||||
}
|
||||
// API calls
|
||||
serveMux.HandleFunc(path+"api/block-index/", s.jsonHandler(s.apiBlockIndex))
|
||||
serveMux.HandleFunc(path+"api/tx/", s.jsonHandler(s.apiTx))
|
||||
|
@ -147,17 +152,13 @@ func (s *PublicServer) OnNewTxAddr(txid string, addr string, isOutput bool) {
|
|||
}
|
||||
|
||||
func (s *PublicServer) txRedirect(w http.ResponseWriter, r *http.Request) {
|
||||
if s.explorerURL != "" {
|
||||
http.Redirect(w, r, joinURL(s.explorerURL, r.URL.Path), 302)
|
||||
s.metrics.ExplorerViews.With(common.Labels{"action": "tx-redirect"}).Inc()
|
||||
}
|
||||
http.Redirect(w, r, joinURL(s.explorerURL, r.URL.Path), 302)
|
||||
s.metrics.ExplorerViews.With(common.Labels{"action": "tx-redirect"}).Inc()
|
||||
}
|
||||
|
||||
func (s *PublicServer) addressRedirect(w http.ResponseWriter, r *http.Request) {
|
||||
if s.explorerURL != "" {
|
||||
http.Redirect(w, r, joinURL(s.explorerURL, r.URL.Path), 302)
|
||||
s.metrics.ExplorerViews.With(common.Labels{"action": "address-redirect"}).Inc()
|
||||
}
|
||||
http.Redirect(w, r, joinURL(s.explorerURL, r.URL.Path), 302)
|
||||
s.metrics.ExplorerViews.With(common.Labels{"action": "address-redirect"}).Inc()
|
||||
}
|
||||
|
||||
func splitBinding(binding string) (addr string, path string) {
|
||||
|
@ -221,8 +222,9 @@ func (s *PublicServer) jsonHandler(handler func(r *http.Request) (interface{}, e
|
|||
|
||||
func (s *PublicServer) newTemplateData() *TemplateData {
|
||||
return &TemplateData{
|
||||
CoinName: s.is.Coin,
|
||||
CoinShortcut: s.is.CoinShortcut,
|
||||
CoinName: s.is.Coin,
|
||||
CoinShortcut: s.is.CoinShortcut,
|
||||
InternalExplorer: s.internalExplorer,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,19 +298,20 @@ const (
|
|||
)
|
||||
|
||||
type TemplateData struct {
|
||||
CoinName string
|
||||
CoinShortcut string
|
||||
Address *api.Address
|
||||
AddrStr string
|
||||
Tx *api.Tx
|
||||
Error *api.ApiError
|
||||
Blocks *api.Blocks
|
||||
Block *api.Block
|
||||
Info *api.SystemInfo
|
||||
Page int
|
||||
PrevPage int
|
||||
NextPage int
|
||||
PagingRange []int
|
||||
CoinName string
|
||||
CoinShortcut string
|
||||
InternalExplorer bool
|
||||
Address *api.Address
|
||||
AddrStr string
|
||||
Tx *api.Tx
|
||||
Error *api.ApiError
|
||||
Blocks *api.Blocks
|
||||
Block *api.Block
|
||||
Info *api.SystemInfo
|
||||
Page int
|
||||
PrevPage int
|
||||
NextPage int
|
||||
PagingRange []int
|
||||
}
|
||||
|
||||
func parseTemplates() []*template.Template {
|
||||
|
@ -453,20 +456,20 @@ func (s *PublicServer) explorerSearch(w http.ResponseWriter, r *http.Request) (t
|
|||
if len(q) > 0 {
|
||||
block, err = s.api.GetBlock(q, 0, 1)
|
||||
if err == nil {
|
||||
http.Redirect(w, r, joinURL("/explorer/block/", block.Hash), 302)
|
||||
http.Redirect(w, r, joinURL("/block/", block.Hash), 302)
|
||||
return noTpl, nil, nil
|
||||
}
|
||||
bestheight, _, err = s.db.GetBestBlock()
|
||||
if err == nil {
|
||||
tx, err = s.api.GetTransaction(q, bestheight, false)
|
||||
if err == nil {
|
||||
http.Redirect(w, r, joinURL("/explorer/tx/", tx.Txid), 302)
|
||||
http.Redirect(w, r, joinURL("/tx/", tx.Txid), 302)
|
||||
return noTpl, nil, nil
|
||||
}
|
||||
}
|
||||
address, err = s.api.GetAddress(q, 0, 1, true)
|
||||
if err == nil {
|
||||
http.Redirect(w, r, joinURL("/explorer/address/", address.AddrStr), 302)
|
||||
http.Redirect(w, r, joinURL("/address/", address.AddrStr), 302)
|
||||
return noTpl, nil, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ h3 {
|
|||
|
||||
.line-top {
|
||||
border-top: 1px solid #EAEAEA;
|
||||
padding: 15px 0 0;
|
||||
padding: 10px 0 0;
|
||||
}
|
||||
|
||||
.line-mid {
|
||||
|
@ -157,6 +157,7 @@ h3 {
|
|||
white-space: nowrap;
|
||||
vertical-align: baseline;
|
||||
border-radius: .25em;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.txvalues:not(:last-child) {
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<h1>Address
|
||||
<small class="text-muted">{{formatAmount $addr.Balance}} {{$cs}}</small>
|
||||
</h1>
|
||||
<div class="alert alert-data">
|
||||
<span class="ellipsis data">{{$addr.AddrStr}}</span>
|
||||
<div class="alert alert-data ellipsis">
|
||||
<span class="data">{{$addr.AddrStr}}</span>
|
||||
</div>
|
||||
<h3>Confirmed</h3>
|
||||
<div class="data-div row">
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
<body>
|
||||
<header id="header">
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-trezor">
|
||||
<!-- <a class="navbar-brand" href="#">Navbar w/ text</a> -->
|
||||
<nav class="navbar navbar-expand navbar-dark bg-trezor">
|
||||
<a class="navbar-brand" href="/" title="Home">
|
||||
<div alt="TREZOR Wallet" class="trezor-logo-svg-white">
|
||||
<svg width="100" height="42" version="1.1" id="logotyp" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 163.7 41.9" space="preserve">
|
||||
|
@ -32,19 +31,21 @@
|
|||
<span class="navbar-text ml-md-auto">
|
||||
<a href="/" class="nav-link">{{.CoinName}} Explorer</a>
|
||||
</span>
|
||||
{{- if .InternalExplorer -}}
|
||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-lg-flex">
|
||||
<li class="nav-item">
|
||||
<a href="/explorer/blocks" class="nav-link">Blocks</a>
|
||||
<a href="/blocks" class="nav-link">Blocks</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/" class="nav-link">Status</a>
|
||||
</li>
|
||||
</ul>
|
||||
<span class="d-none ml-md-auto d-md-flex navbar-form navbar-left">
|
||||
<form id="search" action="/explorer/search" method="get">
|
||||
<form id="search" action="/search" method="get">
|
||||
<input name="q" type="text" class="form-control" placeholder="Search for block, transaction or address" focus="true">
|
||||
</form>
|
||||
</span>
|
||||
{{- end -}}
|
||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-lg-flex ">
|
||||
<li class="nav-item">
|
||||
<a href="https://trezor.io/" class="nav-link">TREZOR</a>
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
{{define "specific"}}{{$cs := .CoinShortcut}}{{$b := .Block}}{{$data := . -}}
|
||||
<h1>Block {{$b.Height}}</h1>
|
||||
<div class="alert alert-data">
|
||||
<span class="ellipsis data">{{$b.Hash}}</span>
|
||||
<div class="alert alert-data ellipsis">
|
||||
<span class="data">{{$b.Hash}}</span>
|
||||
</div>
|
||||
<div class="h-container">
|
||||
<h3 class="h-container-6">Summary</h3>
|
||||
<nav class="h-container-6">
|
||||
<ul class="pagination justify-content-end">
|
||||
<li class="page-item">{{if $b.Prev}}<a class="page-link" href="/explorer/block/{{$b.Prev}}">Previous Block</a>{{else}}<span class="page-link text-muted disabled">Previous Block</span>{{end}}</li>
|
||||
<li class="page-item">{{if $b.Next}}<a class="page-link" href="/explorer/block/{{$b.Next}}">Next Block</a>{{else}}<span class="page-link text-muted disabled">Next Block</span>{{end}}</li>
|
||||
<li class="page-item">{{if $b.Prev}}<a class="page-link" href="/block/{{$b.Prev}}">Previous Block</a>{{else}}<span class="page-link text-muted disabled">Previous Block</span>{{end}}</li>
|
||||
<li class="page-item">{{if $b.Next}}<a class="page-link" href="/block/{{$b.Next}}">Next Block</a>{{else}}<span class="page-link text-muted disabled">Next Block</span>{{end}}</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<tbody>
|
||||
{{- range $b := $blocks.Blocks -}}
|
||||
<tr>
|
||||
<td><a href="/explorer/block/{{$b.Height}}">{{$b.Height}}</a></td>
|
||||
<td><a href="/block/{{$b.Height}}">{{$b.Height}}</a></td>
|
||||
<td>{{formatUnixTime $b.Time}}</td>
|
||||
<td class="text-right">{{$b.Txs}}</td>
|
||||
<td class="text-right">{{$b.Size}}</td>
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>Last Block</td>
|
||||
<td class="data"><a href="/explorer/block/{{$bb.BestHeight}}">{{$bb.BestHeight}}</a></td>
|
||||
<td class="data">{{if .InternalExplorer}}<a href="/block/{{$bb.BestHeight}}">{{$bb.BestHeight}}</a>{{else}}{{$bb.BestHeight}}{{end}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Last Block Update</td>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{{define "specific"}}{{$cs := .CoinShortcut}}{{$tx := .Tx}}
|
||||
<h1>Transaction</h1>
|
||||
<div class="alert alert-data">
|
||||
<span class="ellipsis data">{{$tx.Txid}}</span>
|
||||
<div class="alert alert-data ellipsis">
|
||||
<span class="data">{{$tx.Txid}}</span>
|
||||
</div>
|
||||
<h3>Summary</h3>
|
||||
<div class="data-div">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="alert alert-data">
|
||||
<div class="row line-bot">
|
||||
<div class="col-xs-7 col-md-8 ellipsis">
|
||||
<a href="/explorer/tx/{{$tx.Txid}}">{{$tx.Txid}}</a>
|
||||
<a href="/tx/{{$tx.Txid}}">{{$tx.Txid}}</a>
|
||||
</div>
|
||||
{{- if $tx.Confirmations -}}
|
||||
<div class="col-xs-5 col-md-4 text-muted text-right">mined {{formatUnixTime $tx.Blocktime}}</div>
|
||||
|
@ -17,11 +17,11 @@
|
|||
<tr>
|
||||
<td>
|
||||
{{- if $vin.Txid -}}
|
||||
<a class="float-left text-muted" href="/explorer/tx/{{$vin.Txid}}" title="Outpoint {{$vin.Txid}},{{$vin.Vout}}">➡ </a>
|
||||
<a class="float-left text-muted" href="/tx/{{$vin.Txid}}" title="Outpoint {{$vin.Txid}},{{$vin.Vout}}">➡ </a>
|
||||
{{- end -}}
|
||||
{{- range $a := $vin.Addresses -}}
|
||||
<span class="ellipsis float-left">
|
||||
{{if and (ne $a $addr) $vin.Searchable}}<a href="/explorer/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{end}}
|
||||
{{if and (ne $a $addr) $vin.Searchable}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{end}}
|
||||
</span>
|
||||
{{- else -}}
|
||||
<span class="float-left">No Inputs (Newly Generated Coins)</span>
|
||||
|
@ -53,13 +53,13 @@
|
|||
<td>
|
||||
{{- range $a := $vout.ScriptPubKey.Addresses -}}
|
||||
<span class="ellipsis float-left">
|
||||
{{- if and (ne $a $addr) $vout.ScriptPubKey.Searchable}}<a href="/explorer/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{- end -}}
|
||||
{{- if and (ne $a $addr) $vout.ScriptPubKey.Searchable}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{- end -}}
|
||||
</span>
|
||||
{{- else -}}
|
||||
<span class="float-left">Unparsed address</span>
|
||||
{{- end -}}
|
||||
<span class="float-right{{if stringInSlice $addr $vout.ScriptPubKey.Addresses}} text-success{{end}}">
|
||||
{{formatAmount $vout.Value}} {{$cs}} {{if $vout.Spent}}{{if $vout.SpentTxID}}<a class="text-danger" href="/explorer/tx/{{$vout.SpentTxID}}" title="Spent">➡</a>{{else}}<span class="text-danger" title="Spent">➡</span>{{end}}{{else -}}
|
||||
{{formatAmount $vout.Value}} {{$cs}} {{if $vout.Spent}}{{if $vout.SpentTxID}}<a class="text-danger" href="/tx/{{$vout.SpentTxID}}" title="Spent">➡</a>{{else}}<span class="text-danger" title="Spent">➡</span>{{end}}{{else -}}
|
||||
<span class="text-success" title="Unspent"> <b>×</b></span>
|
||||
{{- end -}}
|
||||
</span>
|
||||
|
|
Loading…
Reference in New Issue