Merge branch 'master' into indexv2
This commit is contained in:
commit
9017d1bffd
8
Gopkg.lock
generated
8
Gopkg.lock
generated
@ -31,6 +31,12 @@
|
|||||||
packages = [".","base58","bech32"]
|
packages = [".","base58","bech32"]
|
||||||
revision = "501929d3d046174c3d39f0ea54ece471aa17238c"
|
revision = "501929d3d046174c3d39f0ea54ece471aa17238c"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/cpacia/bchutil"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "12e86f41eb040d3b85b5d8e3a3a4bed035517c52"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/ethereum/go-ethereum"
|
name = "github.com/ethereum/go-ethereum"
|
||||||
packages = [".","common","common/hexutil","common/math","core/types","crypto","crypto/secp256k1","crypto/sha3","ethclient","ethdb","log","metrics","params","rlp","rpc","trie"]
|
packages = [".","common","common/hexutil","common/math","core/types","crypto","crypto/secp256k1","crypto/sha3","ethclient","ethdb","log","metrics","params","rlp","rpc","trie"]
|
||||||
@ -184,6 +190,6 @@
|
|||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "a463c234bc11d9917876a827f692392845ed89571edc1484ae3e932f555d484b"
|
inputs-digest = "e632a1e904953397e9eae00f30a86bffab2d303232c7bac47a16e1ce663043bf"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|||||||
@ -72,3 +72,7 @@
|
|||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/golang/protobuf"
|
name = "github.com/golang/protobuf"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/cpacia/bchutil"
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package bchain
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
@ -157,6 +158,9 @@ func (p *BaseParser) UnpackTx(buf []byte) (*Tx, uint32, error) {
|
|||||||
},
|
},
|
||||||
Value: pto.Value,
|
Value: pto.Value,
|
||||||
}
|
}
|
||||||
|
if len(pto.Addresses) == 1 {
|
||||||
|
vout[i].Address = NewBaseAddress(pto.Addresses[0])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tx := Tx{
|
tx := Tx{
|
||||||
Blocktime: int64(pt.Blocktime),
|
Blocktime: int64(pt.Blocktime),
|
||||||
@ -169,3 +173,43 @@ func (p *BaseParser) UnpackTx(buf []byte) (*Tx, uint32, error) {
|
|||||||
}
|
}
|
||||||
return &tx, pt.Height, nil
|
return &tx, pt.Height, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type baseAddress struct {
|
||||||
|
addr string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBaseAddress(addr string) Address {
|
||||||
|
return &baseAddress{addr: addr}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a baseAddress) String() string {
|
||||||
|
return a.addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a baseAddress) EncodeAddress(format AddressFormat) (string, error) {
|
||||||
|
if format != DefaultAddress {
|
||||||
|
return "", fmt.Errorf("Unknown address format: %d", format)
|
||||||
|
}
|
||||||
|
return a.addr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a baseAddress) AreEqual(addr string) (bool, error) {
|
||||||
|
ea, err := a.EncodeAddress(0)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return ea == addr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a baseAddress) InSlice(addrs []string) (bool, error) {
|
||||||
|
for _, addr := range addrs {
|
||||||
|
eq, err := a.AreEqual(addr)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if eq {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|||||||
165
bchain/coins/bch/bcashparser.go
Normal file
165
bchain/coins/bch/bcashparser.go
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
package bch
|
||||||
|
|
||||||
|
import (
|
||||||
|
"blockbook/bchain"
|
||||||
|
"blockbook/bchain/coins/btc"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
|
"github.com/btcsuite/btcd/txscript"
|
||||||
|
"github.com/btcsuite/btcutil"
|
||||||
|
"github.com/cpacia/bchutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
var prefixes = []string{"bitcoincash", "bchtest", "bchreg"}
|
||||||
|
|
||||||
|
// BCashParser handle
|
||||||
|
type BCashParser struct {
|
||||||
|
*btc.BitcoinParser
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetChainParams contains network parameters for the main Bitcoin Cash network,
|
||||||
|
// the regression test Bitcoin Cash network, the test Bitcoin Cash network and
|
||||||
|
// the simulation test Bitcoin Cash network, in this order
|
||||||
|
func GetChainParams(chain string) *chaincfg.Params {
|
||||||
|
var params *chaincfg.Params
|
||||||
|
switch chain {
|
||||||
|
case "test":
|
||||||
|
params = &chaincfg.TestNet3Params
|
||||||
|
params.Net = bchutil.TestnetMagic
|
||||||
|
case "regtest":
|
||||||
|
params = &chaincfg.RegressionNetParams
|
||||||
|
params.Net = bchutil.Regtestmagic
|
||||||
|
default:
|
||||||
|
params = &chaincfg.MainNetParams
|
||||||
|
params.Net = bchutil.MainnetMagic
|
||||||
|
}
|
||||||
|
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAddrIDFromAddress returns internal address representation of given address
|
||||||
|
func (p *BCashParser) GetAddrIDFromAddress(address string) ([]byte, error) {
|
||||||
|
return p.AddressToOutputScript(address)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddressToOutputScript converts bitcoin address to ScriptPubKey
|
||||||
|
func (p *BCashParser) AddressToOutputScript(address string) ([]byte, error) {
|
||||||
|
if isCashAddr(address) {
|
||||||
|
da, err := bchutil.DecodeAddress(address, p.Params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
script, err := bchutil.PayToAddrScript(da)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return script, nil
|
||||||
|
} else {
|
||||||
|
da, err := btcutil.DecodeAddress(address, p.Params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
script, err := txscript.PayToAddrScript(da)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return script, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isCashAddr(addr string) bool {
|
||||||
|
slice := strings.Split(addr, ":")
|
||||||
|
if len(slice) != 2 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, prefix := range prefixes {
|
||||||
|
if slice[0] == prefix {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *BCashParser) UnpackTx(buf []byte) (tx *bchain.Tx, height uint32, err error) {
|
||||||
|
tx, height, err = p.BitcoinParser.UnpackTx(buf)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, vout := range tx.Vout {
|
||||||
|
if len(vout.ScriptPubKey.Addresses) == 1 {
|
||||||
|
tx.Vout[i].Address = &bcashAddress{
|
||||||
|
addr: vout.ScriptPubKey.Addresses[0],
|
||||||
|
net: p.Params,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type bcashAddress struct {
|
||||||
|
addr string
|
||||||
|
net *chaincfg.Params
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *bcashAddress) String() string {
|
||||||
|
return a.addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *bcashAddress) EncodeAddress(format bchain.AddressFormat) (string, error) {
|
||||||
|
switch format {
|
||||||
|
case bchain.DefaultAddress:
|
||||||
|
return a.String(), nil
|
||||||
|
case bchain.BCashAddress:
|
||||||
|
da, err := btcutil.DecodeAddress(a.addr, a.net)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var ca btcutil.Address
|
||||||
|
switch da := da.(type) {
|
||||||
|
case *btcutil.AddressPubKeyHash:
|
||||||
|
ca, err = bchutil.NewCashAddressPubKeyHash(da.Hash160()[:], a.net)
|
||||||
|
case *btcutil.AddressScriptHash:
|
||||||
|
ca, err = bchutil.NewCashAddressScriptHash(da.Hash160()[:], a.net)
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("Unknown address type: %T", da)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return ca.String(), nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("Unknown address format: %d", format)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *bcashAddress) AreEqual(addr string) (bool, error) {
|
||||||
|
var format bchain.AddressFormat
|
||||||
|
if isCashAddr(addr) {
|
||||||
|
format = bchain.BCashAddress
|
||||||
|
} else {
|
||||||
|
format = bchain.DefaultAddress
|
||||||
|
}
|
||||||
|
ea, err := a.EncodeAddress(format)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return ea == addr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *bcashAddress) InSlice(addrs []string) (bool, error) {
|
||||||
|
for _, addr := range addrs {
|
||||||
|
eq, err := a.AreEqual(addr)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if eq {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
216
bchain/coins/bch/bcashrpc.go
Normal file
216
bchain/coins/bch/bcashrpc.go
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
package bch
|
||||||
|
|
||||||
|
import (
|
||||||
|
"blockbook/bchain"
|
||||||
|
"blockbook/bchain/coins/btc"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/cpacia/bchutil"
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/juju/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BCashRPC is an interface to JSON-RPC bitcoind service.
|
||||||
|
type BCashRPC struct {
|
||||||
|
*btc.BitcoinRPC
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBCashRPC returns new BCashRPC instance.
|
||||||
|
func NewBCashRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) {
|
||||||
|
b, err := btc.NewBitcoinRPC(config, pushHandler)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s := &BCashRPC{
|
||||||
|
b.(*btc.BitcoinRPC),
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BCashRPC) Initialize() error {
|
||||||
|
b.Mempool = bchain.NewUTXOMempool(b)
|
||||||
|
|
||||||
|
chainName, err := b.GetBlockChainInfo()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
params := GetChainParams(chainName)
|
||||||
|
|
||||||
|
// always create parser
|
||||||
|
b.Parser = &BCashParser{
|
||||||
|
&btc.BitcoinParser{
|
||||||
|
Params: params,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// parameters for getInfo request
|
||||||
|
if params.Net == bchutil.MainnetMagic {
|
||||||
|
b.Testnet = false
|
||||||
|
b.Network = "livenet"
|
||||||
|
} else {
|
||||||
|
b.Testnet = true
|
||||||
|
b.Network = "testnet"
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.Info("rpc: block chain ", params.Name)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getblock
|
||||||
|
|
||||||
|
type cmdGetBlock struct {
|
||||||
|
Method string `json:"method"`
|
||||||
|
Params struct {
|
||||||
|
BlockHash string `json:"blockhash"`
|
||||||
|
Verbose bool `json:"verbose"`
|
||||||
|
} `json:"params"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type resGetBlockRaw struct {
|
||||||
|
Error *bchain.RPCError `json:"error"`
|
||||||
|
Result string `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type resGetBlockThin struct {
|
||||||
|
Error *bchain.RPCError `json:"error"`
|
||||||
|
Result bchain.ThinBlock `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// estimatesmartfee
|
||||||
|
|
||||||
|
type cmdEstimateSmartFee struct {
|
||||||
|
Method string `json:"method"`
|
||||||
|
Params struct {
|
||||||
|
Blocks int `json:"nblocks"`
|
||||||
|
} `json:"params"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type resEstimateSmartFee struct {
|
||||||
|
Error *bchain.RPCError `json:"error"`
|
||||||
|
Result struct {
|
||||||
|
Feerate float64 `json:"feerate"`
|
||||||
|
Blocks int `json:"blocks"`
|
||||||
|
} `json:"result"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBlock returns block with given hash.
|
||||||
|
func (b *BCashRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) {
|
||||||
|
var err error
|
||||||
|
if hash == "" && height > 0 {
|
||||||
|
hash, err = b.GetBlockHash(height)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// XXX
|
||||||
|
// // optimization
|
||||||
|
// if height > 0 {
|
||||||
|
// return b.getBlockWithoutHeader(hash, height)
|
||||||
|
// }
|
||||||
|
header, err := b.GetBlockHeader(hash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
data, err := b.GetBlockRaw(hash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
block, err := b.Parser.ParseBlock(data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Annotatef(err, "hash %v", hash)
|
||||||
|
}
|
||||||
|
block.BlockHeader = *header
|
||||||
|
return block, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBlockRaw returns block with given hash as bytes.
|
||||||
|
func (b *BCashRPC) GetBlockRaw(hash string) ([]byte, error) {
|
||||||
|
glog.V(1).Info("rpc: getblock (verbose=0) ", hash)
|
||||||
|
|
||||||
|
res := resGetBlockRaw{}
|
||||||
|
req := cmdGetBlock{Method: "getblock"}
|
||||||
|
req.Params.BlockHash = hash
|
||||||
|
req.Params.Verbose = false
|
||||||
|
err := b.Call(&req, &res)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Annotatef(err, "hash %v", hash)
|
||||||
|
}
|
||||||
|
if res.Error != nil {
|
||||||
|
if isErrBlockNotFound(res.Error) {
|
||||||
|
return nil, bchain.ErrBlockNotFound
|
||||||
|
}
|
||||||
|
return nil, errors.Annotatef(res.Error, "hash %v", hash)
|
||||||
|
}
|
||||||
|
return hex.DecodeString(res.Result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBlockList returns block with given hash by downloading block
|
||||||
|
// transactions one by one.
|
||||||
|
func (b *BCashRPC) GetBlockList(hash string) (*bchain.Block, error) {
|
||||||
|
glog.V(1).Info("rpc: getblock (verbose=1) ", hash)
|
||||||
|
|
||||||
|
res := resGetBlockThin{}
|
||||||
|
req := cmdGetBlock{Method: "getblock"}
|
||||||
|
req.Params.BlockHash = hash
|
||||||
|
req.Params.Verbose = true
|
||||||
|
err := b.Call(&req, &res)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Annotatef(err, "hash %v", hash)
|
||||||
|
}
|
||||||
|
if res.Error != nil {
|
||||||
|
if isErrBlockNotFound(res.Error) {
|
||||||
|
return nil, bchain.ErrBlockNotFound
|
||||||
|
}
|
||||||
|
return nil, errors.Annotatef(res.Error, "hash %v", hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
txs := make([]bchain.Tx, len(res.Result.Txids))
|
||||||
|
for i, txid := range res.Result.Txids {
|
||||||
|
tx, err := b.GetTransaction(txid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
txs[i] = *tx
|
||||||
|
}
|
||||||
|
block := &bchain.Block{
|
||||||
|
BlockHeader: res.Result.BlockHeader,
|
||||||
|
Txs: txs,
|
||||||
|
}
|
||||||
|
return block, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBlockFull returns block with given hash.
|
||||||
|
func (b *BCashRPC) GetBlockFull(hash string) (*bchain.Block, error) {
|
||||||
|
return nil, errors.New("Not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// EstimateSmartFee returns fee estimation.
|
||||||
|
func (b *BCashRPC) EstimateSmartFee(blocks int, conservative bool) (float64, error) {
|
||||||
|
glog.V(1).Info("rpc: estimatesmartfee ", blocks)
|
||||||
|
|
||||||
|
res := resEstimateSmartFee{}
|
||||||
|
req := cmdEstimateSmartFee{Method: "estimatesmartfee"}
|
||||||
|
req.Params.Blocks = blocks
|
||||||
|
// conservative param is omitted
|
||||||
|
err := b.Call(&req, &res)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
if res.Error != nil {
|
||||||
|
return 0, res.Error
|
||||||
|
}
|
||||||
|
return res.Result.Feerate, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isErrBlockNotFound(err *bchain.RPCError) bool {
|
||||||
|
return err.Message == "Block not found" ||
|
||||||
|
err.Message == "Block height out of range"
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ package coins
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
"blockbook/bchain"
|
||||||
|
"blockbook/bchain/coins/bch"
|
||||||
"blockbook/bchain/coins/btc"
|
"blockbook/bchain/coins/btc"
|
||||||
"blockbook/bchain/coins/eth"
|
"blockbook/bchain/coins/eth"
|
||||||
"blockbook/bchain/coins/zec"
|
"blockbook/bchain/coins/zec"
|
||||||
@ -25,6 +26,8 @@ func init() {
|
|||||||
blockChainFactories["zec"] = zec.NewZCashRPC
|
blockChainFactories["zec"] = zec.NewZCashRPC
|
||||||
blockChainFactories["eth"] = eth.NewEthereumRPC
|
blockChainFactories["eth"] = eth.NewEthereumRPC
|
||||||
blockChainFactories["eth-testnet"] = eth.NewEthereumRPC
|
blockChainFactories["eth-testnet"] = eth.NewEthereumRPC
|
||||||
|
blockChainFactories["bch"] = bch.NewBCashRPC
|
||||||
|
blockChainFactories["bch-testnet"] = bch.NewBCashRPC
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockChain creates bchain.BlockChain of type defined by parameter coin
|
// NewBlockChain creates bchain.BlockChain of type defined by parameter coin
|
||||||
|
|||||||
@ -169,5 +169,12 @@ func (p *BitcoinParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
|
|||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
tx.Blocktime = bt
|
tx.Blocktime = bt
|
||||||
|
|
||||||
|
for i, vout := range tx.Vout {
|
||||||
|
if len(vout.ScriptPubKey.Addresses) == 1 {
|
||||||
|
tx.Vout[i].Address = bchain.NewBaseAddress(vout.ScriptPubKey.Addresses[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return tx, height, nil
|
return tx, height, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,10 +40,25 @@ type ScriptPubKey struct {
|
|||||||
Addresses []string `json:"addresses,omitempty"`
|
Addresses []string `json:"addresses,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AddressFormat = uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultAddress AddressFormat = iota
|
||||||
|
BCashAddress
|
||||||
|
)
|
||||||
|
|
||||||
|
type Address interface {
|
||||||
|
String() string
|
||||||
|
EncodeAddress(format AddressFormat) (string, error)
|
||||||
|
AreEqual(addr string) (bool, error)
|
||||||
|
InSlice(addrs []string) (bool, error)
|
||||||
|
}
|
||||||
|
|
||||||
type Vout struct {
|
type Vout struct {
|
||||||
Value float64 `json:"value"`
|
Value float64 `json:"value"`
|
||||||
N uint32 `json:"n"`
|
N uint32 `json:"n"`
|
||||||
ScriptPubKey ScriptPubKey `json:"scriptPubKey"`
|
ScriptPubKey ScriptPubKey `json:"scriptPubKey"`
|
||||||
|
Address Address
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tx is blockchain transaction
|
// Tx is blockchain transaction
|
||||||
|
|||||||
@ -9,10 +9,12 @@ build-debug: prepare-sources
|
|||||||
chown $(PACKAGER) /out/blockbook
|
chown $(PACKAGER) /out/blockbook
|
||||||
|
|
||||||
test: prepare-sources
|
test: prepare-sources
|
||||||
cd $(GOPATH)/src/blockbook && go test -short ./...
|
#cd $(GOPATH)/src/blockbook && go test -short ./... # FIXME
|
||||||
|
cd $(GOPATH)/src/blockbook && go test -short ./bchain/coins/btc ./bchain/coins/bch ./bchain/coins/eth ./bchain/coins/zec
|
||||||
|
|
||||||
test-all: prepare-sources
|
test-all: prepare-sources
|
||||||
cd $(GOPATH)/src/blockbook && go test ./...
|
# cd $(GOPATH)/src/blockbook && go test ./... # FIXME
|
||||||
|
cd $(GOPATH)/src/blockbook && go test ./bchain/coins/btc ./bchain/coins/bch ./bchain/coins/eth ./bchain/coins/zec
|
||||||
|
|
||||||
prepare-sources:
|
prepare-sources:
|
||||||
@ [ -n "`ls /src 2> /dev/null`" ] || (echo "/src doesn't exist or is empty" 1>&2 && exit 1)
|
@ [ -n "`ls /src 2> /dev/null`" ] || (echo "/src doesn't exist or is empty" 1>&2 && exit 1)
|
||||||
|
|||||||
@ -3,7 +3,8 @@ set -e
|
|||||||
|
|
||||||
cp -r /src/build/deb/debian .
|
cp -r /src/build/deb/debian .
|
||||||
cp -r /src/configs .
|
cp -r /src/configs .
|
||||||
mkdir server && cp -r /src/server/testcert.* /src/server/static server
|
cp -r /src/static static
|
||||||
|
mkdir cert && cp /src/server/testcert.* cert
|
||||||
|
|
||||||
dpkg-buildpackage -us -uc
|
dpkg-buildpackage -us -uc
|
||||||
mv ../*.deb /out
|
mv ../*.deb /out
|
||||||
|
|||||||
1
build/deb/debian/blockbook-bch-testnet.conffiles
Normal file
1
build/deb/debian/blockbook-bch-testnet.conffiles
Normal file
@ -0,0 +1 @@
|
|||||||
|
/opt/blockbook/bch-testnet/config/blockchaincfg.json
|
||||||
2
build/deb/debian/blockbook-bch-testnet.cron.daily
Normal file
2
build/deb/debian/blockbook-bch-testnet.cron.daily
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
find /opt/blockbook/bch-testnet/logs -mtime +6 -type f -delete
|
||||||
2
build/deb/debian/blockbook-bch-testnet.dirs
Normal file
2
build/deb/debian/blockbook-bch-testnet.dirs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/data/bch-testnet/blockbook
|
||||||
|
/opt/blockbook/bch-testnet/logs
|
||||||
5
build/deb/debian/blockbook-bch-testnet.install
Executable file
5
build/deb/debian/blockbook-bch-testnet.install
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/dh-exec
|
||||||
|
blockbook /opt/blockbook/bch-testnet/bin
|
||||||
|
cert /opt/blockbook/bch-testnet
|
||||||
|
static /opt/blockbook/bch-testnet
|
||||||
|
configs/bch-testnet.json => /opt/blockbook/bch-testnet/config/blockchaincfg.json
|
||||||
2
build/deb/debian/blockbook-bch-testnet.links
Normal file
2
build/deb/debian/blockbook-bch-testnet.links
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/opt/blockbook/bch-testnet/cert/testcert.crt /opt/blockbook/bch-testnet/cert/blockbook.crt
|
||||||
|
/opt/blockbook/bch-testnet/cert/testcert.key /opt/blockbook/bch-testnet/cert/blockbook.key
|
||||||
23
build/deb/debian/blockbook-bch-testnet.postinst
Normal file
23
build/deb/debian/blockbook-bch-testnet.postinst
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
|
||||||
|
configure)
|
||||||
|
if ! id -u blockbook &> /dev/null
|
||||||
|
then
|
||||||
|
useradd --system -M -U blockbook
|
||||||
|
fi
|
||||||
|
|
||||||
|
for dir in /data/bch-testnet/blockbook /opt/blockbook/bch-testnet/logs
|
||||||
|
do
|
||||||
|
if [ "$(stat -c '%U' $dir)" != "blockbook" ]
|
||||||
|
then
|
||||||
|
chown -R blockbook:blockbook $dir
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
|
||||||
|
#DEBHELPER#
|
||||||
39
build/deb/debian/blockbook-bch-testnet.service
Normal file
39
build/deb/debian/blockbook-bch-testnet.service
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# It is not recommended to modify this file in-place, because it will
|
||||||
|
# be overwritten during package upgrades. If you want to add further
|
||||||
|
# options or overwrite existing ones then use
|
||||||
|
# $ systemctl edit blockbook-bch-testnet.service
|
||||||
|
# See "man systemd.service" for details.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Blockbook daemon (BCH testnet)
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/opt/blockbook/bch-testnet/bin/blockbook -coin=bch-testnet -blockchaincfg=/opt/blockbook/bch-testnet/config/blockchaincfg.json -datadir=/data/bch-testnet/blockbook/db -sync -httpserver=:18435 -socketio=:18436 -certfile=/opt/blockbook/bch-testnet/cert/blockbook -explorer=https://bch-bitcore1.trezor.io/ -log_dir=/opt/blockbook/bch-testnet/logs
|
||||||
|
User=blockbook
|
||||||
|
Type=simple
|
||||||
|
Restart=on-failure
|
||||||
|
WorkingDirectory=/opt/blockbook/bch-testnet
|
||||||
|
|
||||||
|
# Hardening measures
|
||||||
|
####################
|
||||||
|
|
||||||
|
# Provide a private /tmp and /var/tmp.
|
||||||
|
PrivateTmp=true
|
||||||
|
|
||||||
|
# Mount /usr, /boot/ and /etc read-only for the process.
|
||||||
|
ProtectSystem=full
|
||||||
|
|
||||||
|
# Disallow the process and all of its children to gain
|
||||||
|
# new privileges through execve().
|
||||||
|
NoNewPrivileges=true
|
||||||
|
|
||||||
|
# Use a new /dev namespace only populated with API pseudo devices
|
||||||
|
# such as /dev/null, /dev/zero and /dev/random.
|
||||||
|
PrivateDevices=true
|
||||||
|
|
||||||
|
# Deny the creation of writable and executable memory mappings.
|
||||||
|
MemoryDenyWriteExecute=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
1
build/deb/debian/blockbook-bch.conffiles
Normal file
1
build/deb/debian/blockbook-bch.conffiles
Normal file
@ -0,0 +1 @@
|
|||||||
|
/opt/blockbook/bch/config/blockchaincfg.json
|
||||||
2
build/deb/debian/blockbook-bch.cron.daily
Normal file
2
build/deb/debian/blockbook-bch.cron.daily
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
find /opt/blockbook/bch/logs -mtime +6 -type f -delete
|
||||||
2
build/deb/debian/blockbook-bch.dirs
Normal file
2
build/deb/debian/blockbook-bch.dirs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/data/bch/blockbook
|
||||||
|
/opt/blockbook/bch/logs
|
||||||
5
build/deb/debian/blockbook-bch.install
Executable file
5
build/deb/debian/blockbook-bch.install
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/dh-exec
|
||||||
|
blockbook /opt/blockbook/bch/bin
|
||||||
|
cert /opt/blockbook/bch
|
||||||
|
static /opt/blockbook/bch
|
||||||
|
configs/bch.json => /opt/blockbook/bch/config/blockchaincfg.json
|
||||||
2
build/deb/debian/blockbook-bch.links
Normal file
2
build/deb/debian/blockbook-bch.links
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/opt/blockbook/bch/cert/testcert.crt /opt/blockbook/bch/cert/blockbook.crt
|
||||||
|
/opt/blockbook/bch/cert/testcert.key /opt/blockbook/bch/cert/blockbook.key
|
||||||
23
build/deb/debian/blockbook-bch.postinst
Normal file
23
build/deb/debian/blockbook-bch.postinst
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
|
||||||
|
configure)
|
||||||
|
if ! id -u blockbook &> /dev/null
|
||||||
|
then
|
||||||
|
useradd --system -M -U blockbook
|
||||||
|
fi
|
||||||
|
|
||||||
|
for dir in /data/bch/blockbook /opt/blockbook/bch/logs
|
||||||
|
do
|
||||||
|
if [ "$(stat -c '%U' $dir)" != "blockbook" ]
|
||||||
|
then
|
||||||
|
chown -R blockbook:blockbook $dir
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
|
||||||
|
#DEBHELPER#
|
||||||
39
build/deb/debian/blockbook-bch.service
Normal file
39
build/deb/debian/blockbook-bch.service
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# It is not recommended to modify this file in-place, because it will
|
||||||
|
# be overwritten during package upgrades. If you want to add further
|
||||||
|
# options or overwrite existing ones then use
|
||||||
|
# $ systemctl edit blockbook-bch.service
|
||||||
|
# See "man systemd.service" for details.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Blockbook daemon (BCH mainnet)
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/opt/blockbook/bch/bin/blockbook -coin=bch -blockchaincfg=/opt/blockbook/bch/config/blockchaincfg.json -datadir=/data/bch/blockbook/db -sync -httpserver=:8435 -socketio=:8436 -certfile=/opt/blockbook/bch/cert/blockbook -explorer=https://bitcore1.trezor.io/ -log_dir=/opt/blockbook/bch/logs
|
||||||
|
User=blockbook
|
||||||
|
Type=simple
|
||||||
|
Restart=on-failure
|
||||||
|
WorkingDirectory=/opt/blockbook/bch
|
||||||
|
|
||||||
|
# Hardening measures
|
||||||
|
####################
|
||||||
|
|
||||||
|
# Provide a private /tmp and /var/tmp.
|
||||||
|
PrivateTmp=true
|
||||||
|
|
||||||
|
# Mount /usr, /boot/ and /etc read-only for the process.
|
||||||
|
ProtectSystem=full
|
||||||
|
|
||||||
|
# Disallow the process and all of its children to gain
|
||||||
|
# new privileges through execve().
|
||||||
|
NoNewPrivileges=true
|
||||||
|
|
||||||
|
# Use a new /dev namespace only populated with API pseudo devices
|
||||||
|
# such as /dev/null, /dev/zero and /dev/random.
|
||||||
|
PrivateDevices=true
|
||||||
|
|
||||||
|
# Deny the creation of writable and executable memory mappings.
|
||||||
|
MemoryDenyWriteExecute=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/dh-exec
|
#!/usr/bin/dh-exec
|
||||||
blockbook /opt/blockbook/btc-testnet/bin
|
blockbook /opt/blockbook/btc-testnet/bin
|
||||||
server/testcert.* /opt/blockbook/btc-testnet/cert
|
cert /opt/blockbook/btc-testnet
|
||||||
server/static /opt/blockbook/btc-testnet
|
static /opt/blockbook/btc-testnet
|
||||||
configs/btc-testnet.json => /opt/blockbook/btc-testnet/config/blockchaincfg.json
|
configs/btc-testnet.json => /opt/blockbook/btc-testnet/config/blockchaincfg.json
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/dh-exec
|
#!/usr/bin/dh-exec
|
||||||
blockbook /opt/blockbook/btc/bin
|
blockbook /opt/blockbook/btc/bin
|
||||||
server/testcert.* /opt/blockbook/btc/cert
|
cert /opt/blockbook/btc
|
||||||
server/static /opt/blockbook/btc
|
static /opt/blockbook/btc
|
||||||
configs/btc.json => /opt/blockbook/btc/config/blockchaincfg.json
|
configs/btc.json => /opt/blockbook/btc/config/blockchaincfg.json
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/dh-exec --with=install
|
#!/usr/bin/dh-exec --with=install
|
||||||
blockbook /opt/blockbook/zec/bin
|
blockbook /opt/blockbook/zec/bin
|
||||||
server/testcert.* /opt/blockbook/zec/cert
|
cert /opt/blockbook/zec
|
||||||
server/static /opt/blockbook/zec
|
static /opt/blockbook/zec
|
||||||
configs/zec.json => /opt/blockbook/zec/config/blockchaincfg.json
|
configs/zec.json => /opt/blockbook/zec/config/blockchaincfg.json
|
||||||
|
|||||||
@ -8,14 +8,24 @@ Standards-Version: 3.9.5
|
|||||||
Package: blockbook-btc
|
Package: blockbook-btc
|
||||||
Architecture: amd64
|
Architecture: amd64
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, coreutils, passwd, findutils
|
Depends: ${shlibs:Depends}, ${misc:Depends}, coreutils, passwd, findutils
|
||||||
Description: Satoshilabs blockbook server
|
Description: Satoshilabs blockbook server (Bitcoin mainnet)
|
||||||
|
|
||||||
Package: blockbook-btc-testnet
|
Package: blockbook-btc-testnet
|
||||||
Architecture: amd64
|
Architecture: amd64
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, coreutils, passwd, findutils
|
Depends: ${shlibs:Depends}, ${misc:Depends}, coreutils, passwd, findutils
|
||||||
Description: Satoshilabs blockbook server
|
Description: Satoshilabs blockbook server (Bitcoin testnet)
|
||||||
|
|
||||||
Package: blockbook-zec
|
Package: blockbook-zec
|
||||||
Architecture: amd64
|
Architecture: amd64
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}, coreutils, passwd, findutils
|
Depends: ${shlibs:Depends}, ${misc:Depends}, coreutils, passwd, findutils
|
||||||
Description: Satoshilabs blockbook server
|
Description: Satoshilabs blockbook server (ZCash mainnet)
|
||||||
|
|
||||||
|
Package: blockbook-bch
|
||||||
|
Architecture: amd64
|
||||||
|
Depends: ${shlibs:Depends}, ${misc:Depends}, coreutils, passwd, findutils
|
||||||
|
Description: Satoshilabs blockbook server (Bitcoin Cash mainnet)
|
||||||
|
|
||||||
|
Package: blockbook-bch-testnet
|
||||||
|
Architecture: amd64
|
||||||
|
Depends: ${shlibs:Depends}, ${misc:Depends}, coreutils, passwd, findutils
|
||||||
|
Description: Satoshilabs blockbook server (Bitcoin Cash testnet)
|
||||||
|
|||||||
8
configs/bch-testnet.json
Normal file
8
configs/bch-testnet.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"rpcURL": "http://localhost:18432",
|
||||||
|
"rpcUser": "rpc",
|
||||||
|
"rpcPass": "rpc",
|
||||||
|
"rpcTimeout": 25,
|
||||||
|
"parse": true,
|
||||||
|
"zeroMQBinding": "tcp://127.0.0.1:18434"
|
||||||
|
}
|
||||||
8
configs/bch.json
Normal file
8
configs/bch.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"rpcURL": "http://127.0.0.1:8432",
|
||||||
|
"rpcUser": "rpc",
|
||||||
|
"rpcPass": "rpc",
|
||||||
|
"rpcTimeout": 25,
|
||||||
|
"parse": true,
|
||||||
|
"zeroMQBinding": "tcp://127.0.0.1:8434"
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
TARGETS = bitcoin zcash
|
TARGETS = bitcoin zcash bcash
|
||||||
IMAGE = blockbook-backend-build-deb
|
IMAGE = blockbook-backend-build-deb
|
||||||
NO_CACHE = false
|
NO_CACHE = false
|
||||||
|
|
||||||
|
|||||||
14
contrib/backends/bcash/Makefile
Normal file
14
contrib/backends/bcash/Makefile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
BITCOINABC_VERSION := 0.17.0
|
||||||
|
|
||||||
|
all:
|
||||||
|
wget https://download.bitcoinabc.org/0.17.0/linux/bitcoin-abc-${BITCOINABC_VERSION}-x86_64-linux-gnu.tar.gz
|
||||||
|
tar -xf bitcoin-abc-${BITCOINABC_VERSION}-x86_64-linux-gnu.tar.gz
|
||||||
|
mv bitcoin-abc-${BITCOINABC_VERSION} bitcoin-abc
|
||||||
|
rm bitcoin-abc/bin/bitcoin-qt
|
||||||
|
rm bitcoin-abc/bin/bitcoin-tx
|
||||||
|
rm bitcoin-abc/bin/bitcoin-seeder
|
||||||
|
rm bitcoin-abc/bin/test_bitcoin
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf bitcoin-abc
|
||||||
|
rm -f bitcoin-abc-${BITCOINABC_VERSION}-x86_64-linux-gnu.tar.gz*
|
||||||
13
contrib/backends/bcash/bch-testnet.conf
Normal file
13
contrib/backends/bcash/bch-testnet.conf
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
daemon=1
|
||||||
|
server=1
|
||||||
|
testnet=1
|
||||||
|
nolisten=1
|
||||||
|
rpcuser=rpc
|
||||||
|
rpcpassword=rpc
|
||||||
|
rpcport=18432
|
||||||
|
txindex=1
|
||||||
|
rpcworkqueue=32
|
||||||
|
zmqpubhashtx=tcp://127.0.0.1:18434
|
||||||
|
zmqpubhashblock=tcp://127.0.0.1:18434
|
||||||
|
zmqpubrawblock=tcp://127.0.0.1:18434
|
||||||
|
zmqpubrawtx=tcp://127.0.0.1:18434
|
||||||
12
contrib/backends/bcash/bch.conf
Normal file
12
contrib/backends/bcash/bch.conf
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
daemon=1
|
||||||
|
server=1
|
||||||
|
nolisten=1
|
||||||
|
rpcuser=rpc
|
||||||
|
rpcpassword=rpc
|
||||||
|
rpcport=8432
|
||||||
|
txindex=1
|
||||||
|
rpcworkqueue=32
|
||||||
|
zmqpubhashtx=tcp://127.0.0.1:8434
|
||||||
|
zmqpubhashblock=tcp://127.0.0.1:8434
|
||||||
|
zmqpubrawblock=tcp://127.0.0.1:8434
|
||||||
|
zmqpubrawtx=tcp://127.0.0.1:8434
|
||||||
1
contrib/backends/bcash/debian/bcash-bch.conffiles
Normal file
1
contrib/backends/bcash/debian/bcash-bch.conffiles
Normal file
@ -0,0 +1 @@
|
|||||||
|
/opt/bitcoin/bch/bch.conf
|
||||||
1
contrib/backends/bcash/debian/bcash-bch.dirs
Normal file
1
contrib/backends/bcash/debian/bcash-bch.dirs
Normal file
@ -0,0 +1 @@
|
|||||||
|
/data/bch/bitcoin
|
||||||
2
contrib/backends/bcash/debian/bcash-bch.install
Normal file
2
contrib/backends/bcash/debian/bcash-bch.install
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
bitcoin-abc/* /opt/bitcoin/bch
|
||||||
|
bch.conf /opt/bitcoin/bch
|
||||||
10
contrib/backends/bcash/debian/bcash-bch.logrotate
Normal file
10
contrib/backends/bcash/debian/bcash-bch.logrotate
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/data/bch/bitcoin/debug.log
|
||||||
|
/data/bch/bitcoin/db.log
|
||||||
|
{
|
||||||
|
rotate 7
|
||||||
|
daily
|
||||||
|
compress
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
copytruncate
|
||||||
|
}
|
||||||
20
contrib/backends/bcash/debian/bcash-bch.postinst
Normal file
20
contrib/backends/bcash/debian/bcash-bch.postinst
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
|
||||||
|
configure)
|
||||||
|
if ! id -u bitcoin &> /dev/null
|
||||||
|
then
|
||||||
|
useradd --system -M -U bitcoin
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$(stat -c '%U' /data/bch/bitcoin)" != "bitcoin" ]
|
||||||
|
then
|
||||||
|
chown bitcoin:bitcoin /data/bch/bitcoin
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
|
||||||
|
#DEBHELPER#
|
||||||
44
contrib/backends/bcash/debian/bcash-bch.service
Normal file
44
contrib/backends/bcash/debian/bcash-bch.service
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# It is not recommended to modify this file in-place, because it will
|
||||||
|
# be overwritten during package upgrades. If you want to add further
|
||||||
|
# options or overwrite existing ones then use
|
||||||
|
# $ systemctl edit bcash-bch.service
|
||||||
|
# See "man systemd.service" for details.
|
||||||
|
|
||||||
|
# Note that almost all daemon options could be specified in
|
||||||
|
# /opt/bitcoin/bch/bch.conf
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Bitcoin Cash daemon (mainnet)
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/opt/bitcoin/bch/bin/bitcoind -datadir=/data/bch/bitcoin -conf=/opt/bitcoin/bch/bch.conf -pid=/run/bitcoind/bch.pid
|
||||||
|
# Creates /run/bitcoind owned by bitcoin
|
||||||
|
RuntimeDirectory=bitcoind
|
||||||
|
User=bitcoin
|
||||||
|
Type=forking
|
||||||
|
PIDFile=/run/bitcoind/bch.pid
|
||||||
|
Restart=on-failure
|
||||||
|
|
||||||
|
# Hardening measures
|
||||||
|
####################
|
||||||
|
|
||||||
|
# Provide a private /tmp and /var/tmp.
|
||||||
|
PrivateTmp=true
|
||||||
|
|
||||||
|
# Mount /usr, /boot/ and /etc read-only for the process.
|
||||||
|
ProtectSystem=full
|
||||||
|
|
||||||
|
# Disallow the process and all of its children to gain
|
||||||
|
# new privileges through execve().
|
||||||
|
NoNewPrivileges=true
|
||||||
|
|
||||||
|
# Use a new /dev namespace only populated with API pseudo devices
|
||||||
|
# such as /dev/null, /dev/zero and /dev/random.
|
||||||
|
PrivateDevices=true
|
||||||
|
|
||||||
|
# Deny the creation of writable and executable memory mappings.
|
||||||
|
MemoryDenyWriteExecute=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
1
contrib/backends/bcash/debian/bcash-testnet.conffiles
Normal file
1
contrib/backends/bcash/debian/bcash-testnet.conffiles
Normal file
@ -0,0 +1 @@
|
|||||||
|
/opt/bitcoin/bch-testnet/bch-testnet.conf
|
||||||
1
contrib/backends/bcash/debian/bcash-testnet.dirs
Normal file
1
contrib/backends/bcash/debian/bcash-testnet.dirs
Normal file
@ -0,0 +1 @@
|
|||||||
|
/data/bch-testnet/bitcoin
|
||||||
2
contrib/backends/bcash/debian/bcash-testnet.install
Normal file
2
contrib/backends/bcash/debian/bcash-testnet.install
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
bitcoin-abc/* /opt/bitcoin/bch-testnet
|
||||||
|
bch-testnet.conf /opt/bitcoin/bch-testnet
|
||||||
10
contrib/backends/bcash/debian/bcash-testnet.logrotate
Normal file
10
contrib/backends/bcash/debian/bcash-testnet.logrotate
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/data/bch-testnet/bitcoin/testnet3/debug.log
|
||||||
|
/data/bch-testnet/bitcoin/testnet3/db.log
|
||||||
|
{
|
||||||
|
rotate 7
|
||||||
|
daily
|
||||||
|
compress
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
copytruncate
|
||||||
|
}
|
||||||
20
contrib/backends/bcash/debian/bcash-testnet.postinst
Normal file
20
contrib/backends/bcash/debian/bcash-testnet.postinst
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
|
||||||
|
configure)
|
||||||
|
if ! id -u bitcoin &> /dev/null
|
||||||
|
then
|
||||||
|
useradd --system -M -U bitcoin
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$(stat -c '%U' /data/bch-testnet/bitcoin)" != "bitcoin" ]
|
||||||
|
then
|
||||||
|
chown bitcoin:bitcoin /data/bch-testnet/bitcoin
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
esac
|
||||||
|
|
||||||
|
#DEBHELPER#
|
||||||
44
contrib/backends/bcash/debian/bcash-testnet.service
Normal file
44
contrib/backends/bcash/debian/bcash-testnet.service
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# It is not recommended to modify this file in-place, because it will
|
||||||
|
# be overwritten during package upgrades. If you want to add further
|
||||||
|
# options or overwrite existing ones then use
|
||||||
|
# $ systemctl edit bcash-testnet.service
|
||||||
|
# See "man systemd.service" for details.
|
||||||
|
|
||||||
|
# Note that almost all daemon options could be specified in
|
||||||
|
# /opt/bitcoin/bch-testnet/bch-testnet.conf
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Bitcoin Cash daemon (testnet)
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/opt/bitcoin/bch-testnet/bin/bitcoind -datadir=/data/bch-testnet/bitcoin -conf=/opt/bitcoin/bch-testnet/bch-testnet.conf -pid=/run/bitcoind/bch-testnet.pid
|
||||||
|
# Creates /run/bitcoind owned by bitcoin
|
||||||
|
RuntimeDirectory=bitcoind
|
||||||
|
User=bitcoin
|
||||||
|
Type=forking
|
||||||
|
PIDFile=/run/bitcoind/bch-testnet.pid
|
||||||
|
Restart=on-failure
|
||||||
|
|
||||||
|
# Hardening measures
|
||||||
|
####################
|
||||||
|
|
||||||
|
# Provide a private /tmp and /var/tmp.
|
||||||
|
PrivateTmp=true
|
||||||
|
|
||||||
|
# Mount /usr, /boot/ and /etc read-only for the process.
|
||||||
|
ProtectSystem=full
|
||||||
|
|
||||||
|
# Disallow the process and all of its children to gain
|
||||||
|
# new privileges through execve().
|
||||||
|
NoNewPrivileges=true
|
||||||
|
|
||||||
|
# Use a new /dev namespace only populated with API pseudo devices
|
||||||
|
# such as /dev/null, /dev/zero and /dev/random.
|
||||||
|
PrivateDevices=true
|
||||||
|
|
||||||
|
# Deny the creation of writable and executable memory mappings.
|
||||||
|
MemoryDenyWriteExecute=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
5
contrib/backends/bcash/debian/changelog
Normal file
5
contrib/backends/bcash/debian/changelog
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
bcash (0.17.0-satoshilabs1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Initial build
|
||||||
|
|
||||||
|
-- Jakub Matys <jakub.matys@satoshilabs.com> Fri, 13 Apr 2018 11:31:01 +0200
|
||||||
1
contrib/backends/bcash/debian/compat
Normal file
1
contrib/backends/bcash/debian/compat
Normal file
@ -0,0 +1 @@
|
|||||||
|
9
|
||||||
16
contrib/backends/bcash/debian/control
Normal file
16
contrib/backends/bcash/debian/control
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
Source: bcash
|
||||||
|
Section: satoshilabs
|
||||||
|
Priority: optional
|
||||||
|
Maintainer: jakub.matys@satoshilabs.com
|
||||||
|
Build-Depends: debhelper, wget, tar, gzip, make, dh-systemd, dh-exec
|
||||||
|
Standards-Version: 3.9.5
|
||||||
|
|
||||||
|
Package: bcash-bch
|
||||||
|
Architecture: amd64
|
||||||
|
Depends: ${shlibs:Depends}, ${misc:Depends}, logrotate
|
||||||
|
Description: Satoshilabs packaged bitcoin-cash server
|
||||||
|
|
||||||
|
Package: bcash-testnet
|
||||||
|
Architecture: amd64
|
||||||
|
Depends: ${shlibs:Depends}, ${misc:Depends}, logrotate
|
||||||
|
Description: Satoshilabs packaged bitcoin-cash server
|
||||||
6
contrib/backends/bcash/debian/rules
Executable file
6
contrib/backends/bcash/debian/rules
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
|
||||||
|
DH_VERBOSE = 1
|
||||||
|
|
||||||
|
%:
|
||||||
|
dh $@ --with=systemd
|
||||||
@ -124,27 +124,32 @@ func (s *SocketIoServer) txRedirect(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type reqRange struct {
|
type addrOpts struct {
|
||||||
Start int `json:"start"`
|
Start int `json:"start"`
|
||||||
End int `json:"end"`
|
End int `json:"end"`
|
||||||
QueryMempol bool `json:"queryMempol"`
|
QueryMempol bool `json:"queryMempol"`
|
||||||
QueryMempoolOnly bool `json:"queryMempoolOnly"`
|
QueryMempoolOnly bool `json:"queryMempoolOnly"`
|
||||||
From int `json:"from"`
|
From int `json:"from"`
|
||||||
To int `json:"to"`
|
To int `json:"to"`
|
||||||
|
AddressFormat uint8 `json:"addressFormat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type txOpts struct {
|
||||||
|
AddressFormat uint8 `json:"addressFormat"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var onMessageHandlers = map[string]func(*SocketIoServer, json.RawMessage) (interface{}, error){
|
var onMessageHandlers = map[string]func(*SocketIoServer, json.RawMessage) (interface{}, error){
|
||||||
"getAddressTxids": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
|
"getAddressTxids": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
|
||||||
addr, rr, err := unmarshalGetAddressRequest(params)
|
addr, opts, err := unmarshalGetAddressRequest(params)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rv, err = s.getAddressTxids(addr, &rr)
|
rv, err = s.getAddressTxids(addr, &opts)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
},
|
},
|
||||||
"getAddressHistory": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
|
"getAddressHistory": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
|
||||||
addr, rr, err := unmarshalGetAddressRequest(params)
|
addr, opts, err := unmarshalGetAddressRequest(params)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rv, err = s.getAddressHistory(addr, &rr)
|
rv, err = s.getAddressHistory(addr, &opts)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
},
|
},
|
||||||
@ -173,9 +178,9 @@ var onMessageHandlers = map[string]func(*SocketIoServer, json.RawMessage) (inter
|
|||||||
return s.getInfo()
|
return s.getInfo()
|
||||||
},
|
},
|
||||||
"getDetailedTransaction": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
|
"getDetailedTransaction": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
|
||||||
txid, err := unmarshalStringParameter(params)
|
txid, opts, err := unmarshalGetDetailedTransaction(params)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rv, err = s.getDetailedTransaction(txid)
|
rv, err = s.getDetailedTransaction(txid, opts)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
},
|
},
|
||||||
@ -226,7 +231,7 @@ func (s *SocketIoServer) onMessage(c *gosocketio.Channel, req map[string]json.Ra
|
|||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalGetAddressRequest(params []byte) (addr []string, rr reqRange, err error) {
|
func unmarshalGetAddressRequest(params []byte) (addr []string, opts addrOpts, err error) {
|
||||||
var p []json.RawMessage
|
var p []json.RawMessage
|
||||||
err = json.Unmarshal(params, &p)
|
err = json.Unmarshal(params, &p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -240,7 +245,7 @@ func unmarshalGetAddressRequest(params []byte) (addr []string, rr reqRange, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = json.Unmarshal(p[1], &rr)
|
err = json.Unmarshal(p[1], &opts)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,14 +266,14 @@ type resultAddressTxids struct {
|
|||||||
Result []string `json:"result"`
|
Result []string `json:"result"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SocketIoServer) getAddressTxids(addr []string, rr *reqRange) (res resultAddressTxids, err error) {
|
func (s *SocketIoServer) getAddressTxids(addr []string, opts *addrOpts) (res resultAddressTxids, err error) {
|
||||||
txids := make([]string, 0)
|
txids := make([]string, 0)
|
||||||
lower, higher := uint32(rr.To), uint32(rr.Start)
|
lower, higher := uint32(opts.To), uint32(opts.Start)
|
||||||
for _, address := range addr {
|
for _, address := range addr {
|
||||||
if !rr.QueryMempoolOnly {
|
if !opts.QueryMempoolOnly {
|
||||||
err = s.db.GetTransactions(address, lower, higher, func(txid string, vout uint32, isOutput bool) error {
|
err = s.db.GetTransactions(address, lower, higher, func(txid string, vout uint32, isOutput bool) error {
|
||||||
txids = append(txids, txid)
|
txids = append(txids, txid)
|
||||||
if isOutput && rr.QueryMempol {
|
if isOutput && opts.QueryMempol {
|
||||||
input := s.chain.GetMempoolSpentOutput(txid, vout)
|
input := s.chain.GetMempoolSpentOutput(txid, vout)
|
||||||
if input != "" {
|
if input != "" {
|
||||||
txids = append(txids, txid)
|
txids = append(txids, txid)
|
||||||
@ -280,7 +285,7 @@ func (s *SocketIoServer) getAddressTxids(addr []string, rr *reqRange) (res resul
|
|||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if rr.QueryMempoolOnly || rr.QueryMempol {
|
if opts.QueryMempoolOnly || opts.QueryMempol {
|
||||||
mtxids, err := s.chain.GetMempoolTransactions(address)
|
mtxids, err := s.chain.GetMempoolTransactions(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
@ -375,8 +380,8 @@ func txToResTx(tx *bchain.Tx, height int, hi []txInputs, ho []txOutputs) resTx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SocketIoServer) getAddressHistory(addr []string, rr *reqRange) (res resultGetAddressHistory, err error) {
|
func (s *SocketIoServer) getAddressHistory(addr []string, opts *addrOpts) (res resultGetAddressHistory, err error) {
|
||||||
txr, err := s.getAddressTxids(addr, rr)
|
txr, err := s.getAddressTxids(addr, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -388,7 +393,7 @@ func (s *SocketIoServer) getAddressHistory(addr []string, rr *reqRange) (res res
|
|||||||
res.Result.TotalCount = len(txids)
|
res.Result.TotalCount = len(txids)
|
||||||
res.Result.Items = make([]addressHistoryItem, 0)
|
res.Result.Items = make([]addressHistoryItem, 0)
|
||||||
for i, txid := range txids {
|
for i, txid := range txids {
|
||||||
if i >= rr.From && i < rr.To {
|
if i >= opts.From && i < opts.To {
|
||||||
tx, height, err := s.txCache.GetTransaction(txid, bestheight)
|
tx, height, err := s.txCache.GetTransaction(txid, bestheight)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
@ -402,10 +407,17 @@ func (s *SocketIoServer) getAddressHistory(addr []string, rr *reqRange) (res res
|
|||||||
Script: &vout.ScriptPubKey.Hex,
|
Script: &vout.ScriptPubKey.Hex,
|
||||||
SpentIndex: int(vout.N),
|
SpentIndex: int(vout.N),
|
||||||
}
|
}
|
||||||
if len(vout.ScriptPubKey.Addresses) == 1 {
|
if vout.Address != nil {
|
||||||
a := vout.ScriptPubKey.Addresses[0]
|
a, err := vout.Address.EncodeAddress(opts.AddressFormat)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
ao.Address = &a
|
ao.Address = &a
|
||||||
if stringInSlice(a, addr) {
|
found, err := vout.Address.InSlice(addr)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if found {
|
||||||
hi, ok := ads[a]
|
hi, ok := ads[a]
|
||||||
if ok {
|
if ok {
|
||||||
hi.OutputIndexes = append(hi.OutputIndexes, int(vout.N))
|
hi.OutputIndexes = append(hi.OutputIndexes, int(vout.N))
|
||||||
@ -603,11 +615,31 @@ func unmarshalStringParameter(params []byte) (s string, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unmarshalGetDetailedTransaction(params []byte) (txid string, opts txOpts, err error) {
|
||||||
|
var p []json.RawMessage
|
||||||
|
err = json.Unmarshal(params, &p)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(p) < 1 || len(p) > 2 {
|
||||||
|
err = errors.New("incorrect number of parameters")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(p[0], &txid)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(p) > 1 {
|
||||||
|
err = json.Unmarshal(p[1], &opts)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type resultGetDetailedTransaction struct {
|
type resultGetDetailedTransaction struct {
|
||||||
Result resTx `json:"result"`
|
Result resTx `json:"result"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SocketIoServer) getDetailedTransaction(txid string) (res resultGetDetailedTransaction, err error) {
|
func (s *SocketIoServer) getDetailedTransaction(txid string, opts txOpts) (res resultGetDetailedTransaction, err error) {
|
||||||
bestheight, _, err := s.db.GetBestBlock()
|
bestheight, _, err := s.db.GetBestBlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -631,8 +663,12 @@ func (s *SocketIoServer) getDetailedTransaction(txid string) (res resultGetDetai
|
|||||||
}
|
}
|
||||||
if len(otx.Vout) > int(vin.Vout) {
|
if len(otx.Vout) > int(vin.Vout) {
|
||||||
vout := otx.Vout[vin.Vout]
|
vout := otx.Vout[vin.Vout]
|
||||||
if len(vout.ScriptPubKey.Addresses) == 1 {
|
if vout.Address != nil {
|
||||||
ai.Address = &vout.ScriptPubKey.Addresses[0]
|
a, err := vout.Address.EncodeAddress(opts.AddressFormat)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
ai.Address = &a
|
||||||
}
|
}
|
||||||
ai.Satoshis = int64(vout.Value * 1E8)
|
ai.Satoshis = int64(vout.Value * 1E8)
|
||||||
}
|
}
|
||||||
@ -645,8 +681,12 @@ func (s *SocketIoServer) getDetailedTransaction(txid string) (res resultGetDetai
|
|||||||
Script: &vout.ScriptPubKey.Hex,
|
Script: &vout.ScriptPubKey.Hex,
|
||||||
SpentIndex: int(vout.N),
|
SpentIndex: int(vout.N),
|
||||||
}
|
}
|
||||||
if len(vout.ScriptPubKey.Addresses) == 1 {
|
if vout.Address != nil {
|
||||||
ao.Address = &vout.ScriptPubKey.Addresses[0]
|
a, err := vout.Address.EncodeAddress(opts.AddressFormat)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
ao.Address = &a
|
||||||
}
|
}
|
||||||
ho = append(ho, ao)
|
ho = append(ho, ao)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,16 +56,17 @@
|
|||||||
var addresses = document.getElementById('getAddressHistoryAddresses').value.split(",");
|
var addresses = document.getElementById('getAddressHistoryAddresses').value.split(",");
|
||||||
addresses = addresses.map(s => s.trim());
|
addresses = addresses.map(s => s.trim());
|
||||||
var mempool = document.getElementById("getAddressHistoryMempool").checked;
|
var mempool = document.getElementById("getAddressHistoryMempool").checked;
|
||||||
lookupAddressHistories(addresses, 0, 5, mempool, 20000000, 0, function (result) {
|
var format = document.getElementById("getAddressHistoryFormat").value;
|
||||||
|
lookupAddressHistories(addresses, 0, 5, mempool, 20000000, 0, format, function (result) {
|
||||||
console.log('getAddressHistory sent successfully');
|
console.log('getAddressHistory sent successfully');
|
||||||
console.log(result);
|
console.log(result);
|
||||||
document.getElementById('getAddressHistoryResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
|
document.getElementById('getAddressHistoryResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function lookupAddressHistories(addresses, from, to, mempool, start, end, f) {
|
function lookupAddressHistories(addresses, from, to, mempool, start, end, format, f) {
|
||||||
const method = 'getAddressHistory';
|
const method = 'getAddressHistory';
|
||||||
const rangeParam = mempool ? {
|
const opts = mempool ? {
|
||||||
start, // needed for older bitcores (so we don't load all history if bitcore-node < 3.1.3)
|
start, // needed for older bitcores (so we don't load all history if bitcore-node < 3.1.3)
|
||||||
end,
|
end,
|
||||||
queryMempoolOnly: true,
|
queryMempoolOnly: true,
|
||||||
@ -77,9 +78,10 @@
|
|||||||
const params = [
|
const params = [
|
||||||
addresses,
|
addresses,
|
||||||
{
|
{
|
||||||
...rangeParam,
|
...opts,
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
|
addressFormat: parseInt(format),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
return socket.send({ method, params }, f);
|
return socket.send({ method, params }, f);
|
||||||
@ -87,7 +89,7 @@
|
|||||||
|
|
||||||
function lookupTransactionsIdsMempool(addresses, mempool, start, end, f) {
|
function lookupTransactionsIdsMempool(addresses, mempool, start, end, f) {
|
||||||
const method = 'getAddressTxids';
|
const method = 'getAddressTxids';
|
||||||
const rangeParam = mempool ? {
|
const opts = mempool ? {
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
queryMempoolOnly: true,
|
queryMempoolOnly: true,
|
||||||
@ -98,7 +100,7 @@
|
|||||||
};
|
};
|
||||||
const params = [
|
const params = [
|
||||||
addresses,
|
addresses,
|
||||||
rangeParam,
|
opts,
|
||||||
];
|
];
|
||||||
return socket.send({ method, params }, f);
|
return socket.send({ method, params }, f);
|
||||||
}
|
}
|
||||||
@ -139,6 +141,21 @@
|
|||||||
return socket.send({ method, params }, f);
|
return socket.send({ method, params }, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function estimateFee() {
|
||||||
|
var blocks = document.getElementById('estimateFeeBlocks').value.trim();
|
||||||
|
estimateTxFee(parseInt(blocks), function (result) {
|
||||||
|
console.log('estimateFee sent successfully');
|
||||||
|
console.log(result);
|
||||||
|
document.getElementById('estimateFeeResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function estimateTxFee(blocks, f) {
|
||||||
|
const method = 'estimateFee';
|
||||||
|
const params = [blocks];
|
||||||
|
return socket.send({ method, params }, f);
|
||||||
|
}
|
||||||
|
|
||||||
function getInfo() {
|
function getInfo() {
|
||||||
lookupSyncStatus(function (result) {
|
lookupSyncStatus(function (result) {
|
||||||
console.log('getInfo sent successfully');
|
console.log('getInfo sent successfully');
|
||||||
@ -155,17 +172,21 @@
|
|||||||
|
|
||||||
function getDetailedTransaction() {
|
function getDetailedTransaction() {
|
||||||
var hash = document.getElementById('getDetailedTransactionHash').value.trim();
|
var hash = document.getElementById('getDetailedTransactionHash').value.trim();
|
||||||
lookupDetailedTransaction(hash, function (result) {
|
var format = document.getElementById("getDetailedTransactionFormat").value;
|
||||||
|
lookupDetailedTransaction(hash, format, function (result) {
|
||||||
console.log('getDetailedTransaction sent successfully');
|
console.log('getDetailedTransaction sent successfully');
|
||||||
console.log(result);
|
console.log(result);
|
||||||
document.getElementById('getDetailedTransactionResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
|
document.getElementById('getDetailedTransactionResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function lookupDetailedTransaction(hash, f) {
|
function lookupDetailedTransaction(hash, format, f) {
|
||||||
const method = 'getDetailedTransaction';
|
const method = 'getDetailedTransaction';
|
||||||
const params = [
|
const params = [
|
||||||
hash,
|
hash,
|
||||||
|
{
|
||||||
|
addressFormat: parseInt(format),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
return socket.send({ method, params }, f);
|
return socket.send({ method, params }, f);
|
||||||
}
|
}
|
||||||
@ -275,6 +296,14 @@
|
|||||||
<input type="checkbox" id="getAddressHistoryMempool">
|
<input type="checkbox" id="getAddressHistoryMempool">
|
||||||
<label>only mempool</label>
|
<label>only mempool</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-9"></div>
|
||||||
|
<div class="col form-inline">
|
||||||
|
<label>address format</label>
|
||||||
|
<select id="getAddressHistoryFormat" value="0">
|
||||||
|
<option value="0">default</option>
|
||||||
|
<option value="1">bitcoincash</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col" id="getAddressHistoryResult">
|
<div class="col" id="getAddressHistoryResult">
|
||||||
@ -310,6 +339,19 @@
|
|||||||
<div class="col" id="estimateSmartFeeResult">
|
<div class="col" id="estimateSmartFeeResult">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<input class="btn btn-secondary" type="button" value="estimateFee" onclick="estimateFee()">
|
||||||
|
</div>
|
||||||
|
<div class="col-8">
|
||||||
|
<input type="text" class="form-control" id="estimateFeeBlocks" value="20">
|
||||||
|
</div>
|
||||||
|
<div class="col"></div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col" id="estimateFeeResult">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<input class="btn btn-secondary" type="button" value="getInfo" onclick="getInfo()">
|
<input class="btn btn-secondary" type="button" value="getInfo" onclick="getInfo()">
|
||||||
@ -324,7 +366,14 @@
|
|||||||
<div class="col-8">
|
<div class="col-8">
|
||||||
<input type="text" class="form-control" id="getDetailedTransactionHash" value="474e6795760ebe81cb4023dc227e5a0efe340e1771c89a0035276361ed733de7">
|
<input type="text" class="form-control" id="getDetailedTransactionHash" value="474e6795760ebe81cb4023dc227e5a0efe340e1771c89a0035276361ed733de7">
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col"></div>
|
||||||
|
<div class="col-9"></div>
|
||||||
|
<div class="col form-inline">
|
||||||
|
<label>address format</label>
|
||||||
|
<select id="getDetailedTransactionFormat" value="0">
|
||||||
|
<option value="0">default</option>
|
||||||
|
<option value="1">bitcoincash</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
Loading…
Reference in New Issue
Block a user