// parseAccountBalanceNtfnParams parses out the account name, total balance, // and whether or not the balance is confirmed or unconfirmed from the // parameters of an accountbalance notification. func parseAccountBalanceNtfnParams(params []json.RawMessage) (account string, balance btcutil.Amount, confirmed bool, err error) { if len(params) != 3 { return "", 0, false, wrongNumParams(len(params)) } // Unmarshal first parameter as a string. err = json.Unmarshal(params[0], &account) if err != nil { return "", 0, false, err } // Unmarshal second parameter as a floating point number. var fbal float64 err = json.Unmarshal(params[1], &fbal) if err != nil { return "", 0, false, err } // Unmarshal third parameter as a boolean. err = json.Unmarshal(params[2], &confirmed) if err != nil { return "", 0, false, err } // Bounds check amount. bal, err := btcjson.JSONToAmount(fbal) if err != nil { return "", 0, false, err } return account, btcutil.Amount(bal), confirmed, nil }
func parseTxDetails(m map[string]interface{}) (*TxAttributes, error) { var direction txDirection category, ok := m["category"].(string) if !ok { return nil, errors.New("unspecified category") } switch category { case "send": direction = Send case "receive": direction = Recv default: // TODO: support additional listtransaction categories. return nil, fmt.Errorf("unsupported tx category: %v", category) } address, ok := m["address"].(string) if !ok { return nil, errors.New("unspecified address") } famount, ok := m["amount"].(float64) if !ok { return nil, errors.New("unspecified amount") } amount, err := btcjson.JSONToAmount(famount) if !ok { return nil, fmt.Errorf("invalid amount: %v", err) } funixDate, ok := m["timereceived"].(float64) if !ok { return nil, errors.New("unspecified time") } if fblockTime, ok := m["blocktime"].(float64); ok { if fblockTime < funixDate { funixDate = fblockTime } } unixDate := int64(funixDate) return &TxAttributes{ Direction: direction, Address: address, Amount: amount, Date: time.Unix(unixDate, 0), }, nil }
// TestJSONtoAmount tests that JSONtoAmount returns the proper values. func TestJSONtoAmount(t *testing.T) { for _, tt := range floattests { res, err := btcjson.JSONToAmount(tt.in) if tt.pass { if res != tt.out || err != nil { t.Errorf("Should not fail: %v", tt.in) } } else { if err == nil { t.Errorf("Should not pass: %v", tt.in) } } } return }
// handleNotification examines the passed notification type, performs // conversions to get the raw notification types into higher level types and // delivers the notification to the appropriate On<X> handler registered with // the client. func (c *Client) handleNotification(cmd btcjson.Cmd) { // Ignore the notification if the client is not interested in any // notifications. if c.ntfnHandlers == nil { return } switch ntfn := cmd.(type) { // OnBlockConnected case *btcws.BlockConnectedNtfn: // Ignore the notification is the client is not interested in // it. if c.ntfnHandlers.OnBlockConnected == nil { return } hash, err := btcwire.NewShaHashFromStr(ntfn.Hash) if err != nil { log.Warnf("Received block connected notification with "+ "invalid hash string: %q", ntfn.Hash) return } c.ntfnHandlers.OnBlockConnected(hash, ntfn.Height) // OnBlockDisconnected case *btcws.BlockDisconnectedNtfn: // Ignore the notification is the client is not interested in // it. if c.ntfnHandlers.OnBlockDisconnected == nil { return } hash, err := btcwire.NewShaHashFromStr(ntfn.Hash) if err != nil { log.Warnf("Received block disconnected notification "+ "with invalid hash string: %q", ntfn.Hash) return } c.ntfnHandlers.OnBlockDisconnected(hash, ntfn.Height) // OnRecvTx case *btcws.RecvTxNtfn: // Ignore the notification is the client is not interested in // it. if c.ntfnHandlers.OnRecvTx == nil { return } // Decode the serialized transaction hex to raw bytes. serializedTx, err := hex.DecodeString(ntfn.HexTx) if err != nil { log.Warnf("Received recvtx notification with invalid "+ "transaction hex '%q': %v", ntfn.HexTx, err) } // Deserialize the transaction. var msgTx btcwire.MsgTx err = msgTx.Deserialize(bytes.NewReader(serializedTx)) if err != nil { log.Warnf("Received recvtx notification with "+ "transaction that failed to deserialize: %v", err) } c.ntfnHandlers.OnRecvTx(btcutil.NewTx(&msgTx), ntfn.Block) // OnRedeemingTx case *btcws.RedeemingTxNtfn: // Ignore the notification is the client is not interested in // it. if c.ntfnHandlers.OnRedeemingTx == nil { return } // Decode the serialized transaction hex to raw bytes. serializedTx, err := hex.DecodeString(ntfn.HexTx) if err != nil { log.Warnf("Received redeemingtx notification with "+ "invalid transaction hex '%q': %v", ntfn.HexTx, err) } // Deserialize the transaction. var msgTx btcwire.MsgTx err = msgTx.Deserialize(bytes.NewReader(serializedTx)) if err != nil { log.Warnf("Received redeemingtx notification with "+ "transaction that failed to deserialize: %v", err) } c.ntfnHandlers.OnRedeemingTx(btcutil.NewTx(&msgTx), ntfn.Block) // OnRescanProgress case *btcws.RescanProgressNtfn: // Ignore the notification is the client is not interested in // it. if c.ntfnHandlers.OnRescanProgress == nil { return } c.ntfnHandlers.OnRescanProgress(ntfn.LastProcessed) // OnTxAccepted case *btcws.TxAcceptedNtfn: // Ignore the notification is the client is not interested in // it. if c.ntfnHandlers.OnTxAccepted == nil { return } hash, err := btcwire.NewShaHashFromStr(ntfn.TxID) if err != nil { log.Warnf("Received tx accepted notification with "+ "invalid hash string: %q", ntfn.TxID) return } c.ntfnHandlers.OnTxAccepted(hash, btcutil.Amount(ntfn.Amount)) // OnTxAcceptedVerbose case *btcws.TxAcceptedVerboseNtfn: // Ignore the notification is the client is not interested in // it. if c.ntfnHandlers.OnTxAcceptedVerbose == nil { return } c.ntfnHandlers.OnTxAcceptedVerbose(ntfn.RawTx) // OnBtcdConnected case *btcws.BtcdConnectedNtfn: // Ignore the notification is the client is not interested in // it. if c.ntfnHandlers.OnBtcdConnected == nil { return } c.ntfnHandlers.OnBtcdConnected(ntfn.Connected) // OnAccountBalance case *btcws.AccountBalanceNtfn: // Ignore the notification is the client is not interested in // it. if c.ntfnHandlers.OnAccountBalance == nil { return } balance, err := btcjson.JSONToAmount(ntfn.Balance) if err != nil { log.Warnf("Received account balance notification with "+ "an amount that does not parse: %v", ntfn.Balance) return } c.ntfnHandlers.OnAccountBalance(ntfn.Account, btcutil.Amount(balance), ntfn.Confirmed) // OnWalletLockState case *btcws.WalletLockStateNtfn: // Ignore the notification is the client is not interested in // it. if c.ntfnHandlers.OnWalletLockState == nil { return } c.ntfnHandlers.OnWalletLockState(ntfn.Locked) // OnUnknownNotification default: if c.ntfnHandlers.OnUnknownNotification == nil { return } c.ntfnHandlers.OnUnknownNotification(ntfn) } }