From 5a72e81695a986e91d448f7340af8dafb5db9f49 Mon Sep 17 00:00:00 2001 From: Ragot Geoffrey Date: Tue, 31 Jan 2023 17:51:35 +0100 Subject: [PATCH] fix: negative balances not allowed even with mapping defined (#425) * fix: negative balances not allowed even with mapping defined * fix: keep old error messages for backward compatibility --- .../transaction_controller_test.go | 65 ++++++++++++++++--- pkg/core/numscript.go | 2 +- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/pkg/api/controllers/transaction_controller_test.go b/pkg/api/controllers/transaction_controller_test.go index 9e04a1841..2e5b60c36 100644 --- a/pkg/api/controllers/transaction_controller_test.go +++ b/pkg/api/controllers/transaction_controller_test.go @@ -301,10 +301,9 @@ func TestPostTransactions(t *testing.T) { expectedStatusCode: http.StatusBadRequest, expectedErr: sharedapi.ErrorResponse{ ErrorCode: apierrors.ErrInsufficientFund, - ErrorMessage: "[INSUFFICIENT_FUND] account had insufficient funds", - Details: apierrors.EncodeLink("account had insufficient funds"), + ErrorMessage: "balance.insufficient.TOK", ErrorCodeDeprecated: apierrors.ErrInsufficientFund, - ErrorMessageDeprecated: "[INSUFFICIENT_FUND] account had insufficient funds", + ErrorMessageDeprecated: "balance.insufficient.TOK", }, }, { @@ -593,11 +592,61 @@ func TestPostTransactions(t *testing.T) { ErrorMessageDeprecated: "cannot pass a timestamp prior to the last transaction:", }, }, + { + name: "mapping with postings", + payload: []controllers.PostTransaction{ + { + Postings: core.Postings{ + { + Source: "negativebalances:bar", + Destination: "world", + Amount: core.NewMonetaryInt(1000), + Asset: "TOK", + }, + }, + Timestamp: timestamp3, + }, + }, + expectedStatusCode: http.StatusOK, + expectedRes: sharedapi.BaseResponse[[]core.ExpandedTransaction]{ + Data: &[]core.ExpandedTransaction{{ + Transaction: core.Transaction{ + TransactionData: core.TransactionData{ + Postings: core.Postings{ + { + Source: "negativebalances:bar", + Destination: "world", + Amount: core.NewMonetaryInt(1000), + Asset: "TOK", + }, + }, + Timestamp: timestamp3, + }, + }, + }}, + }, + }, } internal.RunTest(t, fx.Invoke(func(lc fx.Lifecycle, api *api.API) { lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { + internal.SaveMapping(t, api, core.Mapping{ + Contracts: []core.Contract{{ + Name: "negative balances", + Account: "negativebalances:*", + Expr: core.ExprOr{ + &core.ExprGte{ + Op1: core.VariableExpr{Name: "balance"}, + Op2: core.ConstantExpr{Value: 0}, + }, + &core.ExprLte{ + Op1: core.VariableExpr{Name: "balance"}, + Op2: core.ConstantExpr{Value: 0}, + }, + }, + }}, + }) for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { for i := 0; i < len(tc.payload)-1; i++ { @@ -2003,10 +2052,9 @@ func TestPostTransactionsBatch(t *testing.T) { internal.Decode(t, rsp.Body, &err) require.EqualValues(t, sharedapi.ErrorResponse{ ErrorCode: apierrors.ErrInsufficientFund, - ErrorMessage: "[INSUFFICIENT_FUND] account had insufficient funds", - Details: apierrors.EncodeLink("account had insufficient funds"), + ErrorMessage: "balance.insufficient.COIN", ErrorCodeDeprecated: apierrors.ErrInsufficientFund, - ErrorMessageDeprecated: "[INSUFFICIENT_FUND] account had insufficient funds", + ErrorMessageDeprecated: "balance.insufficient.COIN", }, err) }) @@ -2053,10 +2101,9 @@ func TestPostTransactionsBatch(t *testing.T) { internal.Decode(t, rsp.Body, &err) require.EqualValues(t, sharedapi.ErrorResponse{ ErrorCode: apierrors.ErrInsufficientFund, - ErrorMessage: "[INSUFFICIENT_FUND] account had insufficient funds", - Details: apierrors.EncodeLink("account had insufficient funds"), + ErrorMessage: "balance.insufficient.GEM", ErrorCodeDeprecated: apierrors.ErrInsufficientFund, - ErrorMessageDeprecated: "[INSUFFICIENT_FUND] account had insufficient funds", + ErrorMessageDeprecated: "balance.insufficient.GEM", }, err) }) diff --git a/pkg/core/numscript.go b/pkg/core/numscript.go index 1a422d567..d59a6f64f 100644 --- a/pkg/core/numscript.go +++ b/pkg/core/numscript.go @@ -83,7 +83,7 @@ func TxsToScriptsData(txsData ...TransactionData) []ScriptData { if !ok { panic(fmt.Sprintf("source %s not found", p.Source)) } - sb.WriteString(fmt.Sprintf("\tsource = $%s\n", src.name)) + sb.WriteString(fmt.Sprintf("\tsource = $%s allowing unbounded overdraft\n", src.name)) } if p.Destination == WORLD { sb.WriteString("\tdestination = @world\n")