OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / rpcclient / extensions.go
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/btcsuite/btcd/btcjson"
16         "github.com/btcsuite/btcd/chaincfg/chainhash"
17         "github.com/btcsuite/btcd/wire"
18         "github.com/btcsuite/btcutil"
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 []btcutil.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 []btcutil.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 delivere 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 }