OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / rpcclient / notify.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/hex"
11         "encoding/json"
12         "errors"
13         "fmt"
14         "time"
15
16         "github.com/btcsuite/btcd/btcjson"
17         "github.com/btcsuite/btcd/chaincfg/chainhash"
18         "github.com/btcsuite/btcd/wire"
19         "github.com/btcsuite/btcutil"
20 )
21
22 var (
23         // ErrWebsocketsRequired is an error to describe the condition where the
24         // caller is trying to use a websocket-only feature, such as requesting
25         // notifications or other websocket requests when the client is
26         // configured to run in HTTP POST mode.
27         ErrWebsocketsRequired = errors.New("a websocket connection is required " +
28                 "to use this feature")
29 )
30
31 // notificationState is used to track the current state of successfuly
32 // registered notification so the state can be automatically re-established on
33 // reconnect.
34 type notificationState struct {
35         notifyBlocks       bool
36         notifyNewTx        bool
37         notifyNewTxVerbose bool
38         notifyReceived     map[string]struct{}
39         notifySpent        map[btcjson.OutPoint]struct{}
40 }
41
42 // Copy returns a deep copy of the receiver.
43 func (s *notificationState) Copy() *notificationState {
44         var stateCopy notificationState
45         stateCopy.notifyBlocks = s.notifyBlocks
46         stateCopy.notifyNewTx = s.notifyNewTx
47         stateCopy.notifyNewTxVerbose = s.notifyNewTxVerbose
48         stateCopy.notifyReceived = make(map[string]struct{})
49         for addr := range s.notifyReceived {
50                 stateCopy.notifyReceived[addr] = struct{}{}
51         }
52         stateCopy.notifySpent = make(map[btcjson.OutPoint]struct{})
53         for op := range s.notifySpent {
54                 stateCopy.notifySpent[op] = struct{}{}
55         }
56
57         return &stateCopy
58 }
59
60 // newNotificationState returns a new notification state ready to be populated.
61 func newNotificationState() *notificationState {
62         return &notificationState{
63                 notifyReceived: make(map[string]struct{}),
64                 notifySpent:    make(map[btcjson.OutPoint]struct{}),
65         }
66 }
67
68 // newNilFutureResult returns a new future result channel that already has the
69 // result waiting on the channel with the reply set to nil.  This is useful
70 // to ignore things such as notifications when the caller didn't specify any
71 // notification handlers.
72 func newNilFutureResult() chan *response {
73         responseChan := make(chan *response, 1)
74         responseChan <- &response{result: nil, err: nil}
75         return responseChan
76 }
77
78 // NotificationHandlers defines callback function pointers to invoke with
79 // notifications.  Since all of the functions are nil by default, all
80 // notifications are effectively ignored until their handlers are set to a
81 // concrete callback.
82 //
83 // NOTE: Unless otherwise documented, these handlers must NOT directly call any
84 // blocking calls on the client instance since the input reader goroutine blocks
85 // until the callback has completed.  Doing so will result in a deadlock
86 // situation.
87 type NotificationHandlers struct {
88         // OnClientConnected is invoked when the client connects or reconnects
89         // to the RPC server.  This callback is run async with the rest of the
90         // notification handlers, and is safe for blocking client requests.
91         OnClientConnected func()
92
93         // OnBlockConnected is invoked when a block is connected to the longest
94         // (best) chain.  It will only be invoked if a preceding call to
95         // NotifyBlocks has been made to register for the notification and the
96         // function is non-nil.
97         //
98         // NOTE: Deprecated. Use OnFilteredBlockConnected instead.
99         OnBlockConnected func(hash *chainhash.Hash, height int32, t time.Time)
100
101         // OnFilteredBlockConnected is invoked when a block is connected to the
102         // longest (best) chain.  It will only be invoked if a preceding call to
103         // NotifyBlocks has been made to register for the notification and the
104         // function is non-nil.  Its parameters differ from OnBlockConnected: it
105         // receives the block's height, header, and relevant transactions.
106         OnFilteredBlockConnected func(height int32, header *wire.BlockHeader,
107                 txs []*btcutil.Tx)
108
109         // OnBlockDisconnected is invoked when a block is disconnected from the
110         // longest (best) chain.  It will only be invoked if a preceding call to
111         // NotifyBlocks has been made to register for the notification and the
112         // function is non-nil.
113         //
114         // NOTE: Deprecated. Use OnFilteredBlockDisconnected instead.
115         OnBlockDisconnected func(hash *chainhash.Hash, height int32, t time.Time)
116
117         // OnFilteredBlockDisconnected is invoked when a block is disconnected
118         // from the longest (best) chain.  It will only be invoked if a
119         // preceding NotifyBlocks has been made to register for the notification
120         // and the call to function is non-nil.  Its parameters differ from
121         // OnBlockDisconnected: it receives the block's height and header.
122         OnFilteredBlockDisconnected func(height int32, header *wire.BlockHeader)
123
124         // OnRecvTx is invoked when a transaction that receives funds to a
125         // registered address is received into the memory pool and also
126         // connected to the longest (best) chain.  It will only be invoked if a
127         // preceding call to NotifyReceived, Rescan, or RescanEndHeight has been
128         // made to register for the notification and the function is non-nil.
129         //
130         // NOTE: Deprecated. Use OnRelevantTxAccepted instead.
131         OnRecvTx func(transaction *btcutil.Tx, details *btcjson.BlockDetails)
132
133         // OnRedeemingTx is invoked when a transaction that spends a registered
134         // outpoint is received into the memory pool and also connected to the
135         // longest (best) chain.  It will only be invoked if a preceding call to
136         // NotifySpent, Rescan, or RescanEndHeight has been made to register for
137         // the notification and the function is non-nil.
138         //
139         // NOTE: The NotifyReceived will automatically register notifications
140         // for the outpoints that are now "owned" as a result of receiving
141         // funds to the registered addresses.  This means it is possible for
142         // this to invoked indirectly as the result of a NotifyReceived call.
143         //
144         // NOTE: Deprecated. Use OnRelevantTxAccepted instead.
145         OnRedeemingTx func(transaction *btcutil.Tx, details *btcjson.BlockDetails)
146
147         // OnRelevantTxAccepted is invoked when an unmined transaction passes
148         // the client's transaction filter.
149         //
150         // NOTE: This is a btcsuite extension ported from
151         // github.com/decred/dcrrpcclient.
152         OnRelevantTxAccepted func(transaction []byte)
153
154         // OnRescanFinished is invoked after a rescan finishes due to a previous
155         // call to Rescan or RescanEndHeight.  Finished rescans should be
156         // signaled on this notification, rather than relying on the return
157         // result of a rescan request, due to how btcd may send various rescan
158         // notifications after the rescan request has already returned.
159         //
160         // NOTE: Deprecated. Not used with RescanBlocks.
161         OnRescanFinished func(hash *chainhash.Hash, height int32, blkTime time.Time)
162
163         // OnRescanProgress is invoked periodically when a rescan is underway.
164         // It will only be invoked if a preceding call to Rescan or
165         // RescanEndHeight has been made and the function is non-nil.
166         //
167         // NOTE: Deprecated. Not used with RescanBlocks.
168         OnRescanProgress func(hash *chainhash.Hash, height int32, blkTime time.Time)
169
170         // OnTxAccepted is invoked when a transaction is accepted into the
171         // memory pool.  It will only be invoked if a preceding call to
172         // NotifyNewTransactions with the verbose flag set to false has been
173         // made to register for the notification and the function is non-nil.
174         OnTxAccepted func(hash *chainhash.Hash, amount btcutil.Amount)
175
176         // OnTxAccepted is invoked when a transaction is accepted into the
177         // memory pool.  It will only be invoked if a preceding call to
178         // NotifyNewTransactions with the verbose flag set to true has been
179         // made to register for the notification and the function is non-nil.
180         OnTxAcceptedVerbose func(txDetails *btcjson.TxRawResult)
181
182         // OnBtcdConnected is invoked when a wallet connects or disconnects from
183         // btcd.
184         //
185         // This will only be available when client is connected to a wallet
186         // server such as btcwallet.
187         OnBtcdConnected func(connected bool)
188
189         // OnAccountBalance is invoked with account balance updates.
190         //
191         // This will only be available when speaking to a wallet server
192         // such as btcwallet.
193         OnAccountBalance func(account string, balance btcutil.Amount, confirmed bool)
194
195         // OnWalletLockState is invoked when a wallet is locked or unlocked.
196         //
197         // This will only be available when client is connected to a wallet
198         // server such as btcwallet.
199         OnWalletLockState func(locked bool)
200
201         // OnUnknownNotification is invoked when an unrecognized notification
202         // is received.  This typically means the notification handling code
203         // for this package needs to be updated for a new notification type or
204         // the caller is using a custom notification this package does not know
205         // about.
206         OnUnknownNotification func(method string, params []json.RawMessage)
207 }
208
209 // handleNotification examines the passed notification type, performs
210 // conversions to get the raw notification types into higher level types and
211 // delivers the notification to the appropriate On<X> handler registered with
212 // the client.
213 func (c *Client) handleNotification(ntfn *rawNotification) {
214         // Ignore the notification if the client is not interested in any
215         // notifications.
216         if c.ntfnHandlers == nil {
217                 return
218         }
219
220         switch ntfn.Method {
221         // OnBlockConnected
222         case btcjson.BlockConnectedNtfnMethod:
223                 // Ignore the notification if the client is not interested in
224                 // it.
225                 if c.ntfnHandlers.OnBlockConnected == nil {
226                         return
227                 }
228
229                 blockHash, blockHeight, blockTime, err := parseChainNtfnParams(ntfn.Params)
230                 if err != nil {
231                         log.Warnf("Received invalid block connected "+
232                                 "notification: %v", err)
233                         return
234                 }
235
236                 c.ntfnHandlers.OnBlockConnected(blockHash, blockHeight, blockTime)
237
238         // OnFilteredBlockConnected
239         case btcjson.FilteredBlockConnectedNtfnMethod:
240                 // Ignore the notification if the client is not interested in
241                 // it.
242                 if c.ntfnHandlers.OnFilteredBlockConnected == nil {
243                         return
244                 }
245
246                 blockHeight, blockHeader, transactions, err :=
247                         parseFilteredBlockConnectedParams(ntfn.Params)
248                 if err != nil {
249                         log.Warnf("Received invalid filtered block "+
250                                 "connected notification: %v", err)
251                         return
252                 }
253
254                 c.ntfnHandlers.OnFilteredBlockConnected(blockHeight,
255                         blockHeader, transactions)
256
257         // OnBlockDisconnected
258         case btcjson.BlockDisconnectedNtfnMethod:
259                 // Ignore the notification if the client is not interested in
260                 // it.
261                 if c.ntfnHandlers.OnBlockDisconnected == nil {
262                         return
263                 }
264
265                 blockHash, blockHeight, blockTime, err := parseChainNtfnParams(ntfn.Params)
266                 if err != nil {
267                         log.Warnf("Received invalid block connected "+
268                                 "notification: %v", err)
269                         return
270                 }
271
272                 c.ntfnHandlers.OnBlockDisconnected(blockHash, blockHeight, blockTime)
273
274         // OnFilteredBlockDisconnected
275         case btcjson.FilteredBlockDisconnectedNtfnMethod:
276                 // Ignore the notification if the client is not interested in
277                 // it.
278                 if c.ntfnHandlers.OnFilteredBlockDisconnected == nil {
279                         return
280                 }
281
282                 blockHeight, blockHeader, err :=
283                         parseFilteredBlockDisconnectedParams(ntfn.Params)
284                 if err != nil {
285                         log.Warnf("Received invalid filtered block "+
286                                 "disconnected notification: %v", err)
287                         return
288                 }
289
290                 c.ntfnHandlers.OnFilteredBlockDisconnected(blockHeight,
291                         blockHeader)
292
293         // OnRecvTx
294         case btcjson.RecvTxNtfnMethod:
295                 // Ignore the notification if the client is not interested in
296                 // it.
297                 if c.ntfnHandlers.OnRecvTx == nil {
298                         return
299                 }
300
301                 tx, block, err := parseChainTxNtfnParams(ntfn.Params)
302                 if err != nil {
303                         log.Warnf("Received invalid recvtx notification: %v",
304                                 err)
305                         return
306                 }
307
308                 c.ntfnHandlers.OnRecvTx(tx, block)
309
310         // OnRedeemingTx
311         case btcjson.RedeemingTxNtfnMethod:
312                 // Ignore the notification if the client is not interested in
313                 // it.
314                 if c.ntfnHandlers.OnRedeemingTx == nil {
315                         return
316                 }
317
318                 tx, block, err := parseChainTxNtfnParams(ntfn.Params)
319                 if err != nil {
320                         log.Warnf("Received invalid redeemingtx "+
321                                 "notification: %v", err)
322                         return
323                 }
324
325                 c.ntfnHandlers.OnRedeemingTx(tx, block)
326
327         // OnRelevantTxAccepted
328         case btcjson.RelevantTxAcceptedNtfnMethod:
329                 // Ignore the notification if the client is not interested in
330                 // it.
331                 if c.ntfnHandlers.OnRelevantTxAccepted == nil {
332                         return
333                 }
334
335                 transaction, err := parseRelevantTxAcceptedParams(ntfn.Params)
336                 if err != nil {
337                         log.Warnf("Received invalid relevanttxaccepted "+
338                                 "notification: %v", err)
339                         return
340                 }
341
342                 c.ntfnHandlers.OnRelevantTxAccepted(transaction)
343
344         // OnRescanFinished
345         case btcjson.RescanFinishedNtfnMethod:
346                 // Ignore the notification if the client is not interested in
347                 // it.
348                 if c.ntfnHandlers.OnRescanFinished == nil {
349                         return
350                 }
351
352                 hash, height, blkTime, err := parseRescanProgressParams(ntfn.Params)
353                 if err != nil {
354                         log.Warnf("Received invalid rescanfinished "+
355                                 "notification: %v", err)
356                         return
357                 }
358
359                 c.ntfnHandlers.OnRescanFinished(hash, height, blkTime)
360
361         // OnRescanProgress
362         case btcjson.RescanProgressNtfnMethod:
363                 // Ignore the notification if the client is not interested in
364                 // it.
365                 if c.ntfnHandlers.OnRescanProgress == nil {
366                         return
367                 }
368
369                 hash, height, blkTime, err := parseRescanProgressParams(ntfn.Params)
370                 if err != nil {
371                         log.Warnf("Received invalid rescanprogress "+
372                                 "notification: %v", err)
373                         return
374                 }
375
376                 c.ntfnHandlers.OnRescanProgress(hash, height, blkTime)
377
378         // OnTxAccepted
379         case btcjson.TxAcceptedNtfnMethod:
380                 // Ignore the notification if the client is not interested in
381                 // it.
382                 if c.ntfnHandlers.OnTxAccepted == nil {
383                         return
384                 }
385
386                 hash, amt, err := parseTxAcceptedNtfnParams(ntfn.Params)
387                 if err != nil {
388                         log.Warnf("Received invalid tx accepted "+
389                                 "notification: %v", err)
390                         return
391                 }
392
393                 c.ntfnHandlers.OnTxAccepted(hash, amt)
394
395         // OnTxAcceptedVerbose
396         case btcjson.TxAcceptedVerboseNtfnMethod:
397                 // Ignore the notification if the client is not interested in
398                 // it.
399                 if c.ntfnHandlers.OnTxAcceptedVerbose == nil {
400                         return
401                 }
402
403                 rawTx, err := parseTxAcceptedVerboseNtfnParams(ntfn.Params)
404                 if err != nil {
405                         log.Warnf("Received invalid tx accepted verbose "+
406                                 "notification: %v", err)
407                         return
408                 }
409
410                 c.ntfnHandlers.OnTxAcceptedVerbose(rawTx)
411
412         // OnBtcdConnected
413         case btcjson.BtcdConnectedNtfnMethod:
414                 // Ignore the notification if the client is not interested in
415                 // it.
416                 if c.ntfnHandlers.OnBtcdConnected == nil {
417                         return
418                 }
419
420                 connected, err := parseBtcdConnectedNtfnParams(ntfn.Params)
421                 if err != nil {
422                         log.Warnf("Received invalid btcd connected "+
423                                 "notification: %v", err)
424                         return
425                 }
426
427                 c.ntfnHandlers.OnBtcdConnected(connected)
428
429         // OnAccountBalance
430         case btcjson.AccountBalanceNtfnMethod:
431                 // Ignore the notification if the client is not interested in
432                 // it.
433                 if c.ntfnHandlers.OnAccountBalance == nil {
434                         return
435                 }
436
437                 account, bal, conf, err := parseAccountBalanceNtfnParams(ntfn.Params)
438                 if err != nil {
439                         log.Warnf("Received invalid account balance "+
440                                 "notification: %v", err)
441                         return
442                 }
443
444                 c.ntfnHandlers.OnAccountBalance(account, bal, conf)
445
446         // OnWalletLockState
447         case btcjson.WalletLockStateNtfnMethod:
448                 // Ignore the notification if the client is not interested in
449                 // it.
450                 if c.ntfnHandlers.OnWalletLockState == nil {
451                         return
452                 }
453
454                 // The account name is not notified, so the return value is
455                 // discarded.
456                 _, locked, err := parseWalletLockStateNtfnParams(ntfn.Params)
457                 if err != nil {
458                         log.Warnf("Received invalid wallet lock state "+
459                                 "notification: %v", err)
460                         return
461                 }
462
463                 c.ntfnHandlers.OnWalletLockState(locked)
464
465         // OnUnknownNotification
466         default:
467                 if c.ntfnHandlers.OnUnknownNotification == nil {
468                         return
469                 }
470
471                 c.ntfnHandlers.OnUnknownNotification(ntfn.Method, ntfn.Params)
472         }
473 }
474
475 // wrongNumParams is an error type describing an unparseable JSON-RPC
476 // notificiation due to an incorrect number of parameters for the
477 // expected notification type.  The value is the number of parameters
478 // of the invalid notification.
479 type wrongNumParams int
480
481 // Error satisifies the builtin error interface.
482 func (e wrongNumParams) Error() string {
483         return fmt.Sprintf("wrong number of parameters (%d)", e)
484 }
485
486 // parseChainNtfnParams parses out the block hash and height from the parameters
487 // of blockconnected and blockdisconnected notifications.
488 func parseChainNtfnParams(params []json.RawMessage) (*chainhash.Hash,
489         int32, time.Time, error) {
490
491         if len(params) != 3 {
492                 return nil, 0, time.Time{}, wrongNumParams(len(params))
493         }
494
495         // Unmarshal first parameter as a string.
496         var blockHashStr string
497         err := json.Unmarshal(params[0], &blockHashStr)
498         if err != nil {
499                 return nil, 0, time.Time{}, err
500         }
501
502         // Unmarshal second parameter as an integer.
503         var blockHeight int32
504         err = json.Unmarshal(params[1], &blockHeight)
505         if err != nil {
506                 return nil, 0, time.Time{}, err
507         }
508
509         // Unmarshal third parameter as unix time.
510         var blockTimeUnix int64
511         err = json.Unmarshal(params[2], &blockTimeUnix)
512         if err != nil {
513                 return nil, 0, time.Time{}, err
514         }
515
516         // Create hash from block hash string.
517         blockHash, err := chainhash.NewHashFromStr(blockHashStr)
518         if err != nil {
519                 return nil, 0, time.Time{}, err
520         }
521
522         // Create time.Time from unix time.
523         blockTime := time.Unix(blockTimeUnix, 0)
524
525         return blockHash, blockHeight, blockTime, nil
526 }
527
528 // parseFilteredBlockConnectedParams parses out the parameters included in a
529 // filteredblockconnected notification.
530 //
531 // NOTE: This is a btcd extension ported from github.com/decred/dcrrpcclient
532 // and requires a websocket connection.
533 func parseFilteredBlockConnectedParams(params []json.RawMessage) (int32,
534         *wire.BlockHeader, []*btcutil.Tx, error) {
535
536         if len(params) < 3 {
537                 return 0, nil, nil, wrongNumParams(len(params))
538         }
539
540         // Unmarshal first parameter as an integer.
541         var blockHeight int32
542         err := json.Unmarshal(params[0], &blockHeight)
543         if err != nil {
544                 return 0, nil, nil, err
545         }
546
547         // Unmarshal second parameter as a slice of bytes.
548         blockHeaderBytes, err := parseHexParam(params[1])
549         if err != nil {
550                 return 0, nil, nil, err
551         }
552
553         // Deserialize block header from slice of bytes.
554         var blockHeader wire.BlockHeader
555         err = blockHeader.Deserialize(bytes.NewReader(blockHeaderBytes))
556         if err != nil {
557                 return 0, nil, nil, err
558         }
559
560         // Unmarshal third parameter as a slice of hex-encoded strings.
561         var hexTransactions []string
562         err = json.Unmarshal(params[2], &hexTransactions)
563         if err != nil {
564                 return 0, nil, nil, err
565         }
566
567         // Create slice of transactions from slice of strings by hex-decoding.
568         transactions := make([]*btcutil.Tx, len(hexTransactions))
569         for i, hexTx := range hexTransactions {
570                 transaction, err := hex.DecodeString(hexTx)
571                 if err != nil {
572                         return 0, nil, nil, err
573                 }
574
575                 transactions[i], err = btcutil.NewTxFromBytes(transaction)
576                 if err != nil {
577                         return 0, nil, nil, err
578                 }
579         }
580
581         return blockHeight, &blockHeader, transactions, nil
582 }
583
584 // parseFilteredBlockDisconnectedParams parses out the parameters included in a
585 // filteredblockdisconnected notification.
586 //
587 // NOTE: This is a btcd extension ported from github.com/decred/dcrrpcclient
588 // and requires a websocket connection.
589 func parseFilteredBlockDisconnectedParams(params []json.RawMessage) (int32,
590         *wire.BlockHeader, error) {
591         if len(params) < 2 {
592                 return 0, nil, wrongNumParams(len(params))
593         }
594
595         // Unmarshal first parameter as an integer.
596         var blockHeight int32
597         err := json.Unmarshal(params[0], &blockHeight)
598         if err != nil {
599                 return 0, nil, err
600         }
601
602         // Unmarshal second parmeter as a slice of bytes.
603         blockHeaderBytes, err := parseHexParam(params[1])
604         if err != nil {
605                 return 0, nil, err
606         }
607
608         // Deserialize block header from slice of bytes.
609         var blockHeader wire.BlockHeader
610         err = blockHeader.Deserialize(bytes.NewReader(blockHeaderBytes))
611         if err != nil {
612                 return 0, nil, err
613         }
614
615         return blockHeight, &blockHeader, nil
616 }
617
618 func parseHexParam(param json.RawMessage) ([]byte, error) {
619         var s string
620         err := json.Unmarshal(param, &s)
621         if err != nil {
622                 return nil, err
623         }
624         return hex.DecodeString(s)
625 }
626
627 // parseRelevantTxAcceptedParams parses out the parameter included in a
628 // relevanttxaccepted notification.
629 func parseRelevantTxAcceptedParams(params []json.RawMessage) (transaction []byte, err error) {
630         if len(params) < 1 {
631                 return nil, wrongNumParams(len(params))
632         }
633
634         return parseHexParam(params[0])
635 }
636
637 // parseChainTxNtfnParams parses out the transaction and optional details about
638 // the block it's mined in from the parameters of recvtx and redeemingtx
639 // notifications.
640 func parseChainTxNtfnParams(params []json.RawMessage) (*btcutil.Tx,
641         *btcjson.BlockDetails, error) {
642
643         if len(params) == 0 || len(params) > 2 {
644                 return nil, nil, wrongNumParams(len(params))
645         }
646
647         // Unmarshal first parameter as a string.
648         var txHex string
649         err := json.Unmarshal(params[0], &txHex)
650         if err != nil {
651                 return nil, nil, err
652         }
653
654         // If present, unmarshal second optional parameter as the block details
655         // JSON object.
656         var block *btcjson.BlockDetails
657         if len(params) > 1 {
658                 err = json.Unmarshal(params[1], &block)
659                 if err != nil {
660                         return nil, nil, err
661                 }
662         }
663
664         // Hex decode and deserialize the transaction.
665         serializedTx, err := hex.DecodeString(txHex)
666         if err != nil {
667                 return nil, nil, err
668         }
669         var msgTx wire.MsgTx
670         err = msgTx.Deserialize(bytes.NewReader(serializedTx))
671         if err != nil {
672                 return nil, nil, err
673         }
674
675         // TODO: Change recvtx and redeemingtx callback signatures to use
676         // nicer types for details about the block (block hash as a
677         // chainhash.Hash, block time as a time.Time, etc.).
678         return btcutil.NewTx(&msgTx), block, nil
679 }
680
681 // parseRescanProgressParams parses out the height of the last rescanned block
682 // from the parameters of rescanfinished and rescanprogress notifications.
683 func parseRescanProgressParams(params []json.RawMessage) (*chainhash.Hash, int32, time.Time, error) {
684         if len(params) != 3 {
685                 return nil, 0, time.Time{}, wrongNumParams(len(params))
686         }
687
688         // Unmarshal first parameter as an string.
689         var hashStr string
690         err := json.Unmarshal(params[0], &hashStr)
691         if err != nil {
692                 return nil, 0, time.Time{}, err
693         }
694
695         // Unmarshal second parameter as an integer.
696         var height int32
697         err = json.Unmarshal(params[1], &height)
698         if err != nil {
699                 return nil, 0, time.Time{}, err
700         }
701
702         // Unmarshal third parameter as an integer.
703         var blkTime int64
704         err = json.Unmarshal(params[2], &blkTime)
705         if err != nil {
706                 return nil, 0, time.Time{}, err
707         }
708
709         // Decode string encoding of block hash.
710         hash, err := chainhash.NewHashFromStr(hashStr)
711         if err != nil {
712                 return nil, 0, time.Time{}, err
713         }
714
715         return hash, height, time.Unix(blkTime, 0), nil
716 }
717
718 // parseTxAcceptedNtfnParams parses out the transaction hash and total amount
719 // from the parameters of a txaccepted notification.
720 func parseTxAcceptedNtfnParams(params []json.RawMessage) (*chainhash.Hash,
721         btcutil.Amount, error) {
722
723         if len(params) != 2 {
724                 return nil, 0, wrongNumParams(len(params))
725         }
726
727         // Unmarshal first parameter as a string.
728         var txHashStr string
729         err := json.Unmarshal(params[0], &txHashStr)
730         if err != nil {
731                 return nil, 0, err
732         }
733
734         // Unmarshal second parameter as a floating point number.
735         var famt float64
736         err = json.Unmarshal(params[1], &famt)
737         if err != nil {
738                 return nil, 0, err
739         }
740
741         // Bounds check amount.
742         amt, err := btcutil.NewAmount(famt)
743         if err != nil {
744                 return nil, 0, err
745         }
746
747         // Decode string encoding of transaction sha.
748         txHash, err := chainhash.NewHashFromStr(txHashStr)
749         if err != nil {
750                 return nil, 0, err
751         }
752
753         return txHash, amt, nil
754 }
755
756 // parseTxAcceptedVerboseNtfnParams parses out details about a raw transaction
757 // from the parameters of a txacceptedverbose notification.
758 func parseTxAcceptedVerboseNtfnParams(params []json.RawMessage) (*btcjson.TxRawResult,
759         error) {
760
761         if len(params) != 1 {
762                 return nil, wrongNumParams(len(params))
763         }
764
765         // Unmarshal first parameter as a raw transaction result object.
766         var rawTx btcjson.TxRawResult
767         err := json.Unmarshal(params[0], &rawTx)
768         if err != nil {
769                 return nil, err
770         }
771
772         // TODO: change txacceptedverbose notification callbacks to use nicer
773         // types for all details about the transaction (i.e. decoding hashes
774         // from their string encoding).
775         return &rawTx, nil
776 }
777
778 // parseBtcdConnectedNtfnParams parses out the connection status of btcd
779 // and btcwallet from the parameters of a btcdconnected notification.
780 func parseBtcdConnectedNtfnParams(params []json.RawMessage) (bool, error) {
781         if len(params) != 1 {
782                 return false, wrongNumParams(len(params))
783         }
784
785         // Unmarshal first parameter as a boolean.
786         var connected bool
787         err := json.Unmarshal(params[0], &connected)
788         if err != nil {
789                 return false, err
790         }
791
792         return connected, nil
793 }
794
795 // parseAccountBalanceNtfnParams parses out the account name, total balance,
796 // and whether or not the balance is confirmed or unconfirmed from the
797 // parameters of an accountbalance notification.
798 func parseAccountBalanceNtfnParams(params []json.RawMessage) (account string,
799         balance btcutil.Amount, confirmed bool, err error) {
800
801         if len(params) != 3 {
802                 return "", 0, false, wrongNumParams(len(params))
803         }
804
805         // Unmarshal first parameter as a string.
806         err = json.Unmarshal(params[0], &account)
807         if err != nil {
808                 return "", 0, false, err
809         }
810
811         // Unmarshal second parameter as a floating point number.
812         var fbal float64
813         err = json.Unmarshal(params[1], &fbal)
814         if err != nil {
815                 return "", 0, false, err
816         }
817
818         // Unmarshal third parameter as a boolean.
819         err = json.Unmarshal(params[2], &confirmed)
820         if err != nil {
821                 return "", 0, false, err
822         }
823
824         // Bounds check amount.
825         bal, err := btcutil.NewAmount(fbal)
826         if err != nil {
827                 return "", 0, false, err
828         }
829
830         return account, bal, confirmed, nil
831 }
832
833 // parseWalletLockStateNtfnParams parses out the account name and locked
834 // state of an account from the parameters of a walletlockstate notification.
835 func parseWalletLockStateNtfnParams(params []json.RawMessage) (account string,
836         locked bool, err error) {
837
838         if len(params) != 2 {
839                 return "", false, wrongNumParams(len(params))
840         }
841
842         // Unmarshal first parameter as a string.
843         err = json.Unmarshal(params[0], &account)
844         if err != nil {
845                 return "", false, err
846         }
847
848         // Unmarshal second parameter as a boolean.
849         err = json.Unmarshal(params[1], &locked)
850         if err != nil {
851                 return "", false, err
852         }
853
854         return account, locked, nil
855 }
856
857 // FutureNotifyBlocksResult is a future promise to deliver the result of a
858 // NotifyBlocksAsync RPC invocation (or an applicable error).
859 type FutureNotifyBlocksResult chan *response
860
861 // Receive waits for the response promised by the future and returns an error
862 // if the registration was not successful.
863 func (r FutureNotifyBlocksResult) Receive() error {
864         _, err := receiveFuture(r)
865         return err
866 }
867
868 // NotifyBlocksAsync returns an instance of a type that can be used to get the
869 // result of the RPC at some future time by invoking the Receive function on
870 // the returned instance.
871 //
872 // See NotifyBlocks for the blocking version and more details.
873 //
874 // NOTE: This is a btcd extension and requires a websocket connection.
875 func (c *Client) NotifyBlocksAsync() FutureNotifyBlocksResult {
876         // Not supported in HTTP POST mode.
877         if c.config.HTTPPostMode {
878                 return newFutureError(ErrWebsocketsRequired)
879         }
880
881         // Ignore the notification if the client is not interested in
882         // notifications.
883         if c.ntfnHandlers == nil {
884                 return newNilFutureResult()
885         }
886
887         cmd := btcjson.NewNotifyBlocksCmd()
888         return c.sendCmd(cmd)
889 }
890
891 // NotifyBlocks registers the client to receive notifications when blocks are
892 // connected and disconnected from the main chain.  The notifications are
893 // delivered to the notification handlers associated with the client.  Calling
894 // this function has no effect if there are no notification handlers and will
895 // result in an error if the client is configured to run in HTTP POST mode.
896 //
897 // The notifications delivered as a result of this call will be via one of
898 // OnBlockConnected or OnBlockDisconnected.
899 //
900 // NOTE: This is a btcd extension and requires a websocket connection.
901 func (c *Client) NotifyBlocks() error {
902         return c.NotifyBlocksAsync().Receive()
903 }
904
905 // FutureNotifySpentResult is a future promise to deliver the result of a
906 // NotifySpentAsync RPC invocation (or an applicable error).
907 //
908 // NOTE: Deprecated. Use FutureLoadTxFilterResult instead.
909 type FutureNotifySpentResult chan *response
910
911 // Receive waits for the response promised by the future and returns an error
912 // if the registration was not successful.
913 func (r FutureNotifySpentResult) Receive() error {
914         _, err := receiveFuture(r)
915         return err
916 }
917
918 // notifySpentInternal is the same as notifySpentAsync except it accepts
919 // the converted outpoints as a parameter so the client can more efficiently
920 // recreate the previous notification state on reconnect.
921 func (c *Client) notifySpentInternal(outpoints []btcjson.OutPoint) FutureNotifySpentResult {
922         // Not supported in HTTP POST mode.
923         if c.config.HTTPPostMode {
924                 return newFutureError(ErrWebsocketsRequired)
925         }
926
927         // Ignore the notification if the client is not interested in
928         // notifications.
929         if c.ntfnHandlers == nil {
930                 return newNilFutureResult()
931         }
932
933         cmd := btcjson.NewNotifySpentCmd(outpoints)
934         return c.sendCmd(cmd)
935 }
936
937 // newOutPointFromWire constructs the btcjson representation of a transaction
938 // outpoint from the wire type.
939 func newOutPointFromWire(op *wire.OutPoint) btcjson.OutPoint {
940         return btcjson.OutPoint{
941                 Hash:  op.Hash.String(),
942                 Index: op.Index,
943         }
944 }
945
946 // NotifySpentAsync returns an instance of a type that can be used to get the
947 // result of the RPC at some future time by invoking the Receive function on
948 // the returned instance.
949 //
950 // See NotifySpent for the blocking version and more details.
951 //
952 // NOTE: This is a btcd extension and requires a websocket connection.
953 //
954 // NOTE: Deprecated. Use LoadTxFilterAsync instead.
955 func (c *Client) NotifySpentAsync(outpoints []*wire.OutPoint) FutureNotifySpentResult {
956         // Not supported in HTTP POST mode.
957         if c.config.HTTPPostMode {
958                 return newFutureError(ErrWebsocketsRequired)
959         }
960
961         // Ignore the notification if the client is not interested in
962         // notifications.
963         if c.ntfnHandlers == nil {
964                 return newNilFutureResult()
965         }
966
967         ops := make([]btcjson.OutPoint, 0, len(outpoints))
968         for _, outpoint := range outpoints {
969                 ops = append(ops, newOutPointFromWire(outpoint))
970         }
971         cmd := btcjson.NewNotifySpentCmd(ops)
972         return c.sendCmd(cmd)
973 }
974
975 // NotifySpent registers the client to receive notifications when the passed
976 // transaction outputs are spent.  The notifications are delivered to the
977 // notification handlers associated with the client.  Calling this function has
978 // no effect if there are no notification handlers and will result in an error
979 // if the client is configured to run in HTTP POST mode.
980 //
981 // The notifications delivered as a result of this call will be via
982 // OnRedeemingTx.
983 //
984 // NOTE: This is a btcd extension and requires a websocket connection.
985 //
986 // NOTE: Deprecated. Use LoadTxFilter instead.
987 func (c *Client) NotifySpent(outpoints []*wire.OutPoint) error {
988         return c.NotifySpentAsync(outpoints).Receive()
989 }
990
991 // FutureNotifyNewTransactionsResult is a future promise to deliver the result
992 // of a NotifyNewTransactionsAsync RPC invocation (or an applicable error).
993 type FutureNotifyNewTransactionsResult chan *response
994
995 // Receive waits for the response promised by the future and returns an error
996 // if the registration was not successful.
997 func (r FutureNotifyNewTransactionsResult) Receive() error {
998         _, err := receiveFuture(r)
999         return err
1000 }
1001
1002 // NotifyNewTransactionsAsync returns an instance of a type that can be used to
1003 // get the result of the RPC at some future time by invoking the Receive
1004 // function on the returned instance.
1005 //
1006 // See NotifyNewTransactionsAsync for the blocking version and more details.
1007 //
1008 // NOTE: This is a btcd extension and requires a websocket connection.
1009 func (c *Client) NotifyNewTransactionsAsync(verbose bool) FutureNotifyNewTransactionsResult {
1010         // Not supported in HTTP POST mode.
1011         if c.config.HTTPPostMode {
1012                 return newFutureError(ErrWebsocketsRequired)
1013         }
1014
1015         // Ignore the notification if the client is not interested in
1016         // notifications.
1017         if c.ntfnHandlers == nil {
1018                 return newNilFutureResult()
1019         }
1020
1021         cmd := btcjson.NewNotifyNewTransactionsCmd(&verbose)
1022         return c.sendCmd(cmd)
1023 }
1024
1025 // NotifyNewTransactions registers the client to receive notifications every
1026 // time a new transaction is accepted to the memory pool.  The notifications are
1027 // delivered to the notification handlers associated with the client.  Calling
1028 // this function has no effect if there are no notification handlers and will
1029 // result in an error if the client is configured to run in HTTP POST mode.
1030 //
1031 // The notifications delivered as a result of this call will be via one of
1032 // OnTxAccepted (when verbose is false) or OnTxAcceptedVerbose (when verbose is
1033 // true).
1034 //
1035 // NOTE: This is a btcd extension and requires a websocket connection.
1036 func (c *Client) NotifyNewTransactions(verbose bool) error {
1037         return c.NotifyNewTransactionsAsync(verbose).Receive()
1038 }
1039
1040 // FutureNotifyReceivedResult is a future promise to deliver the result of a
1041 // NotifyReceivedAsync RPC invocation (or an applicable error).
1042 //
1043 // NOTE: Deprecated. Use FutureLoadTxFilterResult instead.
1044 type FutureNotifyReceivedResult chan *response
1045
1046 // Receive waits for the response promised by the future and returns an error
1047 // if the registration was not successful.
1048 func (r FutureNotifyReceivedResult) Receive() error {
1049         _, err := receiveFuture(r)
1050         return err
1051 }
1052
1053 // notifyReceivedInternal is the same as notifyReceivedAsync except it accepts
1054 // the converted addresses as a parameter so the client can more efficiently
1055 // recreate the previous notification state on reconnect.
1056 func (c *Client) notifyReceivedInternal(addresses []string) FutureNotifyReceivedResult {
1057         // Not supported in HTTP POST mode.
1058         if c.config.HTTPPostMode {
1059                 return newFutureError(ErrWebsocketsRequired)
1060         }
1061
1062         // Ignore the notification if the client is not interested in
1063         // notifications.
1064         if c.ntfnHandlers == nil {
1065                 return newNilFutureResult()
1066         }
1067
1068         // Convert addresses to strings.
1069         cmd := btcjson.NewNotifyReceivedCmd(addresses)
1070         return c.sendCmd(cmd)
1071 }
1072
1073 // NotifyReceivedAsync returns an instance of a type that can be used to get the
1074 // result of the RPC at some future time by invoking the Receive function on
1075 // the returned instance.
1076 //
1077 // See NotifyReceived for the blocking version and more details.
1078 //
1079 // NOTE: This is a btcd extension and requires a websocket connection.
1080 //
1081 // NOTE: Deprecated. Use LoadTxFilterAsync instead.
1082 func (c *Client) NotifyReceivedAsync(addresses []btcutil.Address) FutureNotifyReceivedResult {
1083         // Not supported in HTTP POST mode.
1084         if c.config.HTTPPostMode {
1085                 return newFutureError(ErrWebsocketsRequired)
1086         }
1087
1088         // Ignore the notification if the client is not interested in
1089         // notifications.
1090         if c.ntfnHandlers == nil {
1091                 return newNilFutureResult()
1092         }
1093
1094         // Convert addresses to strings.
1095         addrs := make([]string, 0, len(addresses))
1096         for _, addr := range addresses {
1097                 addrs = append(addrs, addr.String())
1098         }
1099         cmd := btcjson.NewNotifyReceivedCmd(addrs)
1100         return c.sendCmd(cmd)
1101 }
1102
1103 // NotifyReceived registers the client to receive notifications every time a
1104 // new transaction which pays to one of the passed addresses is accepted to
1105 // memory pool or in a block connected to the block chain.  In addition, when
1106 // one of these transactions is detected, the client is also automatically
1107 // registered for notifications when the new transaction outpoints the address
1108 // now has available are spent (See NotifySpent).  The notifications are
1109 // delivered to the notification handlers associated with the client.  Calling
1110 // this function has no effect if there are no notification handlers and will
1111 // result in an error if the client is configured to run in HTTP POST mode.
1112 //
1113 // The notifications delivered as a result of this call will be via one of
1114 // *OnRecvTx (for transactions that receive funds to one of the passed
1115 // addresses) or OnRedeemingTx (for transactions which spend from one
1116 // of the outpoints which are automatically registered upon receipt of funds to
1117 // the address).
1118 //
1119 // NOTE: This is a btcd extension and requires a websocket connection.
1120 //
1121 // NOTE: Deprecated. Use LoadTxFilter instead.
1122 func (c *Client) NotifyReceived(addresses []btcutil.Address) error {
1123         return c.NotifyReceivedAsync(addresses).Receive()
1124 }
1125
1126 // FutureRescanResult is a future promise to deliver the result of a RescanAsync
1127 // or RescanEndHeightAsync RPC invocation (or an applicable error).
1128 //
1129 // NOTE: Deprecated. Use FutureRescanBlocksResult instead.
1130 type FutureRescanResult chan *response
1131
1132 // Receive waits for the response promised by the future and returns an error
1133 // if the rescan was not successful.
1134 func (r FutureRescanResult) Receive() error {
1135         _, err := receiveFuture(r)
1136         return err
1137 }
1138
1139 // RescanAsync returns an instance of a type that can be used to get the result
1140 // of the RPC at some future time by invoking the Receive function on the
1141 // returned instance.
1142 //
1143 // See Rescan for the blocking version and more details.
1144 //
1145 // NOTE: Rescan requests are not issued on client reconnect and must be
1146 // performed manually (ideally with a new start height based on the last
1147 // rescan progress notification).  See the OnClientConnected notification
1148 // callback for a good callsite to reissue rescan requests on connect and
1149 // reconnect.
1150 //
1151 // NOTE: This is a btcd extension and requires a websocket connection.
1152 //
1153 // NOTE: Deprecated. Use RescanBlocksAsync instead.
1154 func (c *Client) RescanAsync(startBlock *chainhash.Hash,
1155         addresses []btcutil.Address,
1156         outpoints []*wire.OutPoint) FutureRescanResult {
1157
1158         // Not supported in HTTP POST mode.
1159         if c.config.HTTPPostMode {
1160                 return newFutureError(ErrWebsocketsRequired)
1161         }
1162
1163         // Ignore the notification if the client is not interested in
1164         // notifications.
1165         if c.ntfnHandlers == nil {
1166                 return newNilFutureResult()
1167         }
1168
1169         // Convert block hashes to strings.
1170         var startBlockHashStr string
1171         if startBlock != nil {
1172                 startBlockHashStr = startBlock.String()
1173         }
1174
1175         // Convert addresses to strings.
1176         addrs := make([]string, 0, len(addresses))
1177         for _, addr := range addresses {
1178                 addrs = append(addrs, addr.String())
1179         }
1180
1181         // Convert outpoints.
1182         ops := make([]btcjson.OutPoint, 0, len(outpoints))
1183         for _, op := range outpoints {
1184                 ops = append(ops, newOutPointFromWire(op))
1185         }
1186
1187         cmd := btcjson.NewRescanCmd(startBlockHashStr, addrs, ops, nil)
1188         return c.sendCmd(cmd)
1189 }
1190
1191 // Rescan rescans the block chain starting from the provided starting block to
1192 // the end of the longest chain for transactions that pay to the passed
1193 // addresses and transactions which spend the passed outpoints.
1194 //
1195 // The notifications of found transactions are delivered to the notification
1196 // handlers associated with client and this call will not return until the
1197 // rescan has completed.  Calling this function has no effect if there are no
1198 // notification handlers and will result in an error if the client is configured
1199 // to run in HTTP POST mode.
1200 //
1201 // The notifications delivered as a result of this call will be via one of
1202 // OnRedeemingTx (for transactions which spend from the one of the
1203 // passed outpoints), OnRecvTx (for transactions that receive funds
1204 // to one of the passed addresses), and OnRescanProgress (for rescan progress
1205 // updates).
1206 //
1207 // See RescanEndBlock to also specify an ending block to finish the rescan
1208 // without continuing through the best block on the main chain.
1209 //
1210 // NOTE: Rescan requests are not issued on client reconnect and must be
1211 // performed manually (ideally with a new start height based on the last
1212 // rescan progress notification).  See the OnClientConnected notification
1213 // callback for a good callsite to reissue rescan requests on connect and
1214 // reconnect.
1215 //
1216 // NOTE: This is a btcd extension and requires a websocket connection.
1217 //
1218 // NOTE: Deprecated. Use RescanBlocks instead.
1219 func (c *Client) Rescan(startBlock *chainhash.Hash,
1220         addresses []btcutil.Address,
1221         outpoints []*wire.OutPoint) error {
1222
1223         return c.RescanAsync(startBlock, addresses, outpoints).Receive()
1224 }
1225
1226 // RescanEndBlockAsync returns an instance of a type that can be used to get
1227 // the result of the RPC at some future time by invoking the Receive function on
1228 // the returned instance.
1229 //
1230 // See RescanEndBlock for the blocking version and more details.
1231 //
1232 // NOTE: This is a btcd extension and requires a websocket connection.
1233 //
1234 // NOTE: Deprecated. Use RescanBlocksAsync instead.
1235 func (c *Client) RescanEndBlockAsync(startBlock *chainhash.Hash,
1236         addresses []btcutil.Address, outpoints []*wire.OutPoint,
1237         endBlock *chainhash.Hash) FutureRescanResult {
1238
1239         // Not supported in HTTP POST mode.
1240         if c.config.HTTPPostMode {
1241                 return newFutureError(ErrWebsocketsRequired)
1242         }
1243
1244         // Ignore the notification if the client is not interested in
1245         // notifications.
1246         if c.ntfnHandlers == nil {
1247                 return newNilFutureResult()
1248         }
1249
1250         // Convert block hashes to strings.
1251         var startBlockHashStr, endBlockHashStr string
1252         if startBlock != nil {
1253                 startBlockHashStr = startBlock.String()
1254         }
1255         if endBlock != nil {
1256                 endBlockHashStr = endBlock.String()
1257         }
1258
1259         // Convert addresses to strings.
1260         addrs := make([]string, 0, len(addresses))
1261         for _, addr := range addresses {
1262                 addrs = append(addrs, addr.String())
1263         }
1264
1265         // Convert outpoints.
1266         ops := make([]btcjson.OutPoint, 0, len(outpoints))
1267         for _, op := range outpoints {
1268                 ops = append(ops, newOutPointFromWire(op))
1269         }
1270
1271         cmd := btcjson.NewRescanCmd(startBlockHashStr, addrs, ops,
1272                 &endBlockHashStr)
1273         return c.sendCmd(cmd)
1274 }
1275
1276 // RescanEndHeight rescans the block chain starting from the provided starting
1277 // block up to the provided ending block for transactions that pay to the
1278 // passed addresses and transactions which spend the passed outpoints.
1279 //
1280 // The notifications of found transactions are delivered to the notification
1281 // handlers associated with client and this call will not return until the
1282 // rescan has completed.  Calling this function has no effect if there are no
1283 // notification handlers and will result in an error if the client is configured
1284 // to run in HTTP POST mode.
1285 //
1286 // The notifications delivered as a result of this call will be via one of
1287 // OnRedeemingTx (for transactions which spend from the one of the
1288 // passed outpoints), OnRecvTx (for transactions that receive funds
1289 // to one of the passed addresses), and OnRescanProgress (for rescan progress
1290 // updates).
1291 //
1292 // See Rescan to also perform a rescan through current end of the longest chain.
1293 //
1294 // NOTE: This is a btcd extension and requires a websocket connection.
1295 //
1296 // NOTE: Deprecated. Use RescanBlocks instead.
1297 func (c *Client) RescanEndHeight(startBlock *chainhash.Hash,
1298         addresses []btcutil.Address, outpoints []*wire.OutPoint,
1299         endBlock *chainhash.Hash) error {
1300
1301         return c.RescanEndBlockAsync(startBlock, addresses, outpoints,
1302                 endBlock).Receive()
1303 }
1304
1305 // FutureLoadTxFilterResult is a future promise to deliver the result
1306 // of a LoadTxFilterAsync RPC invocation (or an applicable error).
1307 //
1308 // NOTE: This is a btcd extension ported from github.com/decred/dcrrpcclient
1309 // and requires a websocket connection.
1310 type FutureLoadTxFilterResult chan *response
1311
1312 // Receive waits for the response promised by the future and returns an error
1313 // if the registration was not successful.
1314 //
1315 // NOTE: This is a btcd extension ported from github.com/decred/dcrrpcclient
1316 // and requires a websocket connection.
1317 func (r FutureLoadTxFilterResult) Receive() error {
1318         _, err := receiveFuture(r)
1319         return err
1320 }
1321
1322 // LoadTxFilterAsync returns an instance of a type that can be used to
1323 // get the result of the RPC at some future time by invoking the Receive
1324 // function on the returned instance.
1325 //
1326 // See LoadTxFilter for the blocking version and more details.
1327 //
1328 // NOTE: This is a btcd extension ported from github.com/decred/dcrrpcclient
1329 // and requires a websocket connection.
1330 func (c *Client) LoadTxFilterAsync(reload bool, addresses []btcutil.Address,
1331         outPoints []wire.OutPoint) FutureLoadTxFilterResult {
1332
1333         addrStrs := make([]string, len(addresses))
1334         for i, a := range addresses {
1335                 addrStrs[i] = a.EncodeAddress()
1336         }
1337         outPointObjects := make([]btcjson.OutPoint, len(outPoints))
1338         for i := range outPoints {
1339                 outPointObjects[i] = btcjson.OutPoint{
1340                         Hash:  outPoints[i].Hash.String(),
1341                         Index: outPoints[i].Index,
1342                 }
1343         }
1344
1345         cmd := btcjson.NewLoadTxFilterCmd(reload, addrStrs, outPointObjects)
1346         return c.sendCmd(cmd)
1347 }
1348
1349 // LoadTxFilter loads, reloads, or adds data to a websocket client's transaction
1350 // filter.  The filter is consistently updated based on inspected transactions
1351 // during mempool acceptance, block acceptance, and for all rescanned blocks.
1352 //
1353 // NOTE: This is a btcd extension ported from github.com/decred/dcrrpcclient
1354 // and requires a websocket connection.
1355 func (c *Client) LoadTxFilter(reload bool, addresses []btcutil.Address, outPoints []wire.OutPoint) error {
1356         return c.LoadTxFilterAsync(reload, addresses, outPoints).Receive()
1357 }