4 Commits

Author SHA1 Message Date
be49254769 Merge pull request 'bff USDT ledger creation' (#682) from bff-681 into main
All checks were successful
ci/woodpecker/push/bff Pipeline was successful
ci/woodpecker/push/frontend Pipeline was successful
Reviewed-on: #682
2026-03-06 10:58:27 +00:00
Stephan D
34e507b664 bff USDT ledger creation 2026-03-06 11:58:07 +01:00
b481de9ffc Merge pull request 'New comments section in the requests/responses' (#679) from bff-677 into main
Reviewed-on: #679
2026-03-05 19:29:10 +00:00
Stephan D
0c29e7686d New comments section in the requests/responses 2026-03-05 20:28:28 +01:00
3 changed files with 64 additions and 39 deletions

View File

@@ -75,6 +75,9 @@ make clean # Remove all containers and volumes
```bash ```bash
make infra-up # Start infrastructure only (MongoDB, NATS, Vault) make infra-up # Start infrastructure only (MongoDB, NATS, Vault)
make services-up # Start application services only (assumes infra is running) make services-up # Start application services only (assumes infra is running)
make backend-up # Start backend services only (no infrastructure/frontend changes)
make backend-down # Stop backend services only
make backend-rebuild # Rebuild and restart backend services only
make list-services # Show service names, ports, and descriptions make list-services # Show service names, ports, and descriptions
``` ```

View File

@@ -338,9 +338,6 @@ func (a *AccountAPI) openOrgLedgerAccount(ctx context.Context, org *model.Organi
return merrors.Internal("chain gateway default asset is not configured") return merrors.Internal("chain gateway default asset is not configured")
} }
// TODO: remove hardcode
currency := "RUB"
var describable *describablev1.Describable var describable *describablev1.Describable
name := strings.TrimSpace(sr.LedgerWallet.Name) name := strings.TrimSpace(sr.LedgerWallet.Name)
var description *string var description *string
@@ -357,26 +354,47 @@ func (a *AccountAPI) openOrgLedgerAccount(ctx context.Context, org *model.Organi
} }
} }
resp, err := a.ledgerClient.CreateAccount(ctx, &ledgerv1.CreateAccountRequest{ currencies := []string{"RUB", "USDT"}
OrganizationRef: org.ID.Hex(), if chainTokenCurrency := strings.ToUpper(strings.TrimSpace(a.chainAsset.GetTokenSymbol())); chainTokenCurrency != "" {
AccountType: ledgerv1.AccountType_ACCOUNT_TYPE_ASSET, currencies = append(currencies, chainTokenCurrency)
Currency: currency, }
Status: ledgerv1.AccountStatus_ACCOUNT_STATUS_ACTIVE,
Role: ledgerv1.AccountRole_ACCOUNT_ROLE_OPERATING, seen := make(map[string]struct{}, len(currencies))
Metadata: map[string]string{ for _, currency := range currencies {
"source": "signup", currency = strings.ToUpper(strings.TrimSpace(currency))
"login": sr.Account.Login, if currency == "" {
}, continue
Describable: describable, }
}) if _, exists := seen[currency]; exists {
if err != nil { continue
a.logger.Warn("Failed to create ledger account for organization", zap.Error(err), mzap.StorableRef(org)) }
return err seen[currency] = struct{}{}
}
if resp == nil || resp.GetAccount() == nil || strings.TrimSpace(resp.GetAccount().GetLedgerAccountRef()) == "" { resp, err := a.ledgerClient.CreateAccount(ctx, &ledgerv1.CreateAccountRequest{
return merrors.Internal("ledger returned empty account reference") OrganizationRef: org.ID.Hex(),
AccountType: ledgerv1.AccountType_ACCOUNT_TYPE_ASSET,
Currency: currency,
Status: ledgerv1.AccountStatus_ACCOUNT_STATUS_ACTIVE,
Role: ledgerv1.AccountRole_ACCOUNT_ROLE_OPERATING,
Metadata: map[string]string{
"source": "signup",
"login": sr.Account.Login,
},
Describable: describable,
})
if err != nil {
a.logger.Warn("Failed to create ledger account for organization", zap.Error(err), mzap.StorableRef(org), zap.String("currency", currency))
return err
}
if resp == nil || resp.GetAccount() == nil || strings.TrimSpace(resp.GetAccount().GetLedgerAccountRef()) == "" {
return merrors.Internal("ledger returned empty account reference")
}
a.logger.Info("Ledger account created for organization",
mzap.StorableRef(org),
zap.String("currency", currency),
zap.String("ledger_account_ref", resp.GetAccount().GetLedgerAccountRef()))
} }
a.logger.Info("Ledger account created for organization", mzap.StorableRef(org), zap.String("ledger_account_ref", resp.GetAccount().GetLedgerAccountRef()))
return nil return nil
} }

View File

@@ -16,13 +16,13 @@ import (
) )
type stubLedgerAccountClient struct { type stubLedgerAccountClient struct {
createReq *ledgerv1.CreateAccountRequest createReqs []*ledgerv1.CreateAccountRequest
createResp *ledgerv1.CreateAccountResponse createResp *ledgerv1.CreateAccountResponse
createErr error createErr error
} }
func (s *stubLedgerAccountClient) CreateAccount(_ context.Context, req *ledgerv1.CreateAccountRequest) (*ledgerv1.CreateAccountResponse, error) { func (s *stubLedgerAccountClient) CreateAccount(_ context.Context, req *ledgerv1.CreateAccountRequest) (*ledgerv1.CreateAccountResponse, error) {
s.createReq = req s.createReqs = append(s.createReqs, req)
return s.createResp, s.createErr return s.createResp, s.createErr
} }
@@ -31,7 +31,7 @@ func (s *stubLedgerAccountClient) Close() error {
} }
func TestOpenOrgLedgerAccount(t *testing.T) { func TestOpenOrgLedgerAccount(t *testing.T) {
t.Run("creates operating ledger account", func(t *testing.T) { t.Run("creates operating ledger accounts for RUB and USDT", func(t *testing.T) {
desc := " Main org ledger account " desc := " Main org ledger account "
sr := &srequest.Signup{ sr := &srequest.Signup{
Account: model.AccountData{ Account: model.AccountData{
@@ -65,22 +65,26 @@ func TestOpenOrgLedgerAccount(t *testing.T) {
err := api.openOrgLedgerAccount(context.Background(), org, sr) err := api.openOrgLedgerAccount(context.Background(), org, sr)
assert.NoError(t, err) assert.NoError(t, err)
if assert.NotNil(t, ledgerStub.createReq) { if assert.Len(t, ledgerStub.createReqs, 2) {
assert.Equal(t, org.ID.Hex(), ledgerStub.createReq.GetOrganizationRef()) currencies := make([]string, 0, len(ledgerStub.createReqs))
assert.Equal(t, "RUB", ledgerStub.createReq.GetCurrency()) for _, req := range ledgerStub.createReqs {
assert.Equal(t, ledgerv1.AccountType_ACCOUNT_TYPE_ASSET, ledgerStub.createReq.GetAccountType()) currencies = append(currencies, req.GetCurrency())
assert.Equal(t, ledgerv1.AccountStatus_ACCOUNT_STATUS_ACTIVE, ledgerStub.createReq.GetStatus()) assert.Equal(t, org.ID.Hex(), req.GetOrganizationRef())
assert.Equal(t, ledgerv1.AccountRole_ACCOUNT_ROLE_OPERATING, ledgerStub.createReq.GetRole()) assert.Equal(t, ledgerv1.AccountType_ACCOUNT_TYPE_ASSET, req.GetAccountType())
assert.Equal(t, map[string]string{ assert.Equal(t, ledgerv1.AccountStatus_ACCOUNT_STATUS_ACTIVE, req.GetStatus())
"source": "signup", assert.Equal(t, ledgerv1.AccountRole_ACCOUNT_ROLE_OPERATING, req.GetRole())
"login": "owner@example.com", assert.Equal(t, map[string]string{
}, ledgerStub.createReq.GetMetadata()) "source": "signup",
if assert.NotNil(t, ledgerStub.createReq.GetDescribable()) { "login": "owner@example.com",
assert.Equal(t, "Primary Ledger", ledgerStub.createReq.GetDescribable().GetName()) }, req.GetMetadata())
if assert.NotNil(t, ledgerStub.createReq.GetDescribable().Description) { if assert.NotNil(t, req.GetDescribable()) {
assert.Equal(t, "Main org ledger account", ledgerStub.createReq.GetDescribable().GetDescription()) assert.Equal(t, "Primary Ledger", req.GetDescribable().GetName())
if assert.NotNil(t, req.GetDescribable().Description) {
assert.Equal(t, "Main org ledger account", req.GetDescribable().GetDescription())
}
} }
} }
assert.ElementsMatch(t, []string{"RUB", "USDT"}, currencies)
} }
}) })