aboutsummaryrefslogtreecommitdiffstats
path: root/python-packages/order_utils
diff options
context:
space:
mode:
authorLeonid Logvinov <logvinov.leon@gmail.com>2019-01-10 18:51:13 +0800
committerLeonid Logvinov <logvinov.leon@gmail.com>2019-01-10 18:56:15 +0800
commitcee29542451d3bf8c99bd08963a2108768072195 (patch)
treef3d657be53459ce3851fcf9632bd94f32ee80184 /python-packages/order_utils
parenta8d9263062e586b90ee4c303d3d3aca72e428edc (diff)
parent686f27a96f0cd749f6315d7edd2bb56cf1819245 (diff)
downloaddexon-sol-tools-cee29542451d3bf8c99bd08963a2108768072195.tar
dexon-sol-tools-cee29542451d3bf8c99bd08963a2108768072195.tar.gz
dexon-sol-tools-cee29542451d3bf8c99bd08963a2108768072195.tar.bz2
dexon-sol-tools-cee29542451d3bf8c99bd08963a2108768072195.tar.lz
dexon-sol-tools-cee29542451d3bf8c99bd08963a2108768072195.tar.xz
dexon-sol-tools-cee29542451d3bf8c99bd08963a2108768072195.tar.zst
dexon-sol-tools-cee29542451d3bf8c99bd08963a2108768072195.zip
Merge development
Diffstat (limited to 'python-packages/order_utils')
-rwxr-xr-xpython-packages/order_utils/setup.py23
-rw-r--r--python-packages/order_utils/src/conf.py1
-rw-r--r--python-packages/order_utils/src/index.rst15
-rw-r--r--python-packages/order_utils/src/zero_ex/contract_artifacts/__init__.py1
l---------python-packages/order_utils/src/zero_ex/contract_artifacts/artifacts1
-rw-r--r--python-packages/order_utils/src/zero_ex/json_schemas/__init__.py74
l---------python-packages/order_utils/src/zero_ex/json_schemas/schemas1
-rw-r--r--python-packages/order_utils/src/zero_ex/order_utils/__init__.py278
-rw-r--r--python-packages/order_utils/src/zero_ex/order_utils/asset_data_utils.py6
-rw-r--r--python-packages/order_utils/stubs/jsonschema/__init__.pyi11
-rw-r--r--python-packages/order_utils/stubs/jsonschema/exceptions.pyi0
-rw-r--r--python-packages/order_utils/stubs/web3/__init___BASE_31011.pyi26
-rw-r--r--python-packages/order_utils/test/test_doctest.py18
-rw-r--r--python-packages/order_utils/test/test_generate_order_hash_hex.py4
-rw-r--r--python-packages/order_utils/test/test_json_schemas.py23
15 files changed, 256 insertions, 226 deletions
diff --git a/python-packages/order_utils/setup.py b/python-packages/order_utils/setup.py
index 125de5ff7..6f9465680 100755
--- a/python-packages/order_utils/setup.py
+++ b/python-packages/order_utils/setup.py
@@ -21,7 +21,7 @@ class TestCommandExtension(TestCommand):
"""Invoke pytest."""
import pytest
- exit(pytest.main())
+ exit(pytest.main(["--doctest-modules"]))
class LintCommand(distutils.command.build_py.build_py):
@@ -137,14 +137,8 @@ class GanacheCommand(distutils.command.build_py.build_py):
def run(self):
"""Run ganache."""
cmd_line = (
- "docker run -d -p 8545:8545 0xorg/ganache-cli --gasLimit"
- + " 10000000 --db /snapshot --noVMErrorsOnRPCResponse -p 8545"
- + " --networkId 50 -m"
+ "docker run -d -p 8545:8545 0xorg/ganache-cli:2.2.2"
).split()
- cmd_line.append(
- "concert load couple harbor equip island argue ramp clarify fence"
- + " smart topic"
- )
subprocess.call(cmd_line) # nosec
@@ -171,9 +165,13 @@ setup(
"ganache": GanacheCommand,
},
install_requires=[
+ "0x-contract-addresses",
+ "0x-contract-artifacts",
+ "0x-json-schemas",
"eth-abi",
"eth_utils",
- "jsonschema",
+ "hypothesis>=3.31.2", # HACK! this is web3's dependency!
+ # above works around https://github.com/ethereum/web3.py/issues/1179
"mypy_extensions",
"web3",
],
@@ -190,16 +188,13 @@ setup(
"pylint",
"pytest",
"sphinx",
+ "sphinx-autodoc-typehints",
"tox",
"twine",
]
},
python_requires=">=3.6, <4",
- package_data={
- "zero_ex.order_utils": ["py.typed"],
- "zero_ex.contract_artifacts": ["artifacts/*"],
- "zero_ex.json_schemas": ["schemas/*"],
- },
+ package_data={"zero_ex.order_utils": ["py.typed"]},
package_dir={"": "src"},
license="Apache 2.0",
keywords=(
diff --git a/python-packages/order_utils/src/conf.py b/python-packages/order_utils/src/conf.py
index 6b6776d01..d8f56b29e 100644
--- a/python-packages/order_utils/src/conf.py
+++ b/python-packages/order_utils/src/conf.py
@@ -22,6 +22,7 @@ extensions = [
"sphinx.ext.intersphinx",
"sphinx.ext.coverage",
"sphinx.ext.viewcode",
+ "sphinx_autodoc_typehints",
]
templates_path = ["doc_templates"]
diff --git a/python-packages/order_utils/src/index.rst b/python-packages/order_utils/src/index.rst
index 551487ab1..ce618c6ff 100644
--- a/python-packages/order_utils/src/index.rst
+++ b/python-packages/order_utils/src/index.rst
@@ -7,23 +7,26 @@ Python zero_ex.order_utils
:maxdepth: 2
:caption: Contents:
-.. autoclass:: zero_ex.order_utils.Order
+.. automodule:: zero_ex.order_utils
:members:
-See source for class properties. Sphinx does not easily generate class property docs; pull requests welcome.
+.. autoclass:: zero_ex.order_utils.Order
-.. automodule:: zero_ex.order_utils
- :members:
+ See source for class properties. Sphinx is having problems generating docs for ``TypedDict`` declarations; pull requests welcome.
+
+zero_ex.order_utils.asset_data_utils
+------------------------------------
.. automodule:: zero_ex.order_utils.asset_data_utils
:members:
.. autoclass:: zero_ex.order_utils.asset_data_utils.ERC20AssetData
+ See source for class properties. Sphinx is having problems generating docs for ``TypedDict`` declarations; pull requests welcome.
+
.. autoclass:: zero_ex.order_utils.asset_data_utils.ERC721AssetData
-.. automodule:: zero_ex.json_schemas
- :members:
+ See source for class properties. Sphinx is having problems generating docs for ``TypedDict`` declarations; pull requests welcome.
Indices and tables
==================
diff --git a/python-packages/order_utils/src/zero_ex/contract_artifacts/__init__.py b/python-packages/order_utils/src/zero_ex/contract_artifacts/__init__.py
deleted file mode 100644
index ed45d2c8e..000000000
--- a/python-packages/order_utils/src/zero_ex/contract_artifacts/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-"""Solc-generated artifacts for 0x smart contracts."""
diff --git a/python-packages/order_utils/src/zero_ex/contract_artifacts/artifacts b/python-packages/order_utils/src/zero_ex/contract_artifacts/artifacts
deleted file mode 120000
index 82d28ba87..000000000
--- a/python-packages/order_utils/src/zero_ex/contract_artifacts/artifacts
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../packages/contract-artifacts/artifacts \ No newline at end of file
diff --git a/python-packages/order_utils/src/zero_ex/json_schemas/__init__.py b/python-packages/order_utils/src/zero_ex/json_schemas/__init__.py
deleted file mode 100644
index a76a2fa3b..000000000
--- a/python-packages/order_utils/src/zero_ex/json_schemas/__init__.py
+++ /dev/null
@@ -1,74 +0,0 @@
-"""JSON schemas and associated utilities."""
-
-from os import path
-import json
-from typing import Mapping
-
-from pkg_resources import resource_string
-import jsonschema
-
-
-class _LocalRefResolver(jsonschema.RefResolver):
- """Resolve package-local JSON schema id's."""
-
- def __init__(self):
- """Initialize a new instance."""
- self.ref_to_file = {
- "/addressSchema": "address_schema.json",
- "/hexSchema": "hex_schema.json",
- "/orderSchema": "order_schema.json",
- "/wholeNumberSchema": "whole_number_schema.json",
- "/ECSignature": "ec_signature_schema.json",
- "/signedOrderSchema": "signed_order_schema.json",
- "/ecSignatureParameterSchema": (
- "ec_signature_parameter_schema.json" + ""
- ),
- }
- jsonschema.RefResolver.__init__(self, "", "")
-
- def resolve_from_url(self, url: str) -> str:
- """Resolve the given URL.
-
- :param url: a string representing the URL of the JSON schema to fetch.
- :returns: a string representing the deserialized JSON schema
- :raises jsonschema.ValidationError: when the resource associated with
- `url` does not exist.
- """
- ref = url.replace("file://", "")
- if ref in self.ref_to_file:
- return json.loads(
- resource_string(
- "zero_ex.json_schemas", f"schemas/{self.ref_to_file[ref]}"
- )
- )
- raise jsonschema.ValidationError(
- f"Unknown ref '{ref}'. "
- + f"Known refs: {list(self.ref_to_file.keys())}."
- )
-
-
-# Instantiate the `_LocalRefResolver()` only once so that `assert_valid()` can
-# perform multiple schema validations without reading from disk the schema
-# every time.
-_LOCAL_RESOLVER = _LocalRefResolver()
-
-
-def assert_valid(data: Mapping, schema_id: str) -> None:
- """Validate the given `data` against the specified `schema`.
-
- :param data: Python dictionary to be validated as a JSON object.
- :param schema_id: id property of the JSON schema to validate against. Must
- be one of those listed in `the 0x JSON schema files
- <https://github.com/0xProject/0x-monorepo/tree/development/packages/json-schemas/schemas>`_.
-
- Raises an exception if validation fails.
-
- >>> assert_valid(
- ... {'v': 27, 'r': '0x'+'f'*64, 's': '0x'+'f'*64},
- ... '/ECSignature',
- ... )
- """
- # noqa
-
- _, schema = _LOCAL_RESOLVER.resolve(schema_id)
- jsonschema.validate(data, schema, resolver=_LOCAL_RESOLVER)
diff --git a/python-packages/order_utils/src/zero_ex/json_schemas/schemas b/python-packages/order_utils/src/zero_ex/json_schemas/schemas
deleted file mode 120000
index b8257372c..000000000
--- a/python-packages/order_utils/src/zero_ex/json_schemas/schemas
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../packages/json-schemas/schemas/ \ No newline at end of file
diff --git a/python-packages/order_utils/src/zero_ex/order_utils/__init__.py b/python-packages/order_utils/src/zero_ex/order_utils/__init__.py
index 24c6bfd4e..39d411507 100644
--- a/python-packages/order_utils/src/zero_ex/order_utils/__init__.py
+++ b/python-packages/order_utils/src/zero_ex/order_utils/__init__.py
@@ -1,28 +1,29 @@
"""Order utilities for 0x applications.
-Some methods require the caller to pass in a `Web3.HTTPProvider` object. For
-local testing one may construct such a provider pointing at an instance of
+Some methods require the caller to pass in a `Web3.BaseProvider`:code: object.
+For local testing one may construct such a provider pointing at an instance of
`ganache-cli <https://www.npmjs.com/package/ganache-cli>`_ which has the 0x
contracts deployed on it. For convenience, a docker container is provided for
-just this purpose. To start it: ``docker run -d -p 8545:8545 0xorg/ganache-cli
---gasLimit 10000000 --db /snapshot --noVMErrorsOnRPCResponse -p 8545
---networkId 50 -m "concert load couple harbor equip island argue ramp clarify
-fence smart topic"``.
+just this purpose. To start it:
+`docker run -d -p 8545:8545 0xorg/ganache-cli:2.2.2`:code:.
"""
+from copy import copy
from enum import auto, Enum
import json
-from typing import Dict, Tuple
+from typing import cast, Dict, NamedTuple, Tuple
from pkg_resources import resource_string
from mypy_extensions import TypedDict
-from eth_utils import keccak, to_bytes, to_checksum_address
+from eth_utils import keccak, remove_0x_prefix, to_bytes, to_checksum_address
from web3 import Web3
import web3.exceptions
from web3.providers.base import BaseProvider
from web3.utils import datatypes
+from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId
+import zero_ex.contract_artifacts
from zero_ex.dev_utils.type_assertions import (
assert_is_address,
assert_is_hex_string,
@@ -34,34 +35,6 @@ from zero_ex.json_schemas import assert_valid
class _Constants:
"""Static data used by order utilities."""
- _contract_name_to_abi: Dict[str, Dict] = {} # class data, not instance
-
- @classmethod
- def contract_name_to_abi(cls, contract_name: str) -> Dict:
- """Return the ABI for the given contract name.
-
- First tries to get data from the class level storage
- `_contract_name_to_abi`. If it's not there, loads it from disk, stores
- it in the class data (for the next caller), and then returns it.
- """
- try:
- return cls._contract_name_to_abi[contract_name]
- except KeyError:
- cls._contract_name_to_abi[contract_name] = json.loads(
- resource_string(
- "zero_ex.contract_artifacts",
- f"artifacts/{contract_name}.json",
- )
- )["compilerOutput"]["abi"]
- return cls._contract_name_to_abi[contract_name]
-
- network_to_exchange_addr: Dict[str, str] = {
- "1": "0x4f833a24e1f95d70f028921e27040ca56e09ab0b",
- "3": "0x4530c0483a1633c7a1c97d2c53721caff2caaaaf",
- "42": "0x35dd2932454449b14cee11a94d3674a936d5d7b2",
- "50": "0x48bacb9266a570d521063ef5dd96e61686dbe788",
- }
-
null_address = "0x0000000000000000000000000000000000000000"
eip191_header = b"\x19\x01"
@@ -107,53 +80,195 @@ class _Constants:
class Order(TypedDict): # pylint: disable=too-many-instance-attributes
- """Object representation of a 0x order."""
+ """A Web3-compatible representation of the Exchange.Order struct."""
makerAddress: str
+ """Address that created the order."""
+
takerAddress: str
+ """Address that is allowed to fill the order.
+
+ If set to 0, any address is allowed to fill the order.
+ """
+
feeRecipientAddress: str
+ """Address that will recieve fees when order is filled."""
+
senderAddress: str
- makerAssetAmount: str
- takerAssetAmount: str
- makerFee: str
- takerFee: str
- expirationTimeSeconds: str
- salt: str
- makerAssetData: str
- takerAssetData: str
- exchangeAddress: str
+ """Address that is allowed to call Exchange contract methods that affect
+ this order. If set to 0, any address is allowed to call these methods.
+ """
+
+ makerAssetAmount: int
+ """Amount of makerAsset being offered by maker. Must be greater than 0."""
+
+ takerAssetAmount: int
+ """Amount of takerAsset being bid on by maker. Must be greater than 0."""
+
+ makerFee: int
+ """Amount of ZRX paid to feeRecipient by maker when order is filled. If
+ set to 0, no transfer of ZRX from maker to feeRecipient will be attempted.
+ """
+
+ takerFee: int
+ """Amount of ZRX paid to feeRecipient by taker when order is filled. If
+ set to 0, no transfer of ZRX from taker to feeRecipient will be attempted.
+ """
+
+ expirationTimeSeconds: int
+ """Timestamp in seconds at which order expires."""
+
+ salt: int
+ """Arbitrary number to facilitate uniqueness of the order's hash."""
+
+ makerAssetData: bytes
+ """Encoded data that can be decoded by a specified proxy contract when
+ transferring makerAsset. The last byte references the id of this proxy.
+ """
+
+ takerAssetData: bytes
+ """Encoded data that can be decoded by a specified proxy contract when
+ transferring takerAsset. The last byte references the id of this proxy.
+ """
def make_empty_order() -> Order:
"""Construct an empty order.
- Initializes all strings to "0x0000000000000000000000000000000000000000"
- and all numbers to 0.
+ Initializes all strings to "0x0000000000000000000000000000000000000000",
+ all numbers to 0, and all bytes to nulls.
"""
return {
"makerAddress": _Constants.null_address,
"takerAddress": _Constants.null_address,
"senderAddress": _Constants.null_address,
"feeRecipientAddress": _Constants.null_address,
- "makerAssetData": _Constants.null_address,
- "takerAssetData": _Constants.null_address,
- "salt": "0",
- "makerFee": "0",
- "takerFee": "0",
- "makerAssetAmount": "0",
- "takerAssetAmount": "0",
- "expirationTimeSeconds": "0",
- "exchangeAddress": _Constants.null_address,
+ "makerAssetData": (b"\x00") * 20,
+ "takerAssetData": (b"\x00") * 20,
+ "salt": 0,
+ "makerFee": 0,
+ "takerFee": 0,
+ "makerAssetAmount": 0,
+ "takerAssetAmount": 0,
+ "expirationTimeSeconds": 0,
}
-def generate_order_hash_hex(order: Order) -> str:
+def order_to_jsdict(
+ order: Order, exchange_address="0x0000000000000000000000000000000000000000"
+) -> dict:
+ """Convert a Web3-compatible order struct to a JSON-schema-compatible dict.
+
+ More specifically, do explicit decoding for the `bytes`:code: fields.
+
+ >>> import pprint
+ >>> pprint.pprint(order_to_jsdict(
+ ... {
+ ... 'makerAddress': "0x0000000000000000000000000000000000000000",
+ ... 'takerAddress': "0x0000000000000000000000000000000000000000",
+ ... 'feeRecipientAddress':
+ ... "0x0000000000000000000000000000000000000000",
+ ... 'senderAddress': "0x0000000000000000000000000000000000000000",
+ ... 'makerAssetAmount': 1,
+ ... 'takerAssetAmount': 1,
+ ... 'makerFee': 0,
+ ... 'takerFee': 0,
+ ... 'expirationTimeSeconds': 1,
+ ... 'salt': 1,
+ ... 'makerAssetData': (0).to_bytes(1, byteorder='big') * 20,
+ ... 'takerAssetData': (0).to_bytes(1, byteorder='big') * 20,
+ ... },
+ ... ))
+ {'exchangeAddress': '0x0000000000000000000000000000000000000000',
+ 'expirationTimeSeconds': 1,
+ 'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
+ 'makerAddress': '0x0000000000000000000000000000000000000000',
+ 'makerAssetAmount': 1,
+ 'makerAssetData': '0x0000000000000000000000000000000000000000',
+ 'makerFee': 0,
+ 'salt': 1,
+ 'senderAddress': '0x0000000000000000000000000000000000000000',
+ 'takerAddress': '0x0000000000000000000000000000000000000000',
+ 'takerAssetAmount': 1,
+ 'takerAssetData': '0x0000000000000000000000000000000000000000',
+ 'takerFee': 0}
+ """
+ jsdict = cast(Dict, copy(order))
+
+ # encode bytes fields
+ jsdict["makerAssetData"] = "0x" + order["makerAssetData"].hex()
+ jsdict["takerAssetData"] = "0x" + order["takerAssetData"].hex()
+
+ jsdict["exchangeAddress"] = exchange_address
+
+ assert_valid(jsdict, "/orderSchema")
+
+ return jsdict
+
+
+def jsdict_order_to_struct(jsdict: dict) -> Order:
+ r"""Convert a JSON-schema-compatible dict order to a Web3-compatible struct.
+
+ More specifically, do explicit encoding of the `bytes`:code: fields.
+
+ >>> import pprint
+ >>> pprint.pprint(jsdict_order_to_struct(
+ ... {
+ ... 'makerAddress': "0x0000000000000000000000000000000000000000",
+ ... 'takerAddress': "0x0000000000000000000000000000000000000000",
+ ... 'feeRecipientAddress': "0x0000000000000000000000000000000000000000",
+ ... 'senderAddress': "0x0000000000000000000000000000000000000000",
+ ... 'makerAssetAmount': 1000000000000000000,
+ ... 'takerAssetAmount': 1000000000000000000,
+ ... 'makerFee': 0,
+ ... 'takerFee': 0,
+ ... 'expirationTimeSeconds': 12345,
+ ... 'salt': 12345,
+ ... 'makerAssetData': "0x0000000000000000000000000000000000000000",
+ ... 'takerAssetData': "0x0000000000000000000000000000000000000000",
+ ... 'exchangeAddress': "0x0000000000000000000000000000000000000000",
+ ... },
+ ... ))
+ {'expirationTimeSeconds': 12345,
+ 'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
+ 'makerAddress': '0x0000000000000000000000000000000000000000',
+ 'makerAssetAmount': 1000000000000000000,
+ 'makerAssetData': b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00',
+ 'makerFee': 0,
+ 'salt': 12345,
+ 'senderAddress': '0x0000000000000000000000000000000000000000',
+ 'takerAddress': '0x0000000000000000000000000000000000000000',
+ 'takerAssetAmount': 1000000000000000000,
+ 'takerAssetData': b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+ b'\x00\x00\x00\x00\x00\x00\x00\x00',
+ 'takerFee': 0}
+ """ # noqa: E501 (line too long)
+ assert_valid(jsdict, "/orderSchema")
+
+ order = cast(Order, copy(jsdict))
+
+ order["makerAssetData"] = bytes.fromhex(
+ remove_0x_prefix(jsdict["makerAssetData"])
+ )
+ order["takerAssetData"] = bytes.fromhex(
+ remove_0x_prefix(jsdict["takerAssetData"])
+ )
+
+ del order["exchangeAddress"] # type: ignore
+ # silence mypy pending release of
+ # https://github.com/python/mypy/issues/3550
+
+ return order
+
+
+def generate_order_hash_hex(order: Order, exchange_address: str) -> str:
"""Calculate the hash of the given order as a hexadecimal string.
:param order: The order to be hashed. Must conform to `the 0x order JSON schema <https://github.com/0xProject/0x-monorepo/blob/development/packages/json-schemas/schemas/order_schema.json>`_.
:param exchange_address: The address to which the 0x Exchange smart
contract has been deployed.
- :rtype: A string, of ASCII hex digits, representing the order hash.
+ :returns: A string, of ASCII hex digits, representing the order hash.
>>> generate_order_hash_hex(
... {
@@ -167,14 +282,15 @@ def generate_order_hash_hex(order: Order) -> str:
... 'takerFee': "0",
... 'expirationTimeSeconds': "12345",
... 'salt': "12345",
- ... 'makerAssetData': "0x0000000000000000000000000000000000000000",
- ... 'takerAssetData': "0x0000000000000000000000000000000000000000",
- ... 'exchangeAddress': "0x0000000000000000000000000000000000000000",
+ ... 'makerAssetData': (0).to_bytes(1, byteorder='big') * 20,
+ ... 'takerAssetData': (0).to_bytes(1, byteorder='big') * 20,
... },
+ ... exchange_address="0x0000000000000000000000000000000000000000",
... )
'55eaa6ec02f3224d30873577e9ddd069a288c16d6fb407210eecbc501fa76692'
""" # noqa: E501 (line too long)
- assert_valid(order, "/orderSchema")
+ assert_is_address(exchange_address, "exchange_address")
+ assert_valid(order_to_jsdict(order, exchange_address), "/orderSchema")
def pad_20_bytes_to_32(twenty_bytes: bytes):
return bytes(12) + twenty_bytes
@@ -184,7 +300,7 @@ def generate_order_hash_hex(order: Order) -> str:
eip712_domain_struct_hash = keccak(
_Constants.eip712_domain_struct_header
- + pad_20_bytes_to_32(to_bytes(hexstr=order["exchangeAddress"]))
+ + pad_20_bytes_to_32(to_bytes(hexstr=exchange_address))
)
eip712_order_struct_hash = keccak(
@@ -199,8 +315,8 @@ def generate_order_hash_hex(order: Order) -> str:
+ int_to_32_big_endian_bytes(int(order["takerFee"]))
+ int_to_32_big_endian_bytes(int(order["expirationTimeSeconds"]))
+ int_to_32_big_endian_bytes(int(order["salt"]))
- + keccak(to_bytes(hexstr=order["makerAssetData"]))
- + keccak(to_bytes(hexstr=order["takerAssetData"]))
+ + keccak(to_bytes(hexstr=order["makerAssetData"].hex()))
+ + keccak(to_bytes(hexstr=order["takerAssetData"].hex()))
)
return keccak(
@@ -210,20 +326,33 @@ def generate_order_hash_hex(order: Order) -> str:
).hex()
+class OrderInfo(NamedTuple):
+ """A Web3-compatible representation of the Exchange.OrderInfo struct."""
+
+ order_status: str
+ """A `str`:code: describing the order's validity and fillability."""
+
+ order_hash: bytes
+ """A `bytes`:code: object representing the EIP712 hash of the order."""
+
+ order_taker_asset_filled_amount: int
+ """An `int`:code: indicating the amount that has already been filled."""
+
+
def is_valid_signature(
provider: BaseProvider, data: str, signature: str, signer_address: str
) -> Tuple[bool, str]:
"""Check the validity of the supplied signature.
- Check if the supplied ``signature`` corresponds to signing ``data`` with
- the private key corresponding to ``signer_address``.
+ Check if the supplied `signature`:code: corresponds to signing `data`:code:
+ with the private key corresponding to `signer_address`:code:.
:param provider: A Web3 provider able to access the 0x Exchange contract.
:param data: The hex encoded data signed by the supplied signature.
:param signature: The hex encoded signature.
:param signer_address: The hex encoded address that signed the data to
produce the supplied signature.
- :rtype: Tuple consisting of a boolean and a string. Boolean is true if
+ :returns: Tuple consisting of a boolean and a string. Boolean is true if
valid, false otherwise. If false, the string describes the reason.
>>> is_valid_signature(
@@ -241,12 +370,13 @@ def is_valid_signature(
web3_instance = Web3(provider)
# false positive from pylint: disable=no-member
- network_id = web3_instance.net.version
- contract_address = _Constants.network_to_exchange_addr[network_id]
+ contract_address = NETWORK_TO_ADDRESSES[
+ NetworkId(int(web3_instance.net.version))
+ ].exchange
# false positive from pylint: disable=no-member
contract: datatypes.Contract = web3_instance.eth.contract(
address=to_checksum_address(contract_address),
- abi=_Constants.contract_name_to_abi("Exchange"),
+ abi=zero_ex.contract_artifacts.abi_by_name("Exchange"),
)
try:
return (
@@ -337,8 +467,8 @@ def sign_hash(
:param provider: A Web3 provider.
:param signer_address: The address of the signing account.
:param hash_hex: A hex string representing the hash, like that returned
- from `generate_order_hash_hex()`.
- :rtype: A string, of ASCII hex digits, representing the signature.
+ from `generate_order_hash_hex()`:code:.
+ :returns: A string, of ASCII hex digits, representing the signature.
>>> provider = Web3.HTTPProvider("http://127.0.0.1:8545")
>>> sign_hash(
diff --git a/python-packages/order_utils/src/zero_ex/order_utils/asset_data_utils.py b/python-packages/order_utils/src/zero_ex/order_utils/asset_data_utils.py
index fab7479d2..f8e9bc42b 100644
--- a/python-packages/order_utils/src/zero_ex/order_utils/asset_data_utils.py
+++ b/python-packages/order_utils/src/zero_ex/order_utils/asset_data_utils.py
@@ -17,6 +17,8 @@ class ERC20AssetData(TypedDict):
"""Object interface to ERC20 asset data."""
asset_proxy_id: str
+ """asset proxy id"""
+
token_address: str
@@ -32,7 +34,7 @@ def encode_erc20_asset_data(token_address: str) -> str:
"""Encode an ERC20 token address into an asset data string.
:param token_address: the ERC20 token's contract address.
- :rtype: hex encoded asset data string, usable in the makerAssetData or
+ :returns: hex encoded asset data string, usable in the makerAssetData or
takerAssetData fields in a 0x order.
>>> encode_erc20_asset_data('0x1dc4c1cefef38a777b15aa20260a54e584b16c48')
@@ -85,7 +87,7 @@ def encode_erc721_asset_data(token_address: str, token_id: int) -> str:
:param token_address: the ERC721 token's contract address.
:param token_id: the identifier of the asset's instance of the token.
- :rtype: hex encoded asset data string, usable in the makerAssetData or
+ :returns: hex encoded asset data string, usable in the makerAssetData or
takerAssetData fields in a 0x order.
>>> encode_erc721_asset_data('0x1dc4c1cefef38a777b15aa20260a54e584b16c48', 1)
diff --git a/python-packages/order_utils/stubs/jsonschema/__init__.pyi b/python-packages/order_utils/stubs/jsonschema/__init__.pyi
deleted file mode 100644
index 442e2f65e..000000000
--- a/python-packages/order_utils/stubs/jsonschema/__init__.pyi
+++ /dev/null
@@ -1,11 +0,0 @@
-from typing import Any, Dict, Tuple
-
-
-class RefResolver:
- def resolve(self, url: str) -> Tuple[str, Dict]:
- ...
-
-
-class ValidationError(Exception): pass
-
-def validate(instance: Any, schema: Dict, cls=None, *args, **kwargs) -> None: pass
diff --git a/python-packages/order_utils/stubs/jsonschema/exceptions.pyi b/python-packages/order_utils/stubs/jsonschema/exceptions.pyi
deleted file mode 100644
index e69de29bb..000000000
--- a/python-packages/order_utils/stubs/jsonschema/exceptions.pyi
+++ /dev/null
diff --git a/python-packages/order_utils/stubs/web3/__init___BASE_31011.pyi b/python-packages/order_utils/stubs/web3/__init___BASE_31011.pyi
new file mode 100644
index 000000000..fcecc7434
--- /dev/null
+++ b/python-packages/order_utils/stubs/web3/__init___BASE_31011.pyi
@@ -0,0 +1,26 @@
+from typing import Dict, Optional, Union
+
+from web3.utils import datatypes
+
+
+class Web3:
+ class HTTPProvider: ...
+
+ def __init__(self, provider: HTTPProvider) -> None: ...
+
+ @staticmethod
+ def sha3(
+ primitive: Optional[Union[bytes, int, None]] = None,
+ text: Optional[str] = None,
+ hexstr: Optional[str] = None
+ ) -> bytes: ...
+
+ class net:
+ version: str
+ ...
+
+ class eth:
+ @staticmethod
+ def contract(address: str, abi: Dict) -> datatypes.Contract: ...
+ ...
+ ...
diff --git a/python-packages/order_utils/test/test_doctest.py b/python-packages/order_utils/test/test_doctest.py
deleted file mode 100644
index 297f75e75..000000000
--- a/python-packages/order_utils/test/test_doctest.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""Exercise doctests for all of our modules."""
-
-from doctest import testmod
-import pkgutil
-import importlib
-
-import zero_ex
-
-
-def test_all_doctests():
- """Gather zero_ex.* modules and doctest them."""
- for (_, modname, _) in pkgutil.walk_packages(
- path=zero_ex.__path__, prefix="zero_ex."
- ):
- module = importlib.import_module(modname)
- print(module)
- (failure_count, _) = testmod(module)
- assert failure_count == 0
diff --git a/python-packages/order_utils/test/test_generate_order_hash_hex.py b/python-packages/order_utils/test/test_generate_order_hash_hex.py
index 6869a40ed..38b503289 100644
--- a/python-packages/order_utils/test/test_generate_order_hash_hex.py
+++ b/python-packages/order_utils/test/test_generate_order_hash_hex.py
@@ -8,5 +8,7 @@ def test_get_order_hash_hex__empty_order():
expected_hash_hex = (
"faa49b35faeb9197e9c3ba7a52075e6dad19739549f153b77dfcf59408a4b422"
)
- actual_hash_hex = generate_order_hash_hex(make_empty_order())
+ actual_hash_hex = generate_order_hash_hex(
+ make_empty_order(), "0x0000000000000000000000000000000000000000"
+ )
assert actual_hash_hex == expected_hash_hex
diff --git a/python-packages/order_utils/test/test_json_schemas.py b/python-packages/order_utils/test/test_json_schemas.py
deleted file mode 100644
index 51cecbd4f..000000000
--- a/python-packages/order_utils/test/test_json_schemas.py
+++ /dev/null
@@ -1,23 +0,0 @@
-"""Tests of zero_ex.json_schemas"""
-
-
-from zero_ex.order_utils import make_empty_order
-from zero_ex.json_schemas import _LOCAL_RESOLVER, assert_valid
-
-
-def test_assert_valid_caches_resources():
- """Test that the JSON ref resolver in `assert_valid()` caches resources
-
- In order to test the cache we much access the private class of
- `json_schemas` and reset the LRU cache on `_LocalRefResolver`.
- For this to happen, we need to disable errror `W0212`
- on _LOCAL_RESOLVER
- """
- _LOCAL_RESOLVER._remote_cache.cache_clear() # pylint: disable=W0212
-
- assert_valid(make_empty_order(), "/orderSchema")
- cache_info = (
- _LOCAL_RESOLVER._remote_cache.cache_info() # pylint: disable=W0212
- )
- assert cache_info.currsize == 4
- assert cache_info.hits == 10