示例#1
0
 def unstakeOCEAN(self, BPT_unstake: float, pool: bpool.BPool):
     pool.exitswapPoolAmountIn(
         tokenOut_address=globaltokens.OCEAN_address(),
         poolAmountIn_base=toBase18(BPT_unstake),
         minAmountOut_base=toBase18(0.0),
         from_wallet=self._web3wallet)
     self.resetCachedInfo()
示例#2
0
def test_ERC20(alice_wallet, alice_address, bob_wallet, bob_address):
    #use DTFactory to create the token, and Datatoken to mint it
    f = dtfactory.DTFactory()
    dt_address = f.createToken('',
                               'TOK',
                               'TOK',
                               web3util.toBase18(100.0),
                               from_wallet=alice_wallet)
    dt = datatoken.Datatoken(dt_address)
    dt.mint(alice_address, web3util.toBase18(100.0), from_wallet=alice_wallet)

    #now that we've created & minted the token, we can use it with BToken interface
    token = btoken.BToken(dt_address)
    assert token.address == dt_address
    assert token.decimals() == 18
    assert token.balanceOf_base(alice_address) == web3util.toBase18(100.0)
    assert token.balanceOf_base(bob_address) == 0

    assert token.allowance_base(alice_address, bob_address) == 0
    token.approve(bob_address, int(1e18), from_wallet=alice_wallet)
    assert token.allowance_base(alice_address, bob_address) == int(1e18)

    #alice sends all her tokens to Bob, then Bob sends it back
    alice_TOK = token.balanceOf_base(alice_address)
    bob_TOK = token.balanceOf_base(bob_address)
    token.transfer(bob_address, alice_TOK, from_wallet=alice_wallet)
    assert token.balanceOf_base(alice_address) == 0
    assert token.balanceOf_base(bob_address) == (alice_TOK + bob_TOK)

    token.transfer(alice_address, alice_TOK, from_wallet=bob_wallet)
    assert token.balanceOf_base(alice_address) == alice_TOK
    assert token.balanceOf_base(bob_address) == bob_TOK
示例#3
0
def testSendEth():
    _web3 = web3util.get_web3()
    network = web3util.get_network()

    #wallet1 should have got ETH from ganache startup (see deploy.py)
    private_key1 = web3util.confFileValue(network, 'TEST_PRIVATE_KEY1')
    wallet1 = web3wallet.Web3Wallet(private_key1)
    orig_bal1_base = wallet1.ETH_base()
    print("orig bal1 = %s" % web3util.fromBase18(orig_bal1_base))
    assert orig_bal1_base > web3util.toBase18(1.0)

    #wallet2 should have 0 ETH
    wallet2 = web3wallet.randomWeb3Wallet()
    orig_bal2_base = wallet2.ETH_base()
    print("orig bal2 = %s" % web3util.fromBase18(orig_bal2_base))
    assert orig_bal2_base == 0

    #wallet1 gives wallet2 1.0 ETH
    sent_base = web3util.toBase18(1.0)
    wallet1.sendEth(wallet2.address, sent_base)
    
    new_bal1_base = wallet1.ETH_base()
    new_bal2_base = wallet2.ETH_base()
    print("new bal1 = %s" % web3util.fromBase18(new_bal1_base))
    print("new bal2 = %s" % web3util.fromBase18(new_bal2_base))
    assert new_bal2_base == sent_base
    assert (orig_bal1_base - sent_base*1.1) < new_bal1_base < (orig_bal1_base - sent_base)
示例#4
0
def test_gulp(T1, alice_wallet):
    pool = _deployBPool(alice_wallet)

    #bind T1 to the pool, with a balance of 2.0
    T1.approve(pool.address, toBase18(50.0), from_wallet=alice_wallet)
    pool.bind(T1.address,
              toBase18(2.0),
              toBase18(50.0),
              from_wallet=alice_wallet)

    #T1 is now pool's (a) ERC20 balance (b) _records[token].balance
    assert T1.balanceOf_base(pool.address) == toBase18(2.0)  #ERC20 balance
    assert pool.getBalance_base(T1.address) == toBase18(2.0)  #records[]

    #but then some joker accidentally sends 5.0 tokens to the pool's address
    #  rather than binding / rebinding. So it's in ERC20 bal but not records[]
    T1.transfer(pool.address, toBase18(5.0), from_wallet=alice_wallet)
    assert T1.balanceOf_base(pool.address) == toBase18(2.0 + 5.0)  #ERC20 bal
    assert pool.getBalance_base(T1.address) == toBase18(2.0)  #records[]

    #so, 'gulp' gets the pool to absorb the tokens into its balances.
    # i.e. to update _records[token].balance to be in sync with ERC20 balance
    pool.gulp(T1.address, from_wallet=alice_wallet)
    assert T1.balanceOf_base(pool.address) == toBase18(2.0 + 5.0)  #ERC20
    assert pool.getBalance_base(T1.address) == toBase18(2.0 + 5.0)  #records[]
示例#5
0
def test_calcSpotPrice_base(T1, T2, alice_address, alice_wallet):
    pool = _deployBPool(alice_wallet)
    x = pool.calcSpotPrice_base(tokenBalanceIn_base=toBase18(10.0),
                                tokenWeightIn_base=toBase18(1.0),
                                tokenBalanceOut_base=toBase18(11.0),
                                tokenWeightOut_base=toBase18(1.0),
                                swapFee_base=0)
    assert round(fromBase18(x), 3) == 0.909
示例#6
0
 def _createDatatoken(self,dt_name:str,mint_amt:float)-> datatoken.Datatoken:
     """Create datatoken contract and mint DTs to self."""
     wallet = self._wallet._web3wallet
     DT_address = dtfactory.DTFactory().createToken(
         '', dt_name, dt_name, toBase18(mint_amt), from_wallet=wallet)
     DT = datatoken.Datatoken(DT_address)
     DT.mint(wallet.address, toBase18(mint_amt), from_wallet=wallet)
     return DT
示例#7
0
def test_calcInGivenOut_base(alice_wallet):
    pool = _deployBPool(alice_wallet)
    x = pool.calcInGivenOut_base(tokenBalanceIn_base=toBase18(10.0),
                                 tokenWeightIn_base=toBase18(1.0),
                                 tokenBalanceOut_base=toBase18(10.1),
                                 tokenWeightOut_base=toBase18(1.0),
                                 tokenAmountOut_base=toBase18(1.0),
                                 swapFee_base=0)
    assert round(fromBase18(x), 3) == 1.099
示例#8
0
def _createDT(web3_w: web3wallet.Web3Wallet):
    DT_address = dtfactory.DTFactory().createToken('foo',
                                                   'DT1',
                                                   'DT1',
                                                   toBase18(_DT_INIT),
                                                   from_wallet=web3_w)
    DT = datatoken.Datatoken(DT_address)
    DT.mint(web3_w.address, toBase18(_DT_INIT), from_wallet=web3_w)
    return DT
示例#9
0
def test_calcPoolInGivenSingleOut_base(alice_wallet):
    pool = _deployBPool(alice_wallet)
    x = pool.calcPoolInGivenSingleOut(tokenBalanceOut_base=toBase18(1000.0),
                                      tokenWeightOut_base=toBase18(5.0),
                                      poolSupply_base=toBase18(100.0),
                                      totalWeight_base=toBase18(10.0),
                                      tokenAmountOut_base=toBase18(0.1),
                                      swapFee_base=0)
    assert round(fromBase18(x), 3) == 0.005
示例#10
0
def test_calcSingleOutGivenPoolIn_base(alice_wallet):
    pool = _deployBPool(alice_wallet)
    x = pool.calcSingleOutGivenPoolIn_base(tokenBalanceOut_base=toBase18(10.0),
                                           tokenWeightOut_base=toBase18(1.0),
                                           poolSupply_base=toBase18(120.0),
                                           totalWeight_base=toBase18(2.0),
                                           poolAmountIn_base=toBase18(10.0),
                                           swapFee_base=0)
    assert round(fromBase18(x), 3) == 1.597
示例#11
0
def test_setSwapFee_fails(alice_wallet, alice_address, bob_wallet,
                          bob_address):
    factory = bfactory.BFactory()
    pool_address = factory.newBPool(alice_wallet)
    pool = bpool.BPool(pool_address)
    with pytest.raises(Exception):
        pool.setSwapFee(toBase18(0.011),
                        from_wallet=bob_wallet)  #not ok, bob isn't controller
    pool.setController(bob_address, from_wallet=alice_wallet)
    pool.setSwapFee(toBase18(0.011), from_wallet=bob_wallet)  #ok now
示例#12
0
 def stakeOCEAN(self, OCEAN_stake: float, pool: bpool.BPool):
     OCEAN = globaltokens.OCEANtoken()
     OCEAN.approve(pool.address,
                   toBase18(OCEAN_stake),
                   from_wallet=self._web3wallet)
     pool.joinswapExternAmountIn(
         tokenIn_address=globaltokens.OCEAN_address(),
         tokenAmountIn_base=toBase18(OCEAN_stake),
         minPoolAmountOut_base=toBase18(0.0),
         from_wallet=self._web3wallet)
     self.resetCachedInfo()
示例#13
0
def test_exitswapExternAmountOut(T1, T2, alice_address, alice_wallet):
    pool = _createPoolWith2Tokens(T1, T2, alice_wallet, 90.0, 10.0, 9.0, 1.0)
    BPT = pool
    pool.finalize(from_wallet=alice_wallet)
    assert fromBase18(T1.balanceOf_base(alice_address)) == 910.0
    pool.exitswapExternAmountOut(
        tokenOut_address=T1.address,
        tokenAmountOut_base=toBase18(2.0),  #T1 wanted
        maxPoolAmountIn_base=toBase18(10.0),  #max BPT spent 
        from_wallet=alice_wallet)
    assert fromBase18(T1.balanceOf_base(alice_address)) == (910.0 + 2.0)
    assert fromBase18(BPT.balanceOf_base(alice_address)) >= (100.0 - 10.0)
示例#14
0
def test_joinswapPoolAmountOut(T1, T2, alice_address, alice_wallet):
    pool = _createPoolWith2Tokens(T1, T2, alice_wallet, 90.0, 10.0, 9.0, 1.0)
    BPT = pool
    pool.finalize(from_wallet=alice_wallet)
    T1.approve(pool.address, toBase18(90.0), from_wallet=alice_wallet)
    assert fromBase18(T1.balanceOf_base(alice_address)) == 910.0
    pool.joinswapPoolAmountOut(
        tokenIn_address=T1.address,
        poolAmountOut_base=toBase18(10.0),  #BPT wanted
        maxAmountIn_base=toBase18(90.0),  #max T1 to spend
        from_wallet=alice_wallet)
    assert fromBase18(T1.balanceOf_base(alice_address)) >= (910.0 - 90.0)
    assert fromBase18(BPT.balanceOf_base(alice_address)) == (100.0 + 10.0)
示例#15
0
    def _candPoolAgents(self, state):
        """Pools that this agent can afford to buy 1.0 datatokens from,
        at least based on a first approximation. 
        """
        OCEAN_address = globaltokens.OCEAN_address()
        OCEAN = self.OCEAN()
        all_pool_agents = state.agents.filterToPool().values()
        cand_pool_agents = []
        for pool_agent in all_pool_agents:
            pool = pool_agent.pool
            DT_address = pool_agent.datatoken_address

            pool_DT_balance_base = pool.getBalance_base(DT_address)
            pool_OCEAN_balance_base = pool.getBalance_base(OCEAN_address)
            pool_DT_weight_base = pool.getDenormalizedWeight_base(DT_address)
            pool_OCEAN_weight_base = pool.getDenormalizedWeight_base(
                OCEAN_address)
            pool_swapFee_base = pool.getSwapFee_base()

            DT_amount_out_base = toBase18(1.0)

            spotPriceBefore_base = pool.getSpotPrice_base(
                tokenIn_address=OCEAN_address, tokenOut_address=DT_address)
            OCEANamountIn_base = pool.calcInGivenOut_base(
                tokenBalanceIn_base=pool_OCEAN_balance_base,
                tokenWeightIn_base=pool_OCEAN_weight_base,
                tokenBalanceOut_base=pool_DT_balance_base,
                tokenWeightOut_base=pool_DT_weight_base,
                tokenAmountOut_base=DT_amount_out_base,
                swapFee_base=pool_swapFee_base)

            if OCEANamountIn_base < OCEAN:
                cand_pool_agents.append(pool)

        return cand_pool_agents
示例#16
0
    def _buy(self, state):
        """Buy, and consume dataset"""
        OCEAN_address = globaltokens.OCEAN_address()
        OCEAN = self.OCEAN()
        OCEAN_base = self._wallet._OCEAN_base()
        DT_amount_out_base = toBase18(1.0)

        cand_pool_agents = self._candPoolAgents()
        assert cand_pool_agents
        random.shuffle(cand_pool_agents)

        #FIXME: there will be times when slippage is sufficiently high that
        # the data consumer won't be able to successfully buy the DT.
        # In that case, should pick the second choice in cand_pool_agents. Etc.
        pool_agent = cand_pool_agents[0]
        pool = pool_agent.pool
        DT_address = pool_agent.datatoken_address

        pool.swapExactAmountOut(tokenIn_address=OCEAN_address,
                                maxAmountIn_base=OCEAN_base,
                                tokenOut_address=DT_address,
                                tokenAmountOut_base=DT_amount_out_base,
                                maxPrice_base=constants.HUGEINT,
                                from_wallet=self._wallet._web3wallet)

        self._wallet.resetCachedInfo()
示例#17
0
    def transferOCEAN(self, dst_wallet, amt: float) -> None:
        assert isinstance(dst_wallet, AgentWallet) or \
            isinstance(dst_wallet, BurnWallet)
        dst_address = dst_wallet._address

        amt_base = toBase18(amt)
        assert amt_base >= 0
        if amt_base == 0:
            return

        OCEAN_base = self._OCEAN_base()
        if OCEAN_base == 0:
            raise ValueError("no funds to transfer from")

        tol = 1e-12
        if (1.0 - tol) <= amt / fromBase18(OCEAN_base) <= (1.0 + tol):
            amt_base = OCEAN_base

        if amt_base > OCEAN_base:
            raise ValueError("transfer amt (%s) exceeds OCEAN holdings (%s)" %
                             (fromBase18(amt_base), fromBase18(OCEAN_base)))

        globaltokens.OCEANtoken().transfer(dst_address, amt_base,
                                           self._web3wallet)

        dst_wallet._total_OCEAN_in += amt
        self.resetCachedInfo()
        dst_wallet.resetCachedInfo()
示例#18
0
def test_rebind_more_tokens(T1, T2, alice_wallet):
    pool = _createPoolWith2Tokens(T1, T2, alice_wallet, 90.0, 10.0, 9.0, 1.0)

    #insufficient allowance
    with pytest.raises(Exception):
        pool.rebind(T1.address,
                    toBase18(120.0),
                    toBase18(9.0),
                    from_wallet=alice_wallet)

    #sufficient allowance
    T1.approve(pool.address, toBase18(30.0), from_wallet=alice_wallet)
    pool.rebind(T1.address,
                toBase18(120.0),
                toBase18(9.0),
                from_wallet=alice_wallet)
示例#19
0
def test_finalize(T1, T2, alice_address, alice_wallet):
    pool = _createPoolWith2Tokens(T1, T2, alice_wallet, 90.0, 10.0, 9.0, 1.0)

    assert not pool.isPublicSwap()
    assert not pool.isFinalized()
    assert pool.totalSupply_base() == 0
    assert pool.balanceOf_base(alice_address) == 0
    assert pool.allowance_base(alice_address, pool.address) == 0

    pool.finalize(from_wallet=alice_wallet)

    assert pool.isPublicSwap()
    assert pool.isFinalized()
    assert pool.totalSupply_base() == toBase18(100.0)
    assert pool.balanceOf_base(alice_address) == toBase18(100.0)
    assert pool.allowance_base(alice_address, pool.address) == 0

    assert pool.getFinalTokens() == [T1.address, T2.address]
    assert pool.getCurrentTokens() == [T1.address, T2.address]
示例#20
0
    def __init__(self, USD: float = 0.0, OCEAN: float = 0.0, private_key=None):
        if private_key is None:
            self._web3wallet = web3wallet.randomWeb3Wallet()
        else:
            self._web3wallet = web3wallet.Web3Wallet(private_key)

        #Give the new wallet ETH to pay gas fees (but don't track otherwise)
        self._web3wallet.fundFromAbove(toBase18(0.01))  #magic number

        #USD
        self._USD = USD  #lump in ETH too

        #OCEAN
        globaltokens.mintOCEAN(address=self._web3wallet.address,
                               value_base=toBase18(OCEAN))
        self._cached_OCEAN_base: typing.Union[int, None] = None  #for speed

        #amount
        self._total_USD_in: float = USD
        self._total_OCEAN_in: float = OCEAN
示例#21
0
def test_OCEAN():
    wallet = web3wallet.randomWeb3Wallet()

    OCEAN_base = web3util.toBase18(3.0)
    globaltokens.mintOCEAN(address=wallet.address, value_base=OCEAN_base)
    OCEAN_token = globaltokens.OCEANtoken()
    assert isinstance(OCEAN_token, datatoken.Datatoken)
    assert OCEAN_token.symbol() == 'OCEAN'
    assert OCEAN_token.balanceOf_base(wallet.address) == OCEAN_base

    globaltokens.mintOCEAN(address=wallet.address, value_base=OCEAN_base)
    assert OCEAN_token.balanceOf_base(wallet.address) == OCEAN_base * 2
示例#22
0
    def create_pool(self, 
                   datatoken: Datatoken, 
                   _DT_STAKE: float, 
                   _OCEAN_STAKE: float, 
                   POOL_WEIGHT_DT: float,
                   POOL_WEIGHT_OCEAN: float):
        OCEAN = OCEANtoken()
        dt_stake: int = web3util.toBase18(_DT_STAKE)
        ocean_stake: int = web3util.toBase18(_OCEAN_STAKE)
        pool_weight_dt: int = web3util.toBase18(POOL_WEIGHT_DT)
        pool_weight_ocean: int = web3util.toBase18(POOL_WEIGHT_OCEAN)
        pool_address = BFactory().newBPool(from_wallet=self.web3wallet)
        pool = BPool(pool_address)
        datatoken.approve(pool.address, web3util.toBase18(dt_stake), from_wallet=self.web3wallet)
        OCEAN.approve(pool.address, web3util.toBase18(_OCEAN_STAKE), from_wallet=self.web3wallet)
        pool.bind(
            token_address=datatoken.address, 
            balance_base=dt_stake, 
            weight_base=pool_weight_dt,
            from_wallet=self.web3wallet)
        pool.bind(
            token_address=OCEAN.address,
            balance_base=ocean_stake,
            weight_base=pool_weight_ocean,
            from_wallet=self.web3wallet)
        pool.finalize(from_wallet=self.web3wallet)

        return pool
示例#23
0
def test_ERC20(alice_wallet, alice_address,
               bob_wallet, bob_address):
    f = dtfactory.DTFactory()
    dt_address = f.createToken('foo', 'DT1', 'DT1', web3util.toBase18(100.0),
                               from_wallet=alice_wallet)
    dt = datatoken.Datatoken(dt_address)
    dt.mint(alice_address, web3util.toBase18(100.0), from_wallet=alice_wallet)

    #functionality inherited from btoken
    assert dt.address == dt_address
    assert dt.symbol() == 'DT1'
    assert dt.decimals() == 18
    assert dt.balanceOf_base(alice_address) == web3util.toBase18(100.0)
    dt.transfer(bob_address, web3util.toBase18(50.0), from_wallet=alice_wallet)
    assert dt.allowance_base(alice_address, bob_address) == 0
    dt.approve(bob_address, int(1e18), from_wallet=alice_wallet)
    assert dt.allowance_base(alice_address, bob_address) == int(1e18)
    
    #functionality for just datatoken
    assert dt.blob() == 'foo'
    assert 'mint' in dir(dt)
    assert 'setMinter' in dir(dt)
示例#24
0
def test_joinSwapExternAmountIn(T1, T2, alice_wallet, alice_address):
    pool = _createPoolWith2Tokens(T1, T2, alice_wallet, 90.0, 10.0, 9.0, 1.0)
    T1.approve(pool.address, toBase18(100.0), from_wallet=alice_wallet)

    #pool's not public
    with pytest.raises(Exception):
        pool.swapExactAmountOut(tokenIn_address=T1.address,
                                maxAmountIn_base=toBase18(100.0),
                                tokenOut_address=T2.address,
                                tokenAmountOut_base=toBase18(10.0),
                                maxPrice_base=HUGEINT,
                                from_wallet=alice_wallet)

    #pool's public
    pool.setPublicSwap(True, from_wallet=alice_wallet)
    pool.swapExactAmountOut(tokenIn_address=T1.address,
                            maxAmountIn_base=toBase18(100.0),
                            tokenOut_address=T2.address,
                            tokenAmountOut_base=toBase18(1.0),
                            maxPrice_base=HUGEINT,
                            from_wallet=alice_wallet)
    assert 908.94 <= fromBase18(T1.balanceOf_base(alice_address)) <= 908.95
    assert fromBase18(T2.balanceOf_base(alice_address)) == (1000.0 - 9.0)
示例#25
0
def _deployAndMintToken(symbol: str, to_address: str) -> datatoken.Datatoken:
    network = web3util.get_network()
    private_key = web3util.confFileValue(network, 'TEST_PRIVATE_KEY1')
    from_wallet = Web3Wallet(private_key=private_key)
    factory = dtfactory.DTFactory()
    amount_base = web3util.toBase18(1000.0)
    dt_address = factory.createToken('', symbol, symbol, amount_base,
                                     from_wallet)
    dt = datatoken.Datatoken(dt_address)
    dt.mint(account=to_address,
            value_base=amount_base,
            from_wallet=from_wallet)

    return dt
示例#26
0
 def create_datatoken(self,
                      blob: str,
                      name: str,
                      symbol: str,
                      cap_base: float,
                      use_cache: bool=False):
     if self._CACHED_DT and use_cache:
         return self._CACHED_DT
     cap_base = web3util.toBase18(cap_base)
     datatoken_address = DTFactory().createToken(blob, name, symbol, cap_base, self.web3wallet)
     dt = Datatoken(datatoken_address)
     dt.mint(account=self.web3wallet.address, value_base=cap_base, from_wallet=self.web3wallet)
     self._CACHED_DT = dt
     self.datatokens_created[symbol] = dt
     return dt
示例#27
0
def test_notokens_basic(OCEAN_address, alice_wallet, alice_address):
    pool = _deployBPool(alice_wallet)

    assert not pool.isPublicSwap()
    assert not pool.isFinalized()
    assert not pool.isBound(OCEAN_address)
    assert pool.getNumTokens() == 0
    assert pool.getCurrentTokens() == []
    with pytest.raises(Exception):
        pool.getFinalTokens()  #pool's not finalized
    assert pool.getSwapFee_base() == toBase18(1e-6)
    assert pool.getController() == alice_address
    assert str(pool)

    with pytest.raises(Exception):
        pool.finalize()  #can't finalize if no tokens
示例#28
0
def _createPoolWith2Tokens(T1: btoken.BToken, T2: btoken.BToken,
                           wallet: web3wallet.Web3Wallet, bal1: float,
                           bal2: float, w1: float, w2: float):
    pool = _deployBPool(wallet)

    T1.approve(pool.address, toBase18(bal1), from_wallet=wallet)
    T2.approve(pool.address, toBase18(bal2), from_wallet=wallet)

    pool.bind(T1.address, toBase18(bal1), toBase18(w1), from_wallet=wallet)
    pool.bind(T2.address, toBase18(bal2), toBase18(w2), from_wallet=wallet)

    return pool
示例#29
0
def _createPool(DT:datatoken.Datatoken, web3_w:web3wallet.Web3Wallet):
    OCEAN = globaltokens.OCEANtoken()
    
    #Create OCEAN-DT pool
    p_address = bfactory.BFactory().newBPool(from_wallet=web3_w)
    pool = bpool.BPool(p_address)

    DT.approve(pool.address, toBase18(_DT_STAKE), from_wallet=web3_w)
    OCEAN.approve(pool.address, toBase18(_OCEAN_STAKE),from_wallet=web3_w)

    pool.bind(DT.address, toBase18(_DT_STAKE),
              toBase18(POOL_WEIGHT_DT), from_wallet=web3_w)
    pool.bind(OCEAN.address, toBase18(_OCEAN_STAKE),
              toBase18(POOL_WEIGHT_OCEAN), from_wallet=web3_w)

    pool.finalize(from_wallet=web3_w)
    
    return pool
示例#30
0
    def _createPoolAgent(self, state) -> PoolAgent:
        assert self.OCEAN() > 0.0, "should not call if no OCEAN"
        wallet = self._wallet._web3wallet
        OCEAN = globaltokens.OCEANtoken()

        #name
        pool_i = len(state.agents.filterToPool())
        dt_name = f'DT{pool_i}'
        pool_agent_name = f'pool{pool_i}'

        #new DT
        DT = self._createDatatoken(dt_name, mint_amt=1000.0)  #magic number

        #new pool
        pool_address = bfactory.BFactory().newBPool(from_wallet=wallet)
        pool = bpool.BPool(pool_address)

        #bind tokens & add initial liquidity
        OCEAN_bind_amt = self.OCEAN()  #magic number: use all the OCEAN
        DT_bind_amt = 20.0  #magic number

        DT.approve(pool.address, toBase18(DT_bind_amt), from_wallet=wallet)
        OCEAN.approve(pool.address,
                      toBase18(OCEAN_bind_amt),
                      from_wallet=wallet)

        pool.bind(DT.address,
                  toBase18(DT_bind_amt),
                  toBase18(POOL_WEIGHT_DT),
                  from_wallet=wallet)
        pool.bind(OCEAN.address,
                  toBase18(OCEAN_bind_amt),
                  toBase18(POOL_WEIGHT_OCEAN),
                  from_wallet=wallet)

        pool.finalize(from_wallet=wallet)

        #create agent
        pool_agent = PoolAgent(pool_agent_name, pool)
        state.addAgent(pool_agent)
        self._wallet.resetCachedInfo()

        return pool_agent