electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

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:
Melectrum/commands.py | 94++++++++++++++++++++++++++++++-------------------------------------------------
Melectrum/wallet.py | 27+++++++++++++++++++++++++++
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