def __str__(self): def amt(amount: Wad) -> str: return f"{amount} " if amount is not None else "" source_token_name = ERC20Token.token_name_by_address(self.source_token) target_token_name = ERC20Token.token_name_by_address(self.target_token) return f"[{amt(self.source_amount)}{source_token_name} -> {amt(self.target_amount)}{target_token_name} " \ f"@{self.rate} by {self.method} (max={self.max_source_amount} {source_token_name})]"
def approval_function(token: ERC20Token, spender_address: Address, spender_name: str): if token.allowance_of(Address(token.web3.eth.defaultAccount), spender_address) < Wad(2**128 - 1): logger = logging.getLogger("api") logger.info( f"Approving {spender_name} ({spender_address}) to access our {token.name()} directly" ) if not token.approve(spender_address).transact(): raise RuntimeError("Approval failed!")
def approve(self, approval_function): approval_function(ERC20Token(web3=self.web3, address=self.gem()), self.jar(), 'Tub.jar') approval_function(ERC20Token(web3=self.web3, address=self.skr()), self.jar(), 'Tub.jar') approval_function(ERC20Token(web3=self.web3, address=self.sai()), self.pot(), 'Tub.pot') approval_function(ERC20Token(web3=self.web3, address=self.skr()), self.pit(), 'Tub.pit') approval_function(ERC20Token(web3=self.web3, address=self.sai()), self.pit(), 'Tub.pit')
def approval_function(token: ERC20Token, spender_address: Address, spender_name: str): if token.allowance_of(tx_manager.address, spender_address) < Wad(2**128 - 1): logger = logging.getLogger("api") logger.info( f"Approving {spender_name} ({spender_address}) to access our {token.name()}" f" via TxManager {tx_manager.address}") if not tx_manager.execute([], [ (token.approve(spender_address).invocation()) ]).transact(): raise RuntimeError("Approval failed!")
def __init__(self, auction_manager, auction_id, auction_info): self._auction_manager = auction_manager self.auction_id = auction_id self.creator = Address(auction_info[0]) self.selling = ERC20Token(web3=auction_manager.web3, address=Address(auction_info[1])) self.buying = ERC20Token(web3=auction_manager.web3, address=Address(auction_info[2])) self.start_bid = Wad(auction_info[3]) self.min_increase = auction_info[4] self.min_decrease = auction_info[5] self.sell_amount = Wad(auction_info[6]) self.ttl = auction_info[7] self.reversed = auction_info[8] self.unsold = auction_info[9]
def test_equals(self): # given token1 = DSToken.deploy(self.web3, 'ABC') token2 = DSToken.deploy(self.web3, 'DEF') token2b = ERC20Token(web3=self.web3, address=token2.address) # expect assert token1 == token1 assert token2 == token2b assert not token1 == token2 assert not token1 == token2b
def __init__(self, lpc: Lpc): self.lpc = lpc rate = Ray(self.lpc.par() / (self.lpc.tag() * self.lpc.gap())) #TODO we always leave 0.000001 in the liquidity pool, in case of some rounding errors max_entry_ref = Wad.max( (ERC20Token(web3=lpc.web3, address=lpc.alt()).balance_of( lpc.address) / Wad(rate)) - Wad.from_number(0.000001), Wad.from_number(0)) super().__init__(source_token=self.lpc.ref(), target_token=self.lpc.alt(), rate=rate, max_source_amount=max_entry_ref, method="lpc.take(alt)")
def __init__(self): super().__init__() self.tub_address = Address(self.config.get_contract_address("saiTub")) self.tub = Tub(web3=self.web3, address=self.tub_address) self.tap_address = Address(self.config.get_contract_address("saiTap")) self.tap = Tap(web3=self.web3, address=self.tap_address) self.top_address = Address(self.config.get_contract_address("saiTop")) self.top = Top(web3=self.web3, address=self.top_address) self.otc_address = Address(self.config.get_contract_address("otc")) self.otc = SimpleMarket(web3=self.web3, address=self.otc_address) self.skr = ERC20Token(web3=self.web3, address=self.tub.skr()) self.sai = ERC20Token(web3=self.web3, address=self.tub.sai()) self.gem = DSEthToken(web3=self.web3, address=self.tub.gem()) ERC20Token.register_token(self.tub.skr(), 'SKR') ERC20Token.register_token(self.tub.sai(), 'SAI') ERC20Token.register_token(self.tub.gem(), 'WETH')
def test_token_registry(self): # given ERC20Token.register_token( Address('0x0100000000000000000000000000000000000000'), 'ABC') ERC20Token.register_token( Address('0x0200000000000000000000000000000000000000'), 'DEF') ERC20Token.register_token( Address('0x0300000000000000000000000000000000000000'), 'GHI') # expect assert ERC20Token.token_name_by_address( Address('0x0100000000000000000000000000000000000000')) == 'ABC' assert ERC20Token.token_name_by_address( Address('0x0200000000000000000000000000000000000000')) == 'DEF' assert ERC20Token.token_name_by_address( Address('0x0300000000000000000000000000000000000000')) == 'GHI' with pytest.raises(Exception): assert ERC20Token.token_name_by_address( Address('0x0400000000000000000000000000000000000000')) # and assert ERC20Token.token_address_by_name('ABC') == Address( '0x0100000000000000000000000000000000000000') assert ERC20Token.token_address_by_name('DEF') == Address( '0x0200000000000000000000000000000000000000') assert ERC20Token.token_address_by_name('GHI') == Address( '0x0300000000000000000000000000000000000000') with pytest.raises(Exception): ERC20Token.token_address_by_name('XXX')
def test_should_have_printable_representation(self): erc20token = ERC20Token(web3=self.web3, address=self.token.address) assert repr(erc20token) == f"ERC20Token('{erc20token.address}')"
def register_tokens(token1, token2): ERC20Token.register_token(token1, 'TK1') ERC20Token.register_token(token2, 'TK2')
def approve(self, approval_function): approval_function(ERC20Token(web3=self.web3, address=self.ref()), self.address, 'Lpc') approval_function(ERC20Token(web3=self.web3, address=self.alt()), self.address, 'Lpc')
def __init__(self, chain: str): with open('keeper/config.json') as data_file: self.chain = chain self.config = json.load(data_file) for key, value in self.config[self.chain]["tokens"].items(): ERC20Token.register_token(Address(value), key)
def test_fail_when_no_token_with_that_address(self): with pytest.raises(Exception): ERC20Token( web3=self.web3, address=Address('0x0123456789012345678901234567890123456789'))
from keeper import Config from keeper.api.token import DSToken from keeper.api.token import ERC20Token parser = argparse.ArgumentParser(description='Dai Buy&Burn keeper. Buys DAI for MKR on forward auctions.') 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("--eth-from", help="Ethereum account from which to send transactions", required=True, type=str) parser.add_argument("--frequency", help="Frequency of periodical checking of existing auctions (in seconds) (default: 60)", default=60, type=int) parser.add_argument("--mkr-dai-rate", help="Target MKR/DAI rate", required=True, type=float) parser.add_argument("--minimal-mkr-bid", help="Minimal amount of MKR you want to bid", required=True, type=float) parser.add_argument("--step", help="Incremental step towards the maximum price (value between 0 and 1)", required=True, type=float) args = parser.parse_args() web3 = Web3(HTTPProvider(endpoint_uri=f"http://{args.rpc_host}:{args.rpc_port}")) web3.eth.defaultAccount = args.eth_from config = Config(web3) auction_manager_address = Address(config.get_contract_address("auctionManager")) auction_manager = AuctionManager(web3=web3, address=auction_manager_address, is_splitting=True) trader_address = Address(args.eth_from) dai_address = ERC20Token.token_address_by_name("DAI") dai_token = ERC20Token(web3=web3, address=dai_address) mkr_address = ERC20Token.token_address_by_name("MKR") mkr_token = DSToken(web3=web3, address=mkr_address) strategy = BasicForwardAuctionStrategy(dai_token, mkr_token, args.mkr_dai_rate, args.step, Wad(args.minimal_mkr_bid * 1000000000000000000)) engine = AuctionEngine(auction_manager, trader_address, strategy, args.frequency) engine.start()