// Copyright (c) 2014-2017 The btcsuite developers // Copyright (c) 2015-2017 The Decred developers // Use of this source code is governed by an ISC // license that can be found in the LICENSE file. package rpcclient import ( "bytes" "encoding/hex" "encoding/json" "github.com/daglabs/btcd/btcjson" "github.com/daglabs/btcd/util/daghash" "github.com/daglabs/btcd/wire" ) // FutureDebugLevelResult is a future promise to deliver the result of a // DebugLevelAsync RPC invocation (or an applicable error). type FutureDebugLevelResult chan *response // Receive waits for the response promised by the future and returns the result // of setting the debug logging level to the passed level specification or the // list of of the available subsystems for the special keyword 'show'. func (r FutureDebugLevelResult) Receive() (string, error) { res, err := receiveFuture(r) if err != nil { return "", err } // Unmashal the result as a string. var result string err = json.Unmarshal(res, &result) if err != nil { return "", err } return result, nil } // DebugLevelAsync returns an instance of a type that can be used to get the // result of the RPC at some future time by invoking the Receive function on // the returned instance. // // See DebugLevel for the blocking version and more details. // // NOTE: This is a btcd extension. func (c *Client) DebugLevelAsync(levelSpec string) FutureDebugLevelResult { cmd := btcjson.NewDebugLevelCmd(levelSpec) return c.sendCmd(cmd) } // DebugLevel dynamically sets the debug logging level to the passed level // specification. // // The levelspec can be either a debug level or of the form: // =,=,... // // 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() } // FutureGetBestBlockResult is a future promise to deliver the result of a // GetBestBlockAsync RPC invocation (or an applicable error). type FutureGetBestBlockResult chan *response // Receive waits for the response promised by the future and returns the hash // and height of the block in the longest (best) chain. func (r FutureGetBestBlockResult) Receive() (*daghash.Hash, uint64, error) { res, err := receiveFuture(r) if err != nil { return nil, 0, err } // Unmarshal result as a getbestblock result object. var bestBlock btcjson.GetBestBlockResult err = json.Unmarshal(res, &bestBlock) if err != nil { return nil, 0, err } // Convert to hash from string. hash, err := daghash.NewHashFromStr(bestBlock.Hash) if err != nil { return nil, 0, err } return hash, bestBlock.Height, nil } // GetBestBlockAsync returns an instance of a type that can be used to get the // result of the RPC at some future time by invoking the Receive function on the // returned instance. // // See GetBestBlock for the blocking version and more details. // // NOTE: This is a btcd extension. func (c *Client) GetBestBlockAsync() FutureGetBestBlockResult { cmd := btcjson.NewGetBestBlockCmd() return c.sendCmd(cmd) } // GetBestBlock returns the hash and height of the block in the longest (best) // chain. // // NOTE: This is a btcd extension. func (c *Client) GetBestBlock() (*daghash.Hash, uint64, error) { return c.GetBestBlockAsync().Receive() } // FutureGetCurrentNetResult is a future promise to deliver the result of a // GetCurrentNetAsync RPC invocation (or an applicable error). type FutureGetCurrentNetResult chan *response // Receive waits for the response promised by the future and returns the network // the server is running on. func (r FutureGetCurrentNetResult) Receive() (wire.BitcoinNet, error) { res, err := receiveFuture(r) if err != nil { return 0, err } // Unmarshal result as an int64. var net int64 err = json.Unmarshal(res, &net) if err != nil { return 0, err } return wire.BitcoinNet(net), nil } // GetCurrentNetAsync returns an instance of a type that can be used to get the // result of the RPC at some future time by invoking the Receive function on the // returned instance. // // See GetCurrentNet for the blocking version and more details. // // NOTE: This is a btcd extension. func (c *Client) GetCurrentNetAsync() FutureGetCurrentNetResult { cmd := btcjson.NewGetCurrentNetCmd() return c.sendCmd(cmd) } // GetCurrentNet returns the network the server is running on. // // NOTE: This is a btcd extension. func (c *Client) GetCurrentNet() (wire.BitcoinNet, error) { return c.GetCurrentNetAsync().Receive() } // FutureGetHeadersResult is a future promise to deliver the result of a // getheaders RPC invocation (or an applicable error). // // NOTE: This is a btcsuite extension ported from // github.com/decred/dcrrpcclient. type FutureGetHeadersResult chan *response // Receive waits for the response promised by the future and returns the // getheaders result. // // NOTE: This is a btcsuite extension ported from // github.com/decred/dcrrpcclient. func (r FutureGetHeadersResult) Receive() ([]wire.BlockHeader, error) { res, err := receiveFuture(r) if err != nil { return nil, err } // Unmarshal result as a slice of strings. var result []string err = json.Unmarshal(res, &result) if err != nil { return nil, err } // Deserialize the []string into []wire.BlockHeader. headers := make([]wire.BlockHeader, len(result)) for i, headerHex := range result { serialized, err := hex.DecodeString(headerHex) if err != nil { return nil, err } err = headers[i].Deserialize(bytes.NewReader(serialized)) if err != nil { return nil, err } } return headers, nil } // GetTopHeadersAsync 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 GetTopHeaders for the blocking version and more details. func (c *Client) GetTopHeadersAsync(startHash *daghash.Hash) FutureGetHeadersResult { var hash *string if startHash != nil { hash = btcjson.String(startHash.String()) } cmd := btcjson.NewGetTopHeadersCmd(hash) return c.sendCmd(cmd) } // GetTopHeaders sends a getTopHeaders rpc command to the server. func (c *Client) GetTopHeaders(startHash *daghash.Hash) ([]wire.BlockHeader, error) { return c.GetTopHeadersAsync(startHash).Receive() } // 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(startHash, stopHash *daghash.Hash) FutureGetHeadersResult { startHashStr := "" if startHash != nil { startHashStr = startHash.String() } stopHashStr := "" if stopHash != nil { stopHashStr = stopHash.String() } cmd := btcjson.NewGetHeadersCmd(startHashStr, stopHashStr) 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 stopHash. // // NOTE: This is a btcsuite extension ported from // github.com/decred/dcrrpcclient. func (c *Client) GetHeaders(startHash, stopHash *daghash.Hash) ([]wire.BlockHeader, error) { return c.GetHeadersAsync(startHash, stopHash).Receive() } // FutureSessionResult is a future promise to deliver the result of a // SessionAsync RPC invocation (or an applicable error). type FutureSessionResult chan *response // Receive waits for the response promised by the future and returns the // session result. func (r FutureSessionResult) Receive() (*btcjson.SessionResult, error) { res, err := receiveFuture(r) if err != nil { return nil, err } // Unmarshal result as a session result object. var session btcjson.SessionResult err = json.Unmarshal(res, &session) if err != nil { return nil, err } return &session, nil } // SessionAsync returns an instance of a type that can be used to get the result // of the RPC at some future time by invoking the Receive function on the // returned instance. // // See Session for the blocking version and more details. // // NOTE: This is a btcsuite extension. func (c *Client) SessionAsync() FutureSessionResult { // Not supported in HTTP POST mode. if c.config.HTTPPostMode { return newFutureError(ErrWebsocketsRequired) } cmd := btcjson.NewSessionCmd() return c.sendCmd(cmd) } // Session returns details regarding a websocket client's current connection. // // This RPC requires the client to be running in websocket mode. // // NOTE: This is a btcsuite extension. func (c *Client) Session() (*btcjson.SessionResult, error) { return c.SessionAsync().Receive() } // FutureVersionResult is a future promise to deliver 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() }