diff --git a/torba/client/baseaccount.py b/torba/client/baseaccount.py index 9851582cd..5864655c2 100644 --- a/torba/client/baseaccount.py +++ b/torba/client/baseaccount.py @@ -447,8 +447,6 @@ class BaseAccount: if broadcast: await self.ledger.broadcast(tx) else: - await self.ledger.release_outputs( - [txi.txo_ref.txo for txi in tx.inputs] - ) + await self.ledger.release_tx(tx) return tx diff --git a/torba/client/basedatabase.py b/torba/client/basedatabase.py index c36626e53..75f3cb991 100644 --- a/torba/client/basedatabase.py +++ b/torba/client/basedatabase.py @@ -7,7 +7,6 @@ from typing import Tuple, List, Union, Callable, Any, Awaitable, Iterable import sqlite3 -from torba.client.hash import TXRefImmutable from torba.client.basetransaction import BaseTransaction from torba.client.baseaccount import BaseAccount diff --git a/torba/client/baseledger.py b/torba/client/baseledger.py index 1f35fb2eb..7b543c258 100644 --- a/torba/client/baseledger.py +++ b/torba/client/baseledger.py @@ -206,6 +206,9 @@ class BaseLedger(metaclass=LedgerRegistry): def release_outputs(self, txos): return self.db.release_outputs(txos) + def release_tx(self, tx): + return self.release_outputs([txi.txo_ref.txo for txi in tx.inputs]) + async def get_local_status_and_history(self, address): address_details = await self.db.get_address(address=address) history = address_details['history'] or '' diff --git a/torba/client/basetransaction.py b/torba/client/basetransaction.py index ff4582250..358ea168c 100644 --- a/torba/client/basetransaction.py +++ b/torba/client/basetransaction.py @@ -9,6 +9,7 @@ from torba.client.constants import COIN, NULL_HASH32 from torba.client.bcd_data_stream import BCDataStream from torba.client.hash import sha256, TXRef, TXRefImmutable from torba.client.util import ReadOnlyList +from torba.client.errors import InsufficientFundsError if typing.TYPE_CHECKING: from torba.client import baseledger @@ -441,7 +442,8 @@ class BaseTransaction: @classmethod async def create(cls, inputs: Iterable[BaseInput], outputs: Iterable[BaseOutput], - funding_accounts: Iterable[BaseAccount], change_account: BaseAccount): + funding_accounts: Iterable[BaseAccount], change_account: BaseAccount, + sign: bool = True): """ Find optimal set of inputs when only outputs are provided; add change outputs if only inputs are provided or if inputs are greater than outputs. """ @@ -467,7 +469,7 @@ class BaseTransaction: deficit = cost - payment spendables = await ledger.get_spendable_utxos(deficit, funding_accounts) if not spendables: - raise ValueError('Not enough funds to cover this transaction.') + raise InsufficientFundsError('Not enough funds to cover this transaction.') payment += sum(s.effective_amount for s in spendables) tx.add_inputs(s.txi for s in spendables) @@ -500,11 +502,12 @@ class BaseTransaction: # less than the fee, after 5 attempts we give up and go home cost += cost_of_change + 1 - await tx.sign(funding_accounts) + if sign: + await tx.sign(funding_accounts) except Exception as e: log.exception('Failed to create transaction:') - await ledger.release_outputs(tx.outputs) + await ledger.release_tx(tx) raise e return tx diff --git a/torba/client/errors.py b/torba/client/errors.py new file mode 100644 index 000000000..cd290cf05 --- /dev/null +++ b/torba/client/errors.py @@ -0,0 +1,2 @@ +class InsufficientFundsError(Exception): + pass