From b3d1dbdf6891373d90b67b90ec313557f5399620 Mon Sep 17 00:00:00 2001 From: jackstar12 Date: Mon, 14 Oct 2024 18:21:22 +0200 Subject: [PATCH] fix(wallet): only mark utxos as spent after successful broadcast --- onchain/wallet/wallet.go | 46 +++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/onchain/wallet/wallet.go b/onchain/wallet/wallet.go index 8a25450f..cd848a26 100644 --- a/onchain/wallet/wallet.go +++ b/onchain/wallet/wallet.go @@ -702,7 +702,7 @@ func (wallet *Wallet) getUnspentOutputs(subaccount uint64, includeUnconfirmed bo return result, nil } -func (wallet *Wallet) SendToAddress(address string, amount uint64, satPerVbyte float64, sendAll bool) (string, error) { +func (wallet *Wallet) SendToAddress(address string, amount uint64, satPerVbyte float64, sendAll bool) (tx string, err error) { if wallet.Readonly { return "", errors.New("wallet is readonly") } @@ -716,6 +716,9 @@ func (wallet *Wallet) SendToAddress(address string, amount uint64, satPerVbyte f return "", err } + wallet.spentOutputsLock.Lock() + defer wallet.spentOutputsLock.Unlock() + // Disable RBF for asset, current := range outputs.Unspent { if len(current) > int(config.MaxInputs) { @@ -777,38 +780,37 @@ func (wallet *Wallet) SendToAddress(address string, amount uint64, satPerVbyte f if err := mapstructure.Decode(result, &signedTx); err != nil { return "", err } - wallet.spentOutputsLock.Lock() - for _, input := range signedTx.TransactionInputs { - wallet.spentOutputs[input.TxId] = true + if signedTx.Error != "" { + return "", fmt.Errorf("could not sign: %s", signedTx.Error) } - wallet.spentOutputsLock.Unlock() if wallet.txProvider != nil { - - if signedTx.Error != "" { - return "", errors.New(signedTx.Error) + tx, err = wallet.txProvider.BroadcastTransaction(signedTx.Transaction) + } else { + params, free = toJson(result) + var sendTx struct { + TxHash string `json:"txhash"` + Error string `json:"error"` } - tx, err := wallet.txProvider.BroadcastTransaction(signedTx.Transaction) - if err != nil { + if err := withAuthHandler(C.GA_send_transaction(wallet.session, params, handler), handler, &sendTx); err != nil { return "", err } - return tx, nil - } + free() - params, free = toJson(result) - var sendTx struct { - TxHash string `json:"txhash"` - Error string `json:"error"` + if sendTx.Error != "" { + err = errors.New(sendTx.Error) + } + tx = sendTx.TxHash } - if err := withAuthHandler(C.GA_send_transaction(wallet.session, params, handler), handler, &sendTx); err != nil { - return "", err + if err != nil { + return "", fmt.Errorf("failed to broadcast: %w", err) } - free() - if sendTx.Error != "" { - return "", errors.New(sendTx.Error) + for _, input := range signedTx.TransactionInputs { + wallet.spentOutputs[input.TxId] = true } - return sendTx.TxHash, nil + + return tx, nil } func (wallet *Wallet) SetSpentOutputs(outputs []string) {