def test_ERC20(network, alice_wallet, alice_address, bob_wallet, bob_address, OCEAN_address): """Tests an OCEAN token approval, allowance and transfers.""" token = BToken(OCEAN_address) token.approve(bob_address, 0, from_wallet=alice_wallet) # generating ERC20 Tokens, so the symbol is irrelevant assert token.symbol() == "DTT" assert token.decimals() == 18 assert token.balanceOf(alice_address) > util.to_base_18(10.0) assert token.balanceOf(bob_address) > util.to_base_18(10.0) assert token.allowance(alice_address, bob_address) == 0 token.approve(bob_address, int(1e18), from_wallet=alice_wallet) assert token.allowance(alice_address, bob_address) == int(1e18) # alice sends all her OCEAN to Bob, then Bob sends it back alice_OCEAN = token.balanceOf(alice_address) bob_OCEAN = token.balanceOf(bob_address) token.transfer(bob_address, alice_OCEAN, from_wallet=alice_wallet) assert token.balanceOf(alice_address) == 0 assert token.balanceOf(bob_address) == (alice_OCEAN + bob_OCEAN) token.transfer(alice_address, alice_OCEAN, from_wallet=bob_wallet) assert token.balanceOf(alice_address) == alice_OCEAN assert token.balanceOf(bob_address) == bob_OCEAN
def sell_data_tokens( self, pool_address: str, amount: int, min_OCEAN_amount: int, from_wallet: Wallet ) -> str: """ Sell data tokens into this pool, receive `min_OCEAN_amount` of OCEAN tokens. If total income >= min_OCEAN_amount - Caller is spending DataTokens, and receiving OCEAN tokens - DataTokens are going into pool, OCEAN tokens are going out of pool The transaction fails if total income does not reach `min_OCEAN_amount` :param pool_address: str address of pool contract :param amount: int number of data tokens to add to this pool :param min_OCEAN_amount: :param from_wallet: :return: str transaction id/hash """ dtoken_address = self.get_token_address(pool_address) dt = BToken(self.web3, dtoken_address) if dt.balanceOf(from_wallet.address) < amount: raise InsufficientBalance("Insufficient funds for selling DataTokens!") if dt.allowance(from_wallet.address, pool_address) < amount: dt.approve(pool_address, amount, from_wallet=from_wallet) pool = BPool(self.web3, pool_address) return pool.swapExactAmountIn( tokenIn_address=dtoken_address, # entering pool tokenAmountIn=amount, # "" tokenOut_address=self.ocean_address, # leaving pool minAmountOut=min_OCEAN_amount, # "" maxPrice=2 ** 255, # here we limit by max_num_OCEAN, not price from_wallet=from_wallet, )
def add_liquidity_finalized( self, pool_address: str, bpt_amount: int, max_data_token_amount: int, max_OCEAN_amount: int, from_wallet: Wallet, ) -> str: """ Add liquidity to a pool that's been finalized. Buy bpt_amount tokens from the pool, spending DataTokens and OCEAN tokens as needed and up to the specified maximum amounts. :param pool_address: str address of pool contract :param bpt_amount: int number of pool shares to receive for adding the liquidity :param max_data_token_amount: int maximum amount of Data tokens to go into the pool :param max_OCEAN_amount: int maximum amount of OCEAN tokens to go into the pool :param from_wallet: Wallet instance :return: str transaction id/hash """ assert self._is_valid_pool(pool_address), "The pool address is not valid." dt_address = self.get_token_address(pool_address) dt = BToken(self.web3, dt_address) if dt.balanceOf(from_wallet.address) < max_data_token_amount: raise InsufficientBalance( f"Insufficient funds for adding liquidity for {dt.address} datatoken!" ) if dt.allowance(from_wallet.address, pool_address) < max_data_token_amount: dt.approve(pool_address, max_data_token_amount, from_wallet=from_wallet) OCEAN = BToken(self.web3, self.ocean_address) if OCEAN.balanceOf(from_wallet.address) < max_OCEAN_amount: raise InsufficientBalance( f"Insufficient funds for adding liquidity for {OCEAN.address} OCEAN token!" ) if OCEAN.allowance(from_wallet.address, pool_address) < max_OCEAN_amount: OCEAN.approve(pool_address, max_OCEAN_amount, from_wallet=from_wallet) pool = BPool(self.web3, pool_address) return pool.joinPool( bpt_amount, [max_data_token_amount, max_OCEAN_amount], from_wallet=from_wallet, )
def test_ERC20(network, alice_wallet, alice_address, bob_wallet, bob_address, OCEAN_address): token = BToken(OCEAN_address) token.approve(bob_address, 0, from_wallet=alice_wallet) assert token.symbol() == 'OCEAN' assert token.decimals() == 18 assert token.balanceOf(alice_address) > util.to_base_18(10.0) assert token.balanceOf(bob_address) > util.to_base_18(10.0) assert token.allowance(alice_address, bob_address) == 0 token.approve(bob_address, int(1e18), from_wallet=alice_wallet) assert token.allowance(alice_address, bob_address) == int(1e18) # alice sends all her OCEAN to Bob, then Bob sends it back alice_OCEAN = token.balanceOf(alice_address) bob_OCEAN = token.balanceOf(bob_address) token.transfer(bob_address, alice_OCEAN, from_wallet=alice_wallet) assert token.balanceOf(alice_address) == 0 assert token.balanceOf(bob_address) == (alice_OCEAN + bob_OCEAN) token.transfer(alice_address, alice_OCEAN, from_wallet=bob_wallet) assert token.balanceOf(alice_address) == alice_OCEAN assert token.balanceOf(bob_address) == bob_OCEAN
def _add_liquidity( self, pool_address: str, token_address: str, amount: int, from_wallet: Wallet ) -> str: assert amount >= 0 if amount == 0: return "" pool = BPool(self.web3, pool_address) token = BToken(self.web3, token_address) assert token.balanceOf(from_wallet.address) >= amount, ( f"Insufficient funds, {amount} tokens are required of token address {token_address}, " f"but only a balance of {token.balanceOf(from_wallet.address)} is available." ) if token.allowance(from_wallet.address, pool_address) < amount: tx_id = token.approve(pool_address, amount, from_wallet) r = token.get_tx_receipt(self.web3, tx_id) if not r or r.status != 1: raise VerifyTxFailed( f"Approve OCEAN tokens failed, pool was created at {pool_address}" ) pool_amount = pool.joinswapExternAmountIn(token_address, amount, 0, from_wallet) return pool_amount