diff --git a/internal/fsm/fsmevm/stage_before.go b/internal/fsm/fsmevm/stage_before.go index 0cb71a9..4fcff9b 100644 --- a/internal/fsm/fsmevm/stage_before.go +++ b/internal/fsm/fsmevm/stage_before.go @@ -105,6 +105,17 @@ func (s *FSM) sendBaseAssetForBurn(ctx context.Context, wf *workflow.Workflow, _ return nil } + // check if transaction was already sent to avoid "nonce too low" error on retry + existingTxs, err := s.st.TransferTransactions().FindTransactionByType(ctx, s.transfer.ID, models.TransferTransactionTypeSendBurnBaseAsset) + if err != nil { + return fmt.Errorf("find existing transaction: %w", err) + } + if len(existingTxs) > 0 { + s.logger.Infow("transaction already exists, skipping send", "tx_hash", existingTxs[0].TxHash) + // transaction already sent, proceed to next step + return nil + } + // get processing wallet by owner id processingWallet, err := s.bs.Wallets().Processing().GetByBlockchain(ctx, s.transfer.OwnerID, s.evm.Blockchain()) if err != nil { diff --git a/internal/fsm/fsmevm/stage_sending.go b/internal/fsm/fsmevm/stage_sending.go index 241d59b..2cc6254 100644 --- a/internal/fsm/fsmevm/stage_sending.go +++ b/internal/fsm/fsmevm/stage_sending.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" + "github.com/dv-net/dv-processing/internal/models" "github.com/dv-net/dv-processing/internal/util" "github.com/dv-net/dv-processing/internal/workflow" "github.com/dv-net/dv-processing/pkg/walletsdk/evm" @@ -15,6 +16,23 @@ import ( func (s *FSM) sending(ctx context.Context, _ *workflow.Workflow, _ *workflow.Stage, _ *workflow.Step) error { var err error + // check if transaction was already sent to avoid "nonce too low" error on retry + existingTxs, err := s.st.TransferTransactions().FindTransactionByType(ctx, s.transfer.ID, models.TransferTransactionTypeTransfer) + if err != nil { + return fmt.Errorf("find existing transaction: %w", err) + } + if len(existingTxs) > 0 { + s.logger.Infow("transaction already exists, skipping send", "tx_hash", existingTxs[0].TxHash) + // transaction already sent, update transfer with tx hash if needed + if s.transfer.TxHash.String == "" || s.transfer.TxHash.String != existingTxs[0].TxHash { + s.transfer, err = s.bs.Transfers().SetTxHash(ctx, s.transfer.ID, existingTxs[0].TxHash) + if err != nil { + return fmt.Errorf("set tx hash: %w", err) + } + } + return nil + } + fromAddress := s.transfer.GetFromAddress() toAddress := s.transfer.GetToAddress()