def __init__(self, args: list, **kwargs): parser = argparse.ArgumentParser(prog='etherdelta-market-maker-keeper') self.add_arguments(parser=parser) parser.set_defaults(cancel_on_shutdown=False, withdraw_on_shutdown=False) self.arguments = parser.parse_args(args) setup_logging(self.arguments) 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.sai = ERC20Token(web3=self.web3, address=self.tub.sai()) self.gem = ERC20Token(web3=self.web3, address=self.tub.gem()) 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, self.tub) self.spread_feed = create_spread_feed(self.arguments) self.control_feed = create_control_feed(self.arguments) self.order_history_reporter = create_order_history_reporter( self.arguments) 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.history = History() 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()
def __init__(self, web3, dai_tub = '0x448a5065aeBB8E423F0896E6c5D525C040f59af3'): self.web3 = web3 self.tub = Tub(web3=web3, address=Address(dai_tub)) self.tap = Tap(web3=web3, address=self.tub.tap()) self.tokens = { 'MKR': ERC20Token(web3, self.tub.gov()), 'PETH': ERC20Token(web3, self.tub.skr()), 'WETH': ERC20Token(web3, self.tub.gem()), 'DAI': ERC20Token(web3, self.tub.sai()), }
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 __init__(self, args: list, **kwargs): parser = argparse.ArgumentParser(prog='idex-market-maker-keeper') self.add_arguments(parser=parser) parser.set_defaults(cancel_on_shutdown=False, withdraw_on_shutdown=False) self.arguments = parser.parse_args(args) setup_logging(self.arguments) 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.sai = ERC20Token(web3=self.web3, address=self.tub.sai()) self.gem = ERC20Token(web3=self.web3, address=self.tub.gem()) 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, self.tub) self.spread_feed = create_spread_feed(self.arguments) self.control_feed = create_control_feed(self.arguments) self.order_history_reporter = create_order_history_reporter( self.arguments) if self.eth_reserve <= self.min_eth_balance: raise Exception( "--eth-reserve must be higher than --min-eth-balance") self.history = History() self.idex = IDEX(self.web3, Address(self.arguments.idex_address)) self.idex_api = IDEXApi(self.idex, self.arguments.idex_api_server, self.arguments.idex_timeout)
def test_comparison(self, deployment: Deployment): # expect assert deployment.tub == deployment.tub assert deployment.tub == Tub(web3=deployment.web3, address=deployment.tub.address)
def test_fail_when_no_contract_under_that_address(self, deployment: Deployment): # expect with pytest.raises(Exception): Tub(web3=deployment.web3, address=Address('0xdeadadd1e5500000000000000000000000000000'))
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=False, 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( "--oasis-support-address", type=str, required=False, help="Ethereum address of the OasisDEX support contract") parser.add_argument("--buy-token-address", type=str, required=True, help="Ethereum address of the buy token") parser.add_argument("--sell-token-address", type=str, required=True, help="Ethereum address of the sell token") parser.add_argument("--config", type=str, required=True, help="Bands configuration file") parser.add_argument("--price-feed", type=str, required=True, help="Source of price feed") parser.add_argument( "--price-feed-expiry", type=int, default=120, help="Maximum age of the price feed (in seconds, default: 120)") parser.add_argument("--spread-feed", type=str, help="Source of spread feed") parser.add_argument( "--spread-feed-expiry", type=int, default=3600, help="Maximum age of the spread feed (in seconds, default: 3600)") parser.add_argument("--order-history", type=str, help="Endpoint to report active orders to") parser.add_argument( "--order-history-every", type=int, default=30, help= "Frequency of reporting active orders (in seconds, default: 30)") 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 will cease operation") parser.add_argument("--gas-price", type=int, default=0, help="Gas price (in Wei)") 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( "--refresh-frequency", type=int, default=10, help="Order book refresh frequency (in seconds, default: 10)") parser.add_argument("--debug", dest='debug', action='store_true', help="Enable debug output") self.arguments = parser.parse_args(args) setup_logging(self.arguments) 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), support_address=Address(self.arguments.oasis_support_address) if self.arguments.oasis_support_address else None) tub = Tub(web3=self.web3, address=Address(self.arguments.tub_address)) \ if self.arguments.tub_address is not None else None self.token_buy = ERC20Token(web3=self.web3, address=Address( self.arguments.buy_token_address)) self.token_sell = ERC20Token(web3=self.web3, address=Address( self.arguments.sell_token_address)) 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, tub) self.spread_feed = create_spread_feed(self.arguments) self.order_history_reporter = create_order_history_reporter( self.arguments) self.history = History() self.order_book_manager = OrderBookManager( refresh_frequency=self.arguments.refresh_frequency) self.order_book_manager.get_orders_with(lambda: self.our_orders()) self.order_book_manager.place_orders_with(self.place_order_function) self.order_book_manager.cancel_orders_with(self.cancel_order_function) self.order_book_manager.enable_history_reporting( self.order_history_reporter, self.our_buy_orders, self.our_sell_orders) self.order_book_manager.start()
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)
def __init__(self, args, **kwargs): parser = argparse.ArgumentParser("arbitrage-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( "--eth-key", type=str, nargs='*', help= "Ethereum private key(s) to use (e.g. 'key_file=aaa.json,pass_file=aaa.pass')" ) parser.add_argument("--tub-address", type=str, required=True, help="Ethereum address of the Tub contract") parser.add_argument("--tap-address", type=str, required=True, help="Ethereum address of the Tap contract") parser.add_argument( "--exchange-address", type=str, help="Ethereum address of the 0x Exchange contract") parser.add_argument("--oasis-address", type=str, required=True, help="Ethereum address of the OasisDEX contract") parser.add_argument( "--oasis-support-address", type=str, required=False, help="Ethereum address of the OasisDEX support contract") parser.add_argument("--relayer-api-server", type=str, help="Address of the 0x Relayer API") parser.add_argument( "--relayer-per-page", type=int, default=100, help= "Number of orders to fetch per one page from the 0x Relayer API (default: 100)" ) parser.add_argument( "--tx-manager", type=str, help= "Ethereum address of the TxManager contract to use for multi-step arbitrage" ) parser.add_argument("--gas-price", type=int, default=0, help="Gas price in Wei (default: node default)") parser.add_argument( "--base-token", type=str, required=True, help="The token all arbitrage sequences will start and end with") parser.add_argument( "--min-profit", type=float, required=True, help="Minimum profit (in base token) from one arbitrage operation") parser.add_argument( "--max-engagement", type=float, required=True, help="Maximum engagement (in base token) in one arbitrage operation" ) parser.add_argument( "--max-errors", type=int, default=100, help= "Maximum number of allowed errors before the keeper terminates (default: 100)" ) 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 register_keys(self.web3, self.arguments.eth_key) self.our_address = Address(self.arguments.eth_from) self.tub = Tub(web3=self.web3, address=Address(self.arguments.tub_address)) self.tap = Tap(web3=self.web3, address=Address(self.arguments.tap_address)) self.gem = ERC20Token(web3=self.web3, address=self.tub.gem()) self.sai = ERC20Token(web3=self.web3, address=self.tub.sai()) self.skr = ERC20Token(web3=self.web3, address=self.tub.skr()) self.zrx_exchange = ZrxExchange(web3=self.web3, address=Address(self.arguments.exchange_address)) \ if self.arguments.exchange_address is not None else None self.zrx_relayer_api = ZrxRelayerApi(exchange=self.zrx_exchange, api_server=self.arguments.relayer_api_server) \ if self.arguments.relayer_api_server is not None else None self.otc = MatchingMarket( web3=self.web3, address=Address(self.arguments.oasis_address), support_address=Address(self.arguments.oasis_support_address) if self.arguments.oasis_support_address is not None else None) self.base_token = ERC20Token(web3=self.web3, address=Address( self.arguments.base_token)) self.min_profit = Wad.from_number(self.arguments.min_profit) self.max_engagement = Wad.from_number(self.arguments.max_engagement) self.max_errors = self.arguments.max_errors self.errors = 0 if self.arguments.tx_manager: self.tx_manager = TxManager(web3=self.web3, address=Address( self.arguments.tx_manager)) if self.tx_manager.owner() != self.our_address: raise Exception( f"The TxManager has to be owned by the address the keeper is operating from." ) else: self.tx_manager = None logging.basicConfig( format='%(asctime)-15s %(levelname)-8s %(message)s', level=(logging.DEBUG if self.arguments.debug else logging.INFO))
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()
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)
def __init__(self, args: list, **kwargs): parser = argparse.ArgumentParser(prog='tethfinex-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( "--eth-key", type=str, nargs='*', help= "Ethereum private key(s) to use (e.g. 'key_file=aaa.json,pass_file=aaa.pass')" ) parser.add_argument( "--exchange-address", type=str, required=True, help="Ethereum address of the 0x Exchange contract") parser.add_argument("--tub-address", type=str, required=False, help="Ethereum address of the Tub contract") parser.add_argument( "--tethfinex-api-server", type=str, default='https://api.ethfinex.com', help= "Address of the Trustless Ethfinex API server (default: 'https://api.ethfinex.com')" ) parser.add_argument( "--tethfinex-timeout", type=float, default=9.5, help="Timeout for accessing the IDEX API (in seconds, default: 9.5)" ) parser.add_argument( "--pair", type=str, required=True, help="Token pair (sell/buy) on which the keeper will operate") parser.add_argument("--config", type=str, required=True, help="Bands configuration file") parser.add_argument("--price-feed", type=str, required=True, help="Source of price feed") parser.add_argument( "--price-feed-expiry", type=int, default=120, help="Maximum age of the price feed (in seconds, default: 120)") parser.add_argument("--spread-feed", type=str, help="Source of spread feed") parser.add_argument( "--spread-feed-expiry", type=int, default=3600, help="Maximum age of the spread feed (in seconds, default: 3600)") parser.add_argument("--control-feed", type=str, help="Source of control feed") parser.add_argument( "--control-feed-expiry", type=int, default=86400, help="Maximum age of the control feed (in seconds, default: 86400)" ) parser.add_argument("--order-history", type=str, help="Endpoint to report active orders to") parser.add_argument( "--order-history-every", type=int, default=30, help= "Frequency of reporting active orders (in seconds, default: 30)") parser.add_argument("--gas-price", type=int, default=0, help="Gas price (in Wei)") 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("--ethgasstation-api-key", type=str, default=None, help="ethgasstation API key") parser.add_argument( "--refresh-frequency", type=int, default=3, help="Order book refresh frequency (in seconds, default: 3)") 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) setup_logging(self.arguments) 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) register_keys(self.web3, self.arguments.eth_key) tub = Tub(web3=self.web3, address=Address(self.arguments.tub_address)) \ if self.arguments.tub_address is not None else None self.sai = ERC20Token(web3=self.web3, address=tub.sai()) self.price_feed = PriceFeedFactory().create_price_feed( self.arguments, tub) self.bands_config = ReloadableConfig(self.arguments.config) self.gas_price = GasPriceFactory().create_gas_price( self.web3, self.arguments) self.spread_feed = create_spread_feed(self.arguments) self.control_feed = create_control_feed(self.arguments) self.order_history_reporter = create_order_history_reporter( self.arguments) self.history = History() self.tethfinex_exchange = ZrxExchange( web3=self.web3, address=Address(self.arguments.exchange_address)) self.tethfinex_api = TEthfinexApi( self.tethfinex_exchange, self.arguments.tethfinex_api_server, timeout=self.arguments.tethfinex_timeout) config = self.tethfinex_api.get_config()['0x'] self.fee_address = Address(config['ethfinexAddress']) token_registry = config['tokenRegistry'] token_sell = self.token_sell() token_buy = self.token_buy() self.token_sell_wrapper = TEthfinexToken( self.web3, Address(token_registry[token_sell]['wrapperAddress']), token_sell) self.token_buy_wrapper = TEthfinexToken( self.web3, Address(token_registry[token_buy]['wrapperAddress']), token_buy) pair = self.pair() self.order_book_manager = OrderBookManager( refresh_frequency=self.arguments.refresh_frequency, max_workers=1) self.order_book_manager.get_orders_with( lambda: self.tethfinex_api.get_orders(pair)) self.order_book_manager.cancel_orders_with( lambda order: self.tethfinex_api.cancel_order(order.order_id)) self.order_book_manager.enable_history_reporting( self.order_history_reporter, self.our_buy_orders, self.our_sell_orders) self.order_book_manager.start()
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("--relayer-api-server", type=str, required=True, help="Address of the 0x Relayer API") parser.add_argument("--config", type=str, required=True, help="Bands configuration file") parser.add_argument("--price-feed", type=str, required=True, help="Source of price feed") parser.add_argument( "--price-feed-expiry", type=int, default=120, help="Maximum age of the 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 will cease operation") 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( "--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) setup_logging(self.arguments) 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.sai = ERC20Token(web3=self.web3, address=self.tub.sai()) self.gem = ERC20Token(web3=self.web3, address=self.tub.gem()) 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.history = History() 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)
def __init__(self, args, **kwargs): parser = argparse.ArgumentParser("arbitrage-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("--tap-address", type=str, required=True, help="Ethereum address of the Tap contract") parser.add_argument("--oasis-address", type=str, required=True, help="Ethereum address of the OasisDEX contract") parser.add_argument("--tx-manager", type=str, help="Ethereum address of the TxManager contract to use for multi-step arbitrage") parser.add_argument("--gas-price", type=int, default=0, help="Gas price in Wei (default: node default)") parser.add_argument("--base-token", type=str, required=True, help="The token all arbitrage sequences will start and end with") parser.add_argument("--min-profit", type=float, required=True, help="Minimum profit (in base token) from one arbitrage operation") parser.add_argument("--max-engagement", type=float, required=True, help="Maximum engagement (in base token) in one arbitrage operation") parser.add_argument("--max-errors", type=int, default=100, help="Maximum number of allowed errors before the keeper terminates (default: 100)") parser.add_argument("--debug", dest='debug', action='store_true', help="Enable debug output") parser.add_argument("--ipcpath", type=str, required=True, help="Local IPC Path") parser.add_argument("--eth-from-password", type=str, required=True, help="Eth account password") self.arguments = parser.parse_args(args) self.web3 = kwargs['web3'] if 'web3' in kwargs else Web3(IPCProvider(ipc_path=self.arguments.ipcpath)) self.web3.eth.defaultAccount = self.arguments.eth_from if !self.web3.personal.unlockAccount(self.web3.eth.defaultAccount, self.arguments.eth_from_password): raise Exception(f"Incorrect account password") 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.tap = Tap(web3=self.web3, address=Address(self.arguments.tap_address)) self.gem = ERC20Token(web3=self.web3, address=self.tub.gem()) self.sai = ERC20Token(web3=self.web3, address=self.tub.sai()) self.skr = ERC20Token(web3=self.web3, address=self.tub.skr()) self.base_token = ERC20Token(web3=self.web3, address=Address(self.arguments.base_token)) self.min_profit = Wad.from_number(self.arguments.min_profit) self.max_engagement = Wad.from_number(self.arguments.max_engagement) self.max_errors = self.arguments.max_errors self.errors = 0 if self.arguments.tx_manager: self.tx_manager = TxManager(web3=self.web3, address=Address(self.arguments.tx_manager)) if self.tx_manager.owner() != self.our_address: raise Exception(f"The TxManager has to be owned by the address the keeper is operating from.") else: self.tx_manager = None logging.basicConfig(format='%(asctime)-15s %(levelname)-8s %(message)s', level=(logging.DEBUG if self.arguments.debug else logging.INFO))
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 __init__(self, args: list, **kwargs): parser = argparse.ArgumentParser(prog='idex-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("--idex-address", type=str, required=True, help="Ethereum address of the IDEX contract") parser.add_argument("--idex-api-server", type=str, default='https://api.idex.market', help="Address of the IDEX API server (default: 'https://api.idex.market')") parser.add_argument("--idex-timeout", type=float, default=9.5, help="Timeout for accessing the IDEX API (in seconds, default: 9.5)") parser.add_argument("--config", type=str, required=True, help="Bands configuration file") parser.add_argument("--price-feed", type=str, required=True, help="Source of price feed") parser.add_argument("--price-feed-expiry", type=int, default=120, help="Maximum age of the price feed (in seconds, default: 120)") 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 will cease operation") 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("--gas-price", type=int, default=0, help="Gas price (in Wei)") 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) setup_logging(self.arguments) 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.sai = ERC20Token(web3=self.web3, address=self.tub.sai()) self.gem = ERC20Token(web3=self.web3, address=self.tub.gem()) 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) if self.eth_reserve <= self.min_eth_balance: raise Exception("--eth-reserve must be higher than --min-eth-balance") self.history = History() self.idex = IDEX(self.web3, Address(self.arguments.idex_address)) self.idex_api = IDEXApi(self.idex, self.arguments.idex_api_server, self.arguments.idex_timeout)
from pymaker.token import ERC20Token from pymaker.numeric import Ray,Wad from pymaker.sai import Tub parser = argparse.ArgumentParser() parser.add_argument("-w", "--warnratio", help="minimum ratio in percent that gives a warning", type=int, default="180") parser.add_argument("-q", "--quiet", help="only output warnings", action='store_true') parser.add_argument('cdps', metavar='CDP', type=int, nargs='+', help='CDP id(s) to check') args = parser.parse_args() web3 = Web3(HTTPProvider(endpoint_uri="https://mainnet.infura.io/metamask")) tub = Tub(web3=web3, address=Address('0x448a5065aebb8e423f0896e6c5d525c040f59af3')) minimum_ratio=Ray.from_number(args.warnratio / 100) requirements_satisfied=True for cup_id in args.cdps: cup = tub.cups(cup_id) pro = tub.ink(cup_id)*tub.tag() tab = tub.tab(cup_id) if not args.quiet: print(f'CDP #{cup_id}') print(f' Owner {cup.lad}') print(f' Deposited {float(cup.ink):.8} PETH') print(f' Debt {float(tab):.8} DAI') if tab > Wad(0): current_ratio = Ray(pro / tab) if not args.quiet:
def __init__(self, args: list, **kwargs): parser = argparse.ArgumentParser(prog='cdp-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("--tub-address", help="Ethereum address of the Tub contract", required=True, type=str) parser.add_argument( "--min-margin", help= "Margin between the liquidation ratio and the top-up threshold", type=float, required=True) parser.add_argument( "--top-up-margin", help="Margin between the liquidation ratio and the top-up target", type=float, required=True) parser.add_argument("--max-sai", type=float, required=True) parser.add_argument("--avg-sai", type=float, required=True) parser.add_argument("--gas-price", help="Gas price in Wei (default: node default)", default=0, type=int) 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"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.sai = ERC20Token(web3=self.web3, address=self.tub.sai()) self.liquidation_ratio = self.tub.mat() self.minimum_ratio = self.liquidation_ratio + Ray.from_number( self.arguments.min_margin) self.target_ratio = self.liquidation_ratio + Ray.from_number( self.arguments.top_up_margin) self.max_sai = Wad.from_number(self.arguments.max_sai) self.avg_sai = Wad.from_number(self.arguments.avg_sai) logging.basicConfig( format='%(asctime)-15s %(levelname)-8s %(message)s', level=(logging.DEBUG if self.arguments.debug else logging.INFO))
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="Bands configuration file") parser.add_argument("--price-feed", type=str, required=True, help="Source of price feed") parser.add_argument( "--price-feed-expiry", type=int, default=120, help="Maximum age of the 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 will cease operation") parser.add_argument("--gas-price", type=int, default=0, help="Gas price (in Wei)") 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) setup_logging(self.arguments) 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.sai = ERC20Token(web3=self.web3, address=self.tub.sai()) self.gem = ERC20Token(web3=self.web3, address=self.tub.gem()) 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.order_book_manager = OrderBookManager(refresh_frequency=3) self.order_book_manager.get_orders_with(lambda: self.our_orders()) self.order_book_manager.start()
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( "--eth-key", type=str, nargs='*', help= "Ethereum private key(s) to use (e.g. 'key_file=aaa.json,pass_file=aaa.pass')" ) 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="Bands configuration file") parser.add_argument("--price-feed", type=str, required=True, help="Source of price feed") parser.add_argument( "--price-feed-expiry", type=int, default=120, help="Maximum age of the price feed (in seconds, default: 120)") parser.add_argument("--spread-feed", type=str, help="Source of spread feed") parser.add_argument( "--spread-feed-expiry", type=int, default=3600, help="Maximum age of the spread feed (in seconds, default: 3600)") parser.add_argument("--control-feed", type=str, help="Source of control feed") parser.add_argument( "--control-feed-expiry", type=int, default=86400, help="Maximum age of the control feed (in seconds, default: 86400)" ) parser.add_argument("--order-history", type=str, help="Endpoint to report active orders to") parser.add_argument( "--order-history-every", type=int, default=30, help= "Frequency of reporting active orders (in seconds, default: 30)") 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 will cease operation") 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( "--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) setup_logging(self.arguments) 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) register_keys(self.web3, self.arguments.eth_key) self.tub = Tub(web3=self.web3, address=Address(self.arguments.tub_address)) self.sai = ERC20Token(web3=self.web3, address=self.tub.sai()) self.gem = ERC20Token(web3=self.web3, address=self.tub.gem()) 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, self.tub) self.spread_feed = create_spread_feed(self.arguments) self.control_feed = create_control_feed(self.arguments) self.order_history_reporter = create_order_history_reporter( self.arguments) 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.history = History() 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()