Skip to content

Commit

Permalink
fix(ledger) tx reversion handles empty middle accounts (formancehq#711)
Browse files Browse the repository at this point in the history
  • Loading branch information
CrosleyZack committed Feb 26, 2025
1 parent 56b70f9 commit deaed10
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 2 deletions.
7 changes: 7 additions & 0 deletions internal/controller/ledger/controller_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,13 @@ func (ctrl *DefaultController) revertTransaction(ctx context.Context, store Stor
balances[posting.Source][posting.Asset],
big.NewInt(0).Neg(posting.Amount),
)
if _, ok := balances[posting.Destination]; ok {
// if destination is also a source in some posting, since balances should only contain posting sources
balances[posting.Destination][posting.Asset] = balances[posting.Destination][posting.Asset].Add(
balances[posting.Destination][posting.Asset],
posting.Amount,
)
}
}

for account, forAccount := range balances {
Expand Down
91 changes: 89 additions & 2 deletions test/e2e/api_transactions_revert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
package test_suite

import (
"math/big"
"time"

"github.com/formancehq/go-libs/v2/logging"
. "github.com/formancehq/go-libs/v2/testing/api"
"github.com/formancehq/ledger/pkg/client/models/components"
"github.com/formancehq/ledger/pkg/client/models/operations"
. "github.com/formancehq/ledger/pkg/testserver"
"math/big"
"time"

"github.com/formancehq/go-libs/v2/pointer"
"github.com/nats-io/nats.go"
Expand Down Expand Up @@ -217,4 +218,90 @@ var _ = Context("Ledger revert transactions API tests", func() {
})
})
})
When("creating a transaction through an empty passthrough account", func() {
var (
timestamp = time.Now().Round(time.Second).UTC()
tx *components.V2Transaction
err error
)
BeforeEach(func() {
tx, err = CreateTransaction(
ctx,
testServer.GetValue(),
operations.V2CreateTransactionRequest{
V2PostTransaction: components.V2PostTransaction{
Metadata: map[string]string{},
Postings: []components.V2Posting{
{
Amount: big.NewInt(100),
Asset: "USD",
Source: "world",
Destination: "walter",
},
},
Timestamp: &timestamp,
},
Ledger: "default",
},
)
Expect(err).ToNot(HaveOccurred())
})
When("creating the pass-through transaction", func() {
BeforeEach(func() {
tx, err = CreateTransaction(
ctx,
testServer.GetValue(),
operations.V2CreateTransactionRequest{
V2PostTransaction: components.V2PostTransaction{
Metadata: map[string]string{},
Postings: []components.V2Posting{
{
Amount: big.NewInt(10),
Asset: "USD",
Source: "walter",
Destination: "wendy",
},
{
Amount: big.NewInt(10),
Asset: "USD",
Source: "wendy",
Destination: "world",
},
},
Timestamp: &timestamp,
},
Ledger: "default",
},
)
Expect(err).ToNot(HaveOccurred())
})
When("reverting the pass-through transaction", func() {
BeforeEach(func() {
_, err := RevertTransaction(
ctx,
testServer.GetValue(),
operations.V2RevertTransactionRequest{
Ledger: "default",
ID: tx.ID,
AtEffectiveDate: pointer.For(true),
},
)
Expect(err).To(Succeed())
})
It("should revert the passthrough transaction at date of the original tx", func() {
response, err := GetTransaction(
ctx,
testServer.GetValue(),
operations.V2GetTransactionRequest{
Ledger: "default",
ID: tx.ID,
},
)
Expect(err).NotTo(HaveOccurred())
Expect(response.Reverted).To(BeTrue())
Expect(response.Timestamp).To(Equal(tx.Timestamp))
})
})
})
})
})

0 comments on commit deaed10

Please sign in to comment.