def get_all_pools(self, from_block=0, chunk_size=1000, include_balance=False): web3 = Web3Provider.get_web3() current_block = web3.eth.blockNumber bfactory = BFactory(self.bfactory_address) logs = bfactory.get_event_logs( "BPoolRegistered", from_block, current_block, {}, web3=web3, chunk_size=chunk_size, ) if include_balance: pools = sorted( [( lg.args.bpoolAddress, from_base_18( BPool(lg.args.bpoolAddress).getBalance( self.ocean_address)), ) for lg in logs], key=lambda x: x[1], reverse=True, ) else: pools = {lg.args.bpoolAddress for lg in logs} return pools
def get_all_pools(self): bfactory = BFactory(self._addresses.get(BFactory.CONTRACT_NAME)) event_name = 'BPoolRegistered' event = getattr(bfactory.events, event_name) latest_block = self._web3.eth.blockNumber _from = self.bfactory_block chunk = 10000 pools = [] while _from < latest_block: event_filter = EventFilter(event_name, event, None, from_block=_from, to_block=_from + chunk - 1) try: logs = event_filter.get_all_entries(max_tries=10) logs = sorted(logs, key=lambda l: l.blockNumber) pools.extend([l.args.bpoolAddress for l in logs]) except ValueError as e: logger.error( f'get_all_pools BFactory {bfactory.address}, fromBlock {_from}, toBlock{_from+chunk-1}: {e}' ) _from += chunk return pools
def test1(network, alice_wallet): bfactory_address = get_bfactory_address(network) bfactory = BFactory(bfactory_address) pool_address = bfactory.newBPool(from_wallet=alice_wallet) pool = BPool(pool_address) assert isinstance(pool, BPool)
def test_bpool_creation(web3, config, alice_wallet): """Test the creation of a Balancer Pool from BFactory (happy flow).""" bfactory_address = get_bfactory_address(config.address_file, web3=web3) bfactory = BFactory(web3, bfactory_address) pool_address = bfactory.newBPool(from_wallet=alice_wallet) pool = BPool(web3, pool_address) assert isinstance(pool, BPool)
def _deployBPool(network: str, from_wallet: Wallet) -> BPool: """Helper function to deploy a pool.""" factory_address = get_bfactory_address(network) factory = BFactory(factory_address) pool_address = factory.newBPool(from_wallet=from_wallet) pool = BPool(pool_address) return pool
def test_bpool_creation(network, alice_wallet): """Test the creation of a Balancer Pool from BFactory (happy flow).""" bfactory_address = get_bfactory_address(network) bfactory = BFactory(bfactory_address) pool_address = bfactory.newBPool(from_wallet=alice_wallet) pool = BPool(pool_address) assert isinstance(pool, BPool)
def _deployBPool(web3: Web3, address_file: str, network: str, from_wallet: Wallet) -> BPool: """Helper function to deploy a pool.""" factory_address = get_bfactory_address(address_file, network) factory = BFactory(web3, factory_address) pool_address = factory.newBPool(from_wallet=from_wallet) pool = BPool(web3, pool_address) return pool
def test_setSwapFee_fails(network, alice_wallet, alice_address, bob_wallet, bob_address): factory = BFactory(get_bfactory_address(network)) pool_address = factory.newBPool(alice_wallet) pool = BPool(pool_address) with pytest.raises(Exception): pool.setSwapFee(to_base_18(0.011), from_wallet=bob_wallet) # not ok, bob isn't controller pool.setController(bob_address, from_wallet=alice_wallet) pool.setSwapFee(to_base_18(0.011), from_wallet=bob_wallet) # ok now
def test_setSwapFee_fails(network, config, web3, alice_wallet, alice_address, bob_wallet, bob_address): """Tests that someone who isn't a controller can not set the swap fee.""" factory = BFactory(web3, get_bfactory_address(config.address_file, network)) pool_address = factory.newBPool(alice_wallet) pool = BPool(web3, pool_address) with pytest.raises(Exception): pool.setSwapFee(to_wei("0.011"), from_wallet=bob_wallet) # not ok, bob isn't controller pool.setController(bob_address, from_wallet=alice_wallet) pool.setSwapFee(to_wei("0.011"), from_wallet=bob_wallet) # ok now
def get_creation_block(self, pool_address): web3 = Web3Provider.get_web3() bfactory = BFactory(self.bfactory_address) current_block = web3.eth.blockNumber logs = bfactory.get_event_logs('BPoolCreated', 0, current_block, {'newBPoolAddress': pool_address}, web3=web3, chunk_size=current_block) if not logs: return {} assert len(logs) == 1, 'cannot happen' return logs[0].blockNumber
def get_creation_block(self, pool_address): bfactory = BFactory(self.web3, self.bfactory_address) current_block = self.web3.eth.block_number logs = bfactory.get_event_logs( "BPoolCreated", 0, current_block, {"newBPoolAddress": pool_address}, chunk_size=current_block, ) if not logs: return {} assert len(logs) == 1, "cannot happen" return logs[0].blockNumber
def main(): network = 'ganache' private_key = os.getenv('EVENTS_TESTS_PRIVATE_KEY') network_rpc = os.getenv('EVENTS_RPC', 'http://127.0.0.1:8545') config = Config(os.getenv('CONFIG_FILE')) ConfigProvider.set_config(config) # artifacts_path = os.getenv('ARTIFACTS_PATH', ) artifacts_path = config.artifacts_path address_file = Path( os.getenv('ADDRESS_FILE', os.path.join(artifacts_path, 'address.json'))).expanduser().resolve() print(f'deploying contracts and saving addresses in {address_file}') Web3Provider.init_web3(provider=get_web3_connection_provider(network_rpc)) ContractHandler.set_artifacts_path(artifacts_path) web3 = Web3Provider.get_web3() addresses = dict() if os.path.exists(address_file): with open(address_file) as f: network_addresses = json.load(f) else: network_addresses = {network: {}} _addresses = network_addresses[network] # ****SET ENVT**** # grab vars factory_deployer_private_key = private_key # ****SEE FUNDS**** print( "Keys:\n%s\n" % Wallet(web3=web3, private_key=factory_deployer_private_key).keysStr()) # ****DEPLOY**** deployer_wallet = Wallet(web3, private_key=factory_deployer_private_key) minter_addr = deployer_wallet.address cap = 2**255 print("****Deploy DataTokenTemplate: begin****") dt_address = DataToken.deploy(web3, deployer_wallet, artifacts_path, 'Template Contract', 'TEMPLATE', minter_addr, DataToken.DEFAULT_CAP_BASE, DTFactory.FIRST_BLOB, minter_addr) addresses[DataToken.CONTRACT_NAME] = dt_address print("****Deploy DataTokenTemplate: done****\n") print("****Deploy DTFactory: begin****") dtfactory = DTFactory( DTFactory.deploy(web3, deployer_wallet, artifacts_path, dt_address, minter_addr)) addresses[DTFactory.CONTRACT_NAME] = dtfactory.address print("****Deploy DTFactory: done****\n") print("****Deploy BPool: begin****") bpool_address = BPool.deploy(web3, deployer_wallet, artifacts_path) bpool_template = BPool(bpool_address) addresses[BPool.CONTRACT_NAME] = bpool_address print("****Deploy BPool: done****\n") print("****Deploy 'BFactory': begin****") bfactory_address = BFactory.deploy(web3, deployer_wallet, artifacts_path, bpool_template.address) bfactory = BFactory(bfactory_address) addresses[BFactory.CONTRACT_NAME] = bfactory_address print("****Deploy 'BFactory': done****\n") print("****Deploy 'FixedRateExchange': begin****") addresses[FixedRateExchange.CONTRACT_NAME] = FixedRateExchange.deploy( web3, deployer_wallet, artifacts_path) print("****Deploy 'FixedRateExchange': done****\n") print("****Deploy 'Metadata': begin****") addresses[MetadataContract.CONTRACT_NAME] = MetadataContract.deploy( web3, deployer_wallet, artifacts_path) print("****Deploy 'Metadata': done****\n") if network == 'ganache' and 'Ocean' not in _addresses: print("****Deploy fake OCEAN: begin****") # For simplicity, hijack DataTokenTemplate. minter_addr = deployer_wallet.address OCEAN_cap = 1410 * 10**6 # 1.41B OCEAN_cap_base = to_base_18(float(OCEAN_cap)) OCEAN_token = DataToken( DataToken.deploy(web3, deployer_wallet, artifacts_path, 'Ocean', 'OCEAN', minter_addr, OCEAN_cap_base, '', minter_addr)) addresses["Ocean"] = OCEAN_token.address print("****Deploy fake OCEAN: done****\n") print("****Mint fake OCEAN: begin****") OCEAN_token.mint(minter_addr, OCEAN_cap_base, from_wallet=deployer_wallet) print("****Mint fake OCEAN: done****\n") print("****Distribute fake OCEAN: begin****") amt_distribute = 1000 amt_distribute_base = to_base_18(float(amt_distribute)) for key_label in [ 'EVENTS_TESTS_PRIVATE_KEY', 'EVENTS_TESTS_PRIVATE_KEY2' ]: key = os.environ.get(key_label) if not key: continue dst_address = privateKeyToAddress(key) try: OCEAN_token.transfer(dst_address, amt_distribute_base, from_wallet=deployer_wallet) except ValueError: # handle nonce issue time.sleep(3) OCEAN_token.transfer(dst_address, amt_distribute_base, from_wallet=deployer_wallet) print("****Distribute fake OCEAN: done****\n") network_addresses[network].update(addresses) with open(address_file, 'w') as f: json.dump(network_addresses, f, indent=2) print(f'contracts deployed: {network_addresses}') return addresses
def deploy(network, addresses_file): config = ExampleConfig.get_config() ConfigProvider.set_config(config) Web3Provider.init_web3( provider=get_web3_connection_provider(config.network_url)) ContractHandler.set_artifacts_path(config.artifacts_path) artifacts_path = ContractHandler.artifacts_path if not addresses_file: addresses_file = config.address_file else: addresses_file = Path(addresses_file).expanduser().resolve() ocean = get_publisher_ocean_instance() web3 = ocean.web3 addresses = dict() if os.path.exists(addresses_file): with open(addresses_file) as f: network_addresses = json.load(f) else: network_addresses = {network: {}} if network == "ganache" and network not in network_addresses: network = "development" _addresses = network_addresses[network] # ****SET ENVT**** # grab vars factory_deployer_private_key = get_ganache_wallet().private_key # corner cases if invalidKey(factory_deployer_private_key): print("Need valid FACTORY_DEPLOYER_PRIVATE_KEY") sys.exit(0) # ****SEE FUNDS**** print("Keys:\n%s" % Wallet( web3=get_web3(), private_key=factory_deployer_private_key).keysStr()) print("") # ****DEPLOY**** deployer_wallet = Wallet(web3, private_key=factory_deployer_private_key) minter_addr = deployer_wallet.address # cap = 2 ** 255 not used if DTFactory.CONTRACT_NAME not in _addresses: print("****Deploy DataTokenTemplate: begin****") dt_address = DataToken.deploy( web3, deployer_wallet, artifacts_path, "Template Contract", "TEMPLATE", minter_addr, DataToken.DEFAULT_CAP_BASE, DTFactory.FIRST_BLOB, minter_addr, ) addresses[DataToken.CONTRACT_NAME] = dt_address print("****Deploy DataTokenTemplate: done****\n") print("****Deploy DTFactory: begin****") dtfactory = DTFactory( DTFactory.deploy(web3, deployer_wallet, artifacts_path, dt_address, minter_addr)) addresses[DTFactory.CONTRACT_NAME] = dtfactory.address print("****Deploy DTFactory: done****\n") if BFactory.CONTRACT_NAME not in _addresses: print("****Deploy BPool: begin****") bpool_address = BPool.deploy(web3, deployer_wallet, artifacts_path) bpool_template = BPool(bpool_address) addresses[BPool.CONTRACT_NAME] = bpool_address print("****Deploy BPool: done****\n") print("****Deploy 'BFactory': begin****") bfactory_address = BFactory.deploy(web3, deployer_wallet, artifacts_path, bpool_template.address) _ = BFactory(bfactory_address) addresses[BFactory.CONTRACT_NAME] = bfactory_address print("****Deploy 'BFactory': done****\n") if FixedRateExchange.CONTRACT_NAME not in _addresses: print("****Deploy 'FixedRateExchange': begin****") addresses[FixedRateExchange.CONTRACT_NAME] = FixedRateExchange.deploy( web3, deployer_wallet, artifacts_path) print("****Deploy 'FixedRateExchange': done****\n") if MetadataContract.CONTRACT_NAME not in _addresses: print("****Deploy 'Metadata': begin****") addresses[MetadataContract.CONTRACT_NAME] = MetadataContract.deploy( web3, deployer_wallet, artifacts_path) print("****Deploy 'Metadata': done****\n") if network in ("ganache", "development"): print("****Deploy fake OCEAN: begin****") # For simplicity, hijack DataTokenTemplate. minter_addr = deployer_wallet.address OCEAN_cap = 1410 * 10**6 # 1.41B OCEAN_cap_base = util.to_base_18(float(OCEAN_cap)) OCEAN_token = DataToken( DataToken.deploy( web3, deployer_wallet, artifacts_path, "Ocean", "OCEAN", minter_addr, OCEAN_cap_base, "", minter_addr, )) addresses["Ocean"] = OCEAN_token.address print("****Deploy fake OCEAN: done****\n") print("****Mint fake OCEAN: begin****") OCEAN_token.mint(minter_addr, OCEAN_cap_base, from_wallet=deployer_wallet) print("****Mint fake OCEAN: done****\n") print("****Distribute fake OCEAN: begin****") amt_distribute = 1000 amt_distribute_base = util.to_base_18(float(amt_distribute)) for key_label in ["TEST_PRIVATE_KEY1", "TEST_PRIVATE_KEY2"]: key = os.environ.get(key_label) if not key: continue dst_address = privateKeyToAddress(key) OCEAN_token.transfer(dst_address, amt_distribute_base, from_wallet=deployer_wallet) print("****Distribute fake OCEAN: done****\n") network_addresses[network].update(addresses) with open(addresses_file, "w") as f: json.dump(network_addresses, f, indent=2) return addresses
def create(self, data_token_address: str, data_token_amount: float, OCEAN_amount: float, from_wallet: Wallet, data_token_weight: float = balancer_constants.INIT_WEIGHT_DT, swap_fee: float = 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: float amount of initial liquidity of data tokens :param OCEAN_amount: float amount of initial liquidity of OCEAN tokens :param from_wallet: Wallet instance of pool owner :param data_token_weight: float weight of the data token to be set in the new pool must be >= 1 & <= 9 :param swap_fee: float the fee taken by the pool on each swap transaction :return: BPool instance """ bfactory = BFactory(self.bfactory_address) pool_address = bfactory.newBPool(from_wallet) pool = BPool(pool_address) logger.debug(f'pool created with address {pool_address}.') assert 1 <= data_token_weight <= 9 base_weight = 10.0 - data_token_weight # Must approve datatoken and Ocean tokens to the new pool as spender dt = DataToken(data_token_address) tx_id = dt.approve_tokens(pool_address, data_token_amount, from_wallet, wait=True) if dt.get_tx_receipt(tx_id).status != 1: raise AssertionError( f'Approve datatokens failed, pool was created at {pool_address}' ) ot = DataToken(self.ocean_address) tx_id = ot.approve_tokens(pool_address, OCEAN_amount, from_wallet, wait=True) if ot.get_tx_receipt(tx_id).status != 1: raise AssertionError( f'Approve OCEAN tokens failed, pool was created at {pool_address}' ) tx_id = pool.setup(data_token_address, to_base_18(data_token_amount), to_base_18(data_token_weight), self.ocean_address, to_base_18(OCEAN_amount), to_base_18(base_weight), to_base_18(swap_fee), from_wallet) if pool.get_tx_receipt(tx_id).status != 1: raise AssertionError( f'pool.setup failed: txId={tx_id}, receipt={pool.get_tx_receipt(tx_id)}' ) logger.debug( f'create pool completed: poolAddress={pool_address}, pool setup TxId={tx_id}' ) return pool
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
def test1(network, OCEAN_address, alice_wallet, alice_ocean, alice_address, bob_wallet): bfactory_address = get_bfactory_address(network) # =============================================================== # 1. Alice publishes a dataset (= publishes a datatoken) # For now, you're Alice:) Let's proceed. DT = alice_ocean.create_data_token("DataToken1", "DT1", alice_wallet, blob="localhost:8030") DT_address = DT.address # =============================================================== # 2. Alice hosts the dataset # Do from console: # >> touch /var/mydata/myFolder1/file # >> ENV DT="{'0x1234':'/var/mydata/myFolder1'}" # >> docker run @oceanprotocol/provider-py -e CONFIG=DT # =============================================================== # 3. Alice mints DTs DT.mint(alice_address, to_base_18(1000.0), alice_wallet) # =============================================================== # 4. Alice creates an OCEAN-DT pool (=a Balancer Pool) bfactory = BFactory(bfactory_address) pool_address = bfactory.newBPool(from_wallet=alice_wallet) pool = BPool(pool_address) pool.setPublicSwap(True, from_wallet=alice_wallet) pool.setSwapFee(to_base_18(0.1), from_wallet=alice_wallet) # set 10% fee DT.approve(pool_address, to_base_18(90.0), from_wallet=alice_wallet) pool.bind( DT_address, to_base_18(90.0), balancer_constants.INIT_WEIGHT_DT_BASE, from_wallet=alice_wallet, ) OCEAN_token = BToken(OCEAN_address) txid = OCEAN_token.approve(pool_address, to_base_18(10.0), from_wallet=alice_wallet) r = OCEAN_token.get_tx_receipt(txid) assert r and r.status == 1, f"approve failed, receipt={r}" pool.bind( OCEAN_address, to_base_18(10.0), balancer_constants.INIT_WEIGHT_OCEAN_BASE, from_wallet=alice_wallet, ) # =============================================================== # 5. Alice adds liquidity to pool DT.approve(pool_address, to_base_18(9.0), from_wallet=alice_wallet) pool.rebind( DT_address, to_base_18(90.0 + 9.0), balancer_constants.INIT_WEIGHT_DT_BASE, from_wallet=alice_wallet, ) OCEAN_token.approve(pool_address, to_base_18(1.0), from_wallet=alice_wallet) pool.rebind( OCEAN_address, to_base_18(10.0 + 1.0), to_base_18(balancer_constants.INIT_WEIGHT_OCEAN), from_wallet=alice_wallet, ) # 6. Bob buys a DT from pool OCEAN_token.approve(pool_address, to_base_18(2.0), from_wallet=bob_wallet) pool.swapExactAmountOut( tokenIn_address=OCEAN_address, maxAmountIn_base=to_base_18(2.0), tokenOut_address=DT_address, tokenAmountOut_base=to_base_18(1.0), maxPrice_base=2**255, from_wallet=bob_wallet, ) # =============================================================== # 7. Bob consumes dataset # <don't need to show here> # =============================================================== # 8. Alice removes liquidity pool.rebind( DT_address, to_base_18(90.0 + 9.0 - 2.0), balancer_constants.INIT_WEIGHT_DT_BASE, from_wallet=alice_wallet, ) pool.rebind( OCEAN_address, to_base_18(10.0 + 1.0 - 3.0), balancer_constants.INIT_WEIGHT_OCEAN_BASE, from_wallet=alice_wallet, ) # =============================================================== # 9. Alice sells data tokens DT.approve(pool_address, to_base_18(1.0), from_wallet=alice_wallet) pool.swapExactAmountIn( tokenIn_address=DT_address, tokenAmountIn_base=to_base_18(1.0), tokenOut_address=OCEAN_address, minAmountOut_base=to_base_18(0.0001), maxPrice_base=2**255, from_wallet=alice_wallet, ) # =============================================================== # 10. Alice finalizes pool. Now others can add liquidity. pool.finalize(from_wallet=alice_wallet) # =============================================================== # 11. Bob adds liquidity DT.approve(pool_address, to_base_18(1.0), from_wallet=bob_wallet) OCEAN_token.approve(pool_address, to_base_18(1.0), from_wallet=bob_wallet) pool.joinPool(to_base_18(0.1), [to_base_18(1.0), to_base_18(1.0)], from_wallet=bob_wallet) # =============================================================== # 12. Bob adds liquidity AGAIN DT.approve(pool_address, to_base_18(1.0), from_wallet=bob_wallet) OCEAN_token.approve(pool_address, to_base_18(1.0), from_wallet=bob_wallet) pool.joinPool(to_base_18(0.1), [to_base_18(1.0), to_base_18(1.0)], from_wallet=bob_wallet)
def _deployBPool(network: str, from_wallet: Wallet) -> BPool: factory_address = get_bfactory_address(network) factory = BFactory(factory_address) pool_address = factory.newBPool(from_wallet=from_wallet) pool = BPool(pool_address) return pool