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