observe.confirmation for chain gateway #325

Merged
tech merged 1 commits from chain-324 into main 2026-01-26 02:12:44 +00:00
6 changed files with 72 additions and 37 deletions

View File

@@ -132,7 +132,7 @@ func (c *createManagedWalletCommand) Execute(ctx context.Context, req *chainv1.C
wallet := &model.ManagedWallet{ wallet := &model.ManagedWallet{
Describable: pkgmodel.Describable{ Describable: pkgmodel.Describable{
Name: name, Name: name,
Description: desc.Description, Description: description,
}, },
IdempotencyKey: idempotencyKey, IdempotencyKey: idempotencyKey,
WalletRef: walletRef, WalletRef: walletRef,

View File

@@ -208,7 +208,7 @@ func (s *Service) startDiscoveryAnnouncers() {
Service: "CRYPTO_RAIL_GATEWAY", Service: "CRYPTO_RAIL_GATEWAY",
Rail: "CRYPTO", Rail: "CRYPTO",
Network: network.Name, Network: network.Name,
Operations: []string{"balance.read", "payin.crypto", "payout.crypto", "fee.send"}, Operations: []string{"balance.read", "payin.crypto", "payout.crypto", "fee.send", "observe.confirm"},
Currencies: currencies, Currencies: currencies,
InvokeURI: s.invokeURI, InvokeURI: s.invokeURI,
Version: version, Version: version,

View File

@@ -109,17 +109,26 @@ func updateExecutionStepFromTransfer(plan *model.ExecutionPlan, event *chainv1.T
if transferRef == "" { if transferRef == "" {
return nil return nil
} }
step := findExecutionStepByTransferRef(plan, transferRef) if status := executionStepStatusFromTransferStatus(transfer.GetStatus()); status != "" {
var updated *model.ExecutionStep
for _, step := range plan.Steps {
if step == nil { if step == nil {
return nil continue
}
if !strings.EqualFold(strings.TrimSpace(step.TransferRef), transferRef) {
continue
} }
if step.TransferRef == "" { if step.TransferRef == "" {
step.TransferRef = transferRef step.TransferRef = transferRef
} }
if status := executionStepStatusFromTransferStatus(transfer.GetStatus()); status != "" {
setExecutionStepStatus(step, status) setExecutionStepStatus(step, status)
if updated == nil {
updated = step
} }
return step }
return updated
}
return nil
} }
func executionStepStatusFromTransferStatus(status chainv1.TransferStatus) string { func executionStepStatusFromTransferStatus(status chainv1.TransferStatus) string {

View File

@@ -100,6 +100,53 @@ func blockStepConfirmed(plan *model.PaymentPlan, execPlan *model.ExecutionPlan)
return false return false
} }
func linkRailObservation(payment *model.Payment, rail model.Rail, referenceID, dependsOn string) {
if payment == nil || payment.PaymentPlan == nil {
return
}
ref := strings.TrimSpace(referenceID)
if ref == "" {
return
}
plan := payment.PaymentPlan
execPlan := ensureExecutionPlanForPlan(payment, plan)
if execPlan == nil {
return
}
dep := strings.TrimSpace(dependsOn)
for idx, planStep := range plan.Steps {
if planStep == nil {
continue
}
if planStep.Rail != rail || planStep.Action != model.RailOperationObserveConfirm {
continue
}
if dep != "" {
matched := false
for _, entry := range planStep.DependsOn {
if strings.EqualFold(strings.TrimSpace(entry), dep) {
matched = true
break
}
}
if !matched {
continue
}
}
if idx >= len(execPlan.Steps) {
continue
}
execStep := execPlan.Steps[idx]
if execStep == nil {
execStep = &model.ExecutionStep{Code: planStepID(planStep, idx), Description: describePlanStep(planStep)}
execPlan.Steps[idx] = execStep
}
if execStep.TransferRef == "" {
execStep.TransferRef = ref
}
}
}
func planStepID(step *model.PaymentStep, idx int) string { func planStepID(step *model.PaymentStep, idx int) string {
if step != nil { if step != nil {
if val := strings.TrimSpace(step.StepID); val != "" { if val := strings.TrimSpace(step.StepID); val != "" {

View File

@@ -110,11 +110,15 @@ func (p *paymentExecutor) executeSendStep(ctx context.Context, payment *model.Pa
if err != nil { if err != nil {
return false, err return false, err
} }
stepID := planStepID(step, idx)
execStep.TransferRef = strings.TrimSpace(result.ReferenceID) execStep.TransferRef = strings.TrimSpace(result.ReferenceID)
exec := ensureExecutionRefs(payment) exec := ensureExecutionRefs(payment)
if exec.ChainTransferRef == "" && execStep.TransferRef != "" { if exec.ChainTransferRef == "" && execStep.TransferRef != "" {
exec.ChainTransferRef = execStep.TransferRef exec.ChainTransferRef = execStep.TransferRef
} }
if execStep.TransferRef != "" {
linkRailObservation(payment, step.Rail, execStep.TransferRef, stepID)
}
setExecutionStepStatus(execStep, executionStepStatusSubmitted) setExecutionStepStatus(execStep, executionStepStatusSubmitted)
return true, nil return true, nil
case model.RailCardPayout: case model.RailCardPayout:

View File

@@ -117,30 +117,5 @@ func paymentGatewayTargetChatID(payment *model.Payment) string {
} }
func linkProviderSettlementObservation(payment *model.Payment, requestID string) { func linkProviderSettlementObservation(payment *model.Payment, requestID string) {
if payment == nil || payment.PaymentPlan == nil || payment.ExecutionPlan == nil { linkRailObservation(payment, model.RailProviderSettlement, requestID, "")
return
}
requestID = strings.TrimSpace(requestID)
if requestID == "" {
return
}
for idx, planStep := range payment.PaymentPlan.Steps {
if planStep == nil {
continue
}
if planStep.Rail != model.RailProviderSettlement || planStep.Action != model.RailOperationObserveConfirm {
continue
}
if idx >= len(payment.ExecutionPlan.Steps) {
continue
}
execStep := payment.ExecutionPlan.Steps[idx]
if execStep == nil {
execStep = &model.ExecutionStep{Code: planStepID(planStep, idx), Description: describePlanStep(planStep)}
payment.ExecutionPlan.Steps[idx] = execStep
}
if execStep.TransferRef == "" {
execStep.TransferRef = requestID
}
}
} }