Highlight xpub addresses in explorer
This commit is contained in:
parent
9d3cd3b3e9
commit
266b0575b6
@ -233,7 +233,9 @@ type Address struct {
|
|||||||
TotalTokens int `json:"totalTokens,omitempty"`
|
TotalTokens int `json:"totalTokens,omitempty"`
|
||||||
Tokens []Token `json:"tokens,omitempty"`
|
Tokens []Token `json:"tokens,omitempty"`
|
||||||
Erc20Contract *bchain.Erc20Contract `json:"erc20contract,omitempty"`
|
Erc20Contract *bchain.Erc20Contract `json:"erc20contract,omitempty"`
|
||||||
Filter string `json:"-"`
|
// helpers for explorer
|
||||||
|
Filter string `json:"-"`
|
||||||
|
XPubAddresses map[string]struct{} `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddressUtxo holds information about address and its transactions
|
// AddressUtxo holds information about address and its transactions
|
||||||
|
|||||||
34
api/xpub.go
34
api/xpub.go
@ -235,6 +235,10 @@ func (w *Worker) GetAddressForXpub(xpub string, page int, txsOnPage int, option
|
|||||||
}
|
}
|
||||||
// gap is increased one as there must be gap of empty addresses before the derivation is stopped
|
// gap is increased one as there must be gap of empty addresses before the derivation is stopped
|
||||||
gap++
|
gap++
|
||||||
|
page--
|
||||||
|
if page < 0 {
|
||||||
|
page = 0
|
||||||
|
}
|
||||||
var processedHash string
|
var processedHash string
|
||||||
cachedXpubsMux.Lock()
|
cachedXpubsMux.Lock()
|
||||||
data, found := cachedXpubs[xpub]
|
data, found := cachedXpubs[xpub]
|
||||||
@ -305,7 +309,7 @@ func (w *Worker) GetAddressForXpub(xpub string, page int, txsOnPage int, option
|
|||||||
if option >= TxidHistory {
|
if option >= TxidHistory {
|
||||||
txc := make(xpubTxids, 0, 32)
|
txc := make(xpubTxids, 0, 32)
|
||||||
var addTxids func(ad *xpubAddress)
|
var addTxids func(ad *xpubAddress)
|
||||||
if filter.FromHeight != 0 || filter.ToHeight != 0 || filter.Vout != AddressFilterVoutOff {
|
if filter.FromHeight == 0 && filter.ToHeight == 0 && filter.Vout == AddressFilterVoutOff {
|
||||||
addTxids = func(ad *xpubAddress) {
|
addTxids = func(ad *xpubAddress) {
|
||||||
txc = append(txc, ad.txids...)
|
txc = append(txc, ad.txids...)
|
||||||
}
|
}
|
||||||
@ -372,13 +376,21 @@ func (w *Worker) GetAddressForXpub(xpub string, page int, txsOnPage int, option
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalTokens := 0
|
totalTokens := 0
|
||||||
|
xpubAddresses := make(map[string]struct{})
|
||||||
tokens := make([]Token, 0, 4)
|
tokens := make([]Token, 0, 4)
|
||||||
for i := range data.addresses {
|
for i := range data.addresses {
|
||||||
ad := &data.addresses[i]
|
ad := &data.addresses[i]
|
||||||
if ad.balance != nil {
|
if ad.balance != nil {
|
||||||
totalTokens++
|
totalTokens++
|
||||||
if filter.AllTokens || !IsZeroBigInt(&ad.balance.BalanceSat) {
|
if filter.AllTokens || !IsZeroBigInt(&ad.balance.BalanceSat) {
|
||||||
tokens = append(tokens, w.tokenFromXpubAddress(ad, 0, i))
|
t := w.tokenFromXpubAddress(ad, 0, i)
|
||||||
|
tokens = append(tokens, t)
|
||||||
|
xpubAddresses[t.Name] = struct{}{}
|
||||||
|
} else {
|
||||||
|
a, _, _ := w.chainParser.GetAddressesFromAddrDesc(ad.addrDesc)
|
||||||
|
if len(a) > 0 {
|
||||||
|
xpubAddresses[a[0]] = struct{}{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -387,7 +399,14 @@ func (w *Worker) GetAddressForXpub(xpub string, page int, txsOnPage int, option
|
|||||||
if ad.balance != nil {
|
if ad.balance != nil {
|
||||||
totalTokens++
|
totalTokens++
|
||||||
if filter.AllTokens || !IsZeroBigInt(&ad.balance.BalanceSat) {
|
if filter.AllTokens || !IsZeroBigInt(&ad.balance.BalanceSat) {
|
||||||
tokens = append(tokens, w.tokenFromXpubAddress(ad, 1, i))
|
t := w.tokenFromXpubAddress(ad, 1, i)
|
||||||
|
tokens = append(tokens, t)
|
||||||
|
xpubAddresses[t.Name] = struct{}{}
|
||||||
|
} else {
|
||||||
|
a, _, _ := w.chainParser.GetAddressesFromAddrDesc(ad.addrDesc)
|
||||||
|
if len(a) > 0 {
|
||||||
|
xpubAddresses[a[0]] = struct{}{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,10 +421,11 @@ func (w *Worker) GetAddressForXpub(xpub string, page int, txsOnPage int, option
|
|||||||
Txs: int(data.txs),
|
Txs: int(data.txs),
|
||||||
// UnconfirmedBalanceSat: (*Amount)(&uBalSat),
|
// UnconfirmedBalanceSat: (*Amount)(&uBalSat),
|
||||||
// UnconfirmedTxs: len(txm),
|
// UnconfirmedTxs: len(txm),
|
||||||
Transactions: txs,
|
Transactions: txs,
|
||||||
Txids: txids,
|
Txids: txids,
|
||||||
TotalTokens: totalTokens,
|
TotalTokens: totalTokens,
|
||||||
Tokens: tokens,
|
Tokens: tokens,
|
||||||
|
XPubAddresses: xpubAddresses,
|
||||||
}
|
}
|
||||||
glog.Info("GetAddressForXpub ", xpub[:16], ", ", len(data.addresses)+len(data.changeAddresses), " derived addresses, ", data.txs, " total txs finished in ", time.Since(start))
|
glog.Info("GetAddressForXpub ", xpub[:16], ", ", len(data.addresses)+len(data.changeAddresses), " derived addresses, ", data.txs, " total txs finished in ", time.Since(start))
|
||||||
return &addr, nil
|
return &addr, nil
|
||||||
|
|||||||
@ -415,7 +415,7 @@ func (s *PublicServer) parseTemplates() []*template.Template {
|
|||||||
"formatAmount": s.formatAmount,
|
"formatAmount": s.formatAmount,
|
||||||
"formatAmountWithDecimals": formatAmountWithDecimals,
|
"formatAmountWithDecimals": formatAmountWithDecimals,
|
||||||
"setTxToTemplateData": setTxToTemplateData,
|
"setTxToTemplateData": setTxToTemplateData,
|
||||||
"stringInSlice": stringInSlice,
|
"isOwnAddress": isOwnAddress,
|
||||||
}
|
}
|
||||||
var createTemplate func(filenames ...string) *template.Template
|
var createTemplate func(filenames ...string) *template.Template
|
||||||
if s.debug {
|
if s.debug {
|
||||||
@ -504,6 +504,23 @@ func setTxToTemplateData(td *TemplateData, tx *api.Tx) *TemplateData {
|
|||||||
return td
|
return td
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns true if addresses are "own",
|
||||||
|
// i.e. either the address of the address detail or belonging to the xpub
|
||||||
|
func isOwnAddress(td *TemplateData, addresses []string) bool {
|
||||||
|
if len(addresses) == 1 {
|
||||||
|
a := addresses[0]
|
||||||
|
if a == td.AddrStr {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if td.Address != nil && td.Address.XPubAddresses != nil {
|
||||||
|
if _, found := td.Address.XPubAddresses[a]; found {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (s *PublicServer) explorerTx(w http.ResponseWriter, r *http.Request) (tpl, *TemplateData, error) {
|
func (s *PublicServer) explorerTx(w http.ResponseWriter, r *http.Request) (tpl, *TemplateData, error) {
|
||||||
var tx *api.Tx
|
var tx *api.Tx
|
||||||
var err error
|
var err error
|
||||||
|
|||||||
@ -151,7 +151,7 @@ func httpTests_BitcoinType(t *testing.T, ts *httptest.Server) {
|
|||||||
`td class="data">0 FAKE</td>`,
|
`td class="data">0 FAKE</td>`,
|
||||||
`<a href="/address/mzVznVsCHkVHX9UN8WPFASWUUHtxnNn4Jj">mzVznVsCHkVHX9UN8WPFASWUUHtxnNn4Jj</a>`,
|
`<a href="/address/mzVznVsCHkVHX9UN8WPFASWUUHtxnNn4Jj">mzVznVsCHkVHX9UN8WPFASWUUHtxnNn4Jj</a>`,
|
||||||
`13.60030331 FAKE`,
|
`13.60030331 FAKE`,
|
||||||
`<td><span class="float-left">No Inputs (Newly Generated Coins)</span></td>`,
|
`<td><span class="tx-addr">No Inputs (Newly Generated Coins)</span></td>`,
|
||||||
`</html>`,
|
`</html>`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -168,8 +168,8 @@ func httpTests_BitcoinType(t *testing.T, ts *httptest.Server) {
|
|||||||
`<td class="data">0.00012345 FAKE</td>`,
|
`<td class="data">0.00012345 FAKE</td>`,
|
||||||
`<a href="/tx/7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25">7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25</a>`,
|
`<a href="/tx/7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25">7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25</a>`,
|
||||||
`3172.83951061 FAKE <a class="text-danger" href="/spending/7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25/0" title="Spent">➡</a></span>`,
|
`3172.83951061 FAKE <a class="text-danger" href="/spending/7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25/0" title="Spent">➡</a></span>`,
|
||||||
`<td><span class="ellipsis float-left"><a href="/address/mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL">mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL</a></span><span class="float-right">`,
|
`<td><span class="ellipsis tx-addr"><a href="/address/mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL">mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL</a></span><span class="tx-amt">`,
|
||||||
`td><span class="ellipsis float-left"><a href="/address/mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL">mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL</a></span><span class="float-right">`,
|
`td><span class="ellipsis tx-addr"><a href="/address/mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL">mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL</a></span><span class="tx-amt">`,
|
||||||
`9172.83951061 FAKE <span class="text-success" title="Unspent"> <b>×</b></span></span>`,
|
`9172.83951061 FAKE <span class="text-success" title="Unspent"> <b>×</b></span></span>`,
|
||||||
`<a href="/tx/00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840">00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840</a>`,
|
`<a href="/tx/00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840">00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840</a>`,
|
||||||
`</html>`,
|
`</html>`,
|
||||||
@ -290,7 +290,7 @@ func httpTests_BitcoinType(t *testing.T, ts *httptest.Server) {
|
|||||||
`td class="data">0 FAKE</td>`,
|
`td class="data">0 FAKE</td>`,
|
||||||
`<a href="/address/mzVznVsCHkVHX9UN8WPFASWUUHtxnNn4Jj">mzVznVsCHkVHX9UN8WPFASWUUHtxnNn4Jj</a>`,
|
`<a href="/address/mzVznVsCHkVHX9UN8WPFASWUUHtxnNn4Jj">mzVznVsCHkVHX9UN8WPFASWUUHtxnNn4Jj</a>`,
|
||||||
`13.60030331 FAKE`,
|
`13.60030331 FAKE`,
|
||||||
`<td><span class="float-left">No Inputs (Newly Generated Coins)</span></td>`,
|
`<td><span class="tx-addr">No Inputs (Newly Generated Coins)</span></td>`,
|
||||||
`</html>`,
|
`</html>`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -307,8 +307,8 @@ func httpTests_BitcoinType(t *testing.T, ts *httptest.Server) {
|
|||||||
`<td class="data">0.00012345 FAKE</td>`,
|
`<td class="data">0.00012345 FAKE</td>`,
|
||||||
`<a href="/tx/7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25">7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25</a>`,
|
`<a href="/tx/7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25">7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25</a>`,
|
||||||
`3172.83951061 FAKE <a class="text-danger" href="/spending/7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25/0" title="Spent">➡</a></span>`,
|
`3172.83951061 FAKE <a class="text-danger" href="/spending/7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25/0" title="Spent">➡</a></span>`,
|
||||||
`<td><span class="ellipsis float-left"><a href="/address/mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL">mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL</a></span><span class="float-right">`,
|
`<td><span class="ellipsis tx-addr"><a href="/address/mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL">mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL</a></span><span class="tx-amt">`,
|
||||||
`td><span class="ellipsis float-left"><a href="/address/mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL">mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL</a></span><span class="float-right">`,
|
`td><span class="ellipsis tx-addr"><a href="/address/mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL">mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL</a></span><span class="tx-amt">`,
|
||||||
`9172.83951061 FAKE <span class="text-success" title="Unspent"> <b>×</b></span></span>`,
|
`9172.83951061 FAKE <span class="text-success" title="Unspent"> <b>×</b></span></span>`,
|
||||||
`<a href="/tx/00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840">00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840</a>`,
|
`<a href="/tx/00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840">00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840</a>`,
|
||||||
`</html>`,
|
`</html>`,
|
||||||
|
|||||||
@ -292,15 +292,6 @@ type resultGetAddressHistory struct {
|
|||||||
} `json:"result"`
|
} `json:"result"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func stringInSlice(a string, list []string) bool {
|
|
||||||
for _, b := range list {
|
|
||||||
if b == a {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func txToResTx(tx *api.Tx) resTx {
|
func txToResTx(tx *api.Tx) resTx {
|
||||||
inputs := make([]txInputs, len(tx.Vin))
|
inputs := make([]txInputs, len(tx.Vin))
|
||||||
for i := range tx.Vin {
|
for i := range tx.Vin {
|
||||||
|
|||||||
@ -182,6 +182,26 @@ h3 {
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tx-own {
|
||||||
|
background-color: #fff6e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tx-amt {
|
||||||
|
float: right!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tx-in .tx-own .tx-amt {
|
||||||
|
color: #dc3545!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tx-out .tx-own .tx-amt {
|
||||||
|
color: #28a745!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tx-addr {
|
||||||
|
float: left!important;
|
||||||
|
}
|
||||||
|
|
||||||
.ellipsis {
|
.ellipsis {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@ -283,5 +303,5 @@ table.data-table table.data-table th {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.key {
|
.key {
|
||||||
color: #333 ;
|
color: #333;
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
{{define "txdetail"}}{{$cs := .CoinShortcut}}{{$addr := .AddrStr}}{{$tx := .Tx}}
|
{{define "txdetail"}}{{$cs := .CoinShortcut}}{{$addr := .AddrStr}}{{$tx := .Tx}}{{$data := .}}
|
||||||
<div class="alert alert-data">
|
<div class="alert alert-data">
|
||||||
<div class="row line-bot">
|
<div class="row line-bot">
|
||||||
<div class="col-xs-7 col-md-8 ellipsis">
|
<div class="col-xs-7 col-md-8 ellipsis">
|
||||||
@ -10,23 +10,23 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row line-mid">
|
<div class="row line-mid">
|
||||||
<div class="col-md-5">
|
<div class="col-md-5">
|
||||||
<div class="row">
|
<div class="row tx-in">
|
||||||
<table class="table data-table">
|
<table class="table data-table">
|
||||||
<tbody>
|
<tbody>
|
||||||
{{- range $vin := $tx.Vin -}}
|
{{- range $vin := $tx.Vin -}}
|
||||||
<tr>
|
<tr{{if isOwnAddress $data $vin.Addresses}} class="tx-own"{{end}}>
|
||||||
<td>
|
<td>
|
||||||
{{- if $vin.Txid -}}
|
{{- if $vin.Txid -}}
|
||||||
<a class="float-left text-muted" href="/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 -}}
|
{{- end -}}
|
||||||
{{- range $a := $vin.Addresses -}}
|
{{- range $a := $vin.Addresses -}}
|
||||||
<span class="ellipsis float-left">
|
<span class="ellipsis tx-addr">
|
||||||
{{if and (ne $a $addr) $vin.Searchable}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{end}}
|
{{if and (ne $a $addr) $vin.Searchable}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{end}}
|
||||||
</span>
|
</span>
|
||||||
{{- else -}}
|
{{- else -}}
|
||||||
<span class="float-left">{{- if $vin.Hex -}}Unparsed address{{- else -}}No Inputs (Newly Generated Coins){{- end -}}</span>
|
<span class="tx-addr">{{- if $vin.Hex -}}Unparsed address{{- else -}}No Inputs (Newly Generated Coins){{- end -}}</span>
|
||||||
{{- end -}}{{- if $vin.Addresses -}}
|
{{- end -}}{{- if $vin.Addresses -}}
|
||||||
<span class="float-right{{if stringInSlice $addr $vin.Addresses}} text-danger{{end}}">{{formatAmount $vin.ValueSat}} {{$cs}}</span>
|
<span class="tx-amt">{{formatAmount $vin.ValueSat}} {{$cs}}</span>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -45,20 +45,20 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="row">
|
<div class="row tx-out">
|
||||||
<table class="table data-table">
|
<table class="table data-table">
|
||||||
<tbody>
|
<tbody>
|
||||||
{{- range $vout := $tx.Vout -}}
|
{{- range $vout := $tx.Vout -}}
|
||||||
<tr>
|
<tr{{if isOwnAddress $data $vout.Addresses}} class="tx-own"{{end}}>
|
||||||
<td>
|
<td>
|
||||||
{{- range $a := $vout.Addresses -}}
|
{{- range $a := $vout.Addresses -}}
|
||||||
<span class="ellipsis float-left">
|
<span class="ellipsis tx-addr">
|
||||||
{{- if and (ne $a $addr) $vout.Searchable}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{- end -}}
|
{{- if and (ne $a $addr) $vout.Searchable}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{- end -}}
|
||||||
</span>
|
</span>
|
||||||
{{- else -}}
|
{{- else -}}
|
||||||
<span class="float-left">Unparsed address</span>
|
<span class="tx-addr">Unparsed address</span>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
<span class="float-right{{if stringInSlice $addr $vout.Addresses}} text-success{{end}}">
|
<span class="tx-amt">
|
||||||
{{formatAmount $vout.ValueSat}} {{$cs}} {{if $vout.Spent}}<a class="text-danger" href="{{if $vout.SpentTxID}}/tx/{{$vout.SpentTxID}}{{else}}/spending/{{$tx.Txid}}/{{$vout.N}}{{end}}" title="Spent">➡</a>{{else -}}
|
{{formatAmount $vout.ValueSat}} {{$cs}} {{if $vout.Spent}}<a class="text-danger" href="{{if $vout.SpentTxID}}/tx/{{$vout.SpentTxID}}{{else}}/spending/{{$tx.Txid}}/{{$vout.N}}{{end}}" title="Spent">➡</a>{{else -}}
|
||||||
<span class="text-success" title="Unspent"> <b>×</b></span>
|
<span class="text-success" title="Unspent"> <b>×</b></span>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|||||||
@ -29,7 +29,7 @@
|
|||||||
<td>Total XPUB Addresses</td>
|
<td>Total XPUB Addresses</td>
|
||||||
<td class="data">{{$addr.TotalTokens}}</td>
|
<td class="data">{{$addr.TotalTokens}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{- if $addr.Tokens -}}
|
{{- if $addr.TotalTokens -}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{if $data.AllTokens}}XPUB Addresses{{else}}XPUB Addresses with Balance{{end}}</td>
|
<td>{{if $data.AllTokens}}XPUB Addresses{{else}}XPUB Addresses with Balance{{end}}</td>
|
||||||
<td style="padding: 0;">
|
<td style="padding: 0;">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user