mirror of
https://github.com/btcsuite/btcd.git
synced 2024-11-19 01:40:07 +01:00
Add custom/raw request/response support.
This commit is contained in:
parent
793e66c785
commit
1ec6dde39c
141
chain.go
141
chain.go
@ -7,7 +7,7 @@ package btcrpcclient
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
"github.com/conformal/btcjson"
|
||||
"github.com/conformal/btcutil"
|
||||
"github.com/conformal/btcwire"
|
||||
@ -15,23 +15,22 @@ import (
|
||||
|
||||
// FutureGetBestBlockHashResult is a future promise to deliver the result of a
|
||||
// GetBestBlockAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBestBlockHashResult chan *futureResult
|
||||
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() (*btcwire.ShaHash, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
txHashStr, ok := reply.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getbestblockhash: %T\n", reply)
|
||||
// Unmarshal result as a string.
|
||||
var txHashStr string
|
||||
err = json.Unmarshal(res, &txHashStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return btcwire.NewShaHashFromStr(txHashStr)
|
||||
}
|
||||
|
||||
@ -58,21 +57,21 @@ func (c *Client) GetBestBlockHash() (*btcwire.ShaHash, error) {
|
||||
|
||||
// FutureGetBlockResult is a future promise to deliver the result of a
|
||||
// GetBlockAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBlockResult chan *futureResult
|
||||
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() (*btcutil.Block, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
blockHex, ok := reply.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getblock (verbose=0): %T\n", reply)
|
||||
// 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.
|
||||
@ -120,24 +119,23 @@ func (c *Client) GetBlock(blockHash *btcwire.ShaHash) (*btcutil.Block, error) {
|
||||
|
||||
// FutureGetBlockVerboseResult is a future promise to deliver the result of a
|
||||
// GetBlockVerboseAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBlockVerboseResult chan *futureResult
|
||||
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.BlockResult, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
blockResult, ok := reply.(*btcjson.BlockResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getblock (verbose=1): %T\n", reply)
|
||||
// Unmarshal the raw result into a BlockResult.
|
||||
var blockResult btcjson.BlockResult
|
||||
err = json.Unmarshal(res, &blockResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return blockResult, nil
|
||||
return &blockResult, nil
|
||||
}
|
||||
|
||||
// GetBlockVerboseAsync returns an instance of a type that can be used to get
|
||||
@ -170,24 +168,23 @@ func (c *Client) GetBlockVerbose(blockHash *btcwire.ShaHash, verboseTx bool) (*b
|
||||
|
||||
// FutureGetBlockCountResult is a future promise to deliver the result of a
|
||||
// GetBlockCountAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBlockCountResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
count, ok := reply.(float64)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("unexpected response type for "+
|
||||
"getblockcount: %T\n", reply)
|
||||
// Unmarshal the result as an int64.
|
||||
var count int64
|
||||
err = json.Unmarshal(res, &count)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return int64(count), nil
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// GetBlockCountAsync returns an instance of a type that can be used to get the
|
||||
@ -212,23 +209,22 @@ func (c *Client) GetBlockCount() (int64, error) {
|
||||
|
||||
// FutureGetDifficultyResult is a future promise to deliver the result of a
|
||||
// GetDifficultyAsync RPC invocation (or an applicable error).
|
||||
type FutureGetDifficultyResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
difficulty, ok := reply.(float64)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("unexpected response type for "+
|
||||
"getdifficulty: %T\n", reply)
|
||||
// Unmarshal the result as a float64.
|
||||
var difficulty float64
|
||||
err = json.Unmarshal(res, &difficulty)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return difficulty, nil
|
||||
}
|
||||
|
||||
@ -255,23 +251,22 @@ func (c *Client) GetDifficulty() (float64, error) {
|
||||
|
||||
// FutureGetBlockHashResult is a future promise to deliver the result of a
|
||||
// GetBlockHashAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBlockHashResult chan *futureResult
|
||||
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() (*btcwire.ShaHash, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
txHashStr, ok := reply.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getblockhash: %T\n", reply)
|
||||
// Unmarshal the result as a string-encoded sha.
|
||||
var txHashStr string
|
||||
err = json.Unmarshal(res, &txHashStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return btcwire.NewShaHashFromStr(txHashStr)
|
||||
}
|
||||
|
||||
@ -298,23 +293,24 @@ func (c *Client) GetBlockHash(blockHeight int64) (*btcwire.ShaHash, error) {
|
||||
|
||||
// FutureGetRawMempoolResult is a future promise to deliver the result of a
|
||||
// GetRawMempoolAsync RPC invocation (or an applicable error).
|
||||
type FutureGetRawMempoolResult chan *futureResult
|
||||
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() ([]*btcwire.ShaHash, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
txHashStrs, ok := reply.([]string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getrawmempool (verbose=false): %T\n", reply)
|
||||
// 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([]*btcwire.ShaHash, 0, len(txHashStrs))
|
||||
for _, hashStr := range txHashStrs {
|
||||
txHash, err := btcwire.NewShaHashFromStr(hashStr)
|
||||
@ -352,24 +348,24 @@ func (c *Client) GetRawMempool() ([]*btcwire.ShaHash, error) {
|
||||
|
||||
// FutureGetRawMempoolVerboseResult is a future promise to deliver the result of
|
||||
// a GetRawMempoolVerboseAsync RPC invocation (or an applicable error).
|
||||
type FutureGetRawMempoolVerboseResult chan *futureResult
|
||||
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.GetRawMempoolResult, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
mempoolItems, ok := reply.(map[string]btcjson.GetRawMempoolResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getrawmempool (verbose=true): %T\n", reply)
|
||||
// Unmarshal the result as a map of strings (tx shas) to their detailed
|
||||
// results.
|
||||
var mempoolItems map[string]btcjson.GetRawMempoolResult
|
||||
err = json.Unmarshal(res, &mempoolItems)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return mempoolItems, nil
|
||||
}
|
||||
|
||||
@ -400,24 +396,23 @@ func (c *Client) GetRawMempoolVerbose() (map[string]btcjson.GetRawMempoolResult,
|
||||
// FutureVerifyChainResult is a future promise to deliver the result of a
|
||||
// VerifyChainAsync, VerifyChainLevelAsyncRPC, or VerifyChainBlocksAsync
|
||||
// invocation (or an applicable error).
|
||||
type FutureVerifyChainResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
verified, ok := reply.(bool)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("unexpected response type for "+
|
||||
"verifychain: %T\n", reply)
|
||||
// Unmarshal the result as a boolean.
|
||||
var verified bool
|
||||
err = json.Unmarshal(res, &verified)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return verified, nil
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ package btcrpcclient
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/conformal/btcjson"
|
||||
"github.com/conformal/btcutil"
|
||||
@ -15,24 +16,23 @@ import (
|
||||
|
||||
// FutureDebugLevelResult is a future promise to deliver the result of a
|
||||
// DebugLevelAsync RPC invocation (or an applicable error).
|
||||
type FutureDebugLevelResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("unexpected response type for "+
|
||||
"debuglevel: %T\n", reply)
|
||||
// Unmashal the result as a string.
|
||||
var result string
|
||||
err = json.Unmarshal(res, &result)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ func (c *Client) DebugLevel(levelSpec string) (string, error) {
|
||||
|
||||
// FutureCreateEncryptedWalletResult is a future promise to deliver the error
|
||||
// result of a CreateEncryptedWalletAsync RPC invocation.
|
||||
type FutureCreateEncryptedWalletResult chan *futureResult
|
||||
type FutureCreateEncryptedWalletResult chan *response
|
||||
|
||||
// Receive waits for and returns the error response promised by the future.
|
||||
func (r FutureCreateEncryptedWalletResult) Receive() error {
|
||||
@ -104,28 +104,22 @@ func (c *Client) CreateEncryptedWallet(passphrase string) error {
|
||||
|
||||
// FutureListAddressTransactionsResult is a future promise to deliver the result
|
||||
// of a ListAddressTransactionsAsync RPC invocation (or an applicable error).
|
||||
type FutureListAddressTransactionsResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// No transactions.
|
||||
if reply == nil {
|
||||
return nil, nil
|
||||
// Unmarshal the result as an array of listtransactions objects.
|
||||
var transactions []btcjson.ListTransactionsResult
|
||||
err = json.Unmarshal(res, &transactions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
transactions, ok := reply.([]btcjson.ListTransactionsResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"listaddresstransactions: %T\n", reply)
|
||||
}
|
||||
|
||||
return transactions, nil
|
||||
}
|
||||
|
||||
@ -161,30 +155,30 @@ func (c *Client) ListAddressTransactions(addresses []btcutil.Address, account st
|
||||
|
||||
// FutureGetBestBlockResult is a future promise to deliver the result of a
|
||||
// GetBestBlockAsync RPC invocation (or an applicable error).
|
||||
type FutureGetBestBlockResult chan *futureResult
|
||||
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() (*btcwire.ShaHash, int32, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.(*btcws.GetBestBlockResult)
|
||||
if !ok {
|
||||
return nil, 0, fmt.Errorf("unexpected response type for "+
|
||||
"getbestblock: %T\n", reply)
|
||||
// Unmarsal result as a getbestblock result object.
|
||||
var bestBlock btcws.GetBestBlockResult
|
||||
err = json.Unmarshal(res, &bestBlock)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Convert hash string.
|
||||
hash, err := btcwire.NewShaHashFromStr(result.Hash)
|
||||
hash, err := btcwire.NewShaHashFromStr(bestBlock.Hash)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return hash, result.Height, nil
|
||||
return hash, bestBlock.Height, nil
|
||||
}
|
||||
|
||||
// GetBestBlockAsync returns an instance of a type that can be used to get the
|
||||
@ -211,24 +205,24 @@ func (c *Client) GetBestBlock() (*btcwire.ShaHash, int32, error) {
|
||||
|
||||
// FutureGetCurrentNetResult is a future promise to deliver the result of a
|
||||
// GetCurrentNetAsync RPC invocation (or an applicable error).
|
||||
type FutureGetCurrentNetResult chan *futureResult
|
||||
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() (btcwire.BitcoinNet, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
fnet, ok := reply.(float64)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("unexpected response type for "+
|
||||
"getcurrentnet: %T\n", reply)
|
||||
// Unmarshal result as an int64.
|
||||
var net int64
|
||||
err = json.Unmarshal(res, &net)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return btcwire.BitcoinNet(fnet), nil
|
||||
return btcwire.BitcoinNet(net), nil
|
||||
}
|
||||
|
||||
// GetCurrentNetAsync returns an instance of a type that can be used to get the
|
||||
@ -254,34 +248,35 @@ func (c *Client) GetCurrentNet() (btcwire.BitcoinNet, error) {
|
||||
|
||||
// FutureExportWatchingWalletResult is a future promise to deliver the result of
|
||||
// an ExportWatchingWalletAsync RPC invocation (or an applicable error).
|
||||
type FutureExportWatchingWalletResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("unexpected response type for "+
|
||||
"exportwatchingwallet: %T\n", reply)
|
||||
// Unmarshal result as a JSON object.
|
||||
var obj map[string]interface{}
|
||||
err = json.Unmarshal(res, &obj)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
base64Wallet, ok := result["wallet"].(string)
|
||||
// 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",
|
||||
result["wallet"])
|
||||
obj["wallet"])
|
||||
}
|
||||
base64TxStore, ok := result["tx"].(string)
|
||||
base64TxStore, ok := obj["tx"].(string)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("unexpected response type for "+
|
||||
"exportwatchingwallet 'tx' field: %T\n",
|
||||
result["tx"])
|
||||
obj["tx"])
|
||||
}
|
||||
|
||||
walletBytes, err := base64.StdEncoding.DecodeString(base64Wallet)
|
||||
|
@ -64,27 +64,20 @@ const (
|
||||
connectionRetryInterval = time.Second * 5
|
||||
)
|
||||
|
||||
// futureResult holds information about a future promise to deliver the result
|
||||
// of an asynchronous request.
|
||||
type futureResult struct {
|
||||
reply *btcjson.Reply
|
||||
err error
|
||||
}
|
||||
|
||||
// sendPostDetails houses an HTTP POST request to send to an RPC server as well
|
||||
// as the original JSON-RPC command and a channel to reply on when the server
|
||||
// responds with the result.
|
||||
type sendPostDetails struct {
|
||||
command btcjson.Cmd
|
||||
request *http.Request
|
||||
responseChan chan *futureResult
|
||||
responseChan chan *response
|
||||
}
|
||||
|
||||
// jsonRequest holds information about a json request that is used to properly
|
||||
// detect, interpret, and deliver a reply to it.
|
||||
type jsonRequest struct {
|
||||
cmd btcjson.Cmd
|
||||
responseChan chan *futureResult
|
||||
responseChan chan *response
|
||||
}
|
||||
|
||||
// Client represents a Bitcoin RPC client which allows easy access to the
|
||||
@ -231,70 +224,96 @@ func (c *Client) trackRegisteredNtfns(cmd btcjson.Cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
// handleMessage is the main handler for incoming requests. It enforces
|
||||
// authentication, parses the incoming json, looks up and executes handlers
|
||||
// (including pass through for standard RPC commands), sends the appropriate
|
||||
// response. It also detects commands which are marked as long-running and
|
||||
// sends them off to the asyncHander for processing.
|
||||
type (
|
||||
// inMessage is the first type that an incoming message is unmarshaled
|
||||
// into. It supports both requests (for notification support) and
|
||||
// responses. The partially-unmarshaled message is a notification if
|
||||
// the embedded ID (from the response) is nil. Otherwise, it is a
|
||||
// response.
|
||||
inMessage struct {
|
||||
ID *uint64 `json:"id"`
|
||||
*rawNotification
|
||||
*rawResponse
|
||||
}
|
||||
|
||||
// rawNotification is a partially-unmarshaled JSON-RPC notification.
|
||||
rawNotification struct {
|
||||
Method string `json:"method"`
|
||||
Params []json.RawMessage `json:"params"`
|
||||
}
|
||||
|
||||
// rawResponse is a partially-unmarshaled JSON-RPC response. For this
|
||||
// to be valid (according to JSON-RPC 1.0 spec), ID may not be nil.
|
||||
rawResponse struct {
|
||||
Result json.RawMessage `json:"result"`
|
||||
Error *btcjson.Error `json:"error"`
|
||||
}
|
||||
)
|
||||
|
||||
// response is the raw bytes of a JSON-RPC result, or the error if the response
|
||||
// error object was non-null.
|
||||
type response struct {
|
||||
result []byte
|
||||
err error
|
||||
}
|
||||
|
||||
// result checks whether the unmarshaled response contains a non-nil error,
|
||||
// returning an unmarshaled btcjson.Error (or an unmarshaling error) if so.
|
||||
// If the response is not an error, the raw bytes of the request are
|
||||
// returned for further unmashaling into specific result types.
|
||||
func (r rawResponse) result() (result []byte, err error) {
|
||||
if r.Error != nil {
|
||||
return nil, r.Error
|
||||
}
|
||||
return r.Result, nil
|
||||
}
|
||||
|
||||
// handleMessage is the main handler for incoming notifications and responses.
|
||||
func (c *Client) handleMessage(msg []byte) {
|
||||
// Attempt to unmarshal the message as a known JSON-RPC command.
|
||||
if cmd, err := btcjson.ParseMarshaledCmd(msg); err == nil {
|
||||
// Commands that have an ID associated with them are not
|
||||
// notifications. Since this is a client, it should not
|
||||
// be receiving non-notifications.
|
||||
if cmd.Id() != nil {
|
||||
// Invalid response
|
||||
log.Warnf("Remote server sent a non-notification "+
|
||||
"JSON-RPC Request (Id: %v)", cmd.Id())
|
||||
// Attempt to unmarshal the message as either a notifiation or response.
|
||||
in := inMessage{}
|
||||
err := json.Unmarshal(msg, &in)
|
||||
if err != nil {
|
||||
log.Warnf("Remote server sent invalid message: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// JSON-RPC 1.0 notifications are requests with a null id.
|
||||
if in.ID == nil {
|
||||
ntfn := in.rawNotification
|
||||
if ntfn == nil {
|
||||
log.Warn("Malformed notification: missing " +
|
||||
"method and parameters")
|
||||
return
|
||||
}
|
||||
if ntfn.Method == "" {
|
||||
log.Warn("Malformed notification: missing method")
|
||||
return
|
||||
}
|
||||
// params are not optional: nil isn't valid (but len == 0 is)
|
||||
if ntfn.Params == nil {
|
||||
log.Warn("Malformed notification: missing params")
|
||||
return
|
||||
}
|
||||
|
||||
// Deliver the notification.
|
||||
log.Tracef("Received notification [%s]", cmd.Method())
|
||||
c.handleNotification(cmd)
|
||||
log.Tracef("Received notification [%s]", in.Method)
|
||||
c.handleNotification(in.rawNotification)
|
||||
return
|
||||
}
|
||||
|
||||
// The message was not a command/notification, so it should be a reply
|
||||
// to a previous request.
|
||||
|
||||
var r btcjson.Reply
|
||||
if err := json.Unmarshal([]byte(msg), &r); err != nil {
|
||||
log.Warnf("Unable to unmarshal inbound message as " +
|
||||
"notification or response")
|
||||
if in.rawResponse == nil {
|
||||
log.Warn("Malformed response: missing result and error")
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure the reply has an id.
|
||||
if r.Id == nil {
|
||||
log.Warnf("Received response with no id")
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure the id is the expected type.
|
||||
fid, ok := (*r.Id).(float64)
|
||||
if !ok {
|
||||
log.Warnf("Received unexpected id type: %T (value %v)",
|
||||
*r.Id, *r.Id)
|
||||
return
|
||||
}
|
||||
id := uint64(fid)
|
||||
log.Tracef("Received response for id %d (result %v)", id, r.Result)
|
||||
id := *in.ID
|
||||
log.Tracef("Received response for id %d (result %s)", id, in.Result)
|
||||
request := c.removeRequest(id)
|
||||
|
||||
// Nothing more to do if there is no request associated with this reply.
|
||||
if request == nil || request.responseChan == nil {
|
||||
log.Warnf("Received unexpected reply: %s (id %d)", r.Result, id)
|
||||
return
|
||||
}
|
||||
|
||||
// Unmarshal the reply into a concrete result if possible and deliver
|
||||
// it to the associated channel.
|
||||
reply, err := btcjson.ReadResultCmd(request.cmd.Method(), []byte(msg))
|
||||
if err != nil {
|
||||
log.Warnf("Failed to unmarshal reply to command [%s] "+
|
||||
"(id %d): %v", request.cmd.Method(), id, err)
|
||||
request.responseChan <- &futureResult{reply: nil, err: err}
|
||||
log.Warnf("Received unexpected reply: %s (id %d)", in.Result,
|
||||
id)
|
||||
return
|
||||
}
|
||||
|
||||
@ -303,8 +322,9 @@ func (c *Client) handleMessage(msg []byte) {
|
||||
// can automatically be re-established on reconnect.
|
||||
c.trackRegisteredNtfns(request.cmd)
|
||||
|
||||
// Deliver the reply.
|
||||
request.responseChan <- &futureResult{reply: &reply, err: nil}
|
||||
// Deliver the response.
|
||||
result, err := in.rawResponse.result()
|
||||
request.responseChan <- &response{result: result, err: err}
|
||||
}
|
||||
|
||||
// wsInHandler handles all incoming messages for the websocket connection
|
||||
@ -576,24 +596,17 @@ func (c *Client) handleSendPostMessage(details *sendPostDetails) {
|
||||
log.Tracef("Sending command [%s] with id %d", cmd.Method(), cmd.Id())
|
||||
httpResponse, err := c.httpClient.Do(details.request)
|
||||
if err != nil {
|
||||
details.responseChan <- &futureResult{reply: nil, err: err}
|
||||
details.responseChan <- &response{result: nil, err: err}
|
||||
return
|
||||
}
|
||||
|
||||
// Read the raw bytes and close the response.
|
||||
respBytes, err := btcjson.GetRaw(httpResponse.Body)
|
||||
resp, err := btcjson.GetRaw(httpResponse.Body)
|
||||
if err != nil {
|
||||
details.responseChan <- &futureResult{reply: nil, err: err}
|
||||
details.responseChan <- &response{result: nil, err: err}
|
||||
return
|
||||
}
|
||||
|
||||
// Unmarshal the reply into a concrete result if possible.
|
||||
reply, err := btcjson.ReadResultCmd(cmd.Method(), respBytes)
|
||||
if err != nil {
|
||||
details.responseChan <- &futureResult{reply: nil, err: err}
|
||||
return
|
||||
}
|
||||
details.responseChan <- &futureResult{reply: &reply, err: nil}
|
||||
details.responseChan <- &response{result: resp, err: nil}
|
||||
}
|
||||
|
||||
// sendPostHandler handles all outgoing messages when the client is running
|
||||
@ -620,9 +633,9 @@ cleanup:
|
||||
for {
|
||||
select {
|
||||
case details := <-c.sendPostChan:
|
||||
details.responseChan <- &futureResult{
|
||||
reply: nil,
|
||||
err: ErrClientShutdown,
|
||||
details.responseChan <- &response{
|
||||
result: nil,
|
||||
err: ErrClientShutdown,
|
||||
}
|
||||
|
||||
default:
|
||||
@ -637,17 +650,17 @@ cleanup:
|
||||
// sendPostRequest sends the passed HTTP request to the RPC server using the
|
||||
// HTTP client associated with the client. It is backed by a buffered channel,
|
||||
// so it will not block until the send channel is full.
|
||||
func (c *Client) sendPostRequest(req *http.Request, command btcjson.Cmd, responseChan chan *futureResult) {
|
||||
func (c *Client) sendPostRequest(req *http.Request, command btcjson.Cmd, responseChan chan *response) {
|
||||
// Don't send the message if shutting down.
|
||||
select {
|
||||
case <-c.shutdown:
|
||||
responseChan <- &futureResult{reply: nil, err: ErrClientShutdown}
|
||||
responseChan <- &response{result: nil, err: ErrClientShutdown}
|
||||
default:
|
||||
}
|
||||
|
||||
c.sendPostChan <- &sendPostDetails{
|
||||
request: req,
|
||||
command: command,
|
||||
request: req,
|
||||
responseChan: responseChan,
|
||||
}
|
||||
}
|
||||
@ -655,9 +668,9 @@ func (c *Client) sendPostRequest(req *http.Request, command btcjson.Cmd, respons
|
||||
// newFutureError returns a new future result channel that already has the
|
||||
// passed error waitin on the channel with the reply set to nil. This is useful
|
||||
// to easily return errors from the various Async functions.
|
||||
func newFutureError(err error) chan *futureResult {
|
||||
responseChan := make(chan *futureResult, 1)
|
||||
responseChan <- &futureResult{err: err}
|
||||
func newFutureError(err error) chan *response {
|
||||
responseChan := make(chan *response, 1)
|
||||
responseChan <- &response{err: err}
|
||||
return responseChan
|
||||
}
|
||||
|
||||
@ -665,27 +678,10 @@ func newFutureError(err error) chan *futureResult {
|
||||
// reply or any errors. The examined errors include an error in the
|
||||
// futureResult and the error in the reply from the server. This will block
|
||||
// until the result is available on the passed channel.
|
||||
func receiveFuture(responseChan chan *futureResult) (interface{}, error) {
|
||||
func receiveFuture(f chan *response) ([]byte, error) {
|
||||
// Wait for a response on the returned channel.
|
||||
response := <-responseChan
|
||||
if response.err != nil {
|
||||
return nil, response.err
|
||||
}
|
||||
|
||||
// At this point, the command was either sent to the server and
|
||||
// there is a response from it, or it is intentionally a nil result
|
||||
// used to bybass sends for cases such a requesting notifications when
|
||||
// there are no handlers.
|
||||
reply := response.reply
|
||||
if reply == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if reply.Error != nil {
|
||||
return nil, reply.Error
|
||||
}
|
||||
|
||||
return reply.Result, nil
|
||||
r := <-f
|
||||
return r.result, r.err
|
||||
}
|
||||
|
||||
// marshalAndSendPost marshals the passed command to JSON-RPC and sends it to
|
||||
@ -694,10 +690,10 @@ func receiveFuture(responseChan chan *futureResult) (interface{}, error) {
|
||||
// and closed for each command when using this method, however, the underlying
|
||||
// HTTP client might coalesce multiple commands depending on several factors
|
||||
// including the remote server configuration.
|
||||
func (c *Client) marshalAndSendPost(cmd btcjson.Cmd, responseChan chan *futureResult) {
|
||||
func (c *Client) marshalAndSendPost(cmd btcjson.Cmd, responseChan chan *response) {
|
||||
marshalledJSON, err := json.Marshal(cmd)
|
||||
if err != nil {
|
||||
responseChan <- &futureResult{reply: nil, err: err}
|
||||
responseChan <- &response{result: nil, err: err}
|
||||
return
|
||||
}
|
||||
|
||||
@ -709,7 +705,7 @@ func (c *Client) marshalAndSendPost(cmd btcjson.Cmd, responseChan chan *futureRe
|
||||
url := protocol + "://" + c.config.Host
|
||||
req, err := http.NewRequest("POST", url, bytes.NewReader(marshalledJSON))
|
||||
if err != nil {
|
||||
responseChan <- &futureResult{reply: nil, err: err}
|
||||
responseChan <- &response{result: nil, err: err}
|
||||
return
|
||||
}
|
||||
req.Close = true
|
||||
@ -724,10 +720,10 @@ func (c *Client) marshalAndSendPost(cmd btcjson.Cmd, responseChan chan *futureRe
|
||||
|
||||
// marshalAndSend marshals the passed command to JSON-RPC and sends it to the
|
||||
// server. It returns a response channel on which the reply will be delivered.
|
||||
func (c *Client) marshalAndSend(cmd btcjson.Cmd, responseChan chan *futureResult) {
|
||||
marshalledJSON, err := json.Marshal(cmd)
|
||||
func (c *Client) marshalAndSend(cmd btcjson.Cmd, responseChan chan *response) {
|
||||
marshalledJSON, err := cmd.MarshalJSON()
|
||||
if err != nil {
|
||||
responseChan <- &futureResult{reply: nil, err: err}
|
||||
responseChan <- &response{result: nil, err: err}
|
||||
return
|
||||
}
|
||||
|
||||
@ -739,12 +735,12 @@ func (c *Client) marshalAndSend(cmd btcjson.Cmd, responseChan chan *futureResult
|
||||
// response channel on which the reply will be deliver at some point in the
|
||||
// future. It handles both websocket and HTTP POST mode depending on the
|
||||
// configuration of the client.
|
||||
func (c *Client) sendCmd(cmd btcjson.Cmd) chan *futureResult {
|
||||
func (c *Client) sendCmd(cmd btcjson.Cmd) chan *response {
|
||||
// Choose which marshal and send function to use depending on whether
|
||||
// the client running in HTTP POST mode or not. When running in HTTP
|
||||
// POST mode, the command is issued via an HTTP client. Otherwise,
|
||||
// the command is issued via the asynchronous websocket channels.
|
||||
responseChan := make(chan *futureResult, 1)
|
||||
responseChan := make(chan *response, 1)
|
||||
if c.config.HttpPostMode {
|
||||
c.marshalAndSendPost(cmd, responseChan)
|
||||
return responseChan
|
||||
@ -804,9 +800,9 @@ func (c *Client) Disconnect() {
|
||||
c.requestLock.Lock()
|
||||
for e := c.requestList.Front(); e != nil; e = e.Next() {
|
||||
req := e.Value.(*jsonRequest)
|
||||
req.responseChan <- &futureResult{
|
||||
reply: nil,
|
||||
err: ErrClientDisconnect,
|
||||
req.responseChan <- &response{
|
||||
result: nil,
|
||||
err: ErrClientDisconnect,
|
||||
}
|
||||
}
|
||||
c.requestLock.Unlock()
|
||||
@ -834,9 +830,9 @@ func (c *Client) Shutdown() {
|
||||
c.requestLock.Lock()
|
||||
for e := c.requestList.Front(); e != nil; e = e.Next() {
|
||||
req := e.Value.(*jsonRequest)
|
||||
req.responseChan <- &futureResult{
|
||||
reply: nil,
|
||||
err: ErrClientShutdown,
|
||||
req.responseChan <- &response{
|
||||
result: nil,
|
||||
err: ErrClientShutdown,
|
||||
}
|
||||
}
|
||||
c.requestLock.Unlock()
|
||||
|
94
mining.go
94
mining.go
@ -6,28 +6,28 @@ package btcrpcclient
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
"github.com/conformal/btcjson"
|
||||
"github.com/conformal/btcutil"
|
||||
)
|
||||
|
||||
// FutureGetGenerateResult is a future promise to deliver the result of a
|
||||
// GetGenerateAsync RPC invocation (or an applicable error).
|
||||
type FutureGetGenerateResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.(bool)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("unexpected response type for "+
|
||||
"getgenerate: %T\n", reply)
|
||||
// Unmarshal result as a boolean.
|
||||
var result bool
|
||||
err = json.Unmarshal(res, &result)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
@ -55,7 +55,7 @@ func (c *Client) GetGenerate() (bool, error) {
|
||||
|
||||
// FutureSetGenerateResult is a future promise to deliver the result of a
|
||||
// SetGenerateAsync RPC invocation (or an applicable error).
|
||||
type FutureSetGenerateResult chan *futureResult
|
||||
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.
|
||||
@ -90,22 +90,22 @@ func (c *Client) SetGenerate(enable bool, numCPUs int) error {
|
||||
|
||||
// FutureGetHashesPerSecResult is a future promise to deliver the result of a
|
||||
// GetHashesPerSecAsync RPC invocation (or an applicable error).
|
||||
type FutureGetHashesPerSecResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.(int64)
|
||||
if !ok {
|
||||
return -1, fmt.Errorf("unexpected response type for "+
|
||||
"getnetworkhashps: %T\n", reply)
|
||||
// Unmarshal result as an int64.
|
||||
var result int64
|
||||
err = json.Unmarshal(res, &result)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
@ -135,24 +135,24 @@ func (c *Client) GetHashesPerSec() (int64, error) {
|
||||
|
||||
// FutureGetMiningInfoResult is a future promise to deliver the result of a
|
||||
// GetMiningInfoAsync RPC invocation (or an applicable error).
|
||||
type FutureGetMiningInfoResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.(*btcjson.GetMiningInfoResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getmininginfo: %T\n", reply)
|
||||
// Unmarshal result as a getmininginfo result object.
|
||||
var infoResult btcjson.GetMiningInfoResult
|
||||
err = json.Unmarshal(res, &infoResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return &infoResult, nil
|
||||
}
|
||||
|
||||
// GetMiningInfoAsync returns an instance of a type that can be used to get
|
||||
@ -177,22 +177,22 @@ func (c *Client) GetMiningInfo() (*btcjson.GetMiningInfoResult, error) {
|
||||
|
||||
// FutureGetNetworkHashPS is a future promise to deliver the result of a
|
||||
// GetNetworkHashPSAsync RPC invocation (or an applicable error).
|
||||
type FutureGetNetworkHashPS chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.(int64)
|
||||
if !ok {
|
||||
return -1, fmt.Errorf("unexpected response type for "+
|
||||
"getnetworkhashps: %T\n", reply)
|
||||
// Unmarshal result as an int64.
|
||||
var result int64
|
||||
err = json.Unmarshal(res, &result)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
@ -275,24 +275,24 @@ func (c *Client) GetNetworkHashPS3(blocks, height int) (int64, error) {
|
||||
|
||||
// FutureGetWork is a future promise to deliver the result of a
|
||||
// GetWorkAsync RPC invocation (or an applicable error).
|
||||
type FutureGetWork chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.(*btcjson.GetWorkResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getwork (request data): %T\n", reply)
|
||||
// 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
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// GetWorkAsync returns an instance of a type that can be used to get the result
|
||||
@ -319,21 +319,21 @@ func (c *Client) GetWork() (*btcjson.GetWorkResult, error) {
|
||||
|
||||
// FutureGetWorkSubmit is a future promise to deliver the result of a
|
||||
// GetWorkSubmitAsync RPC invocation (or an applicable error).
|
||||
type FutureGetWorkSubmit chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
accepted, ok := reply.(bool)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("unexpected response type for "+
|
||||
"getwork (submit data): %T\n", reply)
|
||||
// Unmarshal result as a boolean.
|
||||
var accepted bool
|
||||
err = json.Unmarshal(res, &accepted)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return accepted, nil
|
||||
@ -364,7 +364,7 @@ func (c *Client) GetWorkSubmit(data string) (bool, error) {
|
||||
|
||||
// FutureSubmitBlockResult is a future promise to deliver the result of a
|
||||
// SubmitBlockAsync RPC invocation (or an applicable error).
|
||||
type FutureSubmitBlockResult chan *futureResult
|
||||
type FutureSubmitBlockResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns an error if
|
||||
// any occurred when submitting the block.
|
||||
|
80
net.go
80
net.go
@ -5,7 +5,7 @@
|
||||
package btcrpcclient
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
"github.com/conformal/btcjson"
|
||||
)
|
||||
|
||||
@ -34,7 +34,7 @@ func (cmd AddNodeCommand) String() string {
|
||||
|
||||
// FutureAddNodeResult is a future promise to deliver the result of an
|
||||
// AddNodeAsync RPC invocation (or an applicable error).
|
||||
type FutureAddNodeResult chan *futureResult
|
||||
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.
|
||||
@ -73,21 +73,21 @@ func (c *Client) AddNode(host string, command AddNodeCommand) error {
|
||||
|
||||
// FutureGetAddedNodeInfoResult is a future promise to deliver the result of a
|
||||
// GetAddedNodeInfoAsync RPC invocation (or an applicable error).
|
||||
type FutureGetAddedNodeInfoResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
nodeInfo, ok := reply.([]btcjson.GetAddedNodeInfoResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getaddednodeinfo (dns=true): %T\n", reply)
|
||||
// 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
|
||||
@ -118,21 +118,21 @@ func (c *Client) GetAddedNodeInfo(peer string) ([]btcjson.GetAddedNodeInfoResult
|
||||
|
||||
// FutureGetAddedNodeInfoNoDNSResult is a future promise to deliver the result
|
||||
// of a GetAddedNodeInfoNoDNSAsync RPC invocation (or an applicable error).
|
||||
type FutureGetAddedNodeInfoNoDNSResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
nodes, ok := reply.([]string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getaddednodeinfo (dns=false): %T\n", reply)
|
||||
// Unmarshal result as an array of strings.
|
||||
var nodes []string
|
||||
err = json.Unmarshal(res, &nodes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nodes, nil
|
||||
@ -164,24 +164,24 @@ func (c *Client) GetAddedNodeInfoNoDNS(peer string) ([]string, error) {
|
||||
|
||||
// FutureGetConnectionCountResult is a future promise to deliver the result
|
||||
// of a GetConnectionCountAsync RPC invocation (or an applicable error).
|
||||
type FutureGetConnectionCountResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
fcount, ok := reply.(float64)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("unexpected response type for "+
|
||||
"getconnectioncount: %T\n", reply)
|
||||
// Unmarshal result as an int64.
|
||||
var count int64
|
||||
err = json.Unmarshal(res, &count)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return int64(fcount), nil
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// GetConnectionCountAsync returns an instance of a type that can be used to get
|
||||
@ -206,7 +206,7 @@ func (c *Client) GetConnectionCount() (int64, error) {
|
||||
|
||||
// FuturePingResult is a future promise to deliver the result of a PingAsync RPC
|
||||
// invocation (or an applicable error).
|
||||
type FuturePingResult chan *futureResult
|
||||
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.
|
||||
@ -244,21 +244,21 @@ func (c *Client) Ping() error {
|
||||
|
||||
// FutureGetPeerInfoResult is a future promise to deliver the result of a
|
||||
// GetPeerInfoAsync RPC invocation (or an applicable error).
|
||||
type FutureGetPeerInfoResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
peerInfo, ok := reply.([]btcjson.GetPeerInfoResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getpeerinfo: %T\n", reply)
|
||||
// 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
|
||||
@ -286,24 +286,24 @@ func (c *Client) GetPeerInfo() ([]btcjson.GetPeerInfoResult, error) {
|
||||
|
||||
// FutureGetNetTotalsResult is a future promise to deliver the result of a
|
||||
// GetNetTotalsAsync RPC invocation (or an applicable error).
|
||||
type FutureGetNetTotalsResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
totals, ok := reply.(*btcjson.GetNetTotalsResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getnettotals: %T\n", reply)
|
||||
// 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
|
||||
return &totals, nil
|
||||
}
|
||||
|
||||
// GetNetTotalsAsync returns an instance of a type that can be used to get the
|
||||
|
392
notify.go
392
notify.go
@ -7,7 +7,9 @@ package btcrpcclient
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/conformal/btcjson"
|
||||
"github.com/conformal/btcutil"
|
||||
"github.com/conformal/btcwire"
|
||||
@ -68,9 +70,9 @@ func newNotificationState() *notificationState {
|
||||
// result waiting on the channel with the reply set to nil. This is useful
|
||||
// to ignore things such as notifications when the caller didn't specify any
|
||||
// notification handlers.
|
||||
func newNilFutureResult() chan *futureResult {
|
||||
responseChan := make(chan *futureResult, 1)
|
||||
responseChan <- &futureResult{reply: nil}
|
||||
func newNilFutureResult() chan *response {
|
||||
responseChan := make(chan *response, 1)
|
||||
responseChan <- &response{result: nil, err: nil}
|
||||
return responseChan
|
||||
}
|
||||
|
||||
@ -161,183 +163,192 @@ type NotificationHandlers struct {
|
||||
// for this package needs to be updated for a new notification type or
|
||||
// the caller is using a custom notification this package does not know
|
||||
// about.
|
||||
OnUnknownNotification func(ntfn interface{})
|
||||
OnUnknownNotification func(method string, params []json.RawMessage)
|
||||
}
|
||||
|
||||
// handleNotification examines the passed notification type, performs
|
||||
// conversions to get the raw notification types into higher level types and
|
||||
// delivers the notification to the appropriate On<X> handler registered with
|
||||
// the client.
|
||||
func (c *Client) handleNotification(cmd btcjson.Cmd) {
|
||||
func (c *Client) handleNotification(ntfn *rawNotification) {
|
||||
// Ignore the notification if the client is not interested in any
|
||||
// notifications.
|
||||
if c.ntfnHandlers == nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch ntfn := cmd.(type) {
|
||||
switch ntfn.Method {
|
||||
// OnBlockConnected
|
||||
case *btcws.BlockConnectedNtfn:
|
||||
case btcws.BlockConnectedNtfnMethod:
|
||||
// Ignore the notification is the client is not interested in
|
||||
// it.
|
||||
if c.ntfnHandlers.OnBlockConnected == nil {
|
||||
return
|
||||
}
|
||||
|
||||
hash, err := btcwire.NewShaHashFromStr(ntfn.Hash)
|
||||
blockSha, blockHeight, err := parseChainNtfnParams(ntfn.Params)
|
||||
if err != nil {
|
||||
log.Warnf("Received block connected notification with "+
|
||||
"invalid hash string: %q", ntfn.Hash)
|
||||
log.Warnf("Received invalid block connected "+
|
||||
"notification: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnBlockConnected(hash, ntfn.Height)
|
||||
c.ntfnHandlers.OnBlockConnected(blockSha, blockHeight)
|
||||
|
||||
// OnBlockDisconnected
|
||||
case *btcws.BlockDisconnectedNtfn:
|
||||
case btcws.BlockDisconnectedNtfnMethod:
|
||||
// Ignore the notification is the client is not interested in
|
||||
// it.
|
||||
if c.ntfnHandlers.OnBlockDisconnected == nil {
|
||||
return
|
||||
}
|
||||
|
||||
hash, err := btcwire.NewShaHashFromStr(ntfn.Hash)
|
||||
blockSha, blockHeight, err := parseChainNtfnParams(ntfn.Params)
|
||||
if err != nil {
|
||||
log.Warnf("Received block disconnected notification "+
|
||||
"with invalid hash string: %q", ntfn.Hash)
|
||||
log.Warnf("Received invalid block connected "+
|
||||
"notification: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnBlockDisconnected(hash, ntfn.Height)
|
||||
c.ntfnHandlers.OnBlockDisconnected(blockSha, blockHeight)
|
||||
|
||||
// OnRecvTx
|
||||
case *btcws.RecvTxNtfn:
|
||||
case btcws.RecvTxNtfnMethod:
|
||||
// Ignore the notification is the client is not interested in
|
||||
// it.
|
||||
if c.ntfnHandlers.OnRecvTx == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Decode the serialized transaction hex to raw bytes.
|
||||
serializedTx, err := hex.DecodeString(ntfn.HexTx)
|
||||
tx, block, err := parseChainTxNtfnParams(ntfn.Params)
|
||||
if err != nil {
|
||||
log.Warnf("Received recvtx notification with invalid "+
|
||||
"transaction hex '%q': %v", ntfn.HexTx, err)
|
||||
}
|
||||
|
||||
// Deserialize the transaction.
|
||||
var msgTx btcwire.MsgTx
|
||||
err = msgTx.Deserialize(bytes.NewReader(serializedTx))
|
||||
if err != nil {
|
||||
log.Warnf("Received recvtx notification with "+
|
||||
"transaction that failed to deserialize: %v",
|
||||
log.Warnf("Received invalid recvtx notification: %v",
|
||||
err)
|
||||
return
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnRecvTx(btcutil.NewTx(&msgTx), ntfn.Block)
|
||||
c.ntfnHandlers.OnRecvTx(tx, block)
|
||||
|
||||
// OnRedeemingTx
|
||||
case *btcws.RedeemingTxNtfn:
|
||||
case btcws.RedeemingTxNtfnMethod:
|
||||
// Ignore the notification is the client is not interested in
|
||||
// it.
|
||||
if c.ntfnHandlers.OnRedeemingTx == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Decode the serialized transaction hex to raw bytes.
|
||||
serializedTx, err := hex.DecodeString(ntfn.HexTx)
|
||||
tx, block, err := parseChainTxNtfnParams(ntfn.Params)
|
||||
if err != nil {
|
||||
log.Warnf("Received redeemingtx notification with "+
|
||||
"invalid transaction hex '%q': %v", ntfn.HexTx,
|
||||
err)
|
||||
log.Warnf("Received invalid redeemingtx "+
|
||||
"notification: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Deserialize the transaction.
|
||||
var msgTx btcwire.MsgTx
|
||||
err = msgTx.Deserialize(bytes.NewReader(serializedTx))
|
||||
if err != nil {
|
||||
log.Warnf("Received redeemingtx notification with "+
|
||||
"transaction that failed to deserialize: %v",
|
||||
err)
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnRedeemingTx(btcutil.NewTx(&msgTx), ntfn.Block)
|
||||
c.ntfnHandlers.OnRedeemingTx(tx, block)
|
||||
|
||||
// OnRescanProgress
|
||||
case *btcws.RescanProgressNtfn:
|
||||
case btcws.RescanProgressNtfnMethod:
|
||||
// Ignore the notification is the client is not interested in
|
||||
// it.
|
||||
if c.ntfnHandlers.OnRescanProgress == nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnRescanProgress(ntfn.LastProcessed)
|
||||
lastProcessed, err := parseRescanProgressNtfnParams(ntfn.Params)
|
||||
if err != nil {
|
||||
log.Warnf("Received invalid rescanprogress "+
|
||||
"notification: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnRescanProgress(lastProcessed)
|
||||
|
||||
// OnTxAccepted
|
||||
case *btcws.TxAcceptedNtfn:
|
||||
case btcws.TxAcceptedNtfnMethod:
|
||||
// Ignore the notification is the client is not interested in
|
||||
// it.
|
||||
if c.ntfnHandlers.OnTxAccepted == nil {
|
||||
return
|
||||
}
|
||||
|
||||
hash, err := btcwire.NewShaHashFromStr(ntfn.TxID)
|
||||
hash, amt, err := parseTxAcceptedNtfnParams(ntfn.Params)
|
||||
if err != nil {
|
||||
log.Warnf("Received tx accepted notification with "+
|
||||
"invalid hash string: %q", ntfn.TxID)
|
||||
log.Warnf("Received invalid tx accepted "+
|
||||
"notification: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnTxAccepted(hash, btcutil.Amount(ntfn.Amount))
|
||||
c.ntfnHandlers.OnTxAccepted(hash, amt)
|
||||
|
||||
// OnTxAcceptedVerbose
|
||||
case *btcws.TxAcceptedVerboseNtfn:
|
||||
case btcws.TxAcceptedVerboseNtfnMethod:
|
||||
// Ignore the notification is the client is not interested in
|
||||
// it.
|
||||
if c.ntfnHandlers.OnTxAcceptedVerbose == nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnTxAcceptedVerbose(ntfn.RawTx)
|
||||
rawTx, err := parseTxAcceptedVerboseNtfnParams(ntfn.Params)
|
||||
if err != nil {
|
||||
log.Warnf("Received invalid tx accepted verbose "+
|
||||
"notification: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnTxAcceptedVerbose(rawTx)
|
||||
|
||||
// OnBtcdConnected
|
||||
case *btcws.BtcdConnectedNtfn:
|
||||
case btcws.BtcdConnectedNtfnMethod:
|
||||
// Ignore the notification is the client is not interested in
|
||||
// it.
|
||||
if c.ntfnHandlers.OnBtcdConnected == nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnBtcdConnected(ntfn.Connected)
|
||||
connected, err := parseBtcdConnectedNtfnParams(ntfn.Params)
|
||||
if err != nil {
|
||||
log.Warnf("Received invalid btcd connected "+
|
||||
"notification: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnBtcdConnected(connected)
|
||||
|
||||
// OnAccountBalance
|
||||
case *btcws.AccountBalanceNtfn:
|
||||
case btcws.AccountBalanceNtfnMethod:
|
||||
// Ignore the notification is the client is not interested in
|
||||
// it.
|
||||
if c.ntfnHandlers.OnAccountBalance == nil {
|
||||
return
|
||||
}
|
||||
|
||||
balance, err := btcjson.JSONToAmount(ntfn.Balance)
|
||||
account, bal, conf, err := parseAccountBalanceNtfnParams(ntfn.Params)
|
||||
if err != nil {
|
||||
log.Warnf("Received account balance notification with "+
|
||||
"an amount that does not parse: %v",
|
||||
ntfn.Balance)
|
||||
log.Warnf("Received invalid account balance "+
|
||||
"notification: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnAccountBalance(ntfn.Account,
|
||||
btcutil.Amount(balance), ntfn.Confirmed)
|
||||
c.ntfnHandlers.OnAccountBalance(account, bal, conf)
|
||||
|
||||
// OnWalletLockState
|
||||
case *btcws.WalletLockStateNtfn:
|
||||
case btcws.WalletLockStateNtfnMethod:
|
||||
// Ignore the notification is the client is not interested in
|
||||
// it.
|
||||
if c.ntfnHandlers.OnWalletLockState == nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnWalletLockState(ntfn.Locked)
|
||||
// The account name is not notified, so the return value is
|
||||
// discarded.
|
||||
_, locked, err := parseWalletLockStateNtfnParams(ntfn.Params)
|
||||
if err != nil {
|
||||
log.Warnf("Received invalid wallet lock state "+
|
||||
"notification: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnWalletLockState(locked)
|
||||
|
||||
// OnUnknownNotification
|
||||
default:
|
||||
@ -345,13 +356,250 @@ func (c *Client) handleNotification(cmd btcjson.Cmd) {
|
||||
return
|
||||
}
|
||||
|
||||
c.ntfnHandlers.OnUnknownNotification(ntfn)
|
||||
c.ntfnHandlers.OnUnknownNotification(ntfn.Method, ntfn.Params)
|
||||
}
|
||||
}
|
||||
|
||||
// wrongNumParams is an error type describing an unparseable JSON-RPC
|
||||
// notificiation due to an incorrect number of parameters for the
|
||||
// expected notification type. The value is the number of parameters
|
||||
// of the invalid notification.
|
||||
type wrongNumParams int
|
||||
|
||||
// Error satisifies the builtin error interface.
|
||||
func (e wrongNumParams) Error() string {
|
||||
return fmt.Sprintf("wrong number of parameters (%d)", e)
|
||||
}
|
||||
|
||||
// parseChainNtfnParams parses out the block hash and height from the parameters
|
||||
// of blockconnected and blockdisconnected notifications.
|
||||
func parseChainNtfnParams(params []json.RawMessage) (*btcwire.ShaHash,
|
||||
int32, error) {
|
||||
|
||||
if len(params) != 2 {
|
||||
return nil, 0, wrongNumParams(len(params))
|
||||
}
|
||||
|
||||
// Unmarshal first parameter as a string.
|
||||
var blockShaStr string
|
||||
err := json.Unmarshal(params[0], &blockShaStr)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Unmarshal second parameter as an integer.
|
||||
var blockHeight int32
|
||||
err = json.Unmarshal(params[1], &blockHeight)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Create ShaHash from block sha string.
|
||||
blockSha, err := btcwire.NewShaHashFromStr(blockShaStr)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return blockSha, blockHeight, nil
|
||||
}
|
||||
|
||||
// parseChainTxNtfnParams parses out the transaction and optional details about
|
||||
// the block it's mined in from the parameters of recvtx and redeemingtx
|
||||
// notifications.
|
||||
func parseChainTxNtfnParams(params []json.RawMessage) (*btcutil.Tx,
|
||||
*btcws.BlockDetails, error) {
|
||||
|
||||
if len(params) == 0 || len(params) > 2 {
|
||||
return nil, nil, wrongNumParams(len(params))
|
||||
}
|
||||
|
||||
// Unmarshal first parameter as a string.
|
||||
var txHex string
|
||||
err := json.Unmarshal(params[0], &txHex)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// If present, unmarshal second optional parameter as the block details
|
||||
// JSON object.
|
||||
var block *btcws.BlockDetails
|
||||
if len(params) > 1 {
|
||||
err = json.Unmarshal(params[1], &block)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Hex decode and deserialize the transaction.
|
||||
serializedTx, err := hex.DecodeString(txHex)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var msgTx btcwire.MsgTx
|
||||
err = msgTx.Deserialize(bytes.NewReader(serializedTx))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// TODO: Change recvtx and redeemingtx callback signatures to use
|
||||
// nicer types for details about the block (block sha as a
|
||||
// btcwire.ShaHash, block time as a time.Time, etc.).
|
||||
return btcutil.NewTx(&msgTx), block, nil
|
||||
}
|
||||
|
||||
// parseRescanProgressNtfnParams parses out the height of the last rescanned
|
||||
// from the parameters of a rescanprogress notification.
|
||||
func parseRescanProgressNtfnParams(params []json.RawMessage) (int32, error) {
|
||||
if len(params) != 1 {
|
||||
return 0, wrongNumParams(len(params))
|
||||
}
|
||||
|
||||
// Unmarshal first parameter as an integer.
|
||||
var height int32
|
||||
err := json.Unmarshal(params[0], &height)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return height, nil
|
||||
}
|
||||
|
||||
// parseTxAcceptedNtfnParams parses out the transaction hash and total amount
|
||||
// from the parameters of a txaccepted notification.
|
||||
func parseTxAcceptedNtfnParams(params []json.RawMessage) (*btcwire.ShaHash,
|
||||
btcutil.Amount, error) {
|
||||
|
||||
if len(params) != 2 {
|
||||
return nil, 0, wrongNumParams(len(params))
|
||||
}
|
||||
|
||||
// Unmarshal first parameter as a string.
|
||||
var txShaStr string
|
||||
err := json.Unmarshal(params[0], &txShaStr)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Unmarshal second parameter as an integer.
|
||||
var amt int64
|
||||
err = json.Unmarshal(params[1], &amt)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Decode string encoding of transaction sha.
|
||||
txSha, err := btcwire.NewShaHashFromStr(txShaStr)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return txSha, btcutil.Amount(amt), nil
|
||||
}
|
||||
|
||||
// parseTxAcceptedVerboseNtfnParams parses out details about a raw transaction
|
||||
// from the parameters of a txacceptedverbose notification.
|
||||
func parseTxAcceptedVerboseNtfnParams(params []json.RawMessage) (*btcjson.TxRawResult,
|
||||
error) {
|
||||
|
||||
if len(params) != 1 {
|
||||
return nil, wrongNumParams(len(params))
|
||||
}
|
||||
|
||||
// Unmarshal first parameter as a raw transaction result object.
|
||||
var rawTx btcjson.TxRawResult
|
||||
err := json.Unmarshal(params[0], &rawTx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: change txacceptedverbose notifiation callbacks to use nicer
|
||||
// types for all details about the transaction (i.e. decoding hashes
|
||||
// from their string encoding).
|
||||
return &rawTx, nil
|
||||
}
|
||||
|
||||
// parseBtcdConnectedNtfnParams parses out the connection status of btcd
|
||||
// and btcwallet from the parameters of a btcdconnected notification.
|
||||
func parseBtcdConnectedNtfnParams(params []json.RawMessage) (bool, error) {
|
||||
if len(params) != 1 {
|
||||
return false, wrongNumParams(len(params))
|
||||
}
|
||||
|
||||
// Unmarshal first parameter as a boolean.
|
||||
var connected bool
|
||||
err := json.Unmarshal(params[0], &connected)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return connected, nil
|
||||
}
|
||||
|
||||
// parseAccountBalanceNtfnParams parses out the account name, total balance,
|
||||
// and whether or not the balance is confirmed or unconfirmed from the
|
||||
// parameters of an accountbalance notification.
|
||||
func parseAccountBalanceNtfnParams(params []json.RawMessage) (account string,
|
||||
balance btcutil.Amount, confirmed bool, err error) {
|
||||
|
||||
if len(params) != 3 {
|
||||
return "", 0, false, wrongNumParams(len(params))
|
||||
}
|
||||
|
||||
// Unmarshal first parameter as a string.
|
||||
err = json.Unmarshal(params[0], &account)
|
||||
if err != nil {
|
||||
return "", 0, false, err
|
||||
}
|
||||
|
||||
// Unmarshal second parameter as a floating point number.
|
||||
var fbal float64
|
||||
err = json.Unmarshal(params[1], &fbal)
|
||||
if err != nil {
|
||||
return "", 0, false, err
|
||||
}
|
||||
|
||||
// Unmarshal third parameter as a boolean.
|
||||
err = json.Unmarshal(params[2], &confirmed)
|
||||
if err != nil {
|
||||
return "", 0, false, err
|
||||
}
|
||||
|
||||
// Bounds check amount.
|
||||
bal, err := btcjson.JSONToAmount(fbal)
|
||||
if err != nil {
|
||||
return "", 0, false, err
|
||||
}
|
||||
|
||||
return account, btcutil.Amount(bal), confirmed, nil
|
||||
}
|
||||
|
||||
// parseWalletLockStateNtfnParams parses out the account name and locked
|
||||
// state of an account from the parameters of a walletlockstate notification.
|
||||
func parseWalletLockStateNtfnParams(params []json.RawMessage) (account string,
|
||||
locked bool, err error) {
|
||||
|
||||
if len(params) != 2 {
|
||||
return "", false, wrongNumParams(len(params))
|
||||
}
|
||||
|
||||
// Unmarshal first parameter as a string.
|
||||
err = json.Unmarshal(params[0], &account)
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
|
||||
// Unmarshal second parameter as a boolean.
|
||||
err = json.Unmarshal(params[1], &locked)
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
|
||||
return account, locked, nil
|
||||
}
|
||||
|
||||
// FutureNotifyBlocksResult is a future promise to deliver the result of a
|
||||
// NotifyBlocksAsync RPC invocation (or an applicable error).
|
||||
type FutureNotifyBlocksResult chan *futureResult
|
||||
type FutureNotifyBlocksResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns an error
|
||||
// if the registration was not successful.
|
||||
@ -405,7 +653,7 @@ func (c *Client) NotifyBlocks() error {
|
||||
|
||||
// FutureNotifySpentResult is a future promise to deliver the result of a
|
||||
// NotifySpentAsync RPC invocation (or an applicable error).
|
||||
type FutureNotifySpentResult chan *futureResult
|
||||
type FutureNotifySpentResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns an error
|
||||
// if the registration was not successful.
|
||||
@ -484,7 +732,7 @@ func (c *Client) NotifySpent(outpoints []*btcwire.OutPoint) error {
|
||||
|
||||
// FutureNotifyNewTransactionsResult is a future promise to deliver the result
|
||||
// of a NotifyNewTransactionsAsync RPC invocation (or an applicable error).
|
||||
type FutureNotifyNewTransactionsResult chan *futureResult
|
||||
type FutureNotifyNewTransactionsResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns an error
|
||||
// if the registration was not successful.
|
||||
@ -542,7 +790,7 @@ func (c *Client) NotifyNewTransactions(verbose bool) error {
|
||||
|
||||
// FutureNotifyReceivedResult is a future promise to deliver the result of a
|
||||
// NotifyReceivedAsync RPC invocation (or an applicable error).
|
||||
type FutureNotifyReceivedResult chan *futureResult
|
||||
type FutureNotifyReceivedResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns an error
|
||||
// if the registration was not successful.
|
||||
@ -630,7 +878,7 @@ func (c *Client) NotifyReceived(addresses []btcutil.Address) error {
|
||||
|
||||
// FutureRescanResult is a future promise to deliver the result of a RescanAsync
|
||||
// or RescanEndHeightAsync RPC invocation (or an applicable error).
|
||||
type FutureRescanResult chan *futureResult
|
||||
type FutureRescanResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns an error
|
||||
// if the rescan was not successful.
|
||||
|
90
rawrequest.go
Normal file
90
rawrequest.go
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2014 Conformal Systems LLC.
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package btcrpcclient
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/conformal/btcjson"
|
||||
)
|
||||
|
||||
// rawRequest satisifies the btcjson.Cmd interface for btcjson raw commands.
|
||||
// This type exists here rather than making btcjson.RawCmd satisify the Cmd
|
||||
// interface due to conflict between the Id and Method field names vs method
|
||||
// names.
|
||||
type rawRequest struct {
|
||||
btcjson.RawCmd
|
||||
}
|
||||
|
||||
// Enforce that rawRequest is a btcjson.Cmd.
|
||||
var _ btcjson.Cmd = &rawRequest{}
|
||||
|
||||
// Id returns the JSON-RPC id of the request.
|
||||
func (r *rawRequest) Id() interface{} {
|
||||
return r.RawCmd.Id
|
||||
}
|
||||
|
||||
// Method returns the method string of the request.
|
||||
func (r *rawRequest) Method() string {
|
||||
return r.RawCmd.Method
|
||||
}
|
||||
|
||||
// MarshalJSON marshals the raw request as a JSON-RPC 1.0 object.
|
||||
func (r *rawRequest) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(r.RawCmd)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals a JSON-RPC 1.0 object into the raw request.
|
||||
func (r *rawRequest) UnmarshalJSON(b []byte) error {
|
||||
return json.Unmarshal(b, &r.RawCmd)
|
||||
}
|
||||
|
||||
// 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{}
|
||||
}
|
||||
|
||||
cmd := &rawRequest{
|
||||
RawCmd: btcjson.RawCmd{
|
||||
Jsonrpc: "1.0",
|
||||
Id: c.NextID(),
|
||||
Method: method,
|
||||
Params: params,
|
||||
},
|
||||
}
|
||||
|
||||
return c.sendCmd(cmd)
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
@ -7,7 +7,7 @@ package btcrpcclient
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
"github.com/conformal/btcjson"
|
||||
"github.com/conformal/btcutil"
|
||||
"github.com/conformal/btcwire"
|
||||
@ -58,21 +58,21 @@ func (s SigHashType) String() string {
|
||||
|
||||
// FutureGetRawTransactionResult is a future promise to deliver the result of a
|
||||
// GetRawTransactionAsync RPC invocation (or an applicable error).
|
||||
type FutureGetRawTransactionResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
txHex, ok := reply.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getrawtransaction (verbose=0): %T\n", reply)
|
||||
// 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.
|
||||
@ -120,24 +120,24 @@ func (c *Client) GetRawTransaction(txHash *btcwire.ShaHash) (*btcutil.Tx, error)
|
||||
// FutureGetRawTransactionVerboseResult is a future promise to deliver the
|
||||
// result of a GetRawTransactionVerboseAsync RPC invocation (or an applicable
|
||||
// error).
|
||||
type FutureGetRawTransactionVerboseResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.(*btcjson.TxRawResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getrawtransaction (verbose=1): %T\n", reply)
|
||||
// Unmarshal result as a gettrawtransaction result object.
|
||||
var rawTxResult btcjson.TxRawResult
|
||||
err = json.Unmarshal(res, &rawTxResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return &rawTxResult, nil
|
||||
}
|
||||
|
||||
// GetRawTransactionVerboseAsync returns an instance of a type that can be used
|
||||
@ -170,24 +170,24 @@ func (c *Client) GetRawTransactionVerbose(txHash *btcwire.ShaHash) (*btcjson.TxR
|
||||
|
||||
// FutureDecodeRawTransactionResult is a future promise to deliver the result
|
||||
// of a DecodeRawTransactionAsync RPC invocation (or an applicable error).
|
||||
type FutureDecodeRawTransactionResult chan *futureResult
|
||||
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) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.(*btcjson.TxRawResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"decoderawtransaction: %T\n", reply)
|
||||
// Unmarshal result as a decoderawtransaction result object.
|
||||
var rawTxResult btcjson.TxRawResult
|
||||
err = json.Unmarshal(res, &rawTxResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return &rawTxResult, nil
|
||||
}
|
||||
|
||||
// DecodeRawTransactionAsync returns an instance of a type that can be used to
|
||||
@ -214,22 +214,22 @@ func (c *Client) DecodeRawTransaction(serializedTx []byte) (*btcjson.TxRawResult
|
||||
|
||||
// FutureCreateRawTransactionResult is a future promise to deliver the result
|
||||
// of a CreateRawTransactionAsync RPC invocation (or an applicable error).
|
||||
type FutureCreateRawTransactionResult chan *futureResult
|
||||
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() (*btcwire.MsgTx, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
txHex, ok := reply.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"createrawtransaction: %T\n", reply)
|
||||
// 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.
|
||||
@ -277,22 +277,22 @@ func (c *Client) CreateRawTransaction(inputs []btcjson.TransactionInput,
|
||||
|
||||
// FutureSendRawTransactionResult is a future promise to deliver the result
|
||||
// of a SendRawTransactionAsync RPC invocation (or an applicable error).
|
||||
type FutureSendRawTransactionResult chan *futureResult
|
||||
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() (*btcwire.ShaHash, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
txHashStr, ok := reply.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"decoderawtransaction: %T\n", reply)
|
||||
// Unmarshal result as a string.
|
||||
var txHashStr string
|
||||
err = json.Unmarshal(res, &txHashStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return btcwire.NewShaHashFromStr(txHashStr)
|
||||
@ -332,25 +332,25 @@ func (c *Client) SendRawTransaction(tx *btcwire.MsgTx, allowHighFees bool) (*btc
|
||||
// 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 *futureResult
|
||||
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() (*btcwire.MsgTx, bool, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.(*btcjson.SignRawTransactionResult)
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf("unexpected response type for "+
|
||||
"signrawtransaction: %T\n", reply)
|
||||
// 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(result.Hex)
|
||||
serializedTx, err := hex.DecodeString(signRawTxResult.Hex)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
@ -361,7 +361,7 @@ func (r FutureSignRawTransactionResult) Receive() (*btcwire.MsgTx, bool, error)
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
return &msgTx, result.Complete, nil
|
||||
return &msgTx, signRawTxResult.Complete, nil
|
||||
}
|
||||
|
||||
// SignRawTransactionAsync returns an instance of a type that can be used to get
|
||||
|
374
wallet.go
374
wallet.go
@ -5,7 +5,7 @@
|
||||
package btcrpcclient
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"encoding/json"
|
||||
"github.com/conformal/btcjson"
|
||||
"github.com/conformal/btcnet"
|
||||
"github.com/conformal/btcutil"
|
||||
@ -19,24 +19,24 @@ import (
|
||||
|
||||
// FutureGetTransactionResult is a future promise to deliver the result
|
||||
// of a GetTransactionAsync RPC invocation (or an applicable error).
|
||||
type FutureGetTransactionResult chan *futureResult
|
||||
type FutureGetTransactionResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns detailed
|
||||
// information about a wallet transaction.
|
||||
func (r FutureGetTransactionResult) Receive() (*btcjson.GetTransactionResult, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.(*btcjson.GetTransactionResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"gettransaction: %T\n", reply)
|
||||
// Unmarshal result as a gettransaction result object
|
||||
var getTx btcjson.GetTransactionResult
|
||||
err = json.Unmarshal(res, &getTx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return &getTx, nil
|
||||
}
|
||||
|
||||
// GetTransactionAsync returns an instance of a type that can be used to get the
|
||||
@ -69,26 +69,21 @@ func (c *Client) GetTransaction(txHash *btcwire.ShaHash) (*btcjson.GetTransactio
|
||||
// FutureListTransactionsResult is a future promise to deliver the result of a
|
||||
// ListTransactionsAsync, ListTransactionsCountAsync, or
|
||||
// ListTransactionsCountFromAsync RPC invocation (or an applicable error).
|
||||
type FutureListTransactionsResult chan *futureResult
|
||||
type FutureListTransactionsResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns a list of
|
||||
// the most recent transactions.
|
||||
func (r FutureListTransactionsResult) Receive() ([]btcjson.ListTransactionsResult, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// No transactions.
|
||||
if reply == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
transactions, ok := reply.([]btcjson.ListTransactionsResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"listtransactions: %T\n", reply)
|
||||
// Unmarshal result as an array of listtransaction result objects.
|
||||
var transactions []btcjson.ListTransactionsResult
|
||||
err = json.Unmarshal(res, &transactions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return transactions, nil
|
||||
@ -167,7 +162,7 @@ func (c *Client) ListTransactionsCountFrom(account string, count, from int) ([]b
|
||||
// FutureListUnspentResult is a future promise to deliver the result of a
|
||||
// ListUnspentAsync, ListUnspentMinAsync, ListUnspentMinMaxAsync, or
|
||||
// ListUnspentMinMaxAddressesAsync RPC invocation (or an applicable error).
|
||||
type FutureListUnspentResult chan *futureResult
|
||||
type FutureListUnspentResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns all
|
||||
// unspent wallet transaction outputs returned by the RPC call. If the
|
||||
@ -175,21 +170,16 @@ type FutureListUnspentResult chan *futureResult
|
||||
// or ListUnspentMinMaxAddressesAsync, the range may be limited by the
|
||||
// parameters of the RPC invocation.
|
||||
func (r FutureListUnspentResult) Receive() ([]btcjson.ListUnspentResult, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// No unspent transaction outputs.
|
||||
if reply == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
unspent, ok := reply.([]btcjson.ListUnspentResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"listunspent: %T\n", reply)
|
||||
// Unmarshal result as an array of listunspent results.
|
||||
var unspent []btcjson.ListUnspentResult
|
||||
err = json.Unmarshal(res, &unspent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return unspent, nil
|
||||
@ -291,25 +281,25 @@ func (c *Client) ListUnspentMinMaxAddresses(minConf, maxConf int, addrs []btcuti
|
||||
// FutureListSinceBlockResult is a future promise to deliver the result of a
|
||||
// ListSinceBlockAsync or ListSinceBlockMinConfAsync RPC invocation (or an
|
||||
// applicable error).
|
||||
type FutureListSinceBlockResult chan *futureResult
|
||||
type FutureListSinceBlockResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns all
|
||||
// transactions added in blocks since the specified block hash, or all
|
||||
// transactions if it is nil.
|
||||
func (r FutureListSinceBlockResult) Receive() (*btcjson.ListSinceBlockResult, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
listResult, ok := reply.(*btcjson.ListSinceBlockResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"listsinceblock: %T\n", reply)
|
||||
// Unmarshal result as a listsinceblock result object.
|
||||
var listResult btcjson.ListSinceBlockResult
|
||||
err = json.Unmarshal(res, &listResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return listResult, nil
|
||||
return &listResult, nil
|
||||
}
|
||||
|
||||
// ListSinceBlockAsync returns an instance of a type that can be used to get
|
||||
@ -376,7 +366,7 @@ func (c *Client) ListSinceBlockMinConf(blockHash *btcwire.ShaHash, minConfirms i
|
||||
|
||||
// FutureSetTxFeeResult is a future promise to deliver the result of a
|
||||
// SetTxFeeAsync RPC invocation (or an applicable error).
|
||||
type FutureSetTxFeeResult chan *futureResult
|
||||
type FutureSetTxFeeResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the result
|
||||
// of setting an optional transaction fee per KB that helps ensure transactions
|
||||
@ -413,20 +403,21 @@ func (c *Client) SetTxFee(fee btcutil.Amount) error {
|
||||
|
||||
// FutureSendToAddressResult is a future promise to deliver the result of a
|
||||
// SendToAddressAsync RPC invocation (or an applicable error).
|
||||
type FutureSendToAddressResult chan *futureResult
|
||||
type FutureSendToAddressResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the hash
|
||||
// of the transaction sending the passed amount to the given address.
|
||||
func (r FutureSendToAddressResult) Receive() (*btcwire.ShaHash, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txHash, ok := reply.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"sendtoaddress: %T\n", reply)
|
||||
// Unmarshal result as a string.
|
||||
var txHash string
|
||||
err = json.Unmarshal(res, &txHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return btcwire.NewShaHashFromStr(txHash)
|
||||
@ -500,22 +491,22 @@ func (c *Client) SendToAddressComment(address btcutil.Address, amount btcutil.Am
|
||||
// FutureSendFromResult is a future promise to deliver the result of a
|
||||
// SendFromAsync, SendFromMinConfAsync, or SendFromCommentAsync RPC invocation
|
||||
// (or an applicable error).
|
||||
type FutureSendFromResult chan *futureResult
|
||||
type FutureSendFromResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the hash
|
||||
// of the transaction sending amount to the given address using the provided
|
||||
// account as a source of funds.
|
||||
func (r FutureSendFromResult) Receive() (*btcwire.ShaHash, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
txHash, ok := reply.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"sendfrom: %T\n", reply)
|
||||
// Unmarshal result as a string.
|
||||
var txHash string
|
||||
err = json.Unmarshal(res, &txHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return btcwire.NewShaHashFromStr(txHash)
|
||||
@ -622,22 +613,22 @@ func (c *Client) SendFromComment(fromAccount string, toAddress btcutil.Address,
|
||||
// FutureSendManyResult is a future promise to deliver the result of a
|
||||
// SendManyAsync, SendManyMinConfAsync, or SendManyCommentAsync RPC invocation
|
||||
// (or an applicable error).
|
||||
type FutureSendManyResult chan *futureResult
|
||||
type FutureSendManyResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the hash
|
||||
// of the transaction sending multiple amounts to multiple addresses using the
|
||||
// provided account as a source of funds.
|
||||
func (r FutureSendManyResult) Receive() (*btcwire.ShaHash, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
txHash, ok := reply.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"sendmany: %T\n", reply)
|
||||
// Unmashal result as a string.
|
||||
var txHash string
|
||||
err = json.Unmarshal(res, &txHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return btcwire.NewShaHashFromStr(txHash)
|
||||
@ -760,22 +751,22 @@ func (c *Client) SendManyComment(fromAccount string,
|
||||
|
||||
// FutureAddMultisigAddressResult is a future promise to deliver the result of a
|
||||
// AddMultisigAddressAsync RPC invocation (or an applicable error).
|
||||
type FutureAddMultisigAddressResult chan *futureResult
|
||||
type FutureAddMultisigAddressResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// multisignature address that requires the specified number of signatures for
|
||||
// the provided addresses.
|
||||
func (r FutureAddMultisigAddressResult) Receive() (btcutil.Address, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
addr, ok := reply.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"addmultisigaddress: %T\n", reply)
|
||||
// Unmarshal result as a string.
|
||||
var addr string
|
||||
err = json.Unmarshal(res, &addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return btcutil.DecodeAddress(addr, &btcnet.MainNetParams)
|
||||
@ -811,24 +802,24 @@ func (c *Client) AddMultisigAddress(requiredSigs int, addresses []btcutil.Addres
|
||||
|
||||
// FutureCreateMultisigResult is a future promise to deliver the result of a
|
||||
// CreateMultisigAsync RPC invocation (or an applicable error).
|
||||
type FutureCreateMultisigResult chan *futureResult
|
||||
type FutureCreateMultisigResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// multisignature address and script needed to redeem it.
|
||||
func (r FutureCreateMultisigResult) Receive() (*btcjson.CreateMultiSigResult, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.(*btcjson.CreateMultiSigResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"createmultisig: %T\n", reply)
|
||||
// Unmarshal result as a createmultisig result object.
|
||||
var multisigRes btcjson.CreateMultiSigResult
|
||||
err = json.Unmarshal(res, &multisigRes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return &multisigRes, nil
|
||||
}
|
||||
|
||||
// CreateMultisigAsync returns an instance of a type that can be used to get
|
||||
@ -861,21 +852,21 @@ func (c *Client) CreateMultisig(requiredSigs int, addresses []btcutil.Address) (
|
||||
|
||||
// FutureGetNewAddressResult is a future promise to deliver the result of a
|
||||
// GetNewAddressAsync RPC invocation (or an applicable error).
|
||||
type FutureGetNewAddressResult chan *futureResult
|
||||
type FutureGetNewAddressResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns a new
|
||||
// address.
|
||||
func (r FutureGetNewAddressResult) Receive() (btcutil.Address, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
addr, ok := reply.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getnewaddress: %T\n", reply)
|
||||
// Unmarshal result as a string.
|
||||
var addr string
|
||||
err = json.Unmarshal(res, &addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return btcutil.DecodeAddress(addr, &btcnet.MainNetParams)
|
||||
@ -903,22 +894,22 @@ func (c *Client) GetNewAddress() (btcutil.Address, error) {
|
||||
|
||||
// FutureGetRawChangeAddressResult is a future promise to deliver the result of
|
||||
// a GetRawChangeAddressAsync RPC invocation (or an applicable error).
|
||||
type FutureGetRawChangeAddressResult chan *futureResult
|
||||
type FutureGetRawChangeAddressResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns a new
|
||||
// address for receiving change that will be associated with the provided
|
||||
// account. Note that this is only for raw transactions and NOT for normal use.
|
||||
func (r FutureGetRawChangeAddressResult) Receive() (btcutil.Address, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
addr, ok := reply.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getrawchangeaddress: %T\n", reply)
|
||||
// Unmarshal result as a string.
|
||||
var addr string
|
||||
err = json.Unmarshal(res, &addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return btcutil.DecodeAddress(addr, &btcnet.MainNetParams)
|
||||
@ -948,21 +939,21 @@ func (c *Client) GetRawChangeAddress(account string) (btcutil.Address, error) {
|
||||
|
||||
// FutureGetAccountAddressResult is a future promise to deliver the result of a
|
||||
// GetAccountAddressAsync RPC invocation (or an applicable error).
|
||||
type FutureGetAccountAddressResult chan *futureResult
|
||||
type FutureGetAccountAddressResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the current
|
||||
// Bitcoin address for receiving payments to the specified account.
|
||||
func (r FutureGetAccountAddressResult) Receive() (btcutil.Address, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
addr, ok := reply.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getaccountaddress: %T\n", reply)
|
||||
// Unmarshal result as a string.
|
||||
var addr string
|
||||
err = json.Unmarshal(res, &addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return btcutil.DecodeAddress(addr, &btcnet.MainNetParams)
|
||||
@ -991,21 +982,21 @@ func (c *Client) GetAccountAddress(account string) (btcutil.Address, error) {
|
||||
|
||||
// FutureGetAccountResult is a future promise to deliver the result of a
|
||||
// GetAccountAsync RPC invocation (or an applicable error).
|
||||
type FutureGetAccountResult chan *futureResult
|
||||
type FutureGetAccountResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the account
|
||||
// associated with the passed address.
|
||||
func (r FutureGetAccountResult) Receive() (string, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
account, ok := reply.(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("unexpected response type for "+
|
||||
"getaccount: %T\n", reply)
|
||||
// Unmarshal result as a string.
|
||||
var account string
|
||||
err = json.Unmarshal(res, &account)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return account, nil
|
||||
@ -1034,7 +1025,7 @@ func (c *Client) GetAccount(address btcutil.Address) (string, error) {
|
||||
|
||||
// FutureSetAccountResult is a future promise to deliver the result of a
|
||||
// SetAccountAsync RPC invocation (or an applicable error).
|
||||
type FutureSetAccountResult chan *futureResult
|
||||
type FutureSetAccountResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the result
|
||||
// of setting the account to be associated with the passed address.
|
||||
@ -1070,21 +1061,21 @@ func (c *Client) SetAccount(address btcutil.Address, account string) error {
|
||||
|
||||
// FutureGetAddressesByAccountResult is a future promise to deliver the result
|
||||
// of a GetAddressesByAccountAsync RPC invocation (or an applicable error).
|
||||
type FutureGetAddressesByAccountResult chan *futureResult
|
||||
type FutureGetAddressesByAccountResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the list of
|
||||
// addresses associated with the passed account.
|
||||
func (r FutureGetAddressesByAccountResult) Receive() ([]btcutil.Address, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
addrStrings, ok := reply.([]string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"getaddressesbyaccount: %T\n", reply)
|
||||
// Unmashal result as an array of string.
|
||||
var addrStrings []string
|
||||
err = json.Unmarshal(res, &addrStrings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addrs := make([]btcutil.Address, 0, len(addrStrings))
|
||||
@ -1122,24 +1113,24 @@ func (c *Client) GetAddressesByAccount(account string) ([]btcutil.Address, error
|
||||
|
||||
// FutureValidateAddressResult is a future promise to deliver the result of a
|
||||
// ValidateAddressAsync RPC invocation (or an applicable error).
|
||||
type FutureValidateAddressResult chan *futureResult
|
||||
type FutureValidateAddressResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns information
|
||||
// about the given bitcoin address.
|
||||
func (r FutureValidateAddressResult) Receive() (*btcjson.ValidateAddressResult, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.(*btcjson.ValidateAddressResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"validateaddress: %T\n", reply)
|
||||
// Unmarshal result as a validateaddress result object.
|
||||
var addrResult btcjson.ValidateAddressResult
|
||||
err = json.Unmarshal(res, &addrResult)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return &addrResult, nil
|
||||
}
|
||||
|
||||
// ValidateAddressAsync returns an instance of a type that can be used to get
|
||||
@ -1165,7 +1156,7 @@ func (c *Client) ValidateAddress(address btcutil.Address) (*btcjson.ValidateAddr
|
||||
|
||||
// FutureKeyPoolRefillResult is a future promise to deliver the result of a
|
||||
// KeyPoolRefillAsync RPC invocation (or an applicable error).
|
||||
type FutureKeyPoolRefillResult chan *futureResult
|
||||
type FutureKeyPoolRefillResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the result
|
||||
// of refilling the key pool.
|
||||
@ -1228,21 +1219,21 @@ func (c *Client) KeyPoolRefillSize(newSize uint) error {
|
||||
// FutureListAccountsResult is a future promise to deliver the result of a
|
||||
// ListAccountsAsync or ListAccountsMinConfAsync RPC invocation (or an
|
||||
// applicable error).
|
||||
type FutureListAccountsResult chan *futureResult
|
||||
type FutureListAccountsResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns returns a
|
||||
// map of account names and their associated balances.
|
||||
func (r FutureListAccountsResult) Receive() (map[string]btcutil.Amount, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
accounts, ok := reply.(map[string]float64)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"listaccounts: %T\n", reply)
|
||||
// Unmarshal result as a json object.
|
||||
var accounts map[string]float64
|
||||
err = json.Unmarshal(res, &accounts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
accountsMap := make(map[string]btcutil.Amount)
|
||||
@ -1307,21 +1298,21 @@ func (c *Client) ListAccountsMinConf(minConfirms int) (map[string]btcutil.Amount
|
||||
// FutureGetBalanceResult is a future promise to deliver the result of a
|
||||
// GetBalanceAsync or GetBalanceMinConfAsync RPC invocation (or an applicable
|
||||
// error).
|
||||
type FutureGetBalanceResult chan *futureResult
|
||||
type FutureGetBalanceResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the
|
||||
// available balance from the server for the specified account.
|
||||
func (r FutureGetBalanceResult) Receive() (btcutil.Amount, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
balance, ok := reply.(float64)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("unexpected response type for "+
|
||||
"getbalance: %T\n", reply)
|
||||
// Unmarshal result as a floating point number.
|
||||
var balance float64
|
||||
err = json.Unmarshal(res, &balance)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
satoshi, err := btcjson.JSONToAmount(balance)
|
||||
@ -1391,21 +1382,21 @@ func (c *Client) GetBalanceMinConf(account string, minConfirms int) (btcutil.Amo
|
||||
// FutureGetReceivedByAccountResult is a future promise to deliver the result of
|
||||
// a GetReceivedByAccountAsync or GetReceivedByAccountMinConfAsync RPC
|
||||
// invocation (or an applicable error).
|
||||
type FutureGetReceivedByAccountResult chan *futureResult
|
||||
type FutureGetReceivedByAccountResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the total
|
||||
// amount received with the specified account.
|
||||
func (r FutureGetReceivedByAccountResult) Receive() (btcutil.Amount, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
balance, ok := reply.(float64)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("unexpected response type for "+
|
||||
"getreceivedbyaccount: %T\n", reply)
|
||||
// Unmarshal result as a floating point number.
|
||||
var balance float64
|
||||
err = json.Unmarshal(res, &balance)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
satoshi, err := btcjson.JSONToAmount(balance)
|
||||
@ -1466,21 +1457,21 @@ func (c *Client) GetReceivedByAccountMinConf(account string, minConfirms int) (b
|
||||
|
||||
// FutureGetUnconfirmedBalanceResult is a future promise to deliver the result
|
||||
// of a GetUnconfirmedBalanceAsync RPC invocation (or an applicable error).
|
||||
type FutureGetUnconfirmedBalanceResult chan *futureResult
|
||||
type FutureGetUnconfirmedBalanceResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns returns the
|
||||
// unconfirmed balance from the server for the specified account.
|
||||
func (r FutureGetUnconfirmedBalanceResult) Receive() (btcutil.Amount, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
balance, ok := reply.(float64)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("unexpected response type for "+
|
||||
"getunconfirmedbalance: %T\n", reply)
|
||||
// Unmarshal result as a floating point number.
|
||||
var balance float64
|
||||
err = json.Unmarshal(res, &balance)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
satoshi, err := btcjson.JSONToAmount(balance)
|
||||
@ -1515,21 +1506,21 @@ func (c *Client) GetUnconfirmedBalance(account string) (btcutil.Amount, error) {
|
||||
// FutureGetReceivedByAddressResult is a future promise to deliver the result of
|
||||
// a GetReceivedByAddressAsync or GetReceivedByAddressMinConfAsync RPC
|
||||
// invocation (or an applicable error).
|
||||
type FutureGetReceivedByAddressResult chan *futureResult
|
||||
type FutureGetReceivedByAddressResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the total
|
||||
// amount received by the specified address.
|
||||
func (r FutureGetReceivedByAddressResult) Receive() (btcutil.Amount, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
balance, ok := reply.(float64)
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("unexpected response type for "+
|
||||
"getreceivedbyaddress: %T\n", reply)
|
||||
// Unmarshal result as a floating point number.
|
||||
var balance float64
|
||||
err = json.Unmarshal(res, &balance)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
satoshi, err := btcjson.JSONToAmount(balance)
|
||||
@ -1594,29 +1585,24 @@ func (c *Client) GetReceivedByAddressMinConf(address btcutil.Address, minConfirm
|
||||
// of a ListReceivedByAccountAsync, ListReceivedByAccountMinConfAsync, or
|
||||
// ListReceivedByAccountIncludeEmptyAsync RPC invocation (or an applicable
|
||||
// error).
|
||||
type FutureListReceivedByAccountResult chan *futureResult
|
||||
type FutureListReceivedByAccountResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns a list of
|
||||
// balances by account.
|
||||
func (r FutureListReceivedByAccountResult) Receive() ([]btcjson.ListReceivedByAccountResult, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// No results.
|
||||
if reply == nil {
|
||||
return nil, nil
|
||||
// Unmarshal as an array of listreceivedbyaccount result objects.
|
||||
var received []btcjson.ListReceivedByAccountResult
|
||||
err = json.Unmarshal(res, &received)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
result, ok := reply.([]btcjson.ListReceivedByAccountResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"listreceivedbyaccount: %T\n", reply)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return received, nil
|
||||
}
|
||||
|
||||
// ListReceivedByAccountAsync returns an instance of a type that can be used to
|
||||
@ -1702,7 +1688,7 @@ func (c *Client) ListReceivedByAccountIncludeEmpty(minConfirms int, includeEmpty
|
||||
|
||||
// FutureWalletLockResult is a future promise to deliver the result of a
|
||||
// WalletLockAsync RPC invocation (or an applicable error).
|
||||
type FutureWalletLockResult chan *futureResult
|
||||
type FutureWalletLockResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the result
|
||||
// of locking the wallet.
|
||||
@ -1759,7 +1745,7 @@ func (c *Client) WalletPassphrase(passphrase string, timeoutSecs int64) error {
|
||||
|
||||
// FutureWalletPassphraseChangeResult is a future promise to deliver the result
|
||||
// of a WalletPassphraseChangeAsync RPC invocation (or an applicable error).
|
||||
type FutureWalletPassphraseChangeResult chan *futureResult
|
||||
type FutureWalletPassphraseChangeResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the result
|
||||
// of changing the wallet passphrase.
|
||||
@ -1799,21 +1785,21 @@ func (c *Client) WalletPassphraseChange(old, new string) error {
|
||||
|
||||
// FutureSignMessageResult is a future promise to deliver the result of a
|
||||
// SignMessageAsync RPC invocation (or an applicable error).
|
||||
type FutureSignMessageResult chan *futureResult
|
||||
type FutureSignMessageResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the message
|
||||
// signed with the private key of the specified address.
|
||||
func (r FutureSignMessageResult) Receive() (string, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
b64, ok := reply.(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("unexpected response type for "+
|
||||
"signmessage: %T\n", reply)
|
||||
// Unmarshal result as a string.
|
||||
var b64 string
|
||||
err = json.Unmarshal(res, &b64)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return b64, nil
|
||||
@ -1845,21 +1831,21 @@ func (c *Client) SignMessage(address btcutil.Address, message string) (string, e
|
||||
|
||||
// FutureVerifyMessageResult is a future promise to deliver the result of a
|
||||
// VerifyMessageAsync RPC invocation (or an applicable error).
|
||||
type FutureVerifyMessageResult chan *futureResult
|
||||
type FutureVerifyMessageResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns whether or
|
||||
// not the message was successfully verified.
|
||||
func (r FutureVerifyMessageResult) Receive() (bool, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
verified, ok := reply.(bool)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("unexpected response type for "+
|
||||
"verifymessage: %T\n", reply)
|
||||
// Unmarshal result as a boolean.
|
||||
var verified bool
|
||||
err = json.Unmarshal(res, &verified)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return verified, nil
|
||||
@ -1895,22 +1881,22 @@ func (c *Client) VerifyMessage(address btcutil.Address, signature, message strin
|
||||
|
||||
// FutureDumpPrivKeyResult is a future promise to deliver the result of a
|
||||
// DumpPrivKeyAsync RPC invocation (or an applicable error).
|
||||
type FutureDumpPrivKeyResult chan *futureResult
|
||||
type FutureDumpPrivKeyResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the private
|
||||
// key corresponding to the passed address encoded in the wallet import format
|
||||
// (WIF)
|
||||
func (r FutureDumpPrivKeyResult) Receive() (*btcutil.WIF, error) {
|
||||
reply, err := receiveFuture(r)
|
||||
res, err := receiveFuture(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure the returned data is the expected type.
|
||||
privKeyWIF, ok := reply.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected response type for "+
|
||||
"dumpprivkey: %T\n", reply)
|
||||
// Unmarshal result as a string.
|
||||
var privKeyWIF string
|
||||
err = json.Unmarshal(res, &privKeyWIF)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return btcutil.DecodeWIF(privKeyWIF)
|
||||
@ -1943,7 +1929,7 @@ func (c *Client) DumpPrivKey(address btcutil.Address) (*btcutil.WIF, error) {
|
||||
|
||||
// FutureImportPrivKeyResult is a future promise to deliver the result of an
|
||||
// ImportPrivKeyAsync RPC invocation (or an applicable error).
|
||||
type FutureImportPrivKeyResult chan *futureResult
|
||||
type FutureImportPrivKeyResult chan *response
|
||||
|
||||
// Receive waits for the response promised by the future and returns the result
|
||||
// of importing the passed private key which must be the wallet import format
|
||||
|
Loading…
Reference in New Issue
Block a user