Add tokens to return level choice to websocket interface
parent
e54998dccc
commit
1c35c632cb
26
api/types.go
26
api/types.go
|
@ -204,8 +204,8 @@ type Paging struct {
|
|||
ItemsOnPage int `json:"itemsOnPage,omitempty"`
|
||||
}
|
||||
|
||||
// TokenDetailLevel specifies detail level of tokens returned by GetAddress and GetXpubAddress
|
||||
type TokenDetailLevel int
|
||||
// TokensToReturn specifies what tokens are returned by GetAddress and GetXpubAddress
|
||||
type TokensToReturn int
|
||||
|
||||
const (
|
||||
// AddressFilterVoutOff disables filtering of transactions by vout
|
||||
|
@ -215,21 +215,21 @@ const (
|
|||
// AddressFilterVoutOutputs specifies that only txs where the address is as output are returned
|
||||
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
|
||||
// TokensToReturnNonzeroBalance - return only tokens with nonzero balance
|
||||
TokensToReturnNonzeroBalance TokensToReturn = 0
|
||||
// TokensToReturnUsed - return tokens with some transfers (even if they have zero balance now)
|
||||
TokensToReturnUsed TokensToReturn = 1
|
||||
// TokensToReturnDerived - return all derived tokens
|
||||
TokensToReturnDerived TokensToReturn = 2
|
||||
)
|
||||
|
||||
// AddressFilter is used to filter data returned from GetAddress api method
|
||||
type AddressFilter struct {
|
||||
Vout int
|
||||
Contract string
|
||||
FromHeight uint32
|
||||
ToHeight uint32
|
||||
TokenLevel TokenDetailLevel
|
||||
Vout int
|
||||
Contract string
|
||||
FromHeight uint32
|
||||
ToHeight uint32
|
||||
TokensToReturn TokensToReturn
|
||||
// OnlyConfirmed set to true will ignore mempool transactions; mempool is also ignored if FromHeight/ToHeight filter is specified
|
||||
OnlyConfirmed bool
|
||||
}
|
||||
|
|
|
@ -906,6 +906,9 @@ func (w *Worker) GetAddressUtxo(address string, onlyConfirmed bool) (Utxos, erro
|
|||
return nil, NewAPIError(fmt.Sprintf("Invalid address '%v', %v", address, err), true)
|
||||
}
|
||||
r, err := w.getAddrDescUtxo(addrDesc, nil, onlyConfirmed, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
glog.Info("GetAddressUtxo ", address, ", ", len(r), " utxos, finished in ", time.Since(start))
|
||||
return r, nil
|
||||
}
|
||||
|
|
|
@ -502,9 +502,9 @@ func (w *Worker) GetXpubAddress(xpub string, page int, txsOnPage int, option Acc
|
|||
}
|
||||
if option > AccountDetailsBasic {
|
||||
token := w.tokenFromXpubAddress(data, ad, ci, i, option)
|
||||
if filter.TokenLevel == TokenDetailDiscovered ||
|
||||
filter.TokenLevel == TokenDetailUsed && ad.balance != nil ||
|
||||
filter.TokenLevel == TokenDetailNonzeroBalance && ad.balance != nil && !IsZeroBigInt(&ad.balance.BalanceSat) {
|
||||
if filter.TokensToReturn == TokensToReturnDerived ||
|
||||
filter.TokensToReturn == TokensToReturnUsed && ad.balance != nil ||
|
||||
filter.TokensToReturn == TokensToReturnNonzeroBalance && ad.balance != nil && !IsZeroBigInt(&ad.balance.BalanceSat) {
|
||||
tokens = append(tokens, token)
|
||||
}
|
||||
xpubAddresses[token.Name] = struct{}{}
|
||||
|
|
|
@ -607,7 +607,7 @@ func (s *PublicServer) explorerAddress(w http.ResponseWriter, r *http.Request) (
|
|||
return addressTpl, data, nil
|
||||
}
|
||||
|
||||
func (s *PublicServer) getXpubAddress(r *http.Request, xpub string, pageSize int, option api.AccountDetails) (*api.Address, api.TokenDetailLevel, error) {
|
||||
func (s *PublicServer) getXpubAddress(r *http.Request, xpub string, pageSize int, option api.AccountDetails) (*api.Address, api.TokensToReturn, error) {
|
||||
var fn = api.AddressFilterVoutOff
|
||||
page, ec := strconv.Atoi(r.URL.Query().Get("page"))
|
||||
if ec != nil {
|
||||
|
@ -622,7 +622,6 @@ func (s *PublicServer) getXpubAddress(r *http.Request, xpub string, pageSize int
|
|||
} else {
|
||||
fn, ec = strconv.Atoi(filter)
|
||||
if ec != nil || fn < 0 {
|
||||
filter = ""
|
||||
fn = api.AddressFilterVoutOff
|
||||
}
|
||||
}
|
||||
|
@ -631,26 +630,26 @@ func (s *PublicServer) getXpubAddress(r *http.Request, xpub string, pageSize int
|
|||
if ec != nil {
|
||||
gap = 0
|
||||
}
|
||||
tokenLevel := api.TokenDetailNonzeroBalance
|
||||
switch r.URL.Query().Get("tokenlevel") {
|
||||
case "discovered":
|
||||
tokenLevel = api.TokenDetailDiscovered
|
||||
tokensToReturn := api.TokensToReturnNonzeroBalance
|
||||
switch r.URL.Query().Get("tokens") {
|
||||
case "derived":
|
||||
tokensToReturn = api.TokensToReturnDerived
|
||||
case "used":
|
||||
tokenLevel = api.TokenDetailUsed
|
||||
tokensToReturn = api.TokensToReturnUsed
|
||||
case "nonzero":
|
||||
tokenLevel = api.TokenDetailNonzeroBalance
|
||||
tokensToReturn = api.TokensToReturnNonzeroBalance
|
||||
}
|
||||
a, err := s.api.GetXpubAddress(xpub, page, pageSize, option, &api.AddressFilter{Vout: fn, TokenLevel: tokenLevel}, gap)
|
||||
return a, tokenLevel, err
|
||||
a, err := s.api.GetXpubAddress(xpub, page, pageSize, option, &api.AddressFilter{Vout: fn, TokensToReturn: tokensToReturn}, gap)
|
||||
return a, tokensToReturn, err
|
||||
}
|
||||
|
||||
func (s *PublicServer) explorerXpub(w http.ResponseWriter, r *http.Request) (tpl, *TemplateData, error) {
|
||||
var address *api.Address
|
||||
var tokenLevel api.TokenDetailLevel
|
||||
var tokensToReturn api.TokensToReturn
|
||||
var err error
|
||||
s.metrics.ExplorerViews.With(common.Labels{"action": "xpub"}).Inc()
|
||||
if i := strings.LastIndexByte(r.URL.Path, '/'); i > 0 {
|
||||
address, tokenLevel, err = s.getXpubAddress(r, r.URL.Path[i+1:], txsOnPage, api.AccountDetailsTxHistoryLight)
|
||||
address, tokensToReturn, err = s.getXpubAddress(r, r.URL.Path[i+1:], txsOnPage, api.AccountDetailsTxHistoryLight)
|
||||
if err != nil {
|
||||
return errorTpl, nil, err
|
||||
}
|
||||
|
@ -665,7 +664,7 @@ func (s *PublicServer) explorerXpub(w http.ResponseWriter, r *http.Request) (tpl
|
|||
data.PageParams = template.URL("&filter=" + filter)
|
||||
data.Address.Filter = filter
|
||||
}
|
||||
data.NonZeroBalanceTokens = tokenLevel == api.TokenDetailNonzeroBalance
|
||||
data.NonZeroBalanceTokens = tokensToReturn == api.TokensToReturnNonzeroBalance
|
||||
return xpubTpl, data, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -461,7 +461,7 @@ func httpTests_BitcoinType(t *testing.T, ts *httptest.Server) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "apiXpub v2 tokenlevel=nonzero",
|
||||
name: "apiXpub v2 tokens=nonzero",
|
||||
r: newGetRequest(ts.URL + "/api/v2/xpub/" + dbtestdata.Xpub),
|
||||
status: http.StatusOK,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
|
@ -470,8 +470,8 @@ func httpTests_BitcoinType(t *testing.T, ts *httptest.Server) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "apiXpub v2 tokenlevel=used",
|
||||
r: newGetRequest(ts.URL + "/api/v2/xpub/" + dbtestdata.Xpub + "?tokenlevel=used"),
|
||||
name: "apiXpub v2 tokens=used",
|
||||
r: newGetRequest(ts.URL + "/api/v2/xpub/" + dbtestdata.Xpub + "?tokens=used"),
|
||||
status: http.StatusOK,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
body: []string{
|
||||
|
@ -479,8 +479,8 @@ func httpTests_BitcoinType(t *testing.T, ts *httptest.Server) {
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "apiXpub v2 tokenlevel=discovered",
|
||||
r: newGetRequest(ts.URL + "/api/v2/xpub/" + dbtestdata.Xpub + "?tokenlevel=discovered"),
|
||||
name: "apiXpub v2 tokens=derived",
|
||||
r: newGetRequest(ts.URL + "/api/v2/xpub/" + dbtestdata.Xpub + "?tokens=derived"),
|
||||
status: http.StatusOK,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
body: []string{
|
||||
|
|
|
@ -330,6 +330,7 @@ func (s *WebsocketServer) onRequest(c *websocketChannel, req *websocketReq) {
|
|||
type accountInfoReq struct {
|
||||
Descriptor string `json:"descriptor"`
|
||||
Details string `json:"details"`
|
||||
Tokens string `json:"tokens"`
|
||||
PageSize int `json:"pageSize"`
|
||||
Page int `json:"page"`
|
||||
FromHeight int `json:"from"`
|
||||
|
@ -360,12 +361,21 @@ func (s *WebsocketServer) getAccountInfo(req *accountInfoReq) (res *api.Address,
|
|||
default:
|
||||
opt = api.AccountDetailsBasic
|
||||
}
|
||||
var tokensToReturn api.TokensToReturn
|
||||
switch req.Tokens {
|
||||
case "used":
|
||||
tokensToReturn = api.TokensToReturnUsed
|
||||
case "nonzero":
|
||||
tokensToReturn = api.TokensToReturnNonzeroBalance
|
||||
default:
|
||||
tokensToReturn = api.TokensToReturnDerived
|
||||
}
|
||||
filter := api.AddressFilter{
|
||||
FromHeight: uint32(req.FromHeight),
|
||||
ToHeight: uint32(req.ToHeight),
|
||||
Contract: req.ContractFilter,
|
||||
Vout: api.AddressFilterVoutOff,
|
||||
TokenLevel: api.TokenDetailDiscovered,
|
||||
FromHeight: uint32(req.FromHeight),
|
||||
ToHeight: uint32(req.ToHeight),
|
||||
Contract: req.ContractFilter,
|
||||
Vout: api.AddressFilterVoutOff,
|
||||
TokensToReturn: tokensToReturn,
|
||||
}
|
||||
a, err := s.api.GetXpubAddress(req.Descriptor, req.Page, req.PageSize, opt, &filter, 0)
|
||||
if err != nil {
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
{{- end -}}
|
||||
{{- if $data.NonZeroBalanceTokens -}}
|
||||
<tr>
|
||||
<td colspan="4"><a href="?tokenlevel=used">Show all XPUB addresses</a></td>
|
||||
<td colspan="4"><a href="?tokens=used">Show all XPUB addresses</a></td>
|
||||
</tr>
|
||||
{{- end -}}
|
||||
</tbody>
|
||||
|
|
|
@ -125,9 +125,11 @@
|
|||
const contractFilter = document.getElementById("getAccountInfoContract").value.trim();
|
||||
const pageSize = 10;
|
||||
const method = 'getAccountInfo';
|
||||
const tokens = "derived"; // could be "nonzero", "used", default is "derived" i.e. all
|
||||
const params = {
|
||||
descriptor,
|
||||
details,
|
||||
tokens,
|
||||
page,
|
||||
pageSize,
|
||||
from,
|
||||
|
|
Loading…
Reference in New Issue