Skip to content

Commit b5dd7c3

Browse files
committed
fix(ledger) tx reversion handles empty middle accounts
1 parent a929bff commit b5dd7c3

File tree

2 files changed

+96
-2
lines changed

2 files changed

+96
-2
lines changed

internal/controller/ledger/controller_default.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,13 @@ func (ctrl *DefaultController) revertTransaction(ctx context.Context, store Stor
406406
balances[posting.Source][posting.Asset],
407407
big.NewInt(0).Neg(posting.Amount),
408408
)
409+
if _, ok := balances[posting.Destination]; ok {
410+
// if destination is also a source in some posting, since balances should only contain posting sources
411+
balances[posting.Destination][posting.Asset] = balances[posting.Destination][posting.Asset].Add(
412+
balances[posting.Destination][posting.Asset],
413+
posting.Amount,
414+
)
415+
}
409416
}
410417

411418
for account, forAccount := range balances {

test/e2e/api_transactions_revert_test.go

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
package test_suite
44

55
import (
6+
"math/big"
7+
"time"
8+
69
"github.com/formancehq/go-libs/v2/logging"
710
. "github.com/formancehq/go-libs/v2/testing/api"
811
"github.com/formancehq/ledger/pkg/client/models/components"
912
"github.com/formancehq/ledger/pkg/client/models/operations"
1013
. "github.com/formancehq/ledger/pkg/testserver"
11-
"math/big"
12-
"time"
1314

1415
"github.com/formancehq/go-libs/v2/pointer"
1516
"github.com/nats-io/nats.go"
@@ -219,4 +220,90 @@ var _ = Context("Ledger revert transactions API tests", func() {
219220
})
220221
})
221222
})
223+
When("creating a transaction through an empty passthrough account", func() {
224+
var (
225+
timestamp = time.Now().Round(time.Second).UTC()
226+
tx *components.V2Transaction
227+
err error
228+
)
229+
BeforeEach(func() {
230+
tx, err = CreateTransaction(
231+
ctx,
232+
testServer.GetValue(),
233+
operations.V2CreateTransactionRequest{
234+
V2PostTransaction: components.V2PostTransaction{
235+
Metadata: map[string]string{},
236+
Postings: []components.V2Posting{
237+
{
238+
Amount: big.NewInt(100),
239+
Asset: "USD",
240+
Source: "world",
241+
Destination: "walter",
242+
},
243+
},
244+
Timestamp: &timestamp,
245+
},
246+
Ledger: "default",
247+
},
248+
)
249+
Expect(err).ToNot(HaveOccurred())
250+
})
251+
When("creating the pass-through transaction", func() {
252+
BeforeEach(func() {
253+
tx, err = CreateTransaction(
254+
ctx,
255+
testServer.GetValue(),
256+
operations.V2CreateTransactionRequest{
257+
V2PostTransaction: components.V2PostTransaction{
258+
Metadata: map[string]string{},
259+
Postings: []components.V2Posting{
260+
{
261+
Amount: big.NewInt(10),
262+
Asset: "USD",
263+
Source: "walter",
264+
Destination: "wendy",
265+
},
266+
{
267+
Amount: big.NewInt(10),
268+
Asset: "USD",
269+
Source: "wendy",
270+
Destination: "world",
271+
},
272+
},
273+
Timestamp: &timestamp,
274+
},
275+
Ledger: "default",
276+
},
277+
)
278+
Expect(err).ToNot(HaveOccurred())
279+
})
280+
When("reverting the pass-through transaction", func() {
281+
BeforeEach(func() {
282+
_, err := RevertTransaction(
283+
ctx,
284+
testServer.GetValue(),
285+
operations.V2RevertTransactionRequest{
286+
Ledger: "default",
287+
ID: tx.ID,
288+
AtEffectiveDate: pointer.For(true),
289+
},
290+
)
291+
Expect(err).To(Succeed())
292+
})
293+
It("should revert the passthrough transaction at date of the original tx", func() {
294+
response, err := GetTransaction(
295+
ctx,
296+
testServer.GetValue(),
297+
operations.V2GetTransactionRequest{
298+
Ledger: "default",
299+
ID: tx.ID,
300+
},
301+
)
302+
Expect(err).NotTo(HaveOccurred())
303+
Expect(response.Reverted).To(BeTrue())
304+
Expect(response.Timestamp).To(Equal(tx.Timestamp))
305+
})
306+
})
307+
})
308+
})
222309
})

0 commit comments

Comments
 (0)