def is_dispensable(self, dt_address: str, amount: int, to_wallet: Wallet) -> bool: """ :return: bool """ if not amount: return False token = DataToken(self.web3, dt_address) if not self.is_active(dt_address): return False user_balance = token.balanceOf(to_wallet.address) max_balance = self.max_balance(dt_address) if user_balance >= max_balance: return False max_tokens = self.max_balance(dt_address) if amount > max_tokens: return False is_true_minter = self.is_true_minter(dt_address) if is_true_minter: return True contract_balance = self.balance(dt_address) if contract_balance >= amount: return True return False
def buy_data_tokens( self, pool_address: str, amount: int, max_OCEAN_amount: int, from_wallet: Wallet ) -> str: """ Buy data tokens from this pool, paying `max_OCEAN_amount` of OCEAN tokens. If total spent <= max_OCEAN_amount. - Caller is spending OCEAN tokens, and receiving `amount` DataTokens - OCEAN tokens are going into pool, DataTokens are going out of pool The transaction fails if total spent exceeds `max_OCEAN_amount`. :param pool_address: str address of pool contract :param amount: int number of data tokens to add to this pool in *base* :param max_OCEAN_amount: :param from_wallet: :return: str transaction id/hash """ ocean_tok = DataToken(self.web3, self.ocean_address) if ocean_tok.balanceOf(from_wallet.address) < max_OCEAN_amount: raise InsufficientBalance("Insufficient funds for buying DataTokens!") if ocean_tok.allowance(from_wallet.address, pool_address) < max_OCEAN_amount: ocean_tok.approve(pool_address, max_OCEAN_amount, from_wallet) dtoken_address = self.get_token_address(pool_address) pool = BPool(self.web3, pool_address) return pool.swapExactAmountOut( tokenIn_address=self.ocean_address, # entering pool maxAmountIn=max_OCEAN_amount, # "" tokenOut_address=dtoken_address, # leaving pool tokenAmountOut=amount, # "" maxPrice=2 ** 255, # here we limit by max_num_OCEAN, not price from_wallet=from_wallet, )
def pay_for_service( amount: float, token_address: str, did: str, service_id: int, fee_receiver: str, from_wallet: Wallet, consumer: str, ) -> str: """ Submits the payment for chosen service in DataTokens. :param amount: :param token_address: :param did: :param service_id: :param fee_receiver: :param from_wallet: Wallet instance :param consumer: str the address of consumer of the service, defaults to the payer (the `from_wallet` address) :return: hex str id of transfer transaction """ amount_base = to_base_18(amount) dt = DataToken(token_address) balance = dt.balanceOf(from_wallet.address) if balance < amount_base: raise AssertionError( f"Your token balance {balance} is not sufficient " f"to execute the requested service. This service " f"requires {amount_base} number of tokens.") if did.startswith("did:"): did = add_0x_prefix(did_to_id(did)) if fee_receiver is None: fee_receiver = ZERO_ADDRESS if consumer is None: consumer = from_wallet.address tx_hash = dt.startOrder(consumer, amount_base, service_id, fee_receiver, from_wallet) try: dt.verify_order_tx( Web3Provider.get_web3(), tx_hash, did, service_id, amount_base, from_wallet.address, ) return tx_hash except (AssertionError, Exception) as e: msg = ( f"Downloading asset files failed. The problem is related to " f"the transfer of the data tokens required for the download " f"service: {e}") logger.error(msg) raise AssertionError(msg)
def pay_for_service( web3: Web3, amount: int, token_address: str, did: str, service_id: int, fee_receiver: str, from_wallet: Wallet, consumer: str, ) -> str: """ Submits the payment for chosen service in DataTokens. :param amount: :param token_address: :param did: :param service_id: :param fee_receiver: :param from_wallet: Wallet instance :param consumer: str the address of consumer of the service :return: hex str id of transfer transaction """ dt = DataToken(web3, token_address) balance = dt.balanceOf(from_wallet.address) if balance < amount: raise InsufficientBalance( f"Your token balance {pretty_ether_and_wei(balance, dt.symbol())} is not sufficient " f"to execute the requested service. This service " f"requires {pretty_ether_and_wei(amount, dt.symbol())}." ) if did.startswith("did:"): did = add_0x_prefix(did_to_id(did)) if fee_receiver is None: fee_receiver = ZERO_ADDRESS tx_hash = dt.startOrder(consumer, amount, service_id, fee_receiver, from_wallet) try: dt.verify_order_tx(tx_hash, did, service_id, amount, from_wallet.address) return tx_hash except (AssertionError, Exception) as e: msg = ( f"Downloading asset files failed. The problem is related to " f"the transfer of the data tokens required for the download " f"service: {e}" ) logger.error(msg) raise AssertionError(msg)
def mint_fake_OCEAN(config: Config) -> None: """ Does the following: 1. Mints tokens 2. Distributes tokens to TEST_PRIVATE_KEY1 and TEST_PRIVATE_KEY2 """ addresses_file = config.address_file with open(addresses_file) as f: network_addresses = json.load(f) web3 = get_web3(config.network_url) deployer_wallet = Wallet( web3, private_key=os.environ.get("FACTORY_DEPLOYER_PRIVATE_KEY"), block_confirmations=config.block_confirmations, transaction_timeout=config.transaction_timeout, ) OCEAN_token = DataToken(web3, address=network_addresses["development"]["Ocean"]) amt_distribute = to_wei(1000) OCEAN_token.mint( deployer_wallet.address, 2 * amt_distribute, from_wallet=deployer_wallet ) for key_label in ["TEST_PRIVATE_KEY1", "TEST_PRIVATE_KEY2"]: key = os.environ.get(key_label) if not key: continue w = Wallet( web3, private_key=key, block_confirmations=config.block_confirmations, transaction_timeout=config.transaction_timeout, ) if OCEAN_token.balanceOf(w.address) < amt_distribute: OCEAN_token.transfer(w.address, amt_distribute, from_wallet=deployer_wallet) if get_ether_balance(web3, w.address) < to_wei(2): send_ether(deployer_wallet, w.address, to_wei(4))
def pay_for_service(amount: float, token_address: str, did: str, service_id: int, fee_receiver: str, from_wallet: Wallet) -> str: """ Submits the payment for chosen service in DataTokens. :param amount: :param token_address: :param did: :param service_id: :param fee_receiver: :param from_wallet: Wallet instance :return: hex str id of transfer transaction """ amount_base = to_base_18(amount) dt = DataToken(token_address) balance = dt.balanceOf(from_wallet.address) if balance < amount_base: raise AssertionError( f'Your token balance {balance} is not sufficient ' f'to execute the requested service. This service ' f'requires {amount_base} number of tokens.') if did.startswith('did:'): did = add_0x_prefix(did_to_id(did)) tx_hash = dt.startOrder(from_wallet.address, amount_base, service_id, fee_receiver, from_wallet) try: dt.verify_order_tx(Web3Provider.get_web3(), tx_hash, did, service_id, amount_base, from_wallet.address) return tx_hash except (AssertionError, Exception) as e: msg = ( f'Downloading asset files failed. The problem is related to ' f'the transfer of the data tokens required for the download ' f'service: {e}') logger.error(msg) raise AssertionError(msg)
def setup_all(request, config, web3): # a test can skip setup_all() via decorator "@pytest.mark.nosetup_all" if "nosetup_all" in request.keywords: return wallet = get_ganache_wallet() if not wallet: return addresses_file = config.address_file if not os.path.exists(addresses_file): return with open(addresses_file) as f: network_addresses = json.load(f) print(f"sender: {wallet.key}, {wallet.address}, {wallet.keys_str()}") print( f"sender balance: {from_wei(get_ether_balance(web3, wallet.address))}") assert get_ether_balance( web3, wallet.address) >= to_wei(10), "Ether balance less than 10." from ocean_lib.models.data_token import DataToken OCEAN_token = DataToken(web3, address=network_addresses["development"]["Ocean"]) amt_distribute = to_wei(1000) for w in (get_publisher_wallet(), get_consumer_wallet()): if get_ether_balance(web3, w.address) < to_wei(2): send_ether(wallet, w.address, to_wei(4)) if OCEAN_token.balanceOf(w.address) < to_wei(100): OCEAN_token.mint(wallet.address, amt_distribute, from_wallet=wallet) OCEAN_token.transfer(w.address, amt_distribute, from_wallet=wallet)
def buy_at_fixed_rate( self, amount: int, wallet: Wallet, max_OCEAN_amount: int, exchange_id: Optional[Union[bytes, str]] = "", data_token: Optional[str] = "", exchange_owner: Optional[str] = "", ) -> bool: exchange, exchange_id = self.get_exchange_id_fallback_dt_and_owner( exchange_id, exchange_owner, data_token) # Figure out the amount of ocean tokens to approve before triggering the exchange function to do the swap ocean_amount = exchange.get_base_token_quote(exchange_id, amount) ocean_token = DataToken(self._web3, self.ocean_address) ocean_ticker = ocean_token.symbol() if ocean_amount > max_OCEAN_amount: raise ValidationError( f"Buying {pretty_ether_and_wei(amount, 'DataTokens')} requires {pretty_ether_and_wei(ocean_amount, ocean_ticker)} " f"tokens which exceeds the max_OCEAN_amount {pretty_ether_and_wei(max_OCEAN_amount, ocean_ticker)}." ) if ocean_token.balanceOf(wallet.address) < ocean_amount: raise InsufficientBalance( f"Insufficient funds for buying {pretty_ether_and_wei(amount, 'DataTokens')}!" ) if ocean_token.allowance(wallet.address, self._exchange_address) < ocean_amount: tx_id = ocean_token.approve(self._exchange_address, ocean_amount, wallet) tx_receipt = ocean_token.get_tx_receipt(self._web3, tx_id) if not tx_receipt or tx_receipt.status != 1: raise VerifyTxFailed( f"Approve OCEAN tokens failed, exchange address was {self._exchange_address} and tx id was {tx_id}!" ) tx_id = exchange.buy_data_token(exchange_id, data_token_amount=amount, from_wallet=wallet) return bool(exchange.get_tx_receipt(self._web3, tx_id).status)
def test_fixed_rate_exchange(web3, alice_ocean, alice_wallet, T1, bob_wallet, T2, contracts_addresses): """Tests for fixed rate exchange. tests: create generateExchangeId getExchange getExchanges getNumberOfExchanges get_base_token_quote buy_data_token """ fixed_ex = FixedRateExchange( web3, contracts_addresses[FixedRateExchange.CONTRACT_NAME]) num_ex = fixed_ex.getNumberOfExchanges() assert num_ex == len(fixed_ex.getExchanges() ), "num exchanges do not match num of exchange ids." ocean_t = alice_ocean.OCEAN_address ocn_token = DataToken(web3, ocean_t) bob_ocean_balance = ocn_token.balanceOf(bob_wallet.address) assert bob_ocean_balance >= to_wei(100), ( f"bob wallet does not have the expected OCEAN tokens balance, " f"got {from_wei(bob_ocean_balance)} instead of 100") # clear any previous ocean token allowance for the exchange contract assert (ocn_token.get_tx_receipt( web3, ocn_token.approve(fixed_ex.address, 1, bob_wallet)).status == 1), "approve failed" assert ocn_token.allowance(bob_wallet.address, fixed_ex.address) == 1, "" rate = to_wei("0.1") tx_id = fixed_ex.create(ocean_t, T1.address, rate, alice_wallet) r = fixed_ex.get_tx_receipt(web3, tx_id) assert r.status == 1, f"create fixed rate exchange failed: TxId {tx_id}." ex_id = fixed_ex.generateExchangeId(ocean_t, T1.address, alice_wallet.address).hex() ex_data = fixed_ex.getExchange(ex_id) expected_values = (alice_wallet.address, T1.address, ocean_t, rate, True, 0) assert ex_data == expected_values, ( f"fixed rate exchange {ex_id} with values {ex_data} " f"does not match the expected values {expected_values}") assert ( fixed_ex.getNumberOfExchanges() == num_ex + 1 ), f"Number of exchanges does not match, expected {num_ex+1} got {fixed_ex.getNumberOfExchanges()}." ################### # Test quote and buy datatokens amount = to_wei(10) # 10 data tokens base_token_quote = fixed_ex.get_base_token_quote(ex_id, amount) expected_base_token_quote = int(amount * rate / to_wei(1)) assert base_token_quote == ( expected_base_token_quote ), f"quote does not seem correct: expected {expected_base_token_quote}, got {base_token_quote}" assert base_token_quote == to_wei(1), "" # buy without approving OCEAN tokens, should fail assert ( run_failing_tx(fixed_ex, fixed_ex.buy_data_token, ex_id, amount, bob_wallet) == 0 ), (f"buy_data_token/swap on EX {ex_id} is expected to fail but did not, " f"maybe the FixedRateExchange is already approved as spender for bob_wallet." ) # approve ocean tokens, buying should still fail because datatokens are not approved by exchange owner assert (ocn_token.get_tx_receipt( web3, ocn_token.approve(fixed_ex.address, base_token_quote, bob_wallet)).status == 1), "approve failed" assert ( run_failing_tx(fixed_ex, fixed_ex.buy_data_token, ex_id, amount, bob_wallet) == 0 ), (f"buy_data_token/swap on EX {ex_id} is expected to fail but did not, " f"maybe the FixedRateExchange is already approved as spender for bob_wallet." ) # approve data token, now buying should succeed assert (T1.get_tx_receipt( web3, T1.approve(fixed_ex.address, amount, alice_wallet)).status == 1), "approve failed" assert (ocn_token.allowance(bob_wallet.address, fixed_ex.address) == base_token_quote), "" tx_id = fixed_ex.buy_data_token(ex_id, amount, bob_wallet) r = fixed_ex.get_tx_receipt(web3, tx_id) assert ( r.status == 1 ), f"buy_data_token/swap on EX {ex_id} failed with status 0: amount {amount}." # verify bob's datatokens balance assert T1.balanceOf(bob_wallet.address) == amount, ( f"bobs datatoken balance is not right, " f"should be {amount}, got {T1.balanceOf(bob_wallet.address)}") assert ocn_token.allowance(bob_wallet.address, fixed_ex.address) == 0, "" ##################### # create another ex then do more tests rate2 = to_wei("0.8") tx_id = fixed_ex.create(ocean_t, T2.address, rate2, alice_wallet) r = fixed_ex.get_tx_receipt(web3, tx_id) assert r.status == 1, f"create fixed rate exchange failed: TxId {tx_id}." assert fixed_ex.getNumberOfExchanges() == num_ex + 2, ( f"Number of exchanges does not match, " f"expected {num_ex+2} got {fixed_ex.getNumberOfExchanges()}.") t2_ex_id = fixed_ex.generateExchangeId(ocean_t, T2.address, alice_wallet.address).hex() exchange_ids = {ti.hex() for ti in fixed_ex.getExchanges()} assert ex_id in exchange_ids, "exchange id not found." assert t2_ex_id in exchange_ids, "exchange id not found." ############################## # test activate/deactivate assert fixed_ex.isActive(ex_id) is True, f"exchange {ex_id} is not active." assert fixed_ex.isActive( t2_ex_id) is True, f"exchange {t2_ex_id} is not active." assert ( run_failing_tx(fixed_ex, fixed_ex.deactivate, t2_ex_id, bob_wallet) == 0 ), f"exchange {t2_ex_id} deactivate (using bob_wallet) should fail but did not." assert (fixed_ex.get_tx_receipt( web3, fixed_ex.deactivate(t2_ex_id, alice_wallet)).status == 1 ), f"exchange {t2_ex_id} deactivate failed." assert (fixed_ex.isActive(t2_ex_id) is False ), f"exchange {t2_ex_id} is active, but it should be deactivated." ################################### # try buying from deactivated ex amount = to_wei(4) # num data tokens base_token_quote = fixed_ex.get_base_token_quote( t2_ex_id, amount) # num base token (OCEAN tokens) expected_base_token_quote = int(amount * rate2 / to_wei(1)) assert base_token_quote == ( expected_base_token_quote ), f"quote does not seem correct: expected {expected_base_token_quote}, got {base_token_quote}" ocn_token.get_tx_receipt( web3, ocn_token.approve(fixed_ex.address, base_token_quote, bob_wallet)) # buy should fail (deactivated exchange) assert ( run_failing_tx(fixed_ex, fixed_ex.buy_data_token, t2_ex_id, amount, bob_wallet) == 0 ), (f"buy_data_token/swap on EX {t2_ex_id} is expected to fail but did not, " f"maybe the FixedRateExchange is already approved as spender for bob_wallet." ) assert (ocn_token.allowance(bob_wallet.address, fixed_ex.address) == base_token_quote), "" assert (fixed_ex.get_tx_receipt(web3, fixed_ex.activate( t2_ex_id, alice_wallet)).status == 1 ), f"exchange {t2_ex_id} deactivate failed." assert (fixed_ex.isActive(t2_ex_id) is True), f"exchange {t2_ex_id} is not active, but it should be." ############################## # buy should still fail as datatokens are not approved to spend by the exchange contract assert ( run_failing_tx(fixed_ex, fixed_ex.buy_data_token, t2_ex_id, amount, bob_wallet) == 0 ), (f"buy_data_token/swap on EX {t2_ex_id} is expected to fail but did not, " f"maybe the FixedRateExchange is already approved as spender for bob_wallet." ) # now buy tokens should succeed assert (T2.get_tx_receipt( web3, T2.approve(fixed_ex.address, amount * 3, alice_wallet)).status == 1), "approve failed" assert (fixed_ex.get_tx_receipt( web3, fixed_ex.buy_data_token(t2_ex_id, amount, bob_wallet)).status == 1 ), f"buy_data_token/swap on EX {ex_id} failed, " assert ocn_token.allowance(bob_wallet.address, fixed_ex.address) == 0, "" # approve again for another purchase ocn_token.get_tx_receipt( web3, ocn_token.approve(fixed_ex.address, base_token_quote, bob_wallet)) assert ( run_failing_tx(fixed_ex, fixed_ex.buy_data_token, t2_ex_id, to_wei(5), bob_wallet) == 0 ), f"buy_data_token/swap on EX {t2_ex_id} should fail because not enough Ocean tokens are approved by buyer." # get new quote for new amount base_token_quote = fixed_ex.get_base_token_quote( t2_ex_id, to_wei(5)) # num base token (OCEAN tokens ocn_token.get_tx_receipt( web3, ocn_token.approve(fixed_ex.address, base_token_quote, bob_wallet)) assert (fixed_ex.get_tx_receipt( web3, fixed_ex.buy_data_token(t2_ex_id, to_wei(5), bob_wallet)).status == 1 ), f"buy_data_token/swap on EX {t2_ex_id} failed." assert ocn_token.allowance(bob_wallet.address, fixed_ex.address) == 0, "" ############################## # test getRate/setRate assert ( fixed_ex.getRate(t2_ex_id) == rate2 ), f"T2 exchange rate does not match {rate2}, got {fixed_ex.getRate(t2_ex_id)}" assert ( fixed_ex.getRate(ex_id) == rate ), f"T1 exchange rate does not match {rate}, got {fixed_ex.getRate(ex_id)}" rate2 = to_wei("0.75") assert (fixed_ex.get_tx_receipt( web3, fixed_ex.setRate(t2_ex_id, rate2, alice_wallet)).status == 1), "setRate failed." assert ( fixed_ex.getRate(t2_ex_id) == rate2 ), f"T2 exchange rate does not match {rate2}, got {fixed_ex.getRate(t2_ex_id)}" assert (run_failing_tx( fixed_ex, fixed_ex.setRate, t2_ex_id, 0, alice_wallet) == 0), "should not accept rate of Zero." assert (run_failing_tx( fixed_ex, fixed_ex.setRate, t2_ex_id, -to_wei("0.05"), alice_wallet) == 0), "should not accept a negative rate." assert (fixed_ex.get_tx_receipt( web3, fixed_ex.setRate(t2_ex_id, to_wei(1000), alice_wallet)).status == 1), "setRate failed."
def get_pool_info(self, pool_address, dt_address=None, from_block=None, to_block=None, flags=None): if not flags: flags = self.POOL_INFO_FLAGS from18 = from_base_18 web3 = Web3Provider.get_web3() current_block = ( to_block if to_block is not None else web3.eth.blockNumber ) # RPC_CALL pool = BPool(pool_address) dt_address = (dt_address if dt_address else self.get_token_address( pool_address, pool, validate=False)) # RPC_CALL from_block = (from_block if from_block is not None else self.get_creation_block(pool_address)) # RPC_CALL pool_creator = None shares = None info_dict = {"address": pool.address, "dataTokenAddress": dt_address} if "datatokenInfo" in flags: dt = DataToken(dt_address) minter = dt.minter() token_holders = [] if "dtHolders" in flags: token_holders = dt.calculate_token_holders( from_block, to_block, 0.000001) order_logs = dt.get_start_order_logs(web3, from_block=from_block, to_block=to_block) info_dict["dataToken"] = { "address": dt.address(), "name": dt.datatoken_name(), "symbol": dt.symbol(), "deciamls": dt.decimals(), "cap": from18(dt.cap()), "totalSupply": from18(dt.totalSupply()), "minter": minter, "minterBalance": from18(dt.balanceOf(minter)), "numHolders": len(token_holders), "holders": token_holders, "numOrders": len(order_logs), } if "price" in flags: info_dict.update({ "spotPrice1DT": from18(pool.getSpotPrice(self.ocean_address, dt_address)), "totalPrice1DT": self.getOceanRequiredToBuyDT(pool_address, dt_amount=1.0), }) if "reserve" in flags: ocn_reserve = from18(pool.getBalance(self.ocean_address)) dt_reserve = from18(pool.getBalance(dt_address)) info_dict.update({ "oceanWeight": from18(pool.getDenormalizedWeight(self.ocean_address)), "oceanReserve": ocn_reserve, "dtWeight": from18(pool.getDenormalizedWeight(dt_address)), "dtReserve": dt_reserve, }) if "shares" in flags or "creator" in flags: pool_creator = pool.getController() shares = from18(pool.totalSupply()) info_dict.update({"creator": pool_creator}) if "shareHolders" in flags: pool_erc20 = DataToken(pool_address) pool_holders = pool_erc20.calculate_token_holders( from_block, current_block, 0.001) info_dict.update({ "numShareHolders": len(pool_holders), "shareHolders": pool_holders }) all_join_records = [] all_exit_records = [] if "liquidityTotals" in flags or "liquidity" in flags: all_join_records = self.get_all_liquidity_additions( web3, pool_address, from_block, current_block, dt_address, raw_result=False, ) # RPC_CALL total_ocn_additions = from18( sum(r[2] for r in all_join_records if r[1] == self.ocean_address)) all_exit_records = self.get_all_liquidity_removals( web3, pool_address, from_block, current_block, dt_address, raw_result=False, ) # RPC_CALL total_ocn_removals = from18( sum(r[2] for r in all_exit_records if r[1] == self.ocean_address)) info_dict.update({ "totalOceanAdditions": total_ocn_additions, "totalOceanRemovals": total_ocn_removals, }) if "liquidity" in flags: creator_shares = from18(pool.balanceOf(pool_creator)) creator_shares_percent = creator_shares / shares account_to_join_record = self.get_account_to_liquidity_records_map( all_join_records) ocean_additions = [ from18(r[2]) for r in account_to_join_record[pool_creator] if r[1] == self.ocean_address ] dt_additions = [ from18(r[2]) for r in account_to_join_record[pool_creator] if r[1] == dt_address ] account_to_exit_record = self.get_account_to_liquidity_records_map( all_exit_records) ocean_removals = [ from18(r[2]) for r in account_to_exit_record.get(pool_creator, []) if r[1] == self.ocean_address ] dt_removals = [ from18(r[2]) for r in account_to_exit_record.get(pool_creator, []) if r[1] == dt_address ] all_swap_records = self.get_all_swaps( web3, pool_address, from_block, current_block, dt_address, raw_result=False, ) account_to_swap_record = self.get_account_to_liquidity_records_map( all_swap_records) ocean_in = [ from18(r[2]) for r in account_to_swap_record.get(pool_creator, []) if r[1] == self.ocean_address ] dt_in = [ from18(r[2]) for r in account_to_swap_record.get(pool_creator, []) if r[1] == dt_address ] ocean_out = [ from18(r[4]) for r in account_to_swap_record.get(pool_creator, []) if r[3] == self.ocean_address ] dt_out = [ from18(r[4]) for r in account_to_swap_record.get(pool_creator, []) if r[3] == dt_address ] swap_fee = from18(pool.getSwapFee()) sum_ocean_additions = sum(ocean_additions) sum_ocean_removals = sum(ocean_removals) sum_ocn_swap_in = sum(ocean_in) sum_ocn_swap_out = sum(ocean_out) sum_dt_additions = sum(dt_additions) sum_dt_removals = sum(dt_removals) sum_dt_swap_in = sum(dt_in) sum_dt_swap_out = sum(dt_out) taxable_ocn = (sum_ocn_swap_in + sum_ocn_swap_out + sum_ocean_additions + sum_ocean_removals - ocean_additions[0]) taxable_dt = (sum_dt_swap_in + sum_dt_swap_out + sum_dt_additions + sum_dt_removals - dt_additions[0]) info_dict.update({ "totalShares": shares, "creator": pool_creator, "creatorShares": creator_shares, "creatorSharesPercentage": creator_shares_percent, "creatorFirstOceanStake": ocean_additions[0], "creatorFirstDTStake": dt_additions[0], "creatorTotalOceanStake": sum(ocean_additions), "creatorTotalDTStake": sum(dt_additions), "creatorTotalOceanUnstake": sum(ocean_removals), "creatorTotalDTUnstake": sum(dt_removals), "totalOceanSwapIn": sum_ocn_swap_in, "totalOceanSwapOut": sum_ocn_swap_out, "totalDTSwapIn": sum_dt_swap_in, "totalDTSwapOut": sum_dt_swap_out, "totalSwapFeesDT": swap_fee * taxable_dt, "totalSwapFeesOcean": swap_fee * taxable_ocn, }) info_dict.update({ "fromBlockNumber": from_block, "latestBlockNumber": current_block }) return info_dict
def create( self, data_token_address: str, data_token_amount: int, OCEAN_amount: int, from_wallet: Wallet, data_token_weight: int = balancer_constants.INIT_WEIGHT_DT, swap_fee: int = balancer_constants.DEFAULT_SWAP_FEE, ) -> BPool: """ Create a new pool with bound datatoken and OCEAN token then finalize it. The pool will have publicSwap enabled and swap fee is set to `balancer_constants.DEFAULT_SWAP_FEE`. Balances of both data tokens and OCEAN tokens must be sufficient in the `from_wallet`, otherwise this will fail. :param data_token_address: str address of the DataToken contract :param data_token_amount: int amount of initial liquidity of data tokens :param OCEAN_amount: int amount of initial liquidity of OCEAN tokens :param from_wallet: Wallet instance of pool owner :param data_token_weight: int weight of the data token to be set in the new pool must be >= 1 & <= 9 :param swap_fee: int the fee taken by the pool on each swap transaction :return: BPool instance """ bfactory = BFactory(self.web3, self.bfactory_address) pool_address = bfactory.newBPool(from_wallet) pool = BPool(self.web3, pool_address) logger.debug(f"pool created with address {pool_address}.") assert to_wei("1") <= data_token_weight <= to_wei("9") base_weight = to_wei(10) - data_token_weight # Must approve datatoken and Ocean tokens to the new pool as spender dt = DataToken(self.web3, data_token_address) if dt.balanceOf(from_wallet.address) < data_token_amount: raise InsufficientBalance( "Insufficient datatoken balance for pool creation!" ) if dt.allowance(from_wallet.address, pool_address) < data_token_amount: tx_id = dt.approve(pool_address, data_token_amount, from_wallet) if dt.get_tx_receipt(self.web3, tx_id).status != 1: raise VerifyTxFailed( f"Approve datatokens failed, pool was created at {pool_address}" ) ot = DataToken(self.web3, self.ocean_address) if ot.balanceOf(from_wallet.address) < OCEAN_amount: raise InsufficientBalance("Insufficient OCEAN balance for pool creation!") if ot.allowance(from_wallet.address, pool_address) < OCEAN_amount: tx_id = ot.approve(pool_address, OCEAN_amount, from_wallet) if ot.get_tx_receipt(self.web3, tx_id).status != 1: raise VerifyTxFailed( f"Approve OCEAN tokens failed, pool was created at {pool_address}" ) tx_id = pool.setup( data_token_address, data_token_amount, data_token_weight, self.ocean_address, OCEAN_amount, base_weight, swap_fee, from_wallet, ) if pool.get_tx_receipt(self.web3, tx_id).status != 1: raise VerifyTxFailed( f"pool.setup failed: txId={tx_id}, receipt={pool.get_tx_receipt(self.web3, tx_id)}" ) logger.debug( f"create pool completed: poolAddress={pool_address}, pool setup TxId={tx_id}" ) return pool