Browse Source

Move create_transaction logic from commands to wallet

master
ThomasV 6 years ago
parent
commit
717d112b26
  1. 94
      electrum/commands.py
  2. 27
      electrum/wallet.py

94
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')

27
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

Loading…
Cancel
Save