327 lines
9.9 KiB
Go
327 lines
9.9 KiB
Go
package paymentapiimp
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/tech/sendico/pkg/merrors"
|
|
"github.com/tech/sendico/pkg/model"
|
|
fxv1 "github.com/tech/sendico/pkg/proto/common/fx/v1"
|
|
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
|
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
|
orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestrator/v1"
|
|
"github.com/tech/sendico/server/interface/api/srequest"
|
|
)
|
|
|
|
func mapPaymentIntent(intent *srequest.PaymentIntent) (*orchestratorv1.PaymentIntent, error) {
|
|
if intent == nil {
|
|
return nil, merrors.InvalidArgument("intent is required")
|
|
}
|
|
|
|
kind, err := mapPaymentKind(intent.Kind)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
settlementMode, err := mapSettlementMode(intent.SettlementMode)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
source, err := mapPaymentEndpoint(intent.Source, "source")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
destination, err := mapPaymentEndpoint(intent.Destination, "destination")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
fx, err := mapFXIntent(intent.FX)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &orchestratorv1.PaymentIntent{
|
|
Kind: kind,
|
|
Source: source,
|
|
Destination: destination,
|
|
Amount: mapMoney(intent.Amount),
|
|
RequiresFx: fx != nil,
|
|
Fx: fx,
|
|
SettlementMode: settlementMode,
|
|
Attributes: copyStringMap(intent.Attributes),
|
|
Customer: mapCustomer(intent.Customer),
|
|
}, nil
|
|
}
|
|
|
|
func mapPaymentEndpoint(endpoint *srequest.Endpoint, field string) (*orchestratorv1.PaymentEndpoint, error) {
|
|
if endpoint == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
var result orchestratorv1.PaymentEndpoint
|
|
switch endpoint.Type {
|
|
case srequest.EndpointTypeLedger:
|
|
payload, err := endpoint.DecodeLedger()
|
|
if err != nil {
|
|
return nil, merrors.InvalidArgument(field + " endpoint: " + err.Error())
|
|
}
|
|
result.Endpoint = &orchestratorv1.PaymentEndpoint_Ledger{
|
|
Ledger: mapLedgerEndpoint(&payload),
|
|
}
|
|
case srequest.EndpointTypeManagedWallet:
|
|
payload, err := endpoint.DecodeManagedWallet()
|
|
if err != nil {
|
|
return nil, merrors.InvalidArgument(field + " endpoint: " + err.Error())
|
|
}
|
|
mw, err := mapManagedWalletEndpoint(&payload)
|
|
if err != nil {
|
|
return nil, merrors.InvalidArgument(field + " endpoint: " + err.Error())
|
|
}
|
|
result.Endpoint = &orchestratorv1.PaymentEndpoint_ManagedWallet{
|
|
ManagedWallet: mw,
|
|
}
|
|
case srequest.EndpointTypeExternalChain:
|
|
payload, err := endpoint.DecodeExternalChain()
|
|
if err != nil {
|
|
return nil, merrors.InvalidArgument(field + " endpoint: " + err.Error())
|
|
}
|
|
ext, err := mapExternalChainEndpoint(&payload)
|
|
if err != nil {
|
|
return nil, merrors.InvalidArgument(field + " endpoint: " + err.Error())
|
|
}
|
|
result.Endpoint = &orchestratorv1.PaymentEndpoint_ExternalChain{
|
|
ExternalChain: ext,
|
|
}
|
|
case srequest.EndpointTypeCard:
|
|
payload, err := endpoint.DecodeCard()
|
|
if err != nil {
|
|
return nil, merrors.InvalidArgument(field + " endpoint: " + err.Error())
|
|
}
|
|
result.Endpoint = &orchestratorv1.PaymentEndpoint_Card{
|
|
Card: mapCardEndpoint(&payload),
|
|
}
|
|
case srequest.EndpointTypeCardToken:
|
|
payload, err := endpoint.DecodeCardToken()
|
|
if err != nil {
|
|
return nil, merrors.InvalidArgument(field + " endpoint: " + err.Error())
|
|
}
|
|
result.Endpoint = &orchestratorv1.PaymentEndpoint_Card{
|
|
Card: mapCardTokenEndpoint(&payload),
|
|
}
|
|
case "":
|
|
return nil, merrors.InvalidArgument(field + " endpoint type is required")
|
|
default:
|
|
return nil, merrors.InvalidArgument(field + " endpoint has unsupported type: " + string(endpoint.Type))
|
|
}
|
|
|
|
result.Metadata = copyStringMap(endpoint.Metadata)
|
|
return &result, nil
|
|
}
|
|
|
|
func mapLedgerEndpoint(endpoint *srequest.LedgerEndpoint) *orchestratorv1.LedgerEndpoint {
|
|
if endpoint == nil {
|
|
return nil
|
|
}
|
|
return &orchestratorv1.LedgerEndpoint{
|
|
LedgerAccountRef: endpoint.LedgerAccountRef,
|
|
ContraLedgerAccountRef: endpoint.ContraLedgerAccountRef,
|
|
}
|
|
}
|
|
|
|
func mapManagedWalletEndpoint(endpoint *srequest.ManagedWalletEndpoint) (*orchestratorv1.ManagedWalletEndpoint, error) {
|
|
if endpoint == nil {
|
|
return nil, nil
|
|
}
|
|
asset, err := mapAsset(endpoint.Asset)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &orchestratorv1.ManagedWalletEndpoint{
|
|
ManagedWalletRef: endpoint.ManagedWalletRef,
|
|
Asset: asset,
|
|
}, nil
|
|
}
|
|
|
|
func mapExternalChainEndpoint(endpoint *srequest.ExternalChainEndpoint) (*orchestratorv1.ExternalChainEndpoint, error) {
|
|
if endpoint == nil {
|
|
return nil, nil
|
|
}
|
|
asset, err := mapAsset(endpoint.Asset)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &orchestratorv1.ExternalChainEndpoint{
|
|
Asset: asset,
|
|
Address: endpoint.Address,
|
|
Memo: endpoint.Memo,
|
|
}, nil
|
|
}
|
|
|
|
func mapAsset(asset *srequest.Asset) (*chainv1.Asset, error) {
|
|
if asset == nil {
|
|
return nil, nil
|
|
}
|
|
chain, err := mapChainNetwork(asset.Chain)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &chainv1.Asset{
|
|
Chain: chain,
|
|
TokenSymbol: asset.TokenSymbol,
|
|
ContractAddress: asset.ContractAddress,
|
|
}, nil
|
|
}
|
|
|
|
func mapMoney(m *model.Money) *moneyv1.Money {
|
|
if m == nil {
|
|
return nil
|
|
}
|
|
return &moneyv1.Money{
|
|
Amount: m.Amount,
|
|
Currency: m.Currency,
|
|
}
|
|
}
|
|
|
|
func mapFXIntent(fx *srequest.FXIntent) (*orchestratorv1.FXIntent, error) {
|
|
if fx == nil {
|
|
return nil, nil
|
|
}
|
|
side, err := mapFXSide(fx.Side)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &orchestratorv1.FXIntent{
|
|
Pair: mapCurrencyPair(fx.Pair),
|
|
Side: side,
|
|
Firm: fx.Firm,
|
|
TtlMs: fx.TTLms,
|
|
PreferredProvider: fx.PreferredProvider,
|
|
MaxAgeMs: fx.MaxAgeMs,
|
|
}, nil
|
|
}
|
|
|
|
func mapCustomer(customer *srequest.Customer) *orchestratorv1.Customer {
|
|
if customer == nil {
|
|
return nil
|
|
}
|
|
return &orchestratorv1.Customer{
|
|
Id: strings.TrimSpace(customer.ID),
|
|
FirstName: strings.TrimSpace(customer.FirstName),
|
|
MiddleName: strings.TrimSpace(customer.MiddleName),
|
|
LastName: strings.TrimSpace(customer.LastName),
|
|
Ip: strings.TrimSpace(customer.IP),
|
|
Zip: strings.TrimSpace(customer.Zip),
|
|
Country: strings.TrimSpace(customer.Country),
|
|
State: strings.TrimSpace(customer.State),
|
|
City: strings.TrimSpace(customer.City),
|
|
Address: strings.TrimSpace(customer.Address),
|
|
}
|
|
}
|
|
|
|
func mapCurrencyPair(pair *srequest.CurrencyPair) *fxv1.CurrencyPair {
|
|
if pair == nil {
|
|
return nil
|
|
}
|
|
return &fxv1.CurrencyPair{
|
|
Base: pair.Base,
|
|
Quote: pair.Quote,
|
|
}
|
|
}
|
|
|
|
func mapCardEndpoint(card *srequest.CardEndpoint) *orchestratorv1.CardEndpoint {
|
|
if card == nil {
|
|
return nil
|
|
}
|
|
result := &orchestratorv1.CardEndpoint{
|
|
CardholderName: strings.TrimSpace(card.FirstName),
|
|
CardholderSurname: strings.TrimSpace(card.LastName),
|
|
ExpMonth: card.ExpMonth,
|
|
ExpYear: card.ExpYear,
|
|
Country: strings.TrimSpace(card.Country),
|
|
}
|
|
if pan := strings.TrimSpace(card.Pan); pan != "" {
|
|
result.Card = &orchestratorv1.CardEndpoint_Pan{Pan: pan}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func mapCardTokenEndpoint(card *srequest.CardTokenEndpoint) *orchestratorv1.CardEndpoint {
|
|
if card == nil {
|
|
return nil
|
|
}
|
|
return &orchestratorv1.CardEndpoint{
|
|
Card: &orchestratorv1.CardEndpoint_Token{Token: strings.TrimSpace(card.Token)},
|
|
MaskedPan: strings.TrimSpace(card.MaskedPan),
|
|
}
|
|
}
|
|
|
|
func mapPaymentKind(kind srequest.PaymentKind) (orchestratorv1.PaymentKind, error) {
|
|
switch strings.TrimSpace(string(kind)) {
|
|
case "", string(srequest.PaymentKindUnspecified):
|
|
return orchestratorv1.PaymentKind_PAYMENT_KIND_UNSPECIFIED, nil
|
|
case string(srequest.PaymentKindPayout):
|
|
return orchestratorv1.PaymentKind_PAYMENT_KIND_PAYOUT, nil
|
|
case string(srequest.PaymentKindInternalTransfer):
|
|
return orchestratorv1.PaymentKind_PAYMENT_KIND_INTERNAL_TRANSFER, nil
|
|
case string(srequest.PaymentKindFxConversion):
|
|
return orchestratorv1.PaymentKind_PAYMENT_KIND_FX_CONVERSION, nil
|
|
default:
|
|
return orchestratorv1.PaymentKind_PAYMENT_KIND_UNSPECIFIED, merrors.InvalidArgument("unsupported payment kind: " + string(kind))
|
|
}
|
|
}
|
|
|
|
func mapSettlementMode(mode srequest.SettlementMode) (orchestratorv1.SettlementMode, error) {
|
|
switch strings.TrimSpace(string(mode)) {
|
|
case "", string(srequest.SettlementModeUnspecified):
|
|
return orchestratorv1.SettlementMode_SETTLEMENT_MODE_UNSPECIFIED, nil
|
|
case string(srequest.SettlementModeFixSource):
|
|
return orchestratorv1.SettlementMode_SETTLEMENT_MODE_FIX_SOURCE, nil
|
|
case string(srequest.SettlementModeFixReceived):
|
|
return orchestratorv1.SettlementMode_SETTLEMENT_MODE_FIX_RECEIVED, nil
|
|
default:
|
|
return orchestratorv1.SettlementMode_SETTLEMENT_MODE_UNSPECIFIED, merrors.InvalidArgument("unsupported settlement mode: " + string(mode))
|
|
}
|
|
}
|
|
|
|
func mapFXSide(side srequest.FXSide) (fxv1.Side, error) {
|
|
switch strings.TrimSpace(string(side)) {
|
|
case "", string(srequest.FXSideUnspecified):
|
|
return fxv1.Side_SIDE_UNSPECIFIED, nil
|
|
case string(srequest.FXSideBuyBaseSellQuote):
|
|
return fxv1.Side_BUY_BASE_SELL_QUOTE, nil
|
|
case string(srequest.FXSideSellBaseBuyQuote):
|
|
return fxv1.Side_SELL_BASE_BUY_QUOTE, nil
|
|
default:
|
|
return fxv1.Side_SIDE_UNSPECIFIED, merrors.InvalidArgument("unsupported fx side: " + string(side))
|
|
}
|
|
}
|
|
|
|
func mapChainNetwork(chain srequest.ChainNetwork) (chainv1.ChainNetwork, error) {
|
|
switch strings.TrimSpace(string(chain)) {
|
|
case "", string(srequest.ChainNetworkUnspecified):
|
|
return chainv1.ChainNetwork_CHAIN_NETWORK_UNSPECIFIED, nil
|
|
case string(srequest.ChainNetworkEthereumMainnet):
|
|
return chainv1.ChainNetwork_CHAIN_NETWORK_ETHEREUM_MAINNET, nil
|
|
case string(srequest.ChainNetworkArbitrumOne):
|
|
return chainv1.ChainNetwork_CHAIN_NETWORK_ARBITRUM_ONE, nil
|
|
case string(srequest.ChainNetworkTronMainnet):
|
|
return chainv1.ChainNetwork_CHAIN_NETWORK_TRON_MAINNET, nil
|
|
case string(srequest.ChainNetworkTronNile):
|
|
return chainv1.ChainNetwork_CHAIN_NETWORK_TRON_NILE, nil
|
|
default:
|
|
return chainv1.ChainNetwork_CHAIN_NETWORK_UNSPECIFIED, merrors.InvalidArgument("unsupported chain network: " + string(chain))
|
|
}
|
|
}
|
|
|
|
func copyStringMap(src map[string]string) map[string]string {
|
|
if len(src) == 0 {
|
|
return nil
|
|
}
|
|
dst := make(map[string]string, len(src))
|
|
for k, v := range src {
|
|
dst[k] = v
|
|
}
|
|
return dst
|
|
}
|