def display_recent_txs(wallet_obj): if not USER_ONLINE: puts(colored.red('BlockCypher connection needed to find transactions related to your addresses.')) puts(colored.red('You may dump all your addresses while offline by selecting option 0.')) return local_tz = get_localzone() # Show overall balance info display_balance_info(wallet_obj=wallet_obj) mpub = wallet_obj.serialize_b58(private=False) 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_from_mkey(mpub), ) verbose_print(wallet_details) # TODO: pagination for lots of transactions txs = wallet_details.get('unconfirmed_txrefs', []) + wallet_details.get('txrefs', []) if txs: for tx_object in flatten_txns_by_hash(txs, nesting=False): if tx_object.get('confirmed_at'): tx_time = tx_object['confirmed_at'] else: tx_time = tx_object['received_at'] net_satoshis_tx = sum(tx_object['txns_satoshis_list']) conf_str = '' if tx_object.get('confirmed_at'): if tx_object.get('confirmations'): if tx_object.get('confirmations') <= 6: conf_str = ' (%s confirmations)' % tx_object.get('confirmations') else: conf_str = ' (6+ confirmations)' else: conf_str = ' (0 confirmations!)' puts(colored.green('%s: %s%s %s in TX hash %s%s' % ( tx_time.astimezone(local_tz).strftime("%Y-%m-%d %H:%M %Z"), '+' if net_satoshis_tx > 0 else '', format_crypto_units( input_quantity=net_satoshis_tx, input_type='satoshi', output_type=UNIT_CHOICE, coin_symbol=coin_symbol_from_mkey(mpub), print_cs=True, ), 'received' if net_satoshis_tx > 0 else 'sent', tx_object['tx_hash'], conf_str, ))) else: puts('No Transactions')
def address_overview(request, coin_symbol, address, wallet_name=None): TXNS_PER_PAGE = 100 # 1 indexed page current_page = request.GET.get('page') if current_page: current_page = int(current_page) else: current_page = 1 try: address_details = get_address_details( address=address, coin_symbol=coin_symbol, txn_limit=TXNS_PER_PAGE, api_key=BLOCKCYPHER_API_KEY, ) except AssertionError: msg = _('Invalid Address') messages.warning(request, msg) redir_url = reverse('coin_overview', kwargs={'coin_symbol': coin_symbol}) return HttpResponseRedirect(redir_url) # import pprint; pprint.pprint(address_details, width=1) if 'error' in address_details: msg = _('Sorry, that address was not found') messages.warning(request, msg) return HttpResponseRedirect(reverse('home')) if request.user.is_authenticated(): # notify user on page of any forwarding or subscriptions they may have for address_subscription in AddressSubscription.objects.filter( auth_user=request.user, b58_address=address, coin_symbol=coin_symbol, unsubscribed_at=None, ): if address_subscription.auth_user.email_verified: msg = _('Private Message: you are subscribed to this address and will receive email notifications at <b>%(user_email)s</b> (<a href="%(unsub_url)s">unsubscribe</a>)' % { 'user_email': request.user.email, 'unsub_url': reverse('user_unsubscribe_address', kwargs={ 'address_subscription_id': address_subscription.id, }), }) messages.info(request, msg, extra_tags='safe') else: msg = _('Private Message: you are not subscribed to this address because you have not clicked the link sent to <b>%(user_email)s</b>' % { 'user_email': request.user.email, }) messages.error(request, msg, extra_tags='safe') print('ERROR') # there can be only one af_initial = get_object_or_None(AddressForwarding, auth_user=request.user, initial_address=address, coin_symbol=coin_symbol, ) if af_initial: msg = _(''' Private Message: this address will automatically forward to <a href="%(destination_addr_uri)s">%(destination_address)s</a> any time a payment is received. <br /><br /> <i>%(small_payments_msg)s</i> ''' % { 'destination_address': af_initial.destination_address, 'destination_addr_uri': reverse('address_overview', kwargs={ 'address': af_initial.destination_address, 'coin_symbol': coin_symbol, }), 'small_payments_msg': SMALL_PAYMENTS_MSG, }) messages.info(request, msg, extra_tags='safe') # There could be many for af_destination in AddressForwarding.objects.filter( auth_user=request.user, destination_address=address, coin_symbol=coin_symbol, ): msg = _(''' Private Message: this address will automatically receive forwarded transactions from <a href="%(initial_addr_uri)s">%(initial_address)s</a>. <br /><br /> <i>%(small_payments_msg)s</i> ''' % { 'initial_address': af_destination.initial_address, 'initial_addr_uri': reverse('address_overview', kwargs={ 'address': af_destination.initial_address, 'coin_symbol': coin_symbol, }), 'small_payments_msg': SMALL_PAYMENTS_MSG, }) messages.info(request, msg, extra_tags='safe') all_transactions = address_details.get('unconfirmed_txrefs', []) + address_details.get('txrefs', []) # transaction pagination: 0-indexed and inclusive tx_start_num = (current_page - 1) * TXNS_PER_PAGE tx_end_num = current_page * TXNS_PER_PAGE - 1 # filter address details for pagination. HACK! all_transactions = all_transactions[tx_start_num:tx_end_num] flattened_txs = flatten_txns_by_hash(all_transactions, nesting=False) api_url = 'https://api.blockcypher.com/v1/%s/%s/addrs/%s' % ( COIN_SYMBOL_MAPPINGS[coin_symbol]['blockcypher_code'], COIN_SYMBOL_MAPPINGS[coin_symbol]['blockcypher_network'], address) return { 'coin_symbol': coin_symbol, 'address': address, 'api_url': api_url, 'wallet_name': wallet_name, 'current_page': current_page, 'max_pages': get_max_pages(num_items=address_details['final_n_tx'], items_per_page=TXNS_PER_PAGE), 'total_sent_satoshis': address_details['total_sent'], 'total_received_satoshis': address_details['total_received'], 'unconfirmed_balance_satoshis': address_details['unconfirmed_balance'], 'confirmed_balance_satoshis': address_details['balance'], 'total_balance_satoshis': address_details['final_balance'], 'flattened_txs': flattened_txs, 'num_confirmed_txns': address_details['n_tx'], 'num_unconfirmed_txns': address_details['unconfirmed_n_tx'], 'num_all_txns': address_details['final_n_tx'], 'BLOCKCYPHER_PUBLIC_KEY': BLOCKCYPHER_PUBLIC_KEY, }
def address_overview(request, coin_symbol, address, wallet_name=None): TXNS_PER_PAGE = 100 # 1 indexed page current_page = request.GET.get('page') if current_page: current_page = int(current_page) else: current_page = 1 try: address_details = get_address_details( address=address, coin_symbol=coin_symbol, txn_limit=TXNS_PER_PAGE, api_key=BLOCKCYPHER_API_KEY, ) except AssertionError: msg = _('Invalid Address') messages.warning(request, msg) redir_url = reverse('coin_overview', kwargs={'coin_symbol': coin_symbol}) return HttpResponseRedirect(redir_url) # import pprint; pprint.pprint(address_details, width=1) if 'error' in address_details: msg = _('Sorry, that address was not found') messages.warning(request, msg) return HttpResponseRedirect(reverse('home')) if request.user.is_authenticated(): # notify user on page of any forwarding or subscriptions they may have for address_subscription in AddressSubscription.objects.filter( auth_user=request.user, b58_address=address, coin_symbol=coin_symbol, unsubscribed_at=None, ): if address_subscription.auth_user.email_verified: msg = _( 'Private Message: you are subscribed to this address and will receive email notifications at <b>%(user_email)s</b> (<a href="%(unsub_url)s">unsubscribe</a>)' % { 'user_email': request.user.email, 'unsub_url': reverse('user_unsubscribe_address', kwargs={ 'address_subscription_id': address_subscription.id, }), }) messages.info(request, msg, extra_tags='safe') else: msg = _( 'Private Message: you are not subscribed to this address because you have not clicked the link sent to <b>%(user_email)s</b>' % { 'user_email': request.user.email, }) messages.error(request, msg, extra_tags='safe') print('ERROR') # there can be only one af_initial = get_object_or_None( AddressForwarding, auth_user=request.user, initial_address=address, coin_symbol=coin_symbol, ) if af_initial: msg = _( ''' Private Message: this address will automatically forward to <a href="%(destination_addr_uri)s">%(destination_address)s</a> any time a payment is received. <br /><br /> <i>%(small_payments_msg)s</i> ''' % { 'destination_address': af_initial.destination_address, 'destination_addr_uri': reverse('address_overview', kwargs={ 'address': af_initial.destination_address, 'coin_symbol': coin_symbol, }), 'small_payments_msg': SMALL_PAYMENTS_MSG, }) messages.info(request, msg, extra_tags='safe') # There could be many for af_destination in AddressForwarding.objects.filter( auth_user=request.user, destination_address=address, coin_symbol=coin_symbol, ): msg = _( ''' Private Message: this address will automatically receive forwarded transactions from <a href="%(initial_addr_uri)s">%(initial_address)s</a>. <br /><br /> <i>%(small_payments_msg)s</i> ''' % { 'initial_address': af_destination.initial_address, 'initial_addr_uri': reverse('address_overview', kwargs={ 'address': af_destination.initial_address, 'coin_symbol': coin_symbol, }), 'small_payments_msg': SMALL_PAYMENTS_MSG, }) messages.info(request, msg, extra_tags='safe') all_transactions = address_details.get( 'unconfirmed_txrefs', []) + address_details.get('txrefs', []) # transaction pagination: 0-indexed and inclusive tx_start_num = (current_page - 1) * TXNS_PER_PAGE tx_end_num = current_page * TXNS_PER_PAGE - 1 # filter address details for pagination. HACK! all_transactions = all_transactions[tx_start_num:tx_end_num] flattened_txs = flatten_txns_by_hash(all_transactions, nesting=False) api_url = 'https://api.blockcypher.com/v1/%s/%s/addrs/%s' % ( COIN_SYMBOL_MAPPINGS[coin_symbol]['blockcypher_code'], COIN_SYMBOL_MAPPINGS[coin_symbol]['blockcypher_network'], address) return { 'coin_symbol': coin_symbol, 'address': address, 'api_url': api_url, 'wallet_name': wallet_name, 'current_page': current_page, 'max_pages': get_max_pages(num_items=address_details['final_n_tx'], items_per_page=TXNS_PER_PAGE), 'total_sent_satoshis': address_details['total_sent'], 'total_received_satoshis': address_details['total_received'], 'unconfirmed_balance_satoshis': address_details['unconfirmed_balance'], 'confirmed_balance_satoshis': address_details['balance'], 'total_balance_satoshis': address_details['final_balance'], 'flattened_txs': flattened_txs, 'num_confirmed_txns': address_details['n_tx'], 'num_unconfirmed_txns': address_details['unconfirmed_n_tx'], 'num_all_txns': address_details['final_n_tx'], 'BLOCKCYPHER_PUBLIC_KEY': BLOCKCYPHER_PUBLIC_KEY, }
def display_recent_txs(wallet_obj): if not USER_ONLINE: puts(colored.red('BlockCypher connection needed to find transactions related to your addresses.')) puts(colored.red('You may dump all your addresses while offline by selecting option 0.')) return local_tz = get_localzone() # Show overall balance info display_balance_info(wallet_obj=wallet_obj) mpub = wallet_obj.serialize_b58(private=False) 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_from_mkey(mpub), ) verbose_print(wallet_details) # TODO: pagination for lots of transactions txs = wallet_details.get('unconfirmed_txrefs', []) + wallet_details.get('txrefs', []) if txs: for tx_object in flatten_txns_by_hash(txs, nesting=False): if tx_object.get('confirmed_at'): tx_time = tx_object['confirmed_at'] else: tx_time = tx_object['received_at'] net_satoshis_tx = sum(tx_object['txns_satoshis_list']) conf_str = '' has_confirmations = False if tx_object.get('confirmed_at'): if tx_object.get('confirmations'): has_confirmations = True if tx_object.get('confirmations') <= 6: conf_str = ' (%s confirmations)' % tx_object.get('confirmations') else: conf_str = ' (6+ confirmations)' else: conf_str = ' (0 confirmations!)' print_str = '%s: %s%s %s in TX hash %s%s' % ( tx_time.astimezone(local_tz).strftime("%Y-%m-%d %H:%M %Z"), '+' if net_satoshis_tx > 0 else '', format_crypto_units( input_quantity=net_satoshis_tx, input_type='satoshi', output_type=UNIT_CHOICE, coin_symbol=coin_symbol_from_mkey(mpub), print_cs=True, ), 'received' if net_satoshis_tx > 0 else 'sent', tx_object['tx_hash'], conf_str, ) if has_confirmations: puts(colored.green(print_str)) else: puts(colored.yellow(print_str)) else: puts('No Transactions')
def wallet_overview(request, coin_symbol, pubkey): subchain_indices = request.GET.get('subchain-indices') if subchain_indices: subchain_indices = subchain_indices.split('-') if subchain_indices == ['']: subchain_indices = [] else: subchain_indices = [int(x) for x in subchain_indices] # TODO: confirm it's a pubkey and not a privkey TXNS_PER_PAGE = 100 # 1 indexed page current_page = request.GET.get('page') if current_page: current_page = int(current_page) else: current_page = 1 # transaction pagination: 0-indexed and inclusive tx_start_num = (current_page - 1) * TXNS_PER_PAGE tx_end_num = current_page * TXNS_PER_PAGE - 1 wallet_name = get_blockcypher_walletname_from_mpub(mpub=pubkey, subchain_indices=subchain_indices) # TODO: could store in DB whether created or not create_hd_wallet( wallet_name=wallet_name, xpubkey=pubkey, api_key=BLOCKCYPHER_API_KEY, subchain_indices=subchain_indices, coin_symbol=coin_symbol, ) wallet_details = get_wallet_transactions( wallet_name=wallet_name, api_key=BLOCKCYPHER_API_KEY, coin_symbol=coin_symbol, txn_limit=TXNS_PER_PAGE, ) # import pprint; pprint.pprint(wallet_details, width=1) assert 'error' not in wallet_details, wallet_details all_transactions = wallet_details.get('unconfirmed_txrefs', []) + wallet_details.get('txrefs', []) # filter address details for pagination. HACK! all_transactions = all_transactions[tx_start_num:tx_end_num] flattened_txs = flatten_txns_by_hash(all_transactions, nesting=False) return { 'is_wallet_page': True, # shared template 'coin_symbol': coin_symbol, 'pubkey': pubkey, 'subchain_indices': subchain_indices, 'current_page': current_page, 'max_pages': get_max_pages(num_items=wallet_details['final_n_tx'], items_per_page=TXNS_PER_PAGE), 'total_sent_satoshis': wallet_details['total_sent'], 'total_received_satoshis': wallet_details['total_received'], 'unconfirmed_balance_satoshis': wallet_details['unconfirmed_balance'], 'confirmed_balance_satoshis': wallet_details['balance'], 'total_balance_satoshis': wallet_details['final_balance'], 'flattened_txs': flattened_txs, 'num_confirmed_txns': wallet_details['n_tx'], 'num_unconfirmed_txns': wallet_details['unconfirmed_n_tx'], 'num_all_txns': wallet_details['final_n_tx'], }
def wallet_overview(request, coin_symbol, pubkey): subchain_indices = request.GET.get('subchain-indices') if subchain_indices: subchain_indices = subchain_indices.split('-') if subchain_indices == ['']: subchain_indices = [] else: subchain_indices = [int(x) for x in subchain_indices] # TODO: confirm it's a pubkey and not a privkey TXNS_PER_PAGE = 100 # 1 indexed page current_page = request.GET.get('page') if current_page: current_page = int(current_page) else: current_page = 1 # transaction pagination: 0-indexed and inclusive tx_start_num = (current_page - 1) * TXNS_PER_PAGE tx_end_num = current_page * TXNS_PER_PAGE - 1 wallet_name = get_blockcypher_walletname_from_mpub( mpub=pubkey, subchain_indices=subchain_indices) # TODO: could store in DB whether created or not create_hd_wallet( wallet_name=wallet_name, xpubkey=pubkey, api_key=BLOCKCYPHER_API_KEY, subchain_indices=subchain_indices, coin_symbol=coin_symbol, ) wallet_details = get_wallet_transactions( wallet_name=wallet_name, api_key=BLOCKCYPHER_API_KEY, coin_symbol=coin_symbol, txn_limit=TXNS_PER_PAGE, ) # import pprint; pprint.pprint(wallet_details, width=1) assert 'error' not in wallet_details, wallet_details wallet_addresses = get_wallet_addresses( wallet_name=wallet_name, api_key=BLOCKCYPHER_API_KEY, is_hd_wallet=True, zero_balance=None, used=None, coin_symbol=coin_symbol, ) # import pprint; pprint.pprint(wallet_addresses, width=1) assert 'error' not in wallet_addresses, wallet_addresses all_transactions = wallet_details.get( 'unconfirmed_txrefs', []) + wallet_details.get('txrefs', []) # filter address details for pagination. HACK! all_transactions = all_transactions[tx_start_num:tx_end_num] flattened_txs = flatten_txns_by_hash(all_transactions, nesting=False) return { 'is_wallet_page': True, # shared template 'coin_symbol': coin_symbol, 'pubkey': pubkey, 'subchain_indices': subchain_indices, 'current_page': current_page, 'max_pages': get_max_pages(num_items=wallet_details['final_n_tx'], items_per_page=TXNS_PER_PAGE), 'total_sent_satoshis': wallet_details['total_sent'], 'total_received_satoshis': wallet_details['total_received'], 'unconfirmed_balance_satoshis': wallet_details['unconfirmed_balance'], 'confirmed_balance_satoshis': wallet_details['balance'], 'total_balance_satoshis': wallet_details['final_balance'], 'flattened_txs': flattened_txs, 'num_confirmed_txns': wallet_details['n_tx'], 'num_unconfirmed_txns': wallet_details['unconfirmed_n_tx'], 'num_all_txns': wallet_details['final_n_tx'], 'wallet_addresses': wallet_addresses, 'bc_wallet_name': wallet_name, }