commit 717d112b26c896881aa263f7e1bdba4f7e0c6420
parent 782f9ed2731583687cbdf824d166bd3546f685e8
Author: ThomasV <thomasv@electrum.org>
Date: Thu, 21 May 2020 10:51:08 +0200
Move create_transaction logic from commands to wallet
Diffstat:
2 files changed, 62 insertions(+), 59 deletions(-)
diff --git a/electrum/commands.py b/electrum/commands.py
@@ -584,81 +584,57 @@ class Commands:
message = util.to_bytes(message)
return ecc.verify_message_with_address(address, sig, message)
- def _mktx(self, wallet: Abstract_Wallet, outputs, *, fee=None, feerate=None, change_addr=None, domain_addr=None, domain_coins=None,
- nocheck=False, unsigned=False, rbf=None, password=None, locktime=None):
- if fee is not None and feerate is not None:
- raise Exception("Cannot specify both 'fee' and 'feerate' at the same time!")
- self.nocheck = nocheck
- change_addr = self._resolver(change_addr, wallet)
- domain_addr = None if domain_addr is None else map(self._resolver, domain_addr, repeat(wallet))
- final_outputs = []
- for address, amount in outputs:
- address = self._resolver(address, wallet)
- amount = satoshis(amount)
- final_outputs.append(PartialTxOutput.from_address_and_value(address, amount))
-
- coins = wallet.get_spendable_coins(domain_addr)
- if domain_coins is not None:
- coins = [coin for coin in coins if (coin.prevout.to_str() in domain_coins)]
- if feerate is not None:
- fee_per_kb = 1000 * Decimal(feerate)
- fee_estimator = partial(SimpleConfig.estimate_fee_for_feerate, fee_per_kb)
- else:
- fee_estimator = fee
- tx = wallet.make_unsigned_transaction(coins=coins,
- outputs=final_outputs,
- fee=fee_estimator,
- change_addr=change_addr)
- if locktime is not None:
- tx.locktime = locktime
- if rbf is None:
- rbf = self.config.get('use_rbf', True)
- if rbf:
- tx.set_rbf(True)
- if not unsigned:
- wallet.sign_transaction(tx, password)
- return tx
-
@command('wp')
async def payto(self, destination, amount, fee=None, feerate=None, from_addr=None, from_coins=None, change_addr=None,
nocheck=False, unsigned=False, rbf=None, password=None, locktime=None, wallet: Abstract_Wallet = None):
"""Create a transaction. """
+ self.nocheck = nocheck
tx_fee = satoshis(fee)
domain_addr = from_addr.split(',') if from_addr else None
domain_coins = from_coins.split(',') if from_coins else None
- tx = self._mktx(wallet,
- [(destination, amount)],
- fee=tx_fee,
- feerate=feerate,
- change_addr=change_addr,
- domain_addr=domain_addr,
- domain_coins=domain_coins,
- nocheck=nocheck,
- unsigned=unsigned,
- rbf=rbf,
- password=password,
- locktime=locktime)
+ change_addr = self._resolver(change_addr, wallet)
+ domain_addr = None if domain_addr is None else map(self._resolver, domain_addr, repeat(wallet))
+ amount_sat = satoshis(amount)
+ outputs = [PartialTxOutput.from_address_and_value(destination, amount_sat)]
+ tx = wallet.create_transaction(
+ outputs,
+ fee=tx_fee,
+ feerate=feerate,
+ change_addr=change_addr,
+ domain_addr=domain_addr,
+ domain_coins=domain_coins,
+ unsigned=unsigned,
+ rbf=rbf,
+ password=password,
+ locktime=locktime)
return tx.serialize()
@command('wp')
async def paytomany(self, outputs, fee=None, feerate=None, from_addr=None, from_coins=None, change_addr=None,
nocheck=False, unsigned=False, rbf=None, password=None, locktime=None, wallet: Abstract_Wallet = None):
"""Create a multi-output transaction. """
+ self.nocheck = nocheck
tx_fee = satoshis(fee)
domain_addr = from_addr.split(',') if from_addr else None
domain_coins = from_coins.split(',') if from_coins else None
- tx = self._mktx(wallet,
- outputs,
- fee=tx_fee,
- feerate=feerate,
- change_addr=change_addr,
- domain_addr=domain_addr,
- domain_coins=domain_coins,
- nocheck=nocheck,
- unsigned=unsigned,
- rbf=rbf,
- password=password,
- locktime=locktime)
+ change_addr = self._resolver(change_addr, wallet)
+ domain_addr = None if domain_addr is None else map(self._resolver, domain_addr, repeat(wallet))
+ final_outputs = []
+ for address, amount in outputs:
+ address = self._resolver(address, wallet)
+ amount_sat = satoshis(amount)
+ final_outputs.append(PartialTxOutput.from_address_and_value(address, amount_sat))
+ tx = wallet.create_transaction(
+ final_outputs,
+ fee=tx_fee,
+ feerate=feerate,
+ change_addr=change_addr,
+ domain_addr=domain_addr,
+ domain_coins=domain_coins,
+ unsigned=unsigned,
+ rbf=rbf,
+ password=password,
+ locktime=locktime)
return tx.serialize()
@command('w')
diff --git a/electrum/wallet.py b/electrum/wallet.py
@@ -1876,6 +1876,33 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
def get_all_known_addresses_beyond_gap_limit(self) -> Set[str]:
pass
+ def create_transaction(self, outputs, *, fee=None, feerate=None, change_addr=None, domain_addr=None, domain_coins=None,
+ unsigned=False, rbf=None, password=None, locktime=None):
+ if fee is not None and feerate is not None:
+ raise Exception("Cannot specify both 'fee' and 'feerate' at the same time!")
+ coins = self.get_spendable_coins(domain_addr)
+ if domain_coins is not None:
+ coins = [coin for coin in coins if (coin.prevout.to_str() in domain_coins)]
+ if feerate is not None:
+ fee_per_kb = 1000 * Decimal(feerate)
+ fee_estimator = partial(SimpleConfig.estimate_fee_for_feerate, fee_per_kb)
+ else:
+ fee_estimator = fee
+ tx = self.make_unsigned_transaction(
+ coins=coins,
+ outputs=outputs,
+ fee=fee_estimator,
+ change_addr=change_addr)
+ if locktime is not None:
+ tx.locktime = locktime
+ if rbf is None:
+ rbf = self.config.get('use_rbf', True)
+ if rbf:
+ tx.set_rbf(True)
+ if not unsigned:
+ self.sign_transaction(tx, password)
+ return tx
+
class Simple_Wallet(Abstract_Wallet):
# wallet with a single keystore