commit f5ef8a38f8d87b3f301e5ecc5500060c71cb1bf0
parent 7f7d5959ad8b6c18533a2cbe0747a86709c69cfa
Author: Joel-Haeberli <haebu@rubigen.ch>
Date: Mon, 3 Jun 2024 12:22:26 +0200
fix: amount bug
Diffstat:
8 files changed, 65 insertions(+), 26 deletions(-)
diff --git a/c2ec/amount.go b/c2ec/amount.go
@@ -119,7 +119,7 @@ func toFractionStr(frac int, fractionalDigits int) string {
// Subtract the amount b from a and return the result.
// a and b must be of the same currency and a >= b
-func (a *Amount) Sub(b Amount) (*Amount, error) {
+func (a *Amount) Sub(b Amount, fractionalDigits int) (*Amount, error) {
if a.Currency != b.Currency {
return nil, errors.New("currency mismatch")
}
@@ -127,7 +127,7 @@ func (a *Amount) Sub(b Amount) (*Amount, error) {
f := a.Fraction
if a.Fraction < b.Fraction {
v -= 1
- f += FractionalBase
+ f += uint64(math.Pow10(fractionalDigits))
}
f -= b.Fraction
if v < b.Value {
@@ -145,7 +145,7 @@ func (a *Amount) Sub(b Amount) (*Amount, error) {
// Add b to a and return the result.
// Returns an error if the currencies do not match or the addition would
// cause an overflow of the value
-func (a *Amount) Add(b Amount) (*Amount, error) {
+func (a *Amount) Add(b Amount, fractionalDigits int) (*Amount, error) {
if a.Currency != b.Currency {
return nil, errors.New("currency mismatch")
}
@@ -156,7 +156,7 @@ func (a *Amount) Add(b Amount) (*Amount, error) {
if v >= MaxAmountValue {
return nil, fmt.Errorf("amount overflow (%d > %d)", v, MaxAmountValue)
}
- f := uint64((a.Fraction + b.Fraction) % FractionalBase)
+ f := uint64((a.Fraction + b.Fraction) % uint64(math.Pow10(fractionalDigits)))
r := Amount{
Currency: a.Currency,
Value: v,
@@ -223,12 +223,4 @@ func (a *Amount) IsZero() bool {
func (a *Amount) String(fractionalDigits int) string {
return FormatAmount(a, fractionalDigits)
-
- // v := strconv.FormatUint(a.Value, 10)
- // if a.Fraction != 0 {
- // f := strconv.FormatUint(a.Fraction, 10)
- // f = strings.TrimRight(f, "0")
- // v = fmt.Sprintf("%s.%s", v, f)
- // }
- // return fmt.Sprintf("%s:%s", a.Currency, v)
}
diff --git a/c2ec/amount_test.go b/c2ec/amount_test.go
@@ -1,5 +1,6 @@
// This file is part of taler-go, the Taler Go implementation.
// Copyright (C) 2022 Martin Schanzenbach
+// Copyright (C) 2024 Joel Häberli
//
// Taler Go is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published
@@ -40,7 +41,7 @@ var c = Amount{
}
func TestAmountAdd(t *testing.T) {
- d, err := a.Add(b)
+ d, err := a.Add(b, 8)
if err != nil {
t.Errorf("Failed adding amount")
}
@@ -50,7 +51,7 @@ func TestAmountAdd(t *testing.T) {
}
func TestAmountSub(t *testing.T) {
- d, err := c.Sub(b)
+ d, err := c.Sub(b, 8)
if err != nil {
t.Errorf("Failed substracting amount")
}
@@ -65,7 +66,7 @@ func TestAmountLarge(t *testing.T) {
fmt.Println(err)
t.Errorf("Failed")
}
- _, err = x.Add(a)
+ _, err = x.Add(a, 2)
if err != nil {
fmt.Println(err)
t.Errorf("Failed")
@@ -93,7 +94,7 @@ func TestAmountSub2(t *testing.T) {
t.FailNow()
}
fmt.Println("subtracting", am.String(2))
- a2, err := am.Sub(*am)
+ a2, err := am.Sub(*am, 2)
if err != nil {
fmt.Println("subtracting failed!", a, err)
t.FailNow()
@@ -122,7 +123,7 @@ func TestAmountSub3(t *testing.T) {
t.FailNow()
}
fmt.Println("subtracting", am.String(4))
- a2, err := am.Sub(*am)
+ a2, err := am.Sub(*am, 4)
if err != nil {
fmt.Println("subtracting failed!", a, err)
t.FailNow()
@@ -268,3 +269,31 @@ func TestFormatAmountInvalid(t *testing.T) {
}
}
}
+
+func TestFeesSub(t *testing.T) {
+
+ amountWithFeesStr := fmt.Sprintf("%s:%s", "CHF", "5.00")
+ amountWithFees, err := ParseAmount(amountWithFeesStr, 3)
+ if err != nil {
+ fmt.Println("failed!", err)
+ t.FailNow()
+ }
+
+ fees, err := ParseAmount("CHF:0.005", 3)
+ if err != nil {
+ fmt.Println("failed!", err)
+ t.FailNow()
+ }
+
+ refundAmount, err := amountWithFees.Sub(*fees, 3)
+ if err != nil {
+ fmt.Println("failed!", err)
+ t.FailNow()
+ }
+
+ if amnt := refundAmount.String(3); amnt != "CHF:4.995" {
+ fmt.Println("expected the refund amount to be CHF:4.995, but it was", amnt)
+ } else {
+ fmt.Println("refundable amount:", amnt)
+ }
+}
diff --git a/c2ec/api-wire-gateway.go b/c2ec/api-wire-gateway.go
@@ -173,7 +173,7 @@ func transfer(res http.ResponseWriter, req *http.Request) {
return
}
- paytoTargetType, tid, err := ParsePaytoWalleeTransaction(transfer.CreditAccount)
+ paytoTargetType, tid, err := ParsePaytoUri(transfer.CreditAccount)
if err != nil {
LogError("wire-gateway-api", err)
setLastResponseCodeForLogger(HTTP_BAD_REQUEST)
diff --git a/c2ec/codec_test.go b/c2ec/codec_test.go
@@ -60,3 +60,22 @@ func TestJsonCodecRoundTrip(t *testing.T) {
assert.DeepEqual(t, &testObj, decodedTestObj)
}
+
+func TestTransferRequest(t *testing.T) {
+
+ reqStr := "{\"request_uid\":\"test-1\",\"amount\":\"CHF:4.95\",\"exchange_base_url\":\"https://exchange.chf.taler.net\",\"wtid\":\"\",\"credit_account\":\"payto://wallee-transaction/R361ZT45TZ026EQ0S909C88F0E2YJY11HXV0VQTCHKR2VHA7DQCG\"}"
+
+ fmt.Println("request string:", reqStr)
+
+ codec := NewJsonCodec[TransferRequest]()
+
+ rdr := bytes.NewReader([]byte(reqStr))
+
+ req, err := codec.Decode(rdr)
+ if err != nil {
+ fmt.Println("error:", err)
+ t.FailNow()
+ }
+
+ fmt.Println(req)
+}
diff --git a/c2ec/encoding.go b/c2ec/encoding.go
@@ -72,7 +72,7 @@ func decodeCrock(e string) ([]byte, error) {
return i, nil
}
- return -1, errors.New("encoding error")
+ return -1, errors.New("crockford decoding error")
}
for readPosition < size || bitpos > 0 {
diff --git a/c2ec/payto.go b/c2ec/payto.go
@@ -33,9 +33,8 @@ func ParsePaytoWalleeTransaction(uri string) (string, string, error) {
if t, i, err := ParsePaytoUri(uri); err != nil {
- _, err := decodeCrock(i)
- if err != nil {
- return "", "", errors.New("invalid transaction-id for wallee-transaction")
+ if t != "wallee-transaction" {
+ return "", "", errors.New("expected payto target type 'wallee-transaction'")
}
return t, i, nil
@@ -53,7 +52,7 @@ func ParsePaytoUri(uri string) (string, string, error) {
parts := strings.Split(raw, PAYTO_PARTS_SEPARATOR)
if len(parts) < 2 {
- return "", "", errors.New("invalid wallee-transaction payto-uri")
+ return "", "", errors.New("invalid payto-uri")
}
return parts[0], parts[1], nil
diff --git a/c2ec/proc-transfer.go b/c2ec/proc-transfer.go
@@ -64,7 +64,7 @@ func transferCallback(notification *Notification, errs chan error) {
errs <- err
}
- paytoTargetType, tid, err := ParsePaytoWalleeTransaction(transfer.CreditAccount)
+ paytoTargetType, tid, err := ParsePaytoUri(transfer.CreditAccount)
if err != nil {
errs <- errors.New("malformed transfer request uid: " + err.Error())
transferFailed(transfer, errs)
@@ -118,7 +118,7 @@ func executePendingTransfers(errs chan error) {
continue
}
- paytoTargetType, tid, err := ParsePaytoWalleeTransaction(t.CreditAccount)
+ paytoTargetType, tid, err := ParsePaytoUri(t.CreditAccount)
if err != nil {
LogError("proc-transfer", err)
errs <- err
diff --git a/c2ec/wallee-client.go b/c2ec/wallee-client.go
@@ -205,7 +205,7 @@ func (w *WalleeClient) Refund(transactionId string) error {
return err
}
- refundAmount, err := amountWithFees.Sub(*fees)
+ refundAmount, err := amountWithFees.Sub(*fees, CONFIG.Server.CurrencyFractionDigits)
if err != nil {
LogError("wallee-client", err)
return err