Commit c0505167 authored by Ralph Pichler's avatar Ralph Pichler Committed by GitHub

chequebook: change cashout api to include uncashed amount (#1402)

parent b4811d8c
...@@ -351,16 +351,14 @@ components: ...@@ -351,16 +351,14 @@ components:
properties: properties:
peer: peer:
$ref: "#/components/schemas/SwarmAddress" $ref: "#/components/schemas/SwarmAddress"
chequebook: lastCashedCheque:
$ref: "#/components/schemas/EthereumAddress" $ref: "#/components/schemas/Cheque"
cumulativePayout:
type: integer
beneficiary:
$ref: "#/components/schemas/EthereumAddress"
transactionHash: transactionHash:
$ref: "#/components/schemas/TransactionHash" $ref: "#/components/schemas/TransactionHash"
result: result:
$ref: "#/components/schemas/SwapCashoutResult" $ref: "#/components/schemas/SwapCashoutResult"
uncashedAmount:
type: integer
TagName: TagName:
type: string type: string
......
...@@ -252,11 +252,10 @@ type swapCashoutStatusResult struct { ...@@ -252,11 +252,10 @@ type swapCashoutStatusResult struct {
type swapCashoutStatusResponse struct { type swapCashoutStatusResponse struct {
Peer swarm.Address `json:"peer"` Peer swarm.Address `json:"peer"`
Chequebook common.Address `json:"chequebook"` Cheque *chequebookLastChequePeerResponse `json:"lastCashedCheque"`
CumulativePayout *big.Int `json:"cumulativePayout"` TransactionHash *common.Hash `json:"transactionHash"`
Beneficiary common.Address `json:"beneficiary"`
TransactionHash common.Hash `json:"transactionHash"`
Result *swapCashoutStatusResult `json:"result"` Result *swapCashoutStatusResult `json:"result"`
UncashedAmount *big.Int `json:"uncashedAmount"`
} }
func (s *Service) swapCashoutStatusHandler(w http.ResponseWriter, r *http.Request) { func (s *Service) swapCashoutStatusHandler(w http.ResponseWriter, r *http.Request) {
...@@ -290,21 +289,30 @@ func (s *Service) swapCashoutStatusHandler(w http.ResponseWriter, r *http.Reques ...@@ -290,21 +289,30 @@ func (s *Service) swapCashoutStatusHandler(w http.ResponseWriter, r *http.Reques
} }
var result *swapCashoutStatusResult var result *swapCashoutStatusResult
if status.Result != nil { var txHash *common.Hash
var chequeResponse *chequebookLastChequePeerResponse
if status.Last != nil {
if status.Last.Result != nil {
result = &swapCashoutStatusResult{ result = &swapCashoutStatusResult{
Recipient: status.Result.Recipient, Recipient: status.Last.Result.Recipient,
LastPayout: status.Result.TotalPayout, LastPayout: status.Last.Result.TotalPayout,
Bounced: status.Result.Bounced, Bounced: status.Last.Result.Bounced,
}
}
chequeResponse = &chequebookLastChequePeerResponse{
Chequebook: status.Last.Cheque.Chequebook.String(),
Payout: status.Last.Cheque.CumulativePayout,
Beneficiary: status.Last.Cheque.Beneficiary.String(),
} }
txHash = &status.Last.TxHash
} }
jsonhttp.OK(w, swapCashoutStatusResponse{ jsonhttp.OK(w, swapCashoutStatusResponse{
Peer: peer, Peer: peer,
TransactionHash: status.TxHash, TransactionHash: txHash,
Chequebook: status.Cheque.Chequebook, Cheque: chequeResponse,
CumulativePayout: status.Cheque.CumulativePayout,
Beneficiary: status.Cheque.Beneficiary,
Result: result, Result: result,
UncashedAmount: status.UncashedAmount,
}) })
} }
......
...@@ -481,6 +481,7 @@ func TestChequebookCashoutStatus(t *testing.T) { ...@@ -481,6 +481,7 @@ func TestChequebookCashoutStatus(t *testing.T) {
recipientAddress := common.HexToAddress("efff") recipientAddress := common.HexToAddress("efff")
totalPayout := big.NewInt(100) totalPayout := big.NewInt(100)
cumulativePayout := big.NewInt(700) cumulativePayout := big.NewInt(700)
uncashedAmount := big.NewInt(200)
chequebookAddress := common.HexToAddress("0xcfec") chequebookAddress := common.HexToAddress("0xcfec")
peer := swarm.MustParseHexAddress("1000000000000000000000000000000000000000000000000000000000000000") peer := swarm.MustParseHexAddress("1000000000000000000000000000000000000000000000000000000000000000")
...@@ -504,12 +505,16 @@ func TestChequebookCashoutStatus(t *testing.T) { ...@@ -504,12 +505,16 @@ func TestChequebookCashoutStatus(t *testing.T) {
Bounced: false, Bounced: false,
} }
t.Run("with result", func(t *testing.T) {
cashoutStatusFunc := func(ctx context.Context, peer swarm.Address) (*chequebook.CashoutStatus, error) { cashoutStatusFunc := func(ctx context.Context, peer swarm.Address) (*chequebook.CashoutStatus, error) {
status := &chequebook.CashoutStatus{ status := &chequebook.CashoutStatus{
Last: &chequebook.LastCashout{
TxHash: actionTxHash, TxHash: actionTxHash,
Cheque: *cheque, Cheque: *cheque,
Result: result, Result: result,
Reverted: false, Reverted: false,
},
UncashedAmount: uncashedAmount,
} }
return status, nil return status, nil
} }
...@@ -518,19 +523,60 @@ func TestChequebookCashoutStatus(t *testing.T) { ...@@ -518,19 +523,60 @@ func TestChequebookCashoutStatus(t *testing.T) {
SwapOpts: []swapmock.Option{swapmock.WithCashoutStatusFunc(cashoutStatusFunc)}, SwapOpts: []swapmock.Option{swapmock.WithCashoutStatusFunc(cashoutStatusFunc)},
}) })
statusResult := &debugapi.SwapCashoutStatusResult{ expected := &debugapi.SwapCashoutStatusResponse{
Peer: peer,
TransactionHash: &actionTxHash,
Cheque: &debugapi.ChequebookLastChequePeerResponse{
Chequebook: chequebookAddress.String(),
Payout: cumulativePayout,
Beneficiary: cheque.Beneficiary.String(),
},
Result: &debugapi.SwapCashoutStatusResult{
Recipient: recipientAddress, Recipient: recipientAddress,
LastPayout: totalPayout, LastPayout: totalPayout,
Bounced: false, Bounced: false,
},
UncashedAmount: uncashedAmount,
}
var got *debugapi.SwapCashoutStatusResponse
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/chequebook/cashout/"+addr.String(), http.StatusOK,
jsonhttptest.WithUnmarshalJSONResponse(&got),
)
if !reflect.DeepEqual(got, expected) {
t.Fatalf("Got: \n %+v \n\n Expected: \n %+v \n\n", got, expected)
} }
})
t.Run("without result", func(t *testing.T) {
cashoutStatusFunc := func(ctx context.Context, peer swarm.Address) (*chequebook.CashoutStatus, error) {
status := &chequebook.CashoutStatus{
Last: &chequebook.LastCashout{
TxHash: actionTxHash,
Cheque: *cheque,
Result: nil,
Reverted: false,
},
UncashedAmount: uncashedAmount,
}
return status, nil
}
testServer := newTestServer(t, testServerOptions{
SwapOpts: []swapmock.Option{swapmock.WithCashoutStatusFunc(cashoutStatusFunc)},
})
expected := &debugapi.SwapCashoutStatusResponse{ expected := &debugapi.SwapCashoutStatusResponse{
Peer: peer, Peer: peer,
TransactionHash: actionTxHash, TransactionHash: &actionTxHash,
Chequebook: chequebookAddress, Cheque: &debugapi.ChequebookLastChequePeerResponse{
CumulativePayout: cumulativePayout, Chequebook: chequebookAddress.String(),
Beneficiary: cheque.Beneficiary, Payout: cumulativePayout,
Result: statusResult, Beneficiary: cheque.Beneficiary.String(),
},
Result: nil,
UncashedAmount: uncashedAmount,
} }
var got *debugapi.SwapCashoutStatusResponse var got *debugapi.SwapCashoutStatusResponse
...@@ -541,7 +587,38 @@ func TestChequebookCashoutStatus(t *testing.T) { ...@@ -541,7 +587,38 @@ func TestChequebookCashoutStatus(t *testing.T) {
if !reflect.DeepEqual(got, expected) { if !reflect.DeepEqual(got, expected) {
t.Fatalf("Got: \n %+v \n\n Expected: \n %+v \n\n", got, expected) t.Fatalf("Got: \n %+v \n\n Expected: \n %+v \n\n", got, expected)
} }
})
t.Run("without last", func(t *testing.T) {
cashoutStatusFunc := func(ctx context.Context, peer swarm.Address) (*chequebook.CashoutStatus, error) {
status := &chequebook.CashoutStatus{
Last: nil,
UncashedAmount: uncashedAmount,
}
return status, nil
}
testServer := newTestServer(t, testServerOptions{
SwapOpts: []swapmock.Option{swapmock.WithCashoutStatusFunc(cashoutStatusFunc)},
})
expected := &debugapi.SwapCashoutStatusResponse{
Peer: peer,
TransactionHash: nil,
Cheque: nil,
Result: nil,
UncashedAmount: uncashedAmount,
}
var got *debugapi.SwapCashoutStatusResponse
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/chequebook/cashout/"+addr.String(), http.StatusOK,
jsonhttptest.WithUnmarshalJSONResponse(&got),
)
if !reflect.DeepEqual(got, expected) {
t.Fatalf("Got: \n %+v \n\n Expected: \n %+v \n\n", got, expected)
}
})
} }
func LastChequesEqual(a, b *debugapi.ChequebookLastChequesResponse) bool { func LastChequesEqual(a, b *debugapi.ChequebookLastChequesResponse) bool {
......
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethersphere/bee/pkg/sctx" "github.com/ethersphere/bee/pkg/sctx"
...@@ -38,14 +39,20 @@ type cashoutService struct { ...@@ -38,14 +39,20 @@ type cashoutService struct {
chequeStore ChequeStore chequeStore ChequeStore
} }
// CashoutStatus is the action plus its result // LastCashout contains information about the last cashout
type CashoutStatus struct { type LastCashout struct {
TxHash common.Hash TxHash common.Hash
Cheque SignedCheque // the cheque that was used to cashout which may be different from the latest cheque Cheque SignedCheque // the cheque that was used to cashout which may be different from the latest cheque
Result *CashChequeResult Result *CashChequeResult
Reverted bool Reverted bool
} }
// CashoutStatus is information about the last cashout and uncashed amounts
type CashoutStatus struct {
Last *LastCashout // last cashout for a chequebook
UncashedAmount *big.Int // amount not yet cashed out
}
// CashChequeResult summarizes the result of a CashCheque or CashChequeBeneficiary call // CashChequeResult summarizes the result of a CashCheque or CashChequeBeneficiary call
type CashChequeResult struct { type CashChequeResult struct {
Beneficiary common.Address // beneficiary of the cheque Beneficiary common.Address // beneficiary of the cheque
...@@ -91,6 +98,37 @@ func cashoutActionKey(chequebook common.Address) string { ...@@ -91,6 +98,37 @@ func cashoutActionKey(chequebook common.Address) string {
return fmt.Sprintf("swap_cashout_%x", chequebook) return fmt.Sprintf("swap_cashout_%x", chequebook)
} }
func (s *cashoutService) paidOut(ctx context.Context, chequebook, beneficiary common.Address) (*big.Int, error) {
callData, err := chequebookABI.Pack("paidOut", beneficiary)
if err != nil {
return nil, err
}
output, err := s.transactionService.Call(ctx, &transaction.TxRequest{
To: &chequebook,
Data: callData,
})
if err != nil {
return nil, err
}
results, err := chequebookABI.Unpack("paidOut", output)
if err != nil {
return nil, err
}
if len(results) != 1 {
return nil, errDecodeABI
}
paidOut, ok := abi.ConvertType(results[0], new(big.Int)).(*big.Int)
if !ok || paidOut == nil {
return nil, errDecodeABI
}
return paidOut, nil
}
// CashCheque sends a cashout transaction for the last cheque of the chequebook // CashCheque sends a cashout transaction for the last cheque of the chequebook
func (s *cashoutService) CashCheque(ctx context.Context, chequebook, recipient common.Address) (common.Hash, error) { func (s *cashoutService) CashCheque(ctx context.Context, chequebook, recipient common.Address) (common.Hash, error) {
cheque, err := s.chequeStore.LastCheque(chequebook) cheque, err := s.chequeStore.LastCheque(chequebook)
...@@ -133,11 +171,19 @@ func (s *cashoutService) CashCheque(ctx context.Context, chequebook, recipient c ...@@ -133,11 +171,19 @@ func (s *cashoutService) CashCheque(ctx context.Context, chequebook, recipient c
// CashoutStatus gets the status of the latest cashout transaction for the chequebook // CashoutStatus gets the status of the latest cashout transaction for the chequebook
func (s *cashoutService) CashoutStatus(ctx context.Context, chequebookAddress common.Address) (*CashoutStatus, error) { func (s *cashoutService) CashoutStatus(ctx context.Context, chequebookAddress common.Address) (*CashoutStatus, error) {
var action *cashoutAction cheque, err := s.chequeStore.LastCheque(chequebookAddress)
err := s.store.Get(cashoutActionKey(chequebookAddress), &action) if err != nil {
return nil, err
}
var action cashoutAction
err = s.store.Get(cashoutActionKey(chequebookAddress), &action)
if err != nil { if err != nil {
if errors.Is(err, storage.ErrNotFound) { if errors.Is(err, storage.ErrNotFound) {
return nil, ErrNoCashout return &CashoutStatus{
Last: nil,
UncashedAmount: cheque.CumulativePayout, // if we never cashed out, assume everything is uncashed
}, nil
} }
return nil, err return nil, err
} }
...@@ -153,10 +199,14 @@ func (s *cashoutService) CashoutStatus(ctx context.Context, chequebookAddress co ...@@ -153,10 +199,14 @@ func (s *cashoutService) CashoutStatus(ctx context.Context, chequebookAddress co
if pending { if pending {
return &CashoutStatus{ return &CashoutStatus{
Last: &LastCashout{
TxHash: action.TxHash, TxHash: action.TxHash,
Cheque: action.Cheque, Cheque: action.Cheque,
Result: nil, Result: nil,
Reverted: false, Reverted: false,
},
// uncashed is the difference since the last sent cashout. we assume that the entire cheque will clear in the pending transaction.
UncashedAmount: new(big.Int).Sub(cheque.CumulativePayout, action.Cheque.CumulativePayout),
}, nil }, nil
} }
...@@ -166,11 +216,21 @@ func (s *cashoutService) CashoutStatus(ctx context.Context, chequebookAddress co ...@@ -166,11 +216,21 @@ func (s *cashoutService) CashoutStatus(ctx context.Context, chequebookAddress co
} }
if receipt.Status == types.ReceiptStatusFailed { if receipt.Status == types.ReceiptStatusFailed {
// if a tx failed (should be almost impossible in practice) we no longer have the necessary information to compute uncashed locally
// assume there are no pending transactions and that the on-chain paidOut is the last cashout action
paidOut, err := s.paidOut(ctx, chequebookAddress, cheque.Beneficiary)
if err != nil {
return nil, err
}
return &CashoutStatus{ return &CashoutStatus{
Last: &LastCashout{
TxHash: action.TxHash, TxHash: action.TxHash,
Cheque: action.Cheque, Cheque: action.Cheque,
Result: nil, Result: nil,
Reverted: true, Reverted: true,
},
UncashedAmount: new(big.Int).Sub(cheque.CumulativePayout, paidOut),
}, nil }, nil
} }
...@@ -180,10 +240,14 @@ func (s *cashoutService) CashoutStatus(ctx context.Context, chequebookAddress co ...@@ -180,10 +240,14 @@ func (s *cashoutService) CashoutStatus(ctx context.Context, chequebookAddress co
} }
return &CashoutStatus{ return &CashoutStatus{
Last: &LastCashout{
TxHash: action.TxHash, TxHash: action.TxHash,
Cheque: action.Cheque, Cheque: action.Cheque,
Result: result, Result: result,
Reverted: false, Reverted: false,
},
// uncashed is the difference since the last sent (and confirmed) cashout.
UncashedAmount: new(big.Int).Sub(cheque.CumulativePayout, result.CumulativePayout),
}, nil }, nil
} }
......
...@@ -75,15 +75,7 @@ func TestCashout(t *testing.T) { ...@@ -75,15 +75,7 @@ func TestCashout(t *testing.T) {
}), }),
), ),
transactionmock.New( transactionmock.New(
transactionmock.WithSendFunc(func(c context.Context, request *transaction.TxRequest) (common.Hash, error) { transactionmock.WithABISend(&chequebookABI, txHash, chequebookAddress, big.NewInt(0), "cashChequeBeneficiary", recipientAddress, cheque.CumulativePayout, cheque.Signature),
if request.To != nil && *request.To != chequebookAddress {
t.Fatalf("sending to wrong contract. wanted %x, got %x", chequebookAddress, request.To)
}
if request.Value.Cmp(big.NewInt(0)) != 0 {
t.Fatal("sending ether to chequebook contract")
}
return txHash, nil
}),
), ),
chequestoremock.NewChequeStore( chequestoremock.NewChequeStore(
chequestoremock.WithLastChequeFunc(func(c common.Address) (*chequebook.SignedCheque, error) { chequestoremock.WithLastChequeFunc(func(c common.Address) (*chequebook.SignedCheque, error) {
...@@ -109,23 +101,11 @@ func TestCashout(t *testing.T) { ...@@ -109,23 +101,11 @@ func TestCashout(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if status.Reverted { verifyStatus(t, status, chequebook.CashoutStatus{
t.Fatal("reported reverted transaction") Last: &chequebook.LastCashout{
} TxHash: txHash,
Cheque: *cheque,
if status.TxHash != txHash { Result: &chequebook.CashChequeResult{
t.Fatalf("wrong transaction hash. wanted %v, got %v", txHash, status.TxHash)
}
if !status.Cheque.Equal(cheque) {
t.Fatalf("wrong cheque in status. wanted %v, got %v", cheque, status.Cheque)
}
if status.Result == nil {
t.Fatal("missing result")
}
expectedResult := &chequebook.CashChequeResult{
Beneficiary: cheque.Beneficiary, Beneficiary: cheque.Beneficiary,
Recipient: recipientAddress, Recipient: recipientAddress,
Caller: cheque.Beneficiary, Caller: cheque.Beneficiary,
...@@ -133,11 +113,11 @@ func TestCashout(t *testing.T) { ...@@ -133,11 +113,11 @@ func TestCashout(t *testing.T) {
CumulativePayout: cumulativePayout, CumulativePayout: cumulativePayout,
CallerPayout: big.NewInt(0), CallerPayout: big.NewInt(0),
Bounced: false, Bounced: false,
} },
Reverted: false,
if !status.Result.Equal(expectedResult) { },
t.Fatalf("wrong result. wanted %v, got %v", expectedResult, status.Result) UncashedAmount: big.NewInt(0),
} })
} }
func TestCashoutBounced(t *testing.T) { func TestCashoutBounced(t *testing.T) {
...@@ -193,15 +173,7 @@ func TestCashoutBounced(t *testing.T) { ...@@ -193,15 +173,7 @@ func TestCashoutBounced(t *testing.T) {
}), }),
), ),
transactionmock.New( transactionmock.New(
transactionmock.WithSendFunc(func(c context.Context, request *transaction.TxRequest) (common.Hash, error) { transactionmock.WithABISend(&chequebookABI, txHash, chequebookAddress, big.NewInt(0), "cashChequeBeneficiary", recipientAddress, cheque.CumulativePayout, cheque.Signature),
if request.To != nil && *request.To != chequebookAddress {
t.Fatalf("sending to wrong contract. wanted %x, got %x", chequebookAddress, request.To)
}
if request.Value.Cmp(big.NewInt(0)) != 0 {
t.Fatal("sending ether to chequebook contract")
}
return txHash, nil
}),
), ),
chequestoremock.NewChequeStore( chequestoremock.NewChequeStore(
chequestoremock.WithLastChequeFunc(func(c common.Address) (*chequebook.SignedCheque, error) { chequestoremock.WithLastChequeFunc(func(c common.Address) (*chequebook.SignedCheque, error) {
...@@ -227,23 +199,11 @@ func TestCashoutBounced(t *testing.T) { ...@@ -227,23 +199,11 @@ func TestCashoutBounced(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if status.Reverted { verifyStatus(t, status, chequebook.CashoutStatus{
t.Fatal("reported reverted transaction") Last: &chequebook.LastCashout{
} TxHash: txHash,
Cheque: *cheque,
if status.TxHash != txHash { Result: &chequebook.CashChequeResult{
t.Fatalf("wrong transaction hash. wanted %v, got %v", txHash, status.TxHash)
}
if !status.Cheque.Equal(cheque) {
t.Fatalf("wrong cheque in status. wanted %v, got %v", cheque, status.Cheque)
}
if status.Result == nil {
t.Fatal("missing result")
}
expectedResult := &chequebook.CashChequeResult{
Beneficiary: cheque.Beneficiary, Beneficiary: cheque.Beneficiary,
Recipient: recipientAddress, Recipient: recipientAddress,
Caller: cheque.Beneficiary, Caller: cheque.Beneficiary,
...@@ -251,11 +211,11 @@ func TestCashoutBounced(t *testing.T) { ...@@ -251,11 +211,11 @@ func TestCashoutBounced(t *testing.T) {
CumulativePayout: cumulativePayout, CumulativePayout: cumulativePayout,
CallerPayout: big.NewInt(0), CallerPayout: big.NewInt(0),
Bounced: true, Bounced: true,
} },
Reverted: false,
if !status.Result.Equal(expectedResult) { },
t.Fatalf("wrong result. wanted %v, got %v", expectedResult, status.Result) UncashedAmount: big.NewInt(0),
} })
} }
func TestCashoutStatusReverted(t *testing.T) { func TestCashoutStatusReverted(t *testing.T) {
...@@ -263,10 +223,12 @@ func TestCashoutStatusReverted(t *testing.T) { ...@@ -263,10 +223,12 @@ func TestCashoutStatusReverted(t *testing.T) {
recipientAddress := common.HexToAddress("efff") recipientAddress := common.HexToAddress("efff")
txHash := common.HexToHash("dddd") txHash := common.HexToHash("dddd")
cumulativePayout := big.NewInt(500) cumulativePayout := big.NewInt(500)
onChainPaidOut := big.NewInt(100)
beneficiary := common.HexToAddress("aaaa")
cheque := &chequebook.SignedCheque{ cheque := &chequebook.SignedCheque{
Cheque: chequebook.Cheque{ Cheque: chequebook.Cheque{
Beneficiary: common.HexToAddress("aaaa"), Beneficiary: beneficiary,
CumulativePayout: cumulativePayout, CumulativePayout: cumulativePayout,
Chequebook: chequebookAddress, Chequebook: chequebookAddress,
}, },
...@@ -293,9 +255,8 @@ func TestCashoutStatusReverted(t *testing.T) { ...@@ -293,9 +255,8 @@ func TestCashoutStatusReverted(t *testing.T) {
}), }),
), ),
transactionmock.New( transactionmock.New(
transactionmock.WithSendFunc(func(ctx context.Context, request *transaction.TxRequest) (common.Hash, error) { transactionmock.WithABISend(&chequebookABI, txHash, chequebookAddress, big.NewInt(0), "cashChequeBeneficiary", recipientAddress, cheque.CumulativePayout, cheque.Signature),
return txHash, nil transactionmock.WithABICall(&chequebookABI, onChainPaidOut.FillBytes(make([]byte, 32)), "paidOut", beneficiary),
}),
), ),
chequestoremock.NewChequeStore( chequestoremock.NewChequeStore(
chequestoremock.WithLastChequeFunc(func(c common.Address) (*chequebook.SignedCheque, error) { chequestoremock.WithLastChequeFunc(func(c common.Address) (*chequebook.SignedCheque, error) {
...@@ -321,17 +282,14 @@ func TestCashoutStatusReverted(t *testing.T) { ...@@ -321,17 +282,14 @@ func TestCashoutStatusReverted(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if !status.Reverted { verifyStatus(t, status, chequebook.CashoutStatus{
t.Fatal("did not report failed transaction as reverted") Last: &chequebook.LastCashout{
} Reverted: true,
TxHash: txHash,
if status.TxHash != txHash { Cheque: *cheque,
t.Fatalf("wrong transaction hash. wanted %v, got %v", txHash, status.TxHash) },
} UncashedAmount: new(big.Int).Sub(cheque.CumulativePayout, onChainPaidOut),
})
if !status.Cheque.Equal(cheque) {
t.Fatalf("wrong cheque in status. wanted %v, got %v", cheque, status.Cheque)
}
} }
func TestCashoutStatusPending(t *testing.T) { func TestCashoutStatusPending(t *testing.T) {
...@@ -361,9 +319,7 @@ func TestCashoutStatusPending(t *testing.T) { ...@@ -361,9 +319,7 @@ func TestCashoutStatusPending(t *testing.T) {
}), }),
), ),
transactionmock.New( transactionmock.New(
transactionmock.WithSendFunc(func(c context.Context, request *transaction.TxRequest) (common.Hash, error) { transactionmock.WithABISend(&chequebookABI, txHash, chequebookAddress, big.NewInt(0), "cashChequeBeneficiary", recipientAddress, cheque.CumulativePayout, cheque.Signature),
return txHash, nil
}),
), ),
chequestoremock.NewChequeStore( chequestoremock.NewChequeStore(
chequestoremock.WithLastChequeFunc(func(c common.Address) (*chequebook.SignedCheque, error) { chequestoremock.WithLastChequeFunc(func(c common.Address) (*chequebook.SignedCheque, error) {
...@@ -389,19 +345,45 @@ func TestCashoutStatusPending(t *testing.T) { ...@@ -389,19 +345,45 @@ func TestCashoutStatusPending(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if status.Reverted { verifyStatus(t, status, chequebook.CashoutStatus{
t.Fatal("did report pending transaction as reverted") Last: &chequebook.LastCashout{
} Reverted: false,
TxHash: txHash,
Cheque: *cheque,
Result: nil,
},
UncashedAmount: big.NewInt(0),
})
}
if status.TxHash != txHash { func verifyStatus(t *testing.T, status *chequebook.CashoutStatus, expected chequebook.CashoutStatus) {
t.Fatalf("wrong transaction hash. wanted %v, got %v", txHash, status.TxHash) if expected.Last == nil {
if status.Last != nil {
t.Fatal("unexpected last cashout")
}
} else {
if status.Last == nil {
t.Fatal("no last cashout")
}
if status.Last.Reverted != expected.Last.Reverted {
t.Fatalf("wrong reverted value. wanted %v, got %v", expected.Last.Reverted, status.Last.Reverted)
}
if status.Last.TxHash != expected.Last.TxHash {
t.Fatalf("wrong transaction hash. wanted %v, got %v", expected.Last.TxHash, status.Last.TxHash)
}
if !status.Last.Cheque.Equal(&expected.Last.Cheque) {
t.Fatalf("wrong cheque in status. wanted %v, got %v", expected.Last.Cheque, status.Last.Cheque)
} }
if !status.Cheque.Equal(cheque) { if expected.Last.Result != nil {
t.Fatalf("wrong cheque in status. wanted %v, got %v", cheque, status.Cheque) if !expected.Last.Result.Equal(status.Last.Result) {
t.Fatalf("wrong result. wanted %v, got %v", expected.Last.Result, status.Last.Result)
}
}
} }
if status.Result != nil { if status.UncashedAmount.Cmp(expected.UncashedAmount) != 0 {
t.Fatalf("got result for pending cashout: %v", status.Result) t.Fatalf("wrong uncashed amount. wanted %d, got %d", expected.UncashedAmount, status.UncashedAmount)
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment