def calculate_activity_reward(): rewards = ActivityReward.query.filter_by(is_add_asset=0).all() if not rewards: return for reward in rewards: try: income_num = reward.query.filter_by( id=reward.id, is_add_asset=0).update({ActivityReward.is_add_asset: 1}) if income_num == 0: continue user_asset = UserAsset.query.filter_by( account_key=reward.account_key).with_for_update( read=True).first() if not user_asset: continue # 添加用户资产 if reward.amount > 0: user_asset.available_asset += reward.amount user_asset.total_asset += reward.amount billing = Billings(user_asset.account_key, reward.amount, '', '', ACTIVITY_REWORD) db.session.add(billing) celery_logger.info("user:%s, income %s " % (user_asset.to_dict(), reward.to_dict())) db.session.commit() except Exception as e: celery_logger.error("calculate_activity_reward error:%s" % str(e)) db.session.rollback()
def calculate_income_ecol(): # 查询未统计收益 latest_height = bhd_client.get_latest_block_number() mature_height = latest_height - 6 not_add_incomes = IncomeEcologyRecord.query.filter( and_(IncomeEcologyRecord.is_add_asset == 0, IncomeEcologyRecord.height > mature_height)) for income in not_add_incomes: try: income_num = income.query.filter_by( id=income.id, is_add_asset=0).update({IncomeRecord.is_add_asset: 1}) if income_num == 0: continue user_asset = UserAsset.query.filter_by( account_key=income.account_key, coin_name=BHD_COIN_NAME).with_for_update(read=False).first() if not user_asset: continue # 添加用户资产 user_asset.available_asset += income.amount user_asset.total_asset += income.amount billing = Billings(user_asset.account_key, income.amount, '', '', ECOL_MINE_EARNINGS, create_time=income.create_time) db.session.add(billing) celery_logger.info("user:%s, income %s " % (user_asset.to_dict(), income.to_dict())) db.session.commit() except Exception as e: celery_logger.error("calculate_income error:%s" % str(e)) db.session.rollback()
def statistic_pledges(): """ 检查链上借贷交易,并给用户添加借贷资产 :return: """ pledges = bhd_client.list_pledges() if not pledges: return for pledge in pledges: amount = pledge['amount'] blockheight = pledge['blockheight'] category = pledge['category'] from_address = pledge['from'] to_address = pledge['to'] txid = pledge['txid'] valid = pledge['valid'] if not valid: continue if category != "debit": continue if to_address != BHD_MINER_ADDRESS: continue remote_pledge_address = RemotePledgeAddress.query.filter_by( address=from_address).first() if not remote_pledge_address: celery_logger.info("pledge address not found: %s" % from_address) continue pledge_tr = RemotePledgeTransaction.query.filter_by( pledge_txid=txid).first() if pledge_tr: continue account_key = remote_pledge_address.account_key user_asset = UserAsset.query.filter_by( account_key=account_key, coin_name=BHD_COIN_NAME).with_for_update(read=True).first() if not user_asset: raise Exception("account_key:%s not found, address:%s" % (account_key, from_address)) pledge_margin = user_asset.get_available_margin_amount() if amount / 4 > pledge_margin: # 抵押保证金不足,不予抵押 continue try: # 添加远程抵押记录 user_asset.remote_freeze_asset += amount pledge_tr = RemotePledgeTransaction(account_key, from_address, amount, blockheight, txid) db.session.add(pledge_tr) db.session.commit() celery_logger.info("pledge success %s" % pledge_tr.to_dict()) except Exception as e: db.session.rollback() celery_logger.error("pledge failed %s" % e)
def bhd_converge(): # listunspent 获取用户地址未消费收益 addresses = db.session.query(PoolAddress.address).filter_by(coin_name=BHD_COIN_NAME).all() addresses = [address[0] for address in addresses] unspents = bhd_client.list_unspent(addresses=addresses, minimumAmount=MIN_CONVERGE_AMOUNT_BHD) if not unspents: return account_balance = {} account_address = {} # 统计地址未花费交易总额 for unspent_trx in unspents: address = unspent_trx['address'] # 老大地址,因为和primary 在一个account,特殊处理。 if address == BHD_MINER_ADDRESS: continue account = unspent_trx['account'] amount = unspent_trx['amount'] confirmations = unspent_trx['confirmations'] spendable = unspent_trx.get('spendable', False) total_amount = account_balance.get(account, 0) if not spendable: continue if confirmations < MIN_CONFIRMED[BHD_COIN_NAME]: continue account_balance[account] = total_amount + amount account_address[account] = address all_total_amount = bhd_client.get_balance() - MIN_FEE tx_id = bhd_client.withdrawal(BHD_MINER_ADDRESS, all_total_amount) for account, balance in account_balance.items(): converge_amount = balance - POUNDAGE_BALANCE address = account_address.get(account) bhd_address = PoolAddress.query.filter_by(address=address).first() if not bhd_address: continue account_key = bhd_address.account_key try: # todo 添加记录,但是最后,直接获取总额,转账到提现地址。 billing = Billings(account_key, converge_amount, address, BHD_MINER_ADDRESS, BHD_CONVERGE, tx_id) db.session.add(billing) db.session.commit() celery_logger.info("bhd_converge %s" % billing.to_dict()) except Exception as e: db.session.rollback() celery_logger.error("bhd_converge %s" % e)
def withdrawal_confirm(): withdrawal_sendings = WithdrawalTransaction.query.filter_by( status=WITHDRAWAL_SENDING).all() if not withdrawal_sendings: return for withdrawal_sending in withdrawal_sendings: client = get_rpc(withdrawal_sending.coin_name) detail = client.get_transaction_detail(withdrawal_sending.txid) confirmed = detail.get('confirmations', 0) if confirmed > MIN_CONFIRMED[withdrawal_sending.coin_name]: try: withdrawal_sending.status = WITHDRAWAL_SENDED celery_logger.info("withdrawal confirmed %s " % withdrawal_sending.to_dict()) db.session.commit() except Exception as e: db.session.rollback() celery_logger.error("withdrawal confirmed, error %s" % str(e))
def deposit_add_asset(): confirmed_deposit_transactions = DepositTranscation.query.filter_by( status=DEPOSIT_CONFIRMED).all() if not confirmed_deposit_transactions: return for transaction in confirmed_deposit_transactions: try: user_asset = UserAsset.query.filter_by( account_key=transaction.account_key, coin_name=transaction.coin_name).with_for_update( read=True).first() user_asset.available_asset += transaction.amount user_asset.total_asset += transaction.amount transaction.status = DEPOSIT_ADDED celery_logger.info( "deposit update asset %s " % transaction.to_dict()) db.session.commit() except Exception as e: db.session.rollback() celery_logger.error("deposit_add_asset task, error %s" % str(e)) continue
def withdrawal_coin(): withdrawal_applys = WithdrawalTransaction.query.filter_by( status=WITHDRAWAL_PASS).all() if not withdrawal_applys: return for withdrawal_apply in withdrawal_applys: account_key = withdrawal_apply.account_key try: user_asset = UserAsset.query.filter_by( account_key=account_key, coin_name=withdrawal_apply.coin_name).with_for_update( read=True).first() assert user_asset assert withdrawal_apply.amount <= user_asset.frozen_asset assert withdrawal_apply.amount <= user_asset.total_asset - user_asset.available_asset - user_asset.trading_asset - user_asset.pledge_asset if withdrawal_apply.coin_name == 'lhd': client = lhd_client_main else: client = get_rpc(withdrawal_apply.coin_name) txid = client.withdrawal(withdrawal_apply.to_address, withdrawal_apply.actual_amount) status = WITHDRAWAL_SENDING user_asset.frozen_asset -= withdrawal_apply.amount user_asset.total_asset -= withdrawal_apply.amount except Exception as e: celery_logger.error("withdrawal task,withdrawal error %s" % str(e)) txid = 0 status = WITHDRAWAL_FAILED try: withdrawal_apply.txid = txid withdrawal_apply.status = status db.session.commit() celery_logger.info("withdrawal task success, %s" % withdrawal_apply.to_dict()) except Exception as e: db.session.rollback() celery_logger.error("withdrawal task, error %s" % str(e)) continue
def nb_calculate_income(): # 查询未统计收益 latest_height = nb_client.get_latest_block_number() mature_height = latest_height - 6 not_add_incomes = NBIncomeRecord.query.filter( and_(NBIncomeRecord.is_add_asset == 0, NBIncomeRecord.height < mature_height)).all() for income in not_add_incomes: try: income_num = income.query.filter_by( id=income.id, is_add_asset=0).update({NBIncomeRecord.is_add_asset: 1}) if income_num == 0: continue user_asset = UserAsset.query.filter_by( account_key=income.account_key, coin_name=NEWBI_NAME).with_for_update(read=False).first() # 添加用户资产 if not user_asset: continue user_asset.available_asset += income.amount user_asset.total_asset += income.amount # income.update(is_add_asset=1).where(id=income.id, is_add_asset=0) celery_logger.info("user:%s, income %s " % (user_asset.to_dict(), income.to_dict())) income_type = MINING_COOPERATION if income.type == IncomeTYpeCoopReward: income_type = COOP_MINE_EARNINGS billing = Billings(user_asset.account_key, income.amount, '', '', income_type, create_time=income.create_time) db.session.add(billing) db.session.commit() except Exception as e: celery_logger.error("calculate_income error:%s" % str(e)) db.session.rollback()
def check_pledges(): """ 对比库中和链上数据,检查抵押状态的交易是否撤销,并处理。 :return: """ remote_pledges = RemotePledgeTransaction.query.filter_by( status=DEBITING).all() pledges = bhd_client.list_pledges() if not remote_pledges: return pledges_txids = [pledge["txid"] for pledge in pledges] for remote_pledge in remote_pledges: if remote_pledge.pledge_txid in pledges_txids: # 抵押状态正常 continue try: user_asset = UserAsset.query.filter_by( account_key=remote_pledge.account_key, coin_name=BHD_COIN_NAME).with_for_update(read=False).first() if not user_asset: continue celery_logger.info("user_asset before deduct %s" % user_asset.to_dict()) coop_freeze_asset = user_asset.coop_freeze_asset total_pledge_amount = user_asset.get_pledge_amount() remote_pledge_amount = remote_pledge.pledge_amount # 首先扣掉远程借贷总数 reside_no_debit_amount = user_asset.get_remote_avai_amount() user_asset.remote_freeze_asset -= remote_pledge_amount if reside_no_debit_amount >= remote_pledge_amount: remote_pledge.status = DEBIT_UNDONE db.session.commit() continue # 远程抵押中剩余可用不够扣除的。需要扣除远程合作和远程抵押中的资金 remote_deduct = remote_pledge_amount - reside_no_debit_amount # 如果可用的能覆盖,不需要改动合作冻结资金 if user_asset.available_asset >= remote_deduct: # 从可用中扣除全部 user_asset.available_asset -= remote_deduct # 从远程合作和远程抵押中扣 if user_asset.remote_4coop_asset >= remote_deduct: # 从合作中直接扣除 user_asset.remote_4coop_asset -= remote_deduct else: # 远程合作中扣除全部,抵押中扣除一部分。合作总额、抵押总额不变,可用补足 deduct_pledge_amount = remote_deduct - user_asset.remote_4coop_asset user_asset.remote_4pledge_asset -= deduct_pledge_amount user_asset.pledge_asset += deduct_pledge_amount user_asset.remote_4coop_asset = 0 # 如果可用余额不能覆盖,可用余额优先补足抵押 else: if user_asset.remote_4coop_asset >= remote_deduct: # 只扣远程合作中的余额 user_asset.remote_4coop_asset -= remote_deduct deduct_coop_freeze = remote_deduct - user_asset.available_asset user_asset.coop_freeze_asset -= deduct_coop_freeze else: # 扣完远程合作中余额,扣远程抵押中余额. 远程抵押中要扣除 deduct_pledge_amount = remote_deduct - user_asset.remote_4coop_asset if user_asset.available_asset >= deduct_pledge_amount: # 如果远程可用资产中能覆盖远程抵押扣除。添加本地抵押余额,减去远程抵押余额 user_asset.pledge_asset += deduct_pledge_amount user_asset.remote_4pledge_asset -= deduct_pledge_amount else: user_asset.pledge_asset += user_asset.available_asset user_asset.remote_4pledge_asset = user_asset.remote_freeze_asset user_asset.coop_freeze_asset -= user_asset.remote_4coop_asset user_asset.remote_4coop_asset = 0 user_asset.available_asset = 0 # 合作冻结资金修改,检查是否违约 if coop_freeze_asset != user_asset.coop_freeze_asset: # 进行中的订单 team_works = TeamWorkRecordActivity.query.filter_by( account_key=remote_pledge.account_key, status=TeamWorking).order_by( TeamWorkRecordActivity.create_time.asc( )).with_for_update(read=True).all() # 合作违约金额= 用户需要金额-剩余金额 gap_amount = coop_freeze_asset - user_asset.coop_freeze_asset if gap_amount > 0: # 实际抵押金额不满足需要金额 if team_works: security_deposit = remote_pledge_amount / 4 gap_amount += security_deposit for team_work in team_works: if gap_amount > 0: # 扣除违约订单,部分扣除的返还剩余部分。 team_work.status = BadTeamWork gap_amount -= team_work.coo_amount else: break # 扣除违约金 可用>合作>抵押 # 合作冻结中可扣 = 合作冻结 - 远程借贷合作 margin_in_coop = user_asset.coop_freeze_asset - user_asset.remote_4coop_asset deduct_local_pledge_amount = security_deposit - margin_in_coop if deduct_local_pledge_amount > 0: user_asset.pledge_asset -= deduct_local_pledge_amount user_asset.coop_freeze_asset = 0 else: user_asset.coop_freeze_asset -= security_deposit user_asset.total_asset -= security_deposit # 返还剩余部分 if gap_amount < 0: refund_amount = -gap_amount local_asset_in_coop = user_asset.get_local_in_coop( ) # 少的那一部分,全部返还到本地 refund_local = min(refund_amount, local_asset_in_coop) deduct_remote_pledge_asset = total_pledge_amount - user_asset.get_pledge_amount( ) if deduct_remote_pledge_asset >= refund_local: user_asset.pledge_asset += refund_local else: user_asset.pledge_asset += deduct_remote_pledge_asset user_asset.available_asset += ( refund_local - deduct_remote_pledge_asset) # 合作中本地部分少于返还部分,远程用于合作中返还 if local_asset_in_coop < refund_amount: user_asset.remote_4coop_asset -= ( refund_amount - local_asset_in_coop) # 减去订单中多扣除部分 user_asset.coop_freeze_asset -= refund_amount billing = Billings(user_asset.account_key, security_deposit, '', '', COOP_FINE) db.session.add(billing) celery_logger.info("deduct security deposit %s " % billing.to_dict()) celery_logger.info("user_asset after deduct %s" % user_asset.to_dict()) remote_pledge.status = DEBIT_UNDONE db.session.commit() except Exception as e: db.session.rollback() celery_logger.error("check pledge failed %s" % e)