Exemplo n.º 1
0
    def __init__(self):
        super().__init__()
        self.offchain = self.arguments.offchain
        self.order_age = self.arguments.order_age
        self.max_eth_amount = Wad.from_number(self.arguments.max_eth_amount)
        self.min_eth_amount = Wad.from_number(self.arguments.min_eth_amount)
        self.max_sai_amount = Wad.from_number(self.arguments.max_sai_amount)
        self.min_sai_amount = Wad.from_number(self.arguments.min_sai_amount)
        self.eth_reserve = Wad.from_number(self.arguments.eth_reserve)
        self.min_margin = self.arguments.min_margin
        self.avg_margin = self.arguments.avg_margin
        self.max_margin = self.arguments.max_margin

        self.etherdelta_address = Address(
            self.config.get_config()["etherDelta"]["contract"])
        self.etherdelta_api_server = self.config.get_config()["etherDelta"]["apiServer"][1] \
            if "apiServer" in self.config.get_config()["etherDelta"] \
            else None
        self.etherdelta = EtherDelta(web3=self.web3,
                                     address=self.etherdelta_address,
                                     api_server=self.etherdelta_api_server)

        if self.offchain and not self.etherdelta.supports_offchain_orders():
            raise Exception(
                "Off-chain EtherDelta orders not supported on this chain")
Exemplo n.º 2
0
    def test_should_identify_multi_step_opportunities(self, token1, token2,
                                                      token3, token4):
        # given
        conversion1 = Conversion(token1, token2, Ray.from_number(1.02),
                                 Wad.from_number(10000), 'met1')
        conversion2 = Conversion(token2, token3, Ray.from_number(1.03),
                                 Wad.from_number(10000), 'met2')
        conversion3 = Conversion(token3, token4, Ray.from_number(1.05),
                                 Wad.from_number(10000), 'met3')
        conversion4 = Conversion(token4, token1, Ray.from_number(1.07),
                                 Wad.from_number(10000), 'met4')
        conversions = [conversion1, conversion2, conversion3, conversion4]
        base_token = token1

        # when
        opportunities = OpportunityFinder(conversions).find_opportunities(
            base_token, Wad.from_number(100))

        # then
        assert len(opportunities) == 1
        assert len(opportunities[0].steps) == 4
        assert opportunities[0].steps[0].method == "met1"
        assert opportunities[0].steps[1].method == "met2"
        assert opportunities[0].steps[2].method == "met3"
        assert opportunities[0].steps[3].method == "met4"
Exemplo n.º 3
0
 def test_round_inequality(self):
     # should hold for all x, ndigits
     x = Wad.from_number(7654.321)
     ndigits = 1
     round_difference = x - round(x, ndigits)
     round_distance = Wad(abs(round_difference.value))
     assert round_distance <= Wad.from_number(0.5 * 10**(-ndigits))
Exemplo n.º 4
0
    def test_tag(self, sai: SaiDeployment):
        # when
        DSValue(web3=sai.web3, address=sai.tub.pip()).poke_with_int(
            Wad.from_number(250.45).value).transact()

        # then
        assert sai.tub.tag() == Wad.from_number(250.45)
Exemplo n.º 5
0
 def test_multiply_by_ray(self):
     assert Wad.from_number(2) * Ray.from_number(3) == Wad.from_number(6)
     assert Wad.from_number(2) * Ray(3) == Wad(0)
     assert Wad(2) * Ray(499999999999999999999999999) == Wad(0)
     assert Wad(2) * Ray(500000000000000000000000000) == Wad(1)
     assert Wad(2) * Ray(999999999999999999999999999) == Wad(1)
     assert Wad(2) * Ray(1000000000000000000000000000) == Wad(2)
Exemplo n.º 6
0
 def test_divide(self):
     assert Wad.from_number(4) / Wad.from_number(2) == Wad.from_number(2)
     assert Wad(4) / Wad.from_number(2) == Wad(2)
     assert Wad(3) / Wad.from_number(2) == Wad(1)
     assert Wad(39) / Wad.from_number(20) == Wad(1)
     assert Wad(40) / Wad.from_number(20) == Wad(2)
     assert Wad.from_number(0.2) / Wad.from_number(0.1) == Wad.from_number(
         2)
Exemplo n.º 7
0
    def test_cork_and_hat(self, sai: SaiDeployment):
        # given
        assert sai.tub.hat() == Wad(0)

        # when
        sai.tub.cork(Wad.from_number(150000)).transact()

        # then
        assert sai.tub.hat() == Wad.from_number(150000)
Exemplo n.º 8
0
    def test_jump_and_gap(self, sai: SaiDeployment):
        # given
        assert sai.tap.gap() == Wad.from_number(1)

        # when
        sai.tap.jump(Wad.from_number(1.05)).transact()

        # then
        assert sai.tap.gap() == Wad.from_number(1.05)
Exemplo n.º 9
0
def test_should_format_two_different_tokens(token1, token2, some_address):
    # given
    transfer1 = Transfer(token1, some_address, some_address,
                         Wad.from_number(105))
    transfer2 = Transfer(token2, some_address, some_address,
                         Wad.from_number(17))

    # expect
    assert TransferFormatter().format([transfer1, transfer2]) \
        == "105.000000000000000000 TK1 and 17.000000000000000000 TK2"
Exemplo n.º 10
0
def test_nicely_convert_to_string_with_amounts(token1, token2):
    # given
    conversion = Conversion(token1, token2, Ray.from_number(1.01),
                            Wad.from_number(1000), 'met()')
    conversion.source_amount = Wad.from_number(50)
    conversion.target_amount = Wad.from_number(50.5)

    # expect
    assert str(conversion) == "[50.000000000000000000 TK1 -> 50.500000000000000000 TK2 @1.010000000000000000000000000" \
                              " by met() (max=1000.000000000000000000 TK1)]"
Exemplo n.º 11
0
    def test_s2s_and_bid_and_ask(self, sai: SaiDeployment):
        # when
        DSValue(web3=sai.web3, address=sai.tub.pip()).poke_with_int(
            Wad.from_number(500).value).transact()
        sai.tap.jump(Wad.from_number(1.05)).transact()

        # then
        assert sai.tap.bid() == Wad.from_number(475)
        assert sai.tap.s2s() == Wad.from_number(500)
        assert sai.tap.ask() == Wad.from_number(525)
Exemplo n.º 12
0
def test_should_format_net_balances(token1, our_address, some_address):
    # given
    transfer1 = Transfer(token1, our_address, some_address,
                         Wad.from_number(15))
    transfer2 = Transfer(token1, some_address, our_address,
                         Wad.from_number(17))

    # expect
    assert TransferFormatter().format_net([transfer1, transfer2], our_address) \
        == "2.000000000000000000 TK1"
Exemplo n.º 13
0
    def bustable_amount_in_sai(self, tap: Tap):
        #TODO we always try to bust 10 SAI less than what the Tub reports
        #in order to discount the growth of `joy()` that might've have happened since the last drip
        #of course this is not the right solution and it won't even work properly if the last
        #drip happened enough time ago
        bustable_woe = tap.woe() - tap.joy() - Wad.from_number(10)

        # we deduct 0.000001 in order to avoid rounding errors
        bustable_fog = tap.fog() * tap.ask() - Wad.from_number(0.000001)

        return Wad.max(bustable_woe, bustable_fog, Wad.from_number(0))
Exemplo n.º 14
0
def test_should_format_net_balances_excluding_transfers_between_us(
        token1, our_address, some_address):
    # given
    transfer1 = Transfer(token1, some_address, our_address, Wad.from_number(4))
    transfer2 = Transfer(token1, our_address, some_address,
                         Wad.from_number(1.5))
    transfer3 = Transfer(token1, our_address, our_address, Wad.from_number(50))

    # expect
    assert TransferFormatter().format_net([transfer1, transfer2, transfer3], our_address) \
        == "2.500000000000000000 TK1"
Exemplo n.º 15
0
    def test_should_calculate_total_rate(self, token1, token2):
        # given
        step1 = Conversion(token1, token2, Ray.from_number(1.01),
                           Wad.from_number(1000), 'met1')
        step2 = Conversion(token2, token1, Ray.from_number(1.02),
                           Wad.from_number(1000), 'met2')

        # when
        sequence = Sequence([step1, step2])

        # then
        assert sequence.total_rate() == Ray.from_number(1.0302)
Exemplo n.º 16
0
def test_should_format_net_balances_if_multiple_transfers(
        token1, our_address, some_address):
    # given
    transfer1 = Transfer(token1, our_address, some_address,
                         Wad.from_number(15))
    transfer2 = Transfer(token1, some_address, our_address,
                         Wad.from_number(17))
    transfer3 = Transfer(token1, some_address, our_address,
                         Wad.from_number(3.5))

    # expect
    assert TransferFormatter().format_net([transfer1, transfer2, transfer3], our_address) \
        == "5.500000000000000000 TK1"
Exemplo n.º 17
0
 def __init__(self, lpc: Lpc):
     self.lpc = lpc
     rate = Ray(self.lpc.par() / (self.lpc.tag() * self.lpc.gap()))
     #TODO we always leave 0.000001 in the liquidity pool, in case of some rounding errors
     max_entry_ref = Wad.max(
         (ERC20Token(web3=lpc.web3, address=lpc.alt()).balance_of(
             lpc.address) / Wad(rate)) - Wad.from_number(0.000001),
         Wad.from_number(0))
     super().__init__(source_token=self.lpc.ref(),
                      target_token=self.lpc.alt(),
                      rate=rate,
                      max_source_amount=max_entry_ref,
                      method="lpc.take(alt)")
Exemplo n.º 18
0
    def test_joy_and_boom(self, sai: SaiDeployment):
        # given
        sai.tub.join(Wad.from_number(10)).transact()
        sai.tub.cork(Wad.from_number(100000)).transact()
        sai.tub.crop(Ray(1000100000000000000000000000)).transact()
        DSValue(web3=sai.web3, address=sai.tub.pip()).poke_with_int(
            Wad.from_number(250).value).transact()

        # and
        sai.tub.open().transact()
        sai.tub.lock(1, Wad.from_number(4)).transact()
        sai.tub.draw(1, Wad.from_number(1000)).transact()

        # when
        sai.tub.drip().transact()
        sai.tub.warp(3600).transact()
        sai.tub.drip().transact()

        # then
        assert sai.skr.balance_of(sai.our_address) == Wad.from_number(6)
        assert sai.tap.joy() == Wad(433303616582911495481)

        # when
        sai.tap.boom(Wad.from_number(1)).transact()

        # then
        assert sai.skr.balance_of(sai.our_address) == Wad.from_number(5)
        assert sai.tap.joy() == Wad(183303616582911495481)
Exemplo n.º 19
0
def test_should_not_include_zeros_in_net_balances(token1, token2, our_address,
                                                  some_address):
    # given
    transfer1 = Transfer(token1, our_address, some_address,
                         Wad.from_number(15))
    transfer2 = Transfer(token1, some_address, our_address,
                         Wad.from_number(17))
    transfer3 = Transfer(token2, our_address, some_address,
                         Wad.from_number(22.5))
    transfer4 = Transfer(token2, some_address, our_address,
                         Wad.from_number(22.5))

    # expect
    assert TransferFormatter().format_net([transfer1, transfer2, transfer3, transfer4], our_address) \
        == "2.000000000000000000 TK1"
Exemplo n.º 20
0
def test_should_format_net_balances_for_more_than_one_token(
        token1, token2, our_address, some_address):
    # given
    transfer1 = Transfer(token1, our_address, some_address,
                         Wad.from_number(15))
    transfer2 = Transfer(token1, some_address, our_address,
                         Wad.from_number(17))
    transfer3 = Transfer(token2, our_address, some_address,
                         Wad.from_number(2.5))
    transfer4 = Transfer(token2, some_address, our_address,
                         Wad.from_number(100))

    # expect
    assert TransferFormatter().format_net([transfer1, transfer2, transfer3, transfer4], our_address) \
        == "2.000000000000000000 TK1 and 97.500000000000000000 TK2"
Exemplo n.º 21
0
    def test_should_recognize_if_there_are_no_opportunities(
            self, token1, token2, token3):
        # given
        conversion1 = Conversion(token1, token2, Ray.from_number(1.02),
                                 Wad.from_number(10000), 'met1')
        conversion2 = Conversion(token2, token3, Ray.from_number(1.03),
                                 Wad.from_number(10000), 'met2')
        conversions = [conversion1, conversion2]
        base_token = token1

        # when
        opportunities = OpportunityFinder(conversions).find_opportunities(
            base_token, Wad.from_number(100))

        # then
        assert len(opportunities) == 0
Exemplo n.º 22
0
    def test_jar_bid_and_ask(self, sai: SaiDeployment):
        # when
        sai.tub.jar_jump(Wad.from_number(1.05)).transact()

        # then
        assert sai.tub.jar_bid() == Ray.from_number(0.95)
        assert sai.tub.jar_ask() == Ray.from_number(1.05)
Exemplo n.º 23
0
def test_support_iterators(token1, some_address):
    # given
    transfer = Transfer(token1, some_address, some_address,
                        Wad.from_number(11.5))

    # expect
    assert TransferFormatter().format(iter([transfer
                                            ])) == "11.500000000000000000 TK1"
Exemplo n.º 24
0
def test_should_format_single_transfer(token1, some_address):
    # given
    transfer = Transfer(token1, some_address, some_address,
                        Wad.from_number(105))

    # expect
    assert TransferFormatter().format([transfer
                                       ]) == "105.000000000000000000 TK1"
Exemplo n.º 25
0
    def test_should_identify_opportunity(self, token1, token2):
        # given
        conversion1 = Conversion(token1, token2, Ray.from_number(1.02),
                                 Wad.from_number(10000), 'met1')
        conversion2 = Conversion(token2, token1, Ray.from_number(1.03),
                                 Wad.from_number(10000), 'met2')
        conversions = [conversion1, conversion2]
        base_token = token1

        # when
        opportunities = OpportunityFinder(conversions).find_opportunities(
            base_token, Wad.from_number(100))

        # then
        assert len(opportunities) == 1
        assert len(opportunities[0].steps) == 2
        assert opportunities[0].steps[0].method == "met1"
        assert opportunities[0].steps[1].method == "met2"
Exemplo n.º 26
0
def test_nicely_convert_to_string_without_amounts(token1, token2):
    # given
    conversion = Conversion(token1, token2, Ray.from_number(1.01),
                            Wad.from_number(1000), 'met()')

    # expect
    assert str(
        conversion
    ) == "[TK1 -> TK2 @1.010000000000000000000000000 by met() (max=1000.000000000000000000 TK1)]"
Exemplo n.º 27
0
 def __init__(self, tub: Tub):
     self.tub = tub
     super().__init__(
         source_token=self.tub.gem(),
         target_token=self.tub.skr(),
         rate=(Ray.from_number(1) / tub.jar_ask()),
         max_source_amount=Wad.from_number(
             1000000),  #1 mio ETH = infinity ;)
         method="tub.join()")
Exemplo n.º 28
0
 def __init__(self, tub: Tub):
     self.tub = tub
     super().__init__(
         source_token=self.tub.skr(),
         target_token=self.tub.gem(),
         rate=tub.jar_bid(),
         max_source_amount=Wad.from_number(
             1000000),  #1 mio SKR = infinity ;)
         method="tub.exit()")
Exemplo n.º 29
0
 def test_should_calculate_tx_costs(self, token1):
     # expect the tx_costs to be non negative and to increase with the number of steps
     steps = []
     prev_tx_costs = Wad.from_number(0)
     for i in range(10):
         steps.append(Conversion(token1, token1, Ray(0), Wad(0), 'met'))
         opportunity = Sequence(steps)
         tx_costs = opportunity.tx_costs()
         assert (tx_costs > prev_tx_costs)
         prev_tx_costs = tx_costs
Exemplo n.º 30
0
    def test_should_identify_all_opportunities_regardless_whether_they_are_profitable(
            self, token1, token2):
        # given
        conversion1 = Conversion(token1, token2, Ray.from_number(1.1),
                                 Wad.from_number(10000), 'met1')
        conversion2 = Conversion(token2, token1, Ray.from_number(0.6),
                                 Wad.from_number(10000), 'met2')
        conversions = [conversion1, conversion2]
        base_token = token1

        # when
        opportunities = OpportunityFinder(conversions).find_opportunities(
            base_token, Wad.from_number(100))

        # then
        assert len(opportunities) == 1
        assert len(opportunities[0].steps) == 2
        assert opportunities[0].steps[0].method == "met1"
        assert opportunities[0].steps[1].method == "met2"