Example #1
0
def transferbitcoin(privatekey, address, pubkey):
    # address, pubkey = details_from_private_key(privatekey)
    details = blockcypher.get_address_details(address, coin_symbol=symbol)
    print("Balance: %d" % details['balance'])
    if not details['balance'] > 1000:
        print("no balance, skipping")
        return
    outputs = [
        {
            'value': details['balance']-fee,
            'address': myaddress,
            # 'script_type': 'pay-to-pubkey-hash',
            # 'script': address_to_script(myaddress),
        }
    ]
    inputs = [{'address': address}]
    pprint(details)
    transaction = blockcypher.create_unsigned_tx(
        inputs, outputs, change_address=myaddress, coin_symbol=symbol)
    pprint(transaction)
    input_addresses = blockcypher.get_input_addresses(transaction)
    privkeys, pubkeys = [], []
    for a in input_addresses:
        assert a == address
        privkeys.append(privatekey)
        pubkeys.append(pubkey)
    signatures = blockcypher.make_tx_signatures(
        transaction['tosign'], privkeys, pubkeys)
    r = blockcypher.broadcast_signed_transaction(
        transaction, signatures, pubkeys, coin_symbol=symbol)
    pprint(r)
def createTransaction(outputAddress, amount):
	#Specify the inputs and outputs below
	#Specify an address, and the backend will work out what transaction output that address has available to spend
	#You do not need to list a change address
	#the transaction will be created with all change (minus the fees) going to the first input address
	inputs = [{'address': 'n1xrgmc48JBh31wYJmRadDyS5Lbh5gGqNu'}]
	outputs = [{'address': outputAddress, 'value': amount}]

	#The next line creates the transaction shell, which is as yet unsigned
	unsigned_tx = blockcypher.create_unsigned_tx(inputs=inputs, outputs=outputs, coin_symbol='btc-testnet', api_key='141dbdc7350f4275900fd063fd56b6d3')

	#Now list the private and public keys corresponding to the inputs
	private_keys=['61361420f531bf9e0893db1dbc061dcc00a22f5fb38f58d25f0fcaa1731d969e']
	public_keys=['025929058c2e17d1983682cf884e6ee7a6319f5098128badd944a2b441bd82fe9e']

	#Next create the signatures
	tx_signatures = blockcypher.make_tx_signatures(txs_to_sign=unsigned_tx['tosign'], privkey_list=private_keys, pubkey_list=public_keys)

	#Finally push the transaction and signatures onto the network
	result = blockcypher.broadcast_signed_transaction(unsigned_tx=unsigned_tx, signatures=tx_signatures, pubkeys=public_keys, coin_symbol='btc-testnet', api_key='141dbdc7350f4275900fd063fd56b6d3')

	# get the transaction hash
	transaction_hash = result['tx']['hash']

	return transaction_hash
Example #3
0
def transferbitcoin(privatekey, address, pubkey):
    # address, pubkey = details_from_private_key(privatekey)
    details = blockcypher.get_address_details(address, coin_symbol=symbol)
    print("Balance: %d" % details['balance'])
    if not details['balance'] > 1000:
        print("no balance, skipping")
        return
    outputs = [{
        'value': details['balance'] - fee,
        'address': myaddress,
        # 'script_type': 'pay-to-pubkey-hash',
        # 'script': address_to_script(myaddress),
    }]
    inputs = [{'address': address}]
    pprint(details)
    transaction = blockcypher.create_unsigned_tx(inputs,
                                                 outputs,
                                                 change_address=myaddress,
                                                 coin_symbol=symbol)
    pprint(transaction)
    input_addresses = blockcypher.get_input_addresses(transaction)
    privkeys, pubkeys = [], []
    for a in input_addresses:
        assert a == address
        privkeys.append(privatekey)
        pubkeys.append(pubkey)
    signatures = blockcypher.make_tx_signatures(transaction['tosign'],
                                                privkeys, pubkeys)
    r = blockcypher.broadcast_signed_transaction(transaction,
                                                 signatures,
                                                 pubkeys,
                                                 coin_symbol=symbol)
    pprint(r)
Example #4
0
def our_create_txt(account_in,account_out):
    '''
    :param account_in,数组:
    :param account_out:
    :example:       account_in=[mypriv1,mypub1,myaddr1]
                    account_out=[myaddr2]
    '''
    inputs = [{'address':account_in[2]}, ]
    outputs = [{'address': account_out[0], 'value': 1}]
    unsigned_tx = create_unsigned_tx(inputs=inputs,\
                                     outputs=outputs, \
                                     coin_symbol=flag,\
                                     api_key=mytoken)
    num=len(get_input_addresses(unsigned_tx))
 #   print unsigned_tx
#    print unsigned_tx
  #  return unsigned_tx

    privkey_list=[account_in[0]]*num
    pubkey_list=[account_in[1]]*num
    #签名
    tx_signatures = make_tx_signatures(txs_to_sign=unsigned_tx['tosign'],\
                                       privkey_list=privkey_list,\
                                       pubkey_list=pubkey_list)
  #  print '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'
  #  print tx_signatures
    kk=broadcast_signed_transaction(unsigned_tx=unsigned_tx, \
                                    signatures=tx_signatures,\
                                    pubkeys=pubkey_list,\
                                    coin_symbol=flag,\
                                    api_key=mytoken)
    #print kk
    print "successed!"
Example #5
0
def send_coin(request, coin_symbol):
    #user=get_user(request)
    payload = request.body.decode("utf-8")
    data = json.loads(payload)
    response = {'status': 400}
    coin = coin_symbol
    amount = data.get('amount')
    addr = data.get('address')
    id = data.get('id')
    user = User.objects.get(id=id)
    wallet = get_wallet(coin_symbol, user)
    addresses = wallet.address_set.all()
    if coin == settings.BTC:
        amount = int(float(amount) * settings.BTC)
        amount = int(float(amount) * settings.BTC)
    if coin == settings.ETH:
        amount = int(float(amount) * settings.WEI)

    if coin == settings.ETH:
        in_addr = addresses[0].address
        tx = create_eth_transaction(in_addr, addr, amount)

    else:
        tx = create_transaction(request.user.username, addr, amount, coin)
    if 'errors' in tx:
        response['message'] = 'Insufficient Balance'
        return JsonResponse(response)
    str_tx = json.dumps(tx)

    try:
        inputs = tx['tx']['inputs'][0]['addresses']
    except:
        response['message'] = 'Insufficient Balance'
        return JsonResponse(response)
    input_addr = addresses.filter(address__in=inputs)
    public_key = [addr.public_key for addr in input_addr]
    priv_key = [addr.private_key_hex for addr in input_addr]
    # pdb.set_trace()
    signatures = make_tx_signatures(txs_to_sign=tx['tosign'],
                                    privkey_list=priv_key,
                                    pubkey_list=public_key)

    if coin == settings.ETH:
        tx_hash = broadcast_eth_transaction(tx, signatures, public_key)
    else:
        tx_hash = broadcast_signed_transaction(unsigned_tx=tx,
                                               signatures=signatures,
                                               pubkeys=public_key,
                                               api_key=settings.TOKEN)

    if 'errors' in tx_hash:
        pdb.set_trace()
        response['message'] = 'Insufficient Balance'
        return JsonResponse(response)

    response['message'] = 'Transaction successfully created'
    response['status'] = 200
    response['tx_hash'] = tx_hash
    return JsonResponse(response)
Example #6
0
def make_tx_and_send(myaddress, output, value):
    unsigned_tx = create_tx(myaddress["address"], output, value)
    unsigned_tx["signatures"], unsigned_tx["pubkeys"] = make_tx_signatures(
        txs_to_sign=unsigned_tx['tosign'],
        privkey=myaddress["private"],
        pubkey=myaddress["public"])

    data = json.dumps(unsigned_tx)
    #print json.dumps(unsigned_tx, sort_keys=False, indent=4, separators=(',', ':'))
    send_tx(data)
Example #7
0
    def post(self, request, *args, **kwargs):
        amount = request.POST.get('amount')
        addr = request.POST.get('address')
        coin = request.POST.get('coin_symbol')
        wallet = Wallet.objects.get(Q(owner=request.user), coin=coin)
        addresses = wallet.address_set.all()
        if coin == 'btc':
            amount = int(float(amount) * 100000000)
        else:
            amount = int(float(amount) * settings.WEI)

        if coin == settings.ETH:
            in_addr = addresses[0].address
            tx = create_eth_transaction(
                'f814981e49d8fc2c42c43143a575aeec4b000c34', addr, amount)

        else:
            tx = create_transaction(request.user.username, addr, amount, coin)
        if 'errors' in tx:
            messages.warning(request, 'Insufficient Balance ')
            return HttpResponseRedirect('/office/wallet/' + coin + '/')

        pdb.set_trace()

        try:
            inputs = tx['tx']['inputs'][0]['addresses']
        except:
            messages.warning(request, 'Insufficient Balance ')
            return HttpResponseRedirect('/office/')

        input_addr = addresses.filter(address__in=inputs)
        public_key = [addr.public_key for addr in input_addr]
        priv_key = [addr.private_key_hex for addr in input_addr]
        #pdb.set_trace()
        signatures = make_tx_signatures(txs_to_sign=tx['tosign'],
                                        privkey_list=priv_key,
                                        pubkey_list=public_key)

        if coin == settings.ETH:
            tx_hash = broadcast_eth_transaction(tx, signatures, public_key)
            #pdb.set_trace()
        else:
            tx_hash = broadcast_signed_transaction(unsigned_tx=tx,
                                                   signatures=signatures,
                                                   pubkeys=public_key,
                                                   api_key=settings.TOKEN)

        if 'errors' in tx_hash:
            messages.warning(request, 'Insufficient Balance ')
            return HttpResponseRedirect('/office/wallet/' + coin + '/')

        messages.success(request, 'Transaction successfully created')
        #create_transaction(from_public_key, from_priv_key,addr,amount,coin,change_address.address)
        return HttpResponseRedirect('/office/wallet/' + coin + '/')
Example #8
0
def proofOfBurnTransaction():

    data = "mdsw22"

    # OP RETURN and push data to stack
    prefix = "6a4c"

    # get the size of data in bytes and hex of the data itself
    hexdata = binascii.hexlify(bytes(data, 'ascii'))
    prefix += binascii.hexlify(bytes(chr(len(data)), 'ascii')).decode('ascii')
    prefix += hexdata.decode('ascii')

    inputs = [{'address': 'n1xrgmc48JBh31wYJmRadDyS5Lbh5gGqNu'}]
    outputs = [{'value': 0, 'script_type': "null-data", 'script': prefix}]

    #The next line creates the transaction shell, which is as yet unsigned
    unsigned_tx = blockcypher.create_unsigned_tx(
        inputs=inputs,
        outputs=outputs,
        coin_symbol='btc-testnet',
        api_key='141dbdc7350f4275900fd063fd56b6d3')

    #Now list the private and public keys corresponding to the inputs
    private_keys = [
        '61361420f531bf9e0893db1dbc061dcc00a22f5fb38f58d25f0fcaa1731d969e'
    ]
    public_keys = [
        '025929058c2e17d1983682cf884e6ee7a6319f5098128badd944a2b441bd82fe9e'
    ]

    #Next create the signatures
    tx_signatures = blockcypher.make_tx_signatures(
        txs_to_sign=unsigned_tx['tosign'],
        privkey_list=private_keys,
        pubkey_list=public_keys)

    #Finally push the transaction and signatures onto the network
    result = blockcypher.broadcast_signed_transaction(
        unsigned_tx=unsigned_tx,
        signatures=tx_signatures,
        pubkeys=public_keys,
        coin_symbol='btc-testnet',
        api_key='141dbdc7350f4275900fd063fd56b6d3')

    # get the transaction hash
    transaction_hash = result['tx']['hash']

    return transaction_hash
Example #9
0
	def Post_MerkleRoot(self):
		hex_to_post = self.root.encode("hex");
		output_script = '6a13' + hex_to_post;
		inputs = [{'address': self.Sender_addr}, ];
		outputs = [{'address': self.Address, 'value': 25},\
		{'value':0, 'script_type':'null-data',\
		'script': output_script},];

		unsigned_tx = create_unsigned_tx(inputs=inputs, outputs=outputs, coin_symbol='btc-testnet',\
			api_key = self.MyToken);


		tx_signatures = make_tx_signatures(txs_to_sign=unsigned_tx['tosign'], \
			privkey_list=self.privkey, pubkey_list=self.pubkey);

		Posted_Tx = broadcast_signed_transaction(unsigned_tx=unsigned_tx, signatures=tx_signatures, pubkeys=self.pubkey,\
			coin_symbol = 'btc-testnet',api_key = self.MyToken);

		self.Tx_hash = Posted_Tx['tx']['hash'];
		return self.Tx_hash;
Example #10
0
def send_multi_payment(payment_privkey, list_of_addresses,
                       payment_per_address):

    payment_address = get_address_from_privkey(payment_privkey)

    if dontuseAddress(payment_address):
        log.debug("Payment address %s not ready" % payment_address)
        return None

    inputs = [{'address': payment_address}]
    payment_in_satoshis = btc_to_satoshis(float(payment_per_address))
    outputs = []

    for address in list_of_addresses:
        outputs.append({'address': address, 'value': int(payment_in_satoshis)})

    unsigned_tx = create_unsigned_tx(inputs=inputs,
                                     outputs=outputs,
                                     api_key=BLOCKCYPHER_TOKEN)

    # iterate through unsigned_tx['tx']['inputs'] to find each address in order
    # need to include duplicates as many times as they may appear
    privkey_list = []
    pubkey_list = []

    for input in unsigned_tx['tx']['inputs']:
        privkey_list.append(payment_privkey)
        pubkey_list.append(get_pubkey_from_privkey(payment_privkey))

    tx_signatures = make_tx_signatures(txs_to_sign=unsigned_tx['tosign'],
                                       privkey_list=privkey_list,
                                       pubkey_list=pubkey_list)

    resp = broadcast_signed_transaction(unsigned_tx=unsigned_tx,
                                        signatures=tx_signatures,
                                        pubkeys=pubkey_list)

    if 'tx' in resp:
        return resp['tx']['hash']
    else:
        return None
Example #11
0
def send_multi_payment(payment_privkey, list_of_addresses, payment_per_address):

    payment_address = get_address_from_privkey(payment_privkey)

    if dontuseAddress(payment_address):
        log.debug("Payment address %s not ready" % payment_address)
        return None

    inputs = [{'address': payment_address}]
    payment_in_satoshis = btc_to_satoshis(float(payment_per_address))
    outputs = []

    for address in list_of_addresses:
        outputs.append({'address': address, 'value': int(payment_in_satoshis)})

    unsigned_tx = create_unsigned_tx(inputs=inputs, outputs=outputs,
                                     api_key=BLOCKCYPHER_TOKEN)

    # iterate through unsigned_tx['tx']['inputs'] to find each address in order
    # need to include duplicates as many times as they may appear
    privkey_list = []
    pubkey_list = []

    for input in unsigned_tx['tx']['inputs']:
        privkey_list.append(payment_privkey)
        pubkey_list.append(get_pubkey_from_privkey(payment_privkey))

    tx_signatures = make_tx_signatures(txs_to_sign=unsigned_tx['tosign'],
                                       privkey_list=privkey_list,
                                       pubkey_list=pubkey_list)

    resp = broadcast_signed_transaction(unsigned_tx=unsigned_tx,
                                        signatures=tx_signatures,
                                        pubkeys=pubkey_list,
                                        api_key=BLOCKCYPHER_TOKEN)

    if 'tx' in resp:
        return resp['tx']['hash']
    else:
        return None
Example #12
0
#You do not need to list a change address, by default the transaction will be created with all change (minus the fees) going to the first input address
inputs = [{'address': address}]
outputs = [{'value': 0, 'script_type': "null-data", 'script': ""}]
#The next line creates the transaction shell, which is as yet unsigned
unsigned_tx = blockcypher.create_unsigned_tx(
    inputs=inputs,
    outputs=outputs,
    coin_symbol='btc-testnet',
    api_key='0d7ace0138a0460baa3600a486dd7df8')

#You can edit the transaction fields at this stage, before signing it.
script = b'mmgw12 OP_RETURN'
script_HEX = script.hex()
unsigned_tx['outputs'][0]['script'] = script_HEX

#Now list the private and public keys corresponding to the inputs
private_keys = [private]
public_keys = [public]
#Next create the signatures
tx_signatures = blockcypher.make_tx_signatures(
    txs_to_sign=unsigned_tx['tosign'],
    privkey_list=private_keys,
    pubkey_list=public_keys)
#Finally push the transaction and signatures onto the network
blockcypher.broadcast_signed_transaction(
    unsigned_tx=unsigned_tx,
    signatures=tx_signatures,
    pubkeys=public_keys,
    coin_symbol='btc-testnet',
    api_key='0d7ace0138a0460baa3600a486dd7df8')
Example #13
0
    },
]
unsigned_tx = create_unsigned_tx(inputs=inputs,
                                 outputs=outputs,
                                 coin_symbol='btc-testnet',
                                 api_key='9ec8d9d06347455b833d04031f7b4c9a')

#embed_data(to_embed='I am the walrus', api_key='07b8071917974a62aeafd77880afe93b', coin_symbol='btc-testnet',data_is_hex=False);
#print unsigned_tx;

privkey_list = [
    '93021c6bc9ee89c06d57931a99341df6cadadb9d0e82ac4acb205b03f0afc03d'
]
pubkey_list = [
    '034cf1d96e5d632c64d987a5db49d1a0840c6fac7e138af2ce027ddee5bc787941'
]
print len(privkey_list), len(pubkey_list), len(unsigned_tx['tosign'])
tx_signatures = make_tx_signatures(txs_to_sign=unsigned_tx['tosign'],
                                   privkey_list=privkey_list,
                                   pubkey_list=pubkey_list)

Tx = broadcast_signed_transaction(unsigned_tx=unsigned_tx,
                                  signatures=tx_signatures,
                                  pubkeys=pubkey_list,
                                  coin_symbol='btc-testnet',
                                  api_key='9ec8d9d06347455b833d04031f7b4c9a')

print Tx['tx']['hash']
#for key in Tx['tx']:
#	print key;
Example #14
0
def sweep_funds_from_privkey(wallet_obj):
    if not USER_ONLINE:
        puts(colored.red('BlockCypher connection needed to fetch unspents and broadcast signed transaction.'))
        return

    mpub = wallet_obj.serialize_b58(private=False)
    coin_symbol = str(coin_symbol_from_mkey(mpub))
    network = guess_network_from_mkey(mpub)

    puts('Enter a private key (in WIF format) to send from:')
    wif_obj = get_wif_obj(network=network, user_prompt=DEFAULT_PROMPT, quit_ok=True)

    if not wif_obj:
        return

    pkey_addr = wif_obj.get_public_key().to_address(compressed=True)

    inputs = [{
            'address': pkey_addr,
            }, ]
    verbose_print('Inputs:\n%s' % inputs)

    dest_addr = get_unused_receiving_addresses(
            wallet_obj=wallet_obj,
            num_addrs=1,
            )[0]['pub_address']

    outputs = [{
            'address': dest_addr,
            'value': -1,  # sweep value
            }, ]
    verbose_print('Outputs:\n%s' % outputs)

    unsigned_tx = create_unsigned_tx(
        inputs=inputs,
        outputs=outputs,
        change_address=None,
        coin_symbol=coin_symbol,
        # will verify in the next step,
        # that way if there is an error here we can display that to user
        verify_tosigntx=False,
        include_tosigntx=True,
        )
    verbose_print('Unsigned TX:')
    verbose_print(unsigned_tx)

    if 'errors' in unsigned_tx:
        puts(colored.red('TX Error(s): Tx NOT Signed or Broadcast'))
        for error in unsigned_tx['errors']:
            puts(colored.red(error['error']))
        # Abandon
        return

    # Verify TX requested to sign is as expected
    tx_is_correct, err_msg = verify_unsigned_tx(
            unsigned_tx=unsigned_tx,
            inputs=inputs,
            outputs=outputs,
            sweep_funds=True,
            change_address=None,
            coin_symbol=coin_symbol,
            )
    if not tx_is_correct:
        puts(colored.red('TX Error: Tx NOT Signed or Broadcast'))
        puts(colored.red(err_msg))
        # Abandon
        return

    privkeyhex_list, pubkeyhex_list = [], []
    for _ in unsigned_tx['tx']['inputs']:
        privkeyhex_list.append(wif_obj.get_key())
        pubkeyhex_list.append(wif_obj.get_public_key().get_key(
            compressed=True))
    verbose_print('Private Key List: %s' % privkeyhex_list)
    verbose_print('Public Key List: %s' % pubkeyhex_list)

    # sign locally
    tx_signatures = make_tx_signatures(
            txs_to_sign=unsigned_tx['tosign'],
            privkey_list=privkeyhex_list,
            pubkey_list=pubkeyhex_list,
            )
    verbose_print('TX Signatures: %s' % tx_signatures)

    # TODO: add final confirmation before broadcast

    broadcasted_tx = broadcast_signed_transaction(
            unsigned_tx=unsigned_tx,
            signatures=tx_signatures,
            pubkeys=pubkeyhex_list,
            coin_symbol=coin_symbol,
    )
    verbose_print('Broadcasted TX')
    verbose_print(broadcasted_tx)

    tx_hash = broadcasted_tx['tx']['hash']
    puts(colored.green('TX Broadcast: %s' % tx_hash))
    tx_url = get_tx_url(
            tx_hash=tx_hash,
            coin_symbol=coin_symbol,
            )
    puts(colored.blue(tx_url))

    # Display updated wallet balance info
    display_balance_info(wallet_obj=wallet_obj)
Example #15
0
def send_funds(wallet_obj, change_address=None, destination_address=None, dest_satoshis=None, tx_preference=None):
    if not USER_ONLINE:
        puts(colored.red('Blockcypher connection needed to fetch unspents and broadcast signed transaction.'))
        puts(colored.red('You may dump all your addresses and private keys while offline by selecting option 0 on the home screen.'))
        return

    mpub = wallet_obj.serialize_b58(private=False)
    if not wallet_obj.private_key:
        print_pubwallet_notice(mpub=mpub)
        return

    coin_symbol = str(coin_symbol_from_mkey(mpub))
    verbose_print(coin_symbol)

    wallet_name = get_blockcypher_walletname_from_mpub(
            mpub=mpub,
            subchain_indices=[0, 1],
            )
    wallet_details = get_wallet_transactions(
            wallet_name=wallet_name,
            api_key=BLOCKCYPHER_API_KEY,
            coin_symbol=coin_symbol,
            )
    verbose_print(wallet_details)

    if wallet_details['final_balance'] == 0:
        puts(colored.red("0 balance. You can't send funds if you don't have them available!"))
        return

    mpriv = wallet_obj.serialize_b58(private=True)

    if not destination_address:
        display_shortname = COIN_SYMBOL_MAPPINGS[coin_symbol]['display_shortname']
        puts('What %s address do you want to send to?' % display_shortname)
        destination_address = get_crypto_address(coin_symbol=coin_symbol, quit_ok=True)
        if destination_address in ('q', 'Q'):
            puts(colored.red('Transaction Not Broadcast!'))
            return

    if not dest_satoshis:

        VALUE_PROMPT = 'Your current balance is %s. How much (in %s) do you want to send? Note that due to transaction fees your full balance may not be available to send.' % (
                format_crypto_units(
                    input_quantity=wallet_details['final_balance'],
                    input_type='satoshi',
                    output_type=UNIT_CHOICE,
                    coin_symbol=coin_symbol,
                    print_cs=True,
                    ),
                get_curr_symbol(
                        coin_symbol=coin_symbol,
                        output_type=UNIT_CHOICE,
                        ),
                )
        puts(VALUE_PROMPT)
        dest_crypto_qty = get_crypto_qty(
                max_num=from_satoshis(
                    input_satoshis=wallet_details['final_balance'],
                    output_type=UNIT_CHOICE,
                    ),
                input_type=UNIT_CHOICE,
                user_prompt=DEFAULT_PROMPT,
                quit_ok=True,
                )
        if dest_crypto_qty in ('q', 'Q'):
            puts(colored.red('Transaction Not Broadcast!'))
            return
        dest_satoshis = to_satoshis(
                input_quantity=dest_crypto_qty,
                input_type=UNIT_CHOICE,
                )

    inputs = [{
            'wallet_name': wallet_name,
            'wallet_token': BLOCKCYPHER_API_KEY,
            }, ]
    outputs = [{
            'value': dest_satoshis,
            'address': destination_address,
            }, ]

    if dest_satoshis == -1:
        sweep_funds = True
        change_address = None
    else:
        sweep_funds = False
        if not change_address:
            change_address = get_unused_change_addresses(
                    wallet_obj=wallet_obj,
                    num_addrs=1,
                    )[0]['pub_address']

    if not tx_preference:
        tx_preference = txn_preference_chooser(user_prompt=DEFAULT_PROMPT)

    verbose_print('Inputs:')
    verbose_print(inputs)
    verbose_print('Outputs:')
    verbose_print(outputs)
    verbose_print('Change Address: %s' % change_address)
    verbose_print('coin symbol: %s' % coin_symbol)
    verbose_print('TX Preference: %s' % tx_preference)

    unsigned_tx = create_unsigned_tx(
        inputs=inputs,
        outputs=outputs,
        change_address=change_address,
        preference=tx_preference,
        coin_symbol=coin_symbol,
        # will verify in the next step,
        # that way if there is an error here we can display that to user
        verify_tosigntx=False,
        include_tosigntx=True,
        )

    verbose_print('Unsigned TX:')
    verbose_print(unsigned_tx)

    if 'errors' in unsigned_tx:
        if any([x.get('error', '').startswith('Not enough funds after fees') for x in unsigned_tx['errors']]):
            puts("Sorry, after transaction fees there's not (quite) enough funds to send %s. Would you like to send the max you can instead?" % (
                format_crypto_units(
                    input_quantity=dest_satoshis,
                    input_type='satoshi',
                    output_type=UNIT_CHOICE,
                    coin_symbol=coin_symbol,
                    print_cs=True,
                )))
            if confirm(user_prompt=DEFAULT_PROMPT, default=False):
                return send_funds(
                        wallet_obj=wallet_obj,
                        change_address=change_address,
                        destination_address=destination_address,
                        dest_satoshis=-1,  # sweep
                        tx_preference=tx_preference,
                        )
            else:
                puts(colored.red('Transaction Not Broadcast!'))
                return

        else:
            puts(colored.red('TX Error(s): Tx NOT Signed or Broadcast'))
            for error in unsigned_tx['errors']:
                puts(colored.red(error['error']))
            # Abandon
            return

    # Verify TX requested to sign is as expected
    tx_is_correct, err_msg = verify_unsigned_tx(
            unsigned_tx=unsigned_tx,
            inputs=inputs,
            outputs=outputs,
            sweep_funds=sweep_funds,
            change_address=change_address,
            coin_symbol=coin_symbol,
            )
    if not tx_is_correct:
        puts(colored.red('TX Error: Tx NOT Signed or Broadcast'))
        puts(colored.red(err_msg))
        # Abandon
        return

    input_addresses = get_input_addresses(unsigned_tx)
    verbose_print('input_addresses')
    verbose_print(input_addresses)

    address_paths = [{'path': x['hd_path'], 'address': x['addresses'][0]} for x in unsigned_tx['tx']['inputs']]

    # be sure all addresses returned
    address_paths_filled = verify_and_fill_address_paths_from_bip32key(
            address_paths=address_paths,
            master_key=mpriv,
            network=guess_network_from_mkey(mpriv),
            )

    verbose_print('adress_paths_filled:')
    verbose_print(address_paths_filled)
    hexkeypair_dict = hexkeypair_list_to_dict(address_paths_filled)

    verbose_print('hexkeypair_dict:')
    verbose_print(hexkeypair_dict)

    if len(hexkeypair_dict.keys()) != len(set(input_addresses)):
        notfound_addrs = set(input_addresses) - set(hexkeypair_dict.keys())
        err_msg = "Couldn't find %s traversing bip32 key" % notfound_addrs
        raise Exception('Traversal Fail: %s' % err_msg)

    privkeyhex_list = [hexkeypair_dict[x]['privkeyhex'] for x in input_addresses]
    pubkeyhex_list = [hexkeypair_dict[x]['pubkeyhex'] for x in input_addresses]

    verbose_print('Private Key List: %s' % privkeyhex_list)
    verbose_print('Public Key List: %s' % pubkeyhex_list)

    # sign locally
    tx_signatures = make_tx_signatures(
            txs_to_sign=unsigned_tx['tosign'],
            privkey_list=privkeyhex_list,
            pubkey_list=pubkeyhex_list,
            )
    verbose_print('TX Signatures: %s' % tx_signatures)

    # final confirmation before broadcast

    if dest_satoshis == -1:
        # remember that sweep TXs cannot verify amounts client-side (only destination addresses)
        dest_satoshis_to_display = unsigned_tx['tx']['total'] - unsigned_tx['tx']['fees']
    else:
        dest_satoshis_to_display = dest_satoshis

    CONF_TEXT = "Send %s to %s with a fee of %s (%s%% of the amount you're sending)?" % (
            format_crypto_units(
                input_quantity=dest_satoshis_to_display,
                input_type='satoshi',
                output_type=UNIT_CHOICE,
                coin_symbol=coin_symbol,
                print_cs=True,
                ),
            destination_address,
            format_crypto_units(
                input_quantity=unsigned_tx['tx']['fees'],
                input_type='satoshi',
                output_type=UNIT_CHOICE,
                coin_symbol=coin_symbol,
                print_cs=True,
                ),
            round(100.0 * unsigned_tx['tx']['fees'] / dest_satoshis_to_display, 4),
            )
    puts(CONF_TEXT)

    if not confirm(user_prompt=DEFAULT_PROMPT, default=True):
        puts(colored.red('Transaction Not Broadcast!'))
        return

    broadcasted_tx = broadcast_signed_transaction(
            unsigned_tx=unsigned_tx,
            signatures=tx_signatures,
            pubkeys=pubkeyhex_list,
            coin_symbol=coin_symbol,
    )
    verbose_print('Broadcast TX Details:')
    verbose_print(broadcasted_tx)

    if 'errors' in broadcasted_tx:
        puts(colored.red('TX Error(s): Tx May NOT Have Been Broadcast'))
        for error in broadcasted_tx['errors']:
            puts(colored.red(error['error']))
        return

    tx_hash = broadcasted_tx['tx']['hash']
    tx_url = get_tx_url(
            tx_hash=tx_hash,
            coin_symbol=coin_symbol,
            )
    puts(colored.green('Transaction %s Broadcast' % tx_hash))
    puts(colored.blue(tx_url))

    # Display updated wallet balance info
    display_balance_info(wallet_obj=wallet_obj)