Example #1
0
// 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
}
Example #2
0
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
}
Example #3
0
// 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
}
Example #4
0
// 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)
	}
}