def __init__(self, log): self.maker = Address(log['args']['makerAddress']) self.fee_recipient = Address(log['args']['feeRecipientAddress']) self.sender = Address(log['args']['senderAddress']) self.pay_asset = Asset.deserialize( bytes_to_hexstring(log['args']['makerAssetData'])) self.buy_asset = Asset.deserialize( bytes_to_hexstring(log['args']['takerAssetData'])) self.order_hash = bytes_to_hexstring(log['args']['orderHash']) self.raw = log
def fill_order(self, order: Order, fill_buy_amount: Wad) -> Transact: """Fills an order. Args: order: The order to be filled. fill_buy_amount: The amount (in terms of `buy_token` of the original order) to be filled. Returns: A :py:class:`pyflex.Transact` instance, which can be used to trigger the transaction. """ assert (isinstance(order, Order)) assert (isinstance(fill_buy_amount, Wad)) method_signature = self.web3.keccak( text=f"fillOrder({self.ORDER_INFO_TYPE},uint256,bytes)")[0:4] method_parameters = encode_single( f"({self.ORDER_INFO_TYPE},uint256,bytes)", [ self._order_tuple(order), fill_buy_amount.value, hexstring_to_bytes(order.signature) ]) request = bytes_to_hexstring(method_signature + method_parameters) return Transact(self, self.web3, self.abi, self.address, self._contract, None, [request])
def __init__(self, log): self.sender = Address(log['args']['senderAddress']) self.maker = Address(log['args']['makerAddress']) self.taker = Address(log['args']['takerAddress']) self.fee_recipient = Address(log['args']['feeRecipientAddress']) self.pay_asset = Asset.deserialize( bytes_to_hexstring(log['args']['makerAssetData'])) self.buy_asset = Asset.deserialize( bytes_to_hexstring(log['args']['takerAssetData'])) self.filled_pay_amount = Wad(int( log['args']['makerAssetFilledAmount'])) self.filled_buy_amount = Wad(int( log['args']['takerAssetFilledAmount'])) self.paid_maker_fee = Wad(int(log['args']['makerFeePaid'])) self.paid_taker_fee = Wad(int(log['args']['takerFeePaid'])) self.order_hash = bytes_to_hexstring(log['args']['orderHash']) self.raw = log
def zrx_asset(self) -> str: """Get the asset data of the ZRX token contract associated with this `ExchangeV2` contract. Returns: The asset data of the `ZRX` token. """ return str( bytes_to_hexstring( self._contract.functions.ZRX_ASSET_DATA().call()))
def __init__(self, value): if isinstance(value, str): assert (value.startswith('0x')) self.value = value elif isinstance(value, bytes): self.value = bytes_to_hexstring(value) else: raise Exception(f"Unable to create calldata from '{value}'")
def eth_sign(message: bytes, web3: Web3, key=None, in_hexbytes=False, account=None): assert (isinstance(message, bytes)) assert (isinstance(web3, Web3)) local_account = _registered_accounts.get( (web3, Address(web3.eth.defaultAccount))) if local_account or (account is not None): if key is None: pkey = local_account.privateKey else: pkey = key start_time = time.time() start_clock = time.process_time() try: if in_hexbytes: message_hash = message else: message_hash = defunct_hash_message(primitive=message) signature = web3.eth.account.signHash( message_hash, private_key=pkey).signature.hex() finally: end_time = time.time() end_clock = time.process_time() logging.debug( f"Local signing took {end_time - start_time:.3f}s time, {end_clock - start_clock:.3f}s clock" ) return signature else: signature = bytes_to_hexstring( web3.manager.request_blocking( "eth_sign", [web3.eth.defaultAccount, encode_hex(message)], )) # for `EthereumJS TestRPC/v2.2.1/ethereum-js` if signature.endswith("00"): signature = signature[:-2] + "1b" if signature.endswith("01"): signature = signature[:-2] + "1c" return signature
def sign_order(self, order: Order) -> Order: """Signs an order so it can be submitted to the relayer. Order will be signed by the `web3.eth.defaultAccount` account. Args: order: Order you want to sign. Returns: Signed order. Copy of the order passed as a parameter with the `signature` field filled with signature. """ assert (isinstance(order, Order)) signature = eth_sign(hexstring_to_bytes(self.get_order_hash(order)), self.web3) v, r, s = to_vrs(signature) signed_order = copy.copy(order) signed_order.signature = bytes_to_hexstring(bytes([v])) + \ bytes_to_hexstring(r)[2:] + \ bytes_to_hexstring(s)[2:] + \ "03" # EthSign return signed_order
def get_order_hash(self, order: Order) -> str: """Calculates hash of an order. Args: order: Order you want to calculate the hash of. Returns: Order hash as a hex string starting with `0x`. """ assert (isinstance(order, Order)) # the hash depends on the exchange contract address as well assert (order.exchange_contract_address == self.address) return bytes_to_hexstring(self._get_order_info(order)[0][1])
def _get_order_info(self, order): assert (isinstance(order, Order)) method_signature = self.web3.keccak( text=f"getOrderInfo({self.ORDER_INFO_TYPE})")[0:4] method_parameters = encode_single(f"({self.ORDER_INFO_TYPE})", [self._order_tuple(order)]) request = bytes_to_hexstring(method_signature + method_parameters) response = self.web3.eth.call({ 'to': self.address.address, 'data': request }) response_decoded = decode_single("((uint8,bytes32,uint256))", response) return response_decoded
def cancel_order(self, order: Order) -> Transact: """Cancels an order. Args: order: Order you want to cancel. Returns: A :py:class:`pyflex.Transact` instance, which can be used to trigger the transaction. """ assert (isinstance(order, Order)) method_signature = self.web3.keccak( text=f"cancelOrder({self.ORDER_INFO_TYPE})")[0:4] method_parameters = encode_single(f"({self.ORDER_INFO_TYPE})", [self._order_tuple(order)]) request = bytes_to_hexstring(method_signature + method_parameters) return Transact(self, self.web3, self.abi, self.address, self._contract, None, [request])
async def cancel_async(self, gas_price: GasPrice): assert isinstance(gas_price, GasPrice) initial_time = time.time() self.gas_price_last = self.current_gas self.tx_hashes.clear() if gas_price.get_gas_price(0) <= self.current_gas * 1.125: self.logger.warning( f"Recovery gas price is less than current gas price {self.current_gas}; " "cancellation will be deferred until the strategy produces an acceptable price." ) while True: seconds_elapsed = int(time.time() - initial_time) gas_price_value = gas_price.get_gas_price(seconds_elapsed) if gas_price_value > self.gas_price_last * 1.125: self.gas_price_last = gas_price_value # Transaction lock isn't needed here, as we are replacing an existing nonce tx_hash = bytes_to_hexstring( self.web3.eth.sendTransaction({ 'from': self.address.address, 'to': self.address.address, 'gasPrice': gas_price_value, 'nonce': self.nonce, 'value': 0 })) self.tx_hashes.append(tx_hash) self.logger.info( f"Attempting to cancel recovered tx with nonce={self.nonce}, " f"gas_price={gas_price_value} (tx_hash={tx_hash})") for tx_hash in self.tx_hashes: receipt = self._get_receipt(tx_hash) if receipt: self.logger.info( f"{self.name()} was cancelled (tx_hash={tx_hash})") return await asyncio.sleep(0.75)
def test_bytes_to_hexstring(): assert bytes_to_hexstring(bytes([0x00])) == '0x00' assert bytes_to_hexstring(bytes([0x01, 0x02, 0x03])) == '0x010203' assert bytes_to_hexstring(bytes([0xff, 0xff])) == '0xffff'
def format_parameter(parameter): if isinstance(parameter, bytes): return bytes_to_hexstring(parameter) else: return parameter