Control token detail level returned by xpub api
This commit is contained in:
parent
63fb910ecb
commit
4846af9f60
42
api/types.go
42
api/types.go
@ -19,13 +19,13 @@ type GetAddressOption int
|
|||||||
const (
|
const (
|
||||||
// Basic - only that address is indexed and some basic info
|
// Basic - only that address is indexed and some basic info
|
||||||
Basic GetAddressOption = iota
|
Basic GetAddressOption = iota
|
||||||
// Balance - only balances
|
// Tokens - basic info + tokens
|
||||||
Balance
|
Tokens
|
||||||
// TxidHistory - balances and txids, subject to paging
|
// TxidHistory - basic + tokens + txids, subject to paging
|
||||||
TxidHistory
|
TxidHistory
|
||||||
// TxHistoryLight - balances and easily obtained tx data (not requiring request to backend), subject to paging
|
// TxHistoryLight - basic + tokens + easily obtained tx data (not requiring request to backend), subject to paging
|
||||||
TxHistoryLight
|
TxHistoryLight
|
||||||
// TxHistory - balances and full tx data, subject to paging
|
// TxHistory - basic + tokens + full tx data, subject to paging
|
||||||
TxHistory
|
TxHistory
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -138,14 +138,17 @@ const XPUBAddressTokenType TokenType = "XPUBAddress"
|
|||||||
|
|
||||||
// Token contains info about tokens held by an address
|
// Token contains info about tokens held by an address
|
||||||
type Token struct {
|
type Token struct {
|
||||||
Type TokenType `json:"type"`
|
Type TokenType `json:"type"`
|
||||||
Contract string `json:"contract"`
|
Name string `json:"name"`
|
||||||
Transfers int `json:"transfers"`
|
Path string `json:"path,omitempty"`
|
||||||
Name string `json:"name"`
|
Contract string `json:"contract,omitempty"`
|
||||||
Symbol string `json:"symbol"`
|
Transfers int `json:"transfers"`
|
||||||
Decimals int `json:"decimals"`
|
Symbol string `json:"symbol,omitempty"`
|
||||||
BalanceSat *Amount `json:"balance,omitempty"`
|
Decimals int `json:"decimals,omitempty"`
|
||||||
ContractIndex string `json:"-"`
|
BalanceSat *Amount `json:"balance,omitempty"`
|
||||||
|
TotalReceivedSat *Amount `json:"totalReceived,omitempty"`
|
||||||
|
TotalSentSat *Amount `json:"totalSent,omitempty"`
|
||||||
|
ContractIndex string `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TokenTransfer contains info about a token transfer done in a transaction
|
// TokenTransfer contains info about a token transfer done in a transaction
|
||||||
@ -198,6 +201,9 @@ type Paging struct {
|
|||||||
ItemsOnPage int `json:"itemsOnPage,omitempty"`
|
ItemsOnPage int `json:"itemsOnPage,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TokenDetailLevel specifies detail level of tokens returned by GetAddress and GetXpubAddress
|
||||||
|
type TokenDetailLevel int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// AddressFilterVoutOff disables filtering of transactions by vout
|
// AddressFilterVoutOff disables filtering of transactions by vout
|
||||||
AddressFilterVoutOff = -1
|
AddressFilterVoutOff = -1
|
||||||
@ -205,6 +211,13 @@ const (
|
|||||||
AddressFilterVoutInputs = -2
|
AddressFilterVoutInputs = -2
|
||||||
// AddressFilterVoutOutputs specifies that only txs where the address is as output are returned
|
// AddressFilterVoutOutputs specifies that only txs where the address is as output are returned
|
||||||
AddressFilterVoutOutputs = -3
|
AddressFilterVoutOutputs = -3
|
||||||
|
|
||||||
|
// TokenDetailNonzeroBalance - use to return only tokens with nonzero balance
|
||||||
|
TokenDetailNonzeroBalance TokenDetailLevel = 0
|
||||||
|
// TokenDetailUsed - use to return tokens with some transfers (even if they have zero balance now)
|
||||||
|
TokenDetailUsed TokenDetailLevel = 1
|
||||||
|
// TokenDetailDiscovered - use to return all discovered tokens
|
||||||
|
TokenDetailDiscovered TokenDetailLevel = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddressFilter is used to filter data returned from GetAddress api method
|
// AddressFilter is used to filter data returned from GetAddress api method
|
||||||
@ -213,8 +226,7 @@ type AddressFilter struct {
|
|||||||
Contract string
|
Contract string
|
||||||
FromHeight uint32
|
FromHeight uint32
|
||||||
ToHeight uint32
|
ToHeight uint32
|
||||||
// AllTokens set to true will include xpub addresses with zero balance
|
TokenLevel TokenDetailLevel
|
||||||
AllTokens bool
|
|
||||||
// OnlyConfirmed set to true will ignore mempool transactions; mempool is also ignored if FromHeight/ToHeight filter is specified
|
// OnlyConfirmed set to true will ignore mempool transactions; mempool is also ignored if FromHeight/ToHeight filter is specified
|
||||||
OnlyConfirmed bool
|
OnlyConfirmed bool
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,7 +51,7 @@ func (w *Worker) getAddressesFromVout(vout *bchain.Vout) (bchain.AddressDescript
|
|||||||
// setSpendingTxToVout is helper function, that finds transaction that spent given output and sets it to the output
|
// setSpendingTxToVout is helper function, that finds transaction that spent given output and sets it to the output
|
||||||
// there is no direct index for the operation, it must be found using addresses -> txaddresses -> tx
|
// there is no direct index for the operation, it must be found using addresses -> txaddresses -> tx
|
||||||
func (w *Worker) setSpendingTxToVout(vout *Vout, txid string, height uint32) error {
|
func (w *Worker) setSpendingTxToVout(vout *Vout, txid string, height uint32) error {
|
||||||
err := w.db.GetAddrDescTransactions(vout.AddrDesc, height, ^uint32(0), func(t string, height uint32, indexes []int32) error {
|
err := w.db.GetAddrDescTransactions(vout.AddrDesc, height, maxUint32, func(t string, height uint32, indexes []int32) error {
|
||||||
for _, index := range indexes {
|
for _, index := range indexes {
|
||||||
// take only inputs
|
// take only inputs
|
||||||
if index < 0 {
|
if index < 0 {
|
||||||
@ -364,7 +364,7 @@ func (w *Worker) getAddressTxids(addrDesc bchain.AddressDescriptor, mempool bool
|
|||||||
} else {
|
} else {
|
||||||
to := filter.ToHeight
|
to := filter.ToHeight
|
||||||
if to == 0 {
|
if to == 0 {
|
||||||
to = ^uint32(0)
|
to = maxUint32
|
||||||
}
|
}
|
||||||
err = w.db.GetAddrDescTransactions(addrDesc, filter.FromHeight, to, callback)
|
err = w.db.GetAddrDescTransactions(addrDesc, filter.FromHeight, to, callback)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -683,8 +683,8 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option GetA
|
|||||||
ba = &db.AddrBalance{}
|
ba = &db.AddrBalance{}
|
||||||
page = 0
|
page = 0
|
||||||
}
|
}
|
||||||
// process mempool, only if blockheight filter is off
|
// process mempool, only if toHeight is not specified
|
||||||
if filter.FromHeight == 0 && filter.ToHeight == 0 && !filter.OnlyConfirmed {
|
if filter.ToHeight == 0 && !filter.OnlyConfirmed {
|
||||||
txm, err = w.getAddressTxids(addrDesc, true, filter, maxInt)
|
txm, err = w.getAddressTxids(addrDesc, true, filter, maxInt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Annotatef(err, "getAddressTxids %v true", addrDesc)
|
return nil, errors.Annotatef(err, "getAddressTxids %v true", addrDesc)
|
||||||
@ -825,7 +825,7 @@ func (w *Worker) getAddrDescUtxo(addrDesc bchain.AddressDescriptor, ba *db.AddrB
|
|||||||
// ba can be nil if the address is only in mempool!
|
// ba can be nil if the address is only in mempool!
|
||||||
if ba != nil && !IsZeroBigInt(&ba.BalanceSat) {
|
if ba != nil && !IsZeroBigInt(&ba.BalanceSat) {
|
||||||
outpoints := make([]bchain.Outpoint, 0, 8)
|
outpoints := make([]bchain.Outpoint, 0, 8)
|
||||||
err = w.db.GetAddrDescTransactions(addrDesc, 0, ^uint32(0), func(txid string, height uint32, indexes []int32) error {
|
err = w.db.GetAddrDescTransactions(addrDesc, 0, maxUint32, func(txid string, height uint32, indexes []int32) error {
|
||||||
for _, index := range indexes {
|
for _, index := range indexes {
|
||||||
// take only outputs
|
// take only outputs
|
||||||
if index >= 0 {
|
if index >= 0 {
|
||||||
@ -943,7 +943,7 @@ func (w *Worker) GetBlock(bid string, page int, txsOnPage int) (*Block, error) {
|
|||||||
// if it's a number, must be less than int32
|
// if it's a number, must be less than int32
|
||||||
var hash string
|
var hash string
|
||||||
height, err := strconv.Atoi(bid)
|
height, err := strconv.Atoi(bid)
|
||||||
if err == nil && height < int(^uint32(0)) {
|
if err == nil && height < int(maxUint32) {
|
||||||
hash, err = w.db.GetBlockHash(uint32(height))
|
hash, err = w.db.GetBlockHash(uint32(height))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
hash = bid
|
hash = bid
|
||||||
|
|||||||
43
api/xpub.go
43
api/xpub.go
@ -218,19 +218,23 @@ func (w *Worker) tokenFromXpubAddress(data *xpubData, ad *xpubAddress, changeInd
|
|||||||
if len(a) > 0 {
|
if len(a) > 0 {
|
||||||
address = a[0]
|
address = a[0]
|
||||||
}
|
}
|
||||||
var balance *big.Int
|
var balance, totalReceived, totalSent *big.Int
|
||||||
var transfers int
|
var transfers int
|
||||||
if ad.balance != nil {
|
if ad.balance != nil {
|
||||||
balance = &ad.balance.BalanceSat
|
balance = &ad.balance.BalanceSat
|
||||||
|
totalSent = &ad.balance.SentSat
|
||||||
|
totalReceived = ad.balance.ReceivedSat()
|
||||||
transfers = int(ad.balance.Txs)
|
transfers = int(ad.balance.Txs)
|
||||||
}
|
}
|
||||||
return Token{
|
return Token{
|
||||||
Type: XPUBAddressTokenType,
|
Type: XPUBAddressTokenType,
|
||||||
Name: address,
|
Name: address,
|
||||||
Decimals: w.chainParser.AmountDecimals(),
|
Decimals: w.chainParser.AmountDecimals(),
|
||||||
BalanceSat: (*Amount)(balance),
|
BalanceSat: (*Amount)(balance),
|
||||||
Transfers: transfers,
|
TotalReceivedSat: (*Amount)(totalReceived),
|
||||||
Contract: fmt.Sprintf("%s/%d/%d", data.basePath, changeIndex, index),
|
TotalSentSat: (*Amount)(totalSent),
|
||||||
|
Transfers: transfers,
|
||||||
|
Path: fmt.Sprintf("%s/%d/%d", data.basePath, changeIndex, index),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,8 +375,8 @@ func (w *Worker) GetXpubAddress(xpub string, page int, txsOnPage int, option Get
|
|||||||
}
|
}
|
||||||
totalResults = -1
|
totalResults = -1
|
||||||
}
|
}
|
||||||
// process mempool, only if blockheight filter is off
|
// process mempool, only if ToHeight is not specified
|
||||||
if filter.FromHeight == 0 && filter.ToHeight == 0 && !filter.OnlyConfirmed {
|
if filter.ToHeight == 0 && !filter.OnlyConfirmed {
|
||||||
txmMap = make(map[string]*Tx)
|
txmMap = make(map[string]*Tx)
|
||||||
for _, da := range [][]xpubAddress{data.addresses, data.changeAddresses} {
|
for _, da := range [][]xpubAddress{data.addresses, data.changeAddresses} {
|
||||||
for i := range da {
|
for i := range da {
|
||||||
@ -442,19 +446,27 @@ func (w *Worker) GetXpubAddress(xpub string, page int, txsOnPage int, option Get
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalTokens := 0
|
totalTokens := 0
|
||||||
xpubAddresses := make(map[string]struct{})
|
var tokens []Token
|
||||||
tokens := make([]Token, 0, 4)
|
var xpubAddresses map[string]struct{}
|
||||||
|
if option != Basic {
|
||||||
|
tokens = make([]Token, 0, 4)
|
||||||
|
xpubAddresses = make(map[string]struct{})
|
||||||
|
}
|
||||||
for ci, da := range [][]xpubAddress{data.addresses, data.changeAddresses} {
|
for ci, da := range [][]xpubAddress{data.addresses, data.changeAddresses} {
|
||||||
for i := range da {
|
for i := range da {
|
||||||
ad := &da[i]
|
ad := &da[i]
|
||||||
token := w.tokenFromXpubAddress(data, ad, ci, i)
|
|
||||||
if ad.balance != nil {
|
if ad.balance != nil {
|
||||||
totalTokens++
|
totalTokens++
|
||||||
if filter.AllTokens || !IsZeroBigInt(&ad.balance.BalanceSat) {
|
}
|
||||||
|
if option != Basic {
|
||||||
|
token := w.tokenFromXpubAddress(data, ad, ci, i)
|
||||||
|
if filter.TokenLevel == TokenDetailDiscovered ||
|
||||||
|
filter.TokenLevel == TokenDetailUsed && ad.balance != nil ||
|
||||||
|
filter.TokenLevel == TokenDetailNonzeroBalance && ad.balance != nil && !IsZeroBigInt(&ad.balance.BalanceSat) {
|
||||||
tokens = append(tokens, token)
|
tokens = append(tokens, token)
|
||||||
}
|
}
|
||||||
|
xpubAddresses[token.Name] = struct{}{}
|
||||||
}
|
}
|
||||||
xpubAddresses[token.Name] = struct{}{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var totalReceived big.Int
|
var totalReceived big.Int
|
||||||
@ -483,7 +495,6 @@ func (w *Worker) GetXpubUtxo(xpub string, onlyConfirmed bool, gap int) (Utxos, e
|
|||||||
start := time.Now()
|
start := time.Now()
|
||||||
data, _, err := w.getXpubData(xpub, 0, 1, Basic, &AddressFilter{
|
data, _, err := w.getXpubData(xpub, 0, 1, Basic, &AddressFilter{
|
||||||
Vout: AddressFilterVoutOff,
|
Vout: AddressFilterVoutOff,
|
||||||
AllTokens: false,
|
|
||||||
OnlyConfirmed: onlyConfirmed,
|
OnlyConfirmed: onlyConfirmed,
|
||||||
}, gap)
|
}, gap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -509,7 +520,7 @@ func (w *Worker) GetXpubUtxo(xpub string, onlyConfirmed bool, gap int) (Utxos, e
|
|||||||
for j := range utxos {
|
for j := range utxos {
|
||||||
a := &utxos[j]
|
a := &utxos[j]
|
||||||
a.Address = t.Name
|
a.Address = t.Name
|
||||||
a.Path = t.Contract
|
a.Path = t.Path
|
||||||
}
|
}
|
||||||
r = append(r, utxos...)
|
r = append(r, utxos...)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -385,27 +385,27 @@ const (
|
|||||||
|
|
||||||
// TemplateData is used to transfer data to the templates
|
// TemplateData is used to transfer data to the templates
|
||||||
type TemplateData struct {
|
type TemplateData struct {
|
||||||
CoinName string
|
CoinName string
|
||||||
CoinShortcut string
|
CoinShortcut string
|
||||||
CoinLabel string
|
CoinLabel string
|
||||||
InternalExplorer bool
|
InternalExplorer bool
|
||||||
ChainType bchain.ChainType
|
ChainType bchain.ChainType
|
||||||
Address *api.Address
|
Address *api.Address
|
||||||
AddrStr string
|
AddrStr string
|
||||||
Tx *api.Tx
|
Tx *api.Tx
|
||||||
Error *api.APIError
|
Error *api.APIError
|
||||||
Blocks *api.Blocks
|
Blocks *api.Blocks
|
||||||
Block *api.Block
|
Block *api.Block
|
||||||
Info *api.SystemInfo
|
Info *api.SystemInfo
|
||||||
Page int
|
Page int
|
||||||
PrevPage int
|
PrevPage int
|
||||||
NextPage int
|
NextPage int
|
||||||
PagingRange []int
|
PagingRange []int
|
||||||
PageParams template.URL
|
PageParams template.URL
|
||||||
TOSLink string
|
TOSLink string
|
||||||
SendTxHex string
|
SendTxHex string
|
||||||
Status string
|
Status string
|
||||||
AllTokens bool
|
NonZeroBalanceTokens bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublicServer) parseTemplates() []*template.Template {
|
func (s *PublicServer) parseTemplates() []*template.Template {
|
||||||
@ -600,7 +600,7 @@ func (s *PublicServer) explorerAddress(w http.ResponseWriter, r *http.Request) (
|
|||||||
return addressTpl, data, nil
|
return addressTpl, data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublicServer) getXpubAddress(r *http.Request, xpub string, pageSize int, option api.GetAddressOption) (*api.Address, error) {
|
func (s *PublicServer) getXpubAddress(r *http.Request, xpub string, pageSize int, option api.GetAddressOption) (*api.Address, api.TokenDetailLevel, error) {
|
||||||
var fn = api.AddressFilterVoutOff
|
var fn = api.AddressFilterVoutOff
|
||||||
page, ec := strconv.Atoi(r.URL.Query().Get("page"))
|
page, ec := strconv.Atoi(r.URL.Query().Get("page"))
|
||||||
if ec != nil {
|
if ec != nil {
|
||||||
@ -624,16 +624,26 @@ func (s *PublicServer) getXpubAddress(r *http.Request, xpub string, pageSize int
|
|||||||
if ec != nil {
|
if ec != nil {
|
||||||
gap = 0
|
gap = 0
|
||||||
}
|
}
|
||||||
allAddresses, _ := strconv.ParseBool(r.URL.Query().Get("alladdresses"))
|
tokenLevel := api.TokenDetailNonzeroBalance
|
||||||
return s.api.GetXpubAddress(xpub, page, pageSize, option, &api.AddressFilter{Vout: fn, AllTokens: allAddresses}, gap)
|
switch r.URL.Query().Get("tokenlevel") {
|
||||||
|
case "discovered":
|
||||||
|
tokenLevel = api.TokenDetailDiscovered
|
||||||
|
case "used":
|
||||||
|
tokenLevel = api.TokenDetailUsed
|
||||||
|
case "nonzero":
|
||||||
|
tokenLevel = api.TokenDetailNonzeroBalance
|
||||||
|
}
|
||||||
|
a, err := s.api.GetXpubAddress(xpub, page, pageSize, option, &api.AddressFilter{Vout: fn, TokenLevel: tokenLevel}, gap)
|
||||||
|
return a, tokenLevel, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublicServer) explorerXpub(w http.ResponseWriter, r *http.Request) (tpl, *TemplateData, error) {
|
func (s *PublicServer) explorerXpub(w http.ResponseWriter, r *http.Request) (tpl, *TemplateData, error) {
|
||||||
var address *api.Address
|
var address *api.Address
|
||||||
|
var tokenLevel api.TokenDetailLevel
|
||||||
var err error
|
var err error
|
||||||
s.metrics.ExplorerViews.With(common.Labels{"action": "xpub"}).Inc()
|
s.metrics.ExplorerViews.With(common.Labels{"action": "xpub"}).Inc()
|
||||||
if i := strings.LastIndexByte(r.URL.Path, '/'); i > 0 {
|
if i := strings.LastIndexByte(r.URL.Path, '/'); i > 0 {
|
||||||
address, err = s.getXpubAddress(r, r.URL.Path[i+1:], txsOnPage, api.TxHistoryLight)
|
address, tokenLevel, err = s.getXpubAddress(r, r.URL.Path[i+1:], txsOnPage, api.TxHistoryLight)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorTpl, nil, err
|
return errorTpl, nil, err
|
||||||
}
|
}
|
||||||
@ -648,8 +658,7 @@ func (s *PublicServer) explorerXpub(w http.ResponseWriter, r *http.Request) (tpl
|
|||||||
data.PageParams = template.URL("&filter=" + filter)
|
data.PageParams = template.URL("&filter=" + filter)
|
||||||
data.Address.Filter = filter
|
data.Address.Filter = filter
|
||||||
}
|
}
|
||||||
allAddresses := r.URL.Query().Get("alladdresses")
|
data.NonZeroBalanceTokens = tokenLevel == api.TokenDetailNonzeroBalance
|
||||||
data.AllTokens, _ = strconv.ParseBool(allAddresses)
|
|
||||||
return xpubTpl, data, nil
|
return xpubTpl, data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -904,7 +913,7 @@ func (s *PublicServer) apiXpub(r *http.Request, apiVersion int) (interface{}, er
|
|||||||
var err error
|
var err error
|
||||||
s.metrics.ExplorerViews.With(common.Labels{"action": "api-xpub"}).Inc()
|
s.metrics.ExplorerViews.With(common.Labels{"action": "api-xpub"}).Inc()
|
||||||
if i := strings.LastIndexByte(r.URL.Path, '/'); i > 0 {
|
if i := strings.LastIndexByte(r.URL.Path, '/'); i > 0 {
|
||||||
address, err = s.getXpubAddress(r, r.URL.Path[i+1:], txsInAPI, api.TxidHistory)
|
address, _, err = s.getXpubAddress(r, r.URL.Path[i+1:], txsInAPI, api.TxidHistory)
|
||||||
if err == nil && apiVersion == apiV1 {
|
if err == nil && apiVersion == apiV1 {
|
||||||
return s.api.AddressToV1(address), nil
|
return s.api.AddressToV1(address), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -349,8 +349,8 @@ func unmarshalGetAccountInfoRequest(params []byte) (*accountInfoReq, error) {
|
|||||||
func (s *WebsocketServer) getAccountInfo(req *accountInfoReq) (res *api.Address, err error) {
|
func (s *WebsocketServer) getAccountInfo(req *accountInfoReq) (res *api.Address, err error) {
|
||||||
var opt api.GetAddressOption
|
var opt api.GetAddressOption
|
||||||
switch req.Details {
|
switch req.Details {
|
||||||
case "balance":
|
case "tokens":
|
||||||
opt = api.Balance
|
opt = api.Tokens
|
||||||
case "txids":
|
case "txids":
|
||||||
opt = api.TxidHistory
|
opt = api.TxidHistory
|
||||||
case "txs":
|
case "txs":
|
||||||
@ -363,7 +363,7 @@ func (s *WebsocketServer) getAccountInfo(req *accountInfoReq) (res *api.Address,
|
|||||||
ToHeight: uint32(req.ToHeight),
|
ToHeight: uint32(req.ToHeight),
|
||||||
Contract: req.ContractFilter,
|
Contract: req.ContractFilter,
|
||||||
Vout: api.AddressFilterVoutOff,
|
Vout: api.AddressFilterVoutOff,
|
||||||
AllTokens: true,
|
TokenLevel: api.TokenDetailDiscovered,
|
||||||
}
|
}
|
||||||
a, err := s.api.GetXpubAddress(req.Descriptor, req.Page, req.PageSize, opt, &filter, 0)
|
a, err := s.api.GetXpubAddress(req.Descriptor, req.Page, req.PageSize, opt, &filter, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{{- if $addr.TotalTokens -}}
|
{{- if $addr.TotalTokens -}}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{if $data.AllTokens}}XPUB Addresses{{else}}XPUB Addresses with Balance{{end}}</td>
|
<td>{{if $data.NonZeroBalanceTokens}}XPUB Addresses with Balance{{else}}XPUB Addresses{{end}}</td>
|
||||||
<td style="padding: 0;">
|
<td style="padding: 0;">
|
||||||
<table class="table data-table">
|
<table class="table data-table">
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -46,12 +46,12 @@
|
|||||||
<td class="data ellipsis"><a href="/address/{{$t.Name}}">{{$t.Name}}</a></td>
|
<td class="data ellipsis"><a href="/address/{{$t.Name}}">{{$t.Name}}</a></td>
|
||||||
<td class="data">{{formatAmount $t.BalanceSat}} {{$cs}}</td>
|
<td class="data">{{formatAmount $t.BalanceSat}} {{$cs}}</td>
|
||||||
<td class="data">{{$t.Transfers}}</td>
|
<td class="data">{{$t.Transfers}}</td>
|
||||||
<td>{{$t.Contract}}</td>
|
<td>{{$t.Path}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- if not $data.AllTokens -}}
|
{{- if $data.NonZeroBalanceTokens -}}
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="4"><a href="?alladdresses=true">Show all XPUB addresses</a></td>
|
<td colspan="4"><a href="?tokenlevel=used">Show all XPUB addresses</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
@ -304,7 +304,7 @@
|
|||||||
<input type="text" placeholder="descriptor" style="width: 79%" class="form-control" id="getAccountInfoDescriptor" value="0xba98d6a5ac827632e3457de7512d211e4ff7e8bd">
|
<input type="text" placeholder="descriptor" style="width: 79%" class="form-control" id="getAccountInfoDescriptor" value="0xba98d6a5ac827632e3457de7512d211e4ff7e8bd">
|
||||||
<select id="getAccountInfoDetails" style="width: 20%; margin-left: 5px;">
|
<select id="getAccountInfoDetails" style="width: 20%; margin-left: 5px;">
|
||||||
<option value="basic">Basic</option>
|
<option value="basic">Basic</option>
|
||||||
<option value="balance">Balance</option>
|
<option value="tokens">Tokens</option>
|
||||||
<option value="txids">Txids</option>
|
<option value="txids">Txids</option>
|
||||||
<option value="txs">Transactions</option>
|
<option value="txs">Transactions</option>
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user