Add explorer api worker
This commit is contained in:
parent
278b18a37f
commit
604b41f10a
49
api/types.go
Normal file
49
api/types.go
Normal file
@ -0,0 +1,49 @@
|
||||
package api
|
||||
|
||||
type ScriptSig struct {
|
||||
Hex string `json:"hex"`
|
||||
Asm string `json:"asm,omitempty"`
|
||||
}
|
||||
|
||||
type Vin struct {
|
||||
Txid string `json:"txid"`
|
||||
Vout uint32 `json:"vout"`
|
||||
Sequence int64 `json:"sequence,omitempty"`
|
||||
N int `json:"n"`
|
||||
ScriptSig ScriptSig `json:"scriptSig"`
|
||||
Addr string `json:"addr"`
|
||||
ValueSat int64 `json:"valueSat"`
|
||||
Value float64 `json:"value"`
|
||||
}
|
||||
|
||||
type ScriptPubKey struct {
|
||||
Hex string `json:"hex"`
|
||||
Asm string `json:"asm,omitempty"`
|
||||
Addresses []string `json:"addresses"`
|
||||
Type string `json:"type,omitempty"`
|
||||
}
|
||||
type Vout struct {
|
||||
Value float64 `json:"value"`
|
||||
N int `json:"n"`
|
||||
ScriptPubKey ScriptPubKey `json:"scriptPubKey"`
|
||||
SpentTxID string `json:"spentTxId,omitempty"`
|
||||
SpentIndex int `json:"spentIndex,omitempty"`
|
||||
SpentHeight int `json:"spentHeight,omitempty"`
|
||||
}
|
||||
|
||||
type Tx struct {
|
||||
Txid string `json:"txid"`
|
||||
Version int32 `json:"version,omitempty"`
|
||||
Locktime uint32 `json:"locktime,omitempty"`
|
||||
Vin []Vin `json:"vin"`
|
||||
Vout []Vout `json:"vout"`
|
||||
Blockhash string `json:"blockhash,omitempty"`
|
||||
Blockheight int `json:"blockheight"`
|
||||
Confirmations uint32 `json:"confirmations"`
|
||||
Time int64 `json:"time,omitempty"`
|
||||
Blocktime int64 `json:"blocktime"`
|
||||
ValueOut float64 `json:"valueOut"`
|
||||
Size int `json:"size,omitempty"`
|
||||
ValueIn float64 `json:"valueIn"`
|
||||
Fees float64 `json:"fees"`
|
||||
}
|
||||
95
api/worker.go
Normal file
95
api/worker.go
Normal file
@ -0,0 +1,95 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/db"
|
||||
)
|
||||
|
||||
// Worker is handle to api worker
|
||||
type Worker struct {
|
||||
db *db.RocksDB
|
||||
txCache *db.TxCache
|
||||
chain bchain.BlockChain
|
||||
chainParser bchain.BlockChainParser
|
||||
}
|
||||
|
||||
// NewWorker creates new api worker
|
||||
func NewWorker(db *db.RocksDB, chain bchain.BlockChain, txCache *db.TxCache) (*Worker, error) {
|
||||
w := &Worker{
|
||||
db: db,
|
||||
txCache: txCache,
|
||||
chain: chain,
|
||||
chainParser: chain.GetChainParser(),
|
||||
}
|
||||
return w, nil
|
||||
}
|
||||
|
||||
func (w *Worker) GetTransaction(txid string, bestheight uint32, spendingTx bool) (*Tx, error) {
|
||||
bchainTx, height, err := w.txCache.GetTransaction(txid, bestheight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var blockhash string
|
||||
if bchainTx.Confirmations > 0 {
|
||||
blockhash, err = w.db.GetBlockHash(height)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var valIn, valOut, fees float64
|
||||
vins := make([]Vin, len(bchainTx.Vin))
|
||||
for i := range bchainTx.Vin {
|
||||
bchainVin := &bchainTx.Vin[i]
|
||||
vin := &vins[i]
|
||||
vin.Txid = bchainVin.Txid
|
||||
vin.N = i
|
||||
vin.Vout = bchainVin.Vout
|
||||
vin.ScriptSig.Hex = bchainVin.ScriptSig.Hex
|
||||
otx, _, err := w.txCache.GetTransaction(bchainVin.Txid, bestheight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(otx.Vout) > int(vin.Vout) {
|
||||
vout := &otx.Vout[vin.Vout]
|
||||
vin.Value = vout.Value
|
||||
valIn += vout.Value
|
||||
vin.ValueSat = int64(vout.Value*1E8 + 0.5)
|
||||
if vout.Address != nil {
|
||||
a := vout.Address.String()
|
||||
vin.Addr = a
|
||||
}
|
||||
}
|
||||
}
|
||||
vouts := make([]Vout, len(bchainTx.Vout))
|
||||
for i := range bchainTx.Vout {
|
||||
bchainVout := &bchainTx.Vout[i]
|
||||
vout := &vouts[i]
|
||||
vout.N = i
|
||||
vout.Value = bchainVout.Value
|
||||
valOut += bchainVout.Value
|
||||
vout.ScriptPubKey.Hex = bchainVout.ScriptPubKey.Hex
|
||||
vout.ScriptPubKey.Addresses = bchainVout.ScriptPubKey.Addresses
|
||||
if spendingTx {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
// for now do not return size, we would have to compute vsize of segwit transactions
|
||||
// size:=len(bchainTx.Hex) / 2
|
||||
fees = valIn - valOut
|
||||
r := &Tx{
|
||||
Blockhash: blockhash,
|
||||
Blockheight: int(height),
|
||||
Blocktime: bchainTx.Blocktime,
|
||||
Confirmations: bchainTx.Confirmations,
|
||||
Fees: fees,
|
||||
Locktime: bchainTx.LockTime,
|
||||
Time: bchainTx.Time,
|
||||
Txid: txid,
|
||||
ValueIn: valIn,
|
||||
ValueOut: valOut,
|
||||
Version: bchainTx.Version,
|
||||
Vin: vins,
|
||||
Vout: vouts,
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
@ -58,9 +58,9 @@ type Vout struct {
|
||||
// Tx is blockchain transaction
|
||||
// unnecessary fields are commented out to avoid overhead
|
||||
type Tx struct {
|
||||
Hex string `json:"hex"`
|
||||
Txid string `json:"txid"`
|
||||
// Version int32 `json:"version"`
|
||||
Hex string `json:"hex"`
|
||||
Txid string `json:"txid"`
|
||||
Version int32 `json:"version"`
|
||||
LockTime uint32 `json:"locktime"`
|
||||
Vin []Vin `json:"vin"`
|
||||
Vout []Vout `json:"vout"`
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"blockbook/api"
|
||||
"blockbook/bchain"
|
||||
"blockbook/common"
|
||||
"blockbook/db"
|
||||
@ -27,6 +28,7 @@ type PublicServer struct {
|
||||
txCache *db.TxCache
|
||||
chain bchain.BlockChain
|
||||
chainParser bchain.BlockChainParser
|
||||
api *api.Worker
|
||||
explorerURL string
|
||||
metrics *common.Metrics
|
||||
is *common.InternalState
|
||||
@ -35,6 +37,11 @@ type PublicServer struct {
|
||||
// NewPublicServerS 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) {
|
||||
|
||||
api, err := api.NewWorker(db, chain, txCache)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
socketio, err := NewSocketIoServer(db, chain, txCache, metrics, is)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -51,6 +58,7 @@ func NewPublicServer(binding string, certFiles string, db *db.RocksDB, chain bch
|
||||
binding: binding,
|
||||
certFiles: certFiles,
|
||||
https: https,
|
||||
api: api,
|
||||
socketio: socketio,
|
||||
db: db,
|
||||
txCache: txCache,
|
||||
@ -66,6 +74,8 @@ func NewPublicServer(binding string, certFiles string, db *db.RocksDB, chain bch
|
||||
// redirect to Bitcore for details of transaction
|
||||
serveMux.HandleFunc(path+"tx/", s.txRedirect)
|
||||
serveMux.HandleFunc(path+"address/", s.addressRedirect)
|
||||
// explorer
|
||||
serveMux.HandleFunc(path+"explorer/tx/", s.explorerTx)
|
||||
// API call used to detect state of Blockbook
|
||||
serveMux.HandleFunc(path+"api/block-index/", s.apiBlockIndex)
|
||||
// handle socket.io
|
||||
@ -139,6 +149,25 @@ func (s *PublicServer) addressRedirect(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *PublicServer) explorerTx(w http.ResponseWriter, r *http.Request) {
|
||||
var tx *api.Tx
|
||||
var err error
|
||||
if i := strings.LastIndexByte(r.URL.Path, '/'); i > 0 {
|
||||
txid := r.URL.Path[i+1:]
|
||||
bestheight, _, err := s.db.GetBestBlock()
|
||||
if err == nil {
|
||||
tx, err = s.api.GetTransaction(txid, bestheight, true)
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
buf, err := json.MarshalIndent(tx, "", " ")
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
w.Write(buf)
|
||||
}
|
||||
}
|
||||
|
||||
type resAboutBlockbookPublic struct {
|
||||
Coin string `json:"coin"`
|
||||
Host string `json:"host"`
|
||||
|
||||
@ -598,7 +598,7 @@ func (s *SocketIoServer) getDetailedTransaction(txid string) (res resultGetDetai
|
||||
return res, err
|
||||
}
|
||||
if len(otx.Vout) > int(vin.Vout) {
|
||||
vout := otx.Vout[vin.Vout]
|
||||
vout := &otx.Vout[vin.Vout]
|
||||
if vout.Address != nil {
|
||||
a := vout.Address.String()
|
||||
ai.Address = &a
|
||||
|
||||
Loading…
Reference in New Issue
Block a user