948 lines
31 KiB
Go
948 lines
31 KiB
Go
package orchestrator
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/tech/sendico/payments/storage/model"
|
|
chainasset "github.com/tech/sendico/pkg/chain"
|
|
paymenttypes "github.com/tech/sendico/pkg/payments/types"
|
|
feesv1 "github.com/tech/sendico/pkg/proto/billing/fees/v1"
|
|
accountingv1 "github.com/tech/sendico/pkg/proto/common/accounting/v1"
|
|
fxv1 "github.com/tech/sendico/pkg/proto/common/fx/v1"
|
|
gatewayv1 "github.com/tech/sendico/pkg/proto/common/gateway/v1"
|
|
moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
|
|
chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
|
|
oraclev1 "github.com/tech/sendico/pkg/proto/oracle/v1"
|
|
orchestratorv1 "github.com/tech/sendico/pkg/proto/payments/orchestrator/v1"
|
|
"google.golang.org/protobuf/types/known/timestamppb"
|
|
)
|
|
|
|
func intentFromProto(src *orchestratorv1.PaymentIntent) model.PaymentIntent {
|
|
if src == nil {
|
|
return model.PaymentIntent{}
|
|
}
|
|
intent := model.PaymentIntent{
|
|
Ref: src.GetRef(),
|
|
Kind: modelKindFromProto(src.GetKind()),
|
|
Source: endpointFromProto(src.GetSource()),
|
|
Destination: endpointFromProto(src.GetDestination()),
|
|
Amount: moneyFromProto(src.GetAmount()),
|
|
RequiresFX: src.GetRequiresFx(),
|
|
FeePolicy: feePolicyFromProto(src.GetFeePolicy()),
|
|
SettlementMode: settlementModeFromProto(src.GetSettlementMode()),
|
|
SettlementCurrency: strings.TrimSpace(src.GetSettlementCurrency()),
|
|
Attributes: cloneMetadata(src.GetAttributes()),
|
|
Customer: customerFromProto(src.GetCustomer()),
|
|
}
|
|
if src.GetFx() != nil {
|
|
intent.FX = fxIntentFromProto(src.GetFx())
|
|
}
|
|
return intent
|
|
}
|
|
|
|
func endpointFromProto(src *orchestratorv1.PaymentEndpoint) model.PaymentEndpoint {
|
|
if src == nil {
|
|
return model.PaymentEndpoint{Type: model.EndpointTypeUnspecified}
|
|
}
|
|
result := model.PaymentEndpoint{
|
|
Type: model.EndpointTypeUnspecified,
|
|
InstanceID: strings.TrimSpace(src.GetInstanceId()),
|
|
Metadata: cloneMetadata(src.GetMetadata()),
|
|
}
|
|
if ledger := src.GetLedger(); ledger != nil {
|
|
result.Type = model.EndpointTypeLedger
|
|
result.Ledger = &model.LedgerEndpoint{
|
|
LedgerAccountRef: strings.TrimSpace(ledger.GetLedgerAccountRef()),
|
|
ContraLedgerAccountRef: strings.TrimSpace(ledger.GetContraLedgerAccountRef()),
|
|
}
|
|
return result
|
|
}
|
|
if managed := src.GetManagedWallet(); managed != nil {
|
|
result.Type = model.EndpointTypeManagedWallet
|
|
result.ManagedWallet = &model.ManagedWalletEndpoint{
|
|
ManagedWalletRef: strings.TrimSpace(managed.GetManagedWalletRef()),
|
|
Asset: assetFromProto(managed.GetAsset()),
|
|
}
|
|
return result
|
|
}
|
|
if external := src.GetExternalChain(); external != nil {
|
|
result.Type = model.EndpointTypeExternalChain
|
|
result.ExternalChain = &model.ExternalChainEndpoint{
|
|
Asset: assetFromProto(external.GetAsset()),
|
|
Address: strings.TrimSpace(external.GetAddress()),
|
|
Memo: strings.TrimSpace(external.GetMemo()),
|
|
}
|
|
return result
|
|
}
|
|
if card := src.GetCard(); card != nil {
|
|
result.Type = model.EndpointTypeCard
|
|
result.Card = &model.CardEndpoint{
|
|
Pan: strings.TrimSpace(card.GetPan()),
|
|
Token: strings.TrimSpace(card.GetToken()),
|
|
Cardholder: strings.TrimSpace(card.GetCardholderName()),
|
|
CardholderSurname: strings.TrimSpace(card.GetCardholderSurname()),
|
|
ExpMonth: card.GetExpMonth(),
|
|
ExpYear: card.GetExpYear(),
|
|
Country: strings.TrimSpace(card.GetCountry()),
|
|
MaskedPan: strings.TrimSpace(card.GetMaskedPan()),
|
|
}
|
|
return result
|
|
}
|
|
return result
|
|
}
|
|
|
|
func fxIntentFromProto(src *orchestratorv1.FXIntent) *model.FXIntent {
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
return &model.FXIntent{
|
|
Pair: pairFromProto(src.GetPair()),
|
|
Side: fxSideFromProto(src.GetSide()),
|
|
Firm: src.GetFirm(),
|
|
TTLMillis: src.GetTtlMs(),
|
|
PreferredProvider: strings.TrimSpace(src.GetPreferredProvider()),
|
|
MaxAgeMillis: src.GetMaxAgeMs(),
|
|
}
|
|
}
|
|
|
|
func quoteSnapshotToModel(src *orchestratorv1.PaymentQuote) *model.PaymentQuoteSnapshot {
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
return &model.PaymentQuoteSnapshot{
|
|
DebitAmount: moneyFromProto(src.GetDebitAmount()),
|
|
DebitSettlementAmount: moneyFromProto(src.GetDebitSettlementAmount()),
|
|
ExpectedSettlementAmount: moneyFromProto(src.GetExpectedSettlementAmount()),
|
|
ExpectedFeeTotal: moneyFromProto(src.GetExpectedFeeTotal()),
|
|
FeeLines: feeLinesFromProto(src.GetFeeLines()),
|
|
FeeRules: feeRulesFromProto(src.GetFeeRules()),
|
|
FXQuote: fxQuoteFromProto(src.GetFxQuote()),
|
|
NetworkFee: networkFeeFromProto(src.GetNetworkFee()),
|
|
QuoteRef: strings.TrimSpace(src.GetQuoteRef()),
|
|
}
|
|
}
|
|
|
|
func toProtoPayment(src *model.Payment) *orchestratorv1.Payment {
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
payment := &orchestratorv1.Payment{
|
|
PaymentRef: src.PaymentRef,
|
|
IdempotencyKey: src.IdempotencyKey,
|
|
Intent: protoIntentFromModel(src.Intent),
|
|
State: protoStateFromModel(src.State),
|
|
FailureCode: protoFailureFromModel(src.FailureCode),
|
|
FailureReason: src.FailureReason,
|
|
LastQuote: modelQuoteToProto(src.LastQuote),
|
|
Execution: protoExecutionFromModel(src.Execution),
|
|
ExecutionPlan: protoExecutionPlanFromModel(src.ExecutionPlan),
|
|
PaymentPlan: protoPaymentPlanFromModel(src.PaymentPlan),
|
|
Metadata: cloneMetadata(src.Metadata),
|
|
}
|
|
if src.CardPayout != nil {
|
|
payment.CardPayout = &orchestratorv1.CardPayout{
|
|
PayoutRef: src.CardPayout.PayoutRef,
|
|
ProviderPaymentId: src.CardPayout.ProviderPaymentID,
|
|
Status: src.CardPayout.Status,
|
|
FailureReason: src.CardPayout.FailureReason,
|
|
CardCountry: src.CardPayout.CardCountry,
|
|
MaskedPan: src.CardPayout.MaskedPan,
|
|
ProviderCode: src.CardPayout.ProviderCode,
|
|
GatewayReference: src.CardPayout.GatewayReference,
|
|
}
|
|
}
|
|
if src.CreatedAt.IsZero() {
|
|
payment.CreatedAt = timestamppb.New(time.Now().UTC())
|
|
} else {
|
|
payment.CreatedAt = timestamppb.New(src.CreatedAt.UTC())
|
|
}
|
|
if src.UpdatedAt != (time.Time{}) {
|
|
payment.UpdatedAt = timestamppb.New(src.UpdatedAt.UTC())
|
|
}
|
|
return payment
|
|
}
|
|
|
|
func protoIntentFromModel(src model.PaymentIntent) *orchestratorv1.PaymentIntent {
|
|
intent := &orchestratorv1.PaymentIntent{
|
|
Ref: src.Ref,
|
|
Kind: protoKindFromModel(src.Kind),
|
|
Source: protoEndpointFromModel(src.Source),
|
|
Destination: protoEndpointFromModel(src.Destination),
|
|
Amount: protoMoney(src.Amount),
|
|
RequiresFx: src.RequiresFX,
|
|
FeePolicy: feePolicyToProto(src.FeePolicy),
|
|
SettlementMode: settlementModeToProto(src.SettlementMode),
|
|
SettlementCurrency: strings.TrimSpace(src.SettlementCurrency),
|
|
Attributes: cloneMetadata(src.Attributes),
|
|
Customer: protoCustomerFromModel(src.Customer),
|
|
}
|
|
if src.FX != nil {
|
|
intent.Fx = protoFXIntentFromModel(src.FX)
|
|
}
|
|
return intent
|
|
}
|
|
|
|
func customerFromProto(src *orchestratorv1.Customer) *model.Customer {
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
return &model.Customer{
|
|
ID: strings.TrimSpace(src.GetId()),
|
|
FirstName: strings.TrimSpace(src.GetFirstName()),
|
|
MiddleName: strings.TrimSpace(src.GetMiddleName()),
|
|
LastName: strings.TrimSpace(src.GetLastName()),
|
|
IP: strings.TrimSpace(src.GetIp()),
|
|
Zip: strings.TrimSpace(src.GetZip()),
|
|
Country: strings.TrimSpace(src.GetCountry()),
|
|
State: strings.TrimSpace(src.GetState()),
|
|
City: strings.TrimSpace(src.GetCity()),
|
|
Address: strings.TrimSpace(src.GetAddress()),
|
|
}
|
|
}
|
|
|
|
func protoCustomerFromModel(src *model.Customer) *orchestratorv1.Customer {
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
return &orchestratorv1.Customer{
|
|
Id: strings.TrimSpace(src.ID),
|
|
FirstName: strings.TrimSpace(src.FirstName),
|
|
MiddleName: strings.TrimSpace(src.MiddleName),
|
|
LastName: strings.TrimSpace(src.LastName),
|
|
Ip: strings.TrimSpace(src.IP),
|
|
Zip: strings.TrimSpace(src.Zip),
|
|
Country: strings.TrimSpace(src.Country),
|
|
State: strings.TrimSpace(src.State),
|
|
City: strings.TrimSpace(src.City),
|
|
Address: strings.TrimSpace(src.Address),
|
|
}
|
|
}
|
|
|
|
func protoEndpointFromModel(src model.PaymentEndpoint) *orchestratorv1.PaymentEndpoint {
|
|
endpoint := &orchestratorv1.PaymentEndpoint{
|
|
Metadata: cloneMetadata(src.Metadata),
|
|
InstanceId: strings.TrimSpace(src.InstanceID),
|
|
}
|
|
switch src.Type {
|
|
case model.EndpointTypeLedger:
|
|
if src.Ledger != nil {
|
|
endpoint.Endpoint = &orchestratorv1.PaymentEndpoint_Ledger{
|
|
Ledger: &orchestratorv1.LedgerEndpoint{
|
|
LedgerAccountRef: src.Ledger.LedgerAccountRef,
|
|
ContraLedgerAccountRef: src.Ledger.ContraLedgerAccountRef,
|
|
},
|
|
}
|
|
}
|
|
case model.EndpointTypeManagedWallet:
|
|
if src.ManagedWallet != nil {
|
|
endpoint.Endpoint = &orchestratorv1.PaymentEndpoint_ManagedWallet{
|
|
ManagedWallet: &orchestratorv1.ManagedWalletEndpoint{
|
|
ManagedWalletRef: src.ManagedWallet.ManagedWalletRef,
|
|
Asset: assetToProto(src.ManagedWallet.Asset),
|
|
},
|
|
}
|
|
}
|
|
case model.EndpointTypeExternalChain:
|
|
if src.ExternalChain != nil {
|
|
endpoint.Endpoint = &orchestratorv1.PaymentEndpoint_ExternalChain{
|
|
ExternalChain: &orchestratorv1.ExternalChainEndpoint{
|
|
Asset: assetToProto(src.ExternalChain.Asset),
|
|
Address: src.ExternalChain.Address,
|
|
Memo: src.ExternalChain.Memo,
|
|
},
|
|
}
|
|
}
|
|
case model.EndpointTypeCard:
|
|
if src.Card != nil {
|
|
card := &orchestratorv1.CardEndpoint{
|
|
CardholderName: src.Card.Cardholder,
|
|
CardholderSurname: src.Card.CardholderSurname,
|
|
ExpMonth: src.Card.ExpMonth,
|
|
ExpYear: src.Card.ExpYear,
|
|
Country: src.Card.Country,
|
|
MaskedPan: src.Card.MaskedPan,
|
|
}
|
|
if pan := strings.TrimSpace(src.Card.Pan); pan != "" {
|
|
card.Card = &orchestratorv1.CardEndpoint_Pan{Pan: pan}
|
|
}
|
|
if token := strings.TrimSpace(src.Card.Token); token != "" {
|
|
card.Card = &orchestratorv1.CardEndpoint_Token{Token: token}
|
|
}
|
|
endpoint.Endpoint = &orchestratorv1.PaymentEndpoint_Card{Card: card}
|
|
}
|
|
default:
|
|
// leave unspecified
|
|
}
|
|
return endpoint
|
|
}
|
|
|
|
func protoFXIntentFromModel(src *model.FXIntent) *orchestratorv1.FXIntent {
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
return &orchestratorv1.FXIntent{
|
|
Pair: pairToProto(src.Pair),
|
|
Side: fxSideToProto(src.Side),
|
|
Firm: src.Firm,
|
|
TtlMs: src.TTLMillis,
|
|
PreferredProvider: src.PreferredProvider,
|
|
MaxAgeMs: src.MaxAgeMillis,
|
|
}
|
|
}
|
|
|
|
func protoExecutionFromModel(src *model.ExecutionRefs) *orchestratorv1.ExecutionRefs {
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
return &orchestratorv1.ExecutionRefs{
|
|
DebitEntryRef: src.DebitEntryRef,
|
|
CreditEntryRef: src.CreditEntryRef,
|
|
FxEntryRef: src.FXEntryRef,
|
|
ChainTransferRef: src.ChainTransferRef,
|
|
CardPayoutRef: src.CardPayoutRef,
|
|
FeeTransferRef: src.FeeTransferRef,
|
|
}
|
|
}
|
|
|
|
func protoExecutionStepFromModel(src *model.ExecutionStep) *orchestratorv1.ExecutionStep {
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
return &orchestratorv1.ExecutionStep{
|
|
Code: src.Code,
|
|
Description: src.Description,
|
|
Amount: protoMoney(src.Amount),
|
|
NetworkFee: protoMoney(src.NetworkFee),
|
|
SourceWalletRef: src.SourceWalletRef,
|
|
DestinationRef: src.DestinationRef,
|
|
TransferRef: src.TransferRef,
|
|
Metadata: cloneMetadata(src.Metadata),
|
|
OperationRef: src.OperationRef,
|
|
}
|
|
}
|
|
|
|
func protoExecutionPlanFromModel(src *model.ExecutionPlan) *orchestratorv1.ExecutionPlan {
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
steps := make([]*orchestratorv1.ExecutionStep, 0, len(src.Steps))
|
|
for _, step := range src.Steps {
|
|
if protoStep := protoExecutionStepFromModel(step); protoStep != nil {
|
|
steps = append(steps, protoStep)
|
|
}
|
|
}
|
|
if len(steps) == 0 {
|
|
steps = nil
|
|
}
|
|
return &orchestratorv1.ExecutionPlan{
|
|
Steps: steps,
|
|
TotalNetworkFee: protoMoney(src.TotalNetworkFee),
|
|
}
|
|
}
|
|
|
|
func protoPaymentStepFromModel(src *model.PaymentStep) *orchestratorv1.PaymentStep {
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
return &orchestratorv1.PaymentStep{
|
|
Rail: protoRailFromModel(src.Rail),
|
|
GatewayId: strings.TrimSpace(src.GatewayID),
|
|
Action: protoRailOperationFromModel(src.Action),
|
|
Amount: protoMoney(src.Amount),
|
|
StepId: strings.TrimSpace(src.StepID),
|
|
InstanceId: strings.TrimSpace(src.InstanceID),
|
|
DependsOn: cloneStringList(src.DependsOn),
|
|
CommitPolicy: strings.TrimSpace(string(src.CommitPolicy)),
|
|
CommitAfter: cloneStringList(src.CommitAfter),
|
|
}
|
|
}
|
|
|
|
func protoPaymentPlanFromModel(src *model.PaymentPlan) *orchestratorv1.PaymentPlan {
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
steps := make([]*orchestratorv1.PaymentStep, 0, len(src.Steps))
|
|
for _, step := range src.Steps {
|
|
if protoStep := protoPaymentStepFromModel(step); protoStep != nil {
|
|
steps = append(steps, protoStep)
|
|
}
|
|
}
|
|
if len(steps) == 0 {
|
|
steps = nil
|
|
}
|
|
plan := &orchestratorv1.PaymentPlan{
|
|
Id: strings.TrimSpace(src.ID),
|
|
Steps: steps,
|
|
IdempotencyKey: strings.TrimSpace(src.IdempotencyKey),
|
|
FxQuote: fxQuoteToProto(src.FXQuote),
|
|
Fees: feeLinesToProto(src.Fees),
|
|
}
|
|
if !src.CreatedAt.IsZero() {
|
|
plan.CreatedAt = timestamppb.New(src.CreatedAt.UTC())
|
|
}
|
|
return plan
|
|
}
|
|
|
|
func modelQuoteToProto(src *model.PaymentQuoteSnapshot) *orchestratorv1.PaymentQuote {
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
return &orchestratorv1.PaymentQuote{
|
|
DebitAmount: protoMoney(src.DebitAmount),
|
|
DebitSettlementAmount: protoMoney(src.DebitSettlementAmount),
|
|
ExpectedSettlementAmount: protoMoney(src.ExpectedSettlementAmount),
|
|
ExpectedFeeTotal: protoMoney(src.ExpectedFeeTotal),
|
|
FeeLines: feeLinesToProto(src.FeeLines),
|
|
FeeRules: feeRulesToProto(src.FeeRules),
|
|
FxQuote: fxQuoteToProto(src.FXQuote),
|
|
NetworkFee: networkFeeToProto(src.NetworkFee),
|
|
QuoteRef: strings.TrimSpace(src.QuoteRef),
|
|
}
|
|
}
|
|
|
|
func filterFromProto(req *orchestratorv1.ListPaymentsRequest) *model.PaymentFilter {
|
|
if req == nil {
|
|
return &model.PaymentFilter{}
|
|
}
|
|
filter := &model.PaymentFilter{
|
|
SourceRef: strings.TrimSpace(req.GetSourceRef()),
|
|
DestinationRef: strings.TrimSpace(req.GetDestinationRef()),
|
|
OrganizationRef: strings.TrimSpace(req.GetOrganizationRef()),
|
|
}
|
|
if req.GetPage() != nil {
|
|
filter.Cursor = strings.TrimSpace(req.GetPage().GetCursor())
|
|
filter.Limit = req.GetPage().GetLimit()
|
|
}
|
|
if len(req.GetFilterStates()) > 0 {
|
|
filter.States = make([]model.PaymentState, 0, len(req.GetFilterStates()))
|
|
for _, st := range req.GetFilterStates() {
|
|
filter.States = append(filter.States, modelStateFromProto(st))
|
|
}
|
|
}
|
|
return filter
|
|
}
|
|
|
|
func protoKindFromModel(kind model.PaymentKind) orchestratorv1.PaymentKind {
|
|
switch kind {
|
|
case model.PaymentKindPayout:
|
|
return orchestratorv1.PaymentKind_PAYMENT_KIND_PAYOUT
|
|
case model.PaymentKindInternalTransfer:
|
|
return orchestratorv1.PaymentKind_PAYMENT_KIND_INTERNAL_TRANSFER
|
|
case model.PaymentKindFXConversion:
|
|
return orchestratorv1.PaymentKind_PAYMENT_KIND_FX_CONVERSION
|
|
default:
|
|
return orchestratorv1.PaymentKind_PAYMENT_KIND_UNSPECIFIED
|
|
}
|
|
}
|
|
|
|
func modelKindFromProto(kind orchestratorv1.PaymentKind) model.PaymentKind {
|
|
switch kind {
|
|
case orchestratorv1.PaymentKind_PAYMENT_KIND_PAYOUT:
|
|
return model.PaymentKindPayout
|
|
case orchestratorv1.PaymentKind_PAYMENT_KIND_INTERNAL_TRANSFER:
|
|
return model.PaymentKindInternalTransfer
|
|
case orchestratorv1.PaymentKind_PAYMENT_KIND_FX_CONVERSION:
|
|
return model.PaymentKindFXConversion
|
|
default:
|
|
return model.PaymentKindUnspecified
|
|
}
|
|
}
|
|
|
|
func protoRailFromModel(rail model.Rail) gatewayv1.Rail {
|
|
switch strings.ToUpper(strings.TrimSpace(string(rail))) {
|
|
case string(model.RailCrypto):
|
|
return gatewayv1.Rail_RAIL_CRYPTO
|
|
case string(model.RailProviderSettlement):
|
|
return gatewayv1.Rail_RAIL_PROVIDER_SETTLEMENT
|
|
case string(model.RailLedger):
|
|
return gatewayv1.Rail_RAIL_LEDGER
|
|
case string(model.RailCardPayout):
|
|
return gatewayv1.Rail_RAIL_CARD_PAYOUT
|
|
case string(model.RailFiatOnRamp):
|
|
return gatewayv1.Rail_RAIL_FIAT_ONRAMP
|
|
default:
|
|
return gatewayv1.Rail_RAIL_UNSPECIFIED
|
|
}
|
|
}
|
|
|
|
func protoRailOperationFromModel(action model.RailOperation) gatewayv1.RailOperation {
|
|
switch strings.ToUpper(strings.TrimSpace(string(action))) {
|
|
case string(model.RailOperationDebit):
|
|
return gatewayv1.RailOperation_RAIL_OPERATION_DEBIT
|
|
case string(model.RailOperationCredit):
|
|
return gatewayv1.RailOperation_RAIL_OPERATION_CREDIT
|
|
case string(model.RailOperationExternalDebit):
|
|
return gatewayv1.RailOperation_RAIL_OPERATION_DEBIT
|
|
case string(model.RailOperationExternalCredit):
|
|
return gatewayv1.RailOperation_RAIL_OPERATION_CREDIT
|
|
case string(model.RailOperationMove):
|
|
return gatewayv1.RailOperation_RAIL_OPERATION_MOVE
|
|
case string(model.RailOperationSend):
|
|
return gatewayv1.RailOperation_RAIL_OPERATION_SEND
|
|
case string(model.RailOperationFee):
|
|
return gatewayv1.RailOperation_RAIL_OPERATION_FEE
|
|
case string(model.RailOperationObserveConfirm):
|
|
return gatewayv1.RailOperation_RAIL_OPERATION_OBSERVE_CONFIRM
|
|
case string(model.RailOperationFXConvert):
|
|
return gatewayv1.RailOperation_RAIL_OPERATION_FX_CONVERT
|
|
case string(model.RailOperationBlock):
|
|
return gatewayv1.RailOperation_RAIL_OPERATION_BLOCK
|
|
case string(model.RailOperationRelease):
|
|
return gatewayv1.RailOperation_RAIL_OPERATION_RELEASE
|
|
default:
|
|
return gatewayv1.RailOperation_RAIL_OPERATION_UNSPECIFIED
|
|
}
|
|
}
|
|
|
|
func protoStateFromModel(state model.PaymentState) orchestratorv1.PaymentState {
|
|
switch state {
|
|
case model.PaymentStateAccepted:
|
|
return orchestratorv1.PaymentState_PAYMENT_STATE_ACCEPTED
|
|
case model.PaymentStateFundsReserved:
|
|
return orchestratorv1.PaymentState_PAYMENT_STATE_FUNDS_RESERVED
|
|
case model.PaymentStateSubmitted:
|
|
return orchestratorv1.PaymentState_PAYMENT_STATE_SUBMITTED
|
|
case model.PaymentStateSettled:
|
|
return orchestratorv1.PaymentState_PAYMENT_STATE_SETTLED
|
|
case model.PaymentStateFailed:
|
|
return orchestratorv1.PaymentState_PAYMENT_STATE_FAILED
|
|
case model.PaymentStateCancelled:
|
|
return orchestratorv1.PaymentState_PAYMENT_STATE_CANCELLED
|
|
default:
|
|
return orchestratorv1.PaymentState_PAYMENT_STATE_UNSPECIFIED
|
|
}
|
|
}
|
|
|
|
func modelStateFromProto(state orchestratorv1.PaymentState) model.PaymentState {
|
|
switch state {
|
|
case orchestratorv1.PaymentState_PAYMENT_STATE_ACCEPTED:
|
|
return model.PaymentStateAccepted
|
|
case orchestratorv1.PaymentState_PAYMENT_STATE_FUNDS_RESERVED:
|
|
return model.PaymentStateFundsReserved
|
|
case orchestratorv1.PaymentState_PAYMENT_STATE_SUBMITTED:
|
|
return model.PaymentStateSubmitted
|
|
case orchestratorv1.PaymentState_PAYMENT_STATE_SETTLED:
|
|
return model.PaymentStateSettled
|
|
case orchestratorv1.PaymentState_PAYMENT_STATE_FAILED:
|
|
return model.PaymentStateFailed
|
|
case orchestratorv1.PaymentState_PAYMENT_STATE_CANCELLED:
|
|
return model.PaymentStateCancelled
|
|
default:
|
|
return model.PaymentStateUnspecified
|
|
}
|
|
}
|
|
|
|
func protoFailureFromModel(code model.PaymentFailureCode) orchestratorv1.PaymentFailureCode {
|
|
switch code {
|
|
case model.PaymentFailureCodeBalance:
|
|
return orchestratorv1.PaymentFailureCode_FAILURE_BALANCE
|
|
case model.PaymentFailureCodeLedger:
|
|
return orchestratorv1.PaymentFailureCode_FAILURE_LEDGER
|
|
case model.PaymentFailureCodeFX:
|
|
return orchestratorv1.PaymentFailureCode_FAILURE_FX
|
|
case model.PaymentFailureCodeChain:
|
|
return orchestratorv1.PaymentFailureCode_FAILURE_CHAIN
|
|
case model.PaymentFailureCodeFees:
|
|
return orchestratorv1.PaymentFailureCode_FAILURE_FEES
|
|
case model.PaymentFailureCodePolicy:
|
|
return orchestratorv1.PaymentFailureCode_FAILURE_POLICY
|
|
default:
|
|
return orchestratorv1.PaymentFailureCode_FAILURE_UNSPECIFIED
|
|
}
|
|
}
|
|
|
|
func settlementModeFromProto(mode orchestratorv1.SettlementMode) model.SettlementMode {
|
|
switch mode {
|
|
case orchestratorv1.SettlementMode_SETTLEMENT_FIX_SOURCE:
|
|
return model.SettlementModeFixSource
|
|
case orchestratorv1.SettlementMode_SETTLEMENT_FIX_RECEIVED:
|
|
return model.SettlementModeFixReceived
|
|
default:
|
|
return model.SettlementModeUnspecified
|
|
}
|
|
}
|
|
|
|
func settlementModeToProto(mode model.SettlementMode) orchestratorv1.SettlementMode {
|
|
switch mode {
|
|
case model.SettlementModeFixSource:
|
|
return orchestratorv1.SettlementMode_SETTLEMENT_FIX_SOURCE
|
|
case model.SettlementModeFixReceived:
|
|
return orchestratorv1.SettlementMode_SETTLEMENT_FIX_RECEIVED
|
|
default:
|
|
return orchestratorv1.SettlementMode_SETTLEMENT_UNSPECIFIED
|
|
}
|
|
}
|
|
|
|
func moneyFromProto(m *moneyv1.Money) *paymenttypes.Money {
|
|
if m == nil {
|
|
return nil
|
|
}
|
|
return &paymenttypes.Money{
|
|
Currency: m.GetCurrency(),
|
|
Amount: m.GetAmount(),
|
|
}
|
|
}
|
|
|
|
func protoMoney(m *paymenttypes.Money) *moneyv1.Money {
|
|
if m == nil {
|
|
return nil
|
|
}
|
|
return &moneyv1.Money{
|
|
Currency: m.GetCurrency(),
|
|
Amount: m.GetAmount(),
|
|
}
|
|
}
|
|
|
|
func feePolicyFromProto(src *feesv1.PolicyOverrides) *paymenttypes.FeePolicy {
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
return &paymenttypes.FeePolicy{
|
|
InsufficientNet: insufficientPolicyFromProto(src.GetInsufficientNet()),
|
|
}
|
|
}
|
|
|
|
func feePolicyToProto(src *paymenttypes.FeePolicy) *feesv1.PolicyOverrides {
|
|
if src == nil {
|
|
return nil
|
|
}
|
|
return &feesv1.PolicyOverrides{
|
|
InsufficientNet: insufficientPolicyToProto(src.InsufficientNet),
|
|
}
|
|
}
|
|
|
|
func insufficientPolicyFromProto(policy feesv1.InsufficientNetPolicy) paymenttypes.InsufficientNetPolicy {
|
|
switch policy {
|
|
case feesv1.InsufficientNetPolicy_BLOCK_POSTING:
|
|
return paymenttypes.InsufficientNetBlockPosting
|
|
case feesv1.InsufficientNetPolicy_SWEEP_ORG_CASH:
|
|
return paymenttypes.InsufficientNetSweepOrgCash
|
|
case feesv1.InsufficientNetPolicy_INVOICE_LATER:
|
|
return paymenttypes.InsufficientNetInvoiceLater
|
|
default:
|
|
return paymenttypes.InsufficientNetUnspecified
|
|
}
|
|
}
|
|
|
|
func insufficientPolicyToProto(policy paymenttypes.InsufficientNetPolicy) feesv1.InsufficientNetPolicy {
|
|
switch policy {
|
|
case paymenttypes.InsufficientNetBlockPosting:
|
|
return feesv1.InsufficientNetPolicy_BLOCK_POSTING
|
|
case paymenttypes.InsufficientNetSweepOrgCash:
|
|
return feesv1.InsufficientNetPolicy_SWEEP_ORG_CASH
|
|
case paymenttypes.InsufficientNetInvoiceLater:
|
|
return feesv1.InsufficientNetPolicy_INVOICE_LATER
|
|
default:
|
|
return feesv1.InsufficientNetPolicy_INSUFFICIENT_NET_UNSPECIFIED
|
|
}
|
|
}
|
|
|
|
func pairFromProto(pair *fxv1.CurrencyPair) *paymenttypes.CurrencyPair {
|
|
if pair == nil {
|
|
return nil
|
|
}
|
|
return &paymenttypes.CurrencyPair{
|
|
Base: pair.GetBase(),
|
|
Quote: pair.GetQuote(),
|
|
}
|
|
}
|
|
|
|
func pairToProto(pair *paymenttypes.CurrencyPair) *fxv1.CurrencyPair {
|
|
if pair == nil {
|
|
return nil
|
|
}
|
|
return &fxv1.CurrencyPair{
|
|
Base: pair.GetBase(),
|
|
Quote: pair.GetQuote(),
|
|
}
|
|
}
|
|
|
|
func fxSideFromProto(side fxv1.Side) paymenttypes.FXSide {
|
|
switch side {
|
|
case fxv1.Side_BUY_BASE_SELL_QUOTE:
|
|
return paymenttypes.FXSideBuyBaseSellQuote
|
|
case fxv1.Side_SELL_BASE_BUY_QUOTE:
|
|
return paymenttypes.FXSideSellBaseBuyQuote
|
|
default:
|
|
return paymenttypes.FXSideUnspecified
|
|
}
|
|
}
|
|
|
|
func fxSideToProto(side paymenttypes.FXSide) fxv1.Side {
|
|
switch side {
|
|
case paymenttypes.FXSideBuyBaseSellQuote:
|
|
return fxv1.Side_BUY_BASE_SELL_QUOTE
|
|
case paymenttypes.FXSideSellBaseBuyQuote:
|
|
return fxv1.Side_SELL_BASE_BUY_QUOTE
|
|
default:
|
|
return fxv1.Side_SIDE_UNSPECIFIED
|
|
}
|
|
}
|
|
|
|
func fxQuoteFromProto(quote *oraclev1.Quote) *paymenttypes.FXQuote {
|
|
if quote == nil {
|
|
return nil
|
|
}
|
|
return &paymenttypes.FXQuote{
|
|
QuoteRef: strings.TrimSpace(quote.GetQuoteRef()),
|
|
Pair: pairFromProto(quote.GetPair()),
|
|
Side: fxSideFromProto(quote.GetSide()),
|
|
Price: decimalFromProto(quote.GetPrice()),
|
|
BaseAmount: moneyFromProto(quote.GetBaseAmount()),
|
|
QuoteAmount: moneyFromProto(quote.GetQuoteAmount()),
|
|
ExpiresAtUnixMs: quote.GetExpiresAtUnixMs(),
|
|
Provider: strings.TrimSpace(quote.GetProvider()),
|
|
RateRef: strings.TrimSpace(quote.GetRateRef()),
|
|
Firm: quote.GetFirm(),
|
|
}
|
|
}
|
|
|
|
func fxQuoteToProto(quote *paymenttypes.FXQuote) *oraclev1.Quote {
|
|
if quote == nil {
|
|
return nil
|
|
}
|
|
return &oraclev1.Quote{
|
|
QuoteRef: strings.TrimSpace(quote.QuoteRef),
|
|
Pair: pairToProto(quote.Pair),
|
|
Side: fxSideToProto(quote.Side),
|
|
Price: decimalToProto(quote.Price),
|
|
BaseAmount: protoMoney(quote.BaseAmount),
|
|
QuoteAmount: protoMoney(quote.QuoteAmount),
|
|
ExpiresAtUnixMs: quote.ExpiresAtUnixMs,
|
|
Provider: strings.TrimSpace(quote.Provider),
|
|
RateRef: strings.TrimSpace(quote.RateRef),
|
|
Firm: quote.Firm,
|
|
}
|
|
}
|
|
|
|
func decimalFromProto(value *moneyv1.Decimal) *paymenttypes.Decimal {
|
|
if value == nil {
|
|
return nil
|
|
}
|
|
return &paymenttypes.Decimal{Value: value.GetValue()}
|
|
}
|
|
|
|
func decimalToProto(value *paymenttypes.Decimal) *moneyv1.Decimal {
|
|
if value == nil {
|
|
return nil
|
|
}
|
|
return &moneyv1.Decimal{Value: value.GetValue()}
|
|
}
|
|
|
|
func assetFromProto(asset *chainv1.Asset) *paymenttypes.Asset {
|
|
if asset == nil {
|
|
return nil
|
|
}
|
|
return &paymenttypes.Asset{
|
|
Chain: chainasset.NetworkAlias(asset.GetChain()),
|
|
TokenSymbol: asset.GetTokenSymbol(),
|
|
ContractAddress: asset.GetContractAddress(),
|
|
}
|
|
}
|
|
|
|
func assetToProto(asset *paymenttypes.Asset) *chainv1.Asset {
|
|
if asset == nil {
|
|
return nil
|
|
}
|
|
return &chainv1.Asset{
|
|
Chain: chainasset.NetworkFromString(asset.Chain),
|
|
TokenSymbol: asset.TokenSymbol,
|
|
ContractAddress: asset.ContractAddress,
|
|
}
|
|
}
|
|
|
|
func networkFeeFromProto(resp *chainv1.EstimateTransferFeeResponse) *paymenttypes.NetworkFeeEstimate {
|
|
if resp == nil {
|
|
return nil
|
|
}
|
|
return &paymenttypes.NetworkFeeEstimate{
|
|
NetworkFee: moneyFromProto(resp.GetNetworkFee()),
|
|
EstimationContext: strings.TrimSpace(resp.GetEstimationContext()),
|
|
}
|
|
}
|
|
|
|
func networkFeeToProto(resp *paymenttypes.NetworkFeeEstimate) *chainv1.EstimateTransferFeeResponse {
|
|
if resp == nil {
|
|
return nil
|
|
}
|
|
return &chainv1.EstimateTransferFeeResponse{
|
|
NetworkFee: protoMoney(resp.NetworkFee),
|
|
EstimationContext: strings.TrimSpace(resp.EstimationContext),
|
|
}
|
|
}
|
|
|
|
func feeLinesFromProto(lines []*feesv1.DerivedPostingLine) []*paymenttypes.FeeLine {
|
|
if len(lines) == 0 {
|
|
return nil
|
|
}
|
|
result := make([]*paymenttypes.FeeLine, 0, len(lines))
|
|
for _, line := range lines {
|
|
if line == nil {
|
|
continue
|
|
}
|
|
result = append(result, &paymenttypes.FeeLine{
|
|
LedgerAccountRef: strings.TrimSpace(line.GetLedgerAccountRef()),
|
|
Money: moneyFromProto(line.GetMoney()),
|
|
LineType: postingLineTypeFromProto(line.GetLineType()),
|
|
Side: entrySideFromProto(line.GetSide()),
|
|
Meta: cloneMetadata(line.GetMeta()),
|
|
})
|
|
}
|
|
if len(result) == 0 {
|
|
return nil
|
|
}
|
|
return result
|
|
}
|
|
|
|
func feeLinesToProto(lines []*paymenttypes.FeeLine) []*feesv1.DerivedPostingLine {
|
|
if len(lines) == 0 {
|
|
return nil
|
|
}
|
|
result := make([]*feesv1.DerivedPostingLine, 0, len(lines))
|
|
for _, line := range lines {
|
|
if line == nil {
|
|
continue
|
|
}
|
|
result = append(result, &feesv1.DerivedPostingLine{
|
|
LedgerAccountRef: strings.TrimSpace(line.LedgerAccountRef),
|
|
Money: protoMoney(line.Money),
|
|
LineType: postingLineTypeToProto(line.LineType),
|
|
Side: entrySideToProto(line.Side),
|
|
Meta: cloneMetadata(line.Meta),
|
|
})
|
|
}
|
|
if len(result) == 0 {
|
|
return nil
|
|
}
|
|
return result
|
|
}
|
|
|
|
func feeRulesFromProto(rules []*feesv1.AppliedRule) []*paymenttypes.AppliedRule {
|
|
if len(rules) == 0 {
|
|
return nil
|
|
}
|
|
result := make([]*paymenttypes.AppliedRule, 0, len(rules))
|
|
for _, rule := range rules {
|
|
if rule == nil {
|
|
continue
|
|
}
|
|
result = append(result, &paymenttypes.AppliedRule{
|
|
RuleID: strings.TrimSpace(rule.GetRuleId()),
|
|
RuleVersion: strings.TrimSpace(rule.GetRuleVersion()),
|
|
Formula: strings.TrimSpace(rule.GetFormula()),
|
|
Rounding: roundingModeFromProto(rule.GetRounding()),
|
|
TaxCode: strings.TrimSpace(rule.GetTaxCode()),
|
|
TaxRate: strings.TrimSpace(rule.GetTaxRate()),
|
|
Parameters: cloneMetadata(rule.GetParameters()),
|
|
})
|
|
}
|
|
if len(result) == 0 {
|
|
return nil
|
|
}
|
|
return result
|
|
}
|
|
|
|
func feeRulesToProto(rules []*paymenttypes.AppliedRule) []*feesv1.AppliedRule {
|
|
if len(rules) == 0 {
|
|
return nil
|
|
}
|
|
result := make([]*feesv1.AppliedRule, 0, len(rules))
|
|
for _, rule := range rules {
|
|
if rule == nil {
|
|
continue
|
|
}
|
|
result = append(result, &feesv1.AppliedRule{
|
|
RuleId: strings.TrimSpace(rule.RuleID),
|
|
RuleVersion: strings.TrimSpace(rule.RuleVersion),
|
|
Formula: strings.TrimSpace(rule.Formula),
|
|
Rounding: roundingModeToProto(rule.Rounding),
|
|
TaxCode: strings.TrimSpace(rule.TaxCode),
|
|
TaxRate: strings.TrimSpace(rule.TaxRate),
|
|
Parameters: cloneMetadata(rule.Parameters),
|
|
})
|
|
}
|
|
if len(result) == 0 {
|
|
return nil
|
|
}
|
|
return result
|
|
}
|
|
|
|
func entrySideFromProto(side accountingv1.EntrySide) paymenttypes.EntrySide {
|
|
switch side {
|
|
case accountingv1.EntrySide_ENTRY_SIDE_DEBIT:
|
|
return paymenttypes.EntrySideDebit
|
|
case accountingv1.EntrySide_ENTRY_SIDE_CREDIT:
|
|
return paymenttypes.EntrySideCredit
|
|
default:
|
|
return paymenttypes.EntrySideUnspecified
|
|
}
|
|
}
|
|
|
|
func entrySideToProto(side paymenttypes.EntrySide) accountingv1.EntrySide {
|
|
switch side {
|
|
case paymenttypes.EntrySideDebit:
|
|
return accountingv1.EntrySide_ENTRY_SIDE_DEBIT
|
|
case paymenttypes.EntrySideCredit:
|
|
return accountingv1.EntrySide_ENTRY_SIDE_CREDIT
|
|
default:
|
|
return accountingv1.EntrySide_ENTRY_SIDE_UNSPECIFIED
|
|
}
|
|
}
|
|
|
|
func postingLineTypeFromProto(lineType accountingv1.PostingLineType) paymenttypes.PostingLineType {
|
|
switch lineType {
|
|
case accountingv1.PostingLineType_POSTING_LINE_FEE:
|
|
return paymenttypes.PostingLineTypeFee
|
|
case accountingv1.PostingLineType_POSTING_LINE_TAX:
|
|
return paymenttypes.PostingLineTypeTax
|
|
case accountingv1.PostingLineType_POSTING_LINE_SPREAD:
|
|
return paymenttypes.PostingLineTypeSpread
|
|
case accountingv1.PostingLineType_POSTING_LINE_REVERSAL:
|
|
return paymenttypes.PostingLineTypeReversal
|
|
default:
|
|
return paymenttypes.PostingLineTypeUnspecified
|
|
}
|
|
}
|
|
|
|
func postingLineTypeToProto(lineType paymenttypes.PostingLineType) accountingv1.PostingLineType {
|
|
switch lineType {
|
|
case paymenttypes.PostingLineTypeFee:
|
|
return accountingv1.PostingLineType_POSTING_LINE_FEE
|
|
case paymenttypes.PostingLineTypeTax:
|
|
return accountingv1.PostingLineType_POSTING_LINE_TAX
|
|
case paymenttypes.PostingLineTypeSpread:
|
|
return accountingv1.PostingLineType_POSTING_LINE_SPREAD
|
|
case paymenttypes.PostingLineTypeReversal:
|
|
return accountingv1.PostingLineType_POSTING_LINE_REVERSAL
|
|
default:
|
|
return accountingv1.PostingLineType_POSTING_LINE_TYPE_UNSPECIFIED
|
|
}
|
|
}
|
|
|
|
func roundingModeFromProto(mode moneyv1.RoundingMode) paymenttypes.RoundingMode {
|
|
switch mode {
|
|
case moneyv1.RoundingMode_ROUND_HALF_EVEN:
|
|
return paymenttypes.RoundingModeHalfEven
|
|
case moneyv1.RoundingMode_ROUND_HALF_UP:
|
|
return paymenttypes.RoundingModeHalfUp
|
|
case moneyv1.RoundingMode_ROUND_DOWN:
|
|
return paymenttypes.RoundingModeDown
|
|
default:
|
|
return paymenttypes.RoundingModeUnspecified
|
|
}
|
|
}
|
|
|
|
func roundingModeToProto(mode paymenttypes.RoundingMode) moneyv1.RoundingMode {
|
|
switch mode {
|
|
case paymenttypes.RoundingModeHalfEven:
|
|
return moneyv1.RoundingMode_ROUND_HALF_EVEN
|
|
case paymenttypes.RoundingModeHalfUp:
|
|
return moneyv1.RoundingMode_ROUND_HALF_UP
|
|
case paymenttypes.RoundingModeDown:
|
|
return moneyv1.RoundingMode_ROUND_DOWN
|
|
default:
|
|
return moneyv1.RoundingMode_ROUNDING_MODE_UNSPECIFIED
|
|
}
|
|
}
|