rpcclient: Merge btcrpcclient repo.
This commit is contained in:
commit
614b799198
25 changed files with 8194 additions and 19 deletions
6
glide.lock
generated
6
glide.lock
generated
|
@ -1,10 +1,8 @@
|
|||
hash: 9e111ebb6989c8b23db0ef5c0523e8dde1ccaa964fa7a42faccbb7a6a60b2860
|
||||
updated: 2017-06-19T16:45:22.5258215-04:00
|
||||
hash: 976decfaf173d97d2e4572399490637aa12e217312a7d8b28813780a738e1151
|
||||
updated: 2017-08-15T20:07:19.2012575-05:00
|
||||
imports:
|
||||
- name: github.com/btcsuite/btclog
|
||||
version: 96c2a91a67da03552a5e6554fe3ccbfbc7f860be
|
||||
- name: github.com/btcsuite/btcrpcclient
|
||||
version: 45b9cb481d2aead4e80aab32d7aa86db386430ab
|
||||
- name: github.com/btcsuite/btcutil
|
||||
version: 501929d3d046174c3d39f0ea54ece471aa17238c
|
||||
subpackages:
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package: github.com/btcsuite/btcd
|
||||
import:
|
||||
- package: github.com/btcsuite/btclog
|
||||
- package: github.com/btcsuite/btcrpcclient
|
||||
- package: github.com/btcsuite/btcutil
|
||||
subpackages:
|
||||
- bloom
|
||||
|
|
|
@ -14,9 +14,9 @@ import (
|
|||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/rpcclient"
|
||||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcrpcclient"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcutil/hdkeychain"
|
||||
)
|
||||
|
@ -102,7 +102,7 @@ type memWallet struct {
|
|||
|
||||
net *chaincfg.Params
|
||||
|
||||
rpc *btcrpcclient.Client
|
||||
rpc *rpcclient.Client
|
||||
|
||||
sync.RWMutex
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ func (m *memWallet) SyncedHeight() int32 {
|
|||
|
||||
// SetRPCClient saves the passed rpc connection to btcd as the wallet's
|
||||
// personal rpc connection.
|
||||
func (m *memWallet) SetRPCClient(rpcClient *btcrpcclient.Client) {
|
||||
func (m *memWallet) SetRPCClient(rpcClient *rpcclient.Client) {
|
||||
m.rpc = rpcClient
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"runtime"
|
||||
"time"
|
||||
|
||||
rpc "github.com/btcsuite/btcrpcclient"
|
||||
rpc "github.com/btcsuite/btcd/rpcclient"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ import (
|
|||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/rpcclient"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcrpcclient"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
|
@ -78,9 +78,9 @@ type Harness struct {
|
|||
// to.
|
||||
ActiveNet *chaincfg.Params
|
||||
|
||||
Node *btcrpcclient.Client
|
||||
Node *rpcclient.Client
|
||||
node *node
|
||||
handlers *btcrpcclient.NotificationHandlers
|
||||
handlers *rpcclient.NotificationHandlers
|
||||
|
||||
wallet *memWallet
|
||||
|
||||
|
@ -97,7 +97,7 @@ type Harness struct {
|
|||
// used.
|
||||
//
|
||||
// NOTE: This function is safe for concurrent access.
|
||||
func New(activeNet *chaincfg.Params, handlers *btcrpcclient.NotificationHandlers,
|
||||
func New(activeNet *chaincfg.Params, handlers *rpcclient.NotificationHandlers,
|
||||
extraArgs []string) (*Harness, error) {
|
||||
|
||||
harnessStateMtx.Lock()
|
||||
|
@ -157,7 +157,7 @@ func New(activeNet *chaincfg.Params, handlers *btcrpcclient.NotificationHandlers
|
|||
numTestInstances++
|
||||
|
||||
if handlers == nil {
|
||||
handlers = &btcrpcclient.NotificationHandlers{}
|
||||
handlers = &rpcclient.NotificationHandlers{}
|
||||
}
|
||||
|
||||
// If a handler for the OnFilteredBlock{Connected,Disconnected} callback
|
||||
|
@ -303,12 +303,12 @@ func (h *Harness) TearDown() error {
|
|||
// we're not able to establish a connection, this function returns with an
|
||||
// error.
|
||||
func (h *Harness) connectRPCClient() error {
|
||||
var client *btcrpcclient.Client
|
||||
var client *rpcclient.Client
|
||||
var err error
|
||||
|
||||
rpcConf := h.node.config.rpcConnConfig()
|
||||
for i := 0; i < h.maxConnRetries; i++ {
|
||||
if client, err = btcrpcclient.New(&rpcConf, h.handlers); err != nil {
|
||||
if client, err = rpcclient.New(&rpcConf, h.handlers); err != nil {
|
||||
time.Sleep(time.Duration(i) * 50 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
|
@ -379,7 +379,7 @@ func (h *Harness) UnlockOutputs(inputs []*wire.TxIn) {
|
|||
// RPCConfig returns the harnesses current rpc configuration. This allows other
|
||||
// potential RPC clients created within tests to connect to a given test
|
||||
// harness instance.
|
||||
func (h *Harness) RPCConfig() btcrpcclient.ConnConfig {
|
||||
func (h *Harness) RPCConfig() rpcclient.ConnConfig {
|
||||
return h.node.config.rpcConnConfig()
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcrpcclient"
|
||||
"github.com/btcsuite/btcd/rpcclient"
|
||||
)
|
||||
|
||||
// JoinType is an enum representing a particular type of "node join". A node
|
||||
|
@ -115,7 +115,7 @@ func ConnectNode(from *Harness, to *Harness) error {
|
|||
numPeers := len(peerInfo)
|
||||
|
||||
targetAddr := to.node.config.listen
|
||||
if err := from.Node.AddNode(targetAddr, btcrpcclient.ANAdd); err != nil {
|
||||
if err := from.Node.AddNode(targetAddr, rpcclient.ANAdd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
13
rpcclient/CONTRIBUTORS
Normal file
13
rpcclient/CONTRIBUTORS
Normal file
|
@ -0,0 +1,13 @@
|
|||
# This is the list of people who have contributed code to the repository.
|
||||
#
|
||||
# Names should be added to this file only after verifying that the individual
|
||||
# or the individual's organization has agreed to the LICENSE.
|
||||
#
|
||||
# Names should be added to this file like so:
|
||||
# Name <email address>
|
||||
|
||||
Dave Collins <davec@conformal.com>
|
||||
Geert-Johan Riemer <geertjohan.riemer@gmail.com>
|
||||
Josh Rickmar <jrick@conformal.com>
|
||||
Michalis Kargakis <michaliskargakis@gmail.com>
|
||||
Ruben de Vries <ruben@rubensayshi.com
|
56
rpcclient/README.md
Normal file
56
rpcclient/README.md
Normal file
|
@ -0,0 +1,56 @@
|
|||
rpcclient
|
||||
=========
|
||||
|
||||
[![Build Status](http://img.shields.io/travis/btcsuite/btcd.svg)](https://travis-ci.org/btcsuite/btcd)
|
||||
[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org)
|
||||
[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/btcsuite/btcd/rpcclient)
|
||||
|
||||
rpcclient implements a Websocket-enabled Bitcoin JSON-RPC client package written
|
||||
in [Go](http://golang.org/). It provides a robust and easy to use client for
|
||||
interfacing with a Bitcoin RPC server that uses a btcd/bitcoin core compatible
|
||||
Bitcoin JSON-RPC API.
|
||||
|
||||
## Status
|
||||
|
||||
This package is currently under active development. It is already stable and
|
||||
the infrastructure is complete. However, there are still several RPCs left to
|
||||
implement and the API is not stable yet.
|
||||
|
||||
## Documentation
|
||||
|
||||
* [API Reference](http://godoc.org/github.com/btcsuite/rpcclient)
|
||||
* [btcd Websockets Example](https://github.com/btcsuite/btcd/rpcclient/blob/master/examples/btcdwebsockets)
|
||||
Connects to a btcd RPC server using TLS-secured websockets, registers for
|
||||
block connected and block disconnected notifications, and gets the current
|
||||
block count
|
||||
* [btcwallet Websockets Example](https://github.com/btcsuite/btcd/rpcclient/blob/master/examples/btcwalletwebsockets)
|
||||
Connects to a btcwallet RPC server using TLS-secured websockets, registers for
|
||||
notifications about changes to account balances, and gets a list of unspent
|
||||
transaction outputs (utxos) the wallet can sign
|
||||
* [Bitcoin Core HTTP POST Example](https://github.com/btcsuite/btcd/rpcclient/blob/master/examples/bitcoincorehttp)
|
||||
Connects to a bitcoin core RPC server using HTTP POST mode with TLS disabled
|
||||
and gets the current block count
|
||||
|
||||
## Major Features
|
||||
|
||||
* Supports Websockets (btcd/btcwallet) and HTTP POST mode (bitcoin core)
|
||||
* Provides callback and registration functions for btcd/btcwallet notifications
|
||||
* Supports btcd extensions
|
||||
* Translates to and from higher-level and easier to use Go types
|
||||
* Offers a synchronous (blocking) and asynchronous API
|
||||
* When running in Websockets mode (the default):
|
||||
* Automatic reconnect handling (can be disabled)
|
||||
* Outstanding commands are automatically reissued
|
||||
* Registered notifications are automatically reregistered
|
||||
* Back-off support on reconnect attempts
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
$ go get -u github.com/btcsuite/btcd/rpcclient
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Package rpcclient is licensed under the [copyfree](http://copyfree.org) ISC
|
||||
License.
|
783
rpcclient/chain.go
Normal file
783
rpcclient/chain.go
Normal file
|
@ -0,0 +1,783 @@
|
|||
// Copyright (c) 2014-2017 The btcsuite developers
|
||||
// Copyright (c) 2015-2017 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rpcclient
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/btcsuite/btcd/btcjson"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
// FutureGetBestBlockHashResult is a future promise to deliver the result of a
|
||||
// GetBestBlockAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBestBlockHashResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the hash of
|
||||
// the best block in the longest block chain.
|
||||
func (r FutureGetBestBlockHashResult) Receive() (*chainhash.Hash, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a string.
|
||||
var txHashStr string
|
||||
err = json.Unmarshal(res, &txHashStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return chainhash.NewHashFromStr(txHashStr)
|
||||
}
|
||||
|
||||
// GetBestBlockHashAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See GetBestBlockHash for the blocking version and more details.
|
||||
func (c *Client) GetBestBlockHashAsync() FutureGetBestBlockHashResult {
|
||||
cmd := btcjson.NewGetBestBlockHashCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetBestBlockHash returns the hash of the best block in the longest block
|
||||
// chain.
|
||||
func (c *Client) GetBestBlockHash() (*chainhash.Hash, error) {
|
||||
return c.GetBestBlockHashAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetBlockResult is a future promise to deliver the result of a
|
||||
// GetBlockAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBlockResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the raw
|
||||
// block requested from the server given its hash.
|
||||
func (r FutureGetBlockResult) Receive() (*wire.MsgBlock, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a string.
|
||||
var blockHex string
|
||||
err = json.Unmarshal(res, &blockHex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Decode the serialized block hex to raw bytes.
|
||||
serializedBlock, err := hex.DecodeString(blockHex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Deserialize the block and return it.
|
||||
var msgBlock wire.MsgBlock
|
||||
err = msgBlock.Deserialize(bytes.NewReader(serializedBlock))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &msgBlock, nil
|
||||
}
|
||||
|
||||
// GetBlockAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetBlock for the blocking version and more details.
|
||||
func (c *Client) GetBlockAsync(blockHash *chainhash.Hash) FutureGetBlockResult {
|
||||
hash := ""
|
||||
if blockHash != nil {
|
||||
hash = blockHash.String()
|
||||
}
|
||||
|
||||
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(false), nil)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetBlock returns a raw block from the server given its hash.
|
||||
//
|
||||
// See GetBlockVerbose to retrieve a data structure with information about the
|
||||
// block instead.
|
||||
func (c *Client) GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error) {
|
||||
return c.GetBlockAsync(blockHash).Receive()
|
||||
}
|
||||
|
||||
// FutureGetBlockVerboseResult is a future promise to deliver the result of a
|
||||
// GetBlockVerboseAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBlockVerboseResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the data
|
||||
// structure from the server with information about the requested block.
|
||||
func (r FutureGetBlockVerboseResult) Receive() (*btcjson.GetBlockVerboseResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal the raw result into a BlockResult.
|
||||
var blockResult btcjson.GetBlockVerboseResult
|
||||
err = json.Unmarshal(res, &blockResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &blockResult, nil
|
||||
}
|
||||
|
||||
// GetBlockVerboseAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See GetBlockVerbose for the blocking version and more details.
|
||||
func (c *Client) GetBlockVerboseAsync(blockHash *chainhash.Hash) FutureGetBlockVerboseResult {
|
||||
hash := ""
|
||||
if blockHash != nil {
|
||||
hash = blockHash.String()
|
||||
}
|
||||
|
||||
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(true), nil)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetBlockVerbose returns a data structure from the server with information
|
||||
// about a block given its hash.
|
||||
//
|
||||
// See GetBlockVerboseTx to retrieve transaction data structures as well.
|
||||
// See GetBlock to retrieve a raw block instead.
|
||||
func (c *Client) GetBlockVerbose(blockHash *chainhash.Hash) (*btcjson.GetBlockVerboseResult, error) {
|
||||
return c.GetBlockVerboseAsync(blockHash).Receive()
|
||||
}
|
||||
|
||||
// GetBlockVerboseTxAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See GetBlockVerboseTx or the blocking version and more details.
|
||||
func (c *Client) GetBlockVerboseTxAsync(blockHash *chainhash.Hash) FutureGetBlockVerboseResult {
|
||||
hash := ""
|
||||
if blockHash != nil {
|
||||
hash = blockHash.String()
|
||||
}
|
||||
|
||||
cmd := btcjson.NewGetBlockCmd(hash, btcjson.Bool(true), btcjson.Bool(true))
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetBlockVerboseTx returns a data structure from the server with information
|
||||
// about a block and its transactions given its hash.
|
||||
//
|
||||
// See GetBlockVerbose if only transaction hashes are preferred.
|
||||
// See GetBlock to retrieve a raw block instead.
|
||||
func (c *Client) GetBlockVerboseTx(blockHash *chainhash.Hash) (*btcjson.GetBlockVerboseResult, error) {
|
||||
return c.GetBlockVerboseTxAsync(blockHash).Receive()
|
||||
}
|
||||
|
||||
// FutureGetBlockCountResult is a future promise to deliver the result of a
|
||||
// GetBlockCountAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBlockCountResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the number
|
||||
// of blocks in the longest block chain.
|
||||
func (r FutureGetBlockCountResult) Receive() (int64, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Unmarshal the result as an int64.
|
||||
var count int64
|
||||
err = json.Unmarshal(res, &count)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// GetBlockCountAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetBlockCount for the blocking version and more details.
|
||||
func (c *Client) GetBlockCountAsync() FutureGetBlockCountResult {
|
||||
cmd := btcjson.NewGetBlockCountCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetBlockCount returns the number of blocks in the longest block chain.
|
||||
func (c *Client) GetBlockCount() (int64, error) {
|
||||
return c.GetBlockCountAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetDifficultyResult is a future promise to deliver the result of a
|
||||
// GetDifficultyAsync RPC invocation (or an applicable error).
|
||||
type FutureGetDifficultyResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// proof-of-work difficulty as a multiple of the minimum difficulty.
|
||||
func (r FutureGetDifficultyResult) Receive() (float64, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Unmarshal the result as a float64.
|
||||
var difficulty float64
|
||||
err = json.Unmarshal(res, &difficulty)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return difficulty, nil
|
||||
}
|
||||
|
||||
// GetDifficultyAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetDifficulty for the blocking version and more details.
|
||||
func (c *Client) GetDifficultyAsync() FutureGetDifficultyResult {
|
||||
cmd := btcjson.NewGetDifficultyCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetDifficulty returns the proof-of-work difficulty as a multiple of the
|
||||
// minimum difficulty.
|
||||
func (c *Client) GetDifficulty() (float64, error) {
|
||||
return c.GetDifficultyAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetBlockChainInfoResult is a promise to deliver the result of a
|
||||
// GetBlockChainInfoAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBlockChainInfoResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns chain info
|
||||
// result provided by the server.
|
||||
func (r FutureGetBlockChainInfoResult) Receive() (*btcjson.GetBlockChainInfoResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var chainInfo btcjson.GetBlockChainInfoResult
|
||||
if err := json.Unmarshal(res, &chainInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &chainInfo, nil
|
||||
}
|
||||
|
||||
// GetBlockChainInfoAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function
|
||||
// on the returned instance.
|
||||
//
|
||||
// See GetBlockChainInfo for the blocking version and more details.
|
||||
func (c *Client) GetBlockChainInfoAsync() FutureGetBlockChainInfoResult {
|
||||
cmd := btcjson.NewGetBlockChainInfoCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetBlockChainInfo returns information related to the processing state of
|
||||
// various chain-specific details such as the current difficulty from the tip
|
||||
// of the main chain.
|
||||
func (c *Client) GetBlockChainInfo() (*btcjson.GetBlockChainInfoResult, error) {
|
||||
return c.GetBlockChainInfoAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetBlockHashResult is a future promise to deliver the result of a
|
||||
// GetBlockHashAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBlockHashResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the hash of
|
||||
// the block in the best block chain at the given height.
|
||||
func (r FutureGetBlockHashResult) Receive() (*chainhash.Hash, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal the result as a string-encoded sha.
|
||||
var txHashStr string
|
||||
err = json.Unmarshal(res, &txHashStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return chainhash.NewHashFromStr(txHashStr)
|
||||
}
|
||||
|
||||
// GetBlockHashAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetBlockHash for the blocking version and more details.
|
||||
func (c *Client) GetBlockHashAsync(blockHeight int64) FutureGetBlockHashResult {
|
||||
cmd := btcjson.NewGetBlockHashCmd(blockHeight)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetBlockHash returns the hash of the block in the best block chain at the
|
||||
// given height.
|
||||
func (c *Client) GetBlockHash(blockHeight int64) (*chainhash.Hash, error) {
|
||||
return c.GetBlockHashAsync(blockHeight).Receive()
|
||||
}
|
||||
|
||||
// FutureGetBlockHeaderResult is a future promise to deliver the result of a
|
||||
// GetBlockHeaderAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBlockHeaderResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// blockheader requested from the server given its hash.
|
||||
func (r FutureGetBlockHeaderResult) Receive() (*wire.BlockHeader, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a string.
|
||||
var bhHex string
|
||||
err = json.Unmarshal(res, &bhHex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serializedBH, err := hex.DecodeString(bhHex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Deserialize the blockheader and return it.
|
||||
var bh wire.BlockHeader
|
||||
err = bh.Deserialize(bytes.NewReader(serializedBH))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &bh, err
|
||||
}
|
||||
|
||||
// GetBlockHeaderAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetBlockHeader for the blocking version and more details.
|
||||
func (c *Client) GetBlockHeaderAsync(blockHash *chainhash.Hash) FutureGetBlockHeaderResult {
|
||||
hash := ""
|
||||
if blockHash != nil {
|
||||
hash = blockHash.String()
|
||||
}
|
||||
|
||||
cmd := btcjson.NewGetBlockHeaderCmd(hash, btcjson.Bool(false))
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetBlockHeader returns the blockheader from the server given its hash.
|
||||
//
|
||||
// See GetBlockHeaderVerbose to retrieve a data structure with information about the
|
||||
// block instead.
|
||||
func (c *Client) GetBlockHeader(blockHash *chainhash.Hash) (*wire.BlockHeader, error) {
|
||||
return c.GetBlockHeaderAsync(blockHash).Receive()
|
||||
}
|
||||
|
||||
// FutureGetBlockHeaderVerboseResult is a future promise to deliver the result of a
|
||||
// GetBlockAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBlockHeaderVerboseResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// data structure of the blockheader requested from the server given its hash.
|
||||
func (r FutureGetBlockHeaderVerboseResult) Receive() (*btcjson.GetBlockHeaderVerboseResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a string.
|
||||
var bh btcjson.GetBlockHeaderVerboseResult
|
||||
err = json.Unmarshal(res, &bh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &bh, nil
|
||||
}
|
||||
|
||||
// GetBlockHeaderVerboseAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetBlockHeader for the blocking version and more details.
|
||||
func (c *Client) GetBlockHeaderVerboseAsync(blockHash *chainhash.Hash) FutureGetBlockHeaderVerboseResult {
|
||||
hash := ""
|
||||
if blockHash != nil {
|
||||
hash = blockHash.String()
|
||||
}
|
||||
|
||||
cmd := btcjson.NewGetBlockHeaderCmd(hash, btcjson.Bool(true))
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetBlockHeaderVerbose returns a data structure with information about the
|
||||
// blockheader from the server given its hash.
|
||||
//
|
||||
// See GetBlockHeader to retrieve a blockheader instead.
|
||||
func (c *Client) GetBlockHeaderVerbose(blockHash *chainhash.Hash) (*btcjson.GetBlockHeaderVerboseResult, error) {
|
||||
return c.GetBlockHeaderVerboseAsync(blockHash).Receive()
|
||||
}
|
||||
|
||||
// FutureGetMempoolEntryResult is a future promise to deliver the result of a
|
||||
// GetMempoolEntryAsync RPC invocation (or an applicable error).
|
||||
type FutureGetMempoolEntryResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns a data
|
||||
// structure with information about the transaction in the memory pool given
|
||||
// its hash.
|
||||
func (r FutureGetMempoolEntryResult) Receive() (*btcjson.GetMempoolEntryResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal the result as an array of strings.
|
||||
var mempoolEntryResult btcjson.GetMempoolEntryResult
|
||||
err = json.Unmarshal(res, &mempoolEntryResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &mempoolEntryResult, nil
|
||||
}
|
||||
|
||||
// GetMempoolEntryAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetMempoolEntry for the blocking version and more details.
|
||||
func (c *Client) GetMempoolEntryAsync(txHash string) FutureGetMempoolEntryResult {
|
||||
cmd := btcjson.NewGetMempoolEntryCmd(txHash)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetMempoolEntry returns a data structure with information about the
|
||||
// transaction in the memory pool given its hash.
|
||||
func (c *Client) GetMempoolEntry(txHash string) (*btcjson.GetMempoolEntryResult, error) {
|
||||
return c.GetMempoolEntryAsync(txHash).Receive()
|
||||
}
|
||||
|
||||
// FutureGetRawMempoolResult is a future promise to deliver the result of a
|
||||
// GetRawMempoolAsync RPC invocation (or an applicable error).
|
||||
type FutureGetRawMempoolResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the hashes
|
||||
// of all transactions in the memory pool.
|
||||
func (r FutureGetRawMempoolResult) Receive() ([]*chainhash.Hash, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal the result as an array of strings.
|
||||
var txHashStrs []string
|
||||
err = json.Unmarshal(res, &txHashStrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create a slice of ShaHash arrays from the string slice.
|
||||
txHashes := make([]*chainhash.Hash, 0, len(txHashStrs))
|
||||
for _, hashStr := range txHashStrs {
|
||||
txHash, err := chainhash.NewHashFromStr(hashStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
txHashes = append(txHashes, txHash)
|
||||
}
|
||||
|
||||
return txHashes, nil
|
||||
}
|
||||
|
||||
// GetRawMempoolAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetRawMempool for the blocking version and more details.
|
||||
func (c *Client) GetRawMempoolAsync() FutureGetRawMempoolResult {
|
||||
cmd := btcjson.NewGetRawMempoolCmd(btcjson.Bool(false))
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetRawMempool returns the hashes of all transactions in the memory pool.
|
||||
//
|
||||
// See GetRawMempoolVerbose to retrieve data structures with information about
|
||||
// the transactions instead.
|
||||
func (c *Client) GetRawMempool() ([]*chainhash.Hash, error) {
|
||||
return c.GetRawMempoolAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetRawMempoolVerboseResult is a future promise to deliver the result of
|
||||
// a GetRawMempoolVerboseAsync RPC invocation (or an applicable error).
|
||||
type FutureGetRawMempoolVerboseResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns a map of
|
||||
// transaction hashes to an associated data structure with information about the
|
||||
// transaction for all transactions in the memory pool.
|
||||
func (r FutureGetRawMempoolVerboseResult) Receive() (map[string]btcjson.GetRawMempoolVerboseResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal the result as a map of strings (tx shas) to their detailed
|
||||
// results.
|
||||
var mempoolItems map[string]btcjson.GetRawMempoolVerboseResult
|
||||
err = json.Unmarshal(res, &mempoolItems)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mempoolItems, nil
|
||||
}
|
||||
|
||||
// GetRawMempoolVerboseAsync returns an instance of a type that can be used to
|
||||
// get the result of the RPC at some future time by invoking the Receive
|
||||
// function on the returned instance.
|
||||
//
|
||||
// See GetRawMempoolVerbose for the blocking version and more details.
|
||||
func (c *Client) GetRawMempoolVerboseAsync() FutureGetRawMempoolVerboseResult {
|
||||
cmd := btcjson.NewGetRawMempoolCmd(btcjson.Bool(true))
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetRawMempoolVerbose returns a map of transaction hashes to an associated
|
||||
// data structure with information about the transaction for all transactions in
|
||||
// the memory pool.
|
||||
//
|
||||
// See GetRawMempool to retrieve only the transaction hashes instead.
|
||||
func (c *Client) GetRawMempoolVerbose() (map[string]btcjson.GetRawMempoolVerboseResult, error) {
|
||||
return c.GetRawMempoolVerboseAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureVerifyChainResult is a future promise to deliver the result of a
|
||||
// VerifyChainAsync, VerifyChainLevelAsyncRPC, or VerifyChainBlocksAsync
|
||||
// invocation (or an applicable error).
|
||||
type FutureVerifyChainResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns whether
|
||||
// or not the chain verified based on the check level and number of blocks
|
||||
// to verify specified in the original call.
|
||||
func (r FutureVerifyChainResult) Receive() (bool, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Unmarshal the result as a boolean.
|
||||
var verified bool
|
||||
err = json.Unmarshal(res, &verified)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return verified, nil
|
||||
}
|
||||
|
||||
// VerifyChainAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See VerifyChain for the blocking version and more details.
|
||||
func (c *Client) VerifyChainAsync() FutureVerifyChainResult {
|
||||
cmd := btcjson.NewVerifyChainCmd(nil, nil)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// VerifyChain requests the server to verify the block chain database using
|
||||
// the default check level and number of blocks to verify.
|
||||
//
|
||||
// See VerifyChainLevel and VerifyChainBlocks to override the defaults.
|
||||
func (c *Client) VerifyChain() (bool, error) {
|
||||
return c.VerifyChainAsync().Receive()
|
||||
}
|
||||
|
||||
// VerifyChainLevelAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See VerifyChainLevel for the blocking version and more details.
|
||||
func (c *Client) VerifyChainLevelAsync(checkLevel int32) FutureVerifyChainResult {
|
||||
cmd := btcjson.NewVerifyChainCmd(&checkLevel, nil)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// VerifyChainLevel requests the server to verify the block chain database using
|
||||
// the passed check level and default number of blocks to verify.
|
||||
//
|
||||
// The check level controls how thorough the verification is with higher numbers
|
||||
// increasing the amount of checks done as consequently how long the
|
||||
// verification takes.
|
||||
//
|
||||
// See VerifyChain to use the default check level and VerifyChainBlocks to
|
||||
// override the number of blocks to verify.
|
||||
func (c *Client) VerifyChainLevel(checkLevel int32) (bool, error) {
|
||||
return c.VerifyChainLevelAsync(checkLevel).Receive()
|
||||
}
|
||||
|
||||
// VerifyChainBlocksAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See VerifyChainBlocks for the blocking version and more details.
|
||||
func (c *Client) VerifyChainBlocksAsync(checkLevel, numBlocks int32) FutureVerifyChainResult {
|
||||
cmd := btcjson.NewVerifyChainCmd(&checkLevel, &numBlocks)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// VerifyChainBlocks requests the server to verify the block chain database
|
||||
// using the passed check level and number of blocks to verify.
|
||||
//
|
||||
// The check level controls how thorough the verification is with higher numbers
|
||||
// increasing the amount of checks done as consequently how long the
|
||||
// verification takes.
|
||||
//
|
||||
// The number of blocks refers to the number of blocks from the end of the
|
||||
// current longest chain.
|
||||
//
|
||||
// See VerifyChain and VerifyChainLevel to use defaults.
|
||||
func (c *Client) VerifyChainBlocks(checkLevel, numBlocks int32) (bool, error) {
|
||||
return c.VerifyChainBlocksAsync(checkLevel, numBlocks).Receive()
|
||||
}
|
||||
|
||||
// FutureGetTxOutResult is a future promise to deliver the result of a
|
||||
// GetTxOutAsync RPC invocation (or an applicable error).
|
||||
type FutureGetTxOutResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns a
|
||||
// transaction given its hash.
|
||||
func (r FutureGetTxOutResult) Receive() (*btcjson.GetTxOutResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// take care of the special case where the output has been spent already
|
||||
// it should return the string "null"
|
||||
if string(res) == "null" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Unmarshal result as an gettxout result object.
|
||||
var txOutInfo *btcjson.GetTxOutResult
|
||||
err = json.Unmarshal(res, &txOutInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return txOutInfo, nil
|
||||
}
|
||||
|
||||
// GetTxOutAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See GetTxOut for the blocking version and more details.
|
||||
func (c *Client) GetTxOutAsync(txHash *chainhash.Hash, index uint32, mempool bool) FutureGetTxOutResult {
|
||||
hash := ""
|
||||
if txHash != nil {
|
||||
hash = txHash.String()
|
||||
}
|
||||
|
||||
cmd := btcjson.NewGetTxOutCmd(hash, index, &mempool)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetTxOut returns the transaction output info if it's unspent and
|
||||
// nil, otherwise.
|
||||
func (c *Client) GetTxOut(txHash *chainhash.Hash, index uint32, mempool bool) (*btcjson.GetTxOutResult, error) {
|
||||
return c.GetTxOutAsync(txHash, index, mempool).Receive()
|
||||
}
|
||||
|
||||
// FutureRescanBlocksResult is a future promise to deliver the result of a
|
||||
// RescanBlocksAsync RPC invocation (or an applicable error).
|
||||
//
|
||||
// NOTE: This is a btcsuite extension ported from
|
||||
// github.com/decred/dcrrpcclient.
|
||||
type FutureRescanBlocksResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// discovered rescanblocks data.
|
||||
//
|
||||
// NOTE: This is a btcsuite extension ported from
|
||||
// github.com/decred/dcrrpcclient.
|
||||
func (r FutureRescanBlocksResult) Receive() ([]btcjson.RescannedBlock, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var rescanBlocksResult []btcjson.RescannedBlock
|
||||
err = json.Unmarshal(res, &rescanBlocksResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rescanBlocksResult, nil
|
||||
}
|
||||
|
||||
// RescanBlocksAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See RescanBlocks for the blocking version and more details.
|
||||
//
|
||||
// NOTE: This is a btcsuite extension ported from
|
||||
// github.com/decred/dcrrpcclient.
|
||||
func (c *Client) RescanBlocksAsync(blockHashes []chainhash.Hash) FutureRescanBlocksResult {
|
||||
strBlockHashes := make([]string, len(blockHashes))
|
||||
for i := range blockHashes {
|
||||
strBlockHashes[i] = blockHashes[i].String()
|
||||
}
|
||||
|
||||
cmd := btcjson.NewRescanBlocksCmd(strBlockHashes)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// RescanBlocks rescans the blocks identified by blockHashes, in order, using
|
||||
// the client's loaded transaction filter. The blocks do not need to be on the
|
||||
// main chain, but they do need to be adjacent to each other.
|
||||
//
|
||||
// NOTE: This is a btcsuite extension ported from
|
||||
// github.com/decred/dcrrpcclient.
|
||||
func (c *Client) RescanBlocks(blockHashes []chainhash.Hash) ([]btcjson.RescannedBlock, error) {
|
||||
return c.RescanBlocksAsync(blockHashes).Receive()
|
||||
}
|
||||
|
||||
// FutureInvalidateBlockResult is a future promise to deliver the result of a
|
||||
// InvalidateBlockAsync RPC invocation (or an applicable error).
|
||||
type FutureInvalidateBlockResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the raw
|
||||
// block requested from the server given its hash.
|
||||
func (r FutureInvalidateBlockResult) Receive() error {
|
||||
_, err := receiveFuture(r)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// InvalidateBlockAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See InvalidateBlock for the blocking version and more details.
|
||||
func (c *Client) InvalidateBlockAsync(blockHash *chainhash.Hash) FutureInvalidateBlockResult {
|
||||
hash := ""
|
||||
if blockHash != nil {
|
||||
hash = blockHash.String()
|
||||
}
|
||||
|
||||
cmd := btcjson.NewInvalidateBlockCmd(hash)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// InvalidateBlock invalidates a specific block.
|
||||
func (c *Client) InvalidateBlock(blockHash *chainhash.Hash) error {
|
||||
return c.InvalidateBlockAsync(blockHash).Receive()
|
||||
}
|
178
rpcclient/doc.go
Normal file
178
rpcclient/doc.go
Normal file
|
@ -0,0 +1,178 @@
|
|||
// Copyright (c) 2014-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package rpcclient implements a websocket-enabled Bitcoin JSON-RPC client.
|
||||
|
||||
Overview
|
||||
|
||||
This client provides a robust and easy to use client for interfacing with a
|
||||
Bitcoin RPC server that uses a btcd/bitcoin core compatible Bitcoin JSON-RPC
|
||||
API. This client has been tested with btcd (https://github.com/btcsuite/btcd),
|
||||
btcwallet (https://github.com/btcsuite/btcwallet), and
|
||||
bitcoin core (https://github.com/bitcoin).
|
||||
|
||||
In addition to the compatible standard HTTP POST JSON-RPC API, btcd and
|
||||
btcwallet provide a websocket interface that is more efficient than the standard
|
||||
HTTP POST method of accessing RPC. The section below discusses the differences
|
||||
between HTTP POST and websockets.
|
||||
|
||||
By default, this client assumes the RPC server supports websockets and has
|
||||
TLS enabled. In practice, this currently means it assumes you are talking to
|
||||
btcd or btcwallet by default. However, configuration options are provided to
|
||||
fall back to HTTP POST and disable TLS to support talking with inferior bitcoin
|
||||
core style RPC servers.
|
||||
|
||||
Websockets vs HTTP POST
|
||||
|
||||
In HTTP POST-based JSON-RPC, every request creates a new HTTP connection,
|
||||
issues the call, waits for the response, and closes the connection. This adds
|
||||
quite a bit of overhead to every call and lacks flexibility for features such as
|
||||
notifications.
|
||||
|
||||
In contrast, the websocket-based JSON-RPC interface provided by btcd and
|
||||
btcwallet only uses a single connection that remains open and allows
|
||||
asynchronous bi-directional communication.
|
||||
|
||||
The websocket interface supports all of the same commands as HTTP POST, but they
|
||||
can be invoked without having to go through a connect/disconnect cycle for every
|
||||
call. In addition, the websocket interface provides other nice features such as
|
||||
the ability to register for asynchronous notifications of various events.
|
||||
|
||||
Synchronous vs Asynchronous API
|
||||
|
||||
The client provides both a synchronous (blocking) and asynchronous API.
|
||||
|
||||
The synchronous (blocking) API is typically sufficient for most use cases. It
|
||||
works by issuing the RPC and blocking until the response is received. This
|
||||
allows straightforward code where you have the response as soon as the function
|
||||
returns.
|
||||
|
||||
The asynchronous API works on the concept of futures. When you invoke the async
|
||||
version of a command, it will quickly return an instance of a type that promises
|
||||
to provide the result of the RPC at some future time. In the background, the
|
||||
RPC call is issued and the result is stored in the returned instance. Invoking
|
||||
the Receive method on the returned instance will either return the result
|
||||
immediately if it has already arrived, or block until it has. This is useful
|
||||
since it provides the caller with greater control over concurrency.
|
||||
|
||||
Notifications
|
||||
|
||||
The first important part of notifications is to realize that they will only
|
||||
work when connected via websockets. This should intuitively make sense
|
||||
because HTTP POST mode does not keep a connection open!
|
||||
|
||||
All notifications provided by btcd require registration to opt-in. For example,
|
||||
if you want to be notified when funds are received by a set of addresses, you
|
||||
register the addresses via the NotifyReceived (or NotifyReceivedAsync) function.
|
||||
|
||||
Notification Handlers
|
||||
|
||||
Notifications are exposed by the client through the use of callback handlers
|
||||
which are setup via a NotificationHandlers instance that is specified by the
|
||||
caller when creating the client.
|
||||
|
||||
It is important that these notification handlers complete quickly since they
|
||||
are intentionally in the main read loop and will block further reads until
|
||||
they complete. This provides the caller with the flexibility to decide what to
|
||||
do when notifications are coming in faster than they are being handled.
|
||||
|
||||
In particular this means issuing a blocking RPC call from a callback handler
|
||||
will cause a deadlock as more server responses won't be read until the callback
|
||||
returns, but the callback would be waiting for a response. Thus, any
|
||||
additional RPCs must be issued an a completely decoupled manner.
|
||||
|
||||
Automatic Reconnection
|
||||
|
||||
By default, when running in websockets mode, this client will automatically
|
||||
keep trying to reconnect to the RPC server should the connection be lost. There
|
||||
is a back-off in between each connection attempt until it reaches one try per
|
||||
minute. Once a connection is re-established, all previously registered
|
||||
notifications are automatically re-registered and any in-flight commands are
|
||||
re-issued. This means from the caller's perspective, the request simply takes
|
||||
longer to complete.
|
||||
|
||||
The caller may invoke the Shutdown method on the client to force the client
|
||||
to cease reconnect attempts and return ErrClientShutdown for all outstanding
|
||||
commands.
|
||||
|
||||
The automatic reconnection can be disabled by setting the DisableAutoReconnect
|
||||
flag to true in the connection config when creating the client.
|
||||
|
||||
Minor RPC Server Differences and Chain/Wallet Separation
|
||||
|
||||
Some of the commands are extensions specific to a particular RPC server. For
|
||||
example, the DebugLevel call is an extension only provided by btcd (and
|
||||
btcwallet passthrough). Therefore if you call one of these commands against
|
||||
an RPC server that doesn't provide them, you will get an unimplemented error
|
||||
from the server. An effort has been made to call out which commmands are
|
||||
extensions in their documentation.
|
||||
|
||||
Also, it is important to realize that btcd intentionally separates the wallet
|
||||
functionality into a separate process named btcwallet. This means if you are
|
||||
connected to the btcd RPC server directly, only the RPCs which are related to
|
||||
chain services will be available. Depending on your application, you might only
|
||||
need chain-related RPCs. In contrast, btcwallet provides pass through treatment
|
||||
for chain-related RPCs, so it supports them in addition to wallet-related RPCs.
|
||||
|
||||
Errors
|
||||
|
||||
There are 3 categories of errors that will be returned throughout this package:
|
||||
|
||||
- Errors related to the client connection such as authentication, endpoint,
|
||||
disconnect, and shutdown
|
||||
- Errors that occur before communicating with the remote RPC server such as
|
||||
command creation and marshaling errors or issues talking to the remote
|
||||
server
|
||||
- Errors returned from the remote RPC server like unimplemented commands,
|
||||
nonexistent requested blocks and transactions, malformed data, and incorrect
|
||||
networks
|
||||
|
||||
The first category of errors are typically one of ErrInvalidAuth,
|
||||
ErrInvalidEndpoint, ErrClientDisconnect, or ErrClientShutdown.
|
||||
|
||||
NOTE: The ErrClientDisconnect will not be returned unless the
|
||||
DisableAutoReconnect flag is set since the client automatically handles
|
||||
reconnect by default as previously described.
|
||||
|
||||
The second category of errors typically indicates a programmer error and as such
|
||||
the type can vary, but usually will be best handled by simply showing/logging
|
||||
it.
|
||||
|
||||
The third category of errors, that is errors returned by the server, can be
|
||||
detected by type asserting the error in a *btcjson.RPCError. For example, to
|
||||
detect if a command is unimplemented by the remote RPC server:
|
||||
|
||||
amount, err := client.GetBalance("")
|
||||
if err != nil {
|
||||
if jerr, ok := err.(*btcjson.RPCError); ok {
|
||||
switch jerr.Code {
|
||||
case btcjson.ErrRPCUnimplemented:
|
||||
// Handle not implemented error
|
||||
|
||||
// Handle other specific errors you care about
|
||||
}
|
||||
}
|
||||
|
||||
// Log or otherwise handle the error knowing it was not one returned
|
||||
// from the remote RPC server.
|
||||
}
|
||||
|
||||
Example Usage
|
||||
|
||||
The following full-blown client examples are in the examples directory:
|
||||
|
||||
- bitcoincorehttp
|
||||
Connects to a bitcoin core RPC server using HTTP POST mode with TLS disabled
|
||||
and gets the current block count
|
||||
- btcdwebsockets
|
||||
Connects to a btcd RPC server using TLS-secured websockets, registers for
|
||||
block connected and block disconnected notifications, and gets the current
|
||||
block count
|
||||
- btcwalletwebsockets
|
||||
Connects to a btcwallet RPC server using TLS-secured websockets, registers
|
||||
for notifications about changes to account balances, and gets a list of
|
||||
unspent transaction outputs (utxos) the wallet can sign
|
||||
*/
|
||||
package rpcclient
|
33
rpcclient/examples/bitcoincorehttp/README.md
Normal file
33
rpcclient/examples/bitcoincorehttp/README.md
Normal file
|
@ -0,0 +1,33 @@
|
|||
Bitcoin Core HTTP POST Example
|
||||
==============================
|
||||
|
||||
This example shows how to use the rpcclient package to connect to a Bitcoin
|
||||
Core RPC server using HTTP POST mode with TLS disabled and gets the current
|
||||
block count.
|
||||
|
||||
## Running the Example
|
||||
|
||||
The first step is to use `go get` to download and install the rpcclient package:
|
||||
|
||||
```bash
|
||||
$ go get github.com/btcsuite/btcd/rpcclient
|
||||
```
|
||||
|
||||
Next, modify the `main.go` source to specify the correct RPC username and
|
||||
password for the RPC server:
|
||||
|
||||
```Go
|
||||
User: "yourrpcuser",
|
||||
Pass: "yourrpcpass",
|
||||
```
|
||||
|
||||
Finally, navigate to the example's directory and run it with:
|
||||
|
||||
```bash
|
||||
$ cd $GOPATH/src/github.com/btcsuite/btcd/rpcclient/examples/bitcoincorehttp
|
||||
$ go run *.go
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This example is licensed under the [copyfree](http://copyfree.org) ISC License.
|
36
rpcclient/examples/bitcoincorehttp/main.go
Normal file
36
rpcclient/examples/bitcoincorehttp/main.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) 2014-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/btcsuite/btcd/rpcclient"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Connect to local bitcoin core RPC server using HTTP POST mode.
|
||||
connCfg := &rpcclient.ConnConfig{
|
||||
Host: "localhost:8332",
|
||||
User: "yourrpcuser",
|
||||
Pass: "yourrpcpass",
|
||||
HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode
|
||||
DisableTLS: true, // Bitcoin core does not provide TLS by default
|
||||
}
|
||||
// Notice the notification parameter is nil since notifications are
|
||||
// not supported in HTTP POST mode.
|
||||
client, err := rpcclient.New(connCfg, nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer client.Shutdown()
|
||||
|
||||
// Get the current block count.
|
||||
blockCount, err := client.GetBlockCount()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Printf("Block count: %d", blockCount)
|
||||
}
|
36
rpcclient/examples/btcdwebsockets/README.md
Normal file
36
rpcclient/examples/btcdwebsockets/README.md
Normal file
|
@ -0,0 +1,36 @@
|
|||
btcd Websockets Example
|
||||
=======================
|
||||
|
||||
This example shows how to use the rpcclient package to connect to a btcd RPC
|
||||
server using TLS-secured websockets, register for block connected and block
|
||||
disconnected notifications, and get the current block count.
|
||||
|
||||
This example also sets a timer to shutdown the client after 10 seconds to
|
||||
demonstrate clean shutdown.
|
||||
|
||||
## Running the Example
|
||||
|
||||
The first step is to use `go get` to download and install the rpcclient package:
|
||||
|
||||
```bash
|
||||
$ go get github.com/btcsuite/btcd/rpcclient
|
||||
```
|
||||
|
||||
Next, modify the `main.go` source to specify the correct RPC username and
|
||||
password for the RPC server:
|
||||
|
||||
```Go
|
||||
User: "yourrpcuser",
|
||||
Pass: "yourrpcpass",
|
||||
```
|
||||
|
||||
Finally, navigate to the example's directory and run it with:
|
||||
|
||||
```bash
|
||||
$ cd $GOPATH/src/github.com/btcsuite/btcd/rpcclient/examples/btcdwebsockets
|
||||
$ go run *.go
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This example is licensed under the [copyfree](http://copyfree.org) ISC License.
|
78
rpcclient/examples/btcdwebsockets/main.go
Normal file
78
rpcclient/examples/btcdwebsockets/main.go
Normal file
|
@ -0,0 +1,78 @@
|
|||
// Copyright (c) 2014-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/rpcclient"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Only override the handlers for notifications you care about.
|
||||
// Also note most of these handlers will only be called if you register
|
||||
// for notifications. See the documentation of the rpcclient
|
||||
// NotificationHandlers type for more details about each handler.
|
||||
ntfnHandlers := rpcclient.NotificationHandlers{
|
||||
OnFilteredBlockConnected: func(height int32, header *wire.BlockHeader, txns []*btcutil.Tx) {
|
||||
log.Printf("Block connected: %v (%d) %v",
|
||||
header.BlockHash(), height, header.Timestamp)
|
||||
},
|
||||
OnFilteredBlockDisconnected: func(height int32, header *wire.BlockHeader) {
|
||||
log.Printf("Block disconnected: %v (%d) %v",
|
||||
header.BlockHash(), height, header.Timestamp)
|
||||
},
|
||||
}
|
||||
|
||||
// Connect to local btcd RPC server using websockets.
|
||||
btcdHomeDir := btcutil.AppDataDir("btcd", false)
|
||||
certs, err := ioutil.ReadFile(filepath.Join(btcdHomeDir, "rpc.cert"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
connCfg := &rpcclient.ConnConfig{
|
||||
Host: "localhost:8334",
|
||||
Endpoint: "ws",
|
||||
User: "yourrpcuser",
|
||||
Pass: "yourrpcpass",
|
||||
Certificates: certs,
|
||||
}
|
||||
client, err := rpcclient.New(connCfg, &ntfnHandlers)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Register for block connect and disconnect notifications.
|
||||
if err := client.NotifyBlocks(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Println("NotifyBlocks: Registration Complete")
|
||||
|
||||
// Get the current block count.
|
||||
blockCount, err := client.GetBlockCount()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Printf("Block count: %d", blockCount)
|
||||
|
||||
// For this example gracefully shutdown the client after 10 seconds.
|
||||
// Ordinarily when to shutdown the client is highly application
|
||||
// specific.
|
||||
log.Println("Client shutdown in 10 seconds...")
|
||||
time.AfterFunc(time.Second*10, func() {
|
||||
log.Println("Client shutting down...")
|
||||
client.Shutdown()
|
||||
log.Println("Client shutdown complete.")
|
||||
})
|
||||
|
||||
// Wait until the client either shuts down gracefully (or the user
|
||||
// terminates the process with Ctrl+C).
|
||||
client.WaitForShutdown()
|
||||
}
|
37
rpcclient/examples/btcwalletwebsockets/README.md
Normal file
37
rpcclient/examples/btcwalletwebsockets/README.md
Normal file
|
@ -0,0 +1,37 @@
|
|||
btcwallet Websockets Example
|
||||
============================
|
||||
|
||||
This example shows how to use the rpcclient package to connect to a btcwallet
|
||||
RPC server using TLS-secured websockets, register for notifications about
|
||||
changes to account balances, and get a list of unspent transaction outputs
|
||||
(utxos) the wallet can sign.
|
||||
|
||||
This example also sets a timer to shutdown the client after 10 seconds to
|
||||
demonstrate clean shutdown.
|
||||
|
||||
## Running the Example
|
||||
|
||||
The first step is to use `go get` to download and install the rpcclient package:
|
||||
|
||||
```bash
|
||||
$ go get github.com/btcsuite/btcd/rpcclient
|
||||
```
|
||||
|
||||
Next, modify the `main.go` source to specify the correct RPC username and
|
||||
password for the RPC server:
|
||||
|
||||
```Go
|
||||
User: "yourrpcuser",
|
||||
Pass: "yourrpcpass",
|
||||
```
|
||||
|
||||
Finally, navigate to the example's directory and run it with:
|
||||
|
||||
```bash
|
||||
$ cd $GOPATH/src/github.com/btcsuite/btcd/rpcclient/examples/btcwalletwebsockets
|
||||
$ go run *.go
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This example is licensed under the [copyfree](http://copyfree.org) ISC License.
|
72
rpcclient/examples/btcwalletwebsockets/main.go
Normal file
72
rpcclient/examples/btcwalletwebsockets/main.go
Normal file
|
@ -0,0 +1,72 @@
|
|||
// Copyright (c) 2014-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/rpcclient"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Only override the handlers for notifications you care about.
|
||||
// Also note most of the handlers will only be called if you register
|
||||
// for notifications. See the documentation of the rpcclient
|
||||
// NotificationHandlers type for more details about each handler.
|
||||
ntfnHandlers := rpcclient.NotificationHandlers{
|
||||
OnAccountBalance: func(account string, balance btcutil.Amount, confirmed bool) {
|
||||
log.Printf("New balance for account %s: %v", account,
|
||||
balance)
|
||||
},
|
||||
}
|
||||
|
||||
// Connect to local btcwallet RPC server using websockets.
|
||||
certHomeDir := btcutil.AppDataDir("btcwallet", false)
|
||||
certs, err := ioutil.ReadFile(filepath.Join(certHomeDir, "rpc.cert"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
connCfg := &rpcclient.ConnConfig{
|
||||
Host: "localhost:18332",
|
||||
Endpoint: "ws",
|
||||
User: "yourrpcuser",
|
||||
Pass: "yourrpcpass",
|
||||
Certificates: certs,
|
||||
}
|
||||
client, err := rpcclient.New(connCfg, &ntfnHandlers)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Get the list of unspent transaction outputs (utxos) that the
|
||||
// connected wallet has at least one private key for.
|
||||
unspent, err := client.ListUnspent()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Printf("Num unspent outputs (utxos): %d", len(unspent))
|
||||
if len(unspent) > 0 {
|
||||
log.Printf("First utxo:\n%v", spew.Sdump(unspent[0]))
|
||||
}
|
||||
|
||||
// For this example gracefully shutdown the client after 10 seconds.
|
||||
// Ordinarily when to shutdown the client is highly application
|
||||
// specific.
|
||||
log.Println("Client shutdown in 10 seconds...")
|
||||
time.AfterFunc(time.Second*10, func() {
|
||||
log.Println("Client shutting down...")
|
||||
client.Shutdown()
|
||||
log.Println("Client shutdown complete.")
|
||||
})
|
||||
|
||||
// Wait until the client either shuts down gracefully (or the user
|
||||
// terminates the process with Ctrl+C).
|
||||
client.WaitForShutdown()
|
||||
}
|
473
rpcclient/extensions.go
Normal file
473
rpcclient/extensions.go
Normal file
|
@ -0,0 +1,473 @@
|
|||
// Copyright (c) 2014-2017 The btcsuite developers
|
||||
// Copyright (c) 2015-2017 The Decred developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rpcclient
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/btcjson"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
// FutureDebugLevelResult is a future promise to deliver the result of a
|
||||
// DebugLevelAsync RPC invocation (or an applicable error).
|
||||
type FutureDebugLevelResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the result
|
||||
// of setting the debug logging level to the passed level specification or the
|
||||
// list of of the available subsystems for the special keyword 'show'.
|
||||
func (r FutureDebugLevelResult) Receive() (string, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Unmashal the result as a string.
|
||||
var result string
|
||||
err = json.Unmarshal(res, &result)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DebugLevelAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See DebugLevel for the blocking version and more details.
|
||||
//
|
||||
// NOTE: This is a btcd extension.
|
||||
func (c *Client) DebugLevelAsync(levelSpec string) FutureDebugLevelResult {
|
||||
cmd := btcjson.NewDebugLevelCmd(levelSpec)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// DebugLevel dynamically sets the debug logging level to the passed level
|
||||
// specification.
|
||||
//
|
||||
// The levelspec can be either a debug level or of the form:
|
||||
// <subsystem>=<level>,<subsystem2>=<level2>,...
|
||||
//
|
||||
// Additionally, the special keyword 'show' can be used to get a list of the
|
||||
// available subsystems.
|
||||
//
|
||||
// NOTE: This is a btcd extension.
|
||||
func (c *Client) DebugLevel(levelSpec string) (string, error) {
|
||||
return c.DebugLevelAsync(levelSpec).Receive()
|
||||
}
|
||||
|
||||
// FutureCreateEncryptedWalletResult is a future promise to deliver the error
|
||||
// result of a CreateEncryptedWalletAsync RPC invocation.
|
||||
type FutureCreateEncryptedWalletResult chan *response
|
||||
|
||||
// Receive waits for and returns the error response promised by the future.
|
||||
func (r FutureCreateEncryptedWalletResult) Receive() error {
|
||||
_, err := receiveFuture(r)
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateEncryptedWalletAsync returns an instance of a type that can be used to
|
||||
// get the result of the RPC at some future time by invoking the Receive
|
||||
// function on the returned instance.
|
||||
//
|
||||
// See CreateEncryptedWallet for the blocking version and more details.
|
||||
//
|
||||
// NOTE: This is a btcwallet extension.
|
||||
func (c *Client) CreateEncryptedWalletAsync(passphrase string) FutureCreateEncryptedWalletResult {
|
||||
cmd := btcjson.NewCreateEncryptedWalletCmd(passphrase)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// CreateEncryptedWallet requests the creation of an encrypted wallet. Wallets
|
||||
// managed by btcwallet are only written to disk with encrypted private keys,
|
||||
// and generating wallets on the fly is impossible as it requires user input for
|
||||
// the encryption passphrase. This RPC specifies the passphrase and instructs
|
||||
// the wallet creation. This may error if a wallet is already opened, or the
|
||||
// new wallet cannot be written to disk.
|
||||
//
|
||||
// NOTE: This is a btcwallet extension.
|
||||
func (c *Client) CreateEncryptedWallet(passphrase string) error {
|
||||
return c.CreateEncryptedWalletAsync(passphrase).Receive()
|
||||
}
|
||||
|
||||
// FutureListAddressTransactionsResult is a future promise to deliver the result
|
||||
// of a ListAddressTransactionsAsync RPC invocation (or an applicable error).
|
||||
type FutureListAddressTransactionsResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns information
|
||||
// about all transactions associated with the provided addresses.
|
||||
func (r FutureListAddressTransactionsResult) Receive() ([]btcjson.ListTransactionsResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal the result as an array of listtransactions objects.
|
||||
var transactions []btcjson.ListTransactionsResult
|
||||
err = json.Unmarshal(res, &transactions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return transactions, nil
|
||||
}
|
||||
|
||||
// ListAddressTransactionsAsync returns an instance of a type that can be used
|
||||
// to get the result of the RPC at some future time by invoking the Receive
|
||||
// function on the returned instance.
|
||||
//
|
||||
// See ListAddressTransactions for the blocking version and more details.
|
||||
//
|
||||
// NOTE: This is a btcd extension.
|
||||
func (c *Client) ListAddressTransactionsAsync(addresses []btcutil.Address, account string) FutureListAddressTransactionsResult {
|
||||
// Convert addresses to strings.
|
||||
addrs := make([]string, 0, len(addresses))
|
||||
for _, addr := range addresses {
|
||||
addrs = append(addrs, addr.EncodeAddress())
|
||||
}
|
||||
cmd := btcjson.NewListAddressTransactionsCmd(addrs, &account)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// ListAddressTransactions returns information about all transactions associated
|
||||
// with the provided addresses.
|
||||
//
|
||||
// NOTE: This is a btcwallet extension.
|
||||
func (c *Client) ListAddressTransactions(addresses []btcutil.Address, account string) ([]btcjson.ListTransactionsResult, error) {
|
||||
return c.ListAddressTransactionsAsync(addresses, account).Receive()
|
||||
}
|
||||
|
||||
// FutureGetBestBlockResult is a future promise to deliver the result of a
|
||||
// GetBestBlockAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBestBlockResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the hash
|
||||
// and height of the block in the longest (best) chain.
|
||||
func (r FutureGetBestBlockResult) Receive() (*chainhash.Hash, int32, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a getbestblock result object.
|
||||
var bestBlock btcjson.GetBestBlockResult
|
||||
err = json.Unmarshal(res, &bestBlock)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Convert to hash from string.
|
||||
hash, err := chainhash.NewHashFromStr(bestBlock.Hash)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return hash, bestBlock.Height, nil
|
||||
}
|
||||
|
||||
// GetBestBlockAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetBestBlock for the blocking version and more details.
|
||||
//
|
||||
// NOTE: This is a btcd extension.
|
||||
func (c *Client) GetBestBlockAsync() FutureGetBestBlockResult {
|
||||
cmd := btcjson.NewGetBestBlockCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetBestBlock returns the hash and height of the block in the longest (best)
|
||||
// chain.
|
||||
//
|
||||
// NOTE: This is a btcd extension.
|
||||
func (c *Client) GetBestBlock() (*chainhash.Hash, int32, error) {
|
||||
return c.GetBestBlockAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetCurrentNetResult is a future promise to deliver the result of a
|
||||
// GetCurrentNetAsync RPC invocation (or an applicable error).
|
||||
type FutureGetCurrentNetResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the network
|
||||
// the server is running on.
|
||||
func (r FutureGetCurrentNetResult) Receive() (wire.BitcoinNet, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Unmarshal result as an int64.
|
||||
var net int64
|
||||
err = json.Unmarshal(res, &net)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return wire.BitcoinNet(net), nil
|
||||
}
|
||||
|
||||
// GetCurrentNetAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetCurrentNet for the blocking version and more details.
|
||||
//
|
||||
// NOTE: This is a btcd extension.
|
||||
func (c *Client) GetCurrentNetAsync() FutureGetCurrentNetResult {
|
||||
cmd := btcjson.NewGetCurrentNetCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetCurrentNet returns the network the server is running on.
|
||||
//
|
||||
// NOTE: This is a btcd extension.
|
||||
func (c *Client) GetCurrentNet() (wire.BitcoinNet, error) {
|
||||
return c.GetCurrentNetAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetHeadersResult is a future promise to deliver the result of a
|
||||
// getheaders RPC invocation (or an applicable error).
|
||||
//
|
||||
// NOTE: This is a btcsuite extension ported from
|
||||
// github.com/decred/dcrrpcclient.
|
||||
type FutureGetHeadersResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// getheaders result.
|
||||
//
|
||||
// NOTE: This is a btcsuite extension ported from
|
||||
// github.com/decred/dcrrpcclient.
|
||||
func (r FutureGetHeadersResult) Receive() ([]wire.BlockHeader, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a slice of strings.
|
||||
var result []string
|
||||
err = json.Unmarshal(res, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Deserialize the []string into []wire.BlockHeader.
|
||||
headers := make([]wire.BlockHeader, len(result))
|
||||
for i, headerHex := range result {
|
||||
serialized, err := hex.DecodeString(headerHex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = headers[i].Deserialize(bytes.NewReader(serialized))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return headers, nil
|
||||
}
|
||||
|
||||
// GetHeadersAsync returns an instance of a type that can be used to get the result
|
||||
// of the RPC at some future time by invoking the Receive function on the returned instance.
|
||||
//
|
||||
// See GetHeaders for the blocking version and more details.
|
||||
//
|
||||
// NOTE: This is a btcsuite extension ported from
|
||||
// github.com/decred/dcrrpcclient.
|
||||
func (c *Client) GetHeadersAsync(blockLocators []chainhash.Hash, hashStop *chainhash.Hash) FutureGetHeadersResult {
|
||||
locators := make([]string, len(blockLocators))
|
||||
for i := range blockLocators {
|
||||
locators[i] = blockLocators[i].String()
|
||||
}
|
||||
hash := ""
|
||||
if hashStop != nil {
|
||||
hash = hashStop.String()
|
||||
}
|
||||
cmd := btcjson.NewGetHeadersCmd(locators, hash)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetHeaders mimics the wire protocol getheaders and headers messages by
|
||||
// returning all headers on the main chain after the first known block in the
|
||||
// locators, up until a block hash matches hashStop.
|
||||
//
|
||||
// NOTE: This is a btcsuite extension ported from
|
||||
// github.com/decred/dcrrpcclient.
|
||||
func (c *Client) GetHeaders(blockLocators []chainhash.Hash, hashStop *chainhash.Hash) ([]wire.BlockHeader, error) {
|
||||
return c.GetHeadersAsync(blockLocators, hashStop).Receive()
|
||||
}
|
||||
|
||||
// FutureExportWatchingWalletResult is a future promise to deliver the result of
|
||||
// an ExportWatchingWalletAsync RPC invocation (or an applicable error).
|
||||
type FutureExportWatchingWalletResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// exported wallet.
|
||||
func (r FutureExportWatchingWalletResult) Receive() ([]byte, []byte, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a JSON object.
|
||||
var obj map[string]interface{}
|
||||
err = json.Unmarshal(res, &obj)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Check for the wallet and tx string fields in the object.
|
||||
base64Wallet, ok := obj["wallet"].(string)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("unexpected response type for "+
|
||||
"exportwatchingwallet 'wallet' field: %T\n",
|
||||
obj["wallet"])
|
||||
}
|
||||
base64TxStore, ok := obj["tx"].(string)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("unexpected response type for "+
|
||||
"exportwatchingwallet 'tx' field: %T\n",
|
||||
obj["tx"])
|
||||
}
|
||||
|
||||
walletBytes, err := base64.StdEncoding.DecodeString(base64Wallet)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
txStoreBytes, err := base64.StdEncoding.DecodeString(base64TxStore)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return walletBytes, txStoreBytes, nil
|
||||
|
||||
}
|
||||
|
||||
// ExportWatchingWalletAsync returns an instance of a type that can be used to
|
||||
// get the result of the RPC at some future time by invoking the Receive
|
||||
// function on the returned instance.
|
||||
//
|
||||
// See ExportWatchingWallet for the blocking version and more details.
|
||||
//
|
||||
// NOTE: This is a btcwallet extension.
|
||||
func (c *Client) ExportWatchingWalletAsync(account string) FutureExportWatchingWalletResult {
|
||||
cmd := btcjson.NewExportWatchingWalletCmd(&account, btcjson.Bool(true))
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// ExportWatchingWallet returns the raw bytes for a watching-only version of
|
||||
// wallet.bin and tx.bin, respectively, for the specified account that can be
|
||||
// used by btcwallet to enable a wallet which does not have the private keys
|
||||
// necessary to spend funds.
|
||||
//
|
||||
// NOTE: This is a btcwallet extension.
|
||||
func (c *Client) ExportWatchingWallet(account string) ([]byte, []byte, error) {
|
||||
return c.ExportWatchingWalletAsync(account).Receive()
|
||||
}
|
||||
|
||||
// FutureSessionResult is a future promise to deliver the result of a
|
||||
// SessionAsync RPC invocation (or an applicable error).
|
||||
type FutureSessionResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// session result.
|
||||
func (r FutureSessionResult) Receive() (*btcjson.SessionResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a session result object.
|
||||
var session btcjson.SessionResult
|
||||
err = json.Unmarshal(res, &session)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &session, nil
|
||||
}
|
||||
|
||||
// SessionAsync returns an instance of a type that can be used to get the result
|
||||
// of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See Session for the blocking version and more details.
|
||||
//
|
||||
// NOTE: This is a btcsuite extension.
|
||||
func (c *Client) SessionAsync() FutureSessionResult {
|
||||
// Not supported in HTTP POST mode.
|
||||
if c.config.HTTPPostMode {
|
||||
return newFutureError(ErrWebsocketsRequired)
|
||||
}
|
||||
|
||||
cmd := btcjson.NewSessionCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// Session returns details regarding a websocket client's current connection.
|
||||
//
|
||||
// This RPC requires the client to be running in websocket mode.
|
||||
//
|
||||
// NOTE: This is a btcsuite extension.
|
||||
func (c *Client) Session() (*btcjson.SessionResult, error) {
|
||||
return c.SessionAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureVersionResult is a future promise to delivere the result of a version
|
||||
// RPC invocation (or an applicable error).
|
||||
//
|
||||
// NOTE: This is a btcsuite extension ported from
|
||||
// github.com/decred/dcrrpcclient.
|
||||
type FutureVersionResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the version
|
||||
// result.
|
||||
//
|
||||
// NOTE: This is a btcsuite extension ported from
|
||||
// github.com/decred/dcrrpcclient.
|
||||
func (r FutureVersionResult) Receive() (map[string]btcjson.VersionResult,
|
||||
error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a version result object.
|
||||
var vr map[string]btcjson.VersionResult
|
||||
err = json.Unmarshal(res, &vr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return vr, nil
|
||||
}
|
||||
|
||||
// VersionAsync returns an instance of a type that can be used to get the result
|
||||
// of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See Version for the blocking version and more details.
|
||||
//
|
||||
// NOTE: This is a btcsuite extension ported from
|
||||
// github.com/decred/dcrrpcclient.
|
||||
func (c *Client) VersionAsync() FutureVersionResult {
|
||||
cmd := btcjson.NewVersionCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// Version returns information about the server's JSON-RPC API versions.
|
||||
//
|
||||
// NOTE: This is a btcsuite extension ported from
|
||||
// github.com/decred/dcrrpcclient.
|
||||
func (c *Client) Version() (map[string]btcjson.VersionResult, error) {
|
||||
return c.VersionAsync().Receive()
|
||||
}
|
1332
rpcclient/infrastructure.go
Normal file
1332
rpcclient/infrastructure.go
Normal file
File diff suppressed because it is too large
Load diff
47
rpcclient/log.go
Normal file
47
rpcclient/log.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) 2014-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rpcclient
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btclog"
|
||||
)
|
||||
|
||||
// log is a logger that is initialized with no output filters. This
|
||||
// means the package will not perform any logging by default until the caller
|
||||
// requests it.
|
||||
var log btclog.Logger
|
||||
|
||||
// The default amount of logging is none.
|
||||
func init() {
|
||||
DisableLog()
|
||||
}
|
||||
|
||||
// DisableLog disables all library log output. Logging output is disabled
|
||||
// by default until UseLogger is called.
|
||||
func DisableLog() {
|
||||
log = btclog.Disabled
|
||||
}
|
||||
|
||||
// UseLogger uses a specified Logger to output package logging info.
|
||||
func UseLogger(logger btclog.Logger) {
|
||||
log = logger
|
||||
}
|
||||
|
||||
// LogClosure is a closure that can be printed with %v to be used to
|
||||
// generate expensive-to-create data for a detailed log level and avoid doing
|
||||
// the work if the data isn't printed.
|
||||
type logClosure func() string
|
||||
|
||||
// String invokes the log closure and returns the results string.
|
||||
func (c logClosure) String() string {
|
||||
return c()
|
||||
}
|
||||
|
||||
// newLogClosure returns a new closure over the passed function which allows
|
||||
// it to be used as a parameter in a logging function that is only invoked when
|
||||
// the logging level is such that the message will actually be logged.
|
||||
func newLogClosure(c func() string) logClosure {
|
||||
return logClosure(c)
|
||||
}
|
417
rpcclient/mining.go
Normal file
417
rpcclient/mining.go
Normal file
|
@ -0,0 +1,417 @@
|
|||
// Copyright (c) 2014-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rpcclient
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/btcsuite/btcd/btcjson"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
// FutureGenerateResult is a future promise to deliver the result of a
|
||||
// GenerateAsync RPC invocation (or an applicable error).
|
||||
type FutureGenerateResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns a list of
|
||||
// block hashes generated by the call.
|
||||
func (r FutureGenerateResult) Receive() ([]*chainhash.Hash, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a list of strings.
|
||||
var result []string
|
||||
err = json.Unmarshal(res, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Convert each block hash to a chainhash.Hash and store a pointer to
|
||||
// each.
|
||||
convertedResult := make([]*chainhash.Hash, len(result))
|
||||
for i, hashString := range result {
|
||||
convertedResult[i], err = chainhash.NewHashFromStr(hashString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return convertedResult, nil
|
||||
}
|
||||
|
||||
// GenerateAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See Generate for the blocking version and more details.
|
||||
func (c *Client) GenerateAsync(numBlocks uint32) FutureGenerateResult {
|
||||
cmd := btcjson.NewGenerateCmd(numBlocks)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// Generate generates numBlocks blocks and returns their hashes.
|
||||
func (c *Client) Generate(numBlocks uint32) ([]*chainhash.Hash, error) {
|
||||
return c.GenerateAsync(numBlocks).Receive()
|
||||
}
|
||||
|
||||
// FutureGetGenerateResult is a future promise to deliver the result of a
|
||||
// GetGenerateAsync RPC invocation (or an applicable error).
|
||||
type FutureGetGenerateResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns true if the
|
||||
// server is set to mine, otherwise false.
|
||||
func (r FutureGetGenerateResult) Receive() (bool, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a boolean.
|
||||
var result bool
|
||||
err = json.Unmarshal(res, &result)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetGenerateAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See GetGenerate for the blocking version and more details.
|
||||
func (c *Client) GetGenerateAsync() FutureGetGenerateResult {
|
||||
cmd := btcjson.NewGetGenerateCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetGenerate returns true if the server is set to mine, otherwise false.
|
||||
func (c *Client) GetGenerate() (bool, error) {
|
||||
return c.GetGenerateAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureSetGenerateResult is a future promise to deliver the result of a
|
||||
// SetGenerateAsync RPC invocation (or an applicable error).
|
||||
type FutureSetGenerateResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns an error if
|
||||
// any occurred when setting the server to generate coins (mine) or not.
|
||||
func (r FutureSetGenerateResult) Receive() error {
|
||||
_, err := receiveFuture(r)
|
||||
return err
|
||||
}
|
||||
|
||||
// SetGenerateAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See SetGenerate for the blocking version and more details.
|
||||
func (c *Client) SetGenerateAsync(enable bool, numCPUs int) FutureSetGenerateResult {
|
||||
cmd := btcjson.NewSetGenerateCmd(enable, &numCPUs)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// SetGenerate sets the server to generate coins (mine) or not.
|
||||
func (c *Client) SetGenerate(enable bool, numCPUs int) error {
|
||||
return c.SetGenerateAsync(enable, numCPUs).Receive()
|
||||
}
|
||||
|
||||
// FutureGetHashesPerSecResult is a future promise to deliver the result of a
|
||||
// GetHashesPerSecAsync RPC invocation (or an applicable error).
|
||||
type FutureGetHashesPerSecResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns a recent
|
||||
// hashes per second performance measurement while generating coins (mining).
|
||||
// Zero is returned if the server is not mining.
|
||||
func (r FutureGetHashesPerSecResult) Receive() (int64, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
// Unmarshal result as an int64.
|
||||
var result int64
|
||||
err = json.Unmarshal(res, &result)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetHashesPerSecAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See GetHashesPerSec for the blocking version and more details.
|
||||
func (c *Client) GetHashesPerSecAsync() FutureGetHashesPerSecResult {
|
||||
cmd := btcjson.NewGetHashesPerSecCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetHashesPerSec returns a recent hashes per second performance measurement
|
||||
// while generating coins (mining). Zero is returned if the server is not
|
||||
// mining.
|
||||
func (c *Client) GetHashesPerSec() (int64, error) {
|
||||
return c.GetHashesPerSecAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetMiningInfoResult is a future promise to deliver the result of a
|
||||
// GetMiningInfoAsync RPC invocation (or an applicable error).
|
||||
type FutureGetMiningInfoResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the mining
|
||||
// information.
|
||||
func (r FutureGetMiningInfoResult) Receive() (*btcjson.GetMiningInfoResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a getmininginfo result object.
|
||||
var infoResult btcjson.GetMiningInfoResult
|
||||
err = json.Unmarshal(res, &infoResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &infoResult, nil
|
||||
}
|
||||
|
||||
// GetMiningInfoAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See GetMiningInfo for the blocking version and more details.
|
||||
func (c *Client) GetMiningInfoAsync() FutureGetMiningInfoResult {
|
||||
cmd := btcjson.NewGetMiningInfoCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetMiningInfo returns mining information.
|
||||
func (c *Client) GetMiningInfo() (*btcjson.GetMiningInfoResult, error) {
|
||||
return c.GetMiningInfoAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetNetworkHashPS is a future promise to deliver the result of a
|
||||
// GetNetworkHashPSAsync RPC invocation (or an applicable error).
|
||||
type FutureGetNetworkHashPS chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// estimated network hashes per second for the block heights provided by the
|
||||
// parameters.
|
||||
func (r FutureGetNetworkHashPS) Receive() (int64, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
// Unmarshal result as an int64.
|
||||
var result int64
|
||||
err = json.Unmarshal(res, &result)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetNetworkHashPSAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See GetNetworkHashPS for the blocking version and more details.
|
||||
func (c *Client) GetNetworkHashPSAsync() FutureGetNetworkHashPS {
|
||||
cmd := btcjson.NewGetNetworkHashPSCmd(nil, nil)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetNetworkHashPS returns the estimated network hashes per second using the
|
||||
// default number of blocks and the most recent block height.
|
||||
//
|
||||
// See GetNetworkHashPS2 to override the number of blocks to use and
|
||||
// GetNetworkHashPS3 to override the height at which to calculate the estimate.
|
||||
func (c *Client) GetNetworkHashPS() (int64, error) {
|
||||
return c.GetNetworkHashPSAsync().Receive()
|
||||
}
|
||||
|
||||
// GetNetworkHashPS2Async returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See GetNetworkHashPS2 for the blocking version and more details.
|
||||
func (c *Client) GetNetworkHashPS2Async(blocks int) FutureGetNetworkHashPS {
|
||||
cmd := btcjson.NewGetNetworkHashPSCmd(&blocks, nil)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetNetworkHashPS2 returns the estimated network hashes per second for the
|
||||
// specified previous number of blocks working backwards from the most recent
|
||||
// block height. The blocks parameter can also be -1 in which case the number
|
||||
// of blocks since the last difficulty change will be used.
|
||||
//
|
||||
// See GetNetworkHashPS to use defaults and GetNetworkHashPS3 to override the
|
||||
// height at which to calculate the estimate.
|
||||
func (c *Client) GetNetworkHashPS2(blocks int) (int64, error) {
|
||||
return c.GetNetworkHashPS2Async(blocks).Receive()
|
||||
}
|
||||
|
||||
// GetNetworkHashPS3Async returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See GetNetworkHashPS3 for the blocking version and more details.
|
||||
func (c *Client) GetNetworkHashPS3Async(blocks, height int) FutureGetNetworkHashPS {
|
||||
cmd := btcjson.NewGetNetworkHashPSCmd(&blocks, &height)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetNetworkHashPS3 returns the estimated network hashes per second for the
|
||||
// specified previous number of blocks working backwards from the specified
|
||||
// block height. The blocks parameter can also be -1 in which case the number
|
||||
// of blocks since the last difficulty change will be used.
|
||||
//
|
||||
// See GetNetworkHashPS and GetNetworkHashPS2 to use defaults.
|
||||
func (c *Client) GetNetworkHashPS3(blocks, height int) (int64, error) {
|
||||
return c.GetNetworkHashPS3Async(blocks, height).Receive()
|
||||
}
|
||||
|
||||
// FutureGetWork is a future promise to deliver the result of a
|
||||
// GetWorkAsync RPC invocation (or an applicable error).
|
||||
type FutureGetWork chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the hash
|
||||
// data to work on.
|
||||
func (r FutureGetWork) Receive() (*btcjson.GetWorkResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a getwork result object.
|
||||
var result btcjson.GetWorkResult
|
||||
err = json.Unmarshal(res, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetWorkAsync returns an instance of a type that can be used to get the result
|
||||
// of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetWork for the blocking version and more details.
|
||||
func (c *Client) GetWorkAsync() FutureGetWork {
|
||||
cmd := btcjson.NewGetWorkCmd(nil)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetWork returns hash data to work on.
|
||||
//
|
||||
// See GetWorkSubmit to submit the found solution.
|
||||
func (c *Client) GetWork() (*btcjson.GetWorkResult, error) {
|
||||
return c.GetWorkAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetWorkSubmit is a future promise to deliver the result of a
|
||||
// GetWorkSubmitAsync RPC invocation (or an applicable error).
|
||||
type FutureGetWorkSubmit chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns whether
|
||||
// or not the submitted block header was accepted.
|
||||
func (r FutureGetWorkSubmit) Receive() (bool, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a boolean.
|
||||
var accepted bool
|
||||
err = json.Unmarshal(res, &accepted)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return accepted, nil
|
||||
}
|
||||
|
||||
// GetWorkSubmitAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetWorkSubmit for the blocking version and more details.
|
||||
func (c *Client) GetWorkSubmitAsync(data string) FutureGetWorkSubmit {
|
||||
cmd := btcjson.NewGetWorkCmd(&data)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetWorkSubmit submits a block header which is a solution to previously
|
||||
// requested data and returns whether or not the solution was accepted.
|
||||
//
|
||||
// See GetWork to request data to work on.
|
||||
func (c *Client) GetWorkSubmit(data string) (bool, error) {
|
||||
return c.GetWorkSubmitAsync(data).Receive()
|
||||
}
|
||||
|
||||
// FutureSubmitBlockResult is a future promise to deliver the result of a
|
||||
// SubmitBlockAsync RPC invocation (or an applicable error).
|
||||
type FutureSubmitBlockResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns an error if
|
||||
// any occurred when submitting the block.
|
||||
func (r FutureSubmitBlockResult) Receive() error {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if string(res) != "null" {
|
||||
var result string
|
||||
err = json.Unmarshal(res, &result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return errors.New(result)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// SubmitBlockAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See SubmitBlock for the blocking version and more details.
|
||||
func (c *Client) SubmitBlockAsync(block *btcutil.Block, options *btcjson.SubmitBlockOptions) FutureSubmitBlockResult {
|
||||
blockHex := ""
|
||||
if block != nil {
|
||||
blockBytes, err := block.Bytes()
|
||||
if err != nil {
|
||||
return newFutureError(err)
|
||||
}
|
||||
|
||||
blockHex = hex.EncodeToString(blockBytes)
|
||||
}
|
||||
|
||||
cmd := btcjson.NewSubmitBlockCmd(blockHex, options)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// SubmitBlock attempts to submit a new block into the bitcoin network.
|
||||
func (c *Client) SubmitBlock(block *btcutil.Block, options *btcjson.SubmitBlockOptions) error {
|
||||
return c.SubmitBlockAsync(block, options).Receive()
|
||||
}
|
||||
|
||||
// TODO(davec): Implement GetBlockTemplate
|
285
rpcclient/net.go
Normal file
285
rpcclient/net.go
Normal file
|
@ -0,0 +1,285 @@
|
|||
// Copyright (c) 2014-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rpcclient
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/btcsuite/btcd/btcjson"
|
||||
)
|
||||
|
||||
// AddNodeCommand enumerates the available commands that the AddNode function
|
||||
// accepts.
|
||||
type AddNodeCommand string
|
||||
|
||||
// Constants used to indicate the command for the AddNode function.
|
||||
const (
|
||||
// ANAdd indicates the specified host should be added as a persistent
|
||||
// peer.
|
||||
ANAdd AddNodeCommand = "add"
|
||||
|
||||
// ANRemove indicates the specified peer should be removed.
|
||||
ANRemove AddNodeCommand = "remove"
|
||||
|
||||
// ANOneTry indicates the specified host should try to connect once,
|
||||
// but it should not be made persistent.
|
||||
ANOneTry AddNodeCommand = "onetry"
|
||||
)
|
||||
|
||||
// String returns the AddNodeCommand in human-readable form.
|
||||
func (cmd AddNodeCommand) String() string {
|
||||
return string(cmd)
|
||||
}
|
||||
|
||||
// FutureAddNodeResult is a future promise to deliver the result of an
|
||||
// AddNodeAsync RPC invocation (or an applicable error).
|
||||
type FutureAddNodeResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns an error if
|
||||
// any occurred when performing the specified command.
|
||||
func (r FutureAddNodeResult) Receive() error {
|
||||
_, err := receiveFuture(r)
|
||||
return err
|
||||
}
|
||||
|
||||
// AddNodeAsync returns an instance of a type that can be used to get the result
|
||||
// of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See AddNode for the blocking version and more details.
|
||||
func (c *Client) AddNodeAsync(host string, command AddNodeCommand) FutureAddNodeResult {
|
||||
cmd := btcjson.NewAddNodeCmd(host, btcjson.AddNodeSubCmd(command))
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// AddNode attempts to perform the passed command on the passed persistent peer.
|
||||
// For example, it can be used to add or a remove a persistent peer, or to do
|
||||
// a one time connection to a peer.
|
||||
//
|
||||
// It may not be used to remove non-persistent peers.
|
||||
func (c *Client) AddNode(host string, command AddNodeCommand) error {
|
||||
return c.AddNodeAsync(host, command).Receive()
|
||||
}
|
||||
|
||||
// FutureGetAddedNodeInfoResult is a future promise to deliver the result of a
|
||||
// GetAddedNodeInfoAsync RPC invocation (or an applicable error).
|
||||
type FutureGetAddedNodeInfoResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns information
|
||||
// about manually added (persistent) peers.
|
||||
func (r FutureGetAddedNodeInfoResult) Receive() ([]btcjson.GetAddedNodeInfoResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal as an array of getaddednodeinfo result objects.
|
||||
var nodeInfo []btcjson.GetAddedNodeInfoResult
|
||||
err = json.Unmarshal(res, &nodeInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nodeInfo, nil
|
||||
}
|
||||
|
||||
// GetAddedNodeInfoAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See GetAddedNodeInfo for the blocking version and more details.
|
||||
func (c *Client) GetAddedNodeInfoAsync(peer string) FutureGetAddedNodeInfoResult {
|
||||
cmd := btcjson.NewGetAddedNodeInfoCmd(true, &peer)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetAddedNodeInfo returns information about manually added (persistent) peers.
|
||||
//
|
||||
// See GetAddedNodeInfoNoDNS to retrieve only a list of the added (persistent)
|
||||
// peers.
|
||||
func (c *Client) GetAddedNodeInfo(peer string) ([]btcjson.GetAddedNodeInfoResult, error) {
|
||||
return c.GetAddedNodeInfoAsync(peer).Receive()
|
||||
}
|
||||
|
||||
// FutureGetAddedNodeInfoNoDNSResult is a future promise to deliver the result
|
||||
// of a GetAddedNodeInfoNoDNSAsync RPC invocation (or an applicable error).
|
||||
type FutureGetAddedNodeInfoNoDNSResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns a list of
|
||||
// manually added (persistent) peers.
|
||||
func (r FutureGetAddedNodeInfoNoDNSResult) Receive() ([]string, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as an array of strings.
|
||||
var nodes []string
|
||||
err = json.Unmarshal(res, &nodes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
// GetAddedNodeInfoNoDNSAsync returns an instance of a type that can be used to
|
||||
// get the result of the RPC at some future time by invoking the Receive
|
||||
// function on the returned instance.
|
||||
//
|
||||
// See GetAddedNodeInfoNoDNS for the blocking version and more details.
|
||||
func (c *Client) GetAddedNodeInfoNoDNSAsync(peer string) FutureGetAddedNodeInfoNoDNSResult {
|
||||
cmd := btcjson.NewGetAddedNodeInfoCmd(false, &peer)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetAddedNodeInfoNoDNS returns a list of manually added (persistent) peers.
|
||||
// This works by setting the dns flag to false in the underlying RPC.
|
||||
//
|
||||
// See GetAddedNodeInfo to obtain more information about each added (persistent)
|
||||
// peer.
|
||||
func (c *Client) GetAddedNodeInfoNoDNS(peer string) ([]string, error) {
|
||||
return c.GetAddedNodeInfoNoDNSAsync(peer).Receive()
|
||||
}
|
||||
|
||||
// FutureGetConnectionCountResult is a future promise to deliver the result
|
||||
// of a GetConnectionCountAsync RPC invocation (or an applicable error).
|
||||
type FutureGetConnectionCountResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the number
|
||||
// of active connections to other peers.
|
||||
func (r FutureGetConnectionCountResult) Receive() (int64, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Unmarshal result as an int64.
|
||||
var count int64
|
||||
err = json.Unmarshal(res, &count)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// GetConnectionCountAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See GetConnectionCount for the blocking version and more details.
|
||||
func (c *Client) GetConnectionCountAsync() FutureGetConnectionCountResult {
|
||||
cmd := btcjson.NewGetConnectionCountCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetConnectionCount returns the number of active connections to other peers.
|
||||
func (c *Client) GetConnectionCount() (int64, error) {
|
||||
return c.GetConnectionCountAsync().Receive()
|
||||
}
|
||||
|
||||
// FuturePingResult is a future promise to deliver the result of a PingAsync RPC
|
||||
// invocation (or an applicable error).
|
||||
type FuturePingResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the result
|
||||
// of queueing a ping to be sent to each connected peer.
|
||||
func (r FuturePingResult) Receive() error {
|
||||
_, err := receiveFuture(r)
|
||||
return err
|
||||
}
|
||||
|
||||
// PingAsync returns an instance of a type that can be used to get the result of
|
||||
// the RPC at some future time by invoking the Receive function on the returned
|
||||
// instance.
|
||||
//
|
||||
// See Ping for the blocking version and more details.
|
||||
func (c *Client) PingAsync() FuturePingResult {
|
||||
cmd := btcjson.NewPingCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// Ping queues a ping to be sent to each connected peer.
|
||||
//
|
||||
// Use the GetPeerInfo function and examine the PingTime and PingWait fields to
|
||||
// access the ping times.
|
||||
func (c *Client) Ping() error {
|
||||
return c.PingAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetPeerInfoResult is a future promise to deliver the result of a
|
||||
// GetPeerInfoAsync RPC invocation (or an applicable error).
|
||||
type FutureGetPeerInfoResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns data about
|
||||
// each connected network peer.
|
||||
func (r FutureGetPeerInfoResult) Receive() ([]btcjson.GetPeerInfoResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as an array of getpeerinfo result objects.
|
||||
var peerInfo []btcjson.GetPeerInfoResult
|
||||
err = json.Unmarshal(res, &peerInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return peerInfo, nil
|
||||
}
|
||||
|
||||
// GetPeerInfoAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetPeerInfo for the blocking version and more details.
|
||||
func (c *Client) GetPeerInfoAsync() FutureGetPeerInfoResult {
|
||||
cmd := btcjson.NewGetPeerInfoCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetPeerInfo returns data about each connected network peer.
|
||||
func (c *Client) GetPeerInfo() ([]btcjson.GetPeerInfoResult, error) {
|
||||
return c.GetPeerInfoAsync().Receive()
|
||||
}
|
||||
|
||||
// FutureGetNetTotalsResult is a future promise to deliver the result of a
|
||||
// GetNetTotalsAsync RPC invocation (or an applicable error).
|
||||
type FutureGetNetTotalsResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns network
|
||||
// traffic statistics.
|
||||
func (r FutureGetNetTotalsResult) Receive() (*btcjson.GetNetTotalsResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a getnettotals result object.
|
||||
var totals btcjson.GetNetTotalsResult
|
||||
err = json.Unmarshal(res, &totals)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &totals, nil
|
||||
}
|
||||
|
||||
// GetNetTotalsAsync returns an instance of a type that can be used to get the
|
||||
// result of the RPC at some future time by invoking the Receive function on the
|
||||
// returned instance.
|
||||
//
|
||||
// See GetNetTotals for the blocking version and more details.
|
||||
func (c *Client) GetNetTotalsAsync() FutureGetNetTotalsResult {
|
||||
cmd := btcjson.NewGetNetTotalsCmd()
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetNetTotals returns network traffic statistics.
|
||||
func (c *Client) GetNetTotals() (*btcjson.GetNetTotalsResult, error) {
|
||||
return c.GetNetTotalsAsync().Receive()
|
||||
}
|
1357
rpcclient/notify.go
Normal file
1357
rpcclient/notify.go
Normal file
File diff suppressed because it is too large
Load diff
78
rpcclient/rawrequest.go
Normal file
78
rpcclient/rawrequest.go
Normal file
|
@ -0,0 +1,78 @@
|
|||
// Copyright (c) 2014-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rpcclient
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/btcsuite/btcd/btcjson"
|
||||
)
|
||||
|
||||
// FutureRawResult is a future promise to deliver the result of a RawRequest RPC
|
||||
// invocation (or an applicable error).
|
||||
type FutureRawResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the raw
|
||||
// response, or an error if the request was unsuccessful.
|
||||
func (r FutureRawResult) Receive() (json.RawMessage, error) {
|
||||
return receiveFuture(r)
|
||||
}
|
||||
|
||||
// RawRequestAsync returns an instance of a type that can be used to get the
|
||||
// result of a custom RPC request at some future time by invoking the Receive
|
||||
// function on the returned instance.
|
||||
//
|
||||
// See RawRequest for the blocking version and more details.
|
||||
func (c *Client) RawRequestAsync(method string, params []json.RawMessage) FutureRawResult {
|
||||
// Method may not be empty.
|
||||
if method == "" {
|
||||
return newFutureError(errors.New("no method"))
|
||||
}
|
||||
|
||||
// Marshal parameters as "[]" instead of "null" when no parameters
|
||||
// are passed.
|
||||
if params == nil {
|
||||
params = []json.RawMessage{}
|
||||
}
|
||||
|
||||
// Create a raw JSON-RPC request using the provided method and params
|
||||
// and marshal it. This is done rather than using the sendCmd function
|
||||
// since that relies on marshalling registered btcjson commands rather
|
||||
// than custom commands.
|
||||
id := c.NextID()
|
||||
rawRequest := &btcjson.Request{
|
||||
Jsonrpc: "1.0",
|
||||
ID: id,
|
||||
Method: method,
|
||||
Params: params,
|
||||
}
|
||||
marshalledJSON, err := json.Marshal(rawRequest)
|
||||
if err != nil {
|
||||
return newFutureError(err)
|
||||
}
|
||||
|
||||
// Generate the request and send it along with a channel to respond on.
|
||||
responseChan := make(chan *response, 1)
|
||||
jReq := &jsonRequest{
|
||||
id: id,
|
||||
method: method,
|
||||
cmd: nil,
|
||||
marshalledJSON: marshalledJSON,
|
||||
responseChan: responseChan,
|
||||
}
|
||||
c.sendRequest(jReq)
|
||||
|
||||
return responseChan
|
||||
}
|
||||
|
||||
// RawRequest allows the caller to send a raw or custom request to the server.
|
||||
// This method may be used to send and receive requests and responses for
|
||||
// requests that are not handled by this client package, or to proxy partially
|
||||
// unmarshaled requests to another JSON-RPC server if a request cannot be
|
||||
// handled directly.
|
||||
func (c *Client) RawRequest(method string, params []json.RawMessage) (json.RawMessage, error) {
|
||||
return c.RawRequestAsync(method, params).Receive()
|
||||
}
|
626
rpcclient/rawtransactions.go
Normal file
626
rpcclient/rawtransactions.go
Normal file
|
@ -0,0 +1,626 @@
|
|||
// Copyright (c) 2014-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package rpcclient
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/btcsuite/btcd/btcjson"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
// SigHashType enumerates the available signature hashing types that the
|
||||
// SignRawTransaction function accepts.
|
||||
type SigHashType string
|
||||
|
||||
// Constants used to indicate the signature hash type for SignRawTransaction.
|
||||
const (
|
||||
// SigHashAll indicates ALL of the outputs should be signed.
|
||||
SigHashAll SigHashType = "ALL"
|
||||
|
||||
// SigHashNone indicates NONE of the outputs should be signed. This
|
||||
// can be thought of as specifying the signer does not care where the
|
||||
// bitcoins go.
|
||||
SigHashNone SigHashType = "NONE"
|
||||
|
||||
// SigHashSingle indicates that a SINGLE output should be signed. This
|
||||
// can be thought of specifying the signer only cares about where ONE of
|
||||
// the outputs goes, but not any of the others.
|
||||
SigHashSingle SigHashType = "SINGLE"
|
||||
|
||||
// SigHashAllAnyoneCanPay indicates that signer does not care where the
|
||||
// other inputs to the transaction come from, so it allows other people
|
||||
// to add inputs. In addition, it uses the SigHashAll signing method
|
||||
// for outputs.
|
||||
SigHashAllAnyoneCanPay SigHashType = "ALL|ANYONECANPAY"
|
||||
|
||||
// SigHashNoneAnyoneCanPay indicates that signer does not care where the
|
||||
// other inputs to the transaction come from, so it allows other people
|
||||
// to add inputs. In addition, it uses the SigHashNone signing method
|
||||
// for outputs.
|
||||
SigHashNoneAnyoneCanPay SigHashType = "NONE|ANYONECANPAY"
|
||||
|
||||
// SigHashSingleAnyoneCanPay indicates that signer does not care where
|
||||
// the other inputs to the transaction come from, so it allows other
|
||||
// people to add inputs. In addition, it uses the SigHashSingle signing
|
||||
// method for outputs.
|
||||
SigHashSingleAnyoneCanPay SigHashType = "SINGLE|ANYONECANPAY"
|
||||
)
|
||||
|
||||
// String returns the SighHashType in human-readable form.
|
||||
func (s SigHashType) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
// FutureGetRawTransactionResult is a future promise to deliver the result of a
|
||||
// GetRawTransactionAsync RPC invocation (or an applicable error).
|
||||
type FutureGetRawTransactionResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns a
|
||||
// transaction given its hash.
|
||||
func (r FutureGetRawTransactionResult) Receive() (*btcutil.Tx, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a string.
|
||||
var txHex string
|
||||
err = json.Unmarshal(res, &txHex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Decode the serialized transaction hex to raw bytes.
|
||||
serializedTx, err := hex.DecodeString(txHex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Deserialize the transaction and return it.
|
||||
var msgTx wire.MsgTx
|
||||
if err := msgTx.Deserialize(bytes.NewReader(serializedTx)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return btcutil.NewTx(&msgTx), nil
|
||||
}
|
||||
|
||||
// GetRawTransactionAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See GetRawTransaction for the blocking version and more details.
|
||||
func (c *Client) GetRawTransactionAsync(txHash *chainhash.Hash) FutureGetRawTransactionResult {
|
||||
hash := ""
|
||||
if txHash != nil {
|
||||
hash = txHash.String()
|
||||
}
|
||||
|
||||
cmd := btcjson.NewGetRawTransactionCmd(hash, btcjson.Int(0))
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetRawTransaction returns a transaction given its hash.
|
||||
//
|
||||
// See GetRawTransactionVerbose to obtain additional information about the
|
||||
// transaction.
|
||||
func (c *Client) GetRawTransaction(txHash *chainhash.Hash) (*btcutil.Tx, error) {
|
||||
return c.GetRawTransactionAsync(txHash).Receive()
|
||||
}
|
||||
|
||||
// FutureGetRawTransactionVerboseResult is a future promise to deliver the
|
||||
// result of a GetRawTransactionVerboseAsync RPC invocation (or an applicable
|
||||
// error).
|
||||
type FutureGetRawTransactionVerboseResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns information
|
||||
// about a transaction given its hash.
|
||||
func (r FutureGetRawTransactionVerboseResult) Receive() (*btcjson.TxRawResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a gettrawtransaction result object.
|
||||
var rawTxResult btcjson.TxRawResult
|
||||
err = json.Unmarshal(res, &rawTxResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &rawTxResult, nil
|
||||
}
|
||||
|
||||
// GetRawTransactionVerboseAsync returns an instance of a type that can be used
|
||||
// to get the result of the RPC at some future time by invoking the Receive
|
||||
// function on the returned instance.
|
||||
//
|
||||
// See GetRawTransactionVerbose for the blocking version and more details.
|
||||
func (c *Client) GetRawTransactionVerboseAsync(txHash *chainhash.Hash) FutureGetRawTransactionVerboseResult {
|
||||
hash := ""
|
||||
if txHash != nil {
|
||||
hash = txHash.String()
|
||||
}
|
||||
|
||||
cmd := btcjson.NewGetRawTransactionCmd(hash, btcjson.Int(1))
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// GetRawTransactionVerbose returns information about a transaction given
|
||||
// its hash.
|
||||
//
|
||||
// See GetRawTransaction to obtain only the transaction already deserialized.
|
||||
func (c *Client) GetRawTransactionVerbose(txHash *chainhash.Hash) (*btcjson.TxRawResult, error) {
|
||||
return c.GetRawTransactionVerboseAsync(txHash).Receive()
|
||||
}
|
||||
|
||||
// FutureDecodeRawTransactionResult is a future promise to deliver the result
|
||||
// of a DecodeRawTransactionAsync RPC invocation (or an applicable error).
|
||||
type FutureDecodeRawTransactionResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns information
|
||||
// about a transaction given its serialized bytes.
|
||||
func (r FutureDecodeRawTransactionResult) Receive() (*btcjson.TxRawResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a decoderawtransaction result object.
|
||||
var rawTxResult btcjson.TxRawResult
|
||||
err = json.Unmarshal(res, &rawTxResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &rawTxResult, nil
|
||||
}
|
||||
|
||||
// DecodeRawTransactionAsync returns an instance of a type that can be used to
|
||||
// get the result of the RPC at some future time by invoking the Receive
|
||||
// function on the returned instance.
|
||||
//
|
||||
// See DecodeRawTransaction for the blocking version and more details.
|
||||
func (c *Client) DecodeRawTransactionAsync(serializedTx []byte) FutureDecodeRawTransactionResult {
|
||||
txHex := hex.EncodeToString(serializedTx)
|
||||
cmd := btcjson.NewDecodeRawTransactionCmd(txHex)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// DecodeRawTransaction returns information about a transaction given its
|
||||
// serialized bytes.
|
||||
func (c *Client) DecodeRawTransaction(serializedTx []byte) (*btcjson.TxRawResult, error) {
|
||||
return c.DecodeRawTransactionAsync(serializedTx).Receive()
|
||||
}
|
||||
|
||||
// FutureCreateRawTransactionResult is a future promise to deliver the result
|
||||
// of a CreateRawTransactionAsync RPC invocation (or an applicable error).
|
||||
type FutureCreateRawTransactionResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns a new
|
||||
// transaction spending the provided inputs and sending to the provided
|
||||
// addresses.
|
||||
func (r FutureCreateRawTransactionResult) Receive() (*wire.MsgTx, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a string.
|
||||
var txHex string
|
||||
err = json.Unmarshal(res, &txHex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Decode the serialized transaction hex to raw bytes.
|
||||
serializedTx, err := hex.DecodeString(txHex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Deserialize the transaction and return it.
|
||||
var msgTx wire.MsgTx
|
||||
if err := msgTx.Deserialize(bytes.NewReader(serializedTx)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &msgTx, nil
|
||||
}
|
||||
|
||||
// CreateRawTransactionAsync returns an instance of a type that can be used to
|
||||
// get the result of the RPC at some future time by invoking the Receive
|
||||
// function on the returned instance.
|
||||
//
|
||||
// See CreateRawTransaction for the blocking version and more details.
|
||||
func (c *Client) CreateRawTransactionAsync(inputs []btcjson.TransactionInput,
|
||||
amounts map[btcutil.Address]btcutil.Amount, lockTime *int64) FutureCreateRawTransactionResult {
|
||||
|
||||
convertedAmts := make(map[string]float64, len(amounts))
|
||||
for addr, amount := range amounts {
|
||||
convertedAmts[addr.String()] = amount.ToBTC()
|
||||
}
|
||||
cmd := btcjson.NewCreateRawTransactionCmd(inputs, convertedAmts, lockTime)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// CreateRawTransaction returns a new transaction spending the provided inputs
|
||||
// and sending to the provided addresses.
|
||||
func (c *Client) CreateRawTransaction(inputs []btcjson.TransactionInput,
|
||||
amounts map[btcutil.Address]btcutil.Amount, lockTime *int64) (*wire.MsgTx, error) {
|
||||
|
||||
return c.CreateRawTransactionAsync(inputs, amounts, lockTime).Receive()
|
||||
}
|
||||
|
||||
// FutureSendRawTransactionResult is a future promise to deliver the result
|
||||
// of a SendRawTransactionAsync RPC invocation (or an applicable error).
|
||||
type FutureSendRawTransactionResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the result
|
||||
// of submitting the encoded transaction to the server which then relays it to
|
||||
// the network.
|
||||
func (r FutureSendRawTransactionResult) Receive() (*chainhash.Hash, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal result as a string.
|
||||
var txHashStr string
|
||||
err = json.Unmarshal(res, &txHashStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return chainhash.NewHashFromStr(txHashStr)
|
||||
}
|
||||
|
||||
// SendRawTransactionAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See SendRawTransaction for the blocking version and more details.
|
||||
func (c *Client) SendRawTransactionAsync(tx *wire.MsgTx, allowHighFees bool) FutureSendRawTransactionResult {
|
||||
txHex := ""
|
||||
if tx != nil {
|
||||
// Serialize the transaction and convert to hex string.
|
||||
buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
|
||||
if err := tx.Serialize(buf); err != nil {
|
||||
return newFutureError(err)
|
||||
}
|
||||
txHex = hex.EncodeToString(buf.Bytes())
|
||||
}
|
||||
|
||||
cmd := btcjson.NewSendRawTransactionCmd(txHex, &allowHighFees)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// SendRawTransaction submits the encoded transaction to the server which will
|
||||
// then relay it to the network.
|
||||
func (c *Client) SendRawTransaction(tx *wire.MsgTx, allowHighFees bool) (*chainhash.Hash, error) {
|
||||
return c.SendRawTransactionAsync(tx, allowHighFees).Receive()
|
||||
}
|
||||
|
||||
// FutureSignRawTransactionResult is a future promise to deliver the result
|
||||
// of one of the SignRawTransactionAsync family of RPC invocations (or an
|
||||
// applicable error).
|
||||
type FutureSignRawTransactionResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// signed transaction as well as whether or not all inputs are now signed.
|
||||
func (r FutureSignRawTransactionResult) Receive() (*wire.MsgTx, bool, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Unmarshal as a signrawtransaction result.
|
||||
var signRawTxResult btcjson.SignRawTransactionResult
|
||||
err = json.Unmarshal(res, &signRawTxResult)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Decode the serialized transaction hex to raw bytes.
|
||||
serializedTx, err := hex.DecodeString(signRawTxResult.Hex)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Deserialize the transaction and return it.
|
||||
var msgTx wire.MsgTx
|
||||
if err := msgTx.Deserialize(bytes.NewReader(serializedTx)); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
return &msgTx, signRawTxResult.Complete, nil
|
||||
}
|
||||
|
||||
// SignRawTransactionAsync returns an instance of a type that can be used to get
|
||||
// the result of the RPC at some future time by invoking the Receive function on
|
||||
// the returned instance.
|
||||
//
|
||||
// See SignRawTransaction for the blocking version and more details.
|
||||
func (c *Client) SignRawTransactionAsync(tx *wire.MsgTx) FutureSignRawTransactionResult {
|
||||
txHex := ""
|
||||
if tx != nil {
|
||||
// Serialize the transaction and convert to hex string.
|
||||
buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
|
||||
if err := tx.Serialize(buf); err != nil {
|
||||
return newFutureError(err)
|
||||
}
|
||||
txHex = hex.EncodeToString(buf.Bytes())
|
||||
}
|
||||
|
||||
cmd := btcjson.NewSignRawTransactionCmd(txHex, nil, nil, nil)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// SignRawTransaction signs inputs for the passed transaction and returns the
|
||||
// signed transaction as well as whether or not all inputs are now signed.
|
||||
//
|
||||
// This function assumes the RPC server already knows the input transactions and
|
||||
// private keys for the passed transaction which needs to be signed and uses the
|
||||
// default signature hash type. Use one of the SignRawTransaction# variants to
|
||||
// specify that information if needed.
|
||||
func (c *Client) SignRawTransaction(tx *wire.MsgTx) (*wire.MsgTx, bool, error) {
|
||||
return c.SignRawTransactionAsync(tx).Receive()
|
||||
}
|
||||
|
||||
// SignRawTransaction2Async returns an instance of a type that can be used to
|
||||
// get the result of the RPC at some future time by invoking the Receive
|
||||
// function on the returned instance.
|
||||
//
|
||||
// See SignRawTransaction2 for the blocking version and more details.
|
||||
func (c *Client) SignRawTransaction2Async(tx *wire.MsgTx, inputs []btcjson.RawTxInput) FutureSignRawTransactionResult {
|
||||
txHex := ""
|
||||
if tx != nil {
|
||||
// Serialize the transaction and convert to hex string.
|
||||
buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
|
||||
if err := tx.Serialize(buf); err != nil {
|
||||
return newFutureError(err)
|
||||
}
|
||||
txHex = hex.EncodeToString(buf.Bytes())
|
||||
}
|
||||
|
||||
cmd := btcjson.NewSignRawTransactionCmd(txHex, &inputs, nil, nil)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// SignRawTransaction2 signs inputs for the passed transaction given the list
|
||||
// of information about the input transactions needed to perform the signing
|
||||
// process.
|
||||
//
|
||||
// This only input transactions that need to be specified are ones the
|
||||
// RPC server does not already know. Already known input transactions will be
|
||||
// merged with the specified transactions.
|
||||
//
|
||||
// See SignRawTransaction if the RPC server already knows the input
|
||||
// transactions.
|
||||
func (c *Client) SignRawTransaction2(tx *wire.MsgTx, inputs []btcjson.RawTxInput) (*wire.MsgTx, bool, error) {
|
||||
return c.SignRawTransaction2Async(tx, inputs).Receive()
|
||||
}
|
||||
|
||||
// SignRawTransaction3Async returns an instance of a type that can be used to
|
||||
// get the result of the RPC at some future time by invoking the Receive
|
||||
// function on the returned instance.
|
||||
//
|
||||
// See SignRawTransaction3 for the blocking version and more details.
|
||||
func (c *Client) SignRawTransaction3Async(tx *wire.MsgTx,
|
||||
inputs []btcjson.RawTxInput,
|
||||
privKeysWIF []string) FutureSignRawTransactionResult {
|
||||
|
||||
txHex := ""
|
||||
if tx != nil {
|
||||
// Serialize the transaction and convert to hex string.
|
||||
buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
|
||||
if err := tx.Serialize(buf); err != nil {
|
||||
return newFutureError(err)
|
||||
}
|
||||
txHex = hex.EncodeToString(buf.Bytes())
|
||||
}
|
||||
|
||||
cmd := btcjson.NewSignRawTransactionCmd(txHex, &inputs, &privKeysWIF,
|
||||
nil)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// SignRawTransaction3 signs inputs for the passed transaction given the list
|
||||
// of information about extra input transactions and a list of private keys
|
||||
// needed to perform the signing process. The private keys must be in wallet
|
||||
// import format (WIF).
|
||||
//
|
||||
// This only input transactions that need to be specified are ones the
|
||||
// RPC server does not already know. Already known input transactions will be
|
||||
// merged with the specified transactions. This means the list of transaction
|
||||
// inputs can be nil if the RPC server already knows them all.
|
||||
//
|
||||
// NOTE: Unlike the merging functionality of the input transactions, ONLY the
|
||||
// specified private keys will be used, so even if the server already knows some
|
||||
// of the private keys, they will NOT be used.
|
||||
//
|
||||
// See SignRawTransaction if the RPC server already knows the input
|
||||
// transactions and private keys or SignRawTransaction2 if it already knows the
|
||||
// private keys.
|
||||
func (c *Client) SignRawTransaction3(tx *wire.MsgTx,
|
||||
inputs []btcjson.RawTxInput,
|
||||
privKeysWIF []string) (*wire.MsgTx, bool, error) {
|
||||
|
||||
return c.SignRawTransaction3Async(tx, inputs, privKeysWIF).Receive()
|
||||
}
|
||||
|
||||
// SignRawTransaction4Async returns an instance of a type that can be used to
|
||||
// get the result of the RPC at some future time by invoking the Receive
|
||||
// function on the returned instance.
|
||||
//
|
||||
// See SignRawTransaction4 for the blocking version and more details.
|
||||
func (c *Client) SignRawTransaction4Async(tx *wire.MsgTx,
|
||||
inputs []btcjson.RawTxInput, privKeysWIF []string,
|
||||
hashType SigHashType) FutureSignRawTransactionResult {
|
||||
|
||||
txHex := ""
|
||||
if tx != nil {
|
||||
// Serialize the transaction and convert to hex string.
|
||||
buf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
|
||||
if err := tx.Serialize(buf); err != nil {
|
||||
return newFutureError(err)
|
||||
}
|
||||
txHex = hex.EncodeToString(buf.Bytes())
|
||||
}
|
||||
|
||||
cmd := btcjson.NewSignRawTransactionCmd(txHex, &inputs, &privKeysWIF,
|
||||
btcjson.String(string(hashType)))
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// SignRawTransaction4 signs inputs for the passed transaction using the
|
||||
// the specified signature hash type given the list of information about extra
|
||||
// input transactions and a potential list of private keys needed to perform
|
||||
// the signing process. The private keys, if specified, must be in wallet
|
||||
// import format (WIF).
|
||||
//
|
||||
// The only input transactions that need to be specified are ones the RPC server
|
||||
// does not already know. This means the list of transaction inputs can be nil
|
||||
// if the RPC server already knows them all.
|
||||
//
|
||||
// NOTE: Unlike the merging functionality of the input transactions, ONLY the
|
||||
// specified private keys will be used, so even if the server already knows some
|
||||
// of the private keys, they will NOT be used. The list of private keys can be
|
||||
// nil in which case any private keys the RPC server knows will be used.
|
||||
//
|
||||
// This function should only used if a non-default signature hash type is
|
||||
// desired. Otherwise, see SignRawTransaction if the RPC server already knows
|
||||
// the input transactions and private keys, SignRawTransaction2 if it already
|
||||
// knows the private keys, or SignRawTransaction3 if it does not know both.
|
||||
func (c *Client) SignRawTransaction4(tx *wire.MsgTx,
|
||||
inputs []btcjson.RawTxInput, privKeysWIF []string,
|
||||
hashType SigHashType) (*wire.MsgTx, bool, error) {
|
||||
|
||||
return c.SignRawTransaction4Async(tx, inputs, privKeysWIF,
|
||||
hashType).Receive()
|
||||
}
|
||||
|
||||
// FutureSearchRawTransactionsResult is a future promise to deliver the result
|
||||
// of the SearchRawTransactionsAsync RPC invocation (or an applicable error).
|
||||
type FutureSearchRawTransactionsResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// found raw transactions.
|
||||
func (r FutureSearchRawTransactionsResult) Receive() ([]*wire.MsgTx, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal as an array of strings.
|
||||
var searchRawTxnsResult []string
|
||||
err = json.Unmarshal(res, &searchRawTxnsResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Decode and deserialize each transaction.
|
||||
msgTxns := make([]*wire.MsgTx, 0, len(searchRawTxnsResult))
|
||||
for _, hexTx := range searchRawTxnsResult {
|
||||
// Decode the serialized transaction hex to raw bytes.
|
||||
serializedTx, err := hex.DecodeString(hexTx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Deserialize the transaction and add it to the result slice.
|
||||
var msgTx wire.MsgTx
|
||||
err = msgTx.Deserialize(bytes.NewReader(serializedTx))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msgTxns = append(msgTxns, &msgTx)
|
||||
}
|
||||
|
||||
return msgTxns, nil
|
||||
}
|
||||
|
||||
// SearchRawTransactionsAsync returns an instance of a type that can be used to
|
||||
// get the result of the RPC at some future time by invoking the Receive
|
||||
// function on the returned instance.
|
||||
//
|
||||
// See SearchRawTransactions for the blocking version and more details.
|
||||
func (c *Client) SearchRawTransactionsAsync(address btcutil.Address, skip, count int, reverse bool, filterAddrs []string) FutureSearchRawTransactionsResult {
|
||||
addr := address.EncodeAddress()
|
||||
verbose := btcjson.Int(0)
|
||||
cmd := btcjson.NewSearchRawTransactionsCmd(addr, verbose, &skip, &count,
|
||||
nil, &reverse, &filterAddrs)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// SearchRawTransactions returns transactions that involve the passed address.
|
||||
//
|
||||
// NOTE: Chain servers do not typically provide this capability unless it has
|
||||
// specifically been enabled.
|
||||
//
|
||||
// See SearchRawTransactionsVerbose to retrieve a list of data structures with
|
||||
// information about the transactions instead of the transactions themselves.
|
||||
func (c *Client) SearchRawTransactions(address btcutil.Address, skip, count int, reverse bool, filterAddrs []string) ([]*wire.MsgTx, error) {
|
||||
return c.SearchRawTransactionsAsync(address, skip, count, reverse, filterAddrs).Receive()
|
||||
}
|
||||
|
||||
// FutureSearchRawTransactionsVerboseResult is a future promise to deliver the
|
||||
// result of the SearchRawTransactionsVerboseAsync RPC invocation (or an
|
||||
// applicable error).
|
||||
type FutureSearchRawTransactionsVerboseResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// found raw transactions.
|
||||
func (r FutureSearchRawTransactionsVerboseResult) Receive() ([]*btcjson.SearchRawTransactionsResult, error) {
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal as an array of raw transaction results.
|
||||
var result []*btcjson.SearchRawTransactionsResult
|
||||
err = json.Unmarshal(res, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SearchRawTransactionsVerboseAsync returns an instance of a type that can be
|
||||
// used to get the result of the RPC at some future time by invoking the Receive
|
||||
// function on the returned instance.
|
||||
//
|
||||
// See SearchRawTransactionsVerbose for the blocking version and more details.
|
||||
func (c *Client) SearchRawTransactionsVerboseAsync(address btcutil.Address, skip,
|
||||
count int, includePrevOut, reverse bool, filterAddrs *[]string) FutureSearchRawTransactionsVerboseResult {
|
||||
|
||||
addr := address.EncodeAddress()
|
||||
verbose := btcjson.Int(1)
|
||||
var prevOut *int
|
||||
if includePrevOut {
|
||||
prevOut = btcjson.Int(1)
|
||||
}
|
||||
cmd := btcjson.NewSearchRawTransactionsCmd(addr, verbose, &skip, &count,
|
||||
prevOut, &reverse, filterAddrs)
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// SearchRawTransactionsVerbose returns a list of data structures that describe
|
||||
// transactions which involve the passed address.
|
||||
//
|
||||
// NOTE: Chain servers do not typically provide this capability unless it has
|
||||
// specifically been enabled.
|
||||
//
|
||||
// See SearchRawTransactions to retrieve a list of raw transactions instead.
|
||||
func (c *Client) SearchRawTransactionsVerbose(address btcutil.Address, skip,
|
||||
count int, includePrevOut, reverse bool, filterAddrs []string) ([]*btcjson.SearchRawTransactionsResult, error) {
|
||||
|
||||
return c.SearchRawTransactionsVerboseAsync(address, skip, count,
|
||||
includePrevOut, reverse, &filterAddrs).Receive()
|
||||
}
|
2241
rpcclient/wallet.go
Normal file
2241
rpcclient/wallet.go
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue