Get address data for explorer using index v3 - WIP
This commit is contained in:
parent
c67306ad09
commit
bbc47db6dd
@ -61,4 +61,7 @@ type Address struct {
|
|||||||
UnconfirmedTxApperances int `json:"unconfirmedTxApperances"`
|
UnconfirmedTxApperances int `json:"unconfirmedTxApperances"`
|
||||||
TxApperances int `json:"txApperances"`
|
TxApperances int `json:"txApperances"`
|
||||||
Transactions []*Tx `json:"transactions"`
|
Transactions []*Tx `json:"transactions"`
|
||||||
|
Page int `json:"page"`
|
||||||
|
TotalPages int `json:"totalPages"`
|
||||||
|
TxsOnPage int `json:"txsOnPage"`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,13 +4,12 @@ import (
|
|||||||
"blockbook/bchain"
|
"blockbook/bchain"
|
||||||
"blockbook/common"
|
"blockbook/common"
|
||||||
"blockbook/db"
|
"blockbook/db"
|
||||||
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
const txsOnPage = 30
|
|
||||||
|
|
||||||
// Worker is handle to api worker
|
// Worker is handle to api worker
|
||||||
type Worker struct {
|
type Worker struct {
|
||||||
db *db.RocksDB
|
db *db.RocksDB
|
||||||
@ -172,7 +171,83 @@ func UniqueTxidsInReverse(txids []string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetAddress computes address value and gets transactions for given address
|
// GetAddress computes address value and gets transactions for given address
|
||||||
func (w *Worker) GetAddress(addrID string, page int) (*Address, error) {
|
func (w *Worker) GetAddressNew(address string, page int, txsOnPage int) (*Address, error) {
|
||||||
|
glog.Info(address, " start")
|
||||||
|
ba, err := w.db.GetAddressBalance(address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if ba == nil {
|
||||||
|
return nil, errors.New("Address not found")
|
||||||
|
}
|
||||||
|
txc, err := w.getAddressTxids(address, false)
|
||||||
|
txc = UniqueTxidsInReverse(txc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
txm, err := w.getAddressTxids(address, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
txm = UniqueTxidsInReverse(txm)
|
||||||
|
bestheight, _, err := w.db.GetBestBlock()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// paging
|
||||||
|
if page < 0 {
|
||||||
|
page = 0
|
||||||
|
}
|
||||||
|
from := page * txsOnPage
|
||||||
|
totalPages := len(txc) / txsOnPage
|
||||||
|
if from >= len(txc) {
|
||||||
|
page = totalPages - 1
|
||||||
|
if page < 0 {
|
||||||
|
page = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
from = page * txsOnPage
|
||||||
|
to := (page + 1) * txsOnPage
|
||||||
|
if to > len(txc) {
|
||||||
|
to = len(txc)
|
||||||
|
}
|
||||||
|
txs := make([]*Tx, len(txm)+to-from)
|
||||||
|
txi := 0
|
||||||
|
// load mempool transactions
|
||||||
|
var uBalSat big.Int
|
||||||
|
for _, tx := range txm {
|
||||||
|
tx, err := w.GetTransaction(tx, bestheight, false)
|
||||||
|
// mempool transaction may fail
|
||||||
|
if err != nil {
|
||||||
|
glog.Error("GetTransaction ", tx, ": ", err)
|
||||||
|
} else {
|
||||||
|
uBalSat.Sub(tx.getAddrVoutValue(address), tx.getAddrVinValue(address))
|
||||||
|
txs[txi] = tx
|
||||||
|
txi++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(txc) != int(ba.Txs) {
|
||||||
|
glog.Warning("DB inconsistency in address ", address, ": number of txs from column addresses ", len(txc), ", from addressBalance ", ba.Txs)
|
||||||
|
}
|
||||||
|
|
||||||
|
r := &Address{
|
||||||
|
AddrStr: address,
|
||||||
|
Balance: w.chainParser.AmountToDecimalString(&ba.BalanceSat),
|
||||||
|
TotalReceived: w.chainParser.AmountToDecimalString(ba.ReceivedSat()),
|
||||||
|
TotalSent: w.chainParser.AmountToDecimalString(&ba.SentSat),
|
||||||
|
TxApperances: len(txc),
|
||||||
|
UnconfirmedBalance: w.chainParser.AmountToDecimalString(&uBalSat),
|
||||||
|
UnconfirmedTxApperances: len(txm),
|
||||||
|
Page: page,
|
||||||
|
TotalPages: totalPages,
|
||||||
|
TxsOnPage: txsOnPage,
|
||||||
|
}
|
||||||
|
glog.Info(address, " finished")
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAddress computes address value and gets transactions for given address
|
||||||
|
func (w *Worker) GetAddress(addrID string, page int, txsOnPage int) (*Address, error) {
|
||||||
glog.Info(addrID, " start")
|
glog.Info(addrID, " start")
|
||||||
txc, err := w.getAddressTxids(addrID, false)
|
txc, err := w.getAddressTxids(addrID, false)
|
||||||
txc = UniqueTxidsInReverse(txc)
|
txc = UniqueTxidsInReverse(txc)
|
||||||
|
|||||||
@ -545,10 +545,10 @@ type AddrBalance struct {
|
|||||||
BalanceSat big.Int
|
BalanceSat big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ab *AddrBalance) ReceivedSat() big.Int {
|
func (ab *AddrBalance) ReceivedSat() *big.Int {
|
||||||
var r big.Int
|
var r big.Int
|
||||||
r.Add(&ab.BalanceSat, &ab.SentSat)
|
r.Add(&ab.BalanceSat, &ab.SentSat)
|
||||||
return r
|
return &r
|
||||||
}
|
}
|
||||||
|
|
||||||
type blockTxs struct {
|
type blockTxs struct {
|
||||||
|
|||||||
@ -18,8 +18,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const blockbookAbout = "Blockbook - blockchain indexer for TREZOR wallet https://trezor.io/. Do not use for any other purpose."
|
const blockbookAbout = "Blockbook - blockchain indexer for TREZOR wallet https://trezor.io/. Do not use for any other purpose."
|
||||||
|
const txsOnPage = 30
|
||||||
|
const txsInAPI = 1000
|
||||||
|
|
||||||
// PublicServer is handle to public http server
|
// PublicServer is a handle to public http server
|
||||||
type PublicServer struct {
|
type PublicServer struct {
|
||||||
binding string
|
binding string
|
||||||
certFiles string
|
certFiles string
|
||||||
@ -37,7 +39,7 @@ type PublicServer struct {
|
|||||||
addressTpl *template.Template
|
addressTpl *template.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPublicServerS creates new public server http interface to blockbook and returns its handle
|
// NewPublicServer creates new public server http interface to blockbook and returns its handle
|
||||||
func NewPublicServer(binding string, certFiles string, db *db.RocksDB, chain bchain.BlockChain, txCache *db.TxCache, explorerURL string, metrics *common.Metrics, is *common.InternalState) (*PublicServer, error) {
|
func NewPublicServer(binding string, certFiles string, db *db.RocksDB, chain bchain.BlockChain, txCache *db.TxCache, explorerURL string, metrics *common.Metrics, is *common.InternalState) (*PublicServer, error) {
|
||||||
|
|
||||||
api, err := api.NewWorker(db, chain, txCache, is)
|
api, err := api.NewWorker(db, chain, txCache, is)
|
||||||
@ -233,9 +235,10 @@ func (s *PublicServer) explorerAddress(w http.ResponseWriter, r *http.Request) {
|
|||||||
page = 0
|
page = 0
|
||||||
}
|
}
|
||||||
addrID := r.URL.Path[i+1:]
|
addrID := r.URL.Path[i+1:]
|
||||||
address, err = s.api.GetAddress(addrID, page)
|
address, err = s.api.GetAddress(addrID, page, txsOnPage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Error(err)
|
glog.Error(err)
|
||||||
|
// TODO return error.html
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
@ -351,7 +354,7 @@ func (s *PublicServer) apiAddress(w http.ResponseWriter, r *http.Request) {
|
|||||||
page = 0
|
page = 0
|
||||||
}
|
}
|
||||||
addrID := r.URL.Path[i+1:]
|
addrID := r.URL.Path[i+1:]
|
||||||
address, err = s.api.GetAddress(addrID, page)
|
address, err = s.api.GetAddress(addrID, page, txsInAPI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Error(err)
|
glog.Error(err)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user