github.com/palcoin-project/palcd@v1.0.0/rpcclient/extensions.go (about)

     1  // Copyright (c) 2014-2017 The btcsuite developers
     2  // Copyright (c) 2015-2017 The Decred developers
     3  // Use of this source code is governed by an ISC
     4  // license that can be found in the LICENSE file.
     5  
     6  package rpcclient
     7  
     8  import (
     9  	"bytes"
    10  	"encoding/base64"
    11  	"encoding/hex"
    12  	"encoding/json"
    13  	"fmt"
    14  
    15  	"github.com/palcoin-project/palcd/btcjson"
    16  	"github.com/palcoin-project/palcd/chaincfg/chainhash"
    17  	"github.com/palcoin-project/palcd/wire"
    18  	"github.com/palcoin-project/palcutil"
    19  )
    20  
    21  // FutureDebugLevelResult is a future promise to deliver the result of a
    22  // DebugLevelAsync RPC invocation (or an applicable error).
    23  type FutureDebugLevelResult chan *response
    24  
    25  // Receive waits for the response promised by the future and returns the result
    26  // of setting the debug logging level to the passed level specification or the
    27  // list of of the available subsystems for the special keyword 'show'.
    28  func (r FutureDebugLevelResult) Receive() (string, error) {
    29  	res, err := receiveFuture(r)
    30  	if err != nil {
    31  		return "", err
    32  	}
    33  
    34  	// Unmashal the result as a string.
    35  	var result string
    36  	err = json.Unmarshal(res, &result)
    37  	if err != nil {
    38  		return "", err
    39  	}
    40  	return result, nil
    41  }
    42  
    43  // DebugLevelAsync returns an instance of a type that can be used to get the
    44  // result of the RPC at some future time by invoking the Receive function on
    45  // the returned instance.
    46  //
    47  // See DebugLevel for the blocking version and more details.
    48  //
    49  // NOTE: This is a btcd extension.
    50  func (c *Client) DebugLevelAsync(levelSpec string) FutureDebugLevelResult {
    51  	cmd := btcjson.NewDebugLevelCmd(levelSpec)
    52  	return c.sendCmd(cmd)
    53  }
    54  
    55  // DebugLevel dynamically sets the debug logging level to the passed level
    56  // specification.
    57  //
    58  // The levelspec can be either a debug level or of the form:
    59  // 	<subsystem>=<level>,<subsystem2>=<level2>,...
    60  //
    61  // Additionally, the special keyword 'show' can be used to get a list of the
    62  // available subsystems.
    63  //
    64  // NOTE: This is a btcd extension.
    65  func (c *Client) DebugLevel(levelSpec string) (string, error) {
    66  	return c.DebugLevelAsync(levelSpec).Receive()
    67  }
    68  
    69  // FutureCreateEncryptedWalletResult is a future promise to deliver the error
    70  // result of a CreateEncryptedWalletAsync RPC invocation.
    71  type FutureCreateEncryptedWalletResult chan *response
    72  
    73  // Receive waits for and returns the error response promised by the future.
    74  func (r FutureCreateEncryptedWalletResult) Receive() error {
    75  	_, err := receiveFuture(r)
    76  	return err
    77  }
    78  
    79  // CreateEncryptedWalletAsync returns an instance of a type that can be used to
    80  // get the result of the RPC at some future time by invoking the Receive
    81  // function on the returned instance.
    82  //
    83  // See CreateEncryptedWallet for the blocking version and more details.
    84  //
    85  // NOTE: This is a btcwallet extension.
    86  func (c *Client) CreateEncryptedWalletAsync(passphrase string) FutureCreateEncryptedWalletResult {
    87  	cmd := btcjson.NewCreateEncryptedWalletCmd(passphrase)
    88  	return c.sendCmd(cmd)
    89  }
    90  
    91  // CreateEncryptedWallet requests the creation of an encrypted wallet.  Wallets
    92  // managed by btcwallet are only written to disk with encrypted private keys,
    93  // and generating wallets on the fly is impossible as it requires user input for
    94  // the encryption passphrase.  This RPC specifies the passphrase and instructs
    95  // the wallet creation.  This may error if a wallet is already opened, or the
    96  // new wallet cannot be written to disk.
    97  //
    98  // NOTE: This is a btcwallet extension.
    99  func (c *Client) CreateEncryptedWallet(passphrase string) error {
   100  	return c.CreateEncryptedWalletAsync(passphrase).Receive()
   101  }
   102  
   103  // FutureListAddressTransactionsResult is a future promise to deliver the result
   104  // of a ListAddressTransactionsAsync RPC invocation (or an applicable error).
   105  type FutureListAddressTransactionsResult chan *response
   106  
   107  // Receive waits for the response promised by the future and returns information
   108  // about all transactions associated with the provided addresses.
   109  func (r FutureListAddressTransactionsResult) Receive() ([]btcjson.ListTransactionsResult, error) {
   110  	res, err := receiveFuture(r)
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  
   115  	// Unmarshal the result as an array of listtransactions objects.
   116  	var transactions []btcjson.ListTransactionsResult
   117  	err = json.Unmarshal(res, &transactions)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  	return transactions, nil
   122  }
   123  
   124  // ListAddressTransactionsAsync returns an instance of a type that can be used
   125  // to get the result of the RPC at some future time by invoking the Receive
   126  // function on the returned instance.
   127  //
   128  // See ListAddressTransactions for the blocking version and more details.
   129  //
   130  // NOTE: This is a btcd extension.
   131  func (c *Client) ListAddressTransactionsAsync(addresses []palcutil.Address, account string) FutureListAddressTransactionsResult {
   132  	// Convert addresses to strings.
   133  	addrs := make([]string, 0, len(addresses))
   134  	for _, addr := range addresses {
   135  		addrs = append(addrs, addr.EncodeAddress())
   136  	}
   137  	cmd := btcjson.NewListAddressTransactionsCmd(addrs, &account)
   138  	return c.sendCmd(cmd)
   139  }
   140  
   141  // ListAddressTransactions returns information about all transactions associated
   142  // with the provided addresses.
   143  //
   144  // NOTE: This is a btcwallet extension.
   145  func (c *Client) ListAddressTransactions(addresses []palcutil.Address, account string) ([]btcjson.ListTransactionsResult, error) {
   146  	return c.ListAddressTransactionsAsync(addresses, account).Receive()
   147  }
   148  
   149  // FutureGetBestBlockResult is a future promise to deliver the result of a
   150  // GetBestBlockAsync RPC invocation (or an applicable error).
   151  type FutureGetBestBlockResult chan *response
   152  
   153  // Receive waits for the response promised by the future and returns the hash
   154  // and height of the block in the longest (best) chain.
   155  func (r FutureGetBestBlockResult) Receive() (*chainhash.Hash, int32, error) {
   156  	res, err := receiveFuture(r)
   157  	if err != nil {
   158  		return nil, 0, err
   159  	}
   160  
   161  	// Unmarshal result as a getbestblock result object.
   162  	var bestBlock btcjson.GetBestBlockResult
   163  	err = json.Unmarshal(res, &bestBlock)
   164  	if err != nil {
   165  		return nil, 0, err
   166  	}
   167  
   168  	// Convert to hash from string.
   169  	hash, err := chainhash.NewHashFromStr(bestBlock.Hash)
   170  	if err != nil {
   171  		return nil, 0, err
   172  	}
   173  
   174  	return hash, bestBlock.Height, nil
   175  }
   176  
   177  // GetBestBlockAsync returns an instance of a type that can be used to get the
   178  // result of the RPC at some future time by invoking the Receive function on the
   179  // returned instance.
   180  //
   181  // See GetBestBlock for the blocking version and more details.
   182  //
   183  // NOTE: This is a btcd extension.
   184  func (c *Client) GetBestBlockAsync() FutureGetBestBlockResult {
   185  	cmd := btcjson.NewGetBestBlockCmd()
   186  	return c.sendCmd(cmd)
   187  }
   188  
   189  // GetBestBlock returns the hash and height of the block in the longest (best)
   190  // chain.
   191  //
   192  // NOTE: This is a btcd extension.
   193  func (c *Client) GetBestBlock() (*chainhash.Hash, int32, error) {
   194  	return c.GetBestBlockAsync().Receive()
   195  }
   196  
   197  // FutureGetCurrentNetResult is a future promise to deliver the result of a
   198  // GetCurrentNetAsync RPC invocation (or an applicable error).
   199  type FutureGetCurrentNetResult chan *response
   200  
   201  // Receive waits for the response promised by the future and returns the network
   202  // the server is running on.
   203  func (r FutureGetCurrentNetResult) Receive() (wire.BitcoinNet, error) {
   204  	res, err := receiveFuture(r)
   205  	if err != nil {
   206  		return 0, err
   207  	}
   208  
   209  	// Unmarshal result as an int64.
   210  	var net int64
   211  	err = json.Unmarshal(res, &net)
   212  	if err != nil {
   213  		return 0, err
   214  	}
   215  
   216  	return wire.BitcoinNet(net), nil
   217  }
   218  
   219  // GetCurrentNetAsync returns an instance of a type that can be used to get the
   220  // result of the RPC at some future time by invoking the Receive function on the
   221  // returned instance.
   222  //
   223  // See GetCurrentNet for the blocking version and more details.
   224  //
   225  // NOTE: This is a btcd extension.
   226  func (c *Client) GetCurrentNetAsync() FutureGetCurrentNetResult {
   227  	cmd := btcjson.NewGetCurrentNetCmd()
   228  	return c.sendCmd(cmd)
   229  }
   230  
   231  // GetCurrentNet returns the network the server is running on.
   232  //
   233  // NOTE: This is a btcd extension.
   234  func (c *Client) GetCurrentNet() (wire.BitcoinNet, error) {
   235  	return c.GetCurrentNetAsync().Receive()
   236  }
   237  
   238  // FutureGetHeadersResult is a future promise to deliver the result of a
   239  // getheaders RPC invocation (or an applicable error).
   240  //
   241  // NOTE: This is a btcsuite extension ported from
   242  // github.com/decred/dcrrpcclient.
   243  type FutureGetHeadersResult chan *response
   244  
   245  // Receive waits for the response promised by the future and returns the
   246  // getheaders result.
   247  //
   248  // NOTE: This is a btcsuite extension ported from
   249  // github.com/decred/dcrrpcclient.
   250  func (r FutureGetHeadersResult) Receive() ([]wire.BlockHeader, error) {
   251  	res, err := receiveFuture(r)
   252  	if err != nil {
   253  		return nil, err
   254  	}
   255  
   256  	// Unmarshal result as a slice of strings.
   257  	var result []string
   258  	err = json.Unmarshal(res, &result)
   259  	if err != nil {
   260  		return nil, err
   261  	}
   262  
   263  	// Deserialize the []string into []wire.BlockHeader.
   264  	headers := make([]wire.BlockHeader, len(result))
   265  	for i, headerHex := range result {
   266  		serialized, err := hex.DecodeString(headerHex)
   267  		if err != nil {
   268  			return nil, err
   269  		}
   270  		err = headers[i].Deserialize(bytes.NewReader(serialized))
   271  		if err != nil {
   272  			return nil, err
   273  		}
   274  	}
   275  	return headers, nil
   276  }
   277  
   278  // GetHeadersAsync returns an instance of a type that can be used to get the result
   279  // of the RPC at some future time by invoking the Receive function on the returned instance.
   280  //
   281  // See GetHeaders for the blocking version and more details.
   282  //
   283  // NOTE: This is a btcsuite extension ported from
   284  // github.com/decred/dcrrpcclient.
   285  func (c *Client) GetHeadersAsync(blockLocators []chainhash.Hash, hashStop *chainhash.Hash) FutureGetHeadersResult {
   286  	locators := make([]string, len(blockLocators))
   287  	for i := range blockLocators {
   288  		locators[i] = blockLocators[i].String()
   289  	}
   290  	hash := ""
   291  	if hashStop != nil {
   292  		hash = hashStop.String()
   293  	}
   294  	cmd := btcjson.NewGetHeadersCmd(locators, hash)
   295  	return c.sendCmd(cmd)
   296  }
   297  
   298  // GetHeaders mimics the wire protocol getheaders and headers messages by
   299  // returning all headers on the main chain after the first known block in the
   300  // locators, up until a block hash matches hashStop.
   301  //
   302  // NOTE: This is a btcsuite extension ported from
   303  // github.com/decred/dcrrpcclient.
   304  func (c *Client) GetHeaders(blockLocators []chainhash.Hash, hashStop *chainhash.Hash) ([]wire.BlockHeader, error) {
   305  	return c.GetHeadersAsync(blockLocators, hashStop).Receive()
   306  }
   307  
   308  // FutureExportWatchingWalletResult is a future promise to deliver the result of
   309  // an ExportWatchingWalletAsync RPC invocation (or an applicable error).
   310  type FutureExportWatchingWalletResult chan *response
   311  
   312  // Receive waits for the response promised by the future and returns the
   313  // exported wallet.
   314  func (r FutureExportWatchingWalletResult) Receive() ([]byte, []byte, error) {
   315  	res, err := receiveFuture(r)
   316  	if err != nil {
   317  		return nil, nil, err
   318  	}
   319  
   320  	// Unmarshal result as a JSON object.
   321  	var obj map[string]interface{}
   322  	err = json.Unmarshal(res, &obj)
   323  	if err != nil {
   324  		return nil, nil, err
   325  	}
   326  
   327  	// Check for the wallet and tx string fields in the object.
   328  	base64Wallet, ok := obj["wallet"].(string)
   329  	if !ok {
   330  		return nil, nil, fmt.Errorf("unexpected response type for "+
   331  			"exportwatchingwallet 'wallet' field: %T\n",
   332  			obj["wallet"])
   333  	}
   334  	base64TxStore, ok := obj["tx"].(string)
   335  	if !ok {
   336  		return nil, nil, fmt.Errorf("unexpected response type for "+
   337  			"exportwatchingwallet 'tx' field: %T\n",
   338  			obj["tx"])
   339  	}
   340  
   341  	walletBytes, err := base64.StdEncoding.DecodeString(base64Wallet)
   342  	if err != nil {
   343  		return nil, nil, err
   344  	}
   345  
   346  	txStoreBytes, err := base64.StdEncoding.DecodeString(base64TxStore)
   347  	if err != nil {
   348  		return nil, nil, err
   349  	}
   350  
   351  	return walletBytes, txStoreBytes, nil
   352  
   353  }
   354  
   355  // ExportWatchingWalletAsync returns an instance of a type that can be used to
   356  // get the result of the RPC at some future time by invoking the Receive
   357  // function on the returned instance.
   358  //
   359  // See ExportWatchingWallet for the blocking version and more details.
   360  //
   361  // NOTE: This is a btcwallet extension.
   362  func (c *Client) ExportWatchingWalletAsync(account string) FutureExportWatchingWalletResult {
   363  	cmd := btcjson.NewExportWatchingWalletCmd(&account, btcjson.Bool(true))
   364  	return c.sendCmd(cmd)
   365  }
   366  
   367  // ExportWatchingWallet returns the raw bytes for a watching-only version of
   368  // wallet.bin and tx.bin, respectively, for the specified account that can be
   369  // used by btcwallet to enable a wallet which does not have the private keys
   370  // necessary to spend funds.
   371  //
   372  // NOTE: This is a btcwallet extension.
   373  func (c *Client) ExportWatchingWallet(account string) ([]byte, []byte, error) {
   374  	return c.ExportWatchingWalletAsync(account).Receive()
   375  }
   376  
   377  // FutureSessionResult is a future promise to deliver the result of a
   378  // SessionAsync RPC invocation (or an applicable error).
   379  type FutureSessionResult chan *response
   380  
   381  // Receive waits for the response promised by the future and returns the
   382  // session result.
   383  func (r FutureSessionResult) Receive() (*btcjson.SessionResult, error) {
   384  	res, err := receiveFuture(r)
   385  	if err != nil {
   386  		return nil, err
   387  	}
   388  
   389  	// Unmarshal result as a session result object.
   390  	var session btcjson.SessionResult
   391  	err = json.Unmarshal(res, &session)
   392  	if err != nil {
   393  		return nil, err
   394  	}
   395  
   396  	return &session, nil
   397  }
   398  
   399  // SessionAsync returns an instance of a type that can be used to get the result
   400  // of the RPC at some future time by invoking the Receive function on the
   401  // returned instance.
   402  //
   403  // See Session for the blocking version and more details.
   404  //
   405  // NOTE: This is a btcsuite extension.
   406  func (c *Client) SessionAsync() FutureSessionResult {
   407  	// Not supported in HTTP POST mode.
   408  	if c.config.HTTPPostMode {
   409  		return newFutureError(ErrWebsocketsRequired)
   410  	}
   411  
   412  	cmd := btcjson.NewSessionCmd()
   413  	return c.sendCmd(cmd)
   414  }
   415  
   416  // Session returns details regarding a websocket client's current connection.
   417  //
   418  // This RPC requires the client to be running in websocket mode.
   419  //
   420  // NOTE: This is a btcsuite extension.
   421  func (c *Client) Session() (*btcjson.SessionResult, error) {
   422  	return c.SessionAsync().Receive()
   423  }
   424  
   425  // FutureVersionResult is a future promise to deliver the result of a version
   426  // RPC invocation (or an applicable error).
   427  //
   428  // NOTE: This is a btcsuite extension ported from
   429  // github.com/decred/dcrrpcclient.
   430  type FutureVersionResult chan *response
   431  
   432  // Receive waits for the response promised by the future and returns the version
   433  // result.
   434  //
   435  // NOTE: This is a btcsuite extension ported from
   436  // github.com/decred/dcrrpcclient.
   437  func (r FutureVersionResult) Receive() (map[string]btcjson.VersionResult,
   438  	error) {
   439  	res, err := receiveFuture(r)
   440  	if err != nil {
   441  		return nil, err
   442  	}
   443  
   444  	// Unmarshal result as a version result object.
   445  	var vr map[string]btcjson.VersionResult
   446  	err = json.Unmarshal(res, &vr)
   447  	if err != nil {
   448  		return nil, err
   449  	}
   450  
   451  	return vr, nil
   452  }
   453  
   454  // VersionAsync returns an instance of a type that can be used to get the result
   455  // of the RPC at some future time by invoking the Receive function on the
   456  // returned instance.
   457  //
   458  // See Version for the blocking version and more details.
   459  //
   460  // NOTE: This is a btcsuite extension ported from
   461  // github.com/decred/dcrrpcclient.
   462  func (c *Client) VersionAsync() FutureVersionResult {
   463  	cmd := btcjson.NewVersionCmd()
   464  	return c.sendCmd(cmd)
   465  }
   466  
   467  // Version returns information about the server's JSON-RPC API versions.
   468  //
   469  // NOTE: This is a btcsuite extension ported from
   470  // github.com/decred/dcrrpcclient.
   471  func (c *Client) Version() (map[string]btcjson.VersionResult, error) {
   472  	return c.VersionAsync().Receive()
   473  }