From c8b8b1183b0cd484baec40b0f3df4c3bd0a32b3d Mon Sep 17 00:00:00 2001 From: Stephan D Date: Fri, 6 Feb 2026 17:50:11 +0100 Subject: [PATCH] Added debit settlement amount calculation --- api/billing/documents/go.mod | 2 +- api/billing/documents/go.sum | 4 +- api/billing/fees/go.mod | 2 +- api/billing/fees/go.sum | 4 +- api/discovery/go.mod | 2 +- api/discovery/go.sum | 4 +- api/fx/ingestor/go.mod | 2 +- api/fx/ingestor/go.sum | 4 +- api/fx/oracle/go.mod | 2 +- api/fx/oracle/go.sum | 4 +- api/gateway/chain/go.mod | 2 +- api/gateway/chain/go.sum | 4 +- .../chain/internal/service/gateway/options.go | 2 +- api/gateway/mntx/go.mod | 2 +- api/gateway/mntx/go.sum | 4 +- api/gateway/tgsettle/go.mod | 2 +- api/gateway/tgsettle/go.sum | 4 +- api/gateway/tron/go.mod | 2 +- api/gateway/tron/go.sum | 4 +- .../tron/internal/service/gateway/options.go | 1 + .../gateway => }/shared/network_registry.go | 0 api/gateway/tron/storage/model/wallet.go | 2 +- api/ledger/go.mod | 2 +- api/ledger/go.sum | 4 +- api/notification/go.mod | 2 +- api/notification/go.sum | 4 +- api/payments/orchestrator/go.mod | 2 +- api/payments/orchestrator/go.sum | 4 +- .../internal/service/orchestrator/convert.go | 2 + .../orchestrator/payment_plan_analyzer.go | 123 ++++++++++++++++++ .../orchestrator/payment_plan_executor.go | 87 +------------ .../orchestrator/payment_plan_order.go | 111 +--------------- .../orchestrator/payment_plan_steps.go | 15 ++- .../service/orchestrator/quote_engine.go | 1 + .../orchestrator/storage/model/payment.go | 5 + api/pkg/go.mod | 2 +- api/pkg/go.sum | 4 +- .../orchestrator/v1/orchestrator.proto | 1 + api/server/go.mod | 2 +- api/server/go.sum | 4 +- api/server/interface/api/sresponse/payment.go | 2 + .../lib/data/dto/payment/payment_quote.dart | 2 + .../data/mapper/payment/payment_quote.dart | 2 + .../lib/models/payment/quote/quote.dart | 2 + 44 files changed, 200 insertions(+), 242 deletions(-) rename api/gateway/tron/{internal/service/gateway => }/shared/network_registry.go (100%) create mode 100644 api/payments/orchestrator/internal/service/orchestrator/payment_plan_analyzer.go diff --git a/api/billing/documents/go.mod b/api/billing/documents/go.mod index 65e056d0..37a80341 100644 --- a/api/billing/documents/go.mod +++ b/api/billing/documents/go.mod @@ -41,7 +41,7 @@ require ( github.com/casbin/govaluate v1.10.0 // indirect github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/go-chi/chi/v5 v5.2.4 // indirect + github.com/go-chi/chi/v5 v5.2.5 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.18.3 // indirect github.com/mattn/go-colorable v0.1.14 // indirect diff --git a/api/billing/documents/go.sum b/api/billing/documents/go.sum index 684e5755..17c1ab13 100644 --- a/api/billing/documents/go.sum +++ b/api/billing/documents/go.sum @@ -78,8 +78,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= diff --git a/api/billing/fees/go.mod b/api/billing/fees/go.mod index d976a362..f0a16410 100644 --- a/api/billing/fees/go.mod +++ b/api/billing/fees/go.mod @@ -25,7 +25,7 @@ require ( github.com/casbin/casbin/v2 v2.135.0 // indirect github.com/casbin/govaluate v1.10.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/go-chi/chi/v5 v5.2.4 // indirect + github.com/go-chi/chi/v5 v5.2.5 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.18.3 // indirect github.com/mattn/go-colorable v0.1.14 // indirect diff --git a/api/billing/fees/go.sum b/api/billing/fees/go.sum index 4e3f9b6c..f9321bd3 100644 --- a/api/billing/fees/go.sum +++ b/api/billing/fees/go.sum @@ -38,8 +38,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= diff --git a/api/discovery/go.mod b/api/discovery/go.mod index f6680737..fd731767 100644 --- a/api/discovery/go.mod +++ b/api/discovery/go.mod @@ -5,7 +5,7 @@ go 1.25.6 replace github.com/tech/sendico/pkg => ../pkg require ( - github.com/go-chi/chi/v5 v5.2.4 + github.com/go-chi/chi/v5 v5.2.5 github.com/prometheus/client_golang v1.23.2 github.com/tech/sendico/pkg v0.1.0 go.uber.org/zap v1.27.1 diff --git a/api/discovery/go.sum b/api/discovery/go.sum index 4e3f9b6c..f9321bd3 100644 --- a/api/discovery/go.sum +++ b/api/discovery/go.sum @@ -38,8 +38,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= diff --git a/api/fx/ingestor/go.mod b/api/fx/ingestor/go.mod index 95cdcf2b..8b005be2 100644 --- a/api/fx/ingestor/go.mod +++ b/api/fx/ingestor/go.mod @@ -7,7 +7,7 @@ replace github.com/tech/sendico/pkg => ../../pkg replace github.com/tech/sendico/fx/storage => ../storage require ( - github.com/go-chi/chi/v5 v5.2.4 + github.com/go-chi/chi/v5 v5.2.5 github.com/google/go-cmp v0.7.0 github.com/prometheus/client_golang v1.23.2 github.com/tech/sendico/fx/storage v0.0.0 diff --git a/api/fx/ingestor/go.sum b/api/fx/ingestor/go.sum index 4e3f9b6c..f9321bd3 100644 --- a/api/fx/ingestor/go.sum +++ b/api/fx/ingestor/go.sum @@ -38,8 +38,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= diff --git a/api/fx/oracle/go.mod b/api/fx/oracle/go.mod index edbc9f38..e863cf0a 100644 --- a/api/fx/oracle/go.mod +++ b/api/fx/oracle/go.mod @@ -25,7 +25,7 @@ require ( github.com/casbin/govaluate v1.10.0 // indirect github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/go-chi/chi/v5 v5.2.4 // indirect + github.com/go-chi/chi/v5 v5.2.5 // indirect github.com/klauspost/compress v1.18.3 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect diff --git a/api/fx/oracle/go.sum b/api/fx/oracle/go.sum index 4e3f9b6c..f9321bd3 100644 --- a/api/fx/oracle/go.sum +++ b/api/fx/oracle/go.sum @@ -38,8 +38,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= diff --git a/api/gateway/chain/go.mod b/api/gateway/chain/go.mod index 88a789fd..f2a15618 100644 --- a/api/gateway/chain/go.mod +++ b/api/gateway/chain/go.mod @@ -38,7 +38,7 @@ require ( github.com/deckarep/golang-set/v2 v2.8.0 // indirect github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect github.com/ethereum/go-verkle v0.2.2 // indirect - github.com/go-chi/chi/v5 v5.2.4 // indirect + github.com/go-chi/chi/v5 v5.2.5 // indirect github.com/go-jose/go-jose/v4 v4.1.3 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/google/uuid v1.6.0 // indirect diff --git a/api/gateway/chain/go.sum b/api/gateway/chain/go.sum index 54666776..8a23f478 100644 --- a/api/gateway/chain/go.sum +++ b/api/gateway/chain/go.sum @@ -90,8 +90,8 @@ github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeD github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= diff --git a/api/gateway/chain/internal/service/gateway/options.go b/api/gateway/chain/internal/service/gateway/options.go index 03485833..d5139ff9 100644 --- a/api/gateway/chain/internal/service/gateway/options.go +++ b/api/gateway/chain/internal/service/gateway/options.go @@ -49,7 +49,7 @@ func WithNetworks(networks []shared.Network) Option { clone.TokenConfigs[i].Symbol = strings.ToUpper(strings.TrimSpace(clone.TokenConfigs[i].Symbol)) clone.TokenConfigs[i].ContractAddress = strings.ToLower(strings.TrimSpace(clone.TokenConfigs[i].ContractAddress)) } - clone.Name = clone.Name + clone.Name = network.Name s.networks[clone.Name] = clone } } diff --git a/api/gateway/mntx/go.mod b/api/gateway/mntx/go.mod index 56795bee..0cffde42 100644 --- a/api/gateway/mntx/go.mod +++ b/api/gateway/mntx/go.mod @@ -5,7 +5,7 @@ go 1.25.6 replace github.com/tech/sendico/pkg => ../../pkg require ( - github.com/go-chi/chi/v5 v5.2.4 + github.com/go-chi/chi/v5 v5.2.5 github.com/prometheus/client_golang v1.23.2 github.com/shopspring/decimal v1.4.0 github.com/tech/sendico/pkg v0.1.0 diff --git a/api/gateway/mntx/go.sum b/api/gateway/mntx/go.sum index 9c658f2c..3464e6c2 100644 --- a/api/gateway/mntx/go.sum +++ b/api/gateway/mntx/go.sum @@ -38,8 +38,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= diff --git a/api/gateway/tgsettle/go.mod b/api/gateway/tgsettle/go.mod index 073b3bd4..27a5b2d9 100644 --- a/api/gateway/tgsettle/go.mod +++ b/api/gateway/tgsettle/go.mod @@ -20,7 +20,7 @@ require ( github.com/casbin/govaluate v1.10.0 // indirect github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/go-chi/chi/v5 v5.2.4 // indirect + github.com/go-chi/chi/v5 v5.2.5 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.18.3 // indirect github.com/mattn/go-colorable v0.1.14 // indirect diff --git a/api/gateway/tgsettle/go.sum b/api/gateway/tgsettle/go.sum index 4e3f9b6c..f9321bd3 100644 --- a/api/gateway/tgsettle/go.sum +++ b/api/gateway/tgsettle/go.sum @@ -38,8 +38,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= diff --git a/api/gateway/tron/go.mod b/api/gateway/tron/go.mod index 214b70d2..3880bd29 100644 --- a/api/gateway/tron/go.mod +++ b/api/gateway/tron/go.mod @@ -42,7 +42,7 @@ require ( github.com/deckarep/golang-set/v2 v2.8.0 // indirect github.com/ethereum/c-kzg-4844/v2 v2.1.5 // indirect github.com/ethereum/go-verkle v0.2.2 // indirect - github.com/go-chi/chi/v5 v5.2.4 // indirect + github.com/go-chi/chi/v5 v5.2.5 // indirect github.com/go-jose/go-jose/v4 v4.1.3 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/google/uuid v1.6.0 // indirect diff --git a/api/gateway/tron/go.sum b/api/gateway/tron/go.sum index 7ba44d8e..3aebb3f0 100644 --- a/api/gateway/tron/go.sum +++ b/api/gateway/tron/go.sum @@ -96,8 +96,8 @@ github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeD github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg= github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= diff --git a/api/gateway/tron/internal/service/gateway/options.go b/api/gateway/tron/internal/service/gateway/options.go index a00aa6b1..19e3866a 100644 --- a/api/gateway/tron/internal/service/gateway/options.go +++ b/api/gateway/tron/internal/service/gateway/options.go @@ -56,6 +56,7 @@ func WithNetworks(networks []shared.Network) Option { clone.TokenConfigs[i].Symbol = strings.ToUpper(strings.TrimSpace(clone.TokenConfigs[i].Symbol)) clone.TokenConfigs[i].ContractAddress = strings.ToLower(strings.TrimSpace(clone.TokenConfigs[i].ContractAddress)) } + clone.Name = network.Name s.networks[clone.Name.String()] = clone } } diff --git a/api/gateway/tron/internal/service/gateway/shared/network_registry.go b/api/gateway/tron/shared/network_registry.go similarity index 100% rename from api/gateway/tron/internal/service/gateway/shared/network_registry.go rename to api/gateway/tron/shared/network_registry.go diff --git a/api/gateway/tron/storage/model/wallet.go b/api/gateway/tron/storage/model/wallet.go index 5e6d7347..1c1f62cc 100644 --- a/api/gateway/tron/storage/model/wallet.go +++ b/api/gateway/tron/storage/model/wallet.go @@ -95,7 +95,7 @@ func (m *ManagedWallet) Normalize() { } m.Network = strings.TrimSpace(strings.ToLower(m.Network)) m.TokenSymbol = strings.TrimSpace(strings.ToUpper(m.TokenSymbol)) - m.ContractAddress = strings.TrimSpace(strings.ToLower(m.ContractAddress)) + m.ContractAddress = strings.TrimSpace(m.ContractAddress) m.DepositAddress = normalizeWalletAddress(m.DepositAddress) m.KeyReference = strings.TrimSpace(m.KeyReference) } diff --git a/api/ledger/go.mod b/api/ledger/go.mod index 6b39a633..615af534 100644 --- a/api/ledger/go.mod +++ b/api/ledger/go.mod @@ -24,7 +24,7 @@ require ( github.com/casbin/mongodb-adapter/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-chi/chi/v5 v5.2.4 // indirect + github.com/go-chi/chi/v5 v5.2.5 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.18.3 // indirect github.com/mattn/go-colorable v0.1.14 // indirect diff --git a/api/ledger/go.sum b/api/ledger/go.sum index 7df11bbf..31dc64f2 100644 --- a/api/ledger/go.sum +++ b/api/ledger/go.sum @@ -38,8 +38,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= diff --git a/api/notification/go.mod b/api/notification/go.mod index bf1efdc6..73140ef2 100644 --- a/api/notification/go.mod +++ b/api/notification/go.mod @@ -6,7 +6,7 @@ replace github.com/tech/sendico/pkg => ../pkg require ( github.com/amplitude/analytics-go v1.3.0 - github.com/go-chi/chi/v5 v5.2.4 + github.com/go-chi/chi/v5 v5.2.5 github.com/mitchellh/mapstructure v1.5.0 github.com/nicksnyder/go-i18n/v2 v2.6.1 github.com/sendgrid/sendgrid-go v3.16.1+incompatible diff --git a/api/notification/go.sum b/api/notification/go.sum index db7bb242..13472e92 100644 --- a/api/notification/go.sum +++ b/api/notification/go.sum @@ -42,8 +42,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= diff --git a/api/payments/orchestrator/go.mod b/api/payments/orchestrator/go.mod index b6d088d3..4494c684 100644 --- a/api/payments/orchestrator/go.mod +++ b/api/payments/orchestrator/go.mod @@ -51,7 +51,7 @@ require ( github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/go-chi/chi/v5 v5.2.4 // indirect + github.com/go-chi/chi/v5 v5.2.5 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect diff --git a/api/payments/orchestrator/go.sum b/api/payments/orchestrator/go.sum index 21e480dd..d4b2991f 100644 --- a/api/payments/orchestrator/go.sum +++ b/api/payments/orchestrator/go.sum @@ -43,8 +43,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= diff --git a/api/payments/orchestrator/internal/service/orchestrator/convert.go b/api/payments/orchestrator/internal/service/orchestrator/convert.go index a5bb955d..706fed45 100644 --- a/api/payments/orchestrator/internal/service/orchestrator/convert.go +++ b/api/payments/orchestrator/internal/service/orchestrator/convert.go @@ -112,6 +112,7 @@ func quoteSnapshotToModel(src *orchestratorv1.PaymentQuote) *model.PaymentQuoteS } return &model.PaymentQuoteSnapshot{ DebitAmount: moneyFromProto(src.GetDebitAmount()), + DebitSettlementAmount: moneyFromProto(src.GetDebitSettlementAmount()), ExpectedSettlementAmount: moneyFromProto(src.GetExpectedSettlementAmount()), ExpectedFeeTotal: moneyFromProto(src.GetExpectedFeeTotal()), FeeLines: feeLinesFromProto(src.GetFeeLines()), @@ -389,6 +390,7 @@ func modelQuoteToProto(src *model.PaymentQuoteSnapshot) *orchestratorv1.PaymentQ } return &orchestratorv1.PaymentQuote{ DebitAmount: protoMoney(src.DebitAmount), + DebitSettlementAmount: protoMoney(src.DebitSettlementAmount), ExpectedSettlementAmount: protoMoney(src.ExpectedSettlementAmount), ExpectedFeeTotal: protoMoney(src.ExpectedFeeTotal), FeeLines: feeLinesToProto(src.FeeLines), diff --git a/api/payments/orchestrator/internal/service/orchestrator/payment_plan_analyzer.go b/api/payments/orchestrator/internal/service/orchestrator/payment_plan_analyzer.go new file mode 100644 index 00000000..dcc111f2 --- /dev/null +++ b/api/payments/orchestrator/internal/service/orchestrator/payment_plan_analyzer.go @@ -0,0 +1,123 @@ +package orchestrator + +import ( + "errors" + + "github.com/tech/sendico/payments/orchestrator/storage/model" + "github.com/tech/sendico/pkg/mlogger" + "go.uber.org/zap" +) + +type Liveness string + +const ( + StepFinal Liveness = "final" + StepRunnable Liveness = "runnable" + StepBlocked Liveness = "blocked" + StepDead Liveness = "dead" +) + +func buildPaymentStepIndex(plan *model.PaymentPlan) map[string]*model.PaymentStep { + idx := make(map[string]*model.PaymentStep, len(plan.Steps)) + for _, s := range plan.Steps { + idx[s.StepID] = s + } + return idx +} + +func buildExecutionStepIndex(plan *model.ExecutionPlan) map[string]*model.ExecutionStep { + index := make(map[string]*model.ExecutionStep, len(plan.Steps)) + for _, s := range plan.Steps { + if s == nil { + continue + } + index[s.Code] = s + } + return index +} + +func stepLiveness( + logger mlogger.Logger, + step *model.ExecutionStep, + pStepIdx map[string]*model.PaymentStep, + eStepIdx map[string]*model.ExecutionStep, +) Liveness { + + if step.IsTerminal() { + return StepFinal + } + + pStep, ok := pStepIdx[step.Code] + if !ok { + logger.Error("step missing in payment plan", + zap.String("step_id", step.Code), + ) + return StepDead + } + + for _, depID := range pStep.DependsOn { + dep := eStepIdx[depID] + if dep == nil { + logger.Warn("dependency missing in execution plan", + zap.String("step_id", step.Code), + zap.String("dep_id", depID), + ) + continue + } + + switch dep.State { + case model.OperationStateFailed: + return StepDead + } + } + + allSuccess := true + for _, depID := range pStep.DependsOn { + dep := eStepIdx[depID] + if dep == nil || dep.State != model.OperationStateSuccess { + allSuccess = false + break + } + } + + if allSuccess { + return StepRunnable + } + + return StepBlocked +} + +func analyzeExecutionPlan( + logger mlogger.Logger, + payment *model.Payment, +) (bool, bool, error) { + + if payment == nil || payment.ExecutionPlan == nil { + return true, false, nil + } + + eIdx := buildExecutionStepIndex(payment.ExecutionPlan) + pIdx := buildPaymentStepIndex(payment.PaymentPlan) + + hasRunnable := false + hasFailed := false + var rootErr error + + for _, s := range payment.ExecutionPlan.Steps { + live := stepLiveness(logger, s, pIdx, eIdx) + + if live == StepRunnable { + hasRunnable = true + } + + if s.State == model.OperationStateFailed { + hasFailed = true + if rootErr == nil && s.Error != "" { + rootErr = errors.New(s.Error) + } + } + } + + done := !hasRunnable + return done, hasFailed, rootErr +} diff --git a/api/payments/orchestrator/internal/service/orchestrator/payment_plan_executor.go b/api/payments/orchestrator/internal/service/orchestrator/payment_plan_executor.go index 51fdedf8..9482b746 100644 --- a/api/payments/orchestrator/internal/service/orchestrator/payment_plan_executor.go +++ b/api/payments/orchestrator/internal/service/orchestrator/payment_plan_executor.go @@ -2,7 +2,6 @@ package orchestrator import ( "context" - "errors" "github.com/tech/sendico/payments/orchestrator/storage" "github.com/tech/sendico/payments/orchestrator/storage/model" @@ -11,31 +10,6 @@ import ( "go.uber.org/zap" ) -func analyzeExecutionPlan(plan *model.ExecutionPlan) (done bool, failed bool, rootErr error) { - if plan == nil || len(plan.Steps) == 0 { - return true, false, nil - } - - done = true - for _, s := range plan.Steps { - if s == nil { - continue - } - - if s.State == model.OperationStateFailed { - failed = true - if rootErr == nil && s.Error != "" { - rootErr = errors.New(s.Error) - } - } - - if !isStepFinal(s) { // created/waiting/processing - done = false - } - } - return done, failed, rootErr -} - func buildStepIndex(plan *model.PaymentPlan) map[string]int { m := make(map[string]int, len(plan.Steps)) for i, s := range plan.Steps { @@ -63,64 +37,6 @@ func isStepFinal(step *model.ExecutionStep) bool { return false } -func stepCodeIsDependent(code string, previousSteps []string) bool { - for _, ps := range previousSteps { - if ps == code { - return true - } - } - return false -} - -func stepIsIndependent( - step *model.ExecutionStep, - plan *model.PaymentPlan, - execSteps map[string]*model.ExecutionStep, -) bool { - - for _, s := range plan.Steps { - if s.StepID != step.Code { - continue - } - - // Do not process step if it is already in a final state - if isStepFinal(step) { - return false - } - - // If the step has no dependencies, it is independent - if len(s.DependsOn) == 0 { - return true - } - - // All dependent steps must be successfully completed - for _, dep := range s.DependsOn { - depStep := execSteps[dep] - if depStep == nil || depStep.State != model.OperationStateSuccess { - return false - } - } - - return true - } - - return false -} - -func planStep(execStep *model.ExecutionStep, plan *model.PaymentPlan) *model.PaymentStep { - if (execStep == nil) || (plan == nil) { - return nil - } - for _, step := range plan.Steps { - if step != nil { - if step.StepID == execStep.Code { - return step - } - } - } - return nil -} - func (p *paymentExecutor) pickIndependentSteps( ctx context.Context, l *zap.Logger, @@ -262,14 +178,13 @@ func (p *paymentExecutor) executePaymentPlan( // Execute steps if err := p.pickWaitingSteps(ctx, logger, store, payment, quote); err != nil { logger.Warn("Step execution returned infrastructure error", zap.Error(err)) - return err } if err := store.Update(ctx, payment); err != nil { return err } - done, failed, rootErr := analyzeExecutionPlan(payment.ExecutionPlan) + done, failed, rootErr := analyzeExecutionPlan(logger, payment) if !done { return nil } diff --git a/api/payments/orchestrator/internal/service/orchestrator/payment_plan_order.go b/api/payments/orchestrator/internal/service/orchestrator/payment_plan_order.go index 5c71eaa1..59f10af0 100644 --- a/api/payments/orchestrator/internal/service/orchestrator/payment_plan_order.go +++ b/api/payments/orchestrator/internal/service/orchestrator/payment_plan_order.go @@ -1,74 +1,12 @@ package orchestrator import ( - "sort" "strings" "github.com/tech/sendico/payments/orchestrator/storage/model" "github.com/tech/sendico/pkg/merrors" ) -func planExecutionOrder(plan *model.PaymentPlan) ([]int, map[string]int, error) { - if plan == nil || len(plan.Steps) == 0 { - return nil, nil, merrors.InvalidArgument("payment plan: steps are required") - } - idToIndex := map[string]int{} - for idx, step := range plan.Steps { - if step == nil { - return nil, nil, merrors.InvalidArgument("payment plan: step is required") - } - id := planStepID(step, idx) - if _, exists := idToIndex[id]; exists { - return nil, nil, merrors.InvalidArgument("payment plan: duplicate step id") - } - idToIndex[id] = idx - } - - indegree := make([]int, len(plan.Steps)) - adj := make([][]int, len(plan.Steps)) - for idx, step := range plan.Steps { - for _, dep := range step.DependsOn { - key := strings.TrimSpace(dep) - if key == "" { - continue - } - depIdx, ok := idToIndex[key] - if !ok { - return nil, nil, merrors.InvalidArgument("payment plan: dependency missing") - } - adj[depIdx] = append(adj[depIdx], idx) - indegree[idx]++ - } - } - - queue := make([]int, 0, len(plan.Steps)) - for idx := range indegree { - if indegree[idx] == 0 { - queue = append(queue, idx) - } - } - sort.Ints(queue) - - order := make([]int, 0, len(plan.Steps)) - for len(queue) > 0 { - current := queue[0] - queue = queue[1:] - order = append(order, current) - for _, next := range adj[current] { - indegree[next]-- - if indegree[next] == 0 { - queue = append(queue, next) - } - } - sort.Ints(queue) - } - - if len(order) != len(plan.Steps) { - return nil, nil, merrors.InvalidArgument("payment plan: dependency cycle detected") - } - return order, idToIndex, nil -} - func executionStepsByCode(plan *model.ExecutionPlan) map[string]*model.ExecutionStep { result := map[string]*model.ExecutionStep{} if plan == nil { @@ -115,9 +53,6 @@ func stepDependenciesReady( merrors.InvalidArgument("payment plan: step is required") } - // ------------------------------------------------------------ - // DependsOn — это ПРОСТО готовность, не успех - // ------------------------------------------------------------ for _, dep := range step.DependsOn { key := strings.TrimSpace(dep) if key == "" { @@ -126,18 +61,18 @@ func stepDependenciesReady( execStep := execSteps[key] if execStep == nil { - // шага ещё не было → ждём + // step has not been started return false, true, false, nil } if execStep.State == model.OperationStateFailed || execStep.State == model.OperationStateCancelled { - // зависимость умерла → этот шаг уже невозможен + // dependency dead, step is impossible return false, false, true, nil } if !execStep.ReadyForNext() { - // шаг ещё в процессе → ждём + // step is processed return false, true, false, nil } } @@ -203,11 +138,11 @@ func stepDependenciesReady( } if execStep.IsTerminal() { - // завершился не фейлом → блокируем + // complete with fail, block return false, false, true, nil } - // ещё выполняется → ждём + // still exexuting, wait return false, true, false, nil } @@ -243,42 +178,6 @@ func stepDependenciesReady( } } -func commitAfterDependenciesSucceeded(step *model.PaymentStep, execSteps map[string]*model.ExecutionStep) bool { - if step == nil { - return false - } - - commitAfter := step.CommitAfter - if len(commitAfter) == 0 { - commitAfter = step.DependsOn - } - if len(commitAfter) == 0 { - return false - } - - for _, dep := range commitAfter { - key := strings.TrimSpace(dep) - if key == "" { - continue - } - - execStep := execSteps[key] - if execStep == nil { - return false - } - - switch execStep.State { - case model.OperationStateSuccess, - model.OperationStateSkipped: - continue - default: - return false - } - } - - return true -} - func cardPayoutDependenciesConfirmed( plan *model.PaymentPlan, execPlan *model.ExecutionPlan, diff --git a/api/payments/orchestrator/internal/service/orchestrator/payment_plan_steps.go b/api/payments/orchestrator/internal/service/orchestrator/payment_plan_steps.go index 478d100b..4eaa2510 100644 --- a/api/payments/orchestrator/internal/service/orchestrator/payment_plan_steps.go +++ b/api/payments/orchestrator/internal/service/orchestrator/payment_plan_steps.go @@ -38,8 +38,8 @@ func (p *paymentExecutor) executePlanStep( logger.Debug("Executing payment plan step") - if isStepFinal(execStep) { - logger.Debug("Step already in final state, skipping execution", + if execStep.IsTerminal() { + logger.Debug("Step already in terminal state, skipping execution", zap.String("state", string(execStep.State)), ) return false, nil @@ -282,18 +282,21 @@ func (p *paymentExecutor) executeSendStep( case model.RailProviderSettlement: logger.Debug("Preparing provider settlement transfer") - amount, err := requireMoney(cloneMoney(payment.Intent.Amount), "provider settlement amount") + amount, err := requireMoney(cloneMoney(payment.LastQuote.DebitSettlementAmount), "provider settlement amount") if err != nil { - logger.Warn("Invalid provider settlement amount", zap.Error(err)) + logger.Warn("Invalid provider settlement amount", zap.Error(err), zap.Any("settlement", payment.LastQuote.DebitSettlementAmount)) return false, err } + logger.Debug("Expected settlement amount", zap.String("amount", amount.Amount), zap.String("currency", amount.Currency)) fee, err := requireMoney(cloneMoney(payment.LastQuote.ExpectedFeeTotal), "provider settlement amount") if err != nil { - logger.Warn("Invalid provider settlement amount", zap.Error(err)) + logger.Warn("Invalid fee settlement amount", zap.Error(err)) return false, err } if fee.Currency != amount.Currency { - logger.Warn("Fee and amount currencies do not match") + logger.Warn("Fee and amount currencies do not match", + zap.String("amount_currency", amount.Currency), zap.String("fee_currency", fee.Currency), + ) return false, merrors.DataConflict("settlement payment: currencies mismatch") } diff --git a/api/payments/orchestrator/internal/service/orchestrator/quote_engine.go b/api/payments/orchestrator/internal/service/orchestrator/quote_engine.go index 392b1847..4aa1f576 100644 --- a/api/payments/orchestrator/internal/service/orchestrator/quote_engine.go +++ b/api/payments/orchestrator/internal/service/orchestrator/quote_engine.go @@ -96,6 +96,7 @@ func (s *Service) buildPaymentQuote(ctx context.Context, orgRef string, req *orc quote := &orchestratorv1.PaymentQuote{ DebitAmount: debitAmount, + DebitSettlementAmount: payAmount, ExpectedSettlementAmount: settlementAmount, ExpectedFeeTotal: feeTotal, FeeLines: feeLines, diff --git a/api/payments/orchestrator/storage/model/payment.go b/api/payments/orchestrator/storage/model/payment.go index 3b3f540a..10d1d51c 100644 --- a/api/payments/orchestrator/storage/model/payment.go +++ b/api/payments/orchestrator/storage/model/payment.go @@ -253,6 +253,7 @@ type Customer struct { // PaymentQuoteSnapshot stores the latest quote info. type PaymentQuoteSnapshot struct { DebitAmount *paymenttypes.Money `bson:"debitAmount,omitempty" json:"debitAmount,omitempty"` + DebitSettlementAmount *paymenttypes.Money `bson:"debitSettlementAmount,omitempty" json:"debitSettlementAmount,omitempty"` ExpectedSettlementAmount *paymenttypes.Money `bson:"expectedSettlementAmount,omitempty" json:"expectedSettlementAmount,omitempty"` ExpectedFeeTotal *paymenttypes.Money `bson:"expectedFeeTotal,omitempty" json:"expectedFeeTotal,omitempty"` FeeLines []*paymenttypes.FeeLine `bson:"feeLines,omitempty" json:"feeLines,omitempty"` @@ -326,6 +327,10 @@ func (s *ExecutionStep) IsSuccess() bool { return s.State == OperationStateSuccess } +func (s *ExecutionStep) IsFailed() bool { + return s.State == OperationStateFailed +} + func (s *ExecutionStep) ReadyForNext() bool { switch s.State { case OperationStateSuccess, diff --git a/api/pkg/go.mod b/api/pkg/go.mod index d7053f8d..50768a5e 100644 --- a/api/pkg/go.mod +++ b/api/pkg/go.mod @@ -5,7 +5,7 @@ go 1.24.0 require ( github.com/casbin/casbin/v2 v2.135.0 github.com/casbin/mongodb-adapter/v4 v4.3.0 - github.com/go-chi/chi/v5 v5.2.4 + github.com/go-chi/chi/v5 v5.2.5 github.com/google/uuid v1.6.0 github.com/mattn/go-colorable v0.1.14 github.com/mitchellh/mapstructure v1.5.0 diff --git a/api/pkg/go.sum b/api/pkg/go.sum index 3b2cb693..984f886e 100644 --- a/api/pkg/go.sum +++ b/api/pkg/go.sum @@ -43,8 +43,8 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= diff --git a/api/proto/payments/orchestrator/v1/orchestrator.proto b/api/proto/payments/orchestrator/v1/orchestrator.proto index 7306ecbe..47934bce 100644 --- a/api/proto/payments/orchestrator/v1/orchestrator.proto +++ b/api/proto/payments/orchestrator/v1/orchestrator.proto @@ -141,6 +141,7 @@ message PaymentQuote { oracle.v1.Quote fx_quote = 6; chain.gateway.v1.EstimateTransferFeeResponse network_fee = 7; string quote_ref = 8; + common.money.v1.Money debit_settlement_amount = 9; } message PaymentQuoteAggregate { diff --git a/api/server/go.mod b/api/server/go.mod index 56d6c872..16afa552 100644 --- a/api/server/go.mod +++ b/api/server/go.mod @@ -15,7 +15,7 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.32.7 github.com/aws/aws-sdk-go-v2/credentials v1.19.7 github.com/aws/aws-sdk-go-v2/service/s3 v1.96.0 - github.com/go-chi/chi/v5 v5.2.4 + github.com/go-chi/chi/v5 v5.2.5 github.com/go-chi/cors v1.2.2 github.com/go-chi/jwtauth/v5 v5.3.3 github.com/go-chi/metrics v0.1.1 diff --git a/api/server/go.sum b/api/server/go.sum index 7c73e5b2..8feb1ff0 100644 --- a/api/server/go.sum +++ b/api/server/go.sum @@ -88,8 +88,8 @@ github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE= github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw= -github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= -github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= +github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= +github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE= github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/jwtauth/v5 v5.3.3 h1:50Uzmacu35/ZP9ER2Ht6SazwPsnLQ9LRJy6zTZJpHEo= diff --git a/api/server/interface/api/sresponse/payment.go b/api/server/interface/api/sresponse/payment.go index 13eb0982..8afd8d47 100644 --- a/api/server/interface/api/sresponse/payment.go +++ b/api/server/interface/api/sresponse/payment.go @@ -38,6 +38,7 @@ type FxQuote struct { type PaymentQuote struct { QuoteRef string `json:"quoteRef,omitempty"` DebitAmount *paymenttypes.Money `json:"debitAmount,omitempty"` + DebitSettlementAmount *paymenttypes.Money `json:"debitSettlementAmount,omitempty"` ExpectedSettlementAmount *paymenttypes.Money `json:"expectedSettlementAmount,omitempty"` ExpectedFeeTotal *paymenttypes.Money `json:"expectedFeeTotal,omitempty"` FeeLines []FeeLine `json:"feeLines,omitempty"` @@ -188,6 +189,7 @@ func toPaymentQuote(q *orchestratorv1.PaymentQuote) *PaymentQuote { return &PaymentQuote{ QuoteRef: q.GetQuoteRef(), DebitAmount: toMoney(q.GetDebitAmount()), + DebitSettlementAmount: toMoney(q.GetDebitSettlementAmount()), ExpectedSettlementAmount: toMoney(q.GetExpectedSettlementAmount()), ExpectedFeeTotal: toMoney(q.GetExpectedFeeTotal()), FeeLines: toFeeLines(q.GetFeeLines()), diff --git a/frontend/pshared/lib/data/dto/payment/payment_quote.dart b/frontend/pshared/lib/data/dto/payment/payment_quote.dart index 19ca95c8..b1e665d9 100644 --- a/frontend/pshared/lib/data/dto/payment/payment_quote.dart +++ b/frontend/pshared/lib/data/dto/payment/payment_quote.dart @@ -12,6 +12,7 @@ part 'payment_quote.g.dart'; class PaymentQuoteDTO { final String? quoteRef; final MoneyDTO? debitAmount; + final MoneyDTO? debitSettlementAmount; final MoneyDTO? expectedSettlementAmount; final MoneyDTO? expectedFeeTotal; final List? feeLines; @@ -21,6 +22,7 @@ class PaymentQuoteDTO { const PaymentQuoteDTO({ this.quoteRef, this.debitAmount, + this.debitSettlementAmount, this.expectedSettlementAmount, this.expectedFeeTotal, this.feeLines, diff --git a/frontend/pshared/lib/data/mapper/payment/payment_quote.dart b/frontend/pshared/lib/data/mapper/payment/payment_quote.dart index 7e9dea20..5763a59c 100644 --- a/frontend/pshared/lib/data/mapper/payment/payment_quote.dart +++ b/frontend/pshared/lib/data/mapper/payment/payment_quote.dart @@ -11,6 +11,7 @@ extension PaymentQuoteDTOMapper on PaymentQuoteDTO { quoteRef: quoteRef, idempotencyKey: idempotencyKey, debitAmount: debitAmount?.toDomain(), + debitSettlementAmount: debitSettlementAmount?.toDomain(), expectedSettlementAmount: expectedSettlementAmount?.toDomain(), expectedFeeTotal: expectedFeeTotal?.toDomain(), feeLines: feeLines?.map((line) => line.toDomain()).toList(), @@ -23,6 +24,7 @@ extension PaymentQuoteMapper on PaymentQuote { PaymentQuoteDTO toDTO() => PaymentQuoteDTO( quoteRef: quoteRef, debitAmount: debitAmount?.toDTO(), + debitSettlementAmount: debitSettlementAmount?.toDTO(), expectedSettlementAmount: expectedSettlementAmount?.toDTO(), expectedFeeTotal: expectedFeeTotal?.toDTO(), feeLines: feeLines?.map((line) => line.toDTO()).toList(), diff --git a/frontend/pshared/lib/models/payment/quote/quote.dart b/frontend/pshared/lib/models/payment/quote/quote.dart index da8eb73c..c6940043 100644 --- a/frontend/pshared/lib/models/payment/quote/quote.dart +++ b/frontend/pshared/lib/models/payment/quote/quote.dart @@ -8,6 +8,7 @@ class PaymentQuote { final String? quoteRef; final String? idempotencyKey; final Money? debitAmount; + final Money? debitSettlementAmount; final Money? expectedSettlementAmount; final Money? expectedFeeTotal; final List? feeLines; @@ -18,6 +19,7 @@ class PaymentQuote { required this.quoteRef, required this.idempotencyKey, required this.debitAmount, + required this.debitSettlementAmount, required this.expectedSettlementAmount, required this.expectedFeeTotal, required this.feeLines, -- 2.49.1