diff --git a/components/fctl/cmd/payments/accounts/balances.go b/components/fctl/cmd/payments/accounts/balances.go new file mode 100644 index 0000000000..a2291d0b5c --- /dev/null +++ b/components/fctl/cmd/payments/accounts/balances.go @@ -0,0 +1,105 @@ +package accounts + +import ( + "fmt" + "time" + + fctl "github.com/formancehq/fctl/pkg" + "github.com/formancehq/formance-sdk-go/pkg/models/operations" + "github.com/formancehq/formance-sdk-go/pkg/models/shared" + "github.com/pterm/pterm" + "github.com/spf13/cobra" +) + +type ListBalancesStore struct { + Cursor *shared.BalancesCursorCursor `json:"cursor"` +} + +type ListBalancesController struct { + store *ListBalancesStore +} + +var _ fctl.Controller[*ListBalancesStore] = (*ListBalancesController)(nil) + +func NewListBalanceStore() *ListBalancesStore { + return &ListBalancesStore{ + Cursor: &shared.BalancesCursorCursor{}, + } +} + +func NewListBalancesController() *ListBalancesController { + return &ListBalancesController{ + store: NewListBalanceStore(), + } +} + +func (c *ListBalancesController) GetStore() *ListBalancesStore { + return c.store +} + +func (c *ListBalancesController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { + cfg, err := fctl.GetConfig(cmd) + if err != nil { + return nil, err + } + + organizationID, err := fctl.ResolveOrganizationID(cmd, cfg) + if err != nil { + return nil, err + } + + stack, err := fctl.ResolveStack(cmd, cfg, organizationID) + if err != nil { + return nil, err + } + + client, err := fctl.NewStackClient(cmd, cfg, stack) + if err != nil { + return nil, err + } + + response, err := client.Payments.GetAccountBalances( + cmd.Context(), + operations.GetAccountBalancesRequest{ + AccountID: args[0], + }, + ) + if err != nil { + return nil, err + } + + if response.StatusCode >= 300 { + return nil, fmt.Errorf("unexpected status code: %d", response.StatusCode) + } + + c.store.Cursor = &response.BalancesCursor.Cursor + + return c, nil +} + +func (c *ListBalancesController) Render(cmd *cobra.Command, args []string) error { + tableData := fctl.Map(c.store.Cursor.Data, func(balance shared.AccountBalance) []string { + return []string{ + balance.AccountID, + balance.Asset, + balance.Balance.String(), + balance.CreatedAt.Format(time.RFC3339), + balance.LastUpdatedAt.Format(time.RFC3339), + } + }) + tableData = fctl.Prepend(tableData, []string{"ID", "Asset", "Balance", + "CreatedAt", "LastUpdatedAt"}) + return pterm.DefaultTable. + WithHasHeader(). + WithWriter(cmd.OutOrStdout()). + WithData(tableData). + Render() +} + +func NewListBalanceCommand() *cobra.Command { + return fctl.NewCommand("balances ", + fctl.WithArgs(cobra.ExactArgs(1)), + fctl.WithShortDescription("List accounts balances"), + fctl.WithController[*ListBalancesStore](NewListBalancesController()), + ) +} diff --git a/components/fctl/cmd/payments/accounts/list.go b/components/fctl/cmd/payments/accounts/list.go new file mode 100644 index 0000000000..2ca391e427 --- /dev/null +++ b/components/fctl/cmd/payments/accounts/list.go @@ -0,0 +1,107 @@ +package accounts + +import ( + "fmt" + "time" + + fctl "github.com/formancehq/fctl/pkg" + "github.com/formancehq/formance-sdk-go/pkg/models/operations" + "github.com/formancehq/formance-sdk-go/pkg/models/shared" + "github.com/pterm/pterm" + "github.com/spf13/cobra" +) + +type ListStore struct { + Cursor *shared.AccountsCursorCursor `json:"cursor"` +} + +type ListController struct { + store *ListStore +} + +var _ fctl.Controller[*ListStore] = (*ListController)(nil) + +func NewListStore() *ListStore { + return &ListStore{ + Cursor: &shared.AccountsCursorCursor{}, + } +} + +func NewListController() *ListController { + return &ListController{ + store: NewListStore(), + } +} + +func (c *ListController) GetStore() *ListStore { + return c.store +} + +func (c *ListController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { + cfg, err := fctl.GetConfig(cmd) + if err != nil { + return nil, err + } + + organizationID, err := fctl.ResolveOrganizationID(cmd, cfg) + if err != nil { + return nil, err + } + + stack, err := fctl.ResolveStack(cmd, cfg, organizationID) + if err != nil { + return nil, err + } + + client, err := fctl.NewStackClient(cmd, cfg, stack) + if err != nil { + return nil, err + } + + response, err := client.Payments.PaymentslistAccounts( + cmd.Context(), + operations.PaymentslistAccountsRequest{}, + ) + if err != nil { + return nil, err + } + + if response.StatusCode >= 300 { + return nil, fmt.Errorf("unexpected status code: %d", response.StatusCode) + } + + c.store.Cursor = &response.AccountsCursor.Cursor + + return c, nil +} + +func (c *ListController) Render(cmd *cobra.Command, args []string) error { + tableData := fctl.Map(c.store.Cursor.Data, func(acc shared.PaymentsAccount) []string { + return []string{ + acc.ID, + acc.AccountName, + acc.CreatedAt.Format(time.RFC3339), + string(acc.Provider), + acc.DefaultAsset, + acc.DefaultCurrency, + acc.Reference, + acc.Type, + } + }) + tableData = fctl.Prepend(tableData, []string{"ID", "AccountName", "CreatedAt", + "Provider", "DefaultAsset", "DefaultCurrency", "Reference", "Type"}) + return pterm.DefaultTable. + WithHasHeader(). + WithWriter(cmd.OutOrStdout()). + WithData(tableData). + Render() +} + +func NewListCommand() *cobra.Command { + return fctl.NewCommand("list", + fctl.WithAliases("ls", "l"), + fctl.WithArgs(cobra.ExactArgs(0)), + fctl.WithShortDescription("List connector accounts"), + fctl.WithController[*ListStore](NewListController()), + ) +} diff --git a/components/fctl/cmd/payments/accounts/root.go b/components/fctl/cmd/payments/accounts/root.go new file mode 100644 index 0000000000..f3aaf4fe4e --- /dev/null +++ b/components/fctl/cmd/payments/accounts/root.go @@ -0,0 +1,18 @@ +package accounts + +import ( + fctl "github.com/formancehq/fctl/pkg" + "github.com/spf13/cobra" +) + +func NewAccountsCommand() *cobra.Command { + return fctl.NewCommand("accounts", + fctl.WithAliases("acc", "a", "ac", "account"), + fctl.WithShortDescription("Accounts management"), + fctl.WithChildCommands( + NewListCommand(), + NewShowCommand(), + NewListBalanceCommand(), + ), + ) +} diff --git a/components/fctl/cmd/payments/accounts/show.go b/components/fctl/cmd/payments/accounts/show.go new file mode 100644 index 0000000000..4c1c4ad098 --- /dev/null +++ b/components/fctl/cmd/payments/accounts/show.go @@ -0,0 +1,103 @@ +package accounts + +import ( + "fmt" + "time" + + fctl "github.com/formancehq/fctl/pkg" + "github.com/formancehq/formance-sdk-go/pkg/models/operations" + "github.com/formancehq/formance-sdk-go/pkg/models/shared" + "github.com/pterm/pterm" + "github.com/spf13/cobra" +) + +type ShowStore struct { + Account *shared.PaymentsAccount `json:"account"` +} +type ShowController struct { + store *ShowStore +} + +var _ fctl.Controller[*ShowStore] = (*ShowController)(nil) + +func NewShowStore() *ShowStore { + return &ShowStore{} +} + +func NewShowController() *ShowController { + return &ShowController{ + store: NewShowStore(), + } +} + +func NewShowCommand() *cobra.Command { + return fctl.NewCommand("get ", + fctl.WithShortDescription("Get account"), + fctl.WithArgs(cobra.ExactArgs(1)), + fctl.WithAliases("sh", "s"), + fctl.WithController[*ShowStore](NewShowController()), + ) +} + +func (c *ShowController) GetStore() *ShowStore { + return c.store +} + +func (c *ShowController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { + cfg, err := fctl.GetConfig(cmd) + if err != nil { + return nil, err + } + + organizationID, err := fctl.ResolveOrganizationID(cmd, cfg) + if err != nil { + return nil, err + } + + stack, err := fctl.ResolveStack(cmd, cfg, organizationID) + if err != nil { + return nil, err + } + + ledgerClient, err := fctl.NewStackClient(cmd, cfg, stack) + if err != nil { + return nil, err + } + + response, err := ledgerClient.Payments.PaymentsgetAccount(cmd.Context(), operations.PaymentsgetAccountRequest{ + AccountID: args[0], + }) + if err != nil { + return nil, err + } + + if response.StatusCode >= 300 { + return nil, fmt.Errorf("unexpected status code: %d", response.StatusCode) + } + + c.store.Account = &response.PaymentsAccountResponse.Data + + return c, nil +} + +func (c *ShowController) Render(cmd *cobra.Command, args []string) error { + fctl.Section.WithWriter(cmd.OutOrStdout()).Println("Information") + tableData := pterm.TableData{} + tableData = append(tableData, []string{pterm.LightCyan("ID"), c.store.Account.ID}) + tableData = append(tableData, []string{pterm.LightCyan("AccountName"), c.store.Account.AccountName}) + tableData = append(tableData, []string{pterm.LightCyan("CreatedAt"), c.store.Account.CreatedAt.Format(time.RFC3339)}) + tableData = append(tableData, []string{pterm.LightCyan("Provider"), string(c.store.Account.Provider)}) + tableData = append(tableData, []string{pterm.LightCyan("DefaultAsset"), c.store.Account.DefaultAsset}) + tableData = append(tableData, []string{pterm.LightCyan("DefaultCurrency"), c.store.Account.DefaultCurrency}) + tableData = append(tableData, []string{pterm.LightCyan("Reference"), c.store.Account.Reference}) + tableData = append(tableData, []string{pterm.LightCyan("Type"), c.store.Account.Type}) + + if err := pterm.DefaultTable. + WithWriter(cmd.OutOrStdout()). + WithData(tableData). + Render(); err != nil { + return err + } + + return nil +} diff --git a/components/fctl/cmd/payments/bankaccounts/create.go b/components/fctl/cmd/payments/bankaccounts/create.go new file mode 100644 index 0000000000..832d4c0389 --- /dev/null +++ b/components/fctl/cmd/payments/bankaccounts/create.go @@ -0,0 +1,85 @@ +package bankaccounts + +import ( + "encoding/json" + "fmt" + + fctl "github.com/formancehq/fctl/pkg" + "github.com/formancehq/formance-sdk-go/pkg/models/shared" + "github.com/pkg/errors" + "github.com/pterm/pterm" + "github.com/spf13/cobra" +) + +type CreateStore struct { + BankAccountID string `json:"bankAccountId"` +} +type CreateController struct { + store *CreateStore +} + +var _ fctl.Controller[*CreateStore] = (*CreateController)(nil) + +func NewCreateStore() *CreateStore { + return &CreateStore{} +} + +func NewCreateController() *CreateController { + return &CreateController{ + store: NewCreateStore(), + } +} + +func NewCreateCommand() *cobra.Command { + return fctl.NewCommand("create |-", + fctl.WithShortDescription("Create a bank account"), + fctl.WithAliases("cr", "c"), + fctl.WithArgs(cobra.ExactArgs(1)), + fctl.WithController[*CreateStore](NewCreateController()), + ) +} + +func (c *CreateController) GetStore() *CreateStore { + return c.store +} + +func (c *CreateController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { + soc, err := fctl.GetStackOrganizationConfig(cmd) + if err != nil { + return nil, err + } + client, err := fctl.NewStackClient(cmd, soc.Config, soc.Stack) + if err != nil { + return nil, errors.Wrap(err, "creating stack client") + } + + script, err := fctl.ReadFile(cmd, soc.Stack, args[0]) + if err != nil { + return nil, err + } + + request := shared.BankAccountRequest{} + if err := json.Unmarshal([]byte(script), &request); err != nil { + return nil, err + } + + //nolint:gosimple + response, err := client.Payments.CreateBankAccount(cmd.Context(), request) + if err != nil { + return nil, err + } + + if response.StatusCode >= 300 { + return nil, fmt.Errorf("unexpected status code: %d", response.StatusCode) + } + + c.store.BankAccountID = response.BankAccountResponse.Data.ID + + return c, nil +} + +func (c *CreateController) Render(cmd *cobra.Command, args []string) error { + pterm.Success.WithWriter(cmd.OutOrStdout()).Printfln("Bank Accounts created with ID: %s", c.store.BankAccountID) + + return nil +} diff --git a/components/fctl/cmd/payments/bankaccounts/list.go b/components/fctl/cmd/payments/bankaccounts/list.go new file mode 100644 index 0000000000..8daaba5cf0 --- /dev/null +++ b/components/fctl/cmd/payments/bankaccounts/list.go @@ -0,0 +1,102 @@ +package bankaccounts + +import ( + "fmt" + "time" + + fctl "github.com/formancehq/fctl/pkg" + "github.com/formancehq/formance-sdk-go/pkg/models/operations" + "github.com/formancehq/formance-sdk-go/pkg/models/shared" + "github.com/pterm/pterm" + "github.com/spf13/cobra" +) + +type ListStore struct { + Cursor *shared.BankAccountsCursorCursor `json:"cursor"` +} + +type ListController struct { + store *ListStore +} + +var _ fctl.Controller[*ListStore] = (*ListController)(nil) + +func NewListStore() *ListStore { + return &ListStore{ + Cursor: &shared.BankAccountsCursorCursor{}, + } +} + +func NewListController() *ListController { + return &ListController{ + store: NewListStore(), + } +} + +func (c *ListController) GetStore() *ListStore { + return c.store +} + +func (c *ListController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { + cfg, err := fctl.GetConfig(cmd) + if err != nil { + return nil, err + } + + organizationID, err := fctl.ResolveOrganizationID(cmd, cfg) + if err != nil { + return nil, err + } + + stack, err := fctl.ResolveStack(cmd, cfg, organizationID) + if err != nil { + return nil, err + } + + client, err := fctl.NewStackClient(cmd, cfg, stack) + if err != nil { + return nil, err + } + + response, err := client.Payments.ListBankAccounts( + cmd.Context(), + operations.ListBankAccountsRequest{}, + ) + if err != nil { + return nil, err + } + + if response.StatusCode >= 300 { + return nil, fmt.Errorf("unexpected status code: %d", response.StatusCode) + } + + c.store.Cursor = &response.BankAccountsCursor.Cursor + + return c, nil +} + +func (c *ListController) Render(cmd *cobra.Command, args []string) error { + tableData := fctl.Map(c.store.Cursor.Data, func(bc shared.BankAccount) []string { + return []string{ + bc.ID, + bc.CreatedAt.Format(time.RFC3339), + bc.Country, + string(bc.Provider), + } + }) + tableData = fctl.Prepend(tableData, []string{"ID", "CreatedAt", "Country", "Provider"}) + return pterm.DefaultTable. + WithHasHeader(). + WithWriter(cmd.OutOrStdout()). + WithData(tableData). + Render() +} + +func NewListCommand() *cobra.Command { + return fctl.NewCommand("list", + fctl.WithAliases("ls", "l"), + fctl.WithArgs(cobra.ExactArgs(0)), + fctl.WithShortDescription("List bank accounts"), + fctl.WithController[*ListStore](NewListController()), + ) +} diff --git a/components/fctl/cmd/payments/bankaccounts/root.go b/components/fctl/cmd/payments/bankaccounts/root.go new file mode 100644 index 0000000000..96fb4e007e --- /dev/null +++ b/components/fctl/cmd/payments/bankaccounts/root.go @@ -0,0 +1,18 @@ +package bankaccounts + +import ( + fctl "github.com/formancehq/fctl/pkg" + "github.com/spf13/cobra" +) + +func NewBankAccountsCommand() *cobra.Command { + return fctl.NewCommand("bank_accounts", + fctl.WithAliases("bacc", "ba", "bac", "baccount"), + fctl.WithShortDescription("Bank Accounts management"), + fctl.WithChildCommands( + NewCreateCommand(), + NewShowCommand(), + NewListCommand(), + ), + ) +} diff --git a/components/fctl/cmd/payments/bankaccounts/show.go b/components/fctl/cmd/payments/bankaccounts/show.go new file mode 100644 index 0000000000..88bc7e8c5d --- /dev/null +++ b/components/fctl/cmd/payments/bankaccounts/show.go @@ -0,0 +1,99 @@ +package bankaccounts + +import ( + "fmt" + "time" + + fctl "github.com/formancehq/fctl/pkg" + "github.com/formancehq/formance-sdk-go/pkg/models/operations" + "github.com/formancehq/formance-sdk-go/pkg/models/shared" + "github.com/pterm/pterm" + "github.com/spf13/cobra" +) + +type ShowStore struct { + BankAccount *shared.BankAccount `json:"bankAccount"` +} +type ShowController struct { + store *ShowStore +} + +var _ fctl.Controller[*ShowStore] = (*ShowController)(nil) + +func NewShowStore() *ShowStore { + return &ShowStore{} +} + +func NewShowController() *ShowController { + return &ShowController{ + store: NewShowStore(), + } +} + +func NewShowCommand() *cobra.Command { + return fctl.NewCommand("get ", + fctl.WithShortDescription("Get bank account"), + fctl.WithArgs(cobra.ExactArgs(1)), + fctl.WithAliases("sh", "s"), + fctl.WithController[*ShowStore](NewShowController()), + ) +} + +func (c *ShowController) GetStore() *ShowStore { + return c.store +} + +func (c *ShowController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { + cfg, err := fctl.GetConfig(cmd) + if err != nil { + return nil, err + } + + organizationID, err := fctl.ResolveOrganizationID(cmd, cfg) + if err != nil { + return nil, err + } + + stack, err := fctl.ResolveStack(cmd, cfg, organizationID) + if err != nil { + return nil, err + } + + ledgerClient, err := fctl.NewStackClient(cmd, cfg, stack) + if err != nil { + return nil, err + } + + response, err := ledgerClient.Payments.GetBankAccount(cmd.Context(), operations.GetBankAccountRequest{ + BankAccountID: args[0], + }) + if err != nil { + return nil, err + } + + if response.StatusCode >= 300 { + return nil, fmt.Errorf("unexpected status code: %d", response.StatusCode) + } + + c.store.BankAccount = &response.BankAccountResponse.Data + + return c, nil +} + +func (c *ShowController) Render(cmd *cobra.Command, args []string) error { + fctl.Section.WithWriter(cmd.OutOrStdout()).Println("Information") + tableData := pterm.TableData{} + tableData = append(tableData, []string{pterm.LightCyan("ID"), c.store.BankAccount.ID}) + tableData = append(tableData, []string{pterm.LightCyan("CreatedAt"), c.store.BankAccount.CreatedAt.Format(time.RFC3339)}) + tableData = append(tableData, []string{pterm.LightCyan("Country"), c.store.BankAccount.Country}) + tableData = append(tableData, []string{pterm.LightCyan("Provider"), string(c.store.BankAccount.Provider)}) + + if err := pterm.DefaultTable. + WithWriter(cmd.OutOrStdout()). + WithData(tableData). + Render(); err != nil { + return err + } + + return nil +} diff --git a/components/fctl/cmd/payments/payments/list.go b/components/fctl/cmd/payments/payments/list.go index f818573964..6d96c04a40 100644 --- a/components/fctl/cmd/payments/payments/list.go +++ b/components/fctl/cmd/payments/payments/list.go @@ -11,32 +11,32 @@ import ( "github.com/spf13/cobra" ) -type PaymentsListStore struct { +type ListStore struct { Cursor *shared.PaymentsCursorCursor `json:"cursor"` } -type PaymentsListController struct { - store *PaymentsListStore +type ListController struct { + store *ListStore } -var _ fctl.Controller[*PaymentsListStore] = (*PaymentsListController)(nil) +var _ fctl.Controller[*ListStore] = (*ListController)(nil) -func NewDefaultPaymentsListStore() *PaymentsListStore { - return &PaymentsListStore{ +func NewListStore() *ListStore { + return &ListStore{ Cursor: &shared.PaymentsCursorCursor{}, } } -func NewPaymentsListController() *PaymentsListController { - return &PaymentsListController{ - store: NewDefaultPaymentsListStore(), +func NewListController() *ListController { + return &ListController{ + store: NewListStore(), } } -func (c *PaymentsListController) GetStore() *PaymentsListStore { +func (c *ListController) GetStore() *ListStore { return c.store } -func (c *PaymentsListController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { +func (c *ListController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { cfg, err := fctl.GetConfig(cmd) if err != nil { @@ -75,7 +75,7 @@ func (c *PaymentsListController) Run(cmd *cobra.Command, args []string) (fctl.Re return c, nil } -func (c *PaymentsListController) Render(cmd *cobra.Command, args []string) error { +func (c *ListController) Render(cmd *cobra.Command, args []string) error { tableData := fctl.Map(c.store.Cursor.Data, func(payment shared.Payment) []string { return []string{ payment.ID, @@ -100,11 +100,11 @@ func (c *PaymentsListController) Render(cmd *cobra.Command, args []string) error Render() } -func NewListPaymentsCommand() *cobra.Command { +func NewListCommand() *cobra.Command { return fctl.NewCommand("list", fctl.WithAliases("ls"), fctl.WithArgs(cobra.ExactArgs(0)), fctl.WithShortDescription("List payments"), - fctl.WithController[*PaymentsListStore](NewPaymentsListController()), + fctl.WithController[*ListStore](NewListController()), ) } diff --git a/components/fctl/cmd/payments/payments/root.go b/components/fctl/cmd/payments/payments/root.go new file mode 100644 index 0000000000..af556c85ab --- /dev/null +++ b/components/fctl/cmd/payments/payments/root.go @@ -0,0 +1,16 @@ +package payments + +import ( + fctl "github.com/formancehq/fctl/pkg" + "github.com/spf13/cobra" +) + +func NewPaymentsCommand() *cobra.Command { + return fctl.NewCommand("payments", + fctl.WithAliases("p"), + fctl.WithShortDescription("Payments management"), + fctl.WithChildCommands( + NewListCommand(), + ), + ) +} diff --git a/components/fctl/cmd/payments/root.go b/components/fctl/cmd/payments/root.go index af02c2757d..f40fefa531 100644 --- a/components/fctl/cmd/payments/root.go +++ b/components/fctl/cmd/payments/root.go @@ -1,6 +1,8 @@ package payments import ( + "github.com/formancehq/fctl/cmd/payments/accounts" + "github.com/formancehq/fctl/cmd/payments/bankaccounts" "github.com/formancehq/fctl/cmd/payments/connectors" "github.com/formancehq/fctl/cmd/payments/payments" "github.com/formancehq/fctl/cmd/payments/transferinitiation" @@ -13,12 +15,10 @@ func NewCommand() *cobra.Command { fctl.WithShortDescription("Payments management"), fctl.WithChildCommands( connectors.NewConnectorsCommand(), - payments.NewListPaymentsCommand(), - transferinitiation.NewShowCommand(), - transferinitiation.NewListTransferInitiationCommand(), - transferinitiation.NewCreateCommand(), - transferinitiation.NewUpdateStatusCommand(), - transferinitiation.NewDeleteCommand(), + payments.NewPaymentsCommand(), + transferinitiation.NewTransferInitiationCommand(), + bankaccounts.NewBankAccountsCommand(), + accounts.NewAccountsCommand(), ), ) } diff --git a/components/fctl/cmd/payments/transferinitiation/create.go b/components/fctl/cmd/payments/transferinitiation/create.go index b224d50380..67578bf290 100644 --- a/components/fctl/cmd/payments/transferinitiation/create.go +++ b/components/fctl/cmd/payments/transferinitiation/create.go @@ -11,22 +11,22 @@ import ( "github.com/spf13/cobra" ) -type TransferInitiationCreateStore struct { +type CreateStore struct { TransferInitiationId string `json:"transferInitiationId"` } -type TransferInitiationCreateController struct { - store *TransferInitiationCreateStore +type CreateController struct { + store *CreateStore } -var _ fctl.Controller[*TransferInitiationCreateStore] = (*TransferInitiationCreateController)(nil) +var _ fctl.Controller[*CreateStore] = (*CreateController)(nil) -func NewDefaultTransferInitiationCreateStore() *TransferInitiationCreateStore { - return &TransferInitiationCreateStore{} +func NewCreateStore() *CreateStore { + return &CreateStore{} } -func NewTransferInitiationCreateController() *TransferInitiationCreateController { - return &TransferInitiationCreateController{ - store: NewDefaultTransferInitiationCreateStore(), +func NewCreateController() *CreateController { + return &CreateController{ + store: NewCreateStore(), } } @@ -35,15 +35,15 @@ func NewCreateCommand() *cobra.Command { fctl.WithShortDescription("Create a transfer initiation"), fctl.WithAliases("cr", "c"), fctl.WithArgs(cobra.ExactArgs(1)), - fctl.WithController[*TransferInitiationCreateStore](NewTransferInitiationCreateController()), + fctl.WithController[*CreateStore](NewCreateController()), ) } -func (c *TransferInitiationCreateController) GetStore() *TransferInitiationCreateStore { +func (c *CreateController) GetStore() *CreateStore { return c.store } -func (c *TransferInitiationCreateController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { +func (c *CreateController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { soc, err := fctl.GetStackOrganizationConfig(cmd) if err != nil { @@ -79,7 +79,7 @@ func (c *TransferInitiationCreateController) Run(cmd *cobra.Command, args []stri return c, nil } -func (c *TransferInitiationCreateController) Render(cmd *cobra.Command, args []string) error { +func (c *CreateController) Render(cmd *cobra.Command, args []string) error { pterm.Success.WithWriter(cmd.OutOrStdout()).Printfln("Transfer Initiation created with ID: %s", c.store.TransferInitiationId) return nil diff --git a/components/fctl/cmd/payments/transferinitiation/delete.go b/components/fctl/cmd/payments/transferinitiation/delete.go index e696c10b91..6e7d679287 100644 --- a/components/fctl/cmd/payments/transferinitiation/delete.go +++ b/components/fctl/cmd/payments/transferinitiation/delete.go @@ -10,40 +10,40 @@ import ( "github.com/spf13/cobra" ) -type TransferInitiationDeleteStore struct { +type DeleteStore struct { TransferID string `json:"transferId"` Success bool `json:"success"` } -type TransferInitiationDeleteController struct { - store *TransferInitiationDeleteStore +type DeleteController struct { + store *DeleteStore } -var _ fctl.Controller[*TransferInitiationDeleteStore] = (*TransferInitiationDeleteController)(nil) +var _ fctl.Controller[*DeleteStore] = (*DeleteController)(nil) -func NewDefaultTransferInitiationDeleteStore() *TransferInitiationDeleteStore { - return &TransferInitiationDeleteStore{} +func NewDeleteStore() *DeleteStore { + return &DeleteStore{} } -func NewTransferInitiationDeleteController() *TransferInitiationDeleteController { - return &TransferInitiationDeleteController{ - store: NewDefaultTransferInitiationDeleteStore(), +func NewDeleteController() *DeleteController { + return &DeleteController{ + store: NewDeleteStore(), } } func NewDeleteCommand() *cobra.Command { return fctl.NewCommand("delete ", - fctl.WithAliases("del", "d"), + fctl.WithAliases("d"), fctl.WithShortDescription("Delete a transfer Initiation"), fctl.WithArgs(cobra.ExactArgs(1)), - fctl.WithController[*TransferInitiationDeleteStore](NewTransferInitiationDeleteController()), + fctl.WithController[*DeleteStore](NewDeleteController()), ) } -func (c *TransferInitiationDeleteController) GetStore() *TransferInitiationDeleteStore { +func (c *DeleteController) GetStore() *DeleteStore { return c.store } -func (c *TransferInitiationDeleteController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { +func (c *DeleteController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { cfg, err := fctl.GetConfig(cmd) if err != nil { return nil, errors.Wrap(err, "retrieving config") @@ -85,7 +85,7 @@ func (c *TransferInitiationDeleteController) Run(cmd *cobra.Command, args []stri return c, nil } -func (c *TransferInitiationDeleteController) Render(cmd *cobra.Command, args []string) error { +func (c *DeleteController) Render(cmd *cobra.Command, args []string) error { pterm.Success.WithShowLineNumber().Printfln("Transfer Initiation %s Deleted!", c.store.TransferID) return nil } diff --git a/components/fctl/cmd/payments/transferinitiation/list.go b/components/fctl/cmd/payments/transferinitiation/list.go index a8e777f9ff..d45a7fbed0 100644 --- a/components/fctl/cmd/payments/transferinitiation/list.go +++ b/components/fctl/cmd/payments/transferinitiation/list.go @@ -11,33 +11,33 @@ import ( "github.com/spf13/cobra" ) -type TransferInitiationListStore struct { +type ListStore struct { Cursor *shared.TransferInitiationsCursorCursor `json:"cursor"` } -type TransferInitiationListController struct { - store *TransferInitiationListStore +type ListController struct { + store *ListStore } -var _ fctl.Controller[*TransferInitiationListStore] = (*TransferInitiationListController)(nil) +var _ fctl.Controller[*ListStore] = (*ListController)(nil) -func NewDefaultTransferInitiationListStore() *TransferInitiationListStore { - return &TransferInitiationListStore{ +func NewListStore() *ListStore { + return &ListStore{ Cursor: &shared.TransferInitiationsCursorCursor{}, } } -func NewTransferInitiationListController() *TransferInitiationListController { - return &TransferInitiationListController{ - store: NewDefaultTransferInitiationListStore(), +func NewListController() *ListController { + return &ListController{ + store: NewListStore(), } } -func (c *TransferInitiationListController) GetStore() *TransferInitiationListStore { +func (c *ListController) GetStore() *ListStore { return c.store } -func (c *TransferInitiationListController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { +func (c *ListController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { cfg, err := fctl.GetConfig(cmd) if err != nil { @@ -76,7 +76,7 @@ func (c *TransferInitiationListController) Run(cmd *cobra.Command, args []string return c, nil } -func (c *TransferInitiationListController) Render(cmd *cobra.Command, args []string) error { +func (c *ListController) Render(cmd *cobra.Command, args []string) error { tableData := fctl.Map(c.store.Cursor.Data, func(tf shared.TransferInitiation) []string { return []string{ tf.ID, @@ -102,11 +102,11 @@ func (c *TransferInitiationListController) Render(cmd *cobra.Command, args []str Render() } -func NewListTransferInitiationCommand() *cobra.Command { - return fctl.NewCommand("list_transfer_initiations", - fctl.WithAliases("ls"), +func NewListCommand() *cobra.Command { + return fctl.NewCommand("list", + fctl.WithAliases("ls", "l"), fctl.WithArgs(cobra.ExactArgs(0)), fctl.WithShortDescription("List transfer initiation"), - fctl.WithController[*TransferInitiationListStore](NewTransferInitiationListController()), + fctl.WithController[*ListStore](NewListController()), ) } diff --git a/components/fctl/cmd/payments/transferinitiation/retry.go b/components/fctl/cmd/payments/transferinitiation/retry.go new file mode 100644 index 0000000000..3e6d30d69c --- /dev/null +++ b/components/fctl/cmd/payments/transferinitiation/retry.go @@ -0,0 +1,78 @@ +package transferinitiation + +import ( + "fmt" + + fctl "github.com/formancehq/fctl/pkg" + "github.com/formancehq/formance-sdk-go/pkg/models/operations" + "github.com/pkg/errors" + "github.com/pterm/pterm" + "github.com/spf13/cobra" +) + +type RetryStore struct { + TransferID string `json:"transferId"` + Success bool `json:"success"` +} +type RetryController struct { + store *RetryStore +} + +var _ fctl.Controller[*RetryStore] = (*RetryController)(nil) + +func NewRetryStore() *RetryStore { + return &RetryStore{} +} + +func NewRetryController() *RetryController { + return &RetryController{ + store: NewRetryStore(), + } +} + +func NewRetryCommand() *cobra.Command { + return fctl.NewCommand("retry ", + fctl.WithShortDescription("Retry a failed transfer initiation"), + fctl.WithAliases("r"), + fctl.WithArgs(cobra.ExactArgs(1)), + fctl.WithController[*RetryStore](NewRetryController()), + ) +} + +func (c *RetryController) GetStore() *RetryStore { + return c.store +} + +func (c *RetryController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { + soc, err := fctl.GetStackOrganizationConfig(cmd) + if err != nil { + return nil, err + } + client, err := fctl.NewStackClient(cmd, soc.Config, soc.Stack) + if err != nil { + return nil, errors.Wrap(err, "creating stack client") + } + + //nolint:gosimple + response, err := client.Payments.RetryTransferInitiation(cmd.Context(), operations.RetryTransferInitiationRequest{ + TransferID: args[0], + }) + if err != nil { + return nil, err + } + + if response.StatusCode >= 300 { + return nil, fmt.Errorf("unexpected status code: %d", response.StatusCode) + } + + c.store.TransferID = args[0] + c.store.Success = true + + return c, nil +} + +func (c *RetryController) Render(cmd *cobra.Command, args []string) error { + pterm.Success.WithWriter(cmd.OutOrStdout()).Printfln("Retry Transfer Initiation with ID: %s", c.store.TransferID) + + return nil +} diff --git a/components/fctl/cmd/payments/transferinitiation/root.go b/components/fctl/cmd/payments/transferinitiation/root.go new file mode 100644 index 0000000000..3159212c40 --- /dev/null +++ b/components/fctl/cmd/payments/transferinitiation/root.go @@ -0,0 +1,21 @@ +package transferinitiation + +import ( + fctl "github.com/formancehq/fctl/pkg" + "github.com/spf13/cobra" +) + +func NewTransferInitiationCommand() *cobra.Command { + return fctl.NewCommand("transfer_initiation", + fctl.WithAliases("ti"), + fctl.WithShortDescription("Transfer Initiation management"), + fctl.WithChildCommands( + NewCreateCommand(), + NewDeleteCommand(), + NewListCommand(), + NewRetryCommand(), + NewShowCommand(), + NewUpdateStatusCommand(), + ), + ) +} diff --git a/components/fctl/cmd/payments/transferinitiation/update_status.go b/components/fctl/cmd/payments/transferinitiation/update_status.go index 7bedfc783b..a937466565 100644 --- a/components/fctl/cmd/payments/transferinitiation/update_status.go +++ b/components/fctl/cmd/payments/transferinitiation/update_status.go @@ -11,41 +11,41 @@ import ( "github.com/spf13/cobra" ) -type UpdateTransferInitiationStatusStore struct { +type UpdateStatusStore struct { TransferID string `json:"transferId"` Status string `json:"status"` Success bool `json:"success"` } -type UpdateTransferInitiationStatusController struct { - store *UpdateTransferInitiationStatusStore +type UpdateStatusController struct { + store *UpdateStatusStore } -var _ fctl.Controller[*UpdateTransferInitiationStatusStore] = (*UpdateTransferInitiationStatusController)(nil) +var _ fctl.Controller[*UpdateStatusStore] = (*UpdateStatusController)(nil) -func NewDefaultUpdateTransferInitiationStatusStore() *UpdateTransferInitiationStatusStore { - return &UpdateTransferInitiationStatusStore{} +func NewUpdateStatusStore() *UpdateStatusStore { + return &UpdateStatusStore{} } -func NewUpdateTransferInitiationStatusController() *UpdateTransferInitiationStatusController { - return &UpdateTransferInitiationStatusController{ - store: NewDefaultUpdateTransferInitiationStatusStore(), +func NewUpdateStatusController() *UpdateStatusController { + return &UpdateStatusController{ + store: NewUpdateStatusStore(), } } func NewUpdateStatusCommand() *cobra.Command { return fctl.NewCommand("update_status ", fctl.WithShortDescription("Update the status of a transfer initiation"), - fctl.WithAliases("cr", "c"), + fctl.WithAliases("u"), fctl.WithArgs(cobra.ExactArgs(2)), - fctl.WithController[*UpdateTransferInitiationStatusStore](NewUpdateTransferInitiationStatusController()), + fctl.WithController[*UpdateStatusStore](NewUpdateStatusController()), ) } -func (c *UpdateTransferInitiationStatusController) GetStore() *UpdateTransferInitiationStatusStore { +func (c *UpdateStatusController) GetStore() *UpdateStatusStore { return c.store } -func (c *UpdateTransferInitiationStatusController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { +func (c *UpdateStatusController) Run(cmd *cobra.Command, args []string) (fctl.Renderable, error) { soc, err := fctl.GetStackOrganizationConfig(cmd) if err != nil { return nil, err @@ -77,8 +77,8 @@ func (c *UpdateTransferInitiationStatusController) Run(cmd *cobra.Command, args return c, nil } -func (c *UpdateTransferInitiationStatusController) Render(cmd *cobra.Command, args []string) error { - pterm.Success.WithWriter(cmd.OutOrStdout()).Printfln("Update Transfer Initiation staus with ID: %s and status %s", c.store.TransferID, c.store.Status) +func (c *UpdateStatusController) Render(cmd *cobra.Command, args []string) error { + pterm.Success.WithWriter(cmd.OutOrStdout()).Printfln("Update Transfer Initiation status with ID: %s and status %s", c.store.TransferID, c.store.Status) return nil } diff --git a/components/payments/openapi.yaml b/components/payments/openapi.yaml index a9153a0a19..3790fcecdf 100644 --- a/components/payments/openapi.yaml +++ b/components/payments/openapi.yaml @@ -124,18 +124,18 @@ paths: '204': $ref: '#/components/responses/NoContent' /accounts: - get: - summary: List accounts - operationId: listAccounts - tags: - - Payments - parameters: - - $ref: '#/components/parameters/PageSize' - - $ref: '#/components/parameters/Cursor' - - $ref: '#/components/parameters/Sort' - responses: - '200': - $ref: '#/components/responses/Accounts' + get: + summary: List accounts + operationId: listAccounts + tags: + - Payments + parameters: + - $ref: '#/components/parameters/PageSize' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/Sort' + responses: + '200': + $ref: '#/components/responses/Accounts' /accounts/{accountId}: get: summary: Get an account @@ -211,6 +211,10 @@ paths: operationId: listBankAccounts tags: - Payments + parameters: + - $ref: '#/components/parameters/PageSize' + - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/Sort' description: List all bank accounts created by user on Formance. responses: '200': @@ -499,7 +503,7 @@ components: content: application/json: schema: - $ref: '#/components/schemas/BankAccountsResponse' + $ref: '#/components/schemas/BankAccountsCursor' BankAccount: description: OK content: @@ -638,6 +642,22 @@ components: type: array items: $ref: '#/components/schemas/TransferInitiation' + BankAccountsCursor: + type: object + required: + - cursor + properties: + cursor: + allOf: + - $ref: '#/components/schemas/CursorBase' + - type: object + required: + - data + properties: + data: + type: array + items: + $ref: '#/components/schemas/BankAccount' AccountsCursor: type: object required: @@ -739,13 +759,6 @@ components: enabled: type: boolean example: true - BankAccountsResponse: - type: object - required: - - data - properties: - data: - $ref: '#/components/schemas/BankAccount' BankAccountResponse: type: object required: diff --git a/docs/openapi/v2.json b/docs/openapi/v2.json index e52dc5ac7e..84f23a8ac3 100644 --- a/docs/openapi/v2.json +++ b/docs/openapi/v2.json @@ -12,27 +12,12 @@ "url": "https://avatars.githubusercontent.com/u/84325077?s=200&v=4", "altText": "Formance" }, - "version": "v1.0.20230927" + "version": "v1.0.20231002" }, "servers": [ { "url": "http://localhost", "description": "local server" - }, - { - "url": "https://{organization}.sandbox.formance.cloud", - "description": "sandbox server", - "variables": { - "organization": { - "description": "The organization on which the ledger is located", - "default": "" - } - } - } - ], - "security": [ - { - "Authorization": [] } ], "paths": { @@ -1030,6 +1015,54 @@ } } }, + "/api/ledger/v2/{ledger}/accounts/{address}/metadata/{key}": { + "delete": { + "description": "Delete metadata by key", + "operationId": "deleteAccountMetadata", + "tags": [ + "Ledger", + "Transactions" + ], + "summary": "Delete metadata by key", + "parameters": [ + { + "name": "ledger", + "in": "path", + "description": "Name of the ledger.", + "required": true, + "schema": { + "type": "string", + "example": "ledger001" + } + }, + { + "name": "address", + "in": "path", + "description": "Account address", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "key", + "in": "path", + "description": "The key to remove.", + "required": true, + "schema": { + "type": "string", + "example": "foo" + } + } + ], + "responses": { + "2XX": { + "description": "Key deleted", + "content": {} + } + } + } + }, "/api/ledger/v2/{ledger}/stats": { "get": { "tags": [ @@ -1455,6 +1488,57 @@ } } }, + "/api/ledger/v2/{ledger}/transactions/{id}/metadata/{key}": { + "delete": { + "description": "Delete metadata by key", + "operationId": "deleteTransactionMetadata", + "summary": "Delete metadata by key", + "tags": [ + "Ledger", + "Transactions" + ], + "parameters": [ + { + "name": "ledger", + "in": "path", + "description": "Name of the ledger.", + "required": true, + "schema": { + "type": "string", + "example": "ledger001" + } + }, + { + "name": "id", + "in": "path", + "description": "Transaction ID.", + "required": true, + "schema": { + "type": "integer", + "format": "int64", + "minimum": 0, + "example": 1234 + } + }, + { + "name": "key", + "in": "path", + "required": true, + "description": "The key to remove.", + "schema": { + "type": "string", + "example": "foo" + } + } + ], + "responses": { + "2XX": { + "description": "Key deleted", + "content": {} + } + } + } + }, "/api/ledger/v2/{ledger}/transactions/{id}/revert": { "post": { "tags": [ @@ -1739,6 +1823,127 @@ } } }, + "/api/payments/transfer-initiation": { + "get": { + "summary": "List Transfer Initiations", + "operationId": "listTransferInitiations", + "tags": [ + "Payments" + ], + "parameters": [ + { + "$ref": "#/components/parameters/PageSize" + }, + { + "$ref": "#/components/parameters/Cursor" + }, + { + "$ref": "#/components/parameters/Sort" + } + ], + "responses": { + "200": { + "$ref": "#/components/responses/TransferInitiations" + } + } + }, + "post": { + "summary": "Create a TransferInitiation", + "tags": [ + "Payments" + ], + "operationId": "createTransferInitiation", + "description": "Create a transfer initiation", + "requestBody": { + "$ref": "#/components/requestBodies/TransferInitiation" + }, + "responses": { + "200": { + "$ref": "#/components/responses/TransferInitiation" + } + } + } + }, + "/api/payments/transfer-initiation/{transferId}": { + "get": { + "summary": "Get a transfer initiation", + "tags": [ + "Payments" + ], + "operationId": "getTransferInitiation", + "parameters": [ + { + "$ref": "#/components/parameters/TransferId" + } + ], + "responses": { + "200": { + "$ref": "#/components/responses/TransferInitiation" + } + } + }, + "delete": { + "summary": "Delete a transfer initiation", + "operationId": "deleteTransferInitiation", + "tags": [ + "Payments" + ], + "description": "Delete a transfer initiation by its id.", + "parameters": [ + { + "$ref": "#/components/parameters/TransferId" + } + ], + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + } + } + } + }, + "/api/payments/transfer-initiation/{transferId}/status": { + "post": { + "summary": "Update the status of a transfer initiation", + "tags": [ + "Payments" + ], + "operationId": "udpateTransferInitiationStatus", + "description": "Update a transfer initiation status", + "parameters": [ + { + "$ref": "#/components/parameters/TransferId" + } + ], + "requestBody": { + "$ref": "#/components/requestBodies/UpdateTransferInitiationStatus" + }, + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + } + } + } + }, + "/api/payments/transfer-initiation/{transferId}/retry": { + "post": { + "summary": "Retry a failed transfer initiation", + "tags": [ + "Payments" + ], + "operationId": "retryTransferInitiation", + "description": "Retry a failed transfer initiation", + "parameters": [ + { + "$ref": "#/components/parameters/TransferId" + } + ], + "responses": { + "204": { + "$ref": "#/components/responses/NoContent" + } + } + } + }, "/api/payments/accounts": { "get": { "summary": "List accounts", @@ -1850,6 +2055,67 @@ } } }, + "/api/payments/bank-accounts": { + "post": { + "summary": "Create a BankAccount in Payments and on the PSP", + "tags": [ + "Payments" + ], + "operationId": "createBankAccount", + "description": "Create a bank account in Payments and on the PSP.", + "requestBody": { + "$ref": "#/components/requestBodies/BankAccount" + }, + "responses": { + "200": { + "$ref": "#/components/responses/BankAccount" + } + } + }, + "get": { + "summary": "List bank accounts created by user on Formance", + "operationId": "listBankAccounts", + "tags": [ + "Payments" + ], + "parameters": [ + { + "$ref": "#/components/parameters/PageSize" + }, + { + "$ref": "#/components/parameters/Cursor" + }, + { + "$ref": "#/components/parameters/Sort" + } + ], + "description": "List all bank accounts created by user on Formance.", + "responses": { + "200": { + "$ref": "#/components/responses/BankAccounts" + } + } + } + }, + "/api/payments/bank-accounts/{bankAccountId}": { + "get": { + "summary": "Get a bank account created by user on Formance", + "tags": [ + "Payments" + ], + "operationId": "getBankAccount", + "parameters": [ + { + "$ref": "#/components/parameters/BankAccountId" + } + ], + "responses": { + "200": { + "$ref": "#/components/responses/BankAccount" + } + } + } + }, "/api/payments/connectors": { "get": { "summary": "List all installed connectors", @@ -2051,24 +2317,6 @@ } } }, - "/api/payments/connectors/stripe/transfers": { - "post": { - "summary": "Transfer funds between Stripe accounts", - "tags": [ - "Payments" - ], - "operationId": "connectorsStripeTransfer", - "description": "Execute a transfer between two Stripe accounts.", - "requestBody": { - "$ref": "#/components/requestBodies/StripeTransfer" - }, - "responses": { - "200": { - "$ref": "#/components/responses/StripeTransfer" - } - } - } - }, "/api/search/_info": { "get": { "summary": "Get server info", @@ -4557,11 +4805,7 @@ ] }, "ConfigInfoResponse": { - "properties": { - "data": { - "$ref": "#/components/schemas/ConfigInfo" - } - } + "$ref": "#/components/schemas/ConfigInfo" }, "Volume": { "type": "object", @@ -4776,7 +5020,7 @@ } } }, - "AccountsCursor": { + "TransferInitiationsCursor": { "type": "object", "required": [ "cursor" @@ -4796,7 +5040,7 @@ "data": { "type": "array", "items": { - "$ref": "#/components/schemas/paymentsAccount" + "$ref": "#/components/schemas/TransferInitiation" } } } @@ -4805,7 +5049,7 @@ } } }, - "BalancesCursor": { + "BankAccountsCursor": { "type": "object", "required": [ "cursor" @@ -4825,7 +5069,7 @@ "data": { "type": "array", "items": { - "$ref": "#/components/schemas/AccountBalance" + "$ref": "#/components/schemas/BankAccount" } } } @@ -4834,7 +5078,7 @@ } } }, - "TasksCursor": { + "AccountsCursor": { "type": "object", "required": [ "cursor" @@ -4854,15 +5098,73 @@ "data": { "type": "array", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TaskStripe" - }, - { - "$ref": "#/components/schemas/TaskWise" - }, - { - "$ref": "#/components/schemas/TaskCurrencyCloud" + "$ref": "#/components/schemas/paymentsAccount" + } + } + } + } + ] + } + } + }, + "BalancesCursor": { + "type": "object", + "required": [ + "cursor" + ], + "properties": { + "cursor": { + "allOf": [ + { + "$ref": "#/components/schemas/CursorBase" + }, + { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AccountBalance" + } + } + } + } + ] + } + } + }, + "TasksCursor": { + "type": "object", + "required": [ + "cursor" + ], + "properties": { + "cursor": { + "allOf": [ + { + "$ref": "#/components/schemas/CursorBase" + }, + { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TaskStripe" + }, + { + "$ref": "#/components/schemas/TaskWise" + }, + { + "$ref": "#/components/schemas/TaskCurrencyCloud" }, { "$ref": "#/components/schemas/TaskDummyPay" @@ -4910,6 +5212,17 @@ } } }, + "TransferInitiationResponse": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/TransferInitiation" + } + } + }, "paymentsAccountResponse": { "type": "object", "required": [ @@ -4944,6 +5257,17 @@ } } }, + "BankAccountResponse": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/BankAccount" + } + } + }, "ConnectorsConfigsResponse": { "type": "object", "required": [ @@ -5079,6 +5403,17 @@ "MONEYCORP" ] }, + "TransferInitiationStatus": { + "type": "string", + "enum": [ + "WAITING_FOR_VALIDATION", + "PROCESSING", + "PROCESSED", + "FAILED", + "REJECTED", + "VALIDATED" + ] + }, "ConnectorConfig": { "anyOf": [ { @@ -5170,7 +5505,7 @@ "pollingPeriod": { "type": "string", "example": "60s", - "description": "The frequency at which the connector will try to fetch new BalanceTransaction objects from Stripe API.\n", + "description": "The frequency at which the connector will try to fetch new BalanceTransaction objects from Wise API.\n", "default": "120s" } } @@ -5197,7 +5532,7 @@ "pollingPeriod": { "type": "string", "example": "60s", - "description": "The frequency at which the connector will try to fetch new BalanceTransaction objects from Stripe API.\n", + "description": "The frequency at which the connector will try to fetch new BalanceTransaction objects from Modulr API.\n", "default": "120s" } } @@ -5240,7 +5575,7 @@ "pollingPeriod": { "type": "string", "example": "60s", - "description": "The frequency at which the connector will try to fetch new BalanceTransaction objects from Stripe API.\n", + "description": "The frequency at which the connector will try to fetch new BalanceTransaction objects from Banking Circle API.\n", "default": "120s" } } @@ -5256,7 +5591,7 @@ "pollingPeriod": { "type": "string", "example": "60s", - "description": "The frequency at which the connector will try to fetch new BalanceTransaction objects from Stripe API.\n", + "description": "The frequency at which the connector will try to fetch new BalanceTransaction objects from MangoPay API.\n", "default": "120s" }, "clientID": { @@ -5296,7 +5631,7 @@ "pollingPeriod": { "type": "string", "example": "60s", - "description": "The frequency at which the connector will try to fetch new BalanceTransaction objects from Stripe API.\n", + "description": "The frequency at which the connector will try to fetch new BalanceTransaction objects from MoneyCorp API.\n", "default": "120s" } } @@ -5330,6 +5665,124 @@ } } }, + "TransferInitiation": { + "type": "object", + "required": [ + "id", + "createdAt", + "updatedAt", + "description", + "sourceAccountID", + "destinationAccountID", + "provider", + "type", + "amount", + "asset", + "status", + "error" + ], + "properties": { + "id": { + "type": "string", + "example": "XXX" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "description": { + "type": "string" + }, + "sourceAccountID": { + "type": "string" + }, + "destinationAccountID": { + "type": "string" + }, + "provider": { + "$ref": "#/components/schemas/Connector" + }, + "type": { + "type": "string", + "enum": [ + "TRANSFER", + "PAYOUT" + ] + }, + "amount": { + "type": "integer", + "format": "bigint" + }, + "asset": { + "type": "string", + "example": "USD" + }, + "status": { + "$ref": "#/components/schemas/TransferInitiationStatus" + }, + "error": { + "type": "string" + }, + "relatedPayments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TransferInitiationPayments" + } + } + } + }, + "TransferInitiationPayments": { + "type": "object", + "required": [ + "paymentID", + "createdAt", + "status", + "error" + ], + "properties": { + "paymentID": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "status": { + "$ref": "#/components/schemas/PaymentStatus" + }, + "error": { + "type": "string" + } + } + }, + "BankAccount": { + "type": "object", + "required": [ + "id", + "createdAt", + "country", + "provider" + ], + "properties": { + "id": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "country": { + "type": "string" + }, + "provider": { + "$ref": "#/components/schemas/Connector" + } + } + }, "Payment": { "type": "object", "required": [ @@ -5846,34 +6299,109 @@ } } }, - "StripeTransferRequest": { + "BankAccountRequest": { + "type": "object", + "required": [ + "country", + "provider", + "name" + ], + "properties": { + "country": { + "type": "string", + "example": "GB" + }, + "provider": { + "$ref": "#/components/schemas/Connector" + }, + "name": { + "type": "string", + "example": "My account" + }, + "accountNumber": { + "type": "string" + }, + "iban": { + "type": "string" + }, + "swiftBicCode": { + "type": "string" + } + } + }, + "TransferInitiationRequest": { "type": "object", + "required": [ + "uniqueRequestID", + "createdAt", + "description", + "sourceAccountID", + "destinationAccountID", + "provider", + "type", + "amount", + "asset", + "validated" + ], "properties": { + "uniqueRequestID": { + "type": "string", + "example": "XXX" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "description": { + "type": "string" + }, + "sourceAccountID": { + "type": "string" + }, + "destinationAccountID": { + "type": "string" + }, + "provider": { + "$ref": "#/components/schemas/Connector" + }, + "type": { + "type": "string", + "enum": [ + "TRANSFER", + "PAYOUT" + ] + }, "amount": { "type": "integer", - "format": "bigint", - "minimum": 0, - "example": 100 + "format": "bigint" }, "asset": { "type": "string", "example": "USD" }, - "destination": { - "type": "string", - "example": "acct_1Gqj58KZcSIg2N2q" - }, - "metadata": { - "type": "object", - "description": "A set of key/value pairs that you can attach to a transfer object.\nIt can be useful for storing additional information about the transfer in a structured format.\n", - "example": { - "order_id": "6735" - } + "validated": { + "type": "boolean" } } }, - "StripeTransferResponse": { - "type": "object" + "UpdateTransferInitiationStatusRequest": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "WAITING_FOR_VALIDATION", + "PROCESSING", + "PROCESSED", + "FAILED", + "REJECTED", + "VALIDATED" + ] + } + } }, "PaymentStatus": { "type": "string", @@ -7433,6 +7961,32 @@ } ] }, + "StripeTransferRequest": { + "type": "object", + "properties": { + "amount": { + "type": "integer", + "format": "bigint", + "minimum": 0, + "example": 100 + }, + "asset": { + "type": "string", + "example": "USD" + }, + "destination": { + "type": "string", + "example": "acct_1Gqj58KZcSIg2N2q" + }, + "metadata": { + "type": "object", + "description": "A set of key/value pairs that you can attach to a transfer object.\nIt can be useful for storing additional information about the transfer in a structured format.\n", + "example": { + "order_id": "6735" + } + } + } + }, "ActivityStripeTransfer": { "$ref": "#/components/schemas/StripeTransferRequest" }, @@ -7625,8 +8179,8 @@ "type": "oauth2", "flows": { "clientCredentials": { - "tokenUrl": "", - "refreshUrl": "", + "tokenUrl": "https://localhost/api/auth/oauth/token", + "refreshUrl": "https://localhost/api/auth/oauth/token", "scopes": {} } } @@ -7666,6 +8220,26 @@ } } }, + "TransferInitiations": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransferInitiationsCursor" + } + } + } + }, + "TransferInitiation": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransferInitiationResponse" + } + } + } + }, "Accounts": { "description": "OK", "content": { @@ -7706,52 +8280,62 @@ } } }, - "ConnectorsConfigs": { + "BankAccounts": { "description": "OK", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ConnectorsConfigsResponse" + "$ref": "#/components/schemas/BankAccountsCursor" } } } }, - "ConnectorConfig": { + "BankAccount": { "description": "OK", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ConnectorConfigResponse" + "$ref": "#/components/schemas/BankAccountResponse" } } } }, - "Tasks": { + "ConnectorsConfigs": { "description": "OK", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TasksCursor" + "$ref": "#/components/schemas/ConnectorsConfigsResponse" } } } }, - "Task": { + "ConnectorConfig": { "description": "OK", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TaskResponse" + "$ref": "#/components/schemas/ConnectorConfigResponse" + } + } + } + }, + "Tasks": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TasksCursor" } } } }, - "StripeTransfer": { + "Task": { "description": "OK", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/StripeTransferResponse" + "$ref": "#/components/schemas/TaskResponse" } } } @@ -7845,6 +8429,26 @@ "example": "XXX", "required": true }, + "TransferId": { + "name": "transferId", + "in": "path", + "schema": { + "type": "string" + }, + "description": "The transfer ID.", + "example": "XXX", + "required": true + }, + "BankAccountId": { + "name": "bankAccountId", + "in": "path", + "schema": { + "type": "string" + }, + "description": "The bank account ID.", + "example": "XXX", + "required": true + }, "Connector": { "name": "connector", "description": "The name of the connector.", @@ -7876,22 +8480,42 @@ } } }, - "StripeTransfer": { + "UpdateMetadata": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/StripeTransferRequest" + "$ref": "#/components/schemas/PaymentMetadata" } } } }, - "UpdateMetadata": { + "TransferInitiation": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/PaymentMetadata" + "$ref": "#/components/schemas/TransferInitiationRequest" + } + } + } + }, + "BankAccount": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BankAccountRequest" + } + } + } + }, + "UpdateTransferInitiationStatus": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateTransferInitiationStatusRequest" } } } diff --git a/openapi/build/generate.json b/openapi/build/generate.json index b1a5986666..84f23a8ac3 100644 --- a/openapi/build/generate.json +++ b/openapi/build/generate.json @@ -12,7 +12,7 @@ "url": "https://avatars.githubusercontent.com/u/84325077?s=200&v=4", "altText": "Formance" }, - "version": "v1.0.20230928" + "version": "v1.0.20231002" }, "servers": [ { @@ -2078,6 +2078,17 @@ "tags": [ "Payments" ], + "parameters": [ + { + "$ref": "#/components/parameters/PageSize" + }, + { + "$ref": "#/components/parameters/Cursor" + }, + { + "$ref": "#/components/parameters/Sort" + } + ], "description": "List all bank accounts created by user on Formance.", "responses": { "200": { @@ -5038,6 +5049,35 @@ } } }, + "BankAccountsCursor": { + "type": "object", + "required": [ + "cursor" + ], + "properties": { + "cursor": { + "allOf": [ + { + "$ref": "#/components/schemas/CursorBase" + }, + { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BankAccount" + } + } + } + } + ] + } + } + }, "AccountsCursor": { "type": "object", "required": [ @@ -5217,17 +5257,6 @@ } } }, - "BankAccountsResponse": { - "type": "object", - "required": [ - "data" - ], - "properties": { - "data": { - "$ref": "#/components/schemas/BankAccount" - } - } - }, "BankAccountResponse": { "type": "object", "required": [ @@ -8256,7 +8285,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/BankAccountsResponse" + "$ref": "#/components/schemas/BankAccountsCursor" } } }