Exemple #1
0
 def _order_tuple(order):
     return (order.maker.address, order.taker.address,
             order.fee_recipient.address, order.sender.address,
             order.pay_amount.value, order.buy_amount.value,
             order.maker_fee.value, order.taker_fee.value, order.expiration,
             order.salt, hexstring_to_bytes(order.pay_asset.serialize()),
             hexstring_to_bytes(order.buy_asset.serialize()))
Exemple #2
0
    def write(self, code: str):
        assert (isinstance(code, str))

        if code.startswith('0x'):
            b32_code = hexstring_to_bytes(code)
        else:
            b32_code = hexstring_to_bytes('0x' + code)

        return Transact(self, self.web3, self.abi, self.address, self._contract, 'write', [b32_code])
Exemple #3
0
    def execute(self, code: str, calldata: Calldata) -> Transact:
        assert (isinstance(code, str))
        assert (isinstance(calldata, Calldata))

        if code.startswith('0x'):
            b32_code = hexstring_to_bytes(code)
        else:
            b32_code = hexstring_to_bytes('0x' + code)

        return Transact(self, self.web3, self.abi, self.address, self._contract,
                        'execute(bytes,bytes)', [b32_code, calldata.as_bytes()])
Exemple #4
0
    def read(self, code: str) -> Optional[Address]:
        assert (isinstance(code, str))

        if code.startswith('0x'):
            b32_code = hexstring_to_bytes(code)
        else:
            b32_code = hexstring_to_bytes('0x' + code)
        address = Address(self._contract.call().read(b32_code))

        if address == Address('0x0000000000000000000000000000000000000000'):
            return None
        else:
            return address
Exemple #5
0
 def from_json(ether_delta, data: dict):
     assert (isinstance(data, dict))
     return Order(ether_delta=ether_delta,
                  maker=Address(data['user']),
                  pay_token=Address(data['tokenGive']),
                  pay_amount=Wad(int(data['amountGive'])),
                  buy_token=Address(data['tokenGet']),
                  buy_amount=Wad(int(data['amountGet'])),
                  expires=int(data['expires']),
                  nonce=int(data['nonce']),
                  v=int(data['v']),
                  r=hexstring_to_bytes(data['r']),
                  s=hexstring_to_bytes(data['s']))
Exemple #6
0
    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 `ec_signature_r`, `ec_signature_s`
            and `ec_signature_v` fields filled with signature values.
        """
        assert(isinstance(order, Order))

        # TODO duplicate code below
        signed_hash = eth_sign(self.web3, hexstring_to_bytes(self.get_order_hash(order)))[2:]
        r = bytes.fromhex(signed_hash[0:64])
        s = bytes.fromhex(signed_hash[64:128])
        v = ord(bytes.fromhex(signed_hash[128:130]))

        signed_order = copy.copy(order)
        signed_order.ec_signature_r = bytes_to_hexstring(r)
        signed_order.ec_signature_s = bytes_to_hexstring(s)
        signed_order.ec_signature_v = v
        return signed_order
Exemple #7
0
    def place_order(self, pair: str, is_sell: bool, price: Wad,
                    amount: Wad) -> str:
        assert (isinstance(pair, str))
        assert (isinstance(is_sell, bool))
        assert (isinstance(price, Wad))
        assert (isinstance(amount, Wad))

        self.logger.info(
            f"Placing order ({'SELL' if is_sell else 'BUY'}, amount {amount} of {pair},"
            f" price {price})...")

        # build order
        order = self._build_order(amount, price, is_sell, pair)

        result = self._http_post_signed(f"/{self.version}/orders/build", order)
        order_id = result['data']['order']['id']
        unsignedOrder = result['data']['order']['json']
        fee = self._get_fee_rate(result)

        # sign order
        signature = eth_sign(hexstring_to_bytes(order_id), self.web3)
        result = self._http_post_signed(f"/{self.version}/orders", {
            "orderId": order_id,
            "signature": signature
        })

        self.logger.info(
            f"Placed order ({'SELL' if is_sell else 'BUY'}, amount {amount} of {pair},"
            f" price {price}, fee {float(fee)*100:.4f}%) as #{order_id}")

        return order_id
Exemple #8
0
    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:`pymaker.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])
Exemple #9
0
    def write(self, code: str):
        assert (isinstance(code, str))

        b32_code = hexstring_to_bytes(code)

        return Transact(self, self.web3, self.abi, self.address,
                        self._contract, 'write', [b32_code])
Exemple #10
0
    def read(self, code: str) -> Address:
        assert (isinstance(code, str))

        b32_code = hexstring_to_bytes(code)
        address = self._contract.call().read(b32_code)

        return Address(address)
Exemple #11
0
    def place_order(self, pair: str, is_sell: bool, price: Wad, amount: Wad) -> str:
        assert(isinstance(pair, str))
        assert(isinstance(is_sell, bool))
        assert(isinstance(price, Wad))
        assert(isinstance(amount, Wad))

        self.logger.info(f"Placing order ({'SELL' if is_sell else 'BUY'}, amount {amount} of {pair},"
                         f" price {price})...")

        # build order
        order = {
            "amount": str(amount),
            "price": str(price),
            "side": 'sell' if is_sell else 'buy',
            "marketId": pair,
        }
        result = self._http_post_signed("/v2/orders/build", order)
        order_id = result['data']['order']['id']
        unsignedOrder = result['data']['order']['json']
        fee = result['data']['order']['feeAmount']

        # sign order
        signature = eth_sign(hexstring_to_bytes(order_id), self.web3)
        result = self._http_post_signed("/v2/orders", {"orderId": order_id, "signature": signature})

        self.logger.info(f"Placed order ({'SELL' if is_sell else 'BUY'}, amount {amount} of {pair},"
                         f" price {price}, fee {float(fee)*100:.4f}%) as #{order_id}")

        return order_id
Exemple #12
0
    def cancel_order(self, order: Order) -> bool:
        assert(isinstance(order, Order))

        nonce = self.next_nonce()
        signed_data = keccak_256(encode_bytes(hexstring_to_bytes(order.order_hash)) +
                                 encode_uint256(nonce)).digest()

        signature = eth_sign(signed_data, self.idex.web3)
        v, r, s = to_vrs(signature)

        data = {
            'orderHash': order.order_hash,
            'nonce': str(nonce),
            'address': self._our_address(),
            'v': v,
            'r': bytes_to_hexstring(r),
            's': bytes_to_hexstring(s)
        }

        self.logger.info(f"Cancelling order #{order.order_id}...")

        result = self._http_post("/cancel", data)
        success = result['success'] == 1

        if success:
            self.logger.info(f"Cancelled order #{order.order_id}")
        else:
            self.logger.info(f"Failed to cancel order #{order.order_id}")

        return success
    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:`pymaker.Transact` instance, which can be used to trigger the transaction.
        """
        assert(isinstance(order, Order))
        assert(isinstance(fill_buy_amount, Wad))

        return Transact(self, self.web3, self.abi, self.address, self._contract, 'fillOrder',
                        [self._order_addresses(order), self._order_values(order), fill_buy_amount.value,
                         True, order.ec_signature_v,
                         hexstring_to_bytes(order.ec_signature_r),
                         hexstring_to_bytes(order.ec_signature_s)])
Exemple #14
0
    def asset_transfer_proxy(self, proxy_id: str) -> Address:
        """Get the address of the `ERC20Proxy` contract associated with this `Exchange` contract.

        Returns:
            The address of the `ERC20Proxy` token.
        """
        assert (isinstance(proxy_id, str))

        return Address(self._contract.call().getAssetProxy(
            hexstring_to_bytes(proxy_id)))
    def get_unavailable_buy_amount(self, order: Order) -> Wad:
        """Return the order amount which was either taken or cancelled.

        Args:
            order: Order you want to get the unavailable amount of.

        Returns:
            The unavailable amount of the order (i.e. the amount which was either taken or cancelled),
            expressed in terms of the `buy_token` token.
        """
        assert(isinstance(order, Order))

        return Wad(self._contract.call().getUnavailableTakerTokenAmount(hexstring_to_bytes(self.get_order_hash(order))))
Exemple #16
0
    def sign_order(self, order: Order) -> Order:
        assert (isinstance(order, Order))

        # TODO duplicate code below
        signed_hash = eth_sign(self.web3,
                               hexstring_to_bytes(
                                   self.get_order_hash(order)))[2:]
        r = bytes.fromhex(signed_hash[0:64])
        s = bytes.fromhex(signed_hash[64:128])
        v = ord(bytes.fromhex(signed_hash[128:130]))

        signed_order = copy.copy(order)
        signed_order.ec_signature_r = bytes_to_hexstring(r)
        signed_order.ec_signature_s = bytes_to_hexstring(s)
        signed_order.ec_signature_v = v
        return signed_order
Exemple #17
0
    def test_permit_specific_addresses_and_sig(self):
        # when
        self.ds_guard.permit(src=Address('0x1111111111222222222211111111112222222222'),
                             dst=Address('0x3333333333444444444433333333334444444444'),
                             sig=hexstring_to_bytes('0xab121fd7')).transact()

        # then
        assert self.can_call(src='0x1111111111222222222211111111112222222222',
                             dst='0x3333333333444444444433333333334444444444',
                             sig='0xab121fd7')

        # and
        assert not self.can_call(src='0x3333333333444444444433333333334444444444',
                                 dst='0x1111111111222222222211111111112222222222',
                                 sig='0xab121fd7')  # different addresses
        assert not self.can_call(src='0x1111111111222222222211111111112222222222',
                                 dst='0x3333333333444444444433333333334444444444',
                                 sig='0xab121fd8')  # different sig
Exemple #18
0
def eth_sign_with_keyfile(message: bytes, raw: bool, keyfile: str, password: str):
    assert(isinstance(message, bytes))
    assert(isinstance(raw, bool))
    assert(isinstance(keyfile, str))
    assert(isinstance(password, str))

    if not raw:
        message = hexstring_to_bytes(Eth._recoveryMessageHash(data=message))

    key = eth_keyfile.decode_keyfile_json(eth_keyfile.load_keyfile(keyfile), bytes(password, 'utf-8'))
    pk = PrivateKey(key, raw=True)
    signature = pk.ecdsa_recoverable_serialize(
        pk.ecdsa_sign_recoverable(message, raw=True)
    )

    signature = signature[0] + utils.bytearray_to_bytestr([signature[1]])
    signature_hex = signature.hex()[0:128] + int_to_bytes(ord(bytes.fromhex(signature.hex()[128:130]))+27).hex()

    return '0x' + signature_hex
Exemple #19
0
def eth_sign(message: bytes, web3: Web3):
    assert(isinstance(message, bytes))
    assert(isinstance(web3, Web3))

    # as `EthereumTesterProvider` does not support `eth_sign`, we implement it ourselves
    if str(web3.providers[0]) == 'EthereumTesterProvider':
        key = k0
        msg = hexstring_to_bytes(Eth._recoveryMessageHash(data=message))

        pk = PrivateKey(key, raw=True)
        signature = pk.ecdsa_recoverable_serialize(
            pk.ecdsa_sign_recoverable(msg, raw=True)
        )

        signature = signature[0] + utils.bytearray_to_bytestr([signature[1]])
        signature_hex = signature.hex()[0:128] + int_to_bytes(ord(bytes.fromhex(signature.hex()[128:130]))+27).hex()

        return '0x' + signature_hex

    return web3.manager.request_blocking(
        "eth_sign", [web3.eth.defaultAccount, encode_hex(message)],
    )
    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 `ec_signature_r`, `ec_signature_s`
            and `ec_signature_v` fields filled with signature values.
        """
        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.ec_signature_r = bytes_to_hexstring(r)
        signed_order.ec_signature_s = bytes_to_hexstring(s)
        signed_order.ec_signature_v = v
        return signed_order
Exemple #21
0
    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
Exemple #22
0
 def can_call(self, src: str, dst: str, sig: str) -> bool:
     return self.ds_guard._contract.call().canCall(src, dst,
                                                   hexstring_to_bytes(sig))
Exemple #23
0
    def get_unavailable_buy_amount(self, order: Order) -> Wad:
        assert (isinstance(order, Order))

        return Wad(self._contract.call().getUnavailableTakerTokenAmount(
            hexstring_to_bytes(self.get_order_hash(order))))
Exemple #24
0
def test_hexstring_to_bytes():
    assert hexstring_to_bytes('0x00') == bytes([0x00])
    assert hexstring_to_bytes('0x010203') == bytes([0x01, 0x02, 0x03])
    assert hexstring_to_bytes('0xffff') == bytes([0xff, 0xff])