lbcd/rpcclient/extensions.go

474 lines
15 KiB
Go
Raw Normal View History

// Copyright (c) 2014-2017 The btcsuite developers
// Copyright (c) 2015-2017 The Decred developers
2014-05-07 18:14:39 +02:00
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package rpcclient
2014-05-07 18:14:39 +02:00
import (
"bytes"
2014-05-07 18:14:39 +02:00
"encoding/base64"
"encoding/hex"
"encoding/json"
2014-05-07 18:14:39 +02:00
"fmt"
2014-07-03 02:33:54 +02:00
"github.com/btcsuite/btcd/btcjson"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
2014-05-07 18:14:39 +02:00
)
// FutureDebugLevelResult is a future promise to deliver the result of a
// DebugLevelAsync RPC invocation (or an applicable error).
type FutureDebugLevelResult chan *response
2014-05-07 18:14:39 +02:00
// Receive waits for the response promised by the future and returns the result
// of setting the debug logging level to the passed level specification or the
// list of of the available subsystems for the special keyword 'show'.
func (r FutureDebugLevelResult) Receive() (string, error) {
res, err := receiveFuture(r)
2014-05-07 18:14:39 +02:00
if err != nil {
return "", err
}
// Unmashal the result as a string.
var result string
err = json.Unmarshal(res, &result)
if err != nil {
return "", err
2014-05-07 18:14:39 +02:00
}
return result, nil
}
// DebugLevelAsync returns an instance of a type that can be used to get the
// result of the RPC at some future time by invoking the Receive function on
// the returned instance.
//
// See DebugLevel for the blocking version and more details.
//
// NOTE: This is a btcd extension.
func (c *Client) DebugLevelAsync(levelSpec string) FutureDebugLevelResult {
Update to make use of latest version of btcjson. This commit contains several changes needed to update the client to use the latest version of btcjson. In addition, it contains a couple of other minor changes along the way. While the underlying changes are quite large, the public API of this package is still the same, so caller should generally not have to update their code due to that. However, the underlying btcjson package API has changed significantly. Since this package hides the vast majority of that from callers, it should not afffect them very much. However, one area in particular to watch out for is that the old btcjson.Error is now btcjson.RPCError, so any callers doing any type assertions there will need to update. The following is a summary of the changes: - The underlying btcjson significantly changed how commands work, so the internals of this package have been reworked to be based off of requests instead of the now non-existant btcjson.Cmd interface - Update all call sites of btcjson.New<Foo>Cmd since they can no longer error or take varargs - The ids for each request are part of the request now instead of the command to match the new btcjson model and are strict uint64s so type assertions are no longer needed (slightly improved efficiency) - Remove the old temporary workaround for the getbalance command with an account of "*" since btcwallet has since been fixed - Change all instances of JSONToAmount to btcutil.NewAmount since that function was removed in favor of btcutil.Amount - Change all btcws invocations to btcjson since they have been combined
2015-01-01 23:34:07 +01:00
cmd := btcjson.NewDebugLevelCmd(levelSpec)
return c.sendCmd(cmd)
}
// DebugLevel dynamically sets the debug logging level to the passed level
// specification.
//
2015-09-20 13:42:49 +02:00
// The levelspec can be either a debug level or of the form:
// <subsystem>=<level>,<subsystem2>=<level2>,...
//
// Additionally, the special keyword 'show' can be used to get a list of the
// available subsystems.
//
// NOTE: This is a btcd extension.
func (c *Client) DebugLevel(levelSpec string) (string, error) {
return c.DebugLevelAsync(levelSpec).Receive()
}
// FutureCreateEncryptedWalletResult is a future promise to deliver the error
// result of a CreateEncryptedWalletAsync RPC invocation.
type FutureCreateEncryptedWalletResult chan *response
// Receive waits for and returns the error response promised by the future.
func (r FutureCreateEncryptedWalletResult) Receive() error {
_, err := receiveFuture(r)
return err
}
// CreateEncryptedWalletAsync returns an instance of a type that can be used to
// get the result of the RPC at some future time by invoking the Receive
// function on the returned instance.
//
// See CreateEncryptedWallet for the blocking version and more details.
//
// NOTE: This is a btcwallet extension.
func (c *Client) CreateEncryptedWalletAsync(passphrase string) FutureCreateEncryptedWalletResult {
Update to make use of latest version of btcjson. This commit contains several changes needed to update the client to use the latest version of btcjson. In addition, it contains a couple of other minor changes along the way. While the underlying changes are quite large, the public API of this package is still the same, so caller should generally not have to update their code due to that. However, the underlying btcjson package API has changed significantly. Since this package hides the vast majority of that from callers, it should not afffect them very much. However, one area in particular to watch out for is that the old btcjson.Error is now btcjson.RPCError, so any callers doing any type assertions there will need to update. The following is a summary of the changes: - The underlying btcjson significantly changed how commands work, so the internals of this package have been reworked to be based off of requests instead of the now non-existant btcjson.Cmd interface - Update all call sites of btcjson.New<Foo>Cmd since they can no longer error or take varargs - The ids for each request are part of the request now instead of the command to match the new btcjson model and are strict uint64s so type assertions are no longer needed (slightly improved efficiency) - Remove the old temporary workaround for the getbalance command with an account of "*" since btcwallet has since been fixed - Change all instances of JSONToAmount to btcutil.NewAmount since that function was removed in favor of btcutil.Amount - Change all btcws invocations to btcjson since they have been combined
2015-01-01 23:34:07 +01:00
cmd := btcjson.NewCreateEncryptedWalletCmd(passphrase)
return c.sendCmd(cmd)
}
// CreateEncryptedWallet requests the creation of an encrypted wallet. Wallets
// managed by btcwallet are only written to disk with encrypted private keys,
// and generating wallets on the fly is impossible as it requires user input for
// the encryption passphrase. This RPC specifies the passphrase and instructs
// the wallet creation. This may error if a wallet is already opened, or the
// new wallet cannot be written to disk.
//
// NOTE: This is a btcwallet extension.
func (c *Client) CreateEncryptedWallet(passphrase string) error {
return c.CreateEncryptedWalletAsync(passphrase).Receive()
}
2014-05-07 18:14:39 +02:00
// FutureListAddressTransactionsResult is a future promise to deliver the result
// of a ListAddressTransactionsAsync RPC invocation (or an applicable error).
type FutureListAddressTransactionsResult chan *response
2014-05-07 18:14:39 +02:00
// Receive waits for the response promised by the future and returns information
// about all transactions associated with the provided addresses.
func (r FutureListAddressTransactionsResult) Receive() ([]btcjson.ListTransactionsResult, error) {
res, err := receiveFuture(r)
2014-05-07 18:14:39 +02:00
if err != nil {
return nil, err
}
// Unmarshal the result as an array of listtransactions objects.
var transactions []btcjson.ListTransactionsResult
err = json.Unmarshal(res, &transactions)
if err != nil {
return nil, err
2014-05-07 18:14:39 +02:00
}
return transactions, nil
}
// ListAddressTransactionsAsync returns an instance of a type that can be used
// to get the result of the RPC at some future time by invoking the Receive
// function on the returned instance.
//
// See ListAddressTransactions for the blocking version and more details.
//
// NOTE: This is a btcd extension.
func (c *Client) ListAddressTransactionsAsync(addresses []btcutil.Address, account string) FutureListAddressTransactionsResult {
// Convert addresses to strings.
addrs := make([]string, 0, len(addresses))
for _, addr := range addresses {
addrs = append(addrs, addr.EncodeAddress())
}
Update to make use of latest version of btcjson. This commit contains several changes needed to update the client to use the latest version of btcjson. In addition, it contains a couple of other minor changes along the way. While the underlying changes are quite large, the public API of this package is still the same, so caller should generally not have to update their code due to that. However, the underlying btcjson package API has changed significantly. Since this package hides the vast majority of that from callers, it should not afffect them very much. However, one area in particular to watch out for is that the old btcjson.Error is now btcjson.RPCError, so any callers doing any type assertions there will need to update. The following is a summary of the changes: - The underlying btcjson significantly changed how commands work, so the internals of this package have been reworked to be based off of requests instead of the now non-existant btcjson.Cmd interface - Update all call sites of btcjson.New<Foo>Cmd since they can no longer error or take varargs - The ids for each request are part of the request now instead of the command to match the new btcjson model and are strict uint64s so type assertions are no longer needed (slightly improved efficiency) - Remove the old temporary workaround for the getbalance command with an account of "*" since btcwallet has since been fixed - Change all instances of JSONToAmount to btcutil.NewAmount since that function was removed in favor of btcutil.Amount - Change all btcws invocations to btcjson since they have been combined
2015-01-01 23:34:07 +01:00
cmd := btcjson.NewListAddressTransactionsCmd(addrs, &account)
2014-05-07 18:14:39 +02:00
return c.sendCmd(cmd)
}
// ListAddressTransactions returns information about all transactions associated
// with the provided addresses.
//
// NOTE: This is a btcwallet extension.
func (c *Client) ListAddressTransactions(addresses []btcutil.Address, account string) ([]btcjson.ListTransactionsResult, error) {
return c.ListAddressTransactionsAsync(addresses, account).Receive()
}
// FutureGetBestBlockResult is a future promise to deliver the result of a
// GetBestBlockAsync RPC invocation (or an applicable error).
type FutureGetBestBlockResult chan *response
2014-05-07 18:14:39 +02:00
// Receive waits for the response promised by the future and returns the hash
// and height of the block in the longest (best) chain.
func (r FutureGetBestBlockResult) Receive() (*chainhash.Hash, int32, error) {
res, err := receiveFuture(r)
2014-05-07 18:14:39 +02:00
if err != nil {
return nil, 0, err
}
2015-09-20 13:42:49 +02:00
// Unmarshal result as a getbestblock result object.
Update to make use of latest version of btcjson. This commit contains several changes needed to update the client to use the latest version of btcjson. In addition, it contains a couple of other minor changes along the way. While the underlying changes are quite large, the public API of this package is still the same, so caller should generally not have to update their code due to that. However, the underlying btcjson package API has changed significantly. Since this package hides the vast majority of that from callers, it should not afffect them very much. However, one area in particular to watch out for is that the old btcjson.Error is now btcjson.RPCError, so any callers doing any type assertions there will need to update. The following is a summary of the changes: - The underlying btcjson significantly changed how commands work, so the internals of this package have been reworked to be based off of requests instead of the now non-existant btcjson.Cmd interface - Update all call sites of btcjson.New<Foo>Cmd since they can no longer error or take varargs - The ids for each request are part of the request now instead of the command to match the new btcjson model and are strict uint64s so type assertions are no longer needed (slightly improved efficiency) - Remove the old temporary workaround for the getbalance command with an account of "*" since btcwallet has since been fixed - Change all instances of JSONToAmount to btcutil.NewAmount since that function was removed in favor of btcutil.Amount - Change all btcws invocations to btcjson since they have been combined
2015-01-01 23:34:07 +01:00
var bestBlock btcjson.GetBestBlockResult
err = json.Unmarshal(res, &bestBlock)
if err != nil {
return nil, 0, err
2014-05-07 18:14:39 +02:00
}
2015-09-20 13:42:49 +02:00
// Convert to hash from string.
hash, err := chainhash.NewHashFromStr(bestBlock.Hash)
2014-05-07 18:14:39 +02:00
if err != nil {
return nil, 0, err
}
return hash, bestBlock.Height, nil
2014-05-07 18:14:39 +02:00
}
// GetBestBlockAsync returns an instance of a type that can be used to get the
// result of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See GetBestBlock for the blocking version and more details.
//
// NOTE: This is a btcd extension.
func (c *Client) GetBestBlockAsync() FutureGetBestBlockResult {
Update to make use of latest version of btcjson. This commit contains several changes needed to update the client to use the latest version of btcjson. In addition, it contains a couple of other minor changes along the way. While the underlying changes are quite large, the public API of this package is still the same, so caller should generally not have to update their code due to that. However, the underlying btcjson package API has changed significantly. Since this package hides the vast majority of that from callers, it should not afffect them very much. However, one area in particular to watch out for is that the old btcjson.Error is now btcjson.RPCError, so any callers doing any type assertions there will need to update. The following is a summary of the changes: - The underlying btcjson significantly changed how commands work, so the internals of this package have been reworked to be based off of requests instead of the now non-existant btcjson.Cmd interface - Update all call sites of btcjson.New<Foo>Cmd since they can no longer error or take varargs - The ids for each request are part of the request now instead of the command to match the new btcjson model and are strict uint64s so type assertions are no longer needed (slightly improved efficiency) - Remove the old temporary workaround for the getbalance command with an account of "*" since btcwallet has since been fixed - Change all instances of JSONToAmount to btcutil.NewAmount since that function was removed in favor of btcutil.Amount - Change all btcws invocations to btcjson since they have been combined
2015-01-01 23:34:07 +01:00
cmd := btcjson.NewGetBestBlockCmd()
2014-05-07 18:14:39 +02:00
return c.sendCmd(cmd)
}
// GetBestBlock returns the hash and height of the block in the longest (best)
// chain.
//
// NOTE: This is a btcd extension.
func (c *Client) GetBestBlock() (*chainhash.Hash, int32, error) {
2014-05-07 18:14:39 +02:00
return c.GetBestBlockAsync().Receive()
}
// FutureGetCurrentNetResult is a future promise to deliver the result of a
// GetCurrentNetAsync RPC invocation (or an applicable error).
type FutureGetCurrentNetResult chan *response
2014-05-07 18:14:39 +02:00
// Receive waits for the response promised by the future and returns the network
// the server is running on.
func (r FutureGetCurrentNetResult) Receive() (wire.BitcoinNet, error) {
res, err := receiveFuture(r)
2014-05-07 18:14:39 +02:00
if err != nil {
return 0, err
}
// Unmarshal result as an int64.
var net int64
err = json.Unmarshal(res, &net)
if err != nil {
return 0, err
2014-05-07 18:14:39 +02:00
}
return wire.BitcoinNet(net), nil
2014-05-07 18:14:39 +02:00
}
// GetCurrentNetAsync returns an instance of a type that can be used to get the
// result of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See GetCurrentNet for the blocking version and more details.
//
// NOTE: This is a btcd extension.
func (c *Client) GetCurrentNetAsync() FutureGetCurrentNetResult {
Update to make use of latest version of btcjson. This commit contains several changes needed to update the client to use the latest version of btcjson. In addition, it contains a couple of other minor changes along the way. While the underlying changes are quite large, the public API of this package is still the same, so caller should generally not have to update their code due to that. However, the underlying btcjson package API has changed significantly. Since this package hides the vast majority of that from callers, it should not afffect them very much. However, one area in particular to watch out for is that the old btcjson.Error is now btcjson.RPCError, so any callers doing any type assertions there will need to update. The following is a summary of the changes: - The underlying btcjson significantly changed how commands work, so the internals of this package have been reworked to be based off of requests instead of the now non-existant btcjson.Cmd interface - Update all call sites of btcjson.New<Foo>Cmd since they can no longer error or take varargs - The ids for each request are part of the request now instead of the command to match the new btcjson model and are strict uint64s so type assertions are no longer needed (slightly improved efficiency) - Remove the old temporary workaround for the getbalance command with an account of "*" since btcwallet has since been fixed - Change all instances of JSONToAmount to btcutil.NewAmount since that function was removed in favor of btcutil.Amount - Change all btcws invocations to btcjson since they have been combined
2015-01-01 23:34:07 +01:00
cmd := btcjson.NewGetCurrentNetCmd()
2014-05-07 18:14:39 +02:00
return c.sendCmd(cmd)
}
// GetCurrentNet returns the network the server is running on.
//
// NOTE: This is a btcd extension.
func (c *Client) GetCurrentNet() (wire.BitcoinNet, error) {
2014-05-07 18:14:39 +02:00
return c.GetCurrentNetAsync().Receive()
}
// FutureGetHeadersResult is a future promise to deliver the result of a
// getheaders RPC invocation (or an applicable error).
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
type FutureGetHeadersResult chan *response
// Receive waits for the response promised by the future and returns the
// getheaders result.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (r FutureGetHeadersResult) Receive() ([]wire.BlockHeader, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal result as a slice of strings.
var result []string
err = json.Unmarshal(res, &result)
if err != nil {
return nil, err
}
// Deserialize the []string into []wire.BlockHeader.
headers := make([]wire.BlockHeader, len(result))
for i, headerHex := range result {
serialized, err := hex.DecodeString(headerHex)
if err != nil {
return nil, err
}
err = headers[i].Deserialize(bytes.NewReader(serialized))
if err != nil {
return nil, err
}
}
return headers, nil
}
// GetHeadersAsync returns an instance of a type that can be used to get the result
// of the RPC at some future time by invoking the Receive function on the returned instance.
//
// See GetHeaders for the blocking version and more details.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (c *Client) GetHeadersAsync(blockLocators []chainhash.Hash, hashStop *chainhash.Hash) FutureGetHeadersResult {
locators := make([]string, len(blockLocators))
for i := range blockLocators {
locators[i] = blockLocators[i].String()
}
hash := ""
if hashStop != nil {
hash = hashStop.String()
}
cmd := btcjson.NewGetHeadersCmd(locators, hash)
return c.sendCmd(cmd)
}
// GetHeaders mimics the wire protocol getheaders and headers messages by
// returning all headers on the main chain after the first known block in the
// locators, up until a block hash matches hashStop.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (c *Client) GetHeaders(blockLocators []chainhash.Hash, hashStop *chainhash.Hash) ([]wire.BlockHeader, error) {
return c.GetHeadersAsync(blockLocators, hashStop).Receive()
}
2014-05-07 18:14:39 +02:00
// FutureExportWatchingWalletResult is a future promise to deliver the result of
// an ExportWatchingWalletAsync RPC invocation (or an applicable error).
type FutureExportWatchingWalletResult chan *response
2014-05-07 18:14:39 +02:00
// Receive waits for the response promised by the future and returns the
// exported wallet.
func (r FutureExportWatchingWalletResult) Receive() ([]byte, []byte, error) {
res, err := receiveFuture(r)
2014-05-07 18:14:39 +02:00
if err != nil {
return nil, nil, err
}
// Unmarshal result as a JSON object.
var obj map[string]interface{}
err = json.Unmarshal(res, &obj)
if err != nil {
return nil, nil, err
2014-05-07 18:14:39 +02:00
}
// Check for the wallet and tx string fields in the object.
base64Wallet, ok := obj["wallet"].(string)
2014-05-07 18:14:39 +02:00
if !ok {
return nil, nil, fmt.Errorf("unexpected response type for "+
"exportwatchingwallet 'wallet' field: %T\n",
obj["wallet"])
2014-05-07 18:14:39 +02:00
}
base64TxStore, ok := obj["tx"].(string)
2014-05-07 18:14:39 +02:00
if !ok {
return nil, nil, fmt.Errorf("unexpected response type for "+
"exportwatchingwallet 'tx' field: %T\n",
obj["tx"])
2014-05-07 18:14:39 +02:00
}
walletBytes, err := base64.StdEncoding.DecodeString(base64Wallet)
if err != nil {
return nil, nil, err
}
txStoreBytes, err := base64.StdEncoding.DecodeString(base64TxStore)
if err != nil {
return nil, nil, err
}
return walletBytes, txStoreBytes, nil
}
// ExportWatchingWalletAsync returns an instance of a type that can be used to
// get the result of the RPC at some future time by invoking the Receive
// function on the returned instance.
//
// See ExportWatchingWallet for the blocking version and more details.
//
// NOTE: This is a btcwallet extension.
func (c *Client) ExportWatchingWalletAsync(account string) FutureExportWatchingWalletResult {
Update to make use of latest version of btcjson. This commit contains several changes needed to update the client to use the latest version of btcjson. In addition, it contains a couple of other minor changes along the way. While the underlying changes are quite large, the public API of this package is still the same, so caller should generally not have to update their code due to that. However, the underlying btcjson package API has changed significantly. Since this package hides the vast majority of that from callers, it should not afffect them very much. However, one area in particular to watch out for is that the old btcjson.Error is now btcjson.RPCError, so any callers doing any type assertions there will need to update. The following is a summary of the changes: - The underlying btcjson significantly changed how commands work, so the internals of this package have been reworked to be based off of requests instead of the now non-existant btcjson.Cmd interface - Update all call sites of btcjson.New<Foo>Cmd since they can no longer error or take varargs - The ids for each request are part of the request now instead of the command to match the new btcjson model and are strict uint64s so type assertions are no longer needed (slightly improved efficiency) - Remove the old temporary workaround for the getbalance command with an account of "*" since btcwallet has since been fixed - Change all instances of JSONToAmount to btcutil.NewAmount since that function was removed in favor of btcutil.Amount - Change all btcws invocations to btcjson since they have been combined
2015-01-01 23:34:07 +01:00
cmd := btcjson.NewExportWatchingWalletCmd(&account, btcjson.Bool(true))
2014-05-07 18:14:39 +02:00
return c.sendCmd(cmd)
}
// ExportWatchingWallet returns the raw bytes for a watching-only version of
// wallet.bin and tx.bin, respectively, for the specified account that can be
// used by btcwallet to enable a wallet which does not have the private keys
// necessary to spend funds.
//
// NOTE: This is a btcwallet extension.
func (c *Client) ExportWatchingWallet(account string) ([]byte, []byte, error) {
return c.ExportWatchingWalletAsync(account).Receive()
}
// FutureSessionResult is a future promise to deliver the result of a
// SessionAsync RPC invocation (or an applicable error).
type FutureSessionResult chan *response
// Receive waits for the response promised by the future and returns the
// session result.
func (r FutureSessionResult) Receive() (*btcjson.SessionResult, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
2015-09-20 13:42:49 +02:00
// Unmarshal result as a session result object.
var session btcjson.SessionResult
err = json.Unmarshal(res, &session)
if err != nil {
return nil, err
}
return &session, nil
}
// SessionAsync returns an instance of a type that can be used to get the result
// of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See Session for the blocking version and more details.
//
// NOTE: This is a btcsuite extension.
func (c *Client) SessionAsync() FutureSessionResult {
// Not supported in HTTP POST mode.
if c.config.HTTPPostMode {
return newFutureError(ErrWebsocketsRequired)
}
cmd := btcjson.NewSessionCmd()
return c.sendCmd(cmd)
}
// Session returns details regarding a websocket client's current connection.
//
// This RPC requires the client to be running in websocket mode.
//
// NOTE: This is a btcsuite extension.
func (c *Client) Session() (*btcjson.SessionResult, error) {
return c.SessionAsync().Receive()
}
// FutureVersionResult is a future promise to delivere the result of a version
// RPC invocation (or an applicable error).
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
type FutureVersionResult chan *response
// Receive waits for the response promised by the future and returns the version
// result.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (r FutureVersionResult) Receive() (map[string]btcjson.VersionResult,
error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal result as a version result object.
var vr map[string]btcjson.VersionResult
err = json.Unmarshal(res, &vr)
if err != nil {
return nil, err
}
return vr, nil
}
// VersionAsync returns an instance of a type that can be used to get the result
// of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See Version for the blocking version and more details.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (c *Client) VersionAsync() FutureVersionResult {
cmd := btcjson.NewVersionCmd()
return c.sendCmd(cmd)
}
// Version returns information about the server's JSON-RPC API versions.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (c *Client) Version() (map[string]btcjson.VersionResult, error) {
return c.VersionAsync().Receive()
}