コード例 #1
0
ファイル: test_sai.py プロジェクト: rthomas6/pymaker
 def test_comparison(self, deployment: Deployment):
     # expect
     assert deployment.vox == deployment.vox
     assert deployment.vox == Vox(web3=deployment.web3,
                                  address=deployment.vox.address)
     assert deployment.vox != Vox(web3=deployment.web3,
                                  address=deployment.top.address)
コード例 #2
0
    def __init__(self, args: list, **kwargs):
        parser = argparse.ArgumentParser(prog='bite-keeper')
        parser.add_argument("--rpc-host",
                            help="JSON-RPC host (default: `localhost')",
                            default="localhost",
                            type=str)
        parser.add_argument("--rpc-port",
                            help="JSON-RPC port (default: `8545')",
                            default=8545,
                            type=int)
        parser.add_argument("--rpc-timeout",
                            help="JSON-RPC timeout (in seconds, default: 10)",
                            default=10,
                            type=int)
        parser.add_argument(
            "--eth-from",
            help="Ethereum account from which to send transactions",
            required=True,
            type=str)
        parser.add_argument(
            "--eth-key",
            type=str,
            nargs='*',
            help=
            "Ethereum private key(s) to use (e.g. 'key_file=/path/to/keystore.json,pass_file=/path/to/passphrase.txt')"
        )
        parser.add_argument("--tub-address",
                            help="Ethereum address of the Tub contract",
                            required=True,
                            type=str)
        parser.add_argument("--debug",
                            help="Enable debug output",
                            dest='debug',
                            action='store_true')
        self.arguments = parser.parse_args(args)

        self.web3 = kwargs['web3'] if 'web3' in kwargs else Web3(
            HTTPProvider(
                endpoint_uri=
                f"https://{self.arguments.rpc_host}:{self.arguments.rpc_port}",
                request_kwargs={"timeout": self.arguments.rpc_timeout}))
        self.web3.eth.defaultAccount = self.arguments.eth_from
        self.our_address = Address(self.arguments.eth_from)
        register_keys(self.web3, self.arguments.eth_key)
        self.tub = Tub(web3=self.web3,
                       address=Address(self.arguments.tub_address))
        self.vox = Vox(web3=self.web3, address=self.tub.vox())

        logging.basicConfig(
            format='%(asctime)-15s %(levelname)-8s %(message)s',
            level=(logging.DEBUG if self.arguments.debug else logging.INFO))
コード例 #3
0
    def __init__(self, args: list, **kwargs):
        parser = argparse.ArgumentParser(prog='etherdelta-market-maker-keeper')

        parser.add_argument("--rpc-host",
                            type=str,
                            default="localhost",
                            help="JSON-RPC host (default: `localhost')")

        parser.add_argument("--rpc-port",
                            type=int,
                            default=8545,
                            help="JSON-RPC port (default: `8545')")

        parser.add_argument("--rpc-timeout",
                            type=int,
                            default=10,
                            help="JSON-RPC timeout (in seconds, default: 10)")

        parser.add_argument(
            "--eth-from",
            type=str,
            required=True,
            help="Ethereum account from which to send transactions")

        parser.add_argument("--tub-address",
                            type=str,
                            required=True,
                            help="Ethereum address of the Tub contract")

        parser.add_argument("--etherdelta-address",
                            type=str,
                            required=True,
                            help="Ethereum address of the EtherDelta contract")

        parser.add_argument(
            "--etherdelta-socket",
            type=str,
            required=True,
            help="Ethereum address of the EtherDelta API socket")

        parser.add_argument(
            "--etherdelta-number-of-attempts",
            type=int,
            default=3,
            help=
            "Number of attempts of running the tool to talk to the EtherDelta API socket"
        )

        parser.add_argument(
            "--etherdelta-retry-interval",
            type=int,
            default=10,
            help=
            "Retry interval for sending orders over the EtherDelta API socket")

        parser.add_argument(
            "--etherdelta-timeout",
            type=int,
            default=120,
            help="Timeout for sending orders over the EtherDelta API socket")

        parser.add_argument("--config",
                            type=str,
                            required=True,
                            help="Buy/sell bands configuration file")

        parser.add_argument(
            "--price-feed",
            type=str,
            help=
            "Source of price feed. Tub price feed will be used if not specified"
        )

        parser.add_argument(
            "--price-feed-expiry",
            type=int,
            default=120,
            help="Maximum age of non-Tub price feed (in seconds, default: 120)"
        )

        parser.add_argument("--order-age",
                            type=int,
                            required=True,
                            help="Age of created orders (in blocks)")

        parser.add_argument(
            "--order-expiry-threshold",
            type=int,
            default=0,
            help=
            "Remaining order age (in blocks) at which order is considered already expired, which"
            " means the keeper will send a new replacement order slightly ahead"
        )

        parser.add_argument(
            "--order-no-cancel-threshold",
            type=int,
            default=0,
            help=
            "Remaining order age (in blocks) below which keeper does not try to cancel orders,"
            " assuming that they will probably expire before the cancel transaction gets mined"
        )

        parser.add_argument(
            "--eth-reserve",
            type=float,
            required=True,
            help=
            "Amount of ETH which will never be deposited so the keeper can cover gas"
        )

        parser.add_argument(
            "--min-eth-balance",
            type=float,
            default=0,
            help=
            "Minimum ETH balance below which keeper with either terminate or not start at all"
        )

        parser.add_argument(
            "--min-eth-deposit",
            type=float,
            required=True,
            help=
            "Minimum amount of ETH that can be deposited in one transaction")

        parser.add_argument(
            "--min-sai-deposit",
            type=float,
            required=True,
            help=
            "Minimum amount of SAI that can be deposited in one transaction")

        parser.add_argument(
            '--cancel-on-shutdown',
            dest='cancel_on_shutdown',
            action='store_true',
            help=
            "Whether should cancel all open orders on EtherDelta on keeper shutdown"
        )

        parser.add_argument(
            '--withdraw-on-shutdown',
            dest='withdraw_on_shutdown',
            action='store_true',
            help=
            "Whether should withdraw all tokens from EtherDelta on keeper shutdown"
        )

        parser.add_argument("--gas-price",
                            type=int,
                            default=0,
                            help="Gas price (in Wei)")

        parser.add_argument(
            "--gas-price-increase",
            type=int,
            help="Gas price increase (in Wei) if no confirmation within"
            " `--gas-price-increase-every` seconds")

        parser.add_argument(
            "--gas-price-increase-every",
            type=int,
            default=120,
            help="Gas price increase frequency (in seconds, default: 120)")

        parser.add_argument("--gas-price-max",
                            type=int,
                            help="Maximum gas price (in Wei)")

        parser.add_argument("--gas-price-file",
                            type=str,
                            help="Gas price configuration file")

        parser.add_argument(
            "--smart-gas-price",
            dest='smart_gas_price',
            action='store_true',
            help=
            "Use smart gas pricing strategy, based on the ethgasstation.info feed"
        )

        parser.add_argument("--debug",
                            dest='debug',
                            action='store_true',
                            help="Enable debug output")

        parser.set_defaults(cancel_on_shutdown=False,
                            withdraw_on_shutdown=False)

        self.arguments = parser.parse_args(args)

        self.web3 = kwargs['web3'] if 'web3' in kwargs else Web3(
            HTTPProvider(
                endpoint_uri=
                f"http://{self.arguments.rpc_host}:{self.arguments.rpc_port}",
                request_kwargs={"timeout": self.arguments.rpc_timeout}))
        self.web3.eth.defaultAccount = self.arguments.eth_from
        self.our_address = Address(self.arguments.eth_from)
        self.tub = Tub(web3=self.web3,
                       address=Address(self.arguments.tub_address))
        self.vox = Vox(web3=self.web3, address=self.tub.vox())
        self.sai = ERC20Token(web3=self.web3, address=self.tub.sai())
        self.gem = ERC20Token(web3=self.web3, address=self.tub.gem())

        logging.basicConfig(
            format='%(asctime)-15s %(levelname)-8s %(message)s',
            level=(logging.DEBUG if self.arguments.debug else logging.INFO))
        logging.getLogger('urllib3.connectionpool').setLevel(logging.INFO)
        logging.getLogger('requests.packages.urllib3.connectionpool').setLevel(
            logging.INFO)

        self.bands_config = ReloadableConfig(self.arguments.config)
        self.eth_reserve = Wad.from_number(self.arguments.eth_reserve)
        self.min_eth_balance = Wad.from_number(self.arguments.min_eth_balance)
        self.min_eth_deposit = Wad.from_number(self.arguments.min_eth_deposit)
        self.min_sai_deposit = Wad.from_number(self.arguments.min_sai_deposit)
        self.gas_price = GasPriceFactory().create_gas_price(self.arguments)
        self.price_feed = PriceFeedFactory().create_price_feed(
            self.arguments.price_feed, self.arguments.price_feed_expiry,
            self.tub, self.vox)

        if self.eth_reserve <= self.min_eth_balance:
            raise Exception(
                "--eth-reserve must be higher than --min-eth-balance")

        assert (self.arguments.order_expiry_threshold >= 0)
        assert (self.arguments.order_no_cancel_threshold >=
                self.arguments.order_expiry_threshold)

        self.etherdelta = EtherDelta(web3=self.web3,
                                     address=Address(
                                         self.arguments.etherdelta_address))
        self.etherdelta_api = EtherDeltaApi(
            client_tool_directory="lib/pymaker/utils/etherdelta-client",
            client_tool_command="node main.js",
            api_server=self.arguments.etherdelta_socket,
            number_of_attempts=self.arguments.etherdelta_number_of_attempts,
            retry_interval=self.arguments.etherdelta_retry_interval,
            timeout=self.arguments.etherdelta_timeout)

        self.our_orders = list()
コード例 #4
0
    def __init__(self):
        web3 = Web3(HTTPProvider("http://localhost:8555"))
        web3.eth.defaultAccount = web3.eth.accounts[0]
        our_address = Address(web3.eth.defaultAccount)
        sai = DSToken.deploy(web3, 'DAI')
        sin = DSToken.deploy(web3, 'SIN')
        skr = DSToken.deploy(web3, 'PETH')
        gem = DSToken.deploy(web3, 'WETH')
        gov = DSToken.deploy(web3, 'MKR')
        pip = DSValue.deploy(web3)
        pep = DSValue.deploy(web3)
        pit = DSVault.deploy(web3)

        vox = Vox.deploy(web3, per=Ray.from_number(1))
        tub = Tub.deploy(web3,
                         sai=sai.address,
                         sin=sin.address,
                         skr=skr.address,
                         gem=gem.address,
                         gov=gov.address,
                         pip=pip.address,
                         pep=pep.address,
                         vox=vox.address,
                         pit=pit.address)
        tap = Tap.deploy(web3, tub.address)
        top = Top.deploy(web3, tub.address, tap.address)

        tub._contract.functions.turn(tap.address.address).transact()

        etherdelta = EtherDelta.deploy(
            web3,
            admin=Address('0x1111100000999998888877777666665555544444'),
            fee_account=Address('0x8888877777666665555544444111110000099999'),
            account_levels_addr=Address(
                '0x0000000000000000000000000000000000000000'),
            fee_make=Wad.from_number(0.01),
            fee_take=Wad.from_number(0.02),
            fee_rebate=Wad.from_number(0.03))

        # set permissions
        dad = DSGuard.deploy(web3)
        dad.permit(DSGuard.ANY, DSGuard.ANY, DSGuard.ANY).transact()
        tub.set_authority(dad.address).transact()
        for auth in [sai, sin, skr, gem, gov, pit, tap, top]:
            auth.set_authority(dad.address).transact()

        # approve
        tub.approve(directly())
        tap.approve(directly())

        # mint some GEMs
        gem.mint(Wad.from_number(1000000)).transact()

        self.snapshot_id = web3.manager.request_blocking("evm_snapshot", [])

        self.web3 = web3
        self.our_address = our_address
        self.sai = sai
        self.sin = sin
        self.skr = skr
        self.gem = gem
        self.gov = gov
        self.vox = vox
        self.tub = tub
        self.tap = tap
        self.top = top
        self.etherdelta = etherdelta
コード例 #5
0
ファイル: deployment.py プロジェクト: ctebbe/pymaker
    def __init__(self):
        web3 = Web3(EthereumTesterProvider())
        web3.eth.defaultAccount = web3.eth.accounts[0]
        our_address = Address(web3.eth.defaultAccount)
        sai = DSToken.deploy(web3, 'DAI')
        sin = DSToken.deploy(web3, 'SIN')
        skr = DSToken.deploy(web3, 'PETH')
        gem = DSToken.deploy(web3, 'WETH')
        gov = DSToken.deploy(web3, 'MKR')
        pip = DSValue.deploy(web3)
        pep = DSValue.deploy(web3)
        pit = DSVault.deploy(web3)

        vox = Vox.deploy(web3, per=Ray.from_number(1))
        tub = Tub.deploy(web3, sai=sai.address, sin=sin.address, skr=skr.address, gem=gem.address, gov=gov.address,
                         pip=pip.address, pep=pep.address, vox=vox.address, pit=pit.address)
        tap = Tap.deploy(web3, tub.address)
        top = Top.deploy(web3, tub.address, tap.address)

        tub._contract.transact().turn(tap.address.address)

        otc = MatchingMarket.deploy(web3, 2600000000)
        etherdelta = EtherDelta.deploy(web3,
                                       admin=Address('0x1111100000999998888877777666665555544444'),
                                       fee_account=Address('0x8888877777666665555544444111110000099999'),
                                       account_levels_addr=Address('0x0000000000000000000000000000000000000000'),
                                       fee_make=Wad.from_number(0.01),
                                       fee_take=Wad.from_number(0.02),
                                       fee_rebate=Wad.from_number(0.03))

        # set permissions
        dad = DSGuard.deploy(web3)
        dad.permit(DSGuard.ANY, DSGuard.ANY, DSGuard.ANY).transact()
        tub.set_authority(dad.address).transact()
        for auth in [sai, sin, skr, gem, gov, pit, tap, top]:
            auth.set_authority(dad.address).transact()

        # whitelist pairs
        otc.add_token_pair_whitelist(sai.address, gem.address).transact()

        # approve
        tub.approve(directly())
        tap.approve(directly())

        # mint some GEMs
        gem.mint(Wad.from_number(1000000)).transact()

        web3.providers[0].rpc_methods.evm_snapshot()

        self.web3 = web3
        self.our_address = our_address
        self.sai = sai
        self.sin = sin
        self.skr = skr
        self.gem = gem
        self.gov = gov
        self.vox = vox
        self.tub = tub
        self.tap = tap
        self.top = top
        self.otc = otc
        self.etherdelta = etherdelta
コード例 #6
0
ファイル: test_sai.py プロジェクト: changwu-tw/pymaker
 def test_fail_when_no_contract_under_that_address(self, deployment: Deployment):
     # expect
     with pytest.raises(Exception):
         Vox(web3=deployment.web3, address=Address('0xdeadadd1e5500000000000000000000000000000'))
    def __init__(self, args: list, **kwargs):
        parser = argparse.ArgumentParser(prog='radarrelay-market-maker-keeper')

        parser.add_argument("--rpc-host",
                            type=str,
                            default="localhost",
                            help="JSON-RPC host (default: `localhost')")

        parser.add_argument("--rpc-port",
                            type=int,
                            default=8545,
                            help="JSON-RPC port (default: `8545')")

        parser.add_argument("--rpc-timeout",
                            type=int,
                            default=10,
                            help="JSON-RPC timeout (in seconds, default: 10)")

        parser.add_argument(
            "--eth-from",
            type=str,
            required=True,
            help="Ethereum account from which to send transactions")

        parser.add_argument("--tub-address",
                            type=str,
                            required=True,
                            help="Ethereum address of the Tub contract")

        parser.add_argument(
            "--exchange-address",
            type=str,
            required=True,
            help="Ethereum address of the 0x Exchange contract")

        parser.add_argument("--weth-address",
                            type=str,
                            required=True,
                            help="Ethereum address of the WETH token")

        parser.add_argument("--relayer-api-server",
                            type=str,
                            required=True,
                            help="Address of the 0x Relayer API")

        parser.add_argument("--config",
                            type=str,
                            required=True,
                            help="Buy/sell bands configuration file")

        parser.add_argument(
            "--price-feed",
            type=str,
            help=
            "Source of price feed. Tub price feed will be used if not specified"
        )

        parser.add_argument(
            "--price-feed-expiry",
            type=int,
            default=120,
            help="Maximum age of non-Tub price feed (in seconds, default: 120)"
        )

        parser.add_argument(
            "--order-expiry",
            type=int,
            required=True,
            help="Expiration time of created orders (in seconds)")

        parser.add_argument(
            "--order-expiry-threshold",
            type=int,
            default=0,
            help=
            "Order expiration time at which order is considered already expired (in seconds)"
        )

        parser.add_argument(
            "--min-eth-balance",
            type=float,
            default=0,
            help=
            "Minimum ETH balance below which keeper with either terminate or not start at all"
        )

        parser.add_argument(
            '--cancel-on-shutdown',
            dest='cancel_on_shutdown',
            action='store_true',
            help=
            "Whether should cancel all open orders on RadarRelay on keeper shutdown"
        )

        parser.add_argument("--gas-price",
                            type=int,
                            default=0,
                            help="Gas price (in Wei)")

        parser.add_argument(
            "--gas-price-increase",
            type=int,
            help="Gas price increase (in Wei) if no confirmation within"
            " `--gas-price-increase-every` seconds")

        parser.add_argument(
            "--gas-price-increase-every",
            type=int,
            default=120,
            help="Gas price increase frequency (in seconds, default: 120)")

        parser.add_argument("--gas-price-max",
                            type=int,
                            help="Maximum gas price (in Wei)")

        parser.add_argument("--gas-price-file",
                            type=str,
                            help="Gas price configuration file")

        parser.add_argument(
            "--smart-gas-price",
            dest='smart_gas_price',
            action='store_true',
            help=
            "Use smart gas pricing strategy, based on the ethgasstation.info feed"
        )

        parser.add_argument("--debug",
                            dest='debug',
                            action='store_true',
                            help="Enable debug output")

        self.arguments = parser.parse_args(args)

        self.web3 = kwargs['web3'] if 'web3' in kwargs else Web3(
            HTTPProvider(
                endpoint_uri=
                f"http://{self.arguments.rpc_host}:{self.arguments.rpc_port}",
                request_kwargs={"timeout": self.arguments.rpc_timeout}))
        self.web3.eth.defaultAccount = self.arguments.eth_from
        self.our_address = Address(self.arguments.eth_from)
        self.tub = Tub(web3=self.web3,
                       address=Address(self.arguments.tub_address))
        self.vox = Vox(web3=self.web3, address=self.tub.vox())
        self.sai = ERC20Token(web3=self.web3, address=self.tub.sai())
        self.ether_token = ERC20Token(web3=self.web3,
                                      address=Address(
                                          self.arguments.weth_address))

        logging.basicConfig(
            format='%(asctime)-15s %(levelname)-8s %(message)s',
            level=(logging.DEBUG if self.arguments.debug else logging.INFO))
        logging.getLogger('urllib3.connectionpool').setLevel(logging.INFO)
        logging.getLogger('requests.packages.urllib3.connectionpool').setLevel(
            logging.INFO)

        self.min_eth_balance = Wad.from_number(self.arguments.min_eth_balance)
        self.bands_config = ReloadableConfig(self.arguments.config)
        self.gas_price = GasPriceFactory().create_gas_price(self.arguments)
        self.price_feed = PriceFeedFactory().create_price_feed(
            self.arguments.price_feed, self.arguments.price_feed_expiry,
            self.tub, self.vox)

        self.radar_relay = ZrxExchange(web3=self.web3,
                                       address=Address(
                                           self.arguments.exchange_address))
        self.radar_relay_api = ZrxRelayerApi(
            exchange=self.radar_relay,
            api_server=self.arguments.relayer_api_server)
コード例 #8
0
    def __init__(self, args: list, **kwargs):
        parser = argparse.ArgumentParser(prog='oasis-market-maker-keeper')

        parser.add_argument("--rpc-host",
                            type=str,
                            default="localhost",
                            help="JSON-RPC host (default: `localhost')")

        parser.add_argument("--rpc-port",
                            type=int,
                            default=8545,
                            help="JSON-RPC port (default: `8545')")

        parser.add_argument("--rpc-timeout",
                            type=int,
                            default=10,
                            help="JSON-RPC timeout (in seconds, default: 10)")

        parser.add_argument(
            "--eth-from",
            type=str,
            required=True,
            help="Ethereum account from which to send transactions")

        parser.add_argument("--tub-address",
                            type=str,
                            required=True,
                            help="Ethereum address of the Tub contract")

        parser.add_argument("--oasis-address",
                            type=str,
                            required=True,
                            help="Ethereum address of the OasisDEX contract")

        parser.add_argument("--config",
                            type=str,
                            required=True,
                            help="Buy/sell bands configuration file")

        parser.add_argument(
            "--price-feed",
            type=str,
            help=
            "Source of price feed. Tub price feed will be used if not specified"
        )

        parser.add_argument(
            "--price-feed-expiry",
            type=int,
            default=120,
            help="Maximum age of non-Tub price feed (in seconds, default: 120)"
        )

        parser.add_argument(
            "--round-places",
            type=int,
            default=2,
            help="Number of decimal places to round order prices to (default=2)"
        )

        parser.add_argument(
            "--min-eth-balance",
            type=float,
            default=0,
            help=
            "Minimum ETH balance below which keeper with either terminate or not start at all"
        )

        parser.add_argument("--gas-price",
                            type=int,
                            default=0,
                            help="Gas price (in Wei)")

        parser.add_argument(
            "--gas-price-increase",
            type=int,
            help="Gas price increase (in Wei) if no confirmation within"
            " `--gas-price-increase-every` seconds")

        parser.add_argument(
            "--gas-price-increase-every",
            type=int,
            default=120,
            help="Gas price increase frequency (in seconds, default: 120)")

        parser.add_argument("--gas-price-max",
                            type=int,
                            help="Maximum gas price (in Wei)")

        parser.add_argument("--gas-price-file",
                            type=str,
                            help="Gas price configuration file")

        parser.add_argument(
            "--smart-gas-price",
            dest='smart_gas_price',
            action='store_true',
            help=
            "Use smart gas pricing strategy, based on the ethgasstation.info feed"
        )

        parser.add_argument("--debug",
                            dest='debug',
                            action='store_true',
                            help="Enable debug output")

        self.arguments = parser.parse_args(args)

        self.web3 = kwargs['web3'] if 'web3' in kwargs else Web3(
            HTTPProvider(
                endpoint_uri=
                f"http://{self.arguments.rpc_host}:{self.arguments.rpc_port}",
                request_kwargs={"timeout": self.arguments.rpc_timeout}))
        self.web3.eth.defaultAccount = self.arguments.eth_from
        self.our_address = Address(self.arguments.eth_from)
        self.otc = MatchingMarket(web3=self.web3,
                                  address=Address(
                                      self.arguments.oasis_address))
        self.tub = Tub(web3=self.web3,
                       address=Address(self.arguments.tub_address))
        self.vox = Vox(web3=self.web3, address=self.tub.vox())
        self.sai = ERC20Token(web3=self.web3, address=self.tub.sai())
        self.gem = ERC20Token(web3=self.web3, address=self.tub.gem())

        logging.basicConfig(
            format='%(asctime)-15s %(levelname)-8s %(message)s',
            level=(logging.DEBUG if self.arguments.debug else logging.INFO))
        logging.getLogger('urllib3.connectionpool').setLevel(logging.INFO)
        logging.getLogger('requests.packages.urllib3.connectionpool').setLevel(
            logging.INFO)

        self.min_eth_balance = Wad.from_number(self.arguments.min_eth_balance)
        self.bands_config = ReloadableConfig(self.arguments.config)
        self.gas_price = GasPriceFactory().create_gas_price(self.arguments)
        self.price_feed = PriceFeedFactory().create_price_feed(
            self.arguments.price_feed, self.arguments.price_feed_expiry,
            self.tub, self.vox)
コード例 #9
0
    def __init__(self, args: list, **kwargs):
        parser = argparse.ArgumentParser(prog='bite-keeper')
        parser.add_argument(
            "--rpc-host",
            type=str,
            default="http://localhost:8545",
            help="JSON-RPC endpoint URI with port " +
                "(default: `http://localhost:8545')"
        )
        parser.add_argument(
            "--rpc-timeout",
            help="JSON-RPC timeout (in seconds, default: 10)",
            default=10,
            type=int
        )
        parser.add_argument(
            "--eth-from",
            help="Ethereum account from which to send transactions",
            required=True,
            type=str
        )
        parser.add_argument(
            "--eth-key",
            type=str,
            nargs='*',
            help="Ethereum private key(s) to use " +
                "(e.g. 'key_file=/path/to/keystore.json," +
                "pass_file=/path/to/passphrase.txt')"
        )
        parser.add_argument(
            "--tub-address",
            help="Ethereum address of the Tub contract",
            required=True,
            type=str
        )
        parser.add_argument(
            "--graphql-url",
            type=str,
            default="https://sai-mainnet.makerfoundation.com/v1",
            help="GraphQL URL " +
                "(default: `https://sai-mainnet.makerfoundation.com/v1')"
        )
        parser.add_argument(
            "--bitecdps-address",
            help="Ethereum address of the BiteCdps contract",
            type=str
        )
        parser.add_argument(
            "--top",
            help="Quickly process N top bites, (default: 500)",
            default=500,
            type=int
        )
        parser.add_argument(
            "--chunks",
            help="Process top bites in chunks of N, (default: 100)",
            default=100,
            type=int
        )
        parser.add_argument(
            "--debug",
            help="Enable debug output",
            dest='debug',
            action='store_true'
        )
        self.arguments = parser.parse_args(args)

        # Configure connection to the chain
        provider = HTTPProvider(
            endpoint_uri=self.arguments.rpc_host,
            request_kwargs={'timeout': self.arguments.rpc_timeout}
        )
        self.web3: Web3 = kwargs['web3'] if 'web3' in kwargs else Web3(provider)
        self.web3.eth.defaultAccount = self.arguments.eth_from
        self.our_address = Address(self.arguments.eth_from)
        register_keys(self.web3, self.arguments.eth_key)
        self.tub = Tub(
            web3=self.web3, address=Address(self.arguments.tub_address)
        )
        self.vox = Vox(web3=self.web3, address=self.tub.vox())
        self.top = self.arguments.top
        self.chunks = self.arguments.chunks

        if self.arguments.bitecdps_address and self.arguments.graphql_url:
            self.use_bitecdps = True
            self.bitecdps = BiteCdps(
                web3=self.web3, address=Address(self.arguments.bitecdps_address)
            )
            self.graphql_url = self.arguments.graphql_url
        else:
            self.use_bitecdps = False

        logging.basicConfig(
            format='%(asctime)-15s %(levelname)-8s %(message)s',
            level=(logging.DEBUG if self.arguments.debug else logging.INFO)
        )
コード例 #10
0
class BiteKeeper:
    """Keeper to bite undercollateralized cups."""

    logger = logging.getLogger('bite-all-keeper')

    def __init__(self, args: list, **kwargs):
        parser = argparse.ArgumentParser(prog='bite-keeper')
        parser.add_argument(
            "--rpc-host",
            type=str,
            default="http://localhost:8545",
            help="JSON-RPC endpoint URI with port " +
                "(default: `http://localhost:8545')"
        )
        parser.add_argument(
            "--rpc-timeout",
            help="JSON-RPC timeout (in seconds, default: 10)",
            default=10,
            type=int
        )
        parser.add_argument(
            "--eth-from",
            help="Ethereum account from which to send transactions",
            required=True,
            type=str
        )
        parser.add_argument(
            "--eth-key",
            type=str,
            nargs='*',
            help="Ethereum private key(s) to use " +
                "(e.g. 'key_file=/path/to/keystore.json," +
                "pass_file=/path/to/passphrase.txt')"
        )
        parser.add_argument(
            "--tub-address",
            help="Ethereum address of the Tub contract",
            required=True,
            type=str
        )
        parser.add_argument(
            "--graphql-url",
            type=str,
            default="https://sai-mainnet.makerfoundation.com/v1",
            help="GraphQL URL " +
                "(default: `https://sai-mainnet.makerfoundation.com/v1')"
        )
        parser.add_argument(
            "--bitecdps-address",
            help="Ethereum address of the BiteCdps contract",
            type=str
        )
        parser.add_argument(
            "--top",
            help="Quickly process N top bites, (default: 500)",
            default=500,
            type=int
        )
        parser.add_argument(
            "--chunks",
            help="Process top bites in chunks of N, (default: 100)",
            default=100,
            type=int
        )
        parser.add_argument(
            "--debug",
            help="Enable debug output",
            dest='debug',
            action='store_true'
        )
        self.arguments = parser.parse_args(args)

        # Configure connection to the chain
        provider = HTTPProvider(
            endpoint_uri=self.arguments.rpc_host,
            request_kwargs={'timeout': self.arguments.rpc_timeout}
        )
        self.web3: Web3 = kwargs['web3'] if 'web3' in kwargs else Web3(provider)
        self.web3.eth.defaultAccount = self.arguments.eth_from
        self.our_address = Address(self.arguments.eth_from)
        register_keys(self.web3, self.arguments.eth_key)
        self.tub = Tub(
            web3=self.web3, address=Address(self.arguments.tub_address)
        )
        self.vox = Vox(web3=self.web3, address=self.tub.vox())
        self.top = self.arguments.top
        self.chunks = self.arguments.chunks

        if self.arguments.bitecdps_address and self.arguments.graphql_url:
            self.use_bitecdps = True
            self.bitecdps = BiteCdps(
                web3=self.web3, address=Address(self.arguments.bitecdps_address)
            )
            self.graphql_url = self.arguments.graphql_url
        else:
            self.use_bitecdps = False

        logging.basicConfig(
            format='%(asctime)-15s %(levelname)-8s %(message)s',
            level=(logging.DEBUG if self.arguments.debug else logging.INFO)
        )

    def main(self):
        with Lifecycle(self.web3) as lifecycle:
            self.lifecycle = lifecycle
            lifecycle.on_block(self.check_all_cups)

    def check_all_cups(self):
        if self.tub._contract.functions.off().call():
            self.logger.info('Single Collateral Dai has been Caged')
            self.logger.info('Starting to bite all cups in the tub contract')

            # Read some things that wont change across cups
            axe = self.tub.axe() # Liquidation penalty [RAY] Fixed at 1 RAY at cage
            par = self.vox.par() # Dai Targe Price     [RAY] Typically 1 RAY
            tag = self.tub.tag() # Ref/Oracle price    [RAY] Fixed at shutdown

            if self.use_bitecdps:
                self.call_bitecdps()
            else:
                for cup_id in range(self.tub.cupi()):
                    self.check_cup(cup_id+1, axe, par, tag)

            self.lifecycle.terminate()
        else:
            self.logger.info('Single Collateral Dai live')

    def check_cup(self, cup_id, axe: Ray, par: Ray, tag: Ray):
        cup = self.tub.cups(cup_id)
        rue = Ray(self.tub.tab(cup_id)) # Amount of Debt[RAY]

        # Amount owed in SKR, including liquidation penalty
        # var owe = rdiv(rmul(rmul(rue, axe), vox.par()), tag());
        owe = ((rue * axe) * par) / tag

        # Bite cups with owe over a threshold that haven't been bitten before
        if owe > Ray.from_number(0) and cup.art != Wad.from_number(0):
            self.logger.info(
                f'Bite cup {cup_id} with owe of {owe} and ink of {cup.ink}'
            )
            self.tub.bite(cup_id).transact(gas_price=self.gas_price())

    def call_bitecdps(self):
        self.logger.info(f'Will bite top {self.top} CDPs')
        # cdps = [i+1 for i in range(self.tub.cupi())]
        cdps = self.get_cdps()
        self.logger.info(f'found {len(cdps)} CDPs')
        for i in range(0, len(cdps), self.chunks):
            chunk = cdps[i:i+self.chunks]
            self.logger.info(f'BiteCdps.bite({chunk})')
            self.bitecdps.bite(chunk).transact(gas_price=self.gas_price())

    def get_cdps(self):
        client = GraphQLClient(self.graphql_url)
        result = client.execute(QUERY.replace('XXX', f'{self.top}'))
        data = json.loads(result)
        cdps = []
        for cdp in data["data"]["allCups"]["nodes"]:
            cdps.append(cdp["id"])
        return cdps

    def gas_price(self):
        """ IncreasingGasPrice """
        GWEI = 1000000000

        return IncreasingGasPrice(initial_price=5*GWEI,
                                  increase_by=10*GWEI,
                                  every_secs=60,
                                  max_price=300*GWEI)
コード例 #11
0
class BiteKeeper:
    """Keeper to bite undercollateralized cups."""

    logger = logging.getLogger('bite-all-keeper')

    def __init__(self, args: list, **kwargs):
        parser = argparse.ArgumentParser(prog='bite-keeper')
        parser.add_argument("--rpc-host",
                            help="JSON-RPC host (default: `localhost')",
                            default="localhost",
                            type=str)
        parser.add_argument("--rpc-port",
                            help="JSON-RPC port (default: `8545')",
                            default=8545,
                            type=int)
        parser.add_argument("--rpc-timeout",
                            help="JSON-RPC timeout (in seconds, default: 10)",
                            default=10,
                            type=int)
        parser.add_argument(
            "--eth-from",
            help="Ethereum account from which to send transactions",
            required=True,
            type=str)
        parser.add_argument(
            "--eth-key",
            type=str,
            nargs='*',
            help=
            "Ethereum private key(s) to use (e.g. 'key_file=/path/to/keystore.json,pass_file=/path/to/passphrase.txt')"
        )
        parser.add_argument("--tub-address",
                            help="Ethereum address of the Tub contract",
                            required=True,
                            type=str)
        parser.add_argument("--debug",
                            help="Enable debug output",
                            dest='debug',
                            action='store_true')
        self.arguments = parser.parse_args(args)

        self.web3 = kwargs['web3'] if 'web3' in kwargs else Web3(
            HTTPProvider(
                endpoint_uri=
                f"https://{self.arguments.rpc_host}:{self.arguments.rpc_port}",
                request_kwargs={"timeout": self.arguments.rpc_timeout}))
        self.web3.eth.defaultAccount = self.arguments.eth_from
        self.our_address = Address(self.arguments.eth_from)
        register_keys(self.web3, self.arguments.eth_key)
        self.tub = Tub(web3=self.web3,
                       address=Address(self.arguments.tub_address))
        self.vox = Vox(web3=self.web3, address=self.tub.vox())

        logging.basicConfig(
            format='%(asctime)-15s %(levelname)-8s %(message)s',
            level=(logging.DEBUG if self.arguments.debug else logging.INFO))

    def main(self):
        with Lifecycle(self.web3) as lifecycle:
            lifecycle.on_block(self.check_all_cups)

    def check_all_cups(self):
        if self.tub._contract.functions.off().call():
            self.logger.info('Single Collateral Dai has been Caged')
            self.logger.info('Starting to bite all cups in the tub contract')

            # Read some things that wont change across cups
            axe = self.tub.axe(
            )  # Liquidation penalty [RAY] Fixed at 1 RAY at cage
            par = self.vox.par()  # Dai Targe Price     [RAY] Typically 1 RAY
            tag = self.tub.tag()  # Ref/Oracle price    [RAY] Fixed at shutdown

            for cup_id in range(self.tub.cupi()):
                self.check_cup(cup_id + 1, axe, par, tag)
        else:
            self.logger.info('Single Collateral Dai live')

    def check_cup(self, cup_id, axe: Ray, par: Ray, tag: Ray):
        cup = self.tub.cups(cup_id)
        rue = Ray(self.tub.tab(cup_id))  # Amount of Debt[RAY]

        # Amount owed in SKR, including liquidation penalty
        # var owe = rdiv(rmul(rmul(rue, axe), vox.par()), tag());
        owe = ((rue * axe) * par) / tag

        # Bite cups with owe over a threshold that haven't been bitten before
        if owe > Ray.from_number(0) and cup.art != Wad.from_number(0):
            self.logger.info(
                f'Bite cup {cup_id} with owe of {owe} and ink of {cup.ink}')
            self.tub.bite(cup_id).transact(gas_price=self.gas_price())

    def gas_price(self):
        """ IncreasingGasPrice """
        GWEI = 1000000000

        return IncreasingGasPrice(initial_price=5 * GWEI,
                                  increase_by=10 * GWEI,
                                  every_secs=60,
                                  max_price=300 * GWEI)