Esempio n. 1
0
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
Esempio n. 2
0
    def sell_data_tokens(self, pool_address: str, amount_base: int,
                         min_OCEAN_amount_base: int,
                         from_wallet: Wallet) -> str:
        """
        Sell data tokens into this pool, receive `min_OCEAN_amount_base` of OCEAN tokens.
        If total income >= min_OCEAN_amount_base
        - 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_base`

        :param pool_address: str address of pool contract
        :param amount_base: int number of data tokens to add to this pool in *base*
        :param min_OCEAN_amount_base:
        :param from_wallet:
        :return: str transaction id/hash
        """
        dtoken_address = self.get_token_address(pool_address)
        dt = BToken(dtoken_address)
        dt.approve(pool_address, amount_base, from_wallet=from_wallet)

        pool = BPool(pool_address)
        return pool.swapExactAmountIn(
            tokenIn_address=dtoken_address,  # entering pool
            tokenAmountIn_base=amount_base,  # ""
            tokenOut_address=self.ocean_address,  # leaving pool
            minAmountOut_base=min_OCEAN_amount_base,  # ""
            maxPrice_base=2**255,  # here we limit by max_num_OCEAN, not price
            from_wallet=from_wallet,
        )
Esempio n. 3
0
    def add_liquidity_finalized(self, pool_address: str, bpt_amount_base: int,
                                max_data_token_amount_base: int,
                                max_OCEAN_amount_base: int,
                                from_wallet: Wallet) -> str:
        """
        Add liquidity to a pool that's been finalized.
        Buy bpt_amount_base 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_base: int number of pool shares to receive for adding the liquidity
        :param max_data_token_amount_base: int maximum amount of Data tokens to go into the pool
        :param max_OCEAN_amount_base: 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)
        dt_address = self.get_token_address(pool_address)
        dt = BToken(dt_address)
        dt.approve(pool_address,
                   max_data_token_amount_base,
                   from_wallet=from_wallet)

        OCEAN = BToken(self.ocean_address)
        OCEAN.approve(pool_address,
                      max_OCEAN_amount_base,
                      from_wallet=from_wallet)

        pool = BPool(pool_address)
        return pool.joinPool(
            bpt_amount_base,
            [max_data_token_amount_base, max_OCEAN_amount_base],
            from_wallet=from_wallet)
Esempio n. 4
0
def _createPoolWith2Tokens(
    network: str,
    config: Config,
    web3: Web3,
    T1: BToken,
    T2: BToken,
    wallet: Wallet,
    bal1: Union[Decimal, str, int],
    bal2: Union[Decimal, str, int],
    w1: Union[Decimal, str, int],
    w2: Union[Decimal, str, int],
):
    """Helper function to create a basic pool containing 2 tokens."""
    pool = _deployBPool(web3, config.address_file, network, wallet)

    T1.get_tx_receipt(
        web3, T1.approve(pool.address, to_wei(bal1), from_wallet=wallet))
    T2.get_tx_receipt(
        web3, T2.approve(pool.address, to_wei(bal2), from_wallet=wallet))

    if pool.isBound(T1.address):
        pool.unbind(T1.address, wallet)

    if pool.isBound(T2.address):
        pool.unbind(T2.address, wallet)

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

    return pool
Esempio n. 5
0
def _createPoolWith2Tokens(
    network: str,
    T1: BToken,
    T2: BToken,
    wallet: Wallet,
    bal1: float,
    bal2: float,
    w1: float,
    w2: float,
):
    """Helper function to create a basic pool containing 2 tokens."""
    pool = _deployBPool(network, wallet)

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

    if pool.isBound(T1.address):
        pool.unbind(T1.address, wallet)

    if pool.isBound(T2.address):
        pool.unbind(T2.address, wallet)

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

    return pool
Esempio n. 6
0
    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,
        )
Esempio n. 7
0
    def _add_liquidity(
        self,
        pool_address: str,
        token_address: str,
        amount_base: int,
        from_wallet: Wallet,
    ) -> str:
        assert amount_base >= 0
        if amount_base == 0:
            return ""

        pool = BPool(pool_address)
        token = BToken(token_address)
        assert token.balanceOf(from_wallet.address) >= amount_base, (
            f"Insufficient funds, {amount_base} tokens are required of token address {token_address}, "
            f"but only a balance of {token.balanceOf(from_wallet.address)} is available."
        )

        tx_id = token.approve(pool_address, amount_base, from_wallet)
        r = token.get_tx_receipt(tx_id)
        if not r or r.status != 1:
            return 0

        pool_amount = pool.joinswapExternAmountIn(token_address, amount_base,
                                                  0, from_wallet)
        return pool_amount
Esempio n. 8
0
    def _add_liquidity(self, pool_address: str, token_address: str,
                       amount_base: int, from_wallet: Wallet) -> str:
        assert amount_base >= 0
        if amount_base == 0:
            return ''

        pool = BPool(pool_address)
        token = BToken(token_address)
        assert token.balanceOf(from_wallet.address) >= amount_base, \
            f'Insufficient funds, {amount_base} tokens are required of token address {token_address}, ' \
            f'but only a balance of {token.balanceOf(from_wallet.address)} is available.'

        token.approve(pool_address, amount_base, from_wallet)

        pool_amount = pool.joinswapExternAmountIn(token_address, amount_base,
                                                  0, from_wallet)
        return pool_amount
Esempio n. 9
0
    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,
        )
Esempio n. 10
0
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
Esempio n. 11
0
    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
Esempio n. 12
0
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)