def run(self): while True: # Just so we don't constantly berate the database if there's no TXs to chew through time.sleep(10) txs = db.get_unprocessed_transactions() for tx in txs: if self.stopped(): break source_address = tx['source_address'] to_address = tx['to_address'] amount = tx['amount'] uid = tx['uid'] attempts = tx['attempts'] raw_withdraw_amt = str(amount) + '000000000000000000000000' wallet_command = { 'action': 'send', 'wallet': settings.wallet, 'source': source_address, 'destination': to_address, 'amount': int(raw_withdraw_amt), 'id': uid } logger.debug("RPC Send") try: wallet_output = wallet.communicate_wallet(wallet_command) except Exception as e: logger.exception(e) continue logger.debug("RPC Response") src_usr = db.get_user_by_wallet_address(source_address) trg_usr = db.get_user_by_wallet_address(to_address) if src_usr is not None: source_id = src_usr.user_id else: source_id = None if trg_usr is not None: target_id = trg_usr.user_id else: target_id = None if 'block' in wallet_output: txid = wallet_output['block'] pending_delta = int( amount) * -1 # To update users pending balances db.mark_transaction_processed(uid, txid, pending_delta, source_id, target_id) logger.info('TX processed. UID: %s, TXID: %s', uid, txid) if target_id is None: withdrawq.put({'user_id': source_id, 'txid': txid}) else: # Not sure what happen but we'll retry a few times if attempts >= MAX_TX_RETRIES: logger.info("Max Retires Exceeded for TX UID: %s", uid) db.mark_transaction_processed(uid, 'invalid', int(amount) * -1, source_id, target_id) else: db.inc_tx_attempts(uid) if self.stopped(): break
def parse_incoming_transactions(): # logger.info('parsing incoming transactions ...') commands = [["listtransactions", '*', 100, 0]] rpc_connection = connect() result = rpc_connection.batch_(commands) return_results = [] if len(result[0]) > 0: for transaction_rpc in result[0]: if transaction_rpc['category'] == 'receive': txid = transaction_rpc['txid'] to_user = db.get_user_by_wallet_address( transaction_rpc['address']) amount = transaction_rpc['amount'] tx_time = datetime.datetime.fromtimestamp( transaction_rpc['time']) raw_tx_rpc = str(transaction_rpc) confirmations = transaction_rpc['confirmations'] status = db.get_transaction_status_by_txid(txid) # logger.debug('processing transaction -> status: %s, raw_tx: %s', status, raw_tx_rpc) if status == 'DOESNT_EXIST' and confirmations >= MIN_CONFIRMATIONS_FOR_DEPOSIT: logger.info('new confirmed transaction received: %s', transaction_rpc) if db.create_deposit_transaction(txid, amount, to_user, tx_time, raw_tx_rpc, 'CONFIRMED'): if to_user is not None: return_results.append([ to_user.user_id, 'new_deposit_confirmed', amount ]) logger.info('transaction processed successfully %s', transaction_rpc) else: logger.critical('could not make deposit transaction !') elif status == 'DOESNT_EXIST' and confirmations < MIN_CONFIRMATIONS_FOR_DEPOSIT: logger.info('new unconfirmed transaction received: %s', transaction_rpc) if db.create_deposit_transaction(txid, amount, to_user, tx_time, raw_tx_rpc, 'UNCONFIRMED'): if to_user is not None: return_results.append([ to_user.user_id, 'new_deposit_unconfirmed', amount ]) logger.info('transaction processed successfully %s', transaction_rpc) else: logger.critical('could not make deposit transaction !') elif status == 'UNCONFIRMED' and confirmations >= MIN_CONFIRMATIONS_FOR_DEPOSIT: logger.info('transaction confirmed: %s', transaction_rpc) if db.confirm_transaction(txid, raw_tx_rpc): if to_user is not None: return_results.append( [to_user.user_id, 'deposit_confirmed', amount]) logger.info('transaction confirmed successfully %s', transaction_rpc) else: logger.critical('could not confirm transaction !') return return_results
async def make_transaction_to_address(source_user, amount, withdraw_address, uid, target_id=None, giveaway_id=0, verify_address=False): # Do not validate address for giveaway tx because we do not know it yet if verify_address: # Check to see if the withdraw address is valid #pulowi falta servicio de validacion #wallet_command = {'action': 'validate_account_number', # 'account': withdraw_address} #address_validation = await communicate_wallet_async(wallet_command) #if ((withdraw_address[:4] == 'ban_' and len(withdraw_address) != 64) # or address_validation['valid'] != '1'): # raise util.TipBotException('invalid_address') if ((withdraw_address[:4] == 'tgm_' and len(withdraw_address) != 106)): raise util.TipBotException('invalid_address') amount = int(amount) if amount >= 1: # See if destination address belongs to a user if target_id is None: user = db.get_user_by_wallet_address(withdraw_address) if user is not None: target_id=user.user_id # Update pending send for user db.create_transaction(source_user, uid, withdraw_address,amount, target_id, giveaway_id) logger.info('TX queued, uid %s', uid) else: raise util.TipBotException('balance_error') return amount
async def make_transaction_to_address(source_user, amount, withdraw_address, uid, target_id=None, giveaway_id=0, verify_address=False): # Do not validate address for giveaway tx because we do not know it yet if verify_address: # Check to see if the withdraw address is valid wallet_command = { 'action': 'validate_account_number', 'account': withdraw_address } address_validation = await asyncio.get_event_loop().run_in_executor( None, communicate_wallet, wallet_command) # If the address was the incorrect length, did not start with xrb_ or nano_ or was deemed invalid by the node, return an error. address_prefix_valid = withdraw_address[:4] == 'ban_' \ or withdraw_address[:5] == 'ban_' if len(withdraw_address) != 64 or not address_prefix_valid \ or address_validation['valid'] != '1': raise util.TipBotException('invalid_address') amount = int(amount) if amount >= 1: # See if destination address belongs to a user if target_id is None: user = db.get_user_by_wallet_address(withdraw_address) if user is not None: target_id = user.user_id # Update pending send for user db.create_transaction(source_user, uid, withdraw_address, amount, target_id, giveaway_id) logger.info('TX queued, uid %s', uid) else: raise util.TipBotException('balance_error') return amount