Add coinbase flag (boolean) to UTXO response #236
parent
45f5d115d6
commit
39f2c73f3e
|
@ -266,6 +266,7 @@ type Utxo struct {
|
|||
Address string `json:"address,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
Locktime uint32 `json:"lockTime,omitempty"`
|
||||
Coinbase bool `json:"coinbase,omitempty"`
|
||||
}
|
||||
|
||||
// Utxos is array of Utxo
|
||||
|
|
|
@ -843,11 +843,16 @@ func (w *Worker) getAddrDescUtxo(addrDesc bchain.AddressDescriptor, ba *db.AddrB
|
|||
// report only outpoints that are not spent in mempool
|
||||
_, e := spentInMempool[bchainTx.Txid+strconv.Itoa(i)]
|
||||
if !e {
|
||||
coinbase := false
|
||||
if len(bchainTx.Vin) == 1 && len(bchainTx.Vin[0].Coinbase) > 0 {
|
||||
coinbase = true
|
||||
}
|
||||
r = append(r, Utxo{
|
||||
Txid: bchainTx.Txid,
|
||||
Vout: int32(i),
|
||||
AmountSat: (*Amount)(&vout.ValueSat),
|
||||
Locktime: bchainTx.LockTime,
|
||||
Coinbase: coinbase,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -882,12 +887,25 @@ func (w *Worker) getAddrDescUtxo(addrDesc bchain.AddressDescriptor, ba *db.AddrB
|
|||
}
|
||||
_, e := spentInMempool[txid+strconv.Itoa(int(utxo.Vout))]
|
||||
if !e {
|
||||
confirmations := bestheight - int(utxo.Height) + 1
|
||||
coinbase := false
|
||||
// for performance reasons, check coinbase transactions only in minimim confirmantion range
|
||||
if confirmations < w.chainParser.MinimumCoinbaseConfirmations() {
|
||||
ta, err := w.db.GetTxAddresses(txid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ta.Inputs) == 1 && len(ta.Inputs[0].AddrDesc) == 0 && IsZeroBigInt(&ta.Inputs[0].ValueSat) {
|
||||
coinbase = true
|
||||
}
|
||||
}
|
||||
r = append(r, Utxo{
|
||||
Txid: txid,
|
||||
Vout: utxo.Vout,
|
||||
AmountSat: (*Amount)(&utxo.ValueSat),
|
||||
Height: int(utxo.Height),
|
||||
Confirmations: bestheight - int(utxo.Height) + 1,
|
||||
Confirmations: confirmations,
|
||||
Coinbase: coinbase,
|
||||
})
|
||||
}
|
||||
checksum.Sub(&checksum, &utxo.ValueSat)
|
||||
|
|
|
@ -161,6 +161,11 @@ func (p *BaseParser) GetChainType() ChainType {
|
|||
return ChainBitcoinType
|
||||
}
|
||||
|
||||
// MinimumCoinbaseConfirmations returns minimum number of confirmations a coinbase transaction must have before it can be spent
|
||||
func (p *BaseParser) MinimumCoinbaseConfirmations() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// PackTx packs transaction to byte array using protobuf
|
||||
func (p *BaseParser) PackTx(tx *Tx, height uint32, blockTime int64) ([]byte, error) {
|
||||
var err error
|
||||
|
|
|
@ -24,12 +24,13 @@ type OutputScriptToAddressesFunc func(script []byte) ([]string, bool, error)
|
|||
// BitcoinParser handle
|
||||
type BitcoinParser struct {
|
||||
*bchain.BaseParser
|
||||
Params *chaincfg.Params
|
||||
OutputScriptToAddressesFunc OutputScriptToAddressesFunc
|
||||
XPubMagic uint32
|
||||
XPubMagicSegwitP2sh uint32
|
||||
XPubMagicSegwitNative uint32
|
||||
Slip44 uint32
|
||||
Params *chaincfg.Params
|
||||
OutputScriptToAddressesFunc OutputScriptToAddressesFunc
|
||||
XPubMagic uint32
|
||||
XPubMagicSegwitP2sh uint32
|
||||
XPubMagicSegwitNative uint32
|
||||
Slip44 uint32
|
||||
minimumCoinbaseConfirmations int
|
||||
}
|
||||
|
||||
// NewBitcoinParser returns new BitcoinParser instance
|
||||
|
@ -39,11 +40,12 @@ func NewBitcoinParser(params *chaincfg.Params, c *Configuration) *BitcoinParser
|
|||
BlockAddressesToKeep: c.BlockAddressesToKeep,
|
||||
AmountDecimalPoint: 8,
|
||||
},
|
||||
Params: params,
|
||||
XPubMagic: c.XPubMagic,
|
||||
XPubMagicSegwitP2sh: c.XPubMagicSegwitP2sh,
|
||||
XPubMagicSegwitNative: c.XPubMagicSegwitNative,
|
||||
Slip44: c.Slip44,
|
||||
Params: params,
|
||||
XPubMagic: c.XPubMagic,
|
||||
XPubMagicSegwitP2sh: c.XPubMagicSegwitP2sh,
|
||||
XPubMagicSegwitNative: c.XPubMagicSegwitNative,
|
||||
Slip44: c.Slip44,
|
||||
minimumCoinbaseConfirmations: c.MinimumCoinbaseConfirmations,
|
||||
}
|
||||
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses
|
||||
return p
|
||||
|
@ -326,6 +328,11 @@ func (p *BitcoinParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
|
|||
return tx, height, nil
|
||||
}
|
||||
|
||||
// MinimumCoinbaseConfirmations returns minimum number of confirmations a coinbase transaction must have before it can be spent
|
||||
func (p *BitcoinParser) MinimumCoinbaseConfirmations() int {
|
||||
return p.minimumCoinbaseConfirmations
|
||||
}
|
||||
|
||||
func (p *BitcoinParser) addrDescFromExtKey(extKey *hdkeychain.ExtendedKey) (bchain.AddressDescriptor, error) {
|
||||
var a btcutil.Address
|
||||
var err error
|
||||
|
|
|
@ -57,6 +57,7 @@ type Configuration struct {
|
|||
Slip44 uint32 `json:"slip44,omitempty"`
|
||||
AlternativeEstimateFee string `json:"alternativeEstimateFee,omitempty"`
|
||||
AlternativeEstimateFeeParams string `json:"alternativeEstimateFeeParams,omitempty"`
|
||||
MinimumCoinbaseConfirmations int `json:"minimumCoinbaseConfirmations,omitempty"`
|
||||
}
|
||||
|
||||
// NewBitcoinRPC returns new BitcoinRPC instance.
|
||||
|
@ -71,6 +72,10 @@ func NewBitcoinRPC(config json.RawMessage, pushHandler func(bchain.NotificationT
|
|||
if c.BlockAddressesToKeep < 100 {
|
||||
c.BlockAddressesToKeep = 100
|
||||
}
|
||||
// default MinimumCoinbaseConfirmations is 100
|
||||
if c.MinimumCoinbaseConfirmations == 0 {
|
||||
c.MinimumCoinbaseConfirmations = 100
|
||||
}
|
||||
// at least 1 mempool worker/subworker for synchronous mempool synchronization
|
||||
if c.MempoolWorkers < 1 {
|
||||
c.MempoolWorkers = 1
|
||||
|
|
|
@ -254,6 +254,8 @@ type BlockChainParser interface {
|
|||
KeepBlockAddresses() int
|
||||
// AmountDecimals returns number of decimal places in coin amounts
|
||||
AmountDecimals() int
|
||||
// MinimumCoinbaseConfirmations returns minimum number of confirmations a coinbase transaction must have before it can be spent
|
||||
MinimumCoinbaseConfirmations() int
|
||||
// AmountToDecimalString converts amount in big.Int to string with decimal point in the correct place
|
||||
AmountToDecimalString(a *big.Int) string
|
||||
// AmountToBigInt converts amount in json.Number (string) to big.Int
|
||||
|
|
10
docs/api.md
10
docs/api.md
|
@ -407,6 +407,8 @@ Returns array of unspent transaction outputs of address or xpub, applicable only
|
|||
|
||||
Unconfirmed utxos do not have field *height*, the field *confirmations* has value *0* and may contain field *lockTime*, if not zero.
|
||||
|
||||
Coinbase utxos do have field *coinbase* set to true, however due to performance reasons only up to minimum coinbase confirmations limit (100). After this limit, utxos are not detected as coinbase.
|
||||
|
||||
```
|
||||
GET /api/v2/utxo/<address|xpub>[?confirmed=true]
|
||||
```
|
||||
|
@ -422,6 +424,14 @@ Response:
|
|||
"confirmations": 0,
|
||||
"lockTime": 2648100
|
||||
},
|
||||
{
|
||||
"txid": "a79e396a32e10856c97b95f43da7e9d2b9a11d446f7638dbd75e5e7603128cac",
|
||||
"vout": 1,
|
||||
"value": "39748685",
|
||||
"height": 2648043,
|
||||
"confirmations": 47,
|
||||
"coinbase": true
|
||||
},
|
||||
{
|
||||
"txid": "de4f379fdc3ea9be063e60340461a014f372a018d70c3db35701654e7066b3ef",
|
||||
"vout": 0,
|
||||
|
|
Loading…
Reference in New Issue