diff --git a/database/database.go b/database/database.go index 070a3508..a0e9e242 100644 --- a/database/database.go +++ b/database/database.go @@ -449,23 +449,29 @@ func (database *Database) QueryRow(query string, args ...any) *sql.Row { return database.db.QueryRow(query, args...) } -func (database *Database) QueryAnySwap(id string) (*Swap, *ReverseSwap, *ChainSwap, error) { +type SomeSwap struct { + Normal *Swap + Reverse *ReverseSwap + Chain *ChainSwap +} + +func (database *Database) QueryAnySwap(id string) (*SomeSwap, error) { swap, err := database.QuerySwap(id) if err == nil { - return swap, nil, nil, nil + return &SomeSwap{Normal: swap}, nil } reverseSwap, err := database.QueryReverseSwap(id) if err == nil { - return nil, reverseSwap, nil, nil + return &SomeSwap{Reverse: reverseSwap}, nil } chainSwap, err := database.QueryChainSwap(id) if err == nil { - return nil, nil, chainSwap, nil + return &SomeSwap{Chain: chainSwap}, nil } - return nil, nil, nil, fmt.Errorf("could not find any type of Swap with ID %s", id) + return nil, fmt.Errorf("could not find any type of Swap with ID %s", id) } func (database *Database) QueryAllRefundableSwaps(tenantId *Id, currency boltz.Currency, currentHeight uint32) ([]*Swap, []*ChainSwap, error) { diff --git a/nursery/chain.go b/nursery/chain.go index ce1ecf0d..cfa98ce3 100644 --- a/nursery/chain.go +++ b/nursery/chain.go @@ -26,7 +26,6 @@ func (nursery *Nursery) RegisterChainSwap(chainSwap database.ChainSwap) error { if err := nursery.registerSwaps([]string{chainSwap.Id}); err != nil { return err } - nursery.sendChainSwapUpdate(chainSwap) return nil } @@ -123,9 +122,6 @@ func (nursery *Nursery) getChainSwapRefundOutput(swap *database.ChainSwap) *Outp if err := nursery.database.AddChainSwapOnchainFee(swap, fee); err != nil { return fmt.Errorf("could not add onchain fee in db: %s", err) } - - nursery.sendChainSwapUpdate(*swap) - return nil }, func(err error) { @@ -139,43 +135,35 @@ func (nursery *Nursery) handleChainSwapError(swap *database.ChainSwap, err error logger.Error(dbErr.Error()) } logger.Errorf("Chain Swap %s error: %s", swap.Id, err) - nursery.sendChainSwapUpdate(*swap) } -func (nursery *Nursery) handleChainSwapStatus(swap *database.ChainSwap, status boltz.SwapStatusResponse) { +func (nursery *Nursery) handleChainSwapStatus(tx *database.Transaction, swap *database.ChainSwap, status boltz.SwapStatusResponse) error { parsedStatus := boltz.ParseEvent(status.Status) if parsedStatus == swap.Status { logger.Debugf("Status of Chain Swap %s is %s already", swap.Id, parsedStatus) - return + return nil } logger.Infof("Status of Chain Swap %s changed to: %s", swap.Id, parsedStatus) - handleError := func(format string, args ...any) { - nursery.handleChainSwapError(swap, fmt.Errorf(format, args...)) - } - if swap.FromData.LockupTransactionId == "" || swap.ToData.LockupTransactionId == "" { response, err := nursery.boltz.GetChainSwapTransactions(swap.Id) if err != nil { var boltzErr boltz.Error if !errors.As(err, &boltzErr) { - handleError("Could not get lockup tx from boltz: " + err.Error()) - return + return fmt.Errorf("get lockup tx from boltz: %w", err) } } else { if swap.FromData.LockupTransactionId == "" && response.UserLock != nil { if err := nursery.setChainSwapLockupTransaction(swap, swap.FromData, response.UserLock.Transaction.Id); err != nil { - handleError("Could not set lockup transaction in database: " + err.Error()) - return + return fmt.Errorf("could not set lockup transaction in database: %w", err) } logger.Infof("Found user lockup for Chain Swap %s", swap.Id) } if swap.ToData.LockupTransactionId == "" && response.ServerLock != nil { if err := nursery.setChainSwapLockupTransaction(swap, swap.ToData, response.ServerLock.Transaction.Id); err != nil { - handleError("Could not set lockup transaction in database: " + err.Error()) - return + return fmt.Errorf("could not set lockup transaction in database: %w", err) } logger.Infof("Found server lockup for Chain Swap %s", swap.Id) } @@ -192,42 +180,30 @@ func (nursery *Nursery) handleChainSwapStatus(swap *database.ChainSwap, status b // TODO: store error logger.Warnf("Boltz did not give us a new quote for Chain Swap %s: %v", swap.Id, quoteError) } else { - handleError("could not get quote: %w", err) - return + return fmt.Errorf("could not get quote: %w", err) } } if quote != nil { result, err := nursery.onchain.FindOutput(chainOutputArgs(swap.FromData)) if err != nil { - handleError(err.Error()) - return + return fmt.Errorf("could not find lockup vout: %w", err) } if err := nursery.CheckAmounts(boltz.ChainSwap, swap.Pair, result.Value, quote.Amount, swap.ServiceFeePercent); err != nil { - handleError("quote amounts not correct: %w", err) - return + return fmt.Errorf("quote amounts not correct: %w", err) } if err := nursery.boltz.AcceptChainSwapQuote(swap.Id, quote); err != nil { - handleError("could not accept quote: %w", err) - return + return fmt.Errorf("could not accept quote: %w", err) } - err = nursery.database.RunTx(func(tx *database.Transaction) error { - if err := tx.SetChainSwapAmount(swap.ToData, quote.Amount); err != nil { - return fmt.Errorf("to amount: %w", err) - } - - if err := tx.SetChainSwapAmount(swap.FromData, result.Value); err != nil { - return fmt.Errorf("from amount: %w", err) - } - return nil - }) - if err != nil { - handleError("could not update chain swap amounts in database: %w", err) - return + if err := tx.SetChainSwapAmount(swap.ToData, quote.Amount); err != nil { + return fmt.Errorf("update to to amount: %w", err) } + if err := tx.SetChainSwapAmount(swap.FromData, result.Value); err != nil { + return fmt.Errorf("update from from amount: %w", err) + } } } @@ -238,8 +214,7 @@ func (nursery *Nursery) handleChainSwapStatus(swap *database.ChainSwap, status b output := nursery.getChainSwapClaimOutput(swap) if _, err := nursery.createTransaction(swap.Pair.To, []*Output{output}); err != nil { - logger.Infof("Could not claim chain swap output: %s", err) - return + return fmt.Errorf("could not claim chain swap output: %w", err) } default: } @@ -247,10 +222,8 @@ func (nursery *Nursery) handleChainSwapStatus(swap *database.ChainSwap, status b logger.Debugf("Updating status of Chain Swap %s to %s", swap.Id, parsedStatus) err := nursery.database.UpdateChainSwapStatus(swap, parsedStatus) - if err != nil { - handleError(fmt.Sprintf("Could not update status of Chain Swap %s to %s: %s", swap.Id, parsedStatus, err)) - return + return fmt.Errorf("could not update status to %s: %w", parsedStatus, err) } if parsedStatus.IsCompletedStatus() { @@ -259,13 +232,11 @@ func (nursery *Nursery) handleChainSwapStatus(swap *database.ChainSwap, status b logger.Infof("Chain Swap service fee: %dsat onchain fee: %dsat", serviceFee, *swap.OnchainFee) if err := nursery.database.SetChainSwapServiceFee(swap, serviceFee); err != nil { - handleError("Could not set swap service fee in database: " + err.Error()) - return + return fmt.Errorf("could not set swap service fee in database: %w", err) } if err := nursery.database.UpdateChainSwapState(swap, boltzrpc.SwapState_SUCCESSFUL, ""); err != nil { - handleError(err.Error()) - return + return fmt.Errorf("could not update swap state: %w", err) } } else if parsedStatus.IsFailedStatus() { // only set to SERVER_ERROR if we are not eligible for a new quote @@ -274,20 +245,17 @@ func (nursery *Nursery) handleChainSwapStatus(swap *database.ChainSwap, status b if swap.State == boltzrpc.SwapState_PENDING { if err := nursery.database.UpdateChainSwapState(swap, boltzrpc.SwapState_SERVER_ERROR, ""); err != nil { - handleError(err.Error()) - return + return fmt.Errorf("could not update swap state: %w", err) } } if swap.FromData.LockupTransactionId != "" { if _, err := nursery.RefundSwaps(swap.Pair.From, nil, []*database.ChainSwap{swap}); err != nil { - handleError("Could not refund Swap " + swap.Id + ": " + err.Error()) - return + return fmt.Errorf("could not refund swap: %w", err) } } } } - nursery.sendChainSwapUpdate(*swap) - + return nil } diff --git a/nursery/nursery.go b/nursery/nursery.go index 0b0c3279..1b26b6a3 100644 --- a/nursery/nursery.go +++ b/nursery/nursery.go @@ -218,6 +218,42 @@ func (nursery *Nursery) recoverSwaps() error { return nursery.registerSwaps(swapIds) } +func (nursery *Nursery) setSomeSwapError(swap *database.SomeSwap, err error) { + var dbErr error + if swap.Normal != nil { + dbErr = nursery.database.UpdateSwapState(swap.Normal, boltzrpc.SwapState_ERROR, err.Error()) + logger.Errorf("Submarine Swap %s error: %v", swap.Normal.Id, err) + } + if swap.Reverse != nil { + dbErr = nursery.database.UpdateReverseSwapState(swap.Reverse, boltzrpc.SwapState_ERROR, err.Error()) + logger.Errorf("Reverse Swap %s error: %v", swap.Reverse.Id, err) + } + if swap.Chain != nil { + dbErr = nursery.database.UpdateChainSwapState(swap.Chain, boltzrpc.SwapState_ERROR, err.Error()) + logger.Errorf("Chain Swap %s error: %v", swap.Chain.Id, err) + } + if dbErr != nil { + logger.Error(dbErr.Error()) + } +} + +func (nursery *Nursery) sendSomeSwapUpdate(swapId string) { + swap, err := nursery.database.QueryAnySwap(swapId) + if err != nil { + logger.Errorf("Could not query swap %s: %v", swapId, err) + return + } + if swap.Normal != nil { + nursery.sendSwapUpdate(*swap.Normal) + } + if swap.Chain != nil { + nursery.sendChainSwapUpdate(*swap.Chain) + } + if swap.Reverse != nil { + nursery.sendReverseSwapUpdate(*swap.Reverse) + } +} + func (nursery *Nursery) startSwapListener() { logger.Infof("Starting swap update listener") @@ -227,7 +263,7 @@ func (nursery *Nursery) startSwapListener() { for status := range nursery.boltzWs.Updates { logger.Debugf("Swap %s status update: %s", status.Id, status.Status) - swap, reverseSwap, chainSwap, err := nursery.database.QueryAnySwap(status.Id) + someSwap, err := nursery.database.QueryAnySwap(status.Id) if err != nil { logger.Errorf("Could not query swap %s: %v", status.Id, err) continue @@ -236,13 +272,20 @@ func (nursery *Nursery) startSwapListener() { logger.Warnf("Boltz could not find Swap %s: %s ", status.Id, status.Error) continue } - if swap != nil { - nursery.handleSwapStatus(swap, status.SwapStatusResponse) - } else if reverseSwap != nil { - nursery.handleReverseSwapStatus(reverseSwap, status.SwapStatusResponse) - } else if chainSwap != nil { - nursery.handleChainSwapStatus(chainSwap, status.SwapStatusResponse) + err = nursery.database.RunTx(func(tx *database.Transaction) error { + if someSwap.Normal != nil { + return nursery.handleSwapStatus(tx, someSwap.Normal, status.SwapStatusResponse) + } else if someSwap.Reverse != nil { + return nursery.handleReverseSwapStatus(tx, someSwap.Reverse, status.SwapStatusResponse) + } else if someSwap.Chain != nil { + return nursery.handleChainSwapStatus(tx, someSwap.Chain, status.SwapStatusResponse) + } + return nil + }) + if err != nil { + nursery.setSomeSwapError(someSwap, err) } + nursery.sendSomeSwapUpdate(status.Id) } nursery.waitGroup.Done() }() diff --git a/nursery/reverse.go b/nursery/reverse.go index bc76416e..7c438e08 100644 --- a/nursery/reverse.go +++ b/nursery/reverse.go @@ -30,7 +30,6 @@ func (nursery *Nursery) RegisterReverseSwap(reverseSwap database.ReverseSwap) er if err := nursery.registerSwaps([]string{reverseSwap.Id}); err != nil { return err } - nursery.sendReverseSwapUpdate(reverseSwap) if err := nursery.payReverseSwap(&reverseSwap); err != nil { return err } @@ -128,16 +127,15 @@ func (nursery *Nursery) handleReverseSwapError(reverseSwap *database.ReverseSwap logger.Error("Could not update Reverse Swap state: " + dbErr.Error()) } logger.Errorf("Reverse Swap %s error: %s", reverseSwap.Id, err) - nursery.sendReverseSwapUpdate(*reverseSwap) } // TODO: fail swap after "transaction.failed" event -func (nursery *Nursery) handleReverseSwapStatus(reverseSwap *database.ReverseSwap, event boltz.SwapStatusResponse) { +func (nursery *Nursery) handleReverseSwapStatus(tx *database.Transaction, reverseSwap *database.ReverseSwap, event boltz.SwapStatusResponse) error { parsedStatus := boltz.ParseEvent(event.Status) if parsedStatus == reverseSwap.Status { logger.Debugf("Status of Reverse Swap %s is %s already", reverseSwap.Id, parsedStatus) - return + return nil } logger.Infof("Status of Reverse Swap %s changed to: %s", reverseSwap.Id, parsedStatus) @@ -148,19 +146,17 @@ func (nursery *Nursery) handleReverseSwapStatus(reverseSwap *database.ReverseSwa switch parsedStatus { case boltz.TransactionMempool: - if err := nursery.database.SetReverseSwapPaidAt(reverseSwap, time.Now()); err != nil { - handleError("Could not set paid at in database: " + err.Error()) - return + if err := tx.SetReverseSwapPaidAt(reverseSwap, time.Now()); err != nil { + return fmt.Errorf("set paid at: %w", err) } fallthrough case boltz.TransactionConfirmed: - err := nursery.database.SetReverseSwapLockupTransactionId(reverseSwap, event.Transaction.Id) + err := tx.SetReverseSwapLockupTransactionId(reverseSwap, event.Transaction.Id) if err != nil { - handleError("Could not set lockup transaction id in database: " + err.Error()) - return + return fmt.Errorf("set lockup transaction id: %w", err) } if parsedStatus == boltz.TransactionMempool && !reverseSwap.AcceptZeroConf { @@ -172,14 +168,12 @@ func (nursery *Nursery) handleReverseSwapStatus(reverseSwap *database.ReverseSwa output := nursery.getReverseSwapClaimOutput(reverseSwap) if _, err := nursery.createTransaction(reverseSwap.Pair.To, []*Output{output}); err != nil { - logger.Info("Could not claim: " + err.Error()) - return + return fmt.Errorf("create transaction: %w", err) } } - if err := nursery.database.UpdateReverseSwapStatus(reverseSwap, parsedStatus); err != nil { - handleError("Could not update status of Reverse Swap " + reverseSwap.Id + ": " + err.Error()) - return + if err := tx.UpdateReverseSwapStatus(reverseSwap, parsedStatus); err != nil { + return fmt.Errorf("set reverse swap status: %w", err) } if parsedStatus.IsCompletedStatus() { @@ -188,9 +182,8 @@ func (nursery *Nursery) handleReverseSwapStatus(reverseSwap *database.ReverseSwa if err != nil { handleError("Could not get payment status: " + err.Error()) } else if status.State == lightning.PaymentSucceeded { - if err := nursery.database.SetReverseSwapRoutingFee(reverseSwap, status.FeeMsat); err != nil { - handleError("Could not set reverse swap routing fee in database: " + err.Error()) - return + if err := tx.SetReverseSwapRoutingFee(reverseSwap, status.FeeMsat); err != nil { + return fmt.Errorf("set routing fee: %w", err) } } else { logger.Warnf("Reverse Swap %s has state completed but payment did not succeed", reverseSwap.Id) @@ -202,24 +195,20 @@ func (nursery *Nursery) handleReverseSwapStatus(reverseSwap *database.ReverseSwa logger.Infof("Reverse Swap service fee: %dsat; boltz onchain fee: %dsat", serviceFee, boltzOnchainFee) - if err := nursery.database.SetReverseSwapServiceFee(reverseSwap, serviceFee, boltzOnchainFee); err != nil { - handleError("Could not set reverse swap service fee in database: " + err.Error()) - return + if err := tx.SetReverseSwapServiceFee(reverseSwap, serviceFee, boltzOnchainFee); err != nil { + return fmt.Errorf("set service fee: %w", err) } - if err := nursery.database.UpdateReverseSwapState(reverseSwap, boltzrpc.SwapState_SUCCESSFUL, ""); err != nil { - handleError("Could not update state of Reverse Swap " + reverseSwap.Id + ": " + err.Error()) - return + if err := tx.UpdateReverseSwapState(reverseSwap, boltzrpc.SwapState_SUCCESSFUL, ""); err != nil { + return fmt.Errorf("update state: %w", err) } } else if parsedStatus.IsFailedStatus() { if reverseSwap.State == boltzrpc.SwapState_PENDING { - if err := nursery.database.UpdateReverseSwapState(reverseSwap, boltzrpc.SwapState_SERVER_ERROR, ""); err != nil { - handleError("Could not update state of Reverse Swap " + reverseSwap.Id + ": " + err.Error()) - return + if err := tx.UpdateReverseSwapState(reverseSwap, boltzrpc.SwapState_SERVER_ERROR, ""); err != nil { + return fmt.Errorf("update state: %w", err) } } } - - nursery.sendReverseSwapUpdate(*reverseSwap) + return nil } func (nursery *Nursery) handleReverseSwapDirectPayment(swap *database.ReverseSwap, output *onchain.Output) { diff --git a/nursery/swap.go b/nursery/swap.go index d82159a3..fa6f7de0 100644 --- a/nursery/swap.go +++ b/nursery/swap.go @@ -62,13 +62,7 @@ func (nursery *Nursery) getRefundOutput(swap *database.Swap) *Output { walletId: swap.WalletId, outputArgs: swapOutputArgs(swap), setTransaction: func(transactionId string, fee uint64) error { - if err := nursery.database.SetSwapRefundTransactionId(swap, transactionId, fee); err != nil { - return err - } - - nursery.sendSwapUpdate(*swap) - - return nil + return nursery.database.SetSwapRefundTransactionId(swap, transactionId, fee) }, setError: func(err error) { nursery.handleSwapError(swap, err) @@ -80,7 +74,6 @@ func (nursery *Nursery) RegisterSwap(swap database.Swap) error { if err := nursery.registerSwaps([]string{swap.Id}); err != nil { return err } - nursery.sendSwapUpdate(swap) return nil } @@ -124,66 +117,54 @@ func (nursery *Nursery) handleSwapError(swap *database.Swap, err error) { logger.Error(dbErr.Error()) } logger.Errorf("Swap %s error: %v", swap.Id, err) - nursery.sendSwapUpdate(*swap) } -func (nursery *Nursery) handleSwapStatus(swap *database.Swap, status boltz.SwapStatusResponse) { +func (nursery *Nursery) handleSwapStatus(tx *database.Transaction, swap *database.Swap, status boltz.SwapStatusResponse) error { parsedStatus := boltz.ParseEvent(status.Status) if parsedStatus == swap.Status { logger.Debugf("Status of Swap %s is %s already", swap.Id, parsedStatus) - return + return nil } logger.Infof("Status of Swap %s changed to: %s", swap.Id, parsedStatus) - handleError := func(err string) { - nursery.handleSwapError(swap, errors.New(err)) - } - if parsedStatus != boltz.InvoiceSet && swap.LockupTransactionId == "" { swapTransactionResponse, err := nursery.boltz.GetSwapTransaction(swap.Id) if err != nil { var boltzErr boltz.Error if !errors.As(err, &boltzErr) { - handleError("Could not get lockup tx from boltz: " + err.Error()) - return + return fmt.Errorf("could not get lockup tx from boltz: %w", err) } } else { lockupTransaction, err := boltz.NewTxFromHex(swap.Pair.From, swapTransactionResponse.TransactionHex, swap.BlindingKey) if err != nil { - handleError("Could not decode lockup transaction: " + err.Error()) - return + return fmt.Errorf("could not decode lockup transaction: %w", err) } - if err := nursery.database.SetSwapLockupTransactionId(swap, lockupTransaction.Hash()); err != nil { - handleError("Could not set lockup transaction in database: " + err.Error()) - return + if err := tx.SetSwapLockupTransactionId(swap, lockupTransaction.Hash()); err != nil { + return fmt.Errorf("could not set lockup transaction in database: %w", err) } result, err := nursery.onchain.FindOutput(swapOutputArgs(swap)) if err != nil { - handleError(err.Error()) - return + return err } logger.Infof("Got lockup transaction of Swap %s: %s", swap.Id, lockupTransaction.Hash()) - if err := nursery.database.SetSwapExpectedAmount(swap, result.Value); err != nil { - handleError("Could not set expected amount in database: " + err.Error()) - return + if err := tx.SetSwapExpectedAmount(swap, result.Value); err != nil { + return fmt.Errorf("could not set expected amount in database: %w", err) } // dont add onchain fee if the swap was paid externally as it might have been part of a larger transaction if swap.WalletId != nil { fee, err := nursery.onchain.GetTransactionFee(swap.Pair.From, swap.LockupTransactionId) if err != nil { - handleError("could not get lockup transaction fee: " + err.Error()) - return + return fmt.Errorf("could not get lockup transaction fee: %w", err) } - if err := nursery.database.SetSwapOnchainFee(swap, fee); err != nil { - handleError("could not set lockup transaction fee in database: " + err.Error()) - return + if err := tx.SetSwapOnchainFee(swap, fee); err != nil { + return fmt.Errorf("could not set lockup transaction fee in database: %w", err) } } } @@ -201,25 +182,21 @@ func (nursery *Nursery) handleSwapStatus(swap *database.Swap, status boltz.SwapS swapRates, err := nursery.boltz.GetInvoiceAmount(swap.Id) if err != nil { - handleError("Could not query Swap rates of Swap " + swap.Id + ": " + err.Error()) - return + return fmt.Errorf("could not query swap rates of swap %s: %w", swap.Id, err) } if err := nursery.CheckAmounts(boltz.NormalSwap, swap.Pair, swap.ExpectedAmount, swapRates.InvoiceAmount, swap.ServiceFeePercent); err != nil { - handleError(fmt.Sprintf("not accepting invoice amount %d from boltz: %s", swapRates.InvoiceAmount, err)) - return + return fmt.Errorf("not accepting invoice amount %d from boltz: %s", swapRates.InvoiceAmount, err) } blockHeight, err := nursery.onchain.GetBlockHeight(swap.Pair.From) if err != nil { - handleError("Could not get block height: " + err.Error()) - return + return fmt.Errorf("could not get block height: %w", err) } if nursery.lightning == nil { - handleError("No lightning node available, can not create invoice for Swap " + swap.Id) - return + return fmt.Errorf("no lightning node available, can not create invoice for swap %s", swap.Id) } invoice, err := nursery.lightning.CreateInvoice( @@ -230,8 +207,7 @@ func (nursery *Nursery) handleSwapStatus(swap *database.Swap, status boltz.SwapS ) if err != nil { - handleError("Could not get new invoice for Swap " + swap.Id + ": " + err.Error()) - return + return fmt.Errorf("could not get new invoice for swap %s: %w", swap.Id, err) } logger.Infof("Generated new invoice for Swap %s for %d saothis", swap.Id, swapRates.InvoiceAmount) @@ -239,15 +215,13 @@ func (nursery *Nursery) handleSwapStatus(swap *database.Swap, status boltz.SwapS _, err = nursery.boltz.SetInvoice(swap.Id, invoice.PaymentRequest) if err != nil { - handleError("Could not set invoice of Swap: " + err.Error()) - return + return fmt.Errorf("could not set invoice of swap %s: %w", swap.Id, err) } - err = nursery.database.SetSwapInvoice(swap, invoice.PaymentRequest) + err = tx.SetSwapInvoice(swap, invoice.PaymentRequest) if err != nil { - handleError("Could not set invoice of Swap in database: " + err.Error()) - return + return fmt.Errorf("could not set invoice of swap %s in database: %w", swap.Id, err) } case boltz.TransactionClaimPending, boltz.TransactionClaimed: @@ -255,20 +229,17 @@ func (nursery *Nursery) handleSwapStatus(swap *database.Swap, status boltz.SwapS decodedInvoice, err := lightning.DecodeInvoice(swap.Invoice, nursery.network.Btc) if err != nil { - handleError("Could not decode invoice: " + err.Error()) - return + return fmt.Errorf("could not decode swap invoice: %w", err) } if nursery.lightning != nil { paid, err := nursery.lightning.CheckInvoicePaid(decodedInvoice.PaymentHash[:]) if err != nil { if !errors.Is(err, lightning.ErrInvoiceNotFound) { - handleError("Could not get invoice information from lightning node: " + err.Error()) - return + return fmt.Errorf("could not get invoice information from lightning node: %w", err) } } else if !paid { - logger.Warnf("Swap %s was not actually settled. Refunding at block %d", swap.Id, swap.TimoutBlockHeight) - return + return fmt.Errorf("invoice was not actually paid. refunding at block %d", swap.TimoutBlockHeight) } } @@ -281,18 +252,15 @@ func (nursery *Nursery) handleSwapStatus(swap *database.Swap, status boltz.SwapS } } - err := nursery.database.UpdateSwapStatus(swap, parsedStatus) - + err := tx.UpdateSwapStatus(swap, parsedStatus) if err != nil { - handleError(fmt.Sprintf("Could not update status of Swap %s to %s: %s", swap.Id, parsedStatus, err)) - return + return fmt.Errorf("could not update status of swap %s to %s: %w", swap.Id, parsedStatus, err) } if parsedStatus.IsCompletedStatus() { decodedInvoice, err := lightning.DecodeInvoice(swap.Invoice, nursery.network.Btc) if err != nil { - handleError("Could not decode invoice: " + err.Error()) - return + return fmt.Errorf("could not decode invoice: %w", err) } serviceFee := swap.ServiceFeePercent.Calculate(decodedInvoice.AmountSat) boltzOnchainFee := int64(swap.ExpectedAmount - decodedInvoice.AmountSat - serviceFee) @@ -303,29 +271,24 @@ func (nursery *Nursery) handleSwapStatus(swap *database.Swap, status boltz.SwapS logger.Infof("Swap service fee: %dsat onchain fee: %dsat", serviceFee, boltzOnchainFee) - if err := nursery.database.SetSwapServiceFee(swap, serviceFee, uint64(boltzOnchainFee)); err != nil { - handleError("Could not set swap service fee in database: " + err.Error()) - return + if err := tx.SetSwapServiceFee(swap, serviceFee, uint64(boltzOnchainFee)); err != nil { + return fmt.Errorf("could not set swap service fee in database: %w", err) } - if err := nursery.database.UpdateSwapState(swap, boltzrpc.SwapState_SUCCESSFUL, ""); err != nil { - handleError(err.Error()) - return + if err := tx.UpdateSwapState(swap, boltzrpc.SwapState_SUCCESSFUL, ""); err != nil { + return fmt.Errorf("update swap state: %w", err) } } else if parsedStatus.IsFailedStatus() { if swap.State == boltzrpc.SwapState_PENDING { - if err := nursery.database.UpdateSwapState(swap, boltzrpc.SwapState_SERVER_ERROR, ""); err != nil { - handleError(err.Error()) - return + if err := tx.UpdateSwapState(swap, boltzrpc.SwapState_SERVER_ERROR, ""); err != nil { + return fmt.Errorf("update swap state: %w", err) } } logger.Infof("Swap %s failed, trying to refund cooperatively", swap.Id) if _, err := nursery.RefundSwaps(swap.Pair.From, []*database.Swap{swap}, nil); err != nil { - handleError("Could not refund Swap " + swap.Id + ": " + err.Error()) - return + return fmt.Errorf("could not refund: %w", err) } - return } - nursery.sendSwapUpdate(*swap) + return nil } diff --git a/rpcserver/router.go b/rpcserver/router.go index b4ff7796..90418a62 100644 --- a/rpcserver/router.go +++ b/rpcserver/router.go @@ -545,11 +545,11 @@ func (server *routedBoltzServer) ClaimSwaps(ctx context.Context, request *boltzr } func (server *routedBoltzServer) GetSwapInfo(ctx context.Context, request *boltzrpc.GetSwapInfoRequest) (*boltzrpc.GetSwapInfoResponse, error) { - swap, reverseSwap, chainSwap, err := server.database.QueryAnySwap(request.Id) + someSwap, err := server.database.QueryAnySwap(request.Id) if err != nil { return nil, errors.New("could not find Swap with ID " + request.Id) } - return server.serializeAnySwap(ctx, swap, reverseSwap, chainSwap) + return server.serializeAnySwap(ctx, someSwap) } func (server *routedBoltzServer) GetSwapInfoStream(request *boltzrpc.GetSwapInfoRequest, stream boltzrpc.Boltz_GetSwapInfoStreamServer) error { @@ -575,7 +575,11 @@ func (server *routedBoltzServer) GetSwapInfoStream(request *boltzrpc.GetSwapInfo } for update := range updates { - response, err := server.serializeAnySwap(stream.Context(), update.Swap, update.ReverseSwap, update.ChainSwap) + response, err := server.serializeAnySwap(stream.Context(), &database.SomeSwap{ + Normal: update.Swap, + Chain: update.ChainSwap, + Reverse: update.ReverseSwap, + }) if err == nil { if err := stream.Send(response); err != nil { stop() @@ -2184,23 +2188,23 @@ func (server *routedBoltzServer) ListTenants(ctx context.Context, request *boltz return response, nil } -func (server *routedBoltzServer) serializeAnySwap(ctx context.Context, swap *database.Swap, reverseSwap *database.ReverseSwap, chainSwap *database.ChainSwap) (*boltzrpc.GetSwapInfoResponse, error) { +func (server *routedBoltzServer) serializeAnySwap(ctx context.Context, someSwap *database.SomeSwap) (*boltzrpc.GetSwapInfoResponse, error) { if tenantId := macaroons.TenantIdFromContext(ctx); tenantId != nil { err := status.Error(codes.PermissionDenied, "tenant does not have permission to view this swap") - if swap != nil && swap.TenantId != *tenantId { + if someSwap.Normal != nil && someSwap.Normal.TenantId != *tenantId { return nil, err } - if reverseSwap != nil && reverseSwap.TenantId != *tenantId { + if someSwap.Reverse != nil && someSwap.Reverse.TenantId != *tenantId { return nil, err } - if chainSwap != nil && chainSwap.TenantId != *tenantId { + if someSwap.Chain != nil && someSwap.Chain.TenantId != *tenantId { return nil, err } } return &boltzrpc.GetSwapInfoResponse{ - Swap: serializeSwap(swap), - ReverseSwap: serializeReverseSwap(reverseSwap), - ChainSwap: serializeChainSwap(chainSwap), + Swap: serializeSwap(someSwap.Normal), + ReverseSwap: serializeReverseSwap(someSwap.Reverse), + ChainSwap: serializeChainSwap(someSwap.Chain), }, nil }