def _get_effective_share_info(self, share_token_items, total_share_token_amount, db_session): effective_share_dict = {} position_holder_dict = {} share_token_dict = {} total_effective_share_amount = Decimal(0) for item in share_token_items: share_token_dict[item.holder] = item.balance token_map = self._get_token_map(db_session) perp_addr = token_map[self._share_token_address].get('perp_addr') amm_proxy_addr = token_map[self._share_token_address].get('amm_proxy_addr') position_items = db_session.query(PositionBalance)\ .filter(PositionBalance.perpetual_address == perp_addr)\ .all() for item in position_items: position_holder_dict[item.holder] = item.balance amm_position = position_holder_dict[amm_proxy_addr] for holder, holder_position_in_margin_account in position_holder_dict.items(): holder_share_token_amount = share_token_dict.get(holder) if holder_share_token_amount == Decimal(0) or holder_share_token_amount is None: continue holder_position_in_amm = Wad.from_number(amm_position) * Wad.from_number(holder_share_token_amount) / Wad.from_number(total_share_token_amount) holder_portfolio_position = holder_position_in_amm + Wad.from_number(holder_position_in_margin_account) imbalance_rate = abs(holder_portfolio_position / holder_position_in_amm) imbalance_rate = Decimal(str(imbalance_rate)) if imbalance_rate <= Decimal(0.1): holder_effective_share = holder_share_token_amount elif imbalance_rate >= Decimal(0.9): holder_effective_share = holder_share_token_amount * Decimal(0.1) else: holder_effective_share = holder_share_token_amount * (Decimal(89/80) - imbalance_rate * Decimal(9/8)) effective_share_dict[holder] = holder_effective_share total_effective_share_amount += holder_effective_share return effective_share_dict, total_effective_share_amount
def _get_keeper_liquidate_amount(self, keeper_account): markPrice = self.perp.markPrice() availableMargin = self.perp.getAvailableMargin(keeper_account) if config.INVERSE: markPrice = Wad.from_number(1)/markPrice amount = int(availableMargin * Wad.from_number(config.LEVERAGE) * markPrice) amount = math.floor(amount/config.LOT_SIZE)*config.LOT_SIZE return Wad.from_number(amount)
def _get_holder_reward_weight(self, block_number, pool_value_info, db_session): holder_amms_weight_dict = {} holder_amms_reward_dict = {} amms_pool_total_reward = Decimal(0) for pool_name in pool_value_info.keys(): total_share_token_amount = pool_value_info[pool_name][ 'total_share_token_amount'] if total_share_token_amount == 0: continue share_token_items = pool_value_info[pool_name]['share_token_items'] pool_type = pool_value_info[pool_name]['pool_type'] pool_reward = pool_value_info[pool_name]['pool_reward'] amms_pool_total_reward += Decimal(str(pool_reward)) for item in share_token_items: holder = item.holder if item.balance == Decimal(0): continue # amm pool, use effective share after xia_rebalance_hard_fork block number if pool_type == 'AMM' and block_number >= self._xia_rebalance_hard_fork_block_number: total_effective_share_amount = pool_value_info[pool_name][ 'total_effective_share_amount'] holder_effective_share_amount = pool_value_info[pool_name][ 'effective_share_dict'].get(holder, Decimal(0)) wad_reward = pool_reward * Wad.from_number( holder_effective_share_amount) / Wad.from_number( total_effective_share_amount) reward = Decimal(str(wad_reward)) if holder not in holder_amms_reward_dict: holder_amms_reward_dict[holder] = reward else: holder_amms_reward_dict[holder] += reward self._save_theory_mining_reward('AMM', holder_amms_reward_dict, db_session) holder_mcb_balance_dict = self._get_holder_mcb_balance(db_session) total_holder_reward_weight = Decimal(0) for holder, reward in holder_amms_reward_dict.items(): holder_reward_percent = reward / amms_pool_total_reward holder_mcb_balance = holder_mcb_balance_dict.get( holder, Decimal(0)) reward_factor = self._get_holder_reward_factor( holder, reward, holder_mcb_balance) total_holder_reward_weight += holder_reward_percent * reward_factor for holder, reward in holder_amms_reward_dict.items(): holder_mcb_balance = holder_mcb_balance_dict.get( holder, Decimal(0)) reward_factor = self._get_holder_reward_factor( holder, reward, holder_mcb_balance) holder_amms_weight_dict[ holder] = reward_factor / total_holder_reward_weight return holder_amms_weight_dict
def __init__(self, side: int, size: int, entry_value: int, entry_social_loss: int, entry_funding_loss: int, cash_balance: int): assert (isinstance(side, int)) assert (isinstance(size, int)) assert (isinstance(entry_value, int)) assert (isinstance(entry_social_loss, int)) assert (isinstance(entry_funding_loss, int)) self.side = PositionSide(side) self.size = Wad(size) self.entry_value = Wad(entry_value) self.entry_social_loss = Wad(entry_social_loss) self.entry_funding_loss = Wad(entry_funding_loss) self.cash_balance = Wad(cash_balance)
def allowance(self, address: Address, guy: Address) -> Wad: assert (isinstance(address, Address)) assert (isinstance(guy, Address)) return Wad( self.contract.functions.allowance(address.address, guy.address).call())
def _check_redeeming_accounts(self): fund_state = self.fund.state() if fund_state == State.Normal: try: fundMarginAccount = self.perp.getMarginAccount(Address(config.FUND_ADDRESS)) redeeming_accounts = self._get_redeeming_accounts() for account in redeeming_accounts: price_limit = self._get_redeem_trade_price(fundMarginAccount.side) share_amount = self.fund.redeemingBalance(account) if share_amount > Wad(0): side = 2 if fundMarginAccount.side == PositionSide.LONG else 1 tx_hash = self.fund.bidRedeemingShare(account, share_amount, price_limit, side , self.keeper_account, self.gas_price) transaction_status = self._wait_transaction_receipt(tx_hash, 10) if transaction_status: self.logger.info(f"bidRedeemingShare success. amount:{share_amount}") else: self.logger.info(f"bidRedeemingShare fail. amount:{share_amount}") except Exception as e: self.logger.fatal(f"_check_redeeming_accounts bidRedeemingShare fail. error:{e}") elif fund_state == State.Emergency: try: fundMarginAccount = self.perp.getMarginAccount(Address(config.FUND_ADDRESS)) # price_limit = self._get_redeem_trade_price(fundMarginAccount.side) price_limit = self.perp.markPrice() total_supply = self.fund.total_supply() self.get_gas_price() side = 2 if fundMarginAccount.side == PositionSide.LONG else 1 tx_hash = self.fund.bidSettledShare(total_supply, price_limit, side, self.keeper_account, self.gas_price) transaction_status = self._wait_transaction_receipt(tx_hash, 10) if transaction_status: self.logger.info(f"bidSettledShare success. amount:{total_supply}") else: self.logger.info(f"bidSettledShare fail. amount:{total_supply}") except Exception as e: self.logger.fatal(f"_check_redeeming_accounts emergency fail. error:{e}")
def run(self): if self._check_account_from_key() is False: return # approve MCB token to disperse for multiple transaction if self._MCBToken.allowance(self._payer_account, self._disperse.address) == Wad(0): self._MCBToken.approve(self._disperse.address, self._payer_account) # restore pending transaction if need # unpaid_rewards = self._restore_pending_data() # check pending transactions if self._check_pending_transactions() is False: return # get all miners unpaid rewards unpaid_rewards = self._get_miner_unpaid_reward() miners_count = len(unpaid_rewards["miners"]) if miners_count == 0: self._logger.info(f"no miner need to be payed") return total_amount = Decimal(0) for reward in unpaid_rewards['amounts']: total_amount += reward self._logger.info(f"total_amount: {total_amount*(Decimal(10)**18)}") admin_input = input("yes or no: ") if admin_input != "yes": self._logger.info(f"input is {admin_input}. payer stop!") return # get gas price for transaction self._get_gas_price() # send MCB to all accounts for i in range(math.ceil(miners_count/config.MAX_PATCH_NUM)): start_idx = i*config.MAX_PATCH_NUM end_idx = min((i+1)*config.MAX_PATCH_NUM, miners_count) self._logger.info(f"miners count: {miners_count}, send from {start_idx} to {end_idx}") miners = unpaid_rewards["miners"][start_idx:end_idx] amounts = unpaid_rewards["amounts"][start_idx:end_idx] try: tx_hash = self._disperse.disperse_token(self._MCBToken.address, miners, amounts, self._payer_account, self._gas_price) self._save_payment_transaction(self._web3.toHex(tx_hash), miners, amounts) except Exception as e: self._logger.fatal(f"disperse transaction fail! Exception:{e}") continue try: tx_receipt = self._web3.eth.waitForTransactionReceipt(tx_hash, timeout=config.WAIT_TIMEOUT) self._save_payments_info(tx_receipt, miners, amounts) except Exception as e: self._logger.fatal( f"get trasaction receipt fail! tx_hash:{tx_hash}, err:{e}") continue return
def __init__(self, needRebalance: bool, amount: int, side: int): assert (isinstance(needRebalance, bool)) assert (isinstance(amount, int)) assert (isinstance(side, int)) self.needRebalance = needRebalance self.amount = Wad(amount) self.side = PositionSide(side)
def approve(self, address: Address, user: Address, limit: Wad = Wad(2**256 - 1)): assert (isinstance(address, Address)) assert (isinstance(limit, Wad)) tx_hash = self.contract.functions.approve( address.address, limit.value).transact({'from': user.address}) tx_receipt = self.web3.eth.waitForTransactionReceipt(tx_hash) #self.logger.info(tx_receipt) return tx_receipt
def disperse_token(self, token: Address, addresses: list, amounts: list, user: Address, gasPrice: int): amounts_toWad = [] for amount in amounts: amounts_toWad.append(Wad.from_number(amount).value) tx_hash = self.contract.functions.disperseToken( token.address, addresses, amounts_toWad).transact({ 'from': user.address, 'gasPrice': gasPrice }) return tx_hash
def _get_pool_usd_value(self, block_number, pool_name, pool_share_token_address, inverse, db_session): amm_usd_value = Decimal(0) amm_position = Decimal(0) token_map = self._get_token_map(pool_share_token_address, db_session) perp_addr = token_map[pool_share_token_address].get('perp_addr') amm_proxy_addr = token_map[pool_share_token_address].get( 'amm_proxy_addr') amm_proxy_item = db_session.query(PositionBalance)\ .filter(PositionBalance.perpetual_address == perp_addr)\ .filter(PositionBalance.holder == amm_proxy_addr)\ .first() if amm_proxy_item: amm_position = amm_proxy_item.balance if inverse: amm_usd_value = abs(Wad.from_number(amm_position)) else: chain_link_price = self._get_chain_link_price( block_number, pool_name, db_session) # vanilla contract amm_usd_value = abs( Wad.from_number(amm_position) * Wad.from_number(chain_link_price)) return amm_usd_value
def _close_position_in_AMM(self): margin_account = self.perp.getMarginAccount(self.keeper_account) size = int(margin_account.size) if size < config.POSITION_LIMIT: return deadline = int(time.time()) + config.DEADLINE amm_available_margin = self.AMM.current_available_margin() self.logger.info(f"amm_available_margin:{amm_available_margin}") amm_position_size = self.AMM.position_size() self.logger.info(f"amm_position_size:{amm_position_size}") trade_side = PositionSide.LONG if margin_account.side == PositionSide.SHORT else PositionSide.SHORT try: trade_price = compute_AMM_price(amm_available_margin, amm_position_size, trade_side, margin_account.size) self.logger.info(f"compute_price:{trade_price}") except Exception as e: self.logger.fatal(f"compute amm price failed. error:{e}") return trade_price = trade_price*Wad.from_number(1 - config.PRICE_SLIPPAGE) if trade_side == PositionSide.SHORT else trade_price*Wad.from_number(1 + config.PRICE_SLIPPAGE) tx_hash = None try: if trade_side == PositionSide.LONG: tx_hash = self.AMM.buy(margin_account.size, trade_price, deadline, self.keeper_account, self.gas_price) else: tx_hash = self.AMM.sell(margin_account.size, trade_price, deadline, self.keeper_account, self.gas_price) self.logger.info(f"close in AMM success. price:{trade_price} size{margin_account.size}") # wait transaction times is 1, cause amm transaction deadline is 120s, if wait timeout, transaction will fail, no need to add gas price transaction_status = self._wait_transaction_receipt(tx_hash, 1) if transaction_status: self.logger.info(f"close position in AMM success. price:{trade_price} size:{margin_account.size}") else: self.logger.info(f"close position in AMM fail. price:{trade_price} amount:{margin_account.size}") except Exception as e: self.logger.fatal(f"close position in AMM failed. price:{trade_price} size:{margin_account.size} error:{e}")
def _get_calculate_liquidate_amount(self, address): markPrice = self.perp.markPrice() cal_amount = int(self.perp.calculateLiquidateAmount(address, markPrice)) cal_amount = math.ceil(cal_amount/config.LOT_SIZE)*config.LOT_SIZE return Wad.from_number(cal_amount)
def _get_pool_value_info(self, block_number, pool_info, pool_reward_percent, db_session): if self._mining_round == 'QIN' and block_number < self._qin_reduce_reward_block_number: self._reward_per_block = 2 elif self._mining_round == 'QIN' and block_number >= self._qin_reduce_reward_block_number: self._reward_per_block = 0.2 # support vote https://vote.mcdex.io/mainnet/proposal/14, blocknumber >=11601000 && blocknumber <11685000 reward 0.1875 elif block_number >= 11601000 and block_number < 11685000: self._reward_per_block = 0.1875 # update uniswap_pool_proportion, every block update self._update_uniswap_pool_proportion(pool_info, db_session) pool_value_info = {} pools_total_effective_value = Wad(0) for pool_name in pool_info.keys(): pool_share_token_address = pool_info[pool_name].get( 'pool_share_token_address') if pool_name not in pool_value_info.keys(): pool_value_info[pool_name] = {} pool_value_info[pool_name][ 'pool_share_token_address'] = pool_share_token_address # use for amm pools reward distribute amm_pool_proportion = pool_info[pool_name].get( 'amm_pool_proportion', 1) pool_value_info[pool_name][ 'amm_pool_proportion'] = amm_pool_proportion # use for uniswap pools reward distribute uniswap_pool_proportion = pool_info[pool_name].get( 'uniswap_pool_proportion', 1) pool_value_info[pool_name][ 'uniswap_pool_proportion'] = uniswap_pool_proportion pool_type = pool_info[pool_name].get('pool_type') pool_contract_inverse = pool_info[pool_name].get( 'pool_contract_inverse', True) pool_value_info[pool_name]['pool_type'] = pool_type total_share_token_amount = self._get_total_share_token_amount( pool_share_token_address, db_session) pool_value_info[pool_name][ 'total_share_token_amount'] = total_share_token_amount share_token_items = self._get_share_token_items( pool_share_token_address, db_session) pool_value_info[pool_name]['share_token_items'] = share_token_items if pool_type == 'AMM' and block_number >= self._xia_rebalance_hard_fork_block_number: # pool_type is AMM, use effective share calc reward: # 1) period XIA and block_number >=_xia_rebalance_hard_fork_block_number; # 2) period SHANG; # 3) FROM period ZHOU, effective share eq to holder share effective_share_dict, total_effective_share_amount = self._get_effective_share_info( block_number, pool_share_token_address, share_token_items, total_share_token_amount, db_session) pool_value_info[pool_name][ 'effective_share_dict'] = effective_share_dict pool_value_info[pool_name][ 'total_effective_share_amount'] = total_effective_share_amount pool_usd_value = self._get_pool_usd_value( block_number, pool_name, pool_share_token_address, pool_contract_inverse, db_session) if total_share_token_amount != 0: pool_effective_usd_value = pool_usd_value * Wad.from_number( total_effective_share_amount) / Wad.from_number( total_share_token_amount) else: self._logger.warning( f'opps, pool:{pool_name}, share_token total amount is zero, skip it!' ) pool_effective_usd_value = Wad(0) pool_value_info[pool_name][ 'pool_effective_usd_value'] = pool_effective_usd_value pools_total_effective_value += pool_effective_usd_value else: # include two case: # 1) pool_type is UNISWAP; # 2) pool_type is AMM and block number before _xia_rebalance_hard_fork_block_number; pool_reward = Wad.from_number( pool_reward_percent) * Wad.from_number( self._reward_per_block) * Wad.from_number( uniswap_pool_proportion) pool_value_info[pool_name]['pool_reward'] = pool_reward # update AMM pool reward if pool_type == 'AMM' and block_number >= self._xia_rebalance_hard_fork_block_number: for pool_name in pool_value_info.keys(): amm_pool_proportion = pool_value_info[pool_name].get( 'amm_pool_proportion', 1) pool_effective_usd_value = pool_value_info[pool_name][ 'pool_effective_usd_value'] if block_number >= self._qin_begin_block_number: pool_reward = Wad.from_number( pool_reward_percent) * Wad.from_number( self._reward_per_block) * Wad.from_number( amm_pool_proportion) else: pool_reward = Wad.from_number( pool_reward_percent) * Wad.from_number( self._reward_per_block ) * pool_effective_usd_value / Wad.from_number( pools_total_effective_value) pool_value_info[pool_name]['pool_reward'] = pool_reward return pool_value_info
def getAvailableMargin(self, address: Address) -> Wad: availableMargin = self.contract.functions.availableMargin( address.address).call() return Wad(availableMargin)
def markPrice(self) -> Wad: return Wad(self.contract.functions.markPrice().call())
def __init__(self, price: int, amount: int): assert (isinstance(price, int)) assert (isinstance(amount, int)) self.price = Wad(price) self.amount = Wad(amount)
def current_available_margin(self) -> Wad: return Wad(self.contract.functions.currentAvailableMargin().call())
def calculateLiquidateAmount(self, guy: Address, price: Wad) -> Wad: return Wad( self.contract.functions.calculateLiquidateAmount( guy.address, price.value).call())
def netAssetValuePerShare(self) -> Wad: return Wad(self.contract.functions.netAssetValuePerShare().call())
def redeemingBalance(self, address: Address) -> Wad: assert isinstance(address, Address) return Wad( self.contract.functions.redeemingBalance(address.address).call())
def _get_effective_share_info(self, block_number, pool_share_token_address, share_token_items, total_share_token_amount, db_session): effective_share_dict = {} position_holder_dict = {} share_token_dict = {} total_effective_share_amount = Decimal(0) for item in share_token_items: share_token_dict[item.holder] = item.balance if block_number >= self._zhou_begin_block_number: # period from ZHOU, pool_effective_usd_value is pool_usd_value effective_share_dict = share_token_dict total_effective_share_amount = total_share_token_amount return effective_share_dict, total_effective_share_amount token_map = self._get_token_map(pool_share_token_address, db_session) perp_addr = token_map[pool_share_token_address].get('perp_addr') amm_proxy_addr = token_map[pool_share_token_address].get( 'amm_proxy_addr') position_items = db_session.query(PositionBalance)\ .filter(PositionBalance.perpetual_address == perp_addr)\ .all() for item in position_items: position_holder_dict[item.holder] = item.balance amm_position = position_holder_dict.get(amm_proxy_addr, Decimal(0)) for holder, holder_position_in_margin_account in position_holder_dict.items( ): holder_share_token_amount = share_token_dict.get(holder) if holder_share_token_amount == Decimal( 0) or holder_share_token_amount is None: continue holder_position_in_amm = Wad.from_number( amm_position) * Wad.from_number( holder_share_token_amount) / Wad.from_number( total_share_token_amount) holder_portfolio_position = holder_position_in_amm + Wad.from_number( holder_position_in_margin_account) imbalance_rate = abs(holder_portfolio_position / holder_position_in_amm) imbalance_rate = Decimal(str(imbalance_rate)) if self._mining_round == 'XIA': if imbalance_rate <= Decimal(0.1): holder_effective_share = holder_share_token_amount elif imbalance_rate >= Decimal(0.9): holder_effective_share = holder_share_token_amount * Decimal( 0.1) else: holder_effective_share = holder_share_token_amount * ( Decimal(89 / 80) - imbalance_rate * Decimal(9 / 8)) elif self._mining_round == 'SHANG': if imbalance_rate <= Decimal(0.2): holder_effective_share = holder_share_token_amount elif imbalance_rate >= Decimal(0.9): holder_effective_share = holder_share_token_amount * Decimal( 0.1) else: holder_effective_share = holder_share_token_amount * ( Decimal(44 / 35) - imbalance_rate * Decimal(9 / 7)) effective_share_dict[holder] = holder_effective_share total_effective_share_amount += holder_effective_share return effective_share_dict, total_effective_share_amount
def sync(self, watcher_id, block_number, block_hash, db_session): """Sync data""" if block_number < self._begin_block or block_number > self._end_block: self._logger.info(f'block_number {block_number} not in mining window!') return result = db_session.query(TokenBalance)\ .filter(TokenBalance.token == self._share_token_address)\ .with_entities( func.sum(TokenBalance.balance) ).first() if result[0] is None: self._logger.warning(f'opps, token_balance is empty!') return total_share_token_amount = result[0] # get all immature summary items immature_summary_dict = {} immature_summary_items = db_session.query(ImmatureMiningRewardSummary)\ .filter(ImmatureMiningRewardSummary.mining_round == self._mining_round)\ .all() for item in immature_summary_items: immature_summary_dict[item.holder] = item share_token_items = db_session.query(TokenBalance)\ .filter(TokenBalance.token == self._share_token_address)\ .with_entities( TokenBalance.holder, TokenBalance.balance ).all() self._logger.info(f'sync mining reward, block_number:{block_number}, holders:{len(share_token_items)}') # check rebalance_hard_fork block number if block_number >= self._rebalance_hard_fork_block_number: effective_share_dict, total_effective_share_amount = self._get_effective_share_info(share_token_items, total_share_token_amount, db_session) for item in share_token_items: holder = item.holder if block_number >= self._rebalance_hard_fork_block_number: holder_effective_share_amount = effective_share_dict.get(holder, Decimal(0)) wad_reward = Wad.from_number(self._reward_per_block) * Wad.from_number(holder_effective_share_amount) / Wad.from_number(total_effective_share_amount) reward = Decimal(str(wad_reward)) else: holder_share_token_amount = Decimal(item.balance) wad_reward = Wad.from_number(self._reward_per_block) * Wad.from_number(holder_share_token_amount) / Wad.from_number(total_share_token_amount) reward = Decimal(str(wad_reward)) immature_mining_reward = ImmatureMiningReward() immature_mining_reward.block_number = block_number immature_mining_reward.mining_round = self._mining_round immature_mining_reward.holder = holder immature_mining_reward.mcb_balance = reward db_session.add(immature_mining_reward) # update immature_mining_reward_summaries table, simulated materialized view if holder not in immature_summary_dict.keys(): immature_summary_item = ImmatureMiningRewardSummary() immature_summary_item.mining_round = self._mining_round immature_summary_item.holder = holder immature_summary_item.mcb_balance = reward else: immature_summary_item = immature_summary_dict[holder] immature_summary_item.mcb_balance += reward db_session.add(immature_summary_item)
def current_fair_price(self, user: Address) -> Wad: return Wad(self.contract.functions.currentFairPrice().call({'from': user.address}))
def _calculate_pools_reward(self, block_number, pool_info, pool_reward_percent, db_session): pool_value_info = self._get_pool_value_info(block_number, pool_info, pool_reward_percent, db_session) self._logger.info( f'sync mining reward, block_number:{block_number}, pools:{",".join(pool_info.keys())}' ) holder_amms_weight_dict = {} holder_weight_dict = {} if block_number >= self._qin_begin_block_number: holder_amms_weight_dict = self._get_holder_amms_reward_weight( block_number, pool_value_info, db_session) elif block_number >= self._zhou_begin_block_number: holder_weight_dict = self._get_holder_reward_weight( block_number, pool_value_info, db_session) for pool_name in pool_value_info.keys(): if block_number >= self._qin_begin_block_number: holder_weight_dict = holder_amms_weight_dict.get(pool_name, {}) # get all immature summary items of pool_name immature_summary_dict = {} immature_summary_items = db_session.query(ImmatureMiningRewardSummary)\ .filter(ImmatureMiningRewardSummary.mining_round == self._mining_round)\ .filter(ImmatureMiningRewardSummary.pool_name == pool_name)\ .all() for item in immature_summary_items: immature_summary_dict[item.holder] = item total_share_token_amount = pool_value_info[pool_name][ 'total_share_token_amount'] if total_share_token_amount == 0: self._logger.warning( f'opps, pool:{pool_name}, share_token total amount is zero, skip it!' ) continue share_token_items = pool_value_info[pool_name]['share_token_items'] pool_type = pool_value_info[pool_name]['pool_type'] pool_reward = pool_value_info[pool_name]['pool_reward'] for item in share_token_items: holder = item.holder if item.balance == Decimal(0): continue # amm pool, use effective share after xia_rebalance_hard_fork block number if pool_type == 'AMM' and block_number >= self._xia_rebalance_hard_fork_block_number: holder_weight = holder_weight_dict.get(holder, Decimal(1)) total_effective_share_amount = pool_value_info[pool_name][ 'total_effective_share_amount'] holder_effective_share_amount = pool_value_info[pool_name][ 'effective_share_dict'].get(holder, Decimal(0)) wad_reward = Wad.from_number( holder_weight) * pool_reward * Wad.from_number( holder_effective_share_amount) / Wad.from_number( total_effective_share_amount) reward = Decimal(str(wad_reward)) else: holder_share_token_amount = Decimal(item.balance) wad_reward = pool_reward * Wad.from_number( holder_share_token_amount) / Wad.from_number( total_share_token_amount) reward = Decimal(str(wad_reward)) immature_mining_reward = ImmatureMiningReward() immature_mining_reward.block_number = block_number immature_mining_reward.pool_name = pool_name immature_mining_reward.mining_round = self._mining_round immature_mining_reward.holder = holder immature_mining_reward.mcb_balance = reward db_session.add(immature_mining_reward) # update immature_mining_reward_summaries table, simulated materialized view if holder not in immature_summary_dict.keys(): immature_summary_item = ImmatureMiningRewardSummary() immature_summary_item.mining_round = self._mining_round immature_summary_item.pool_name = pool_name immature_summary_item.holder = holder immature_summary_item.mcb_balance = reward else: immature_summary_item = immature_summary_dict[holder] immature_summary_item.mcb_balance += reward db_session.add(immature_summary_item)
def total_supply(self) -> Wad: return Wad(self.contract.functions.totalSupply().call())
def position_size(self) -> Wad: return Wad(self.contract.functions.positionSize().call())
def getRebalanceSlippage(self) -> Wad: description = self.contract.functions.description().call() return Wad(description[2])
def balance_of(self, address: Address) -> Wad: assert (isinstance(address, Address)) return Wad(self.contract.functions.balanceOf(address.address).call())