Skip to content

Commit

Permalink
feat(ledger): add capability to revert tx at effective date of origin…
Browse files Browse the repository at this point in the history
…al tx (#1374)
  • Loading branch information
gfyrag committed Apr 4, 2024
1 parent ef0e9ec commit 218d7ee
Show file tree
Hide file tree
Showing 37 changed files with 751 additions and 145 deletions.
2 changes: 1 addition & 1 deletion components/fctl/cmd/ledger/accounts/show.go
Expand Up @@ -95,5 +95,5 @@ func (c *ShowController) Render(cmd *cobra.Command, args []string) error {
fmt.Fprintln(cmd.OutOrStdout())

return fctl.PrintMetadata(cmd.OutOrStdout(),
collectionutils.ConvertMap(c.store.Account.Metadata, collectionutils.ToFmtString[string]))
collectionutils.ConvertMap(c.store.Account.Metadata, collectionutils.ToFmtString))
}
92 changes: 75 additions & 17 deletions components/fctl/cmd/ledger/internal/print.go
Expand Up @@ -39,7 +39,7 @@ func printCommonInformation(
tableData = append(tableData, []string{"Source", "Destination", "Asset", "Amount"})
for _, posting := range postings {
tableData = append(tableData, []string{
posting.Source, posting.Destination, posting.Asset, fmt.Sprint(posting.Amount),
posting.GetSource(), posting.GetDestination(), posting.GetAsset(), posting.GetAmount().String(),
})
}

Expand All @@ -55,30 +55,30 @@ func printCommonInformation(
return nil
}

func PrintExpandedTransaction(out io.Writer, transaction shared.Transaction) error {
func PrintExpandedTransaction(out io.Writer, transaction ExpandedTransaction) error {

if err := printCommonInformation(
out,
transaction.Txid,
transaction.GetID(),
func() string {
if transaction.Reference == nil {
if transaction.GetReference() == nil {
return ""
}
return *transaction.Reference
return *transaction.GetReference()
}(),
transaction.Postings,
transaction.Timestamp,
transaction.GetPostings(),
transaction.GetTimestamp(),
); err != nil {
return err
}

fctl.Section.WithWriter(out).Println("Summary")
tableData := pterm.TableData{}
tableData = append(tableData, []string{"Account", "Asset", "Movement", "Final balance"})
for account, postCommitVolume := range transaction.PostCommitVolumes {
for account, postCommitVolume := range transaction.GetPostCommitVolumes() {
for asset, volumes := range postCommitVolume {
movement := big.NewInt(0)
movement = movement.Sub(volumes.Balance, (transaction.PreCommitVolumes)[account][asset].Balance)
movement = movement.Sub(volumes.Balance, (transaction.GetPreCommitVolumes())[account][asset].Balance)
movementStr := fmt.Sprint(movement)
if movement.Cmp(big.NewInt(0)) > 0 {
movementStr = "+" + movementStr
Expand All @@ -97,29 +97,87 @@ func PrintExpandedTransaction(out io.Writer, transaction shared.Transaction) err
}

fmt.Fprintln(out, "")
if err := PrintMetadata(out, collectionutils.ConvertMap(transaction.Metadata, collectionutils.ToFmtString[any])); err != nil {
if err := PrintMetadata(out, transaction.GetMetadata()); err != nil {
return err
}
return nil
}

func PrintTransaction(out io.Writer, transaction shared.Transaction) error {
type Transaction interface {
GetReference() *string
GetID() *big.Int
GetPostings() []shared.Posting
GetTimestamp() time.Time
GetMetadata() map[string]string
}

type v2Transaction struct {
shared.V2Transaction
}

func (t v2Transaction) GetPostings() []shared.Posting {
return collectionutils.Map(t.V2Transaction.GetPostings(), func(from shared.V2Posting) shared.Posting {
return shared.Posting{
Amount: from.GetAmount(),
Asset: from.GetAsset(),
Destination: from.GetDestination(),
Source: from.GetSource(),
}
})
}

var _ Transaction = (*v2Transaction)(nil)

func WrapV2Transaction(transaction shared.V2Transaction) *v2Transaction {
return &v2Transaction{
V2Transaction: transaction,
}
}

type v1Transaction struct {
shared.Transaction
}

func (t v1Transaction) GetID() *big.Int {
return t.Transaction.GetTxid()
}

func (t v1Transaction) GetMetadata() map[string]string {
return collectionutils.ConvertMap(t.Transaction.Metadata, collectionutils.ToFmtString)
}

var _ Transaction = (*v1Transaction)(nil)

func WrapV1Transaction(transaction shared.Transaction) *v1Transaction {
return &v1Transaction{
Transaction: transaction,
}
}

type ExpandedTransaction interface {
Transaction
GetPreCommitVolumes() map[string]map[string]shared.Volume
GetPostCommitVolumes() map[string]map[string]shared.Volume
}

func PrintTransaction(out io.Writer, transaction Transaction) error {

reference := ""
if transaction.Reference != nil {
reference = *transaction.Reference
if transaction.GetReference() != nil {
reference = *transaction.GetReference()
}
if err := printCommonInformation(
out,
transaction.Txid,
transaction.GetID(),
reference,
transaction.Postings,
transaction.Timestamp,
transaction.GetPostings(),
transaction.GetTimestamp(),
); err != nil {
return err
}

if err := PrintMetadata(out, collectionutils.ConvertMap(transaction.Metadata, collectionutils.ToFmtString[string])); err != nil {
// collectionutils.ConvertMap(transaction.Metadata, collectionutils.ToFmtString[string])
if err := PrintMetadata(out, transaction.GetMetadata()); err != nil {
return err
}
return nil
Expand Down
2 changes: 1 addition & 1 deletion components/fctl/cmd/ledger/send.go
Expand Up @@ -118,5 +118,5 @@ func (c *SendController) Run(cmd *cobra.Command, args []string) (fctl.Renderable

// TODO: This need to use the ui.NewListModel
func (c *SendController) Render(cmd *cobra.Command, args []string) error {
return internal.PrintTransaction(cmd.OutOrStdout(), *c.store.Transaction)
return internal.PrintTransaction(cmd.OutOrStdout(), internal.WrapV1Transaction(*c.store.Transaction))
}
2 changes: 1 addition & 1 deletion components/fctl/cmd/ledger/transactions/num.go
Expand Up @@ -173,5 +173,5 @@ func (c *NumController) Run(cmd *cobra.Command, args []string) (fctl.Renderable,
}

func (c *NumController) Render(cmd *cobra.Command, args []string) error {
return internal.PrintTransaction(cmd.OutOrStdout(), *c.store.Transaction)
return internal.PrintTransaction(cmd.OutOrStdout(), internal.WrapV1Transaction(*c.store.Transaction))
}
61 changes: 44 additions & 17 deletions components/fctl/cmd/ledger/transactions/revert.go
Expand Up @@ -3,15 +3,16 @@ package transactions
import (
"fmt"

"github.com/formancehq/stack/libs/go-libs/pointer"

"github.com/formancehq/fctl/cmd/ledger/internal"
fctl "github.com/formancehq/fctl/pkg"
"github.com/formancehq/formance-sdk-go/v2/pkg/models/operations"
"github.com/formancehq/formance-sdk-go/v2/pkg/models/shared"
"github.com/spf13/cobra"
)

type RevertStore struct {
Transaction *shared.Transaction `json:"transaction"`
Transaction internal.Transaction `json:"transaction"`
}
type RevertController struct {
store *RevertStore
Expand All @@ -35,6 +36,7 @@ func NewRevertCommand() *cobra.Command {
fctl.WithShortDescription("Revert a transaction"),
fctl.WithArgs(cobra.ExactArgs(1)),
fctl.WithValidArgs("last"),
fctl.WithBoolFlag("at-effective-date", false, "set the timestamp to the original transaction timestamp"),
fctl.WithController[*RevertStore](NewRevertController()),
)
}
Expand All @@ -56,25 +58,50 @@ func (c *RevertController) Run(cmd *cobra.Command, args []string) (fctl.Renderab
return nil, err
}

request := operations.RevertTransactionRequest{
Ledger: ledger,
Txid: txId,
}

response, err := store.Client().Ledger.RevertTransaction(cmd.Context(), request)
if response.ErrorResponse != nil {
return nil, fmt.Errorf("%s: %s", response.ErrorResponse.ErrorCode, response.ErrorResponse.ErrorMessage)
if fctl.GetBool(cmd, "at-effective-date") {
request := operations.V2RevertTransactionRequest{
Ledger: ledger,
ID: txId,
AtEffectiveDate: pointer.For(true),
}

response, err := store.Client().Ledger.V2RevertTransaction(cmd.Context(), request)
if err != nil {
return nil, err
}
if response.V2ErrorResponse != nil {
return nil, fmt.Errorf("%s: %s", response.V2ErrorResponse.ErrorCode, response.V2ErrorResponse.ErrorMessage)
}

if response.StatusCode >= 300 {
return nil, fmt.Errorf("unexpected status code: %d", response.StatusCode)
}

c.store.Transaction = internal.WrapV2Transaction(response.V2RevertTransactionResponse.Data)
} else {
request := operations.RevertTransactionRequest{
Ledger: ledger,
Txid: txId,
}

response, err := store.Client().Ledger.RevertTransaction(cmd.Context(), request)
if err != nil {
return nil, err
}
if response.ErrorResponse != nil {
return nil, fmt.Errorf("%s: %s", response.ErrorResponse.ErrorCode, response.ErrorResponse.ErrorMessage)
}

if response.StatusCode >= 300 {
return nil, fmt.Errorf("unexpected status code: %d", response.StatusCode)
}

c.store.Transaction = internal.WrapV1Transaction(response.TransactionResponse.Data)
}

if response.StatusCode >= 300 {
return nil, fmt.Errorf("unexpected status code: %d", response.StatusCode)
}

c.store.Transaction = &response.TransactionResponse.Data

return c, nil
}

func (c *RevertController) Render(cmd *cobra.Command, args []string) error {
return internal.PrintTransaction(cmd.OutOrStdout(), *c.store.Transaction)
return internal.PrintTransaction(cmd.OutOrStdout(), c.store.Transaction)
}
2 changes: 1 addition & 1 deletion components/fctl/cmd/ledger/transactions/show.go
Expand Up @@ -74,5 +74,5 @@ func (c *ShowController) Run(cmd *cobra.Command, args []string) (fctl.Renderable
}

func (c *ShowController) Render(cmd *cobra.Command, args []string) error {
return internal.PrintExpandedTransaction(cmd.OutOrStdout(), c.store.Transaction)
return internal.PrintExpandedTransaction(cmd.OutOrStdout(), internal.WrapV1Transaction(c.store.Transaction))
}

0 comments on commit 218d7ee

Please sign in to comment.