refactored payment orchestration

This commit is contained in:
Stephan D
2026-02-03 00:40:46 +01:00
parent 05d998e0f7
commit 5e87e2f2f9
184 changed files with 3920 additions and 2219 deletions

View File

@@ -26,8 +26,8 @@ func resolveDestination(ctx context.Context, deps Deps, dest *chainv1.TransferDe
deps.Logger.Warn("Destination wallet lookup failed", zap.Error(err), zap.String("managed_wallet_ref", managedRef))
return model.TransferDestination{}, err
}
if !strings.EqualFold(wallet.Network, source.Network) {
deps.Logger.Warn("Destination wallet network mismatch", zap.String("source_network", source.Network), zap.String("dest_network", wallet.Network))
if wallet.Network != source.Network {
deps.Logger.Warn("Destination wallet network mismatch", zap.String("source_network", string(source.Network)), zap.String("dest_network", string(wallet.Network)))
return model.TransferDestination{}, merrors.InvalidArgument("destination wallet network mismatch")
}
if strings.TrimSpace(wallet.DepositAddress) == "" {
@@ -44,12 +44,12 @@ func resolveDestination(ctx context.Context, deps Deps, dest *chainv1.TransferDe
return model.TransferDestination{}, merrors.InvalidArgument("destination is required")
}
if deps.Drivers == nil {
deps.Logger.Warn("Chain drivers missing", zap.String("network", source.Network))
deps.Logger.Warn("Chain drivers missing", zap.String("network", string(source.Network)))
return model.TransferDestination{}, merrors.Internal("chain drivers not configured")
}
chainDriver, err := deps.Drivers.Driver(source.Network)
if err != nil {
deps.Logger.Warn("Unsupported chain driver", zap.String("network", source.Network), zap.Error(err))
deps.Logger.Warn("Unsupported chain driver", zap.String("network", string(source.Network)), zap.Error(err))
return model.TransferDestination{}, merrors.InvalidArgument("unsupported chain for wallet")
}
normalized, err := chainDriver.NormalizeAddress(external)

View File

@@ -53,19 +53,18 @@ func (c *estimateTransferFeeCommand) Execute(ctx context.Context, req *chainv1.E
return gsresponse.Auto[chainv1.EstimateTransferFeeResponse](c.deps.Logger, mservice.ChainGateway, err)
}
networkKey := strings.ToLower(strings.TrimSpace(sourceWallet.Network))
networkCfg, ok := c.deps.Networks.Network(networkKey)
networkCfg, ok := c.deps.Networks.Network(sourceWallet.Network)
if !ok {
c.deps.Logger.Warn("Unsupported chain", zap.String("network", networkKey))
c.deps.Logger.Warn("Unsupported chain", zap.String("network", string(sourceWallet.Network)))
return gsresponse.InvalidArgument[chainv1.EstimateTransferFeeResponse](c.deps.Logger, mservice.ChainGateway, merrors.InvalidArgument("unsupported chain for wallet"))
}
if c.deps.Drivers == nil {
c.deps.Logger.Warn("Chain drivers missing", zap.String("network", networkKey))
c.deps.Logger.Warn("Chain drivers missing", zap.String("network", string(sourceWallet.Network)))
return gsresponse.Internal[chainv1.EstimateTransferFeeResponse](c.deps.Logger, mservice.ChainGateway, merrors.Internal("chain drivers not configured"))
}
chainDriver, err := c.deps.Drivers.Driver(networkKey)
chainDriver, err := c.deps.Drivers.Driver(sourceWallet.Network)
if err != nil {
c.deps.Logger.Warn("Unsupported chain driver", zap.String("network", networkKey), zap.Error(err))
c.deps.Logger.Warn("Unsupported chain driver", zap.String("network", string(sourceWallet.Network)), zap.Error(err))
return gsresponse.InvalidArgument[chainv1.EstimateTransferFeeResponse](c.deps.Logger, mservice.ChainGateway, merrors.InvalidArgument("unsupported chain for wallet"))
}

View File

@@ -125,9 +125,9 @@ func (c *ensureGasTopUpCommand) Execute(ctx context.Context, req *chainv1.Ensure
Destination: &chainv1.TransferDestination{
Destination: &chainv1.TransferDestination_ManagedWalletRef{ManagedWalletRef: targetWalletRef},
},
Amount: topUp,
Metadata: shared.CloneMetadata(req.GetMetadata()),
ClientReference: strings.TrimSpace(req.GetClientReference()),
Amount: topUp,
Metadata: shared.CloneMetadata(req.GetMetadata()),
PaymentRef: strings.TrimSpace(req.GetPaymentRef()),
}
submitResponder := NewSubmitTransfer(c.deps.WithLogger("transfer.submit")).Execute(ctx, submitReq)
@@ -152,12 +152,7 @@ func computeGasTopUp(ctx context.Context, deps Deps, walletRef string, estimated
return nil, false, nil, nil, err
}
networkKey := strings.ToLower(strings.TrimSpace(walletModel.Network))
if strings.HasPrefix(networkKey, "tron") {
return nil, false, nil, nil, merrors.InvalidArgument("tron networks must use the tron gateway")
}
networkCfg, ok := deps.Networks.Network(networkKey)
networkCfg, ok := deps.Networks.Network(walletModel.Network)
if !ok {
return nil, false, nil, nil, merrors.InvalidArgument("unsupported chain for wallet")
}
@@ -248,7 +243,7 @@ func logDecision(logger mlogger.Logger, walletRef string, estimatedFee *moneyv1.
zap.Bool("cap_hit", capHit),
}
if walletModel != nil {
fields = append(fields, zap.String("network", strings.TrimSpace(walletModel.Network)))
fields = append(fields, zap.String("network", string(walletModel.Network)))
}
logger.Info("Gas top-up decision", fields...)
}

View File

@@ -41,8 +41,8 @@ func toProtoTransfer(transfer *model.Transfer) *chainv1.Transfer {
SourceWalletRef: transfer.SourceWalletRef,
Destination: destination,
Asset: asset,
RequestedAmount: shared.CloneMoney(transfer.RequestedAmount),
NetAmount: shared.CloneMoney(transfer.NetAmount),
RequestedAmount: shared.MonenyToProto(transfer.RequestedAmount),
NetAmount: shared.MonenyToProto(transfer.NetAmount),
Fees: protoFees,
Status: shared.TransferStatusToProto(transfer.Status),
TransactionHash: transfer.TxHash,

View File

@@ -77,10 +77,9 @@ func (c *submitTransferCommand) Execute(ctx context.Context, req *chainv1.Submit
c.deps.Logger.Warn("Organization mismatch", zap.String("wallet_org", sourceWallet.OrganizationRef), zap.String("req_org", organizationRef))
return gsresponse.InvalidArgument[chainv1.SubmitTransferResponse](c.deps.Logger, mservice.ChainGateway, merrors.InvalidArgument("organization_ref mismatch with wallet"))
}
networkKey := strings.ToLower(strings.TrimSpace(sourceWallet.Network))
networkCfg, ok := c.deps.Networks.Network(networkKey)
networkCfg, ok := c.deps.Networks.Network(sourceWallet.Network)
if !ok {
c.deps.Logger.Warn("Unsupported chain", zap.String("network", networkKey))
c.deps.Logger.Warn("Unsupported chain", zap.String("network", string(sourceWallet.Network)))
return gsresponse.InvalidArgument[chainv1.SubmitTransferResponse](c.deps.Logger, mservice.ChainGateway, merrors.InvalidArgument("unsupported chain for wallet"))
}
@@ -124,17 +123,19 @@ func (c *submitTransferCommand) Execute(ctx context.Context, req *chainv1.Submit
transfer := &model.Transfer{
IdempotencyKey: idempotencyKey,
TransferRef: shared.GenerateTransferRef(),
IntentRef: req.IntentRef,
OperationRef: req.OperationRef,
OrganizationRef: organizationRef,
SourceWalletRef: sourceWalletRef,
Destination: destination,
Network: sourceWallet.Network,
TokenSymbol: effectiveTokenSymbol,
ContractAddress: effectiveContractAddress,
RequestedAmount: shared.CloneMoney(amount),
NetAmount: netAmount,
RequestedAmount: shared.ProtoToMoney(amount),
NetAmount: shared.ProtoToMoney(netAmount),
Fees: fees,
Status: model.TransferStatusPending,
ClientReference: strings.TrimSpace(req.GetClientReference()),
Status: model.TransferStatusCreated,
PaymentRef: strings.TrimSpace(req.GetPaymentRef()),
LastStatusAt: c.deps.Clock.Now().UTC(),
}

View File

@@ -51,23 +51,19 @@ func (c *createManagedWalletCommand) Execute(ctx context.Context, req *chainv1.C
return gsresponse.InvalidArgument[chainv1.CreateManagedWalletResponse](c.deps.Logger, mservice.ChainGateway, merrors.InvalidArgument("asset is required"))
}
chainKey, _ := shared.ChainKeyFromEnum(asset.GetChain())
if chainKey == "" {
c.deps.Logger.Warn("Unsupported chain", zap.Any("chain", asset.GetChain()))
return gsresponse.InvalidArgument[chainv1.CreateManagedWalletResponse](c.deps.Logger, mservice.ChainGateway, merrors.InvalidArgument("unsupported chain"))
}
chainKey := shared.ChainKeyFromEnum(asset.GetChain())
networkCfg, ok := c.deps.Networks.Network(chainKey)
if !ok {
c.deps.Logger.Warn("Unsupported chain in config", zap.String("chain", chainKey))
c.deps.Logger.Warn("Unsupported chain in config", zap.String("chain", string(chainKey)))
return gsresponse.InvalidArgument[chainv1.CreateManagedWalletResponse](c.deps.Logger, mservice.ChainGateway, merrors.InvalidArgument("unsupported chain"))
}
if c.deps.Drivers == nil {
c.deps.Logger.Warn("Chain drivers missing", zap.String("chain", chainKey))
c.deps.Logger.Warn("Chain drivers missing", zap.String("chain", string(chainKey)))
return gsresponse.Internal[chainv1.CreateManagedWalletResponse](c.deps.Logger, mservice.ChainGateway, merrors.Internal("chain drivers not configured"))
}
chainDriver, err := c.deps.Drivers.Driver(chainKey)
if err != nil {
c.deps.Logger.Warn("Unsupported chain driver", zap.String("chain", chainKey), zap.Error(err))
c.deps.Logger.Warn("Unsupported chain driver", zap.String("chain", string(chainKey)), zap.Error(err))
return gsresponse.InvalidArgument[chainv1.CreateManagedWalletResponse](c.deps.Logger, mservice.ChainGateway, merrors.InvalidArgument("unsupported chain"))
}
@@ -81,7 +77,7 @@ func (c *createManagedWalletCommand) Execute(ctx context.Context, req *chainv1.C
if !strings.EqualFold(tokenSymbol, networkCfg.NativeToken) {
contractAddress = shared.ResolveContractAddress(networkCfg.TokenConfigs, tokenSymbol)
if contractAddress == "" {
c.deps.Logger.Warn("Unsupported token", zap.String("token", tokenSymbol), zap.String("chain", chainKey))
c.deps.Logger.Warn("Unsupported token", zap.String("token", tokenSymbol), zap.String("chain", string(chainKey)))
return gsresponse.InvalidArgument[chainv1.CreateManagedWalletResponse](c.deps.Logger, mservice.ChainGateway, merrors.InvalidArgument("unsupported token for chain"))
}
}

View File

@@ -34,7 +34,7 @@ func (c *listManagedWalletsCommand) Execute(ctx context.Context, req *chainv1.Li
filter.OwnerRefFilter = &ownerRef
}
if asset := req.GetAsset(); asset != nil {
filter.Network, _ = shared.ChainKeyFromEnum(asset.GetChain())
filter.Network = shared.ChainKeyFromEnum(asset.GetChain())
filter.TokenSymbol = strings.TrimSpace(asset.GetTokenSymbol())
}
if page := req.GetPage(); page != nil {

View File

@@ -3,7 +3,6 @@ package wallet
import (
"context"
"fmt"
"strings"
"github.com/tech/sendico/gateway/chain/internal/service/gateway/driver"
"github.com/tech/sendico/gateway/chain/storage/model"
@@ -24,21 +23,20 @@ func OnChainWalletBalances(ctx context.Context, deps Deps, wallet *model.Managed
return nil, nil, merrors.Internal("chain drivers not configured")
}
networkKey := strings.ToLower(strings.TrimSpace(wallet.Network))
network, ok := deps.Networks.Network(networkKey)
network, ok := deps.Networks.Network(wallet.Network)
if !ok {
logger.Warn("Requested network is not configured",
zap.String("wallet_ref", wallet.WalletRef),
zap.String("network", networkKey),
zap.String("network", string(wallet.Network)),
)
return nil, nil, merrors.Internal(fmt.Sprintf("Requested network '%s' is not configured", networkKey))
return nil, nil, merrors.Internal(fmt.Sprintf("Requested network '%s' is not configured", wallet.Network))
}
chainDriver, err := deps.Drivers.Driver(networkKey)
chainDriver, err := deps.Drivers.Driver(wallet.Network)
if err != nil {
logger.Warn("Chain driver not configured",
zap.String("wallet_ref", wallet.WalletRef),
zap.String("network", networkKey),
zap.String("network", string(wallet.Network)),
zap.Error(err),
)
return nil, nil, merrors.InvalidArgument("unsupported chain")