feat: add retries for swap refund (#1914)

* feat: add retries for swap refund

* chore: address feedback
This commit is contained in:
Adithya Vardhan 2025-11-18 09:35:20 +05:30 committed by GitHub
parent 87146bf80b
commit 1fde06a61d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 67 additions and 33 deletions

View file

@ -756,7 +756,7 @@ func (api *api) RefundSwap(refundSwapRequest *RefundSwapRequest) error {
if api.svc.GetSwapsService() == nil {
return errors.New("SwapsService not started")
}
return api.svc.GetSwapsService().RefundSwap(refundSwapRequest.SwapId, refundSwapRequest.Address)
return api.svc.GetSwapsService().RefundSwap(refundSwapRequest.SwapId, refundSwapRequest.Address, false)
}
func (api *api) GetAutoSwapConfig() (*GetAutoSwapConfigResponse, error) {

View file

@ -58,7 +58,7 @@ type SwapsService interface {
SwapIn(amount uint64, autoSwap bool) (*SwapResponse, error)
GetSwapOutInfo() (*SwapInfo, error)
GetSwapInInfo() (*SwapInfo, error)
RefundSwap(swapId, address string) error
RefundSwap(swapId, address string, enableRetries bool) error
GetSwap(swapId string) (*Swap, error)
ListSwaps() ([]Swap, error)
}
@ -583,7 +583,7 @@ func (svc *swapsService) markSwapState(dbSwap *db.Swap, state string) {
}
}
func (svc *swapsService) RefundSwap(swapId, address string) error {
func (svc *swapsService) RefundSwap(swapId, address string, enableRetries bool) error {
var swap db.Swap
err := svc.db.Limit(1).Find(&swap, &db.Swap{
SwapId: swapId,
@ -674,11 +674,6 @@ func (svc *swapsService) RefundSwap(swapId, address string) error {
logger.Logger.WithField("swapId", swapId).WithError(err).Error("Failed to find lockup address output")
return err
}
feeRates, err := svc.getFeeRates()
if err != nil {
logger.Logger.WithField("swapId", swapId).WithError(err).Error("Failed to fetch fee rate to create claim transaction")
return err
}
if address == "" {
address, err = svc.lnClient.GetNewOnchainAddress(svc.ctx)
@ -699,31 +694,70 @@ func (svc *swapsService) RefundSwap(swapId, address string) error {
return err
}
fastestFee := float64(feeRates.FastestFee)
refundTransaction, _, err := boltz.ConstructTransaction(
network,
boltz.CurrencyBtc,
[]boltz.OutputDetails{
{
SwapId: swapId,
SwapType: boltz.NormalSwap,
Address: address,
LockupTransaction: lockupTransaction,
TimeoutBlockHeight: swapTransactionResp.TimeoutBlockHeight,
Vout: vout,
PrivateKey: ourKeys,
SwapTree: tree,
Cooperative: true,
var refundTransaction boltz.Transaction
for i := 0; ; i++ {
select {
case <-svc.ctx.Done():
logger.Logger.WithField("swapId", swapId).Info("Swap refund context cancelled")
return nil
case <-time.After(time.Duration(min(i*5, 30)) * time.Second): // timeout
}
nodeInfo, err := svc.lnClient.GetInfo(svc.ctx)
if err != nil {
logger.Logger.WithError(err).WithFields(logrus.Fields{
"swapId": swapId,
"iteration": i,
}).WithError(err).Error("Failed to request node info")
continue
}
feeRates, err := svc.getFeeRates()
if err != nil {
logger.Logger.WithError(err).WithFields(logrus.Fields{
"swapId": swapId,
"iteration": i,
}).Error("Failed to fetch fee rate to create claim transaction")
continue
}
cooperative := swapTransactionResp.TimeoutBlockHeight > nodeInfo.BlockHeight
fastestFee := float64(feeRates.FastestFee)
refundTransaction, _, err = boltz.ConstructTransaction(
network,
boltz.CurrencyBtc,
[]boltz.OutputDetails{
{
SwapId: swapId,
SwapType: boltz.NormalSwap,
Address: address,
LockupTransaction: lockupTransaction,
TimeoutBlockHeight: swapTransactionResp.TimeoutBlockHeight,
Vout: vout,
PrivateKey: ourKeys,
SwapTree: tree,
Cooperative: cooperative,
},
},
},
boltz.Fee{
SatsPerVbyte: &fastestFee,
},
svc.boltzApi,
)
if err != nil {
logger.Logger.WithField("swapId", swapId).WithError(err).Error("Could not create claim transaction")
return err
boltz.Fee{
SatsPerVbyte: &fastestFee,
},
svc.boltzApi,
)
if err != nil {
logger.Logger.WithFields(logrus.Fields{
"swapId": swapId,
"iteration": i,
"cooperative": cooperative,
}).WithError(err).Error("Could not create claim transaction refund")
if enableRetries && cooperative {
continue
}
return err
}
break
}
vout, _, _ = refundTransaction.FindVout(network, address)
@ -972,7 +1006,7 @@ func (svc *swapsService) startSwapInListener(swap *db.Swap) {
"reason": update.Status,
}).Error("Swap in failed, initiating refund")
err = svc.RefundSwap(swap.SwapId, "")
err = svc.RefundSwap(swap.SwapId, "", true)
if err != nil {
logger.Logger.WithError(err).WithFields(logrus.Fields{
"swapId": swap.SwapId,