Migrate Python libraries to v3 (#2284)
* .gitignore migrations/0x_ganache_snapshot * .gitignore new-ish Python contract wrappers These should have been added back when we started generating these wrappers. * rm superfluous contract artifact in Python package All of the contract artifacts were removed from the Python package recently, because now they're copied from the monorepo/packages area as an automated build step. Somehow this one artifact slipped through the cracks. * Eliminate circular dependency This was preventing the Exchange wrapper from ever importing its validator! * Improve output of monorepo-level parallel script - Capture stderr (and have it included in stdout) so that it doesn't leak onto the console for commands that didn't actually fail. - Include all error output in the Exception object (eliminate print statement). * Silence new versions of linters Newer versions care about this stuff. Old versions didn't, and we don't either. * Support Rich Reverts via Web3.py middleware * Fix bug in generated wrappers' bytes handling `bytes.fromhex(bytes.decode('utf-8')` is just plain wrong. It would work for some cases, but is not working when trying to fill orders with the latest Exchange contract. * Migrate to Exchange v3 * Fix typo in DevUtils documentation * Include new contracts in docs * Re-enable Python checks in CI * Accept strings for bytes * Fix CircleCI build artifacts for gen'd python I swear the previous way was working before, but it wasn't working now, so this fixes it. * Accept a provider OR a Web3 object In various places. This allows the caller to install middleware (which in web3.py is installed on a Web3 object, not on a provider) before executing any RPC calls, which is important for the case where one wants to produce signatures locally before submitting to a remote node. * wrapper base: don't assume there are accounts * Eliminate some inline linter directives * make CHANGELOGs be REVERSE chronological * Update CHANGELOG entries and bump version numbers * @0x/contract-addresses: Put addr's in JSON, not TS This allows easier consumption by other languages. (Specifically, it eliminates the overhead of keeping the Python addresses package in sync with the TypeScript one.) * sra_client.py: incl. docker in `./setup.py clean` * sra_client.py: Migrate to protocol v3 Removed script that existed only to exclude runs of sra_client builds (parallel_without_sra_client). Now `parallel` is used by CI, re-including sra_client in CI checks. * abi-gen/templates/Py: clarify if/else logic In response to https://github.com/0xProject/0x-monorepo/pull/2284#discussion_r342200906 * sra_client.py: Update CHANGELOG and bump version * contract_addresses/setup.py: rm unnecessary rm * json_schemas.py: corrections to dev dependencies * In tests against deployment, also run doctests * contract_wrappers example: rm xtra Order attribute Thanks to @steveklebanoff for catching this. https://github.com/0xProject/0x-monorepo/pull/2284#pullrequestreview-312065368
This commit is contained in:
parent
cbe4c4fbf9
commit
e61f23d001
@ -192,14 +192,33 @@ jobs:
|
|||||||
working_directory: ~/repo
|
working_directory: ~/repo
|
||||||
docker:
|
docker:
|
||||||
- image: nikolaik/python-nodejs:python3.7-nodejs8
|
- image: nikolaik/python-nodejs:python3.7-nodejs8
|
||||||
- image: 0xorg/ganache-cli:2.2.2
|
- image: 0xorg/ganache-cli:4.4.0-beta.1
|
||||||
- image: 0xorg/launch-kit-backend:74bcc39
|
|
||||||
environment:
|
environment:
|
||||||
RPC_URL: http://localhost:8545
|
VERSION: 4.4.0-beta.1
|
||||||
|
SNAPSHOT_NAME: 0x_ganache_snapshot-v3-beta
|
||||||
|
- image: 0xorg/mesh:6.0.0-beta-0xv3
|
||||||
|
environment:
|
||||||
|
ETHEREUM_RPC_URL: 'http://localhost:8545'
|
||||||
|
ETHEREUM_NETWORK_ID: '50'
|
||||||
|
ETHEREUM_CHAIN_ID: '1337'
|
||||||
|
USE_BOOTSTRAP_LIST: 'true'
|
||||||
|
VERBOSITY: 3
|
||||||
|
PRIVATE_KEY_PATH: ''
|
||||||
|
BLOCK_POLLING_INTERVAL: '5s'
|
||||||
|
P2P_LISTEN_PORT: '60557'
|
||||||
|
command: |
|
||||||
|
sh -c "waitForGanache () { until printf 'POST /\r\nContent-Length: 26\r\n\r\n{\"method\":\"net_listening\"}' | nc localhost 8545 | grep true; do continue; done }; waitForGanache && ./mesh"
|
||||||
|
- image: 0xorg/launch-kit-backend:v3
|
||||||
|
environment:
|
||||||
|
RPC_URL: 'http://localhost:8545'
|
||||||
NETWORK_ID: 50
|
NETWORK_ID: 50
|
||||||
WHITELIST_ALL_TOKENS: True
|
WHITELIST_ALL_TOKENS: True
|
||||||
|
FEE_RECIPIENT: '0x0000000000000000000000000000000000000001'
|
||||||
|
MAKER_FEE_UNIT_AMOUNT: 0
|
||||||
|
TAKER_FEE_UNIT_AMOUNT: 0
|
||||||
|
MESH_ENDPOINT: 'ws://localhost:60557'
|
||||||
command: |
|
command: |
|
||||||
sh -c "until printf 'POST /\r\nContent-Length: 26\r\n\r\n{\"method\":\"net_listening\"}' | nc localhost 8545 | grep true; do continue; done; node_modules/.bin/forever ts/lib/index.js"
|
sh -c "waitForMesh () { sleep 5; }; waitForMesh && node_modules/.bin/forever ts/lib/index.js"
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
@ -221,8 +240,14 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
command: |
|
command: |
|
||||||
cd python-packages
|
cd python-packages
|
||||||
./parallel_without_sra_client coverage run setup.py test
|
./parallel coverage run setup.py test
|
||||||
./build_docs
|
./build_docs
|
||||||
|
- run:
|
||||||
|
command: |
|
||||||
|
# copy generated wrappers into contract_wrappers/build,
|
||||||
|
# JUST so CircleCI will persist them as build artifacts.
|
||||||
|
cd python-packages/contract_wrappers/src/zero_ex
|
||||||
|
for i in contract_wrappers/[^__]*/; do mkdir -p ../../build/$i; cp $i/__init__.py ../../build/$i; done
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: coverage-python-contract-addresses-{{ .Environment.CIRCLE_SHA1 }}
|
key: coverage-python-contract-addresses-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
paths:
|
paths:
|
||||||
@ -247,8 +272,6 @@ jobs:
|
|||||||
key: coverage-python-sra-client-{{ .Environment.CIRCLE_SHA1 }}
|
key: coverage-python-sra-client-{{ .Environment.CIRCLE_SHA1 }}
|
||||||
paths:
|
paths:
|
||||||
- ~/repo/python-packages/sra_client/.coverage
|
- ~/repo/python-packages/sra_client/.coverage
|
||||||
- store_artifacts:
|
|
||||||
path: ~/repo/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/*/__init__.py
|
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: ~/repo/python-packages/contract_addresses/build
|
path: ~/repo/python-packages/contract_addresses/build
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
@ -426,12 +449,11 @@ workflows:
|
|||||||
- test-exchange-ganache-3.0
|
- test-exchange-ganache-3.0
|
||||||
- test-rest
|
- test-rest
|
||||||
- static-tests
|
- static-tests
|
||||||
# - test-python:
|
- test-python:
|
||||||
# requires:
|
requires:
|
||||||
# - build
|
- build
|
||||||
# - test-rest
|
- static-tests-python:
|
||||||
# - static-tests-python:
|
requires:
|
||||||
# requires:
|
- build
|
||||||
# - test-python
|
|
||||||
# skip python tox run for now, as we don't yet have multiple test environments to support.
|
# skip python tox run for now, as we don't yet have multiple test environments to support.
|
||||||
# - test-rest-python
|
# - test-rest-python
|
||||||
|
10
.gitignore
vendored
10
.gitignore
vendored
@ -130,6 +130,7 @@ contracts/erc1155/generated-wrappers/
|
|||||||
contracts/extensions/generated-wrappers/
|
contracts/extensions/generated-wrappers/
|
||||||
contracts/exchange-forwarder/generated-wrappers/
|
contracts/exchange-forwarder/generated-wrappers/
|
||||||
contracts/dev-utils/generated-wrappers/
|
contracts/dev-utils/generated-wrappers/
|
||||||
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dev_utils/__init__.py
|
||||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_token/__init__.py
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_token/__init__.py
|
||||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/__init__.py
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/__init__.py
|
||||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/asset_proxy_owner/__init__.py
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/asset_proxy_owner/__init__.py
|
||||||
@ -138,6 +139,8 @@ python-packages/contract_wrappers/src/zero_ex/contract_wrappers/coordinator_regi
|
|||||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dummy_erc20_token/__init__.py
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dummy_erc20_token/__init__.py
|
||||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dummy_erc721_token/__init__.py
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dummy_erc721_token/__init__.py
|
||||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dutch_auction/__init__.py
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/dutch_auction/__init__.py
|
||||||
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc1155_mintable/__init__.py
|
||||||
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc1155_proxy/__init__.py
|
||||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_proxy/__init__.py
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_proxy/__init__.py
|
||||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc721_proxy/__init__.py
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc721_proxy/__init__.py
|
||||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc721_token/__init__.py
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc721_token/__init__.py
|
||||||
@ -148,6 +151,7 @@ python-packages/contract_wrappers/src/zero_ex/contract_wrappers/i_validator/__in
|
|||||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/i_wallet/__init__.py
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/i_wallet/__init__.py
|
||||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/multi_asset_proxy/__init__.py
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/multi_asset_proxy/__init__.py
|
||||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/order_validator/__init__.py
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/order_validator/__init__.py
|
||||||
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/static_call_proxy/__init__.py
|
||||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/weth9/__init__.py
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/weth9/__init__.py
|
||||||
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/zrx_token/__init__.py
|
python-packages/contract_wrappers/src/zero_ex/contract_wrappers/zrx_token/__init__.py
|
||||||
|
|
||||||
@ -164,10 +168,14 @@ __pycache__
|
|||||||
python-packages/*/src/*.egg-info
|
python-packages/*/src/*.egg-info
|
||||||
python-packages/*/.coverage
|
python-packages/*/.coverage
|
||||||
|
|
||||||
# python keeps package-local copies of json schemas
|
# python keeps package-local copies of json schemas and contract addresses
|
||||||
python-packages/json_schemas/src/zero_ex/json_schemas/schemas
|
python-packages/json_schemas/src/zero_ex/json_schemas/schemas
|
||||||
|
python-packages/contract_addresses/src/zero_ex/contract_addresses/addresses.json
|
||||||
|
|
||||||
# Doc README copy
|
# Doc README copy
|
||||||
packages/*/docs/README.md
|
packages/*/docs/README.md
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# the snapshot that gets built for migrations sure does have a ton of files
|
||||||
|
packages/migrations/0x_ganache_snapshot*
|
||||||
|
@ -1,4 +1,25 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "4.5.0-beta.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "In Python wrappers, accept string arguments to bytes parameters",
|
||||||
|
"pr": 2284
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "In Python wrappers, support module-local, Web3.py-compatible middleware",
|
||||||
|
"pr": 2284
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "In Python wrappers, allow contracts to be instantiated with EITHER a Web3.py BaseProvider OR a Web3 client object",
|
||||||
|
"pr": 2284
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "In Python wrappers, fix bug with casting some bytes objects using bytes.fromhex()",
|
||||||
|
"pr": 2284
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "4.4.0-beta.0",
|
"version": "4.4.0-beta.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -115,7 +115,7 @@ export const utils = {
|
|||||||
{ regex: '^address$', pyType: 'str' },
|
{ regex: '^address$', pyType: 'str' },
|
||||||
{ regex: '^bool$', pyType: 'bool' },
|
{ regex: '^bool$', pyType: 'bool' },
|
||||||
{ regex: '^u?int\\d*$', pyType: 'int' },
|
{ regex: '^u?int\\d*$', pyType: 'int' },
|
||||||
{ regex: '^bytes\\d*$', pyType: 'bytes' },
|
{ regex: '^bytes\\d*$', pyType: 'Union[bytes, str]' },
|
||||||
];
|
];
|
||||||
for (const regexAndTxType of solTypeRegexToPyType) {
|
for (const regexAndTxType of solTypeRegexToPyType) {
|
||||||
const { regex, pyType } = regexAndTxType;
|
const { regex, pyType } = regexAndTxType;
|
||||||
|
@ -40,6 +40,12 @@ except ImportError:
|
|||||||
"""No-op input validator."""
|
"""No-op input validator."""
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
from .middleware import MIDDLEWARE # type: ignore
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
{{tupleDefinitions ABIString}}
|
{{tupleDefinitions ABIString}}
|
||||||
|
|
||||||
{{#each methods}}
|
{{#each methods}}
|
||||||
@ -59,30 +65,57 @@ class {{contractName}}:
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
validator: {{contractName}}Validator = None,
|
validator: {{contractName}}Validator = None,
|
||||||
):
|
):
|
||||||
"""Get an instance of wrapper for smart contract.
|
"""Get an instance of wrapper for smart contract.
|
||||||
|
|
||||||
:param provider: instance of :class:`web3.providers.base.BaseProvider`
|
:param web3_or_provider: Either an instance of `web3.Web3`:code: or
|
||||||
|
`web3.providers.base.BaseProvider`:code:
|
||||||
:param contract_address: where the contract has been deployed
|
:param contract_address: where the contract has been deployed
|
||||||
:param validator: for validation of method inputs.
|
:param validator: for validation of method inputs.
|
||||||
"""
|
"""
|
||||||
|
# pylint: disable=too-many-statements
|
||||||
|
|
||||||
self.contract_address = contract_address
|
self.contract_address = contract_address
|
||||||
|
|
||||||
if not validator:
|
if not validator:
|
||||||
validator = {{contractName}}Validator(provider, contract_address)
|
validator = {{contractName}}Validator(web3_or_provider, contract_address)
|
||||||
|
|
||||||
self._web3_eth = Web3( # type: ignore # pylint: disable=no-member
|
web3 = None
|
||||||
provider
|
if isinstance(web3_or_provider, BaseProvider):
|
||||||
).eth
|
web3 = Web3(web3_or_provider)
|
||||||
|
elif isinstance(web3_or_provider, Web3):
|
||||||
|
web3 = web3_or_provider
|
||||||
|
else:
|
||||||
|
raise TypeError(
|
||||||
|
"Expected parameter 'web3_or_provider' to be an instance of either"
|
||||||
|
+ " Web3 or BaseProvider"
|
||||||
|
)
|
||||||
|
|
||||||
|
# if any middleware was imported, inject it
|
||||||
|
try:
|
||||||
|
MIDDLEWARE
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
for middleware in MIDDLEWARE:
|
||||||
|
web3.middleware_onion.inject(
|
||||||
|
middleware['function'], layer=middleware['layer'],
|
||||||
|
)
|
||||||
|
except ValueError as value_error:
|
||||||
|
if value_error.args == ("You can't add the same un-named instance twice",):
|
||||||
|
pass
|
||||||
|
|
||||||
|
self._web3_eth = web3.eth
|
||||||
|
|
||||||
{{#if methods}}
|
{{#if methods}}
|
||||||
functions = self._web3_eth.contract(address=to_checksum_address(contract_address), abi={{contractName}}.abi()).functions
|
functions = self._web3_eth.contract(address=to_checksum_address(contract_address), abi={{contractName}}.abi()).functions
|
||||||
|
|
||||||
{{#each methods}}
|
{{#each methods}}
|
||||||
self.{{toPythonIdentifier this.languageSpecificName}} = {{toPythonClassname this.languageSpecificName}}Method(provider, contract_address, functions.{{this.name}}, validator)
|
self.{{toPythonIdentifier this.languageSpecificName}} = {{toPythonClassname this.languageSpecificName}}Method(web3_or_provider, contract_address, functions.{{this.name}}, validator)
|
||||||
|
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
class {{toPythonClassname this.languageSpecificName}}Method(ContractMethod):
|
class {{toPythonClassname this.languageSpecificName}}Method(ContractMethod):
|
||||||
"""Various interfaces to the {{this.name}} method."""
|
"""Various interfaces to the {{this.name}} method."""
|
||||||
|
|
||||||
def __init__(self, provider: BaseProvider, contract_address: str, contract_function: ContractFunction, validator: Validator=None):
|
def __init__(self, web3_or_provider: Union[Web3, BaseProvider], contract_address: str, contract_function: ContractFunction, validator: Validator=None):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
{{#if inputs}}
|
{{#if inputs}}
|
||||||
@ -21,13 +21,6 @@ class {{toPythonClassname this.languageSpecificName}}Method(ContractMethod):
|
|||||||
{{else if (equal type 'uint256')}}
|
{{else if (equal type 'uint256')}}
|
||||||
# safeguard against fractional inputs
|
# safeguard against fractional inputs
|
||||||
{{toPythonIdentifier this.name}} = int({{toPythonIdentifier this.name}})
|
{{toPythonIdentifier this.name}} = int({{toPythonIdentifier this.name}})
|
||||||
{{else if (equal type 'bytes')}}
|
|
||||||
{{toPythonIdentifier this.name}} = bytes.fromhex({{toPythonIdentifier this.name}}.decode("utf-8"))
|
|
||||||
{{else if (equal type 'bytes[]')}}
|
|
||||||
{{toPythonIdentifier this.name}} = [
|
|
||||||
bytes.fromhex({{toPythonIdentifier this.name}}_element.decode("utf-8"))
|
|
||||||
for {{toPythonIdentifier this.name}}_element in {{toPythonIdentifier this.name}}
|
|
||||||
]
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
return ({{> params }})
|
return ({{> params }})
|
||||||
|
@ -40,6 +40,12 @@ except ImportError:
|
|||||||
"""No-op input validator."""
|
"""No-op input validator."""
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
from .middleware import MIDDLEWARE # type: ignore
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Tuple0x246f9407(TypedDict):
|
class Tuple0x246f9407(TypedDict):
|
||||||
"""Python representation of a tuple or struct.
|
"""Python representation of a tuple or struct.
|
||||||
|
|
||||||
@ -94,11 +100,11 @@ class Tuple0xcf8ad995(TypedDict):
|
|||||||
accomplished via `str.encode("utf_8")`:code:
|
accomplished via `str.encode("utf_8")`:code:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
someBytes: bytes
|
someBytes: Union[bytes, str]
|
||||||
|
|
||||||
anInteger: int
|
anInteger: int
|
||||||
|
|
||||||
aDynamicArrayOfBytes: List[bytes]
|
aDynamicArrayOfBytes: List[Union[bytes, str]]
|
||||||
|
|
||||||
aString: str
|
aString: str
|
||||||
|
|
||||||
@ -142,7 +148,7 @@ class Tuple0xf95128ef(TypedDict):
|
|||||||
|
|
||||||
foo: int
|
foo: int
|
||||||
|
|
||||||
bar: bytes
|
bar: Union[bytes, str]
|
||||||
|
|
||||||
car: str
|
car: str
|
||||||
|
|
||||||
@ -165,9 +171,9 @@ class Tuple0xa057bf41(TypedDict):
|
|||||||
|
|
||||||
input: Tuple0xf95128ef
|
input: Tuple0xf95128ef
|
||||||
|
|
||||||
lorem: bytes
|
lorem: Union[bytes, str]
|
||||||
|
|
||||||
ipsum: bytes
|
ipsum: Union[bytes, str]
|
||||||
|
|
||||||
dolor: str
|
dolor: str
|
||||||
|
|
||||||
@ -177,13 +183,13 @@ class SimpleRequireMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(self, tx_params: Optional[TxParams] = None) -> None:
|
def call(self, tx_params: Optional[TxParams] = None) -> None:
|
||||||
@ -217,27 +223,26 @@ class AcceptsAnArrayOfBytesMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(self, a: List[bytes]):
|
def validate_and_normalize_inputs(self, a: List[Union[bytes, str]]):
|
||||||
"""Validate the inputs to the acceptsAnArrayOfBytes method."""
|
"""Validate the inputs to the acceptsAnArrayOfBytes method."""
|
||||||
self.validator.assert_valid(
|
self.validator.assert_valid(
|
||||||
method_name="acceptsAnArrayOfBytes",
|
method_name="acceptsAnArrayOfBytes",
|
||||||
parameter_name="a",
|
parameter_name="a",
|
||||||
argument_value=a,
|
argument_value=a,
|
||||||
)
|
)
|
||||||
a = [bytes.fromhex(a_element.decode("utf-8")) for a_element in a]
|
|
||||||
return a
|
return a
|
||||||
|
|
||||||
def call(
|
def call(
|
||||||
self, a: List[bytes], tx_params: Optional[TxParams] = None
|
self, a: List[Union[bytes, str]], tx_params: Optional[TxParams] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Execute underlying contract method via eth_call.
|
"""Execute underlying contract method via eth_call.
|
||||||
|
|
||||||
@ -252,7 +257,7 @@ class AcceptsAnArrayOfBytesMethod(ContractMethod):
|
|||||||
return self.underlying_method(a).call(tx_params.as_dict())
|
return self.underlying_method(a).call(tx_params.as_dict())
|
||||||
|
|
||||||
def send_transaction(
|
def send_transaction(
|
||||||
self, a: List[bytes], tx_params: Optional[TxParams] = None
|
self, a: List[Union[bytes, str]], tx_params: Optional[TxParams] = None
|
||||||
) -> Union[HexBytes, bytes]:
|
) -> Union[HexBytes, bytes]:
|
||||||
"""Execute underlying contract method via eth_sendTransaction.
|
"""Execute underlying contract method via eth_sendTransaction.
|
||||||
|
|
||||||
@ -267,7 +272,7 @@ class AcceptsAnArrayOfBytesMethod(ContractMethod):
|
|||||||
return self.underlying_method(a).transact(tx_params.as_dict())
|
return self.underlying_method(a).transact(tx_params.as_dict())
|
||||||
|
|
||||||
def estimate_gas(
|
def estimate_gas(
|
||||||
self, a: List[bytes], tx_params: Optional[TxParams] = None
|
self, a: List[Union[bytes, str]], tx_params: Optional[TxParams] = None
|
||||||
) -> int:
|
) -> int:
|
||||||
"""Estimate gas consumption of method call."""
|
"""Estimate gas consumption of method call."""
|
||||||
(a) = self.validate_and_normalize_inputs(a)
|
(a) = self.validate_and_normalize_inputs(a)
|
||||||
@ -280,13 +285,13 @@ class SimpleInputSimpleOutputMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(self, index_0: int):
|
def validate_and_normalize_inputs(self, index_0: int):
|
||||||
@ -340,13 +345,13 @@ class WithdrawMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(self, wad: int):
|
def validate_and_normalize_inputs(self, wad: int):
|
||||||
@ -395,17 +400,17 @@ class MultiInputMultiOutputMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(
|
def validate_and_normalize_inputs(
|
||||||
self, index_0: int, index_1: bytes, index_2: str
|
self, index_0: int, index_1: Union[bytes, str], index_2: str
|
||||||
):
|
):
|
||||||
"""Validate the inputs to the multiInputMultiOutput method."""
|
"""Validate the inputs to the multiInputMultiOutput method."""
|
||||||
self.validator.assert_valid(
|
self.validator.assert_valid(
|
||||||
@ -420,7 +425,6 @@ class MultiInputMultiOutputMethod(ContractMethod):
|
|||||||
parameter_name="index_1",
|
parameter_name="index_1",
|
||||||
argument_value=index_1,
|
argument_value=index_1,
|
||||||
)
|
)
|
||||||
index_1 = bytes.fromhex(index_1.decode("utf-8"))
|
|
||||||
self.validator.assert_valid(
|
self.validator.assert_valid(
|
||||||
method_name="multiInputMultiOutput",
|
method_name="multiInputMultiOutput",
|
||||||
parameter_name="index_2",
|
parameter_name="index_2",
|
||||||
@ -431,10 +435,10 @@ class MultiInputMultiOutputMethod(ContractMethod):
|
|||||||
def call(
|
def call(
|
||||||
self,
|
self,
|
||||||
index_0: int,
|
index_0: int,
|
||||||
index_1: bytes,
|
index_1: Union[bytes, str],
|
||||||
index_2: str,
|
index_2: str,
|
||||||
tx_params: Optional[TxParams] = None,
|
tx_params: Optional[TxParams] = None,
|
||||||
) -> Tuple[bytes, bytes, str]:
|
) -> Tuple[Union[bytes, str], Union[bytes, str], str]:
|
||||||
"""Execute underlying contract method via eth_call.
|
"""Execute underlying contract method via eth_call.
|
||||||
|
|
||||||
Tests decoding when the input and output are complex and have more than
|
Tests decoding when the input and output are complex and have more than
|
||||||
@ -454,7 +458,7 @@ class MultiInputMultiOutputMethod(ContractMethod):
|
|||||||
def send_transaction(
|
def send_transaction(
|
||||||
self,
|
self,
|
||||||
index_0: int,
|
index_0: int,
|
||||||
index_1: bytes,
|
index_1: Union[bytes, str],
|
||||||
index_2: str,
|
index_2: str,
|
||||||
tx_params: Optional[TxParams] = None,
|
tx_params: Optional[TxParams] = None,
|
||||||
) -> Union[HexBytes, bytes]:
|
) -> Union[HexBytes, bytes]:
|
||||||
@ -477,7 +481,7 @@ class MultiInputMultiOutputMethod(ContractMethod):
|
|||||||
def estimate_gas(
|
def estimate_gas(
|
||||||
self,
|
self,
|
||||||
index_0: int,
|
index_0: int,
|
||||||
index_1: bytes,
|
index_1: Union[bytes, str],
|
||||||
index_2: str,
|
index_2: str,
|
||||||
tx_params: Optional[TxParams] = None,
|
tx_params: Optional[TxParams] = None,
|
||||||
) -> int:
|
) -> int:
|
||||||
@ -496,17 +500,21 @@ class EcrecoverFnMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(
|
def validate_and_normalize_inputs(
|
||||||
self, _hash: bytes, v: int, r: bytes, s: bytes
|
self,
|
||||||
|
_hash: Union[bytes, str],
|
||||||
|
v: int,
|
||||||
|
r: Union[bytes, str],
|
||||||
|
s: Union[bytes, str],
|
||||||
):
|
):
|
||||||
"""Validate the inputs to the ecrecoverFn method."""
|
"""Validate the inputs to the ecrecoverFn method."""
|
||||||
self.validator.assert_valid(
|
self.validator.assert_valid(
|
||||||
@ -527,10 +535,10 @@ class EcrecoverFnMethod(ContractMethod):
|
|||||||
|
|
||||||
def call(
|
def call(
|
||||||
self,
|
self,
|
||||||
_hash: bytes,
|
_hash: Union[bytes, str],
|
||||||
v: int,
|
v: int,
|
||||||
r: bytes,
|
r: Union[bytes, str],
|
||||||
s: bytes,
|
s: Union[bytes, str],
|
||||||
tx_params: Optional[TxParams] = None,
|
tx_params: Optional[TxParams] = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Execute underlying contract method via eth_call.
|
"""Execute underlying contract method via eth_call.
|
||||||
@ -555,10 +563,10 @@ class EcrecoverFnMethod(ContractMethod):
|
|||||||
|
|
||||||
def send_transaction(
|
def send_transaction(
|
||||||
self,
|
self,
|
||||||
_hash: bytes,
|
_hash: Union[bytes, str],
|
||||||
v: int,
|
v: int,
|
||||||
r: bytes,
|
r: Union[bytes, str],
|
||||||
s: bytes,
|
s: Union[bytes, str],
|
||||||
tx_params: Optional[TxParams] = None,
|
tx_params: Optional[TxParams] = None,
|
||||||
) -> Union[HexBytes, bytes]:
|
) -> Union[HexBytes, bytes]:
|
||||||
"""Execute underlying contract method via eth_sendTransaction.
|
"""Execute underlying contract method via eth_sendTransaction.
|
||||||
@ -585,10 +593,10 @@ class EcrecoverFnMethod(ContractMethod):
|
|||||||
|
|
||||||
def estimate_gas(
|
def estimate_gas(
|
||||||
self,
|
self,
|
||||||
_hash: bytes,
|
_hash: Union[bytes, str],
|
||||||
v: int,
|
v: int,
|
||||||
r: bytes,
|
r: Union[bytes, str],
|
||||||
s: bytes,
|
s: Union[bytes, str],
|
||||||
tx_params: Optional[TxParams] = None,
|
tx_params: Optional[TxParams] = None,
|
||||||
) -> int:
|
) -> int:
|
||||||
"""Estimate gas consumption of method call."""
|
"""Estimate gas consumption of method call."""
|
||||||
@ -604,24 +612,25 @@ class AcceptsBytesMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(self, a: bytes):
|
def validate_and_normalize_inputs(self, a: Union[bytes, str]):
|
||||||
"""Validate the inputs to the acceptsBytes method."""
|
"""Validate the inputs to the acceptsBytes method."""
|
||||||
self.validator.assert_valid(
|
self.validator.assert_valid(
|
||||||
method_name="acceptsBytes", parameter_name="a", argument_value=a
|
method_name="acceptsBytes", parameter_name="a", argument_value=a
|
||||||
)
|
)
|
||||||
a = bytes.fromhex(a.decode("utf-8"))
|
|
||||||
return a
|
return a
|
||||||
|
|
||||||
def call(self, a: bytes, tx_params: Optional[TxParams] = None) -> None:
|
def call(
|
||||||
|
self, a: Union[bytes, str], tx_params: Optional[TxParams] = None
|
||||||
|
) -> None:
|
||||||
"""Execute underlying contract method via eth_call.
|
"""Execute underlying contract method via eth_call.
|
||||||
|
|
||||||
:param tx_params: transaction parameters
|
:param tx_params: transaction parameters
|
||||||
@ -632,7 +641,7 @@ class AcceptsBytesMethod(ContractMethod):
|
|||||||
return self.underlying_method(a).call(tx_params.as_dict())
|
return self.underlying_method(a).call(tx_params.as_dict())
|
||||||
|
|
||||||
def send_transaction(
|
def send_transaction(
|
||||||
self, a: bytes, tx_params: Optional[TxParams] = None
|
self, a: Union[bytes, str], tx_params: Optional[TxParams] = None
|
||||||
) -> Union[HexBytes, bytes]:
|
) -> Union[HexBytes, bytes]:
|
||||||
"""Execute underlying contract method via eth_sendTransaction.
|
"""Execute underlying contract method via eth_sendTransaction.
|
||||||
|
|
||||||
@ -644,7 +653,7 @@ class AcceptsBytesMethod(ContractMethod):
|
|||||||
return self.underlying_method(a).transact(tx_params.as_dict())
|
return self.underlying_method(a).transact(tx_params.as_dict())
|
||||||
|
|
||||||
def estimate_gas(
|
def estimate_gas(
|
||||||
self, a: bytes, tx_params: Optional[TxParams] = None
|
self, a: Union[bytes, str], tx_params: Optional[TxParams] = None
|
||||||
) -> int:
|
) -> int:
|
||||||
"""Estimate gas consumption of method call."""
|
"""Estimate gas consumption of method call."""
|
||||||
(a) = self.validate_and_normalize_inputs(a)
|
(a) = self.validate_and_normalize_inputs(a)
|
||||||
@ -657,13 +666,13 @@ class NoInputSimpleOutputMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(self, tx_params: Optional[TxParams] = None) -> int:
|
def call(self, tx_params: Optional[TxParams] = None) -> int:
|
||||||
@ -701,13 +710,13 @@ class RevertWithConstantMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(self, tx_params: Optional[TxParams] = None) -> None:
|
def call(self, tx_params: Optional[TxParams] = None) -> None:
|
||||||
@ -741,13 +750,13 @@ class SimpleRevertMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(self, tx_params: Optional[TxParams] = None) -> None:
|
def call(self, tx_params: Optional[TxParams] = None) -> None:
|
||||||
@ -783,13 +792,13 @@ class MethodUsingNestedStructWithInnerStructNotUsedElsewhereMethod(
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(self, tx_params: Optional[TxParams] = None) -> Tuple0x1b9da225:
|
def call(self, tx_params: Optional[TxParams] = None) -> Tuple0x1b9da225:
|
||||||
@ -823,13 +832,13 @@ class NestedStructOutputMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(self, tx_params: Optional[TxParams] = None) -> Tuple0xc9bdd2d5:
|
def call(self, tx_params: Optional[TxParams] = None) -> Tuple0xc9bdd2d5:
|
||||||
@ -863,13 +872,13 @@ class RequireWithConstantMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(self, tx_params: Optional[TxParams] = None) -> None:
|
def call(self, tx_params: Optional[TxParams] = None) -> None:
|
||||||
@ -903,13 +912,13 @@ class WithAddressInputMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(
|
def validate_and_normalize_inputs(
|
||||||
@ -1011,13 +1020,13 @@ class StructInputMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(self, s: Tuple0xcf8ad995):
|
def validate_and_normalize_inputs(self, s: Tuple0xcf8ad995):
|
||||||
@ -1065,13 +1074,13 @@ class NonPureMethodMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(
|
def call(
|
||||||
@ -1106,13 +1115,13 @@ class ComplexInputComplexOutputMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(self, complex_input: Tuple0xf95128ef):
|
def validate_and_normalize_inputs(self, complex_input: Tuple0xf95128ef):
|
||||||
@ -1176,13 +1185,13 @@ class NoInputNoOutputMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(self, tx_params: Optional[TxParams] = None) -> None:
|
def call(self, tx_params: Optional[TxParams] = None) -> None:
|
||||||
@ -1220,13 +1229,13 @@ class SimplePureFunctionWithInputMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(self, x: int):
|
def validate_and_normalize_inputs(self, x: int):
|
||||||
@ -1276,13 +1285,13 @@ class NonPureMethodThatReturnsNothingMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(
|
def call(
|
||||||
@ -1317,13 +1326,13 @@ class SimplePureFunctionMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(self, tx_params: Optional[TxParams] = None) -> int:
|
def call(self, tx_params: Optional[TxParams] = None) -> int:
|
||||||
@ -1357,13 +1366,13 @@ class NestedStructInputMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(self, n: Tuple0xc9bdd2d5):
|
def validate_and_normalize_inputs(self, n: Tuple0xc9bdd2d5):
|
||||||
@ -1413,13 +1422,13 @@ class MethodReturningMultipleValuesMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(self, tx_params: Optional[TxParams] = None) -> Tuple[int, str]:
|
def call(self, tx_params: Optional[TxParams] = None) -> Tuple[int, str]:
|
||||||
@ -1453,13 +1462,13 @@ class MethodReturningArrayOfStructsMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(
|
def call(
|
||||||
@ -1495,13 +1504,13 @@ class EmitSimpleEventMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(
|
def call(
|
||||||
@ -1536,13 +1545,13 @@ class StructOutputMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(self, tx_params: Optional[TxParams] = None) -> Tuple0xcf8ad995:
|
def call(self, tx_params: Optional[TxParams] = None) -> Tuple0xcf8ad995:
|
||||||
@ -1580,13 +1589,13 @@ class PureFunctionWithConstantMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def call(self, tx_params: Optional[TxParams] = None) -> int:
|
def call(self, tx_params: Optional[TxParams] = None) -> int:
|
||||||
@ -1620,13 +1629,13 @@ class SimpleInputNoOutputMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(self, index_0: int):
|
def validate_and_normalize_inputs(self, index_0: int):
|
||||||
@ -1680,13 +1689,13 @@ class OverloadedMethod2Method(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(self, a: str):
|
def validate_and_normalize_inputs(self, a: str):
|
||||||
@ -1734,13 +1743,13 @@ class OverloadedMethod1Method(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(self, a: int):
|
def validate_and_normalize_inputs(self, a: int):
|
||||||
@ -1943,24 +1952,55 @@ class AbiGenDummy:
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
validator: AbiGenDummyValidator = None,
|
validator: AbiGenDummyValidator = None,
|
||||||
):
|
):
|
||||||
"""Get an instance of wrapper for smart contract.
|
"""Get an instance of wrapper for smart contract.
|
||||||
|
|
||||||
:param provider: instance of :class:`web3.providers.base.BaseProvider`
|
:param web3_or_provider: Either an instance of `web3.Web3`:code: or
|
||||||
|
`web3.providers.base.BaseProvider`:code:
|
||||||
:param contract_address: where the contract has been deployed
|
:param contract_address: where the contract has been deployed
|
||||||
:param validator: for validation of method inputs.
|
:param validator: for validation of method inputs.
|
||||||
"""
|
"""
|
||||||
|
# pylint: disable=too-many-statements
|
||||||
|
|
||||||
self.contract_address = contract_address
|
self.contract_address = contract_address
|
||||||
|
|
||||||
if not validator:
|
if not validator:
|
||||||
validator = AbiGenDummyValidator(provider, contract_address)
|
validator = AbiGenDummyValidator(
|
||||||
|
web3_or_provider, contract_address
|
||||||
|
)
|
||||||
|
|
||||||
self._web3_eth = Web3( # type: ignore # pylint: disable=no-member
|
web3 = None
|
||||||
provider
|
if isinstance(web3_or_provider, BaseProvider):
|
||||||
).eth
|
web3 = Web3(web3_or_provider)
|
||||||
|
elif isinstance(web3_or_provider, Web3):
|
||||||
|
web3 = web3_or_provider
|
||||||
|
else:
|
||||||
|
raise TypeError(
|
||||||
|
"Expected parameter 'web3_or_provider' to be an instance of either"
|
||||||
|
+ " Web3 or BaseProvider"
|
||||||
|
)
|
||||||
|
|
||||||
|
# if any middleware was imported, inject it
|
||||||
|
try:
|
||||||
|
MIDDLEWARE
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
for middleware in MIDDLEWARE:
|
||||||
|
web3.middleware_onion.inject(
|
||||||
|
middleware["function"], layer=middleware["layer"]
|
||||||
|
)
|
||||||
|
except ValueError as value_error:
|
||||||
|
if value_error.args == (
|
||||||
|
"You can't add the same un-named instance twice",
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
self._web3_eth = web3.eth
|
||||||
|
|
||||||
functions = self._web3_eth.contract(
|
functions = self._web3_eth.contract(
|
||||||
address=to_checksum_address(contract_address),
|
address=to_checksum_address(contract_address),
|
||||||
@ -1968,162 +2008,210 @@ class AbiGenDummy:
|
|||||||
).functions
|
).functions
|
||||||
|
|
||||||
self.simple_require = SimpleRequireMethod(
|
self.simple_require = SimpleRequireMethod(
|
||||||
provider, contract_address, functions.simpleRequire, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.simpleRequire,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.accepts_an_array_of_bytes = AcceptsAnArrayOfBytesMethod(
|
self.accepts_an_array_of_bytes = AcceptsAnArrayOfBytesMethod(
|
||||||
provider,
|
web3_or_provider,
|
||||||
contract_address,
|
contract_address,
|
||||||
functions.acceptsAnArrayOfBytes,
|
functions.acceptsAnArrayOfBytes,
|
||||||
validator,
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.simple_input_simple_output = SimpleInputSimpleOutputMethod(
|
self.simple_input_simple_output = SimpleInputSimpleOutputMethod(
|
||||||
provider,
|
web3_or_provider,
|
||||||
contract_address,
|
contract_address,
|
||||||
functions.simpleInputSimpleOutput,
|
functions.simpleInputSimpleOutput,
|
||||||
validator,
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.withdraw = WithdrawMethod(
|
self.withdraw = WithdrawMethod(
|
||||||
provider, contract_address, functions.withdraw, validator
|
web3_or_provider, contract_address, functions.withdraw, validator
|
||||||
)
|
)
|
||||||
|
|
||||||
self.multi_input_multi_output = MultiInputMultiOutputMethod(
|
self.multi_input_multi_output = MultiInputMultiOutputMethod(
|
||||||
provider,
|
web3_or_provider,
|
||||||
contract_address,
|
contract_address,
|
||||||
functions.multiInputMultiOutput,
|
functions.multiInputMultiOutput,
|
||||||
validator,
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.ecrecover_fn = EcrecoverFnMethod(
|
self.ecrecover_fn = EcrecoverFnMethod(
|
||||||
provider, contract_address, functions.ecrecoverFn, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.ecrecoverFn,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.accepts_bytes = AcceptsBytesMethod(
|
self.accepts_bytes = AcceptsBytesMethod(
|
||||||
provider, contract_address, functions.acceptsBytes, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.acceptsBytes,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.no_input_simple_output = NoInputSimpleOutputMethod(
|
self.no_input_simple_output = NoInputSimpleOutputMethod(
|
||||||
provider,
|
web3_or_provider,
|
||||||
contract_address,
|
contract_address,
|
||||||
functions.noInputSimpleOutput,
|
functions.noInputSimpleOutput,
|
||||||
validator,
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.revert_with_constant = RevertWithConstantMethod(
|
self.revert_with_constant = RevertWithConstantMethod(
|
||||||
provider, contract_address, functions.revertWithConstant, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.revertWithConstant,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.simple_revert = SimpleRevertMethod(
|
self.simple_revert = SimpleRevertMethod(
|
||||||
provider, contract_address, functions.simpleRevert, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.simpleRevert,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.method_using_nested_struct_with_inner_struct_not_used_elsewhere = MethodUsingNestedStructWithInnerStructNotUsedElsewhereMethod(
|
self.method_using_nested_struct_with_inner_struct_not_used_elsewhere = MethodUsingNestedStructWithInnerStructNotUsedElsewhereMethod(
|
||||||
provider,
|
web3_or_provider,
|
||||||
contract_address,
|
contract_address,
|
||||||
functions.methodUsingNestedStructWithInnerStructNotUsedElsewhere,
|
functions.methodUsingNestedStructWithInnerStructNotUsedElsewhere,
|
||||||
validator,
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.nested_struct_output = NestedStructOutputMethod(
|
self.nested_struct_output = NestedStructOutputMethod(
|
||||||
provider, contract_address, functions.nestedStructOutput, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.nestedStructOutput,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.require_with_constant = RequireWithConstantMethod(
|
self.require_with_constant = RequireWithConstantMethod(
|
||||||
provider,
|
web3_or_provider,
|
||||||
contract_address,
|
contract_address,
|
||||||
functions.requireWithConstant,
|
functions.requireWithConstant,
|
||||||
validator,
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.with_address_input = WithAddressInputMethod(
|
self.with_address_input = WithAddressInputMethod(
|
||||||
provider, contract_address, functions.withAddressInput, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.withAddressInput,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.struct_input = StructInputMethod(
|
self.struct_input = StructInputMethod(
|
||||||
provider, contract_address, functions.structInput, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.structInput,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.non_pure_method = NonPureMethodMethod(
|
self.non_pure_method = NonPureMethodMethod(
|
||||||
provider, contract_address, functions.nonPureMethod, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.nonPureMethod,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.complex_input_complex_output = ComplexInputComplexOutputMethod(
|
self.complex_input_complex_output = ComplexInputComplexOutputMethod(
|
||||||
provider,
|
web3_or_provider,
|
||||||
contract_address,
|
contract_address,
|
||||||
functions.complexInputComplexOutput,
|
functions.complexInputComplexOutput,
|
||||||
validator,
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.no_input_no_output = NoInputNoOutputMethod(
|
self.no_input_no_output = NoInputNoOutputMethod(
|
||||||
provider, contract_address, functions.noInputNoOutput, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.noInputNoOutput,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.simple_pure_function_with_input = SimplePureFunctionWithInputMethod(
|
self.simple_pure_function_with_input = SimplePureFunctionWithInputMethod(
|
||||||
provider,
|
web3_or_provider,
|
||||||
contract_address,
|
contract_address,
|
||||||
functions.simplePureFunctionWithInput,
|
functions.simplePureFunctionWithInput,
|
||||||
validator,
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.non_pure_method_that_returns_nothing = NonPureMethodThatReturnsNothingMethod(
|
self.non_pure_method_that_returns_nothing = NonPureMethodThatReturnsNothingMethod(
|
||||||
provider,
|
web3_or_provider,
|
||||||
contract_address,
|
contract_address,
|
||||||
functions.nonPureMethodThatReturnsNothing,
|
functions.nonPureMethodThatReturnsNothing,
|
||||||
validator,
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.simple_pure_function = SimplePureFunctionMethod(
|
self.simple_pure_function = SimplePureFunctionMethod(
|
||||||
provider, contract_address, functions.simplePureFunction, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.simplePureFunction,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.nested_struct_input = NestedStructInputMethod(
|
self.nested_struct_input = NestedStructInputMethod(
|
||||||
provider, contract_address, functions.nestedStructInput, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.nestedStructInput,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.method_returning_multiple_values = MethodReturningMultipleValuesMethod(
|
self.method_returning_multiple_values = MethodReturningMultipleValuesMethod(
|
||||||
provider,
|
web3_or_provider,
|
||||||
contract_address,
|
contract_address,
|
||||||
functions.methodReturningMultipleValues,
|
functions.methodReturningMultipleValues,
|
||||||
validator,
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.method_returning_array_of_structs = MethodReturningArrayOfStructsMethod(
|
self.method_returning_array_of_structs = MethodReturningArrayOfStructsMethod(
|
||||||
provider,
|
web3_or_provider,
|
||||||
contract_address,
|
contract_address,
|
||||||
functions.methodReturningArrayOfStructs,
|
functions.methodReturningArrayOfStructs,
|
||||||
validator,
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.emit_simple_event = EmitSimpleEventMethod(
|
self.emit_simple_event = EmitSimpleEventMethod(
|
||||||
provider, contract_address, functions.emitSimpleEvent, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.emitSimpleEvent,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.struct_output = StructOutputMethod(
|
self.struct_output = StructOutputMethod(
|
||||||
provider, contract_address, functions.structOutput, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.structOutput,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.pure_function_with_constant = PureFunctionWithConstantMethod(
|
self.pure_function_with_constant = PureFunctionWithConstantMethod(
|
||||||
provider,
|
web3_or_provider,
|
||||||
contract_address,
|
contract_address,
|
||||||
functions.pureFunctionWithConstant,
|
functions.pureFunctionWithConstant,
|
||||||
validator,
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.simple_input_no_output = SimpleInputNoOutputMethod(
|
self.simple_input_no_output = SimpleInputNoOutputMethod(
|
||||||
provider,
|
web3_or_provider,
|
||||||
contract_address,
|
contract_address,
|
||||||
functions.simpleInputNoOutput,
|
functions.simpleInputNoOutput,
|
||||||
validator,
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.overloaded_method2 = OverloadedMethod2Method(
|
self.overloaded_method2 = OverloadedMethod2Method(
|
||||||
provider, contract_address, functions.overloadedMethod, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.overloadedMethod,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.overloaded_method1 = OverloadedMethod1Method(
|
self.overloaded_method1 = OverloadedMethod1Method(
|
||||||
provider, contract_address, functions.overloadedMethod, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.overloadedMethod,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_withdrawal_event(
|
def get_withdrawal_event(
|
||||||
|
@ -40,30 +40,65 @@ except ImportError:
|
|||||||
"""No-op input validator."""
|
"""No-op input validator."""
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
from .middleware import MIDDLEWARE # type: ignore
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-many-public-methods,too-many-instance-attributes
|
# pylint: disable=too-many-public-methods,too-many-instance-attributes
|
||||||
class LibDummy:
|
class LibDummy:
|
||||||
"""Wrapper class for LibDummy Solidity contract."""
|
"""Wrapper class for LibDummy Solidity contract."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
validator: LibDummyValidator = None,
|
validator: LibDummyValidator = None,
|
||||||
):
|
):
|
||||||
"""Get an instance of wrapper for smart contract.
|
"""Get an instance of wrapper for smart contract.
|
||||||
|
|
||||||
:param provider: instance of :class:`web3.providers.base.BaseProvider`
|
:param web3_or_provider: Either an instance of `web3.Web3`:code: or
|
||||||
|
`web3.providers.base.BaseProvider`:code:
|
||||||
:param contract_address: where the contract has been deployed
|
:param contract_address: where the contract has been deployed
|
||||||
:param validator: for validation of method inputs.
|
:param validator: for validation of method inputs.
|
||||||
"""
|
"""
|
||||||
|
# pylint: disable=too-many-statements
|
||||||
|
|
||||||
self.contract_address = contract_address
|
self.contract_address = contract_address
|
||||||
|
|
||||||
if not validator:
|
if not validator:
|
||||||
validator = LibDummyValidator(provider, contract_address)
|
validator = LibDummyValidator(web3_or_provider, contract_address)
|
||||||
|
|
||||||
self._web3_eth = Web3( # type: ignore # pylint: disable=no-member
|
web3 = None
|
||||||
provider
|
if isinstance(web3_or_provider, BaseProvider):
|
||||||
).eth
|
web3 = Web3(web3_or_provider)
|
||||||
|
elif isinstance(web3_or_provider, Web3):
|
||||||
|
web3 = web3_or_provider
|
||||||
|
else:
|
||||||
|
raise TypeError(
|
||||||
|
"Expected parameter 'web3_or_provider' to be an instance of either"
|
||||||
|
+ " Web3 or BaseProvider"
|
||||||
|
)
|
||||||
|
|
||||||
|
# if any middleware was imported, inject it
|
||||||
|
try:
|
||||||
|
MIDDLEWARE
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
for middleware in MIDDLEWARE:
|
||||||
|
web3.middleware_onion.inject(
|
||||||
|
middleware["function"], layer=middleware["layer"]
|
||||||
|
)
|
||||||
|
except ValueError as value_error:
|
||||||
|
if value_error.args == (
|
||||||
|
"You can't add the same un-named instance twice",
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
self._web3_eth = web3.eth
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def abi():
|
def abi():
|
||||||
|
@ -40,18 +40,24 @@ except ImportError:
|
|||||||
"""No-op input validator."""
|
"""No-op input validator."""
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
from .middleware import MIDDLEWARE # type: ignore
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class PublicAddConstantMethod(ContractMethod):
|
class PublicAddConstantMethod(ContractMethod):
|
||||||
"""Various interfaces to the publicAddConstant method."""
|
"""Various interfaces to the publicAddConstant method."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(self, x: int):
|
def validate_and_normalize_inputs(self, x: int):
|
||||||
@ -101,13 +107,13 @@ class PublicAddOneMethod(ContractMethod):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
contract_function: ContractFunction,
|
contract_function: ContractFunction,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
"""Persist instance data."""
|
"""Persist instance data."""
|
||||||
super().__init__(provider, contract_address, validator)
|
super().__init__(web3_or_provider, contract_address, validator)
|
||||||
self.underlying_method = contract_function
|
self.underlying_method = contract_function
|
||||||
|
|
||||||
def validate_and_normalize_inputs(self, x: int):
|
def validate_and_normalize_inputs(self, x: int):
|
||||||
@ -166,24 +172,55 @@ class TestLibDummy:
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
validator: TestLibDummyValidator = None,
|
validator: TestLibDummyValidator = None,
|
||||||
):
|
):
|
||||||
"""Get an instance of wrapper for smart contract.
|
"""Get an instance of wrapper for smart contract.
|
||||||
|
|
||||||
:param provider: instance of :class:`web3.providers.base.BaseProvider`
|
:param web3_or_provider: Either an instance of `web3.Web3`:code: or
|
||||||
|
`web3.providers.base.BaseProvider`:code:
|
||||||
:param contract_address: where the contract has been deployed
|
:param contract_address: where the contract has been deployed
|
||||||
:param validator: for validation of method inputs.
|
:param validator: for validation of method inputs.
|
||||||
"""
|
"""
|
||||||
|
# pylint: disable=too-many-statements
|
||||||
|
|
||||||
self.contract_address = contract_address
|
self.contract_address = contract_address
|
||||||
|
|
||||||
if not validator:
|
if not validator:
|
||||||
validator = TestLibDummyValidator(provider, contract_address)
|
validator = TestLibDummyValidator(
|
||||||
|
web3_or_provider, contract_address
|
||||||
|
)
|
||||||
|
|
||||||
self._web3_eth = Web3( # type: ignore # pylint: disable=no-member
|
web3 = None
|
||||||
provider
|
if isinstance(web3_or_provider, BaseProvider):
|
||||||
).eth
|
web3 = Web3(web3_or_provider)
|
||||||
|
elif isinstance(web3_or_provider, Web3):
|
||||||
|
web3 = web3_or_provider
|
||||||
|
else:
|
||||||
|
raise TypeError(
|
||||||
|
"Expected parameter 'web3_or_provider' to be an instance of either"
|
||||||
|
+ " Web3 or BaseProvider"
|
||||||
|
)
|
||||||
|
|
||||||
|
# if any middleware was imported, inject it
|
||||||
|
try:
|
||||||
|
MIDDLEWARE
|
||||||
|
except NameError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
for middleware in MIDDLEWARE:
|
||||||
|
web3.middleware_onion.inject(
|
||||||
|
middleware["function"], layer=middleware["layer"]
|
||||||
|
)
|
||||||
|
except ValueError as value_error:
|
||||||
|
if value_error.args == (
|
||||||
|
"You can't add the same un-named instance twice",
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
self._web3_eth = web3.eth
|
||||||
|
|
||||||
functions = self._web3_eth.contract(
|
functions = self._web3_eth.contract(
|
||||||
address=to_checksum_address(contract_address),
|
address=to_checksum_address(contract_address),
|
||||||
@ -191,11 +228,17 @@ class TestLibDummy:
|
|||||||
).functions
|
).functions
|
||||||
|
|
||||||
self.public_add_constant = PublicAddConstantMethod(
|
self.public_add_constant = PublicAddConstantMethod(
|
||||||
provider, contract_address, functions.publicAddConstant, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.publicAddConstant,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.public_add_one = PublicAddOneMethod(
|
self.public_add_one = PublicAddOneMethod(
|
||||||
provider, contract_address, functions.publicAddOne, validator
|
web3_or_provider,
|
||||||
|
contract_address,
|
||||||
|
functions.publicAddOne,
|
||||||
|
validator,
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
117
packages/contract-addresses/addresses.json
Normal file
117
packages/contract-addresses/addresses.json
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
{
|
||||||
|
"1": {
|
||||||
|
"exchangeV2": "0x080bf510fcbf18b91105470639e9561022937712",
|
||||||
|
"exchange": "0x0000000000000000000000000000000000000000",
|
||||||
|
"erc20Proxy": "0x95e6f48254609a6ee006f7d493c8e5fb97094cef",
|
||||||
|
"erc721Proxy": "0xefc70a1b18c432bdc64b596838b4d138f6bc6cad",
|
||||||
|
"forwarder": "0x0000000000000000000000000000000000000000",
|
||||||
|
"orderValidator": "0x0000000000000000000000000000000000000000",
|
||||||
|
"zrxToken": "0xe41d2489571d322189246dafa5ebde1f4699f498",
|
||||||
|
"etherToken": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
||||||
|
"assetProxyOwner": "0xdffe798c7172dd6deb32baee68af322e8f495ce0",
|
||||||
|
"zeroExGovernor": "0x0000000000000000000000000000000000000000",
|
||||||
|
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||||
|
"coordinatorRegistry": "0x45797531b873fd5e519477a070a955764c1a5b07",
|
||||||
|
"coordinator": "0x0000000000000000000000000000000000000000",
|
||||||
|
"multiAssetProxy": "0xef701d5389ae74503d633396c4d654eabedc9d78",
|
||||||
|
"staticCallProxy": "0x3517b88c19508c08650616019062b898ab65ed29",
|
||||||
|
"erc1155Proxy": "0x7eefbd48fd63d441ec7435d024ec7c5131019add",
|
||||||
|
"zrxVault": "0x0000000000000000000000000000000000000000",
|
||||||
|
"staking": "0x0000000000000000000000000000000000000000",
|
||||||
|
"stakingProxy": "0x0000000000000000000000000000000000000000",
|
||||||
|
"devUtils": "0x0000000000000000000000000000000000000000",
|
||||||
|
"erc20BridgeProxy": "0x0000000000000000000000000000000000000000"
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"erc20Proxy": "0xb1408f4c245a23c31b98d2c626777d4c0d766caa",
|
||||||
|
"erc721Proxy": "0xe654aac058bfbf9f83fcaee7793311dd82f6ddb4",
|
||||||
|
"zrxToken": "0xff67881f8d12f372d91baae9752eb3631ff0ed00",
|
||||||
|
"etherToken": "0xc778417e063141139fce010982780140aa0cd5ab",
|
||||||
|
"exchangeV2": "0xbff9493f92a3df4b0429b6d00743b3cfb4c85831",
|
||||||
|
"exchange": "0xc56388332ddfc98701fefed94535100c6166956c",
|
||||||
|
"assetProxyOwner": "0x0000000000000000000000000000000000000000",
|
||||||
|
"zeroExGovernor": "0xdcf20f7b447d51f2b3e5499b7f6cbbf7295a5d26",
|
||||||
|
"forwarder": "0xe66ae6162b3e9067d6ce9e5b9799cca1ba0d09f8",
|
||||||
|
"orderValidator": "0x0000000000000000000000000000000000000000",
|
||||||
|
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||||
|
"coordinatorRegistry": "0x403cc23e88c17c4652fb904784d1af640a6722d9",
|
||||||
|
"coordinator": "0xad8464022213a618c96a1178a927a5ed15ad6949",
|
||||||
|
"multiAssetProxy": "0xab8fbd189c569ccdee3a4d929bb7f557be4028f6",
|
||||||
|
"staticCallProxy": "0xe1b97e47aa3796276033a5341e884d2ba46b6ac1",
|
||||||
|
"erc1155Proxy": "0x19bb6caa3bc34d39e5a23cedfa3e6c7e7f3c931d",
|
||||||
|
"devUtils": "0x9a8590eebcfc53f0cc7ab5ebb8c079e9e7d4e0f5",
|
||||||
|
"zrxVault": "0xffd161026865ad8b4ab28a76840474935eec4dfa",
|
||||||
|
"staking": "0x3f46b98061a3e1e1f41dff296ec19402c298f8a9",
|
||||||
|
"stakingProxy": "0xfaabcee42ab6b9c649794ac6c133711071897ee9",
|
||||||
|
"erc20BridgeProxy": "0x599b340b5045436a99b1f0c718d30f5a0c8519dd"
|
||||||
|
},
|
||||||
|
"4": {
|
||||||
|
"exchangeV2": "0xbff9493f92a3df4b0429b6d00743b3cfb4c85831",
|
||||||
|
"exchange": "0x3afe8aa355e086d898447732cfa5d931cfb2a792",
|
||||||
|
"erc20Proxy": "0x2f5ae4f6106e89b4147651688a92256885c5f410",
|
||||||
|
"erc721Proxy": "0x7656d773e11ff7383a14dcf09a9c50990481cd10",
|
||||||
|
"zrxToken": "0x8080c7e4b81ecf23aa6f877cfbfd9b0c228c6ffa",
|
||||||
|
"etherToken": "0xc778417e063141139fce010982780140aa0cd5ab",
|
||||||
|
"assetProxyOwner": "0x0000000000000000000000000000000000000000",
|
||||||
|
"zeroExGovernor": "0x5d751aa855a1aee5fe44cf5350ed25b5727b66ae",
|
||||||
|
"forwarder": "0xf36eabdfe986b35b62c8fd5a98a7f2aebb79b291",
|
||||||
|
"orderValidator": "0x0000000000000000000000000000000000000000",
|
||||||
|
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||||
|
"coordinatorRegistry": "0x1084b6a398e47907bae43fec3ff4b677db6e4fee",
|
||||||
|
"coordinator": "0x9ae7a6e4e4d58c36b7aa573fc06ce46dd3cb0d44",
|
||||||
|
"multiAssetProxy": "0xb34cde0ad3a83d04abebc0b66e75196f22216621",
|
||||||
|
"staticCallProxy": "0xe1b97e47aa3796276033a5341e884d2ba46b6ac1",
|
||||||
|
"erc1155Proxy": "0x19bb6caa3bc34d39e5a23cedfa3e6c7e7f3c931d",
|
||||||
|
"devUtils": "0xfcbb258112485f18dd68f4b1016e48c23542fdc5",
|
||||||
|
"zrxVault": "0xa5bf6ac73bc40790fc6ffc9dbbbce76c9176e224",
|
||||||
|
"staking": "0x344d4f661a82afdd84d31456c291822d90d5dc3a",
|
||||||
|
"stakingProxy": "0xc6ad5277ea225ac05e271eb14a7ebb480cd9dd9f",
|
||||||
|
"erc20BridgeProxy": "0x31b8653642110f17bdb1f719901d7e7d49b08141"
|
||||||
|
},
|
||||||
|
"42": {
|
||||||
|
"erc20Proxy": "0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e",
|
||||||
|
"erc721Proxy": "0x2a9127c745688a165106c11cd4d647d2220af821",
|
||||||
|
"zrxToken": "0x2002d3812f58e35f0ea1ffbf80a75a38c32175fa",
|
||||||
|
"etherToken": "0xd0a1e359811322d97991e03f863a0c30c2cf029c",
|
||||||
|
"exchangeV2": "0x30589010550762d2f0d06f650d8e8b6ade6dbf4b",
|
||||||
|
"exchange": "0xca8b1626b3b7a0da722ca9f264c4630c7d34d3b8",
|
||||||
|
"assetProxyOwner": "0x0000000000000000000000000000000000000000",
|
||||||
|
"zeroExGovernor": "0x3654e5363cd75c8974c76208137df9691e820e97",
|
||||||
|
"forwarder": "0xd6330f9d2073e1889a295dd1dd2e28d42dec4bff",
|
||||||
|
"orderValidator": "0x0000000000000000000000000000000000000000",
|
||||||
|
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||||
|
"coordinatorRegistry": "0x09fb99968c016a3ff537bf58fb3d9fe55a7975d5",
|
||||||
|
"coordinator": "0x10e0b1c2e6065ec7f290c7e3731264f9a2bf2b2d",
|
||||||
|
"multiAssetProxy": "0xf6313a772c222f51c28f2304c0703b8cf5428fd8",
|
||||||
|
"staticCallProxy": "0x48e94bdb9033640d45ea7c721e25f380f8bffa43",
|
||||||
|
"erc1155Proxy": "0x64517fa2b480ba3678a2a3c0cf08ef7fd4fad36f",
|
||||||
|
"devUtils": "0x58c4fbdf9222f10ad2bef8f4d374f209135e71a5",
|
||||||
|
"zrxVault": "0xf36eabdfe986b35b62c8fd5a98a7f2aebb79b291",
|
||||||
|
"staking": "0x89150f5eed50b3528f79bfb539f29d727f92821c",
|
||||||
|
"stakingProxy": "0xbab9145f1d57cd4bb0c9aa2d1ece0a5b6e734d34",
|
||||||
|
"erc20BridgeProxy": "0xfb2dd2a1366de37f7241c83d47da58fd503e2c64"
|
||||||
|
},
|
||||||
|
"50": {
|
||||||
|
"erc20Proxy": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48",
|
||||||
|
"erc721Proxy": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401",
|
||||||
|
"erc1155Proxy": "0x6a4a62e5a7ed13c361b176a5f62c2ee620ac0df8",
|
||||||
|
"zrxToken": "0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c",
|
||||||
|
"etherToken": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082",
|
||||||
|
"exchangeV2": "0x48bacb9266a570d521063ef5dd96e61686dbe788",
|
||||||
|
"exchange": "0x48bacb9266a570d521063ef5dd96e61686dbe788",
|
||||||
|
"zeroExGovernor": "0x0000000000000000000000000000000000000000",
|
||||||
|
"assetProxyOwner": "0x0000000000000000000000000000000000000000",
|
||||||
|
"forwarder": "0x0000000000000000000000000000000000000000",
|
||||||
|
"orderValidator": "0x0000000000000000000000000000000000000000",
|
||||||
|
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||||
|
"coordinatorRegistry": "0x1941ff73d1154774d87521d2d0aaad5d19c8df60",
|
||||||
|
"coordinator": "0x0000000000000000000000000000000000000000",
|
||||||
|
"multiAssetProxy": "0xcfc18cec799fbd1793b5c43e773c98d4d61cc2db",
|
||||||
|
"staticCallProxy": "0x6dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f",
|
||||||
|
"devUtils": "0x38ef19fdf8e8415f18c307ed71967e19aac28ba1",
|
||||||
|
"zrxVault": "0x0000000000000000000000000000000000000000",
|
||||||
|
"staking": "0x0000000000000000000000000000000000000000",
|
||||||
|
"stakingProxy": "0x0000000000000000000000000000000000000000",
|
||||||
|
"erc20BridgeProxy": "0x0000000000000000000000000000000000000000"
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import addresses from '../addresses.json';
|
||||||
|
|
||||||
export interface ContractAddresses {
|
export interface ContractAddresses {
|
||||||
erc20Proxy: string;
|
erc20Proxy: string;
|
||||||
erc721Proxy: string;
|
erc721Proxy: string;
|
||||||
@ -32,127 +34,6 @@ export enum NetworkId {
|
|||||||
Ganache = 50,
|
Ganache = 50,
|
||||||
}
|
}
|
||||||
|
|
||||||
const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
||||||
|
|
||||||
const networkToAddresses: { [networkId: number]: ContractAddresses } = {
|
|
||||||
1: {
|
|
||||||
exchangeV2: '0x080bf510fcbf18b91105470639e9561022937712',
|
|
||||||
exchange: NULL_ADDRESS,
|
|
||||||
erc20Proxy: '0x95e6f48254609a6ee006f7d493c8e5fb97094cef',
|
|
||||||
erc721Proxy: '0xefc70a1b18c432bdc64b596838b4d138f6bc6cad',
|
|
||||||
forwarder: NULL_ADDRESS,
|
|
||||||
orderValidator: NULL_ADDRESS,
|
|
||||||
zrxToken: '0xe41d2489571d322189246dafa5ebde1f4699f498',
|
|
||||||
etherToken: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
|
|
||||||
assetProxyOwner: '0xdffe798c7172dd6deb32baee68af322e8f495ce0',
|
|
||||||
zeroExGovernor: NULL_ADDRESS,
|
|
||||||
dutchAuction: NULL_ADDRESS,
|
|
||||||
coordinatorRegistry: '0x45797531b873fd5e519477a070a955764c1a5b07',
|
|
||||||
coordinator: NULL_ADDRESS,
|
|
||||||
multiAssetProxy: '0xef701d5389ae74503d633396c4d654eabedc9d78',
|
|
||||||
staticCallProxy: '0x3517b88c19508c08650616019062b898ab65ed29',
|
|
||||||
erc1155Proxy: '0x7eefbd48fd63d441ec7435d024ec7c5131019add',
|
|
||||||
zrxVault: NULL_ADDRESS,
|
|
||||||
staking: NULL_ADDRESS,
|
|
||||||
stakingProxy: NULL_ADDRESS,
|
|
||||||
devUtils: NULL_ADDRESS,
|
|
||||||
erc20BridgeProxy: NULL_ADDRESS,
|
|
||||||
},
|
|
||||||
3: {
|
|
||||||
erc20Proxy: '0xb1408f4c245a23c31b98d2c626777d4c0d766caa',
|
|
||||||
erc721Proxy: '0xe654aac058bfbf9f83fcaee7793311dd82f6ddb4',
|
|
||||||
zrxToken: '0xff67881f8d12f372d91baae9752eb3631ff0ed00',
|
|
||||||
etherToken: '0xc778417e063141139fce010982780140aa0cd5ab',
|
|
||||||
exchangeV2: '0xbff9493f92a3df4b0429b6d00743b3cfb4c85831',
|
|
||||||
exchange: '0xc56388332ddfc98701fefed94535100c6166956c',
|
|
||||||
assetProxyOwner: NULL_ADDRESS,
|
|
||||||
zeroExGovernor: '0xdcf20f7b447d51f2b3e5499b7f6cbbf7295a5d26',
|
|
||||||
forwarder: '0xe66ae6162b3e9067d6ce9e5b9799cca1ba0d09f8',
|
|
||||||
orderValidator: NULL_ADDRESS,
|
|
||||||
dutchAuction: NULL_ADDRESS,
|
|
||||||
coordinatorRegistry: '0x403cc23e88c17c4652fb904784d1af640a6722d9',
|
|
||||||
coordinator: '0xad8464022213a618c96a1178a927a5ed15ad6949',
|
|
||||||
multiAssetProxy: '0xab8fbd189c569ccdee3a4d929bb7f557be4028f6',
|
|
||||||
staticCallProxy: '0xe1b97e47aa3796276033a5341e884d2ba46b6ac1',
|
|
||||||
erc1155Proxy: '0x19bb6caa3bc34d39e5a23cedfa3e6c7e7f3c931d',
|
|
||||||
devUtils: '0x9a8590eebcfc53f0cc7ab5ebb8c079e9e7d4e0f5',
|
|
||||||
zrxVault: '0xffd161026865ad8b4ab28a76840474935eec4dfa',
|
|
||||||
staking: '0x3f46b98061a3e1e1f41dff296ec19402c298f8a9',
|
|
||||||
stakingProxy: '0xfaabcee42ab6b9c649794ac6c133711071897ee9',
|
|
||||||
erc20BridgeProxy: '0x599b340b5045436a99b1f0c718d30f5a0c8519dd',
|
|
||||||
},
|
|
||||||
4: {
|
|
||||||
exchangeV2: '0xbff9493f92a3df4b0429b6d00743b3cfb4c85831',
|
|
||||||
exchange: '0x3afe8aa355e086d898447732cfa5d931cfb2a792',
|
|
||||||
erc20Proxy: '0x2f5ae4f6106e89b4147651688a92256885c5f410',
|
|
||||||
erc721Proxy: '0x7656d773e11ff7383a14dcf09a9c50990481cd10',
|
|
||||||
zrxToken: '0x8080c7e4b81ecf23aa6f877cfbfd9b0c228c6ffa',
|
|
||||||
etherToken: '0xc778417e063141139fce010982780140aa0cd5ab',
|
|
||||||
assetProxyOwner: NULL_ADDRESS,
|
|
||||||
zeroExGovernor: '0x5d751aa855a1aee5fe44cf5350ed25b5727b66ae',
|
|
||||||
forwarder: '0xf36eabdfe986b35b62c8fd5a98a7f2aebb79b291',
|
|
||||||
orderValidator: NULL_ADDRESS,
|
|
||||||
dutchAuction: NULL_ADDRESS,
|
|
||||||
coordinatorRegistry: '0x1084b6a398e47907bae43fec3ff4b677db6e4fee',
|
|
||||||
coordinator: '0x9ae7a6e4e4d58c36b7aa573fc06ce46dd3cb0d44',
|
|
||||||
multiAssetProxy: '0xb34cde0ad3a83d04abebc0b66e75196f22216621',
|
|
||||||
staticCallProxy: '0xe1b97e47aa3796276033a5341e884d2ba46b6ac1',
|
|
||||||
erc1155Proxy: '0x19bb6caa3bc34d39e5a23cedfa3e6c7e7f3c931d',
|
|
||||||
devUtils: '0xfcbb258112485f18dd68f4b1016e48c23542fdc5',
|
|
||||||
zrxVault: '0xa5bf6ac73bc40790fc6ffc9dbbbce76c9176e224',
|
|
||||||
staking: '0x344d4f661a82afdd84d31456c291822d90d5dc3a',
|
|
||||||
stakingProxy: '0xc6ad5277ea225ac05e271eb14a7ebb480cd9dd9f',
|
|
||||||
erc20BridgeProxy: '0x31b8653642110f17bdb1f719901d7e7d49b08141',
|
|
||||||
},
|
|
||||||
42: {
|
|
||||||
erc20Proxy: '0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e',
|
|
||||||
erc721Proxy: '0x2a9127c745688a165106c11cd4d647d2220af821',
|
|
||||||
zrxToken: '0x2002d3812f58e35f0ea1ffbf80a75a38c32175fa',
|
|
||||||
etherToken: '0xd0a1e359811322d97991e03f863a0c30c2cf029c',
|
|
||||||
exchangeV2: '0x30589010550762d2f0d06f650d8e8b6ade6dbf4b',
|
|
||||||
exchange: '0xca8b1626b3b7a0da722ca9f264c4630c7d34d3b8',
|
|
||||||
assetProxyOwner: NULL_ADDRESS,
|
|
||||||
zeroExGovernor: '0x3654e5363cd75c8974c76208137df9691e820e97',
|
|
||||||
forwarder: '0xd6330f9d2073e1889a295dd1dd2e28d42dec4bff',
|
|
||||||
orderValidator: NULL_ADDRESS,
|
|
||||||
dutchAuction: NULL_ADDRESS,
|
|
||||||
coordinatorRegistry: '0x09fb99968c016a3ff537bf58fb3d9fe55a7975d5',
|
|
||||||
coordinator: '0x10e0b1c2e6065ec7f290c7e3731264f9a2bf2b2d',
|
|
||||||
multiAssetProxy: '0xf6313a772c222f51c28f2304c0703b8cf5428fd8',
|
|
||||||
staticCallProxy: '0x48e94bdb9033640d45ea7c721e25f380f8bffa43',
|
|
||||||
erc1155Proxy: '0x64517fa2b480ba3678a2a3c0cf08ef7fd4fad36f',
|
|
||||||
devUtils: '0x58c4fbdf9222f10ad2bef8f4d374f209135e71a5',
|
|
||||||
zrxVault: '0xf36eabdfe986b35b62c8fd5a98a7f2aebb79b291',
|
|
||||||
staking: '0x89150f5eed50b3528f79bfb539f29d727f92821c',
|
|
||||||
stakingProxy: '0xbab9145f1d57cd4bb0c9aa2d1ece0a5b6e734d34',
|
|
||||||
erc20BridgeProxy: '0xfb2dd2a1366de37f7241c83d47da58fd503e2c64',
|
|
||||||
},
|
|
||||||
// NetworkId 50 represents our Ganache snapshot generated from migrations.
|
|
||||||
50: {
|
|
||||||
erc20Proxy: '0x1dc4c1cefef38a777b15aa20260a54e584b16c48',
|
|
||||||
erc721Proxy: '0x1d7022f5b17d2f8b695918fb48fa1089c9f85401',
|
|
||||||
erc1155Proxy: '0x6a4a62e5a7ed13c361b176a5f62c2ee620ac0df8',
|
|
||||||
zrxToken: '0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c',
|
|
||||||
etherToken: '0x0b1ba0af832d7c05fd64161e0db78e85978e8082',
|
|
||||||
exchangeV2: '0x48bacb9266a570d521063ef5dd96e61686dbe788',
|
|
||||||
exchange: '0x48bacb9266a570d521063ef5dd96e61686dbe788',
|
|
||||||
zeroExGovernor: NULL_ADDRESS,
|
|
||||||
assetProxyOwner: NULL_ADDRESS,
|
|
||||||
forwarder: NULL_ADDRESS,
|
|
||||||
orderValidator: NULL_ADDRESS,
|
|
||||||
dutchAuction: NULL_ADDRESS,
|
|
||||||
coordinatorRegistry: '0x1941ff73d1154774d87521d2d0aaad5d19c8df60',
|
|
||||||
coordinator: NULL_ADDRESS,
|
|
||||||
multiAssetProxy: '0xcfc18cec799fbd1793b5c43e773c98d4d61cc2db',
|
|
||||||
staticCallProxy: '0x6dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f',
|
|
||||||
devUtils: '0x38ef19fdf8e8415f18c307ed71967e19aac28ba1',
|
|
||||||
zrxVault: NULL_ADDRESS,
|
|
||||||
staking: NULL_ADDRESS,
|
|
||||||
stakingProxy: NULL_ADDRESS,
|
|
||||||
erc20BridgeProxy: NULL_ADDRESS,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to get addresses of contracts that have been deployed to either the
|
* Used to get addresses of contracts that have been deployed to either the
|
||||||
* Ethereum mainnet or a supported testnet. Throws if there are no known
|
* Ethereum mainnet or a supported testnet. Throws if there are no known
|
||||||
@ -162,6 +43,8 @@ const networkToAddresses: { [networkId: number]: ContractAddresses } = {
|
|||||||
* given networkId.
|
* given networkId.
|
||||||
*/
|
*/
|
||||||
export function getContractAddressesForNetworkOrThrow(networkId: NetworkId): ContractAddresses {
|
export function getContractAddressesForNetworkOrThrow(networkId: NetworkId): ContractAddresses {
|
||||||
|
const networkToAddresses: { [networkId: number]: ContractAddresses } = addresses;
|
||||||
|
|
||||||
if (networkToAddresses[networkId] === undefined) {
|
if (networkToAddresses[networkId] === undefined) {
|
||||||
throw new Error(`Unknown network id (${networkId}). No known 0x contracts have been deployed on this network.`);
|
throw new Error(`Unknown network id (${networkId}). No known 0x contracts have been deployed on this network.`);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
"extends": "../../tsconfig",
|
"extends": "../../tsconfig",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "lib",
|
"outDir": "lib",
|
||||||
"rootDir": "."
|
"rootDir": ".",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"esModuleInterop": true
|
||||||
},
|
},
|
||||||
"include": ["./src/**/*"]
|
"include": ["./src/**/*"],
|
||||||
|
"files": ["./addresses.json"]
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,14 @@
|
|||||||
|
|
||||||
"""setuptools module for contract_addresses package."""
|
"""setuptools module for contract_addresses package."""
|
||||||
|
|
||||||
|
# pylint: disable=import-outside-toplevel
|
||||||
|
# we import things outside of top-level because 3rd party libs may not yet be
|
||||||
|
# installed when you invoke this script
|
||||||
|
|
||||||
import subprocess # nosec
|
import subprocess # nosec
|
||||||
from shutil import rmtree
|
from shutil import copyfile, rmtree
|
||||||
from os import environ, path
|
from os import environ, path
|
||||||
from sys import argv
|
from sys import argv, exit # pylint: disable=redefined-builtin
|
||||||
|
|
||||||
from distutils.command.clean import clean
|
from distutils.command.clean import clean
|
||||||
import distutils.command.build_py
|
import distutils.command.build_py
|
||||||
@ -13,6 +17,34 @@ from setuptools import find_packages, setup
|
|||||||
from setuptools.command.test import test as TestCommand
|
from setuptools.command.test import test as TestCommand
|
||||||
|
|
||||||
|
|
||||||
|
class PreInstallCommand(distutils.command.build_py.build_py):
|
||||||
|
"""Custom setuptools command class for pulling in addresses.json."""
|
||||||
|
|
||||||
|
description = (
|
||||||
|
"Pull in addresses.json from ../../packages/contract-addresses"
|
||||||
|
)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
"""Copy over addresses.json."""
|
||||||
|
pkgdir = path.dirname(path.realpath(argv[0]))
|
||||||
|
|
||||||
|
destination_path = path.join(
|
||||||
|
pkgdir, "src", "zero_ex", "contract_addresses"
|
||||||
|
)
|
||||||
|
|
||||||
|
copyfile(
|
||||||
|
path.join(
|
||||||
|
pkgdir,
|
||||||
|
"..",
|
||||||
|
"..",
|
||||||
|
"packages",
|
||||||
|
"contract-addresses",
|
||||||
|
"addresses.json",
|
||||||
|
),
|
||||||
|
path.join(destination_path, "addresses.json"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class LintCommand(distutils.command.build_py.build_py):
|
class LintCommand(distutils.command.build_py.build_py):
|
||||||
"""Custom setuptools command class for running linters."""
|
"""Custom setuptools command class for running linters."""
|
||||||
|
|
||||||
@ -131,6 +163,7 @@ setup(
|
|||||||
author_email="feuGeneA@users.noreply.github.com",
|
author_email="feuGeneA@users.noreply.github.com",
|
||||||
cmdclass={
|
cmdclass={
|
||||||
"clean": CleanCommandExtension,
|
"clean": CleanCommandExtension,
|
||||||
|
"pre_install": PreInstallCommand,
|
||||||
"lint": LintCommand,
|
"lint": LintCommand,
|
||||||
"test": TestCommandExtension,
|
"test": TestCommandExtension,
|
||||||
"test_publish": TestPublishCommand,
|
"test_publish": TestPublishCommand,
|
||||||
@ -156,7 +189,9 @@ setup(
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
python_requires=">=3.6, <4",
|
python_requires=">=3.6, <4",
|
||||||
package_data={"zero_ex.contract_addresses": ["py.typed"]},
|
package_data={
|
||||||
|
"zero_ex.contract_addresses": ["py.typed", "addresses.json"]
|
||||||
|
},
|
||||||
package_dir={"": "src"},
|
package_dir={"": "src"},
|
||||||
license="Apache 2.0",
|
license="Apache 2.0",
|
||||||
keywords=(
|
keywords=(
|
||||||
|
@ -19,7 +19,7 @@ Python zero_ex.contract_addresses
|
|||||||
:members:
|
:members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
.. autodata:: zero_ex.contract_addresses.NETWORK_TO_ADDRESSES
|
.. autodata:: zero_ex.contract_addresses.network_to_addresses
|
||||||
:annotation: : Dict[NetworkId, ContractAddresses]
|
:annotation: : Dict[NetworkId, ContractAddresses]
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
"""0x Python API."""
|
"""0x Python API."""
|
||||||
__import__("pkg_resources").declare_namespace(__name__)
|
__import__("pkg_resources").declare_namespace(__name__) # type: ignore
|
||||||
|
@ -10,8 +10,11 @@ Install the package with pip::
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
import json
|
||||||
from typing import Dict, NamedTuple
|
from typing import Dict, NamedTuple
|
||||||
|
|
||||||
|
from pkg_resources import resource_string
|
||||||
|
|
||||||
|
|
||||||
class ContractAddresses(NamedTuple):
|
class ContractAddresses(NamedTuple):
|
||||||
"""An abstract record listing all the contracts that have addresses."""
|
"""An abstract record listing all the contracts that have addresses."""
|
||||||
@ -20,10 +23,7 @@ class ContractAddresses(NamedTuple):
|
|||||||
"""Address of the ERC20Proxy contract."""
|
"""Address of the ERC20Proxy contract."""
|
||||||
|
|
||||||
erc721_proxy: str
|
erc721_proxy: str
|
||||||
"""Address of the ERC20Proxy contract."""
|
"""Address of the ERC721Proxy contract."""
|
||||||
|
|
||||||
erc1155_proxy: str
|
|
||||||
"""Address of the ERC1155Proxy contract."""
|
|
||||||
|
|
||||||
zrx_token: str
|
zrx_token: str
|
||||||
"""Address of the ZRX token contract."""
|
"""Address of the ZRX token contract."""
|
||||||
@ -31,27 +31,57 @@ class ContractAddresses(NamedTuple):
|
|||||||
ether_token: str
|
ether_token: str
|
||||||
"""Address of the WETH token contract."""
|
"""Address of the WETH token contract."""
|
||||||
|
|
||||||
|
exchange_v2: str
|
||||||
|
"""Address of the v2 Exchange contract."""
|
||||||
|
|
||||||
exchange: str
|
exchange: str
|
||||||
"""Address of the Exchange contract."""
|
"""Address of the v3 Exchange contract."""
|
||||||
|
|
||||||
asset_proxy_owner: str
|
asset_proxy_owner: str
|
||||||
"""Address of the AssetProxyOwner contract."""
|
"""Address of the AssetProxyOwner contract."""
|
||||||
|
|
||||||
|
zero_ex_governor: str
|
||||||
|
"""Address of the ZeroExGovernor contract."""
|
||||||
|
|
||||||
forwarder: str
|
forwarder: str
|
||||||
"""Address of the Forwarder contract."""
|
"""Address of the Forwarder contract."""
|
||||||
|
|
||||||
order_validator: str
|
order_validator: str
|
||||||
"""Address of the OrderValidator contract."""
|
"""Address of the OrderValidator contract."""
|
||||||
|
|
||||||
|
dutch_auction: str
|
||||||
|
"""Address of the DutchAuction contract."""
|
||||||
|
|
||||||
coordinator_registry: str
|
coordinator_registry: str
|
||||||
"""Address of the CoordinatorRegistry contract."""
|
"""Address of the CoordinatorRegistry contract."""
|
||||||
|
|
||||||
coordinator: str
|
coordinator: str
|
||||||
"""Address of the Coordinator contract."""
|
"""Address of the Coordinator contract."""
|
||||||
|
|
||||||
|
multi_asset_proxy: str
|
||||||
|
"""Address of the MultiAssetProxy contract."""
|
||||||
|
|
||||||
|
static_call_proxy: str
|
||||||
|
"""Address of the StaticCallProxy contract."""
|
||||||
|
|
||||||
|
erc1155_proxy: str
|
||||||
|
"""Address of the ERC1155Proxy contract."""
|
||||||
|
|
||||||
dev_utils: str
|
dev_utils: str
|
||||||
"""Address of the DevUtils contract."""
|
"""Address of the DevUtils contract."""
|
||||||
|
|
||||||
|
zrx_vault: str
|
||||||
|
"""Address of the ZRXVault contract."""
|
||||||
|
|
||||||
|
staking: str
|
||||||
|
"""Address of the Staking contract."""
|
||||||
|
|
||||||
|
staking_proxy: str
|
||||||
|
"""Address of the StakingProxy contract."""
|
||||||
|
|
||||||
|
erc20_bridge_proxy: str
|
||||||
|
"""Address of the ERC20BridgeProxy contract."""
|
||||||
|
|
||||||
|
|
||||||
class NetworkId(Enum):
|
class NetworkId(Enum):
|
||||||
"""Network names correlated to their network identification numbers.
|
"""Network names correlated to their network identification numbers.
|
||||||
@ -70,83 +100,62 @@ class NetworkId(Enum):
|
|||||||
GANACHE = 50
|
GANACHE = 50
|
||||||
|
|
||||||
|
|
||||||
NETWORK_TO_ADDRESSES: Dict[NetworkId, ContractAddresses] = {
|
class _AddressCache:
|
||||||
NetworkId.MAINNET: ContractAddresses( # nosec
|
"""A cache to facilitate lazy & singular loading of contract addresses."""
|
||||||
erc20_proxy="0x95e6f48254609a6ee006f7d493c8e5fb97094cef",
|
|
||||||
erc721_proxy="0xefc70a1b18c432bdc64b596838b4d138f6bc6cad",
|
|
||||||
zrx_token="0xe41d2489571d322189246dafa5ebde1f4699f498",
|
|
||||||
ether_token="0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
|
|
||||||
exchange="0x080bf510fcbf18b91105470639e9561022937712",
|
|
||||||
asset_proxy_owner="0xdffe798c7172dd6deb32baee68af322e8f495ce0",
|
|
||||||
forwarder="0x76481caa104b5f6bccb540dae4cefaf1c398ebea",
|
|
||||||
order_validator="0xa09329c6003c9a5402102e226417738ee22cf1f2",
|
|
||||||
coordinator_registry="0x45797531b873fd5e519477a070a955764c1a5b07",
|
|
||||||
coordinator="0xa14857e8930acd9a882d33ec20559beb5479c8a6",
|
|
||||||
erc1155_proxy="0x7eefbd48fd63d441ec7435d024ec7c5131019add",
|
|
||||||
dev_utils="0x92d9a4d50190ae04e03914db2ee650124af844e6",
|
|
||||||
),
|
|
||||||
NetworkId.ROPSTEN: ContractAddresses( # nosec
|
|
||||||
erc20_proxy="0xb1408f4c245a23c31b98d2c626777d4c0d766caa",
|
|
||||||
erc721_proxy="0xe654aac058bfbf9f83fcaee7793311dd82f6ddb4",
|
|
||||||
zrx_token="0xff67881f8d12f372d91baae9752eb3631ff0ed00",
|
|
||||||
ether_token="0xc778417e063141139fce010982780140aa0cd5ab",
|
|
||||||
exchange="0xbff9493f92a3df4b0429b6d00743b3cfb4c85831",
|
|
||||||
asset_proxy_owner="0xf5fa5b5fed2727a0e44ac67f6772e97977aa358b",
|
|
||||||
forwarder="0x1ebdc9758e85c1c6a85af06cc96cf89000a31913",
|
|
||||||
order_validator="0x90431a90516ab49af23a0530e04e8c7836e7122f",
|
|
||||||
coordinator_registry="0x403cc23e88c17c4652fb904784d1af640a6722d9",
|
|
||||||
coordinator="0x2ba02e03ee0029311e0f43715307870a3e701b53",
|
|
||||||
erc1155_proxy="0x19bb6caa3bc34d39e5a23cedfa3e6c7e7f3c931d",
|
|
||||||
dev_utils="0x3e0b46bad8e374e4a110c12b832cb120dbe4a479",
|
|
||||||
),
|
|
||||||
NetworkId.RINKEBY: ContractAddresses( # nosec
|
|
||||||
exchange="0xbff9493f92a3df4b0429b6d00743b3cfb4c85831",
|
|
||||||
erc20_proxy="0x2f5ae4f6106e89b4147651688a92256885c5f410",
|
|
||||||
erc721_proxy="0x7656d773e11ff7383a14dcf09a9c50990481cd10",
|
|
||||||
zrx_token="0x8080c7e4b81ecf23aa6f877cfbfd9b0c228c6ffa",
|
|
||||||
ether_token="0xc778417e063141139fce010982780140aa0cd5ab",
|
|
||||||
asset_proxy_owner="0xe1703da878afcebff5b7624a826902af475b9c03",
|
|
||||||
forwarder="0x1ebdc9758e85c1c6a85af06cc96cf89000a31913",
|
|
||||||
order_validator="0x0c5173a51e26b29d6126c686756fb9fbef71f762",
|
|
||||||
coordinator_registry="0x1084b6a398e47907bae43fec3ff4b677db6e4fee",
|
|
||||||
coordinator="0x2ba02e03ee0029311e0f43715307870a3e701b53",
|
|
||||||
erc1155_proxy="0x19bb6caa3bc34d39e5a23cedfa3e6c7e7f3c931d",
|
|
||||||
dev_utils="0x2d4a9abda7b8b3605c8dbd34e3550a7467c78287'",
|
|
||||||
),
|
|
||||||
NetworkId.KOVAN: ContractAddresses( # nosec
|
|
||||||
erc20_proxy="0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e",
|
|
||||||
erc721_proxy="0x2a9127c745688a165106c11cd4d647d2220af821",
|
|
||||||
zrx_token="0x2002d3812f58e35f0ea1ffbf80a75a38c32175fa",
|
|
||||||
ether_token="0xd0a1e359811322d97991e03f863a0c30c2cf029c",
|
|
||||||
exchange="0x30589010550762d2f0d06f650d8e8b6ade6dbf4b",
|
|
||||||
asset_proxy_owner="0x2c824d2882baa668e0d5202b1e7f2922278703f8",
|
|
||||||
forwarder="0x1ebdc9758e85c1c6a85af06cc96cf89000a31913",
|
|
||||||
order_validator="0xb389da3d204b412df2f75c6afb3d0a7ce0bc283d",
|
|
||||||
coordinator_registry="0x09fb99968c016a3ff537bf58fb3d9fe55a7975d5",
|
|
||||||
coordinator="0x2ba02e03ee0029311e0f43715307870a3e701b53",
|
|
||||||
erc1155_proxy="0x64517fa2b480ba3678a2a3c0cf08ef7fd4fad36f",
|
|
||||||
dev_utils="0x1e3616bc5144362f95d72de41874395567697e93",
|
|
||||||
),
|
|
||||||
NetworkId.GANACHE: ContractAddresses( # nosec
|
|
||||||
exchange="0x48bacb9266a570d521063ef5dd96e61686dbe788",
|
|
||||||
erc20_proxy="0x1dc4c1cefef38a777b15aa20260a54e584b16c48",
|
|
||||||
erc721_proxy="0x1d7022f5b17d2f8b695918fb48fa1089c9f85401",
|
|
||||||
erc1155_proxy="0x6a4a62e5a7ed13c361b176a5f62c2ee620ac0df8",
|
|
||||||
zrx_token="0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c",
|
|
||||||
ether_token="0x0b1ba0af832d7c05fd64161e0db78e85978e8082",
|
|
||||||
asset_proxy_owner="0x8d42e38980ce74736c21c059b2240df09958d3c8",
|
|
||||||
forwarder="0xaa86dda78e9434aca114b6676fc742a18d15a1cc",
|
|
||||||
order_validator="0x4d3d5c850dd5bd9d6f4adda3dd039a3c8054ca29",
|
|
||||||
coordinator_registry="0x1941ff73d1154774d87521d2d0aaad5d19c8df60",
|
|
||||||
coordinator="0x0d8b0dd11f5d34ed41d556def5f841900d5b1c6b",
|
|
||||||
dev_utils="0x38ef19fdf8e8415f18c307ed71967e19aac28ba1",
|
|
||||||
),
|
|
||||||
}
|
|
||||||
"""A mapping from instances of NetworkId to instances of ContractAddresses.
|
|
||||||
|
|
||||||
Addresses under NetworkId.Ganache are from our Ganache snapshot generated from
|
# pylint: disable=too-few-public-methods
|
||||||
npm package @0x/migrations.
|
|
||||||
|
|
||||||
>>> NETWORK_TO_ADDRESSES[NetworkId.MAINNET].exchange
|
# class data, not instance:
|
||||||
0x4f833a24e1f95d70f028921e27040ca56e09ab0b
|
_network_to_addresses: Dict[str, ContractAddresses] = {}
|
||||||
"""
|
|
||||||
|
@classmethod
|
||||||
|
def network_to_addresses(cls, network_id: NetworkId):
|
||||||
|
"""Return the addresses for the given network ID.
|
||||||
|
|
||||||
|
First tries to get data from the class level storage
|
||||||
|
`_network_to_addresses`. 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._network_to_addresses[str(network_id.value)]
|
||||||
|
except KeyError:
|
||||||
|
cls._network_to_addresses = json.loads(
|
||||||
|
resource_string("zero_ex.contract_addresses", "addresses.json")
|
||||||
|
)
|
||||||
|
return cls._network_to_addresses[str(network_id.value)]
|
||||||
|
|
||||||
|
|
||||||
|
def network_to_addresses(network_id: NetworkId) -> ContractAddresses:
|
||||||
|
"""Map a NetworkId to an instance of ContractAddresses.
|
||||||
|
|
||||||
|
Addresses under NetworkId.Ganache are from our Ganache snapshot generated
|
||||||
|
from npm package @0x/migrations.
|
||||||
|
|
||||||
|
>>> network_to_addresses(NetworkId.MAINNET).exchange
|
||||||
|
'0x...'
|
||||||
|
"""
|
||||||
|
addresses = _AddressCache.network_to_addresses(network_id)
|
||||||
|
|
||||||
|
return ContractAddresses(
|
||||||
|
erc20_proxy=addresses["erc20Proxy"],
|
||||||
|
erc721_proxy=addresses["erc721Proxy"],
|
||||||
|
zrx_token=addresses["zrxToken"],
|
||||||
|
ether_token=addresses["etherToken"],
|
||||||
|
exchange_v2=addresses["exchangeV2"],
|
||||||
|
exchange=addresses["exchange"],
|
||||||
|
asset_proxy_owner=addresses["assetProxyOwner"],
|
||||||
|
zero_ex_governor=addresses["zeroExGovernor"],
|
||||||
|
forwarder=addresses["forwarder"],
|
||||||
|
order_validator=addresses["orderValidator"],
|
||||||
|
dutch_auction=addresses["dutchAuction"],
|
||||||
|
coordinator_registry=addresses["coordinatorRegistry"],
|
||||||
|
coordinator=addresses["coordinator"],
|
||||||
|
multi_asset_proxy=addresses["multiAssetProxy"],
|
||||||
|
static_call_proxy=addresses["staticCallProxy"],
|
||||||
|
erc1155_proxy=addresses["erc1155Proxy"],
|
||||||
|
dev_utils=addresses["devUtils"],
|
||||||
|
zrx_vault=addresses["zrxVault"],
|
||||||
|
staking=addresses["staking"],
|
||||||
|
staking_proxy=addresses["stakingProxy"],
|
||||||
|
erc20_bridge_proxy=addresses["erc20BridgeProxy"],
|
||||||
|
)
|
||||||
|
@ -10,3 +10,9 @@ envlist = py37
|
|||||||
commands =
|
commands =
|
||||||
pip install -e .[dev]
|
pip install -e .[dev]
|
||||||
python setup.py test
|
python setup.py test
|
||||||
|
|
||||||
|
[testenv:run_tests_against_deployment]
|
||||||
|
setenv = PY_IGNORE_IMPORTMISMATCH = 1
|
||||||
|
commands=
|
||||||
|
pip install 0x-contract-addresses[dev]
|
||||||
|
pytest --doctest-modules src
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 2.0.0 - 2019-01-09
|
## 3.0.0 - TBD
|
||||||
|
|
||||||
- Initial release.
|
- Updated with artifacts for version 3 of the protocol.
|
||||||
|
|
||||||
## 2.0.1 - 2019-04-30
|
## 2.0.1 - 2019-04-30
|
||||||
|
|
||||||
- Expanded documentation.
|
- Expanded documentation.
|
||||||
|
|
||||||
|
## 2.0.0 - 2019-01-09
|
||||||
|
|
||||||
|
- Initial release.
|
||||||
|
@ -2,10 +2,14 @@
|
|||||||
|
|
||||||
"""setuptools module for contract_artifacts package."""
|
"""setuptools module for contract_artifacts package."""
|
||||||
|
|
||||||
|
# pylint: disable=import-outside-toplevel
|
||||||
|
# we import things outside of top-level because 3rd party libs may not yet be
|
||||||
|
# installed when you invoke this script
|
||||||
|
|
||||||
import subprocess # nosec
|
import subprocess # nosec
|
||||||
from shutil import copytree, rmtree
|
from shutil import copytree, rmtree
|
||||||
from os import environ, path
|
from os import environ, path
|
||||||
from sys import argv
|
from sys import argv, exit # pylint: disable=redefined-builtin
|
||||||
|
|
||||||
from distutils.command.clean import clean
|
from distutils.command.clean import clean
|
||||||
import distutils.command.build_py
|
import distutils.command.build_py
|
||||||
@ -148,7 +152,7 @@ with open("README.md", "r") as file_handle:
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="0x-contract-artifacts",
|
name="0x-contract-artifacts",
|
||||||
version="2.0.1",
|
version="3.0.0",
|
||||||
description="0x smart contract compilation artifacts",
|
description="0x smart contract compilation artifacts",
|
||||||
long_description=README_MD,
|
long_description=README_MD,
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
"""0x Python API."""
|
"""0x Python API."""
|
||||||
__import__("pkg_resources").declare_namespace(__name__)
|
__import__("pkg_resources").declare_namespace(__name__) # type: ignore
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
{
|
|
||||||
"schemaVersion": "2.0.0",
|
|
||||||
"contractName": "EthBalanceChecker",
|
|
||||||
"compilerOutput": {
|
|
||||||
"abi": [
|
|
||||||
{
|
|
||||||
"constant": true,
|
|
||||||
"inputs": [{ "internalType": "address[]", "name": "addresses", "type": "address[]" }],
|
|
||||||
"name": "getEthBalances",
|
|
||||||
"outputs": [{ "internalType": "uint256[]", "name": "", "type": "uint256[]" }],
|
|
||||||
"payable": false,
|
|
||||||
"stateMutability": "view",
|
|
||||||
"type": "function"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"devdoc": {
|
|
||||||
"methods": {
|
|
||||||
"getEthBalances(address[])": {
|
|
||||||
"details": "Batch fetches ETH balances",
|
|
||||||
"params": { "addresses": "Array of addresses." },
|
|
||||||
"return": "Array of ETH balances."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"evm": {
|
|
||||||
"bytecode": {
|
|
||||||
"object": "0x608060405234801561001057600080fd5b506101e5806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a0901e5114610030575b600080fd5b6100d36004803603602081101561004657600080fd5b81019060208101813564010000000081111561006157600080fd5b82018360208201111561007357600080fd5b8035906020019184602083028401116401000000008311171561009557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610123945050505050565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561010f5781810151838201526020016100f7565b505050509050019250505060405180910390f35b6060808251604051908082528060200260200182016040528015610151578160200160208202803883390190505b50905060005b835181146101a95783818151811061016b57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff163182828151811061019657fe5b6020908102919091010152600101610157565b509291505056fea265627a7a7231582094309783f0b63086d85d9cb4f6e5be253699056ac1580a863367c5076ecb5c1864736f6c634300050b0032"
|
|
||||||
},
|
|
||||||
"deployedBytecode": {
|
|
||||||
"object": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a0901e5114610030575b600080fd5b6100d36004803603602081101561004657600080fd5b81019060208101813564010000000081111561006157600080fd5b82018360208201111561007357600080fd5b8035906020019184602083028401116401000000008311171561009557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610123945050505050565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561010f5781810151838201526020016100f7565b505050509050019250505060405180910390f35b6060808251604051908082528060200260200182016040528015610151578160200160208202803883390190505b50905060005b835181146101a95783818151811061016b57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff163182828151811061019657fe5b6020908102919091010152600101610157565b509291505056fea265627a7a7231582094309783f0b63086d85d9cb4f6e5be253699056ac1580a863367c5076ecb5c1864736f6c634300050b0032"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compiler": {
|
|
||||||
"name": "solc",
|
|
||||||
"version": "soljson-v0.5.11+commit.c082d0b4.js",
|
|
||||||
"settings": {
|
|
||||||
"optimizer": {
|
|
||||||
"enabled": true,
|
|
||||||
"runs": 10000,
|
|
||||||
"details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true }
|
|
||||||
},
|
|
||||||
"outputSelection": {
|
|
||||||
"*": {
|
|
||||||
"*": [
|
|
||||||
"abi",
|
|
||||||
"devdoc",
|
|
||||||
"evm.bytecode.object",
|
|
||||||
"evm.bytecode.sourceMap",
|
|
||||||
"evm.deployedBytecode.object",
|
|
||||||
"evm.deployedBytecode.sourceMap"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"evmVersion": "constantinople"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"networks": {}
|
|
||||||
}
|
|
@ -10,3 +10,9 @@ envlist = py37
|
|||||||
commands =
|
commands =
|
||||||
pip install -e .[dev]
|
pip install -e .[dev]
|
||||||
python setup.py test
|
python setup.py test
|
||||||
|
|
||||||
|
[testenv:run_tests_against_deployment]
|
||||||
|
setenv = PY_IGNORE_IMPORTMISMATCH = 1
|
||||||
|
commands=
|
||||||
|
pip install 0x-contract-artifacts[dev]
|
||||||
|
pytest --doctest-modules src
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2.0.0 - TBD
|
||||||
|
|
||||||
|
- Updated for version 3 of the protocol.
|
||||||
|
- Allow wrappers to be instantiated with EITHER a Web3.py `BaseProvider` OR an already-instantiated `Web3` client object.
|
||||||
|
- Accept `str`ing arguments to `bytes` contract method parameters.
|
||||||
|
- Expanded documentation examples.
|
||||||
|
- Moved methods `jsdict_to_order()` and `order_to_jsdict()` from `zero_ex.contract_wrappers.exchange.types` to `zero_ex.contract_wrappers.order_conversions`.
|
||||||
|
- Changed field name `zero_ex.contract_wrappers.tx_params.TxParams.gasPrice` to `.gas_price`.
|
||||||
|
|
||||||
## 1.1.0 - 2019-08-14
|
## 1.1.0 - 2019-08-14
|
||||||
|
|
||||||
- Added wrapper for DevUtils contract.
|
- Added wrapper for DevUtils contract.
|
||||||
|
@ -2,11 +2,15 @@
|
|||||||
|
|
||||||
"""setuptools module for contract_wrappers package."""
|
"""setuptools module for contract_wrappers package."""
|
||||||
|
|
||||||
|
# pylint: disable=import-outside-toplevel
|
||||||
|
# we import things outside of top-level because 3rd party libs may not yet be
|
||||||
|
# installed when you invoke this script
|
||||||
|
|
||||||
import subprocess # nosec
|
import subprocess # nosec
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
from os import environ, path, remove
|
from os import environ, path, remove
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from sys import argv
|
from sys import argv, exit # pylint: disable=redefined-builtin
|
||||||
|
|
||||||
from distutils.command.clean import clean
|
from distutils.command.clean import clean
|
||||||
import distutils.command.build_py
|
import distutils.command.build_py
|
||||||
@ -192,7 +196,7 @@ with open("README.md", "r") as file_handle:
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="0x-contract-wrappers",
|
name="0x-contract-wrappers",
|
||||||
version="1.1.0",
|
version="2.0.0",
|
||||||
description="Python wrappers for 0x smart contracts",
|
description="Python wrappers for 0x smart contracts",
|
||||||
long_description=README_MD,
|
long_description=README_MD,
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
|
@ -34,7 +34,7 @@ zero_ex.contract_wrappers.coordinator_registry
|
|||||||
|
|
||||||
|
|
||||||
zero_ex.contract_wrappers.dev_utils
|
zero_ex.contract_wrappers.dev_utils
|
||||||
=======================================
|
===================================
|
||||||
|
|
||||||
.. automodule:: zero_ex.contract_wrappers.dev_utils
|
.. automodule:: zero_ex.contract_wrappers.dev_utils
|
||||||
:members:
|
:members:
|
||||||
@ -49,6 +49,22 @@ zero_ex.contract_wrappers.dutch_auction
|
|||||||
:special-members:
|
:special-members:
|
||||||
|
|
||||||
|
|
||||||
|
zero_ex.contract_wrappers.erc1155_mintable
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
.. automodule:: zero_ex.contract_wrappers.erc1155_mintable
|
||||||
|
:members:
|
||||||
|
:special-members:
|
||||||
|
|
||||||
|
|
||||||
|
zero_ex.contract_wrappers.erc1155_proxy
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
.. automodule:: zero_ex.contract_wrappers.erc1155_proxy
|
||||||
|
:members:
|
||||||
|
:special-members:
|
||||||
|
|
||||||
|
|
||||||
zero_ex.contract_wrappers.erc20_proxy
|
zero_ex.contract_wrappers.erc20_proxy
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
@ -145,6 +161,14 @@ zero_ex.contract_wrappers.order_validator
|
|||||||
:special-members:
|
:special-members:
|
||||||
|
|
||||||
|
|
||||||
|
zero_ex.contract_wrappers.static_call_proxy
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
.. automodule:: zero_ex.contract_wrappers.static_call_proxy
|
||||||
|
:members:
|
||||||
|
:special-members:
|
||||||
|
|
||||||
|
|
||||||
zero_ex.contract_wrappers.weth9
|
zero_ex.contract_wrappers.weth9
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
@ -180,18 +204,20 @@ zero_ex.contract_wrappers.exchange.types
|
|||||||
|
|
||||||
.. autoclass:: zero_ex.contract_wrappers.exchange.types.MatchedFillResults
|
.. autoclass:: zero_ex.contract_wrappers.exchange.types.MatchedFillResults
|
||||||
|
|
||||||
|
.. autoclass:: zero_ex.contract_wrappers.exchange.types.ZeroExTransaction
|
||||||
|
|
||||||
zero_ex.contract_wrappers.exchange: Generated Tuples
|
zero_ex.contract_wrappers.exchange: Generated Tuples
|
||||||
====================================================
|
====================================================
|
||||||
|
|
||||||
.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0x260219a2
|
.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0x6ca34a6f
|
||||||
|
|
||||||
This is the generated class representing `the Order struct <https://0x.org/docs/contracts#structs-Order>`_.
|
This is the generated class representing `the Order struct <https://0x.org/docs/contracts#structs-Order>`_.
|
||||||
|
|
||||||
.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0xbb41e5b3
|
.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0x735c43e3
|
||||||
|
|
||||||
This is the generated class representing `the FillResults struct <https://0x.org/docs/contracts#structs-FillResults>`_.
|
This is the generated class representing `the FillResults struct <https://0x.org/docs/contracts#structs-FillResults>`_.
|
||||||
|
|
||||||
.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0x054ca44e
|
.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0x4c5ca29b
|
||||||
|
|
||||||
This is the generated class representing `the MatchedFillResults struct <https://0x.org/docs/contracts#structs-MatchedFillResults>`_.
|
This is the generated class representing `the MatchedFillResults struct <https://0x.org/docs/contracts#structs-MatchedFillResults>`_.
|
||||||
|
|
||||||
@ -199,6 +225,10 @@ zero_ex.contract_wrappers.exchange: Generated Tuples
|
|||||||
|
|
||||||
This is the generated class representing `the OrderInfo struct <https://0x.org/docs/contracts#structs-OrderInfo>`_.
|
This is the generated class representing `the OrderInfo struct <https://0x.org/docs/contracts#structs-OrderInfo>`_.
|
||||||
|
|
||||||
|
.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0xdabc15fe
|
||||||
|
|
||||||
|
This is the generated class representing `the ZeroExTransaction struct <https://0x.org/docs/contracts#structs-ZeroExTransaction>`_.
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
"""0x Python API."""
|
"""0x Python API."""
|
||||||
__import__("pkg_resources").declare_namespace(__name__)
|
__import__("pkg_resources").declare_namespace(__name__) # type: ignore
|
||||||
|
@ -52,10 +52,10 @@ the addresses of the 0x contracts on each network, including those that come
|
|||||||
pre-deployed deployed in the `0xorg/ganache-cli`:code: docker image. Let's
|
pre-deployed deployed in the `0xorg/ganache-cli`:code: docker image. Let's
|
||||||
capture the addresses we'll use throughout the examples below:
|
capture the addresses we'll use throughout the examples below:
|
||||||
|
|
||||||
>>> from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId
|
>>> from zero_ex.contract_addresses import network_to_addresses, NetworkId
|
||||||
>>> weth_address = NETWORK_TO_ADDRESSES[NetworkId.GANACHE].ether_token
|
>>> weth_address = network_to_addresses(NetworkId.GANACHE).ether_token
|
||||||
>>> zrx_address = NETWORK_TO_ADDRESSES[NetworkId.GANACHE].zrx_token
|
>>> zrx_address = network_to_addresses(NetworkId.GANACHE).zrx_token
|
||||||
>>> exchange_address = NETWORK_TO_ADDRESSES[NetworkId.GANACHE].exchange
|
>>> exchange_address = network_to_addresses(NetworkId.GANACHE).exchange
|
||||||
|
|
||||||
Wrapping ETH
|
Wrapping ETH
|
||||||
------------
|
------------
|
||||||
@ -92,15 +92,15 @@ balance:
|
|||||||
|
|
||||||
>>> from zero_ex.contract_wrappers.erc20_token import ERC20Token
|
>>> from zero_ex.contract_wrappers.erc20_token import ERC20Token
|
||||||
>>> zrx_token = ERC20Token(
|
>>> zrx_token = ERC20Token(
|
||||||
... provider=ganache,
|
... web3_or_provider=ganache,
|
||||||
... contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].zrx_token,
|
... contract_address=network_to_addresses(NetworkId.GANACHE).zrx_token,
|
||||||
... )
|
... )
|
||||||
>>> weth_token = ERC20Token(
|
>>> weth_token = ERC20Token(
|
||||||
... provider=ganache,
|
... web3_or_provider=ganache,
|
||||||
... contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].ether_token,
|
... contract_address=network_to_addresses(NetworkId.GANACHE).ether_token,
|
||||||
... )
|
... )
|
||||||
|
|
||||||
>>> erc20_proxy_addr = NETWORK_TO_ADDRESSES[NetworkId.GANACHE].erc20_proxy
|
>>> erc20_proxy_addr = network_to_addresses(NetworkId.GANACHE).erc20_proxy
|
||||||
|
|
||||||
>>> tx = zrx_token.approve.send_transaction(
|
>>> tx = zrx_token.approve.send_transaction(
|
||||||
... erc20_proxy_addr,
|
... erc20_proxy_addr,
|
||||||
@ -135,16 +135,20 @@ Constructing an order
|
|||||||
... takerAssetAmount=to_wei(0.1, 'ether'),
|
... takerAssetAmount=to_wei(0.1, 'ether'),
|
||||||
... expirationTimeSeconds=round(
|
... expirationTimeSeconds=round(
|
||||||
... (datetime.utcnow() + timedelta(days=1)).timestamp()
|
... (datetime.utcnow() + timedelta(days=1)).timestamp()
|
||||||
... )
|
... ),
|
||||||
|
... makerFeeAssetData='0x',
|
||||||
|
... takerFeeAssetData='0x',
|
||||||
... )
|
... )
|
||||||
|
|
||||||
For this order to be valid, our Maker must sign a hash of it:
|
For this order to be valid, our Maker must sign a hash of it:
|
||||||
|
|
||||||
>>> from zero_ex.order_utils import generate_order_hash_hex
|
>>> from zero_ex.order_utils import generate_order_hash_hex
|
||||||
>>> order_hash_hex = generate_order_hash_hex(order, exchange_address)
|
>>> order_hash_hex = generate_order_hash_hex(
|
||||||
|
... order, exchange_address, Web3(ganache).eth.chainId
|
||||||
|
... )
|
||||||
|
|
||||||
>>> from zero_ex.order_utils import sign_hash_to_bytes
|
>>> from zero_ex.order_utils import sign_hash
|
||||||
>>> maker_signature = sign_hash_to_bytes(
|
>>> maker_signature = sign_hash(
|
||||||
... ganache, Web3.toChecksumAddress(maker_address), order_hash_hex
|
... ganache, Web3.toChecksumAddress(maker_address), order_hash_hex
|
||||||
... )
|
... )
|
||||||
|
|
||||||
@ -156,16 +160,37 @@ more information on working with Relayers, see `the documentation for
|
|||||||
Filling an order
|
Filling an order
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Now our Taker will fill the order. The `takerAssetAmount`:code: parameter
|
Now we'll have our Taker fill the order.
|
||||||
specifies the amount of tokens (in this case WETH) that the taker wants to
|
|
||||||
fill. This example fills the order completely, but partial fills are possible
|
|
||||||
too.
|
|
||||||
|
|
||||||
>>> from zero_ex.contract_wrappers.exchange import Exchange
|
>>> from zero_ex.contract_wrappers.exchange import Exchange
|
||||||
>>> exchange = Exchange(
|
>>> exchange = Exchange(
|
||||||
... provider=ganache,
|
... web3_or_provider=ganache,
|
||||||
... contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].exchange,
|
... contract_address=network_to_addresses(NetworkId.GANACHE).exchange,
|
||||||
... )
|
... )
|
||||||
|
|
||||||
|
But before filling an order, one may wish to check that it's actually fillable:
|
||||||
|
|
||||||
|
>>> from zero_ex.contract_wrappers.exchange.types import OrderStatus
|
||||||
|
>>> OrderStatus(exchange.get_order_info.call(order)[0])
|
||||||
|
<OrderStatus.FILLABLE: 3>
|
||||||
|
|
||||||
|
The `takerAssetAmount`:code: parameter specifies the amount of tokens (in this
|
||||||
|
case WETH) that the taker wants to fill. This example fills the order
|
||||||
|
completely, but partial fills are possible too.
|
||||||
|
|
||||||
|
One may wish to first call the method in a read-only way, to ensure that it
|
||||||
|
will not revert, and to validate that the return data is as expected:
|
||||||
|
|
||||||
|
>>> exchange.fill_order.call(
|
||||||
|
... order=order,
|
||||||
|
... taker_asset_fill_amount=order["takerAssetAmount"],
|
||||||
|
... signature=maker_signature,
|
||||||
|
... tx_params=TxParams(from_=taker_address)
|
||||||
|
... )
|
||||||
|
(100000000000000000, 100000000000000000, 0, 0, 0)
|
||||||
|
|
||||||
|
Finally, submit the transaction:
|
||||||
|
|
||||||
>>> tx_hash = exchange.fill_order.send_transaction(
|
>>> tx_hash = exchange.fill_order.send_transaction(
|
||||||
... order=order,
|
... order=order,
|
||||||
... taker_asset_fill_amount=order["takerAssetAmount"],
|
... taker_asset_fill_amount=order["takerAssetAmount"],
|
||||||
@ -184,12 +209,15 @@ the exchange wrapper:
|
|||||||
'makerAddress': '0x...',
|
'makerAddress': '0x...',
|
||||||
'makerAssetData': b...,
|
'makerAssetData': b...,
|
||||||
'makerAssetFilledAmount': 100000000000000000,
|
'makerAssetFilledAmount': 100000000000000000,
|
||||||
|
'makerFeeAssetData': b...,
|
||||||
'makerFeePaid': 0,
|
'makerFeePaid': 0,
|
||||||
'orderHash': b...,
|
'orderHash': b...,
|
||||||
|
'protocolFeePaid': ...,
|
||||||
'senderAddress': '0x...',
|
'senderAddress': '0x...',
|
||||||
'takerAddress': '0x...',
|
'takerAddress': '0x...',
|
||||||
'takerAssetData': b...,
|
'takerAssetData': b...,
|
||||||
'takerAssetFilledAmount': 100000000000000000,
|
'takerAssetFilledAmount': 100000000000000000,
|
||||||
|
'takerFeeAssetData': b...,
|
||||||
'takerFeePaid': 0}
|
'takerFeePaid': 0}
|
||||||
>>> exchange.get_fill_event(tx_hash)[0].args.takerAssetFilledAmount
|
>>> exchange.get_fill_event(tx_hash)[0].args.takerAssetFilledAmount
|
||||||
100000000000000000
|
100000000000000000
|
||||||
@ -206,7 +234,9 @@ A Maker can cancel an order that has yet to be filled.
|
|||||||
... senderAddress='0x0000000000000000000000000000000000000000',
|
... senderAddress='0x0000000000000000000000000000000000000000',
|
||||||
... feeRecipientAddress='0x0000000000000000000000000000000000000000',
|
... feeRecipientAddress='0x0000000000000000000000000000000000000000',
|
||||||
... makerAssetData=asset_data_utils.encode_erc20(weth_address),
|
... makerAssetData=asset_data_utils.encode_erc20(weth_address),
|
||||||
|
... makerFeeAssetData=asset_data_utils.encode_erc20('0x' + '00'*20),
|
||||||
... takerAssetData=asset_data_utils.encode_erc20(weth_address),
|
... takerAssetData=asset_data_utils.encode_erc20(weth_address),
|
||||||
|
... takerFeeAssetData=asset_data_utils.encode_erc20('0x' + '00'*20),
|
||||||
... salt=random.randint(1, 100000000000000000),
|
... salt=random.randint(1, 100000000000000000),
|
||||||
... makerFee=0,
|
... makerFee=0,
|
||||||
... takerFee=0,
|
... takerFee=0,
|
||||||
@ -248,7 +278,9 @@ is an example where the taker fills two orders in one transaction:
|
|||||||
... senderAddress='0x0000000000000000000000000000000000000000',
|
... senderAddress='0x0000000000000000000000000000000000000000',
|
||||||
... feeRecipientAddress='0x0000000000000000000000000000000000000000',
|
... feeRecipientAddress='0x0000000000000000000000000000000000000000',
|
||||||
... makerAssetData=asset_data_utils.encode_erc20(zrx_address),
|
... makerAssetData=asset_data_utils.encode_erc20(zrx_address),
|
||||||
|
... makerFeeAssetData=asset_data_utils.encode_erc20('0x' + '00'*20),
|
||||||
... takerAssetData=asset_data_utils.encode_erc20(weth_address),
|
... takerAssetData=asset_data_utils.encode_erc20(weth_address),
|
||||||
|
... takerFeeAssetData=asset_data_utils.encode_erc20('0x' + '00'*20),
|
||||||
... salt=random.randint(1, 100000000000000000),
|
... salt=random.randint(1, 100000000000000000),
|
||||||
... makerFee=0,
|
... makerFee=0,
|
||||||
... takerFee=0,
|
... takerFee=0,
|
||||||
@ -258,10 +290,12 @@ is an example where the taker fills two orders in one transaction:
|
|||||||
... (datetime.utcnow() + timedelta(days=1)).timestamp()
|
... (datetime.utcnow() + timedelta(days=1)).timestamp()
|
||||||
... )
|
... )
|
||||||
... )
|
... )
|
||||||
>>> signature_1 = sign_hash_to_bytes(
|
>>> signature_1 = sign_hash(
|
||||||
... ganache,
|
... ganache,
|
||||||
... Web3.toChecksumAddress(maker_address),
|
... Web3.toChecksumAddress(maker_address),
|
||||||
... generate_order_hash_hex(order_1, exchange.contract_address)
|
... generate_order_hash_hex(
|
||||||
|
... order_1, exchange.contract_address, Web3(ganache).eth.chainId
|
||||||
|
... ),
|
||||||
... )
|
... )
|
||||||
>>> order_2 = Order(
|
>>> order_2 = Order(
|
||||||
... makerAddress=maker_address,
|
... makerAddress=maker_address,
|
||||||
@ -269,7 +303,9 @@ is an example where the taker fills two orders in one transaction:
|
|||||||
... senderAddress='0x0000000000000000000000000000000000000000',
|
... senderAddress='0x0000000000000000000000000000000000000000',
|
||||||
... feeRecipientAddress='0x0000000000000000000000000000000000000000',
|
... feeRecipientAddress='0x0000000000000000000000000000000000000000',
|
||||||
... makerAssetData=asset_data_utils.encode_erc20(zrx_address),
|
... makerAssetData=asset_data_utils.encode_erc20(zrx_address),
|
||||||
|
... makerFeeAssetData=asset_data_utils.encode_erc20('0x' + '00'*20),
|
||||||
... takerAssetData=asset_data_utils.encode_erc20(weth_address),
|
... takerAssetData=asset_data_utils.encode_erc20(weth_address),
|
||||||
|
... takerFeeAssetData=asset_data_utils.encode_erc20('0x' + '00'*20),
|
||||||
... salt=random.randint(1, 100000000000000000),
|
... salt=random.randint(1, 100000000000000000),
|
||||||
... makerFee=0,
|
... makerFee=0,
|
||||||
... takerFee=0,
|
... takerFee=0,
|
||||||
@ -279,10 +315,12 @@ is an example where the taker fills two orders in one transaction:
|
|||||||
... (datetime.utcnow() + timedelta(days=1)).timestamp()
|
... (datetime.utcnow() + timedelta(days=1)).timestamp()
|
||||||
... )
|
... )
|
||||||
... )
|
... )
|
||||||
>>> signature_2 = sign_hash_to_bytes(
|
>>> signature_2 = sign_hash(
|
||||||
... ganache,
|
... ganache,
|
||||||
... Web3.toChecksumAddress(maker_address),
|
... Web3.toChecksumAddress(maker_address),
|
||||||
... generate_order_hash_hex(order_2, exchange.contract_address)
|
... generate_order_hash_hex(
|
||||||
|
... order_2, exchange.contract_address, Web3(ganache).eth.chainId
|
||||||
|
... ),
|
||||||
... )
|
... )
|
||||||
|
|
||||||
Fill order_1 and order_2 together:
|
Fill order_1 and order_2 together:
|
||||||
@ -308,7 +346,9 @@ will be consumed.
|
|||||||
... senderAddress='0x0000000000000000000000000000000000000000',
|
... senderAddress='0x0000000000000000000000000000000000000000',
|
||||||
... feeRecipientAddress='0x0000000000000000000000000000000000000000',
|
... feeRecipientAddress='0x0000000000000000000000000000000000000000',
|
||||||
... makerAssetData=asset_data_utils.encode_erc20(weth_address),
|
... makerAssetData=asset_data_utils.encode_erc20(weth_address),
|
||||||
|
... makerFeeAssetData=asset_data_utils.encode_erc20('0x' + '00'*20),
|
||||||
... takerAssetData=asset_data_utils.encode_erc20(weth_address),
|
... takerAssetData=asset_data_utils.encode_erc20(weth_address),
|
||||||
|
... takerFeeAssetData=asset_data_utils.encode_erc20('0x' + '00'*20),
|
||||||
... salt=random.randint(1, 100000000000000000),
|
... salt=random.randint(1, 100000000000000000),
|
||||||
... makerFee=0,
|
... makerFee=0,
|
||||||
... takerFee=0,
|
... takerFee=0,
|
||||||
@ -320,7 +360,7 @@ will be consumed.
|
|||||||
... ),
|
... ),
|
||||||
... tx_params=TxParams(from_=maker_address),
|
... tx_params=TxParams(from_=maker_address),
|
||||||
... )
|
... )
|
||||||
73...
|
74...
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .tx_params import TxParams
|
from .tx_params import TxParams
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"""Base wrapper class for accessing ethereum smart contracts."""
|
"""Base wrapper class for accessing ethereum smart contracts."""
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any, Union
|
||||||
|
|
||||||
from eth_utils import is_address, to_checksum_address
|
from eth_utils import is_address, to_checksum_address
|
||||||
from web3 import Web3
|
from web3 import Web3
|
||||||
@ -12,7 +12,11 @@ from .tx_params import TxParams
|
|||||||
class Validator:
|
class Validator:
|
||||||
"""Base class for validating inputs to methods."""
|
"""Base class for validating inputs to methods."""
|
||||||
|
|
||||||
def __init__(self, provider: BaseProvider, contract_address: str):
|
def __init__(
|
||||||
|
self,
|
||||||
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
|
contract_address: str,
|
||||||
|
):
|
||||||
"""Initialize the instance."""
|
"""Initialize the instance."""
|
||||||
|
|
||||||
def assert_valid(
|
def assert_valid(
|
||||||
@ -32,7 +36,7 @@ class ContractMethod:
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
provider: BaseProvider,
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
contract_address: str,
|
contract_address: str,
|
||||||
validator: Validator = None,
|
validator: Validator = None,
|
||||||
):
|
):
|
||||||
@ -42,9 +46,20 @@ class ContractMethod:
|
|||||||
:param contract_address: Where the contract has been deployed to.
|
:param contract_address: Where the contract has been deployed to.
|
||||||
:param validator: Used to validate method inputs.
|
:param validator: Used to validate method inputs.
|
||||||
"""
|
"""
|
||||||
self._web3_eth = Web3(provider).eth # pylint: disable=no-member
|
web3 = None
|
||||||
|
if isinstance(web3_or_provider, BaseProvider):
|
||||||
|
web3 = Web3(web3_or_provider)
|
||||||
|
elif isinstance(web3_or_provider, Web3):
|
||||||
|
web3 = web3_or_provider
|
||||||
|
if web3 is None:
|
||||||
|
raise TypeError(
|
||||||
|
"Expected parameter 'web3_or_provider' to be an instance of either"
|
||||||
|
+ " Web3 or BaseProvider"
|
||||||
|
)
|
||||||
|
|
||||||
|
self._web3_eth = web3.eth # pylint: disable=no-member
|
||||||
if validator is None:
|
if validator is None:
|
||||||
validator = Validator(provider, contract_address)
|
validator = Validator(web3_or_provider, contract_address)
|
||||||
self.validator = validator
|
self.validator = validator
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -59,8 +74,13 @@ class ContractMethod:
|
|||||||
if not tx_params:
|
if not tx_params:
|
||||||
tx_params = TxParams()
|
tx_params = TxParams()
|
||||||
if not tx_params.from_:
|
if not tx_params.from_:
|
||||||
tx_params.from_ = (
|
tx_params.from_ = self._web3_eth.defaultAccount or (
|
||||||
self._web3_eth.defaultAccount or self._web3_eth.accounts[0]
|
self._web3_eth.accounts[0]
|
||||||
|
if len(self._web3_eth.accounts) > 0
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
if tx_params.from_:
|
||||||
|
tx_params.from_ = self.validate_and_checksum_address(
|
||||||
|
tx_params.from_
|
||||||
)
|
)
|
||||||
tx_params.from_ = self.validate_and_checksum_address(tx_params.from_)
|
|
||||||
return tx_params
|
return tx_params
|
||||||
|
@ -0,0 +1,80 @@
|
|||||||
|
"""Exception classes common to all wrappers."""
|
||||||
|
|
||||||
|
from inspect import isclass
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from eth_abi import decode_abi
|
||||||
|
|
||||||
|
|
||||||
|
class RichRevert(Exception):
|
||||||
|
"""Raised when a contract method returns a rich revert error."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, abi_signature: str, param_names: List[str], return_data: str
|
||||||
|
):
|
||||||
|
"""Populate instance variables with decoded return data values."""
|
||||||
|
arg_start_index = abi_signature.index("(") + 1
|
||||||
|
arg_end_index = abi_signature.index(")")
|
||||||
|
arguments = decode_abi(
|
||||||
|
abi_signature[arg_start_index:arg_end_index].split(","),
|
||||||
|
bytes.fromhex(return_data[10:]),
|
||||||
|
)
|
||||||
|
for (param_name, argument) in zip(param_names, arguments):
|
||||||
|
setattr(self, param_name, argument)
|
||||||
|
super().__init__(vars(self))
|
||||||
|
|
||||||
|
|
||||||
|
class NoExceptionForSelector(Exception):
|
||||||
|
"""Indicates that no exception could be found for the given selector."""
|
||||||
|
|
||||||
|
|
||||||
|
def exception_class_from_rich_revert_selector(
|
||||||
|
selector: str, exceptions_module
|
||||||
|
) -> RichRevert:
|
||||||
|
"""Return the appropriate exception class.
|
||||||
|
|
||||||
|
:param selector: A string of the format '0xffffffff' which indicates the
|
||||||
|
4-byte ABI function selector of a rich revert error type, which is
|
||||||
|
expected to be found as a class attribute on some class in
|
||||||
|
`exceptions_module`:code:.
|
||||||
|
:param exceptions_module: The Python module in which to look for a class
|
||||||
|
with a `selector`:code: attribute matching the value of the
|
||||||
|
`selector`:code: argument.
|
||||||
|
"""
|
||||||
|
# noqa: D202 (No blank lines allowed after function docstring
|
||||||
|
def _get_rich_revert_exception_classes():
|
||||||
|
def _exception_name_is_class_with_selector(name: str):
|
||||||
|
if not isclass(getattr(exceptions_module, name)):
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
getattr(exceptions_module, name).selector
|
||||||
|
except AttributeError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _convert_class_name_to_class(name: str):
|
||||||
|
return getattr(exceptions_module, name)
|
||||||
|
|
||||||
|
return list(
|
||||||
|
map(
|
||||||
|
_convert_class_name_to_class,
|
||||||
|
filter(
|
||||||
|
_exception_name_is_class_with_selector,
|
||||||
|
dir(exceptions_module),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
rich_reverts = _get_rich_revert_exception_classes()
|
||||||
|
|
||||||
|
try:
|
||||||
|
return next(
|
||||||
|
filter(
|
||||||
|
lambda rich_revert: rich_revert.selector == selector,
|
||||||
|
rich_reverts,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except StopIteration:
|
||||||
|
raise NoExceptionForSelector(selector)
|
@ -0,0 +1,341 @@
|
|||||||
|
"""Exchange-specific exception classes."""
|
||||||
|
|
||||||
|
from enum import auto, Enum
|
||||||
|
|
||||||
|
from zero_ex.contract_wrappers.exceptions import RichRevert
|
||||||
|
|
||||||
|
# pylint: disable=missing-docstring
|
||||||
|
|
||||||
|
|
||||||
|
class AssetProxyDispatchErrorCodes(Enum): # noqa: D101 (missing docstring)
|
||||||
|
INVALID_ASSET_DATA_LENGTH = 0
|
||||||
|
UNKNOWN_ASSET_PROXY = auto()
|
||||||
|
|
||||||
|
|
||||||
|
class BatchMatchOrdersErrorCodes(Enum): # noqa: D101 (missing docstring)
|
||||||
|
ZERO_LEFT_ORDERS = 0
|
||||||
|
ZERO_RIGHT_ORDERS = auto()
|
||||||
|
INVALID_LENGTH_LEFT_SIGNATURES = auto()
|
||||||
|
INVALID_LENGTH_RIGHT_SIGNATURES = auto()
|
||||||
|
|
||||||
|
|
||||||
|
class ExchangeContextErrorCodes(Enum): # noqa: D101 (missing docstring)
|
||||||
|
INVALID_MAKER = 0
|
||||||
|
INVALID_TAKER = auto()
|
||||||
|
INVALID_SENDER = auto()
|
||||||
|
|
||||||
|
|
||||||
|
class FillErrorCodes(Enum): # noqa: D101 (missing docstring)
|
||||||
|
INVALID_TAKER_AMOUNT = 0
|
||||||
|
TAKER_OVERPAY = auto()
|
||||||
|
OVERFILL = auto()
|
||||||
|
INVALID_FILL_PRICE = auto()
|
||||||
|
|
||||||
|
|
||||||
|
class SignatureErrorCodes(Enum): # noqa: D101 (missing docstring)
|
||||||
|
BAD_ORDER_SIGNATURE = 0
|
||||||
|
BAD_TRANSACTION_SIGNATURE = auto()
|
||||||
|
INVALID_LENGTH = auto()
|
||||||
|
UNSUPPORTED = auto()
|
||||||
|
ILLEGAL = auto()
|
||||||
|
INAPPROPRIATE_SIGNATURE_TYPE = auto()
|
||||||
|
INVALID_SIGNER = auto()
|
||||||
|
|
||||||
|
|
||||||
|
class TransactionErrorCodes(Enum): # noqa: D101 (missing docstring)
|
||||||
|
ALREADY_EXECUTED = 0
|
||||||
|
EXPIRED = auto()
|
||||||
|
|
||||||
|
|
||||||
|
class IncompleteFillErrorCode(Enum): # noqa: D101 (missing docstring)
|
||||||
|
INCOMPLETE_MARKET_BUY_ORDERS = 0
|
||||||
|
INCOMPLETE_MARKET_SELL_ORDERS = auto()
|
||||||
|
INCOMPLETE_FILL_ORDER = auto()
|
||||||
|
|
||||||
|
|
||||||
|
class SignatureError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"SignatureError(uint8,bytes32,address,bytes)",
|
||||||
|
["errorCode", "hash", "signerAddress", "signature"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
errorCode: SignatureErrorCodes
|
||||||
|
hash: bytes
|
||||||
|
signerAddress: str
|
||||||
|
signature: bytes
|
||||||
|
|
||||||
|
selector = "0x7e5a2318"
|
||||||
|
|
||||||
|
|
||||||
|
class SignatureValidatorNotApprovedError(
|
||||||
|
RichRevert
|
||||||
|
): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"SignatureValidatorNotApprovedError(address,address)",
|
||||||
|
["signerAddress", "validatorAddress"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
signerAddress: str
|
||||||
|
validatorAddress: str
|
||||||
|
|
||||||
|
selector = "0xa15c0d06"
|
||||||
|
|
||||||
|
|
||||||
|
class EIP1271SignatureError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"EIP1271SignatureError(address,bytes,bytes,bytes)",
|
||||||
|
["verifyingContractAddress", "data", "signature", "errorData"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
verifyingContractAddress: str
|
||||||
|
data: bytes
|
||||||
|
signature: bytes
|
||||||
|
errorData: bytes
|
||||||
|
|
||||||
|
selector = "0x5bd0428d"
|
||||||
|
|
||||||
|
|
||||||
|
class SignatureWalletError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"SignatureWalletError(bytes32,address,bytes,bytes)",
|
||||||
|
["hash", "walletAddress", "signature", "errorData"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
hash: bytes
|
||||||
|
walletAddress: str
|
||||||
|
signature: bytes
|
||||||
|
errorData: bytes
|
||||||
|
|
||||||
|
selector = "0x1b8388f7"
|
||||||
|
|
||||||
|
|
||||||
|
class OrderStatusError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"OrderStatusError(bytes32,uint8)",
|
||||||
|
["orderHash", "orderStatus"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
orderHash: bytes
|
||||||
|
orderStatus: int
|
||||||
|
|
||||||
|
selector = "0xfdb6ca8d"
|
||||||
|
|
||||||
|
|
||||||
|
class ExchangeInvalidContextError(
|
||||||
|
RichRevert
|
||||||
|
): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"ExchangeInvalidContextError(uint8,bytes32,address)",
|
||||||
|
["errorCode", "orderHash", "contextAddress"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
errorCode: ExchangeContextErrorCodes
|
||||||
|
orderHash: bytes
|
||||||
|
contextAddress: str
|
||||||
|
|
||||||
|
selector = "0xe53c76c8"
|
||||||
|
|
||||||
|
|
||||||
|
class FillError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"FillError(uint8,bytes32)", ["errorCode", "orderHash"], return_data
|
||||||
|
)
|
||||||
|
|
||||||
|
errorCode: FillErrorCodes
|
||||||
|
orderHash: bytes
|
||||||
|
|
||||||
|
selector = "0xe94a7ed0"
|
||||||
|
|
||||||
|
|
||||||
|
class OrderEpochError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"OrderEpochError(address,address,uint256)",
|
||||||
|
["makerAddress", "orderSenderAddress", "currentEpoch"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
makerAddress: str
|
||||||
|
orderSenderAddress: str
|
||||||
|
currentEpoch: int
|
||||||
|
|
||||||
|
selector = "0x4ad31275"
|
||||||
|
|
||||||
|
|
||||||
|
class AssetProxyExistsError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"AssetProxyExistsError(bytes4,address)",
|
||||||
|
["assetProxyId", "assetProxyAddress"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
assetProxyId: bytes
|
||||||
|
assetProxyAddress: str
|
||||||
|
|
||||||
|
selector = "0x11c7b720"
|
||||||
|
|
||||||
|
|
||||||
|
class AssetProxyDispatchError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"AssetProxyDispatchError(uint8,bytes32,bytes)",
|
||||||
|
["errorCode", "orderHash", "assetData"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
errorCode: AssetProxyDispatchErrorCodes
|
||||||
|
orderHash: bytes
|
||||||
|
assetData: bytes
|
||||||
|
|
||||||
|
selector = "0x488219a6"
|
||||||
|
|
||||||
|
|
||||||
|
class AssetProxyTransferError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"AssetProxyTransferError(bytes32,bytes,bytes)",
|
||||||
|
["orderHash", "assetData", "errorData"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
orderHash: bytes
|
||||||
|
assetData: bytes
|
||||||
|
errorData: bytes
|
||||||
|
|
||||||
|
selector = "0x4678472b"
|
||||||
|
|
||||||
|
|
||||||
|
class NegativeSpreadError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"NegativeSpreadError(bytes32,bytes32)",
|
||||||
|
["leftOrderHash", "rightOrderHash"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
leftOrderHash: bytes
|
||||||
|
rightOrderHash: bytes
|
||||||
|
|
||||||
|
selector = "0xb6555d6f"
|
||||||
|
|
||||||
|
|
||||||
|
class TransactionError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"TransactionError(uint8,bytes32)",
|
||||||
|
["errorCode", "transactionHash"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
errorCode: TransactionErrorCodes
|
||||||
|
transactionHash: bytes
|
||||||
|
|
||||||
|
selector = "0xf5985184"
|
||||||
|
|
||||||
|
|
||||||
|
class TransactionExecutionError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"TransactionExecutionError(bytes32,bytes)",
|
||||||
|
["transactionHash", "errorData"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
transactionHash: bytes
|
||||||
|
errorData: bytes
|
||||||
|
|
||||||
|
selector = "0x20d11f61"
|
||||||
|
|
||||||
|
|
||||||
|
class TransactionGasPriceError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"TransactionGasPriceError(bytes32,uint256,uint256)",
|
||||||
|
["transactionHash", "actualGasPrice", "requiredGasPrice"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
transactionHash: bytes
|
||||||
|
actualGasPrice: int
|
||||||
|
requiredGasPrice: int
|
||||||
|
|
||||||
|
selector = "0xa26dac09"
|
||||||
|
|
||||||
|
|
||||||
|
class TransactionInvalidContextError(
|
||||||
|
RichRevert
|
||||||
|
): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"TransactionInvalidContextError(bytes32,address)",
|
||||||
|
["transactionHash", "currentContextAddress"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
transactionHash: bytes
|
||||||
|
currentContextAddress: str
|
||||||
|
|
||||||
|
selector = "0xdec4aedf"
|
||||||
|
|
||||||
|
|
||||||
|
class IncompleteFillError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"IncompleteFillError(uint8,uint256,uint256)",
|
||||||
|
["errorCode", "expectedAssetAmount", "actualAssetAmount"],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
errorCode: IncompleteFillErrorCode
|
||||||
|
expectedAssetAmount: int
|
||||||
|
actualAssetAmount: int
|
||||||
|
|
||||||
|
selector = "0x18e4b141"
|
||||||
|
|
||||||
|
|
||||||
|
class BatchMatchOrdersError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"BatchMatchOrdersError(uint8)", ["errorCode"], return_data
|
||||||
|
)
|
||||||
|
|
||||||
|
errorCode: BatchMatchOrdersErrorCodes
|
||||||
|
|
||||||
|
selector = "0xd4092f4f"
|
||||||
|
|
||||||
|
|
||||||
|
class PayProtocolFeeError(RichRevert): # noqa: D101 (missing docstring)
|
||||||
|
def __init__(self, return_data): # noqa: D107 (missing docstring)
|
||||||
|
super().__init__(
|
||||||
|
"PayProtocolFeeError(bytes32,uint256,address,address,bytes)",
|
||||||
|
[
|
||||||
|
"orderHash",
|
||||||
|
"protocolFee",
|
||||||
|
"makerAddress",
|
||||||
|
"takerAddress",
|
||||||
|
"errorData",
|
||||||
|
],
|
||||||
|
return_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
orderHash: bytes
|
||||||
|
protocolFee: int
|
||||||
|
makerAddress: str
|
||||||
|
takerAddress: str
|
||||||
|
errorData: bytes
|
||||||
|
|
||||||
|
selector = "0x87cb1e75"
|
@ -0,0 +1,36 @@
|
|||||||
|
"""Web3.py-compatible middleware to be injected upon contract instantiation."""
|
||||||
|
|
||||||
|
from zero_ex.contract_wrappers.exceptions import (
|
||||||
|
exception_class_from_rich_revert_selector,
|
||||||
|
NoExceptionForSelector,
|
||||||
|
)
|
||||||
|
|
||||||
|
from . import exceptions
|
||||||
|
|
||||||
|
|
||||||
|
def rich_revert_handler(make_request, _):
|
||||||
|
"""Return a middlware to raise exceptions for rich revert return data."""
|
||||||
|
# noqa: D202 (No blank lines allowed after function docstring
|
||||||
|
def middleware(method, params):
|
||||||
|
response = make_request(method, params)
|
||||||
|
try:
|
||||||
|
raise exception_class_from_rich_revert_selector(
|
||||||
|
response["result"][0:10], exceptions
|
||||||
|
)(response["result"])
|
||||||
|
except NoExceptionForSelector:
|
||||||
|
# response prefix didn't indicate a known error
|
||||||
|
pass
|
||||||
|
except TypeError:
|
||||||
|
# eg "unhashable type: 'slice'". if response["result"] isn't
|
||||||
|
# sliceable (eg if it's a dict), then it definitely isn't a rich
|
||||||
|
# revert.
|
||||||
|
pass
|
||||||
|
except KeyError:
|
||||||
|
# response doesn't have a "result" key
|
||||||
|
pass
|
||||||
|
return response
|
||||||
|
|
||||||
|
return middleware
|
||||||
|
|
||||||
|
|
||||||
|
MIDDLEWARE = [{"layer": 0, "function": rich_revert_handler}]
|
@ -11,17 +11,13 @@ Converting between the JSON wire format and the types accepted by Web3.py (eg
|
|||||||
converting Exchange structs between JSON and Python objects.
|
converting Exchange structs between JSON and Python objects.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from copy import copy
|
from enum import auto, Enum
|
||||||
from typing import cast, Dict
|
|
||||||
|
|
||||||
from eth_utils import remove_0x_prefix
|
|
||||||
|
|
||||||
from zero_ex.json_schemas import assert_valid
|
|
||||||
|
|
||||||
from . import (
|
from . import (
|
||||||
Tuple0xbb41e5b3,
|
Tuple0x735c43e3,
|
||||||
Tuple0x260219a2,
|
Tuple0x6ca34a6f,
|
||||||
Tuple0x054ca44e,
|
Tuple0x4c5ca29b,
|
||||||
|
Tuple0xdabc15fe,
|
||||||
Tuple0xb1e4a1ae,
|
Tuple0xb1e4a1ae,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,27 +29,35 @@ from . import (
|
|||||||
# of each of these classes.
|
# of each of these classes.
|
||||||
|
|
||||||
|
|
||||||
class FillResults(Tuple0xbb41e5b3):
|
class FillResults(Tuple0x735c43e3):
|
||||||
"""The `FillResults`:code: Solidity struct.
|
"""The `FillResults`:code: Solidity struct.
|
||||||
|
|
||||||
Also known as
|
Also known as
|
||||||
`zero_ex.contract_wrappers.exchange.Tuple0xbb41e5b3`:py:class:.
|
`zero_ex.contract_wrappers.exchange.Tuple0x735c43e3`:py:class:.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Order(Tuple0x260219a2):
|
class Order(Tuple0x6ca34a6f):
|
||||||
"""The `Order`:code: Solidity struct.
|
"""The `Order`:code: Solidity struct.
|
||||||
|
|
||||||
Also known as
|
Also known as
|
||||||
`zero_ex.contract_wrappers.exchange.Tuple0x260219a2`:py:class:.
|
`zero_ex.contract_wrappers.exchange.Tuple0x6ca34a6f`:py:class:.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class MatchedFillResults(Tuple0x054ca44e):
|
class MatchedFillResults(Tuple0x4c5ca29b):
|
||||||
"""The `MatchedFillResults`:code: Solidity struct.
|
"""The `MatchedFillResults`:code: Solidity struct.
|
||||||
|
|
||||||
Also known as
|
Also known as
|
||||||
`zero_ex.contract_wrappers.exchange.Tuple0x054ca44e`:py:class:.
|
`zero_ex.contract_wrappers.exchange.Tuple0x4c5ca29b`:py:class:.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ZeroExTransaction(Tuple0xdabc15fe):
|
||||||
|
"""The `ZeroExTransaction`:code: Solidity struct.
|
||||||
|
|
||||||
|
Also known as
|
||||||
|
`zero_ex.contract_wrappers.exchange.Tuple0xdabc15fe`:py:class:.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@ -65,136 +69,11 @@ class OrderInfo(Tuple0xb1e4a1ae):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def order_to_jsdict(
|
class OrderStatus(Enum): # noqa: D101 # pylint: disable=missing-docstring
|
||||||
order: Order,
|
INVALID = 0
|
||||||
exchange_address="0x0000000000000000000000000000000000000000",
|
INVALID_MAKER_ASSET_AMOUNT = auto()
|
||||||
signature: str = None,
|
INVALID_TAKER_ASSET_AMOUNT = auto()
|
||||||
) -> dict:
|
FILLABLE = auto()
|
||||||
"""Convert a Web3-compatible order struct to a JSON-schema-compatible dict.
|
EXPIRED = auto()
|
||||||
|
FULLY_FILLED = auto()
|
||||||
More specifically, do explicit decoding for the `bytes`:code: fields, and
|
CANCELLED = auto()
|
||||||
convert numerics to strings.
|
|
||||||
|
|
||||||
>>> 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
|
|
||||||
|
|
||||||
jsdict["expirationTimeSeconds"] = str(order["expirationTimeSeconds"])
|
|
||||||
|
|
||||||
jsdict["makerAssetAmount"] = str(order["makerAssetAmount"])
|
|
||||||
jsdict["takerAssetAmount"] = str(order["takerAssetAmount"])
|
|
||||||
|
|
||||||
jsdict["makerFee"] = str(order["makerFee"])
|
|
||||||
jsdict["takerFee"] = str(order["takerFee"])
|
|
||||||
|
|
||||||
jsdict["salt"] = str(order["salt"])
|
|
||||||
|
|
||||||
if signature is not None:
|
|
||||||
jsdict["signature"] = signature
|
|
||||||
|
|
||||||
assert_valid(jsdict, "/orderSchema")
|
|
||||||
|
|
||||||
return jsdict
|
|
||||||
|
|
||||||
|
|
||||||
def jsdict_to_order(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, and
|
|
||||||
parse integers from strings.
|
|
||||||
|
|
||||||
>>> import pprint
|
|
||||||
>>> pprint.pprint(jsdict_to_order(
|
|
||||||
... {
|
|
||||||
... '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"])
|
|
||||||
)
|
|
||||||
|
|
||||||
order["makerAssetAmount"] = int(jsdict["makerAssetAmount"])
|
|
||||||
order["takerAssetAmount"] = int(jsdict["takerAssetAmount"])
|
|
||||||
|
|
||||||
order["makerFee"] = int(jsdict["makerFee"])
|
|
||||||
order["takerFee"] = int(jsdict["takerFee"])
|
|
||||||
|
|
||||||
order["expirationTimeSeconds"] = int(jsdict["expirationTimeSeconds"])
|
|
||||||
|
|
||||||
order["salt"] = int(jsdict["salt"])
|
|
||||||
|
|
||||||
del order["exchangeAddress"] # type: ignore
|
|
||||||
# silence mypy pending release of
|
|
||||||
# https://github.com/python/mypy/issues/3550
|
|
||||||
|
|
||||||
return order
|
|
||||||
|
@ -1,22 +1,40 @@
|
|||||||
"""Validate inputs to the Exchange contract."""
|
"""Validate inputs to the Exchange contract."""
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any, Union
|
||||||
|
|
||||||
|
from web3 import Web3
|
||||||
from web3.providers.base import BaseProvider
|
from web3.providers.base import BaseProvider
|
||||||
|
|
||||||
from zero_ex import json_schemas
|
from zero_ex import json_schemas
|
||||||
|
from zero_ex.contract_wrappers.order_conversions import order_to_jsdict
|
||||||
|
|
||||||
from ..bases import Validator
|
from ..bases import Validator
|
||||||
from .types import order_to_jsdict
|
|
||||||
|
|
||||||
|
|
||||||
class ExchangeValidator(Validator):
|
class ExchangeValidator(Validator):
|
||||||
"""Validate inputs to Exchange methods."""
|
"""Validate inputs to Exchange methods."""
|
||||||
|
|
||||||
def __init__(self, provider: BaseProvider, contract_address: str):
|
def __init__(
|
||||||
|
self,
|
||||||
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
|
contract_address: str,
|
||||||
|
):
|
||||||
"""Initialize the class."""
|
"""Initialize the class."""
|
||||||
super().__init__(provider, contract_address)
|
super().__init__(web3_or_provider, contract_address)
|
||||||
|
|
||||||
|
web3 = None
|
||||||
|
if isinstance(web3_or_provider, BaseProvider):
|
||||||
|
web3 = Web3(web3_or_provider)
|
||||||
|
elif isinstance(web3_or_provider, Web3):
|
||||||
|
web3 = web3_or_provider
|
||||||
|
if web3 is None:
|
||||||
|
raise TypeError(
|
||||||
|
"Expected parameter 'web3_or_provider' to be an instance of either"
|
||||||
|
+ " Web3 or BaseProvider"
|
||||||
|
)
|
||||||
|
|
||||||
self.contract_address = contract_address
|
self.contract_address = contract_address
|
||||||
|
self.chain_id = web3.eth.chainId
|
||||||
|
|
||||||
def assert_valid(
|
def assert_valid(
|
||||||
self, method_name: str, parameter_name: str, argument_value: Any
|
self, method_name: str, parameter_name: str, argument_value: Any
|
||||||
@ -30,13 +48,17 @@ class ExchangeValidator(Validator):
|
|||||||
"""
|
"""
|
||||||
if parameter_name == "order":
|
if parameter_name == "order":
|
||||||
json_schemas.assert_valid(
|
json_schemas.assert_valid(
|
||||||
order_to_jsdict(argument_value, self.contract_address),
|
order_to_jsdict(
|
||||||
|
argument_value, self.chain_id, self.contract_address
|
||||||
|
),
|
||||||
"/orderSchema",
|
"/orderSchema",
|
||||||
)
|
)
|
||||||
|
|
||||||
if parameter_name == "orders":
|
if parameter_name == "orders":
|
||||||
for order in argument_value:
|
for order in argument_value:
|
||||||
json_schemas.assert_valid(
|
json_schemas.assert_valid(
|
||||||
order_to_jsdict(order, self.contract_address),
|
order_to_jsdict(
|
||||||
|
order, self.chain_id, self.contract_address
|
||||||
|
),
|
||||||
"/orderSchema",
|
"/orderSchema",
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,180 @@
|
|||||||
|
"""Utilities to convert between JSON and Python-native objects."""
|
||||||
|
|
||||||
|
from copy import copy
|
||||||
|
from typing import cast, Dict, Union
|
||||||
|
|
||||||
|
from eth_utils import remove_0x_prefix
|
||||||
|
|
||||||
|
from zero_ex.json_schemas import assert_valid
|
||||||
|
from zero_ex.contract_wrappers.exchange.types import Order
|
||||||
|
|
||||||
|
|
||||||
|
def order_to_jsdict(
|
||||||
|
order: Order,
|
||||||
|
chain_id: int,
|
||||||
|
exchange_address="0x0000000000000000000000000000000000000000",
|
||||||
|
signature: str = None,
|
||||||
|
) -> dict:
|
||||||
|
"""Convert a Web3-compatible order struct to a JSON-schema-compatible dict.
|
||||||
|
|
||||||
|
More specifically, do explicit decoding for the `bytes`:code: fields, and
|
||||||
|
convert numerics to strings.
|
||||||
|
|
||||||
|
>>> 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,
|
||||||
|
... 'makerFeeAssetData': (0).to_bytes(1, byteorder='big') * 20,
|
||||||
|
... 'takerFeeAssetData': (0).to_bytes(1, byteorder='big') * 20,
|
||||||
|
... },
|
||||||
|
... chain_id=50
|
||||||
|
... ))
|
||||||
|
{'chainId': 50,
|
||||||
|
'exchangeAddress': '0x0000000000000000000000000000000000000000',
|
||||||
|
'expirationTimeSeconds': '1',
|
||||||
|
'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
|
||||||
|
'makerAddress': '0x0000000000000000000000000000000000000000',
|
||||||
|
'makerAssetAmount': '1',
|
||||||
|
'makerAssetData': '0x0000000000000000000000000000000000000000',
|
||||||
|
'makerFee': '0',
|
||||||
|
'makerFeeAssetData': '0x0000000000000000000000000000000000000000',
|
||||||
|
'salt': '1',
|
||||||
|
'senderAddress': '0x0000000000000000000000000000000000000000',
|
||||||
|
'takerAddress': '0x0000000000000000000000000000000000000000',
|
||||||
|
'takerAssetAmount': '1',
|
||||||
|
'takerAssetData': '0x0000000000000000000000000000000000000000',
|
||||||
|
'takerFee': '0',
|
||||||
|
'takerFeeAssetData': '0x0000000000000000000000000000000000000000'}
|
||||||
|
"""
|
||||||
|
jsdict = cast(Dict, copy(order))
|
||||||
|
|
||||||
|
def encode_bytes(bytes_or_str: Union[bytes, str]) -> bytes:
|
||||||
|
def ensure_hex_prefix(hex_str: str):
|
||||||
|
if hex_str[0:2] != "0x":
|
||||||
|
hex_str = "0x" + hex_str
|
||||||
|
return hex_str
|
||||||
|
|
||||||
|
return ensure_hex_prefix(
|
||||||
|
cast(bytes, bytes_or_str).hex()
|
||||||
|
if isinstance(bytes_or_str, bytes)
|
||||||
|
else bytes_or_str
|
||||||
|
)
|
||||||
|
|
||||||
|
jsdict["makerAssetData"] = encode_bytes(order["makerAssetData"])
|
||||||
|
jsdict["takerAssetData"] = encode_bytes(order["takerAssetData"])
|
||||||
|
jsdict["makerFeeAssetData"] = encode_bytes(order["makerFeeAssetData"])
|
||||||
|
jsdict["takerFeeAssetData"] = encode_bytes(order["takerFeeAssetData"])
|
||||||
|
|
||||||
|
jsdict["exchangeAddress"] = exchange_address
|
||||||
|
|
||||||
|
jsdict["expirationTimeSeconds"] = str(order["expirationTimeSeconds"])
|
||||||
|
|
||||||
|
jsdict["makerAssetAmount"] = str(order["makerAssetAmount"])
|
||||||
|
jsdict["takerAssetAmount"] = str(order["takerAssetAmount"])
|
||||||
|
|
||||||
|
jsdict["makerFee"] = str(order["makerFee"])
|
||||||
|
jsdict["takerFee"] = str(order["takerFee"])
|
||||||
|
|
||||||
|
jsdict["salt"] = str(order["salt"])
|
||||||
|
|
||||||
|
jsdict["chainId"] = chain_id
|
||||||
|
|
||||||
|
if signature is not None:
|
||||||
|
jsdict["signature"] = signature
|
||||||
|
|
||||||
|
assert_valid(jsdict, "/orderSchema")
|
||||||
|
|
||||||
|
return jsdict
|
||||||
|
|
||||||
|
|
||||||
|
def jsdict_to_order(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, and
|
||||||
|
parse integers from strings.
|
||||||
|
|
||||||
|
>>> import pprint
|
||||||
|
>>> pprint.pprint(jsdict_to_order(
|
||||||
|
... {
|
||||||
|
... 'makerAddress': "0x0000000000000000000000000000000000000000",
|
||||||
|
... 'takerAddress': "0x0000000000000000000000000000000000000000",
|
||||||
|
... 'feeRecipientAddress': "0x0000000000000000000000000000000000000000",
|
||||||
|
... 'senderAddress': "0x0000000000000000000000000000000000000000",
|
||||||
|
... 'makerAssetAmount': "1000000000000000000",
|
||||||
|
... 'takerAssetAmount': "1000000000000000000",
|
||||||
|
... 'makerFee': "0",
|
||||||
|
... 'takerFee': "0",
|
||||||
|
... 'expirationTimeSeconds': "12345",
|
||||||
|
... 'salt': "12345",
|
||||||
|
... 'makerAssetData': "0x0000000000000000000000000000000000000000",
|
||||||
|
... 'takerAssetData': "0x0000000000000000000000000000000000000000",
|
||||||
|
... 'makerFeeAssetData': "0x0000000000000000000000000000000000000000",
|
||||||
|
... 'takerFeeAssetData': "0x0000000000000000000000000000000000000000",
|
||||||
|
... 'exchangeAddress': "0x0000000000000000000000000000000000000000",
|
||||||
|
... 'chainId': 50
|
||||||
|
... },
|
||||||
|
... ))
|
||||||
|
{'chainId': 50,
|
||||||
|
'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,
|
||||||
|
'makerFeeAssetData': b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
b'\x00\x00\x00\x00\x00\x00\x00\x00',
|
||||||
|
'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,
|
||||||
|
'takerFeeAssetData': b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
b'\x00\x00\x00\x00\x00\x00\x00\x00'}
|
||||||
|
""" # noqa: E501 (line too long)
|
||||||
|
assert_valid(jsdict, "/orderSchema")
|
||||||
|
|
||||||
|
order = cast(Order, copy(jsdict))
|
||||||
|
|
||||||
|
order["makerAssetData"] = bytes.fromhex(
|
||||||
|
remove_0x_prefix(jsdict["makerAssetData"])
|
||||||
|
)
|
||||||
|
order["makerFeeAssetData"] = bytes.fromhex(
|
||||||
|
remove_0x_prefix(jsdict["makerFeeAssetData"])
|
||||||
|
)
|
||||||
|
order["takerAssetData"] = bytes.fromhex(
|
||||||
|
remove_0x_prefix(jsdict["takerAssetData"])
|
||||||
|
)
|
||||||
|
order["takerFeeAssetData"] = bytes.fromhex(
|
||||||
|
remove_0x_prefix(jsdict["takerFeeAssetData"])
|
||||||
|
)
|
||||||
|
|
||||||
|
order["makerAssetAmount"] = int(jsdict["makerAssetAmount"])
|
||||||
|
order["takerAssetAmount"] = int(jsdict["takerAssetAmount"])
|
||||||
|
|
||||||
|
order["makerFee"] = int(jsdict["makerFee"])
|
||||||
|
order["takerFee"] = int(jsdict["takerFee"])
|
||||||
|
|
||||||
|
order["expirationTimeSeconds"] = int(jsdict["expirationTimeSeconds"])
|
||||||
|
|
||||||
|
order["salt"] = int(jsdict["salt"])
|
||||||
|
|
||||||
|
del order["exchangeAddress"] # type: ignore
|
||||||
|
# silence mypy pending release of
|
||||||
|
# https://github.com/python/mypy/issues/3550
|
||||||
|
|
||||||
|
return order
|
@ -23,7 +23,7 @@ class TxParams:
|
|||||||
gas: Optional[int] = attr.ib(
|
gas: Optional[int] = attr.ib(
|
||||||
default=None, converter=attr.converters.optional(int)
|
default=None, converter=attr.converters.optional(int)
|
||||||
)
|
)
|
||||||
gasPrice: Optional[int] = attr.ib(
|
gas_price: Optional[int] = attr.ib(
|
||||||
default=None, converter=attr.converters.optional(int)
|
default=None, converter=attr.converters.optional(int)
|
||||||
)
|
)
|
||||||
nonce: Optional[int] = attr.ib(
|
nonce: Optional[int] = attr.ib(
|
||||||
@ -36,4 +36,7 @@ class TxParams:
|
|||||||
if "from_" in res:
|
if "from_" in res:
|
||||||
res["from"] = res["from_"]
|
res["from"] = res["from_"]
|
||||||
del res["from_"]
|
del res["from_"]
|
||||||
|
if "gas_price" in res:
|
||||||
|
res["gasPrice"] = res["gas_price"]
|
||||||
|
del res["gas_price"]
|
||||||
return res
|
return res
|
||||||
|
@ -26,16 +26,24 @@ class Web3:
|
|||||||
class middleware_stack:
|
class middleware_stack:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get(key: str) -> Callable: ...
|
def get(key: str) -> Callable: ...
|
||||||
|
|
||||||
|
def inject(
|
||||||
|
self, middleware_func: object, layer: object
|
||||||
|
) -> None: ...
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
middleware_onion: middleware_stack
|
||||||
|
|
||||||
class net:
|
class net:
|
||||||
version: str
|
version: str
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
class eth:
|
class Eth:
|
||||||
defaultAccount: str
|
defaultAccount: str
|
||||||
accounts: List[str]
|
accounts: List[str]
|
||||||
|
chainId: int
|
||||||
...
|
...
|
||||||
|
|
||||||
class account:
|
class account:
|
||||||
@ -53,4 +61,7 @@ class Web3:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def isAddress(address: str) -> bool: ...
|
def isAddress(address: str) -> bool: ...
|
||||||
...
|
...
|
||||||
|
|
||||||
|
eth: Eth
|
||||||
|
|
||||||
...
|
...
|
||||||
|
@ -5,7 +5,7 @@ from eth_utils import to_checksum_address
|
|||||||
from web3 import Web3
|
from web3 import Web3
|
||||||
|
|
||||||
from zero_ex.order_utils import asset_data_utils
|
from zero_ex.order_utils import asset_data_utils
|
||||||
from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId
|
from zero_ex.contract_addresses import network_to_addresses, NetworkId
|
||||||
from zero_ex.contract_artifacts import abi_by_name
|
from zero_ex.contract_artifacts import abi_by_name
|
||||||
|
|
||||||
|
|
||||||
@ -36,14 +36,14 @@ def accounts(web3_eth): # pylint: disable=redefined-outer-name
|
|||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def erc20_proxy_address():
|
def erc20_proxy_address():
|
||||||
"""Get the 0x ERC20 Proxy address."""
|
"""Get the 0x ERC20 Proxy address."""
|
||||||
return NETWORK_TO_ADDRESSES[NetworkId.GANACHE].erc20_proxy
|
return network_to_addresses(NetworkId.GANACHE).erc20_proxy
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def weth_asset_data(): # pylint: disable=redefined-outer-name
|
def weth_asset_data(): # pylint: disable=redefined-outer-name
|
||||||
"""Get 0x asset data for Wrapped Ether (WETH) token."""
|
"""Get 0x asset data for Wrapped Ether (WETH) token."""
|
||||||
return asset_data_utils.encode_erc20(
|
return asset_data_utils.encode_erc20(
|
||||||
NETWORK_TO_ADDRESSES[NetworkId.GANACHE].ether_token
|
network_to_addresses(NetworkId.GANACHE).ether_token
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ def weth_instance(web3_eth): # pylint: disable=redefined-outer-name
|
|||||||
"""Get an instance of the WrapperEther contract."""
|
"""Get an instance of the WrapperEther contract."""
|
||||||
return web3_eth.contract(
|
return web3_eth.contract(
|
||||||
address=to_checksum_address(
|
address=to_checksum_address(
|
||||||
NETWORK_TO_ADDRESSES[NetworkId.GANACHE].ether_token
|
network_to_addresses(NetworkId.GANACHE).ether_token
|
||||||
),
|
),
|
||||||
abi=abi_by_name("WETH9"),
|
abi=abi_by_name("WETH9"),
|
||||||
)
|
)
|
||||||
@ -61,7 +61,7 @@ def weth_instance(web3_eth): # pylint: disable=redefined-outer-name
|
|||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def zrx_address():
|
def zrx_address():
|
||||||
"""Get address of ZRX token for Ganache network."""
|
"""Get address of ZRX token for Ganache network."""
|
||||||
return NETWORK_TO_ADDRESSES[NetworkId.GANACHE].zrx_token
|
return network_to_addresses(NetworkId.GANACHE).zrx_token
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId
|
from zero_ex.contract_addresses import network_to_addresses, NetworkId
|
||||||
from zero_ex.contract_wrappers.bases import ContractMethod
|
from zero_ex.contract_wrappers.bases import ContractMethod
|
||||||
|
|
||||||
|
|
||||||
@ -10,6 +10,6 @@ from zero_ex.contract_wrappers.bases import ContractMethod
|
|||||||
def contract_wrapper(ganache_provider):
|
def contract_wrapper(ganache_provider):
|
||||||
"""Get a ContractMethod instance for testing."""
|
"""Get a ContractMethod instance for testing."""
|
||||||
return ContractMethod(
|
return ContractMethod(
|
||||||
provider=ganache_provider,
|
web3_or_provider=ganache_provider,
|
||||||
contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].ether_token,
|
contract_address=network_to_addresses(NetworkId.GANACHE).ether_token,
|
||||||
)
|
)
|
||||||
|
@ -4,7 +4,7 @@ from decimal import Decimal
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId
|
from zero_ex.contract_addresses import network_to_addresses, NetworkId
|
||||||
from zero_ex.contract_wrappers import TxParams
|
from zero_ex.contract_wrappers import TxParams
|
||||||
from zero_ex.contract_wrappers.erc20_token import ERC20Token
|
from zero_ex.contract_wrappers.erc20_token import ERC20Token
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ MAX_ALLOWANCE = int("{:.0f}".format(Decimal(2) ** 256 - 1))
|
|||||||
def erc20_wrapper(ganache_provider):
|
def erc20_wrapper(ganache_provider):
|
||||||
"""Get an instance of ERC20Token wrapper class for testing."""
|
"""Get an instance of ERC20Token wrapper class for testing."""
|
||||||
return ERC20Token(
|
return ERC20Token(
|
||||||
ganache_provider, NETWORK_TO_ADDRESSES[NetworkId.GANACHE].ether_token
|
ganache_provider, network_to_addresses(NetworkId.GANACHE).ether_token
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,20 +5,24 @@ import random
|
|||||||
import pytest
|
import pytest
|
||||||
from eth_utils import remove_0x_prefix
|
from eth_utils import remove_0x_prefix
|
||||||
|
|
||||||
from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId
|
from zero_ex.contract_addresses import network_to_addresses, NetworkId
|
||||||
from zero_ex.contract_wrappers import TxParams
|
from zero_ex.contract_wrappers import TxParams
|
||||||
from zero_ex.contract_wrappers.exchange import Exchange
|
from zero_ex.contract_wrappers.exchange import Exchange
|
||||||
from zero_ex.contract_wrappers.exchange.types import Order
|
from zero_ex.contract_wrappers.exchange.types import Order
|
||||||
from zero_ex.json_schemas import assert_valid
|
from zero_ex.json_schemas import assert_valid
|
||||||
from zero_ex.order_utils import generate_order_hash_hex, sign_hash_to_bytes
|
from zero_ex.order_utils import (
|
||||||
|
asset_data_utils,
|
||||||
|
generate_order_hash_hex,
|
||||||
|
sign_hash,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def exchange_wrapper(ganache_provider):
|
def exchange_wrapper(ganache_provider):
|
||||||
"""Get an Exchange wrapper instance."""
|
"""Get an Exchange wrapper instance."""
|
||||||
return Exchange(
|
return Exchange(
|
||||||
provider=ganache_provider,
|
web3_or_provider=ganache_provider,
|
||||||
contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].exchange,
|
contract_address=network_to_addresses(NetworkId.GANACHE).exchange,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -43,6 +47,8 @@ def create_test_order(
|
|||||||
salt=random.randint(1, 1000000000),
|
salt=random.randint(1, 1000000000),
|
||||||
makerAssetData=maker_asset_data,
|
makerAssetData=maker_asset_data,
|
||||||
takerAssetData=taker_asset_data,
|
takerAssetData=taker_asset_data,
|
||||||
|
makerFeeAssetData=asset_data_utils.encode_erc20("0x" + "00" * 20),
|
||||||
|
takerFeeAssetData=asset_data_utils.encode_erc20("0x" + "00" * 20),
|
||||||
)
|
)
|
||||||
return order
|
return order
|
||||||
|
|
||||||
@ -67,16 +73,29 @@ def test_exchange_wrapper__fill_order(
|
|||||||
exchange_wrapper, # pylint: disable=redefined-outer-name
|
exchange_wrapper, # pylint: disable=redefined-outer-name
|
||||||
ganache_provider,
|
ganache_provider,
|
||||||
weth_asset_data,
|
weth_asset_data,
|
||||||
|
zrx_asset_data,
|
||||||
):
|
):
|
||||||
"""Test filling an order."""
|
"""Test filling an order."""
|
||||||
taker = accounts[0]
|
taker = accounts[0]
|
||||||
maker = accounts[1]
|
maker = accounts[1]
|
||||||
exchange_address = exchange_wrapper.contract_address
|
exchange_address = exchange_wrapper.contract_address
|
||||||
order = create_test_order(maker, 1, weth_asset_data, 1, weth_asset_data)
|
order = create_test_order(maker, 1, weth_asset_data, 1, zrx_asset_data)
|
||||||
order_hash = generate_order_hash_hex(
|
order_hash = generate_order_hash_hex(
|
||||||
order=order, exchange_address=exchange_address
|
order=order, exchange_address=exchange_address, chain_id=1337
|
||||||
)
|
)
|
||||||
order_signature = sign_hash_to_bytes(ganache_provider, maker, order_hash)
|
order_signature = sign_hash(ganache_provider, maker, order_hash)
|
||||||
|
|
||||||
|
fill_results = exchange_wrapper.fill_order.call(
|
||||||
|
order=order,
|
||||||
|
taker_asset_fill_amount=order["takerAssetAmount"],
|
||||||
|
signature=order_signature,
|
||||||
|
tx_params=TxParams(from_=taker),
|
||||||
|
)
|
||||||
|
assert fill_results[0] == 1
|
||||||
|
assert fill_results[1] == 1
|
||||||
|
assert fill_results[2] == 0
|
||||||
|
assert fill_results[3] == 0
|
||||||
|
assert fill_results[4] == 0
|
||||||
|
|
||||||
tx_hash = exchange_wrapper.fill_order.send_transaction(
|
tx_hash = exchange_wrapper.fill_order.send_transaction(
|
||||||
order=order,
|
order=order,
|
||||||
@ -107,11 +126,13 @@ def test_exchange_wrapper__batch_fill_orders(
|
|||||||
orders.append(order_1)
|
orders.append(order_1)
|
||||||
orders.append(order_2)
|
orders.append(order_2)
|
||||||
order_hashes = [
|
order_hashes = [
|
||||||
generate_order_hash_hex(order=order, exchange_address=exchange_address)
|
generate_order_hash_hex(
|
||||||
|
order=order, exchange_address=exchange_address, chain_id=1337
|
||||||
|
)
|
||||||
for order in orders
|
for order in orders
|
||||||
]
|
]
|
||||||
order_signatures = [
|
order_signatures = [
|
||||||
sign_hash_to_bytes(ganache_provider, maker, order_hash)
|
sign_hash(ganache_provider, maker, order_hash)
|
||||||
for order_hash in order_hashes
|
for order_hash in order_hashes
|
||||||
]
|
]
|
||||||
taker_amounts = [order["takerAssetAmount"] for order in orders]
|
taker_amounts = [order["takerAssetAmount"] for order in orders]
|
||||||
@ -128,3 +149,20 @@ def test_exchange_wrapper__batch_fill_orders(
|
|||||||
assert_fill_log(
|
assert_fill_log(
|
||||||
fill_events[index].args, maker, taker, order, order_hashes[index]
|
fill_events[index].args, maker, taker, order, order_hashes[index]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_two_instantiations_with_web3_objects(web3_instance):
|
||||||
|
"""Test that instantiating two Exchange objects doesn't raise.
|
||||||
|
|
||||||
|
When instantiating an Exchange object with a web3 client (rather than a
|
||||||
|
provider) there was a bug encountered where web3.py was giving an error
|
||||||
|
when trying to install the rich-revert-handling middleware on the web3
|
||||||
|
client, an error saying "can't install this same middleware instance
|
||||||
|
again." Test that that bug isn't occurring.
|
||||||
|
"""
|
||||||
|
exchange = Exchange( # pylint: disable=unused-variable
|
||||||
|
web3_instance, network_to_addresses(NetworkId.GANACHE).exchange
|
||||||
|
)
|
||||||
|
exchange2 = Exchange( # pylint: disable=unused-variable
|
||||||
|
web3_instance, network_to_addresses(NetworkId.GANACHE).exchange
|
||||||
|
)
|
||||||
|
@ -20,6 +20,7 @@ commands =
|
|||||||
pytest test
|
pytest test
|
||||||
|
|
||||||
[testenv:run_tests_against_deployment]
|
[testenv:run_tests_against_deployment]
|
||||||
|
setenv = PY_IGNORE_IMPORTMISMATCH = 1
|
||||||
commands =
|
commands =
|
||||||
pip install 0x-contract-wrappers
|
pip install 0x-contract-wrappers[dev]
|
||||||
pytest test
|
pytest --doctest-modules src test
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 1.1.1 - TBD
|
||||||
|
|
||||||
|
- Removed dev dependency on package `0x-contract-wrappers`
|
||||||
|
|
||||||
## 1.1.0 - 2019-08-09
|
## 1.1.0 - 2019-08-09
|
||||||
|
|
||||||
- Added `verifyingContractAddress` to `/zeroExTransactionSchema`.
|
- Added `verifyingContractAddress` to `/zeroExTransactionSchema`.
|
||||||
|
@ -2,12 +2,16 @@
|
|||||||
|
|
||||||
"""setuptools module for json_schemas package."""
|
"""setuptools module for json_schemas package."""
|
||||||
|
|
||||||
|
# pylint: disable=import-outside-toplevel
|
||||||
|
# we import things outside of top-level because 3rd party libs may not yet be
|
||||||
|
# installed when you invoke this script
|
||||||
|
|
||||||
import distutils.command.build_py
|
import distutils.command.build_py
|
||||||
from distutils.command.clean import clean
|
from distutils.command.clean import clean
|
||||||
import subprocess # nosec
|
import subprocess # nosec
|
||||||
from shutil import copytree, rmtree
|
from shutil import copytree, rmtree
|
||||||
from os import environ, path
|
from os import environ, path
|
||||||
from sys import argv
|
from sys import argv, exit # pylint: disable=redefined-builtin
|
||||||
|
|
||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
from setuptools.command.test import test as TestCommand
|
from setuptools.command.test import test as TestCommand
|
||||||
@ -139,7 +143,7 @@ with open("README.md", "r") as file_handle:
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="0x-json-schemas",
|
name="0x-json-schemas",
|
||||||
version="1.1.0",
|
version="1.1.1",
|
||||||
description="JSON schemas for 0x applications",
|
description="JSON schemas for 0x applications",
|
||||||
long_description=README_MD,
|
long_description=README_MD,
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
@ -162,11 +166,11 @@ setup(
|
|||||||
extras_require={
|
extras_require={
|
||||||
"dev": [
|
"dev": [
|
||||||
"0x-contract-addresses",
|
"0x-contract-addresses",
|
||||||
"0x-contract-wrappers",
|
|
||||||
"bandit",
|
"bandit",
|
||||||
"black",
|
"black",
|
||||||
"coverage",
|
"coverage",
|
||||||
"coveralls",
|
"coveralls",
|
||||||
|
"eth_utils",
|
||||||
"mypy",
|
"mypy",
|
||||||
"mypy_extensions",
|
"mypy_extensions",
|
||||||
"pycodestyle",
|
"pycodestyle",
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
"""0x Python API."""
|
"""0x Python API."""
|
||||||
__import__("pkg_resources").declare_namespace(__name__)
|
__import__("pkg_resources").declare_namespace(__name__) # type: ignore
|
||||||
|
@ -60,36 +60,38 @@ def assert_valid(data: Mapping, schema_id: str) -> None:
|
|||||||
Raises an exception if validation fails.
|
Raises an exception if validation fails.
|
||||||
|
|
||||||
>>> from zero_ex.json_schemas import assert_valid
|
>>> from zero_ex.json_schemas import assert_valid
|
||||||
>>> from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId
|
>>> from zero_ex.contract_addresses import network_to_addresses, NetworkId
|
||||||
>>> from zero_ex.contract_wrappers.exchange.types import (
|
|
||||||
... Order, order_to_jsdict
|
|
||||||
... )
|
|
||||||
>>> from zero_ex.order_utils import asset_data_utils
|
|
||||||
>>> from eth_utils import remove_0x_prefix
|
>>> from eth_utils import remove_0x_prefix
|
||||||
>>> import random
|
>>> import random
|
||||||
>>> from datetime import datetime, timedelta
|
>>> from datetime import datetime, timedelta
|
||||||
>>> example_order = Order(
|
>>> assert_valid(
|
||||||
... makerAddress='0x5409ed021d9299bf6814279a6a1411a7e866a631',
|
... {'makerAddress': '0x5409ed021d9299bf6814279a6a1411a7e866a631',
|
||||||
... takerAddress='0x0000000000000000000000000000000000000000',
|
... 'takerAddress': '0x0000000000000000000000000000000000000000',
|
||||||
... senderAddress='0x0000000000000000000000000000000000000000',
|
... 'senderAddress': '0x0000000000000000000000000000000000000000',
|
||||||
... exchangeAddress='0x4f833a24e1f95d70f028921e27040ca56e09ab0b',
|
... 'exchangeAddress': '0x4f833a24e1f95d70f028921e27040ca56e09ab0b',
|
||||||
... feeRecipientAddress='0x0000000000000000000000000000000000000000',
|
... 'feeRecipientAddress': (
|
||||||
... makerAssetData=asset_data_utils.encode_erc20(
|
... '0x0000000000000000000000000000000000000000'
|
||||||
... NETWORK_TO_ADDRESSES[NetworkId.MAINNET].zrx_token
|
... ),
|
||||||
... ),
|
... 'makerAssetData': (
|
||||||
... takerAssetData=asset_data_utils.encode_erc20(
|
... network_to_addresses(NetworkId.MAINNET).zrx_token
|
||||||
... NETWORK_TO_ADDRESSES[NetworkId.MAINNET].ether_token
|
... ),
|
||||||
... ),
|
... 'takerAssetData': (
|
||||||
... salt=random.randint(1, 100000000000000000),
|
... network_to_addresses(NetworkId.MAINNET).ether_token
|
||||||
... makerFee=0,
|
... ),
|
||||||
... takerFee=0,
|
... 'salt': random.randint(1, 100000000000000000),
|
||||||
... makerAssetAmount=1000000000000000000,
|
... 'makerFee': 0,
|
||||||
... takerAssetAmount=500000000000000000000,
|
... 'makerFeeAssetData': '0x' + '00'*20,
|
||||||
... expirationTimeSeconds=round(
|
... 'takerFee': 0,
|
||||||
... (datetime.utcnow() + timedelta(days=1)).timestamp()
|
... 'takerFeeAssetData': '0x' + '00'*20,
|
||||||
... )
|
... 'makerAssetAmount': 1000000000000000000,
|
||||||
|
... 'takerAssetAmount': 500000000000000000000,
|
||||||
|
... 'expirationTimeSeconds': round(
|
||||||
|
... (datetime.utcnow() + timedelta(days=1)).timestamp()
|
||||||
|
... ),
|
||||||
|
... 'chainId': 50
|
||||||
|
... },
|
||||||
|
... "/orderSchema"
|
||||||
... )
|
... )
|
||||||
>>> assert_valid(order_to_jsdict(example_order), "/orderSchema")
|
|
||||||
"""
|
"""
|
||||||
_, schema = _LOCAL_RESOLVER.resolve(schema_id)
|
_, schema = _LOCAL_RESOLVER.resolve(schema_id)
|
||||||
jsonschema.validate(data, schema, resolver=_LOCAL_RESOLVER)
|
jsonschema.validate(data, schema, resolver=_LOCAL_RESOLVER)
|
||||||
|
@ -15,11 +15,14 @@ EMPTY_ORDER = {
|
|||||||
"takerAssetData": NULL_ADDRESS,
|
"takerAssetData": NULL_ADDRESS,
|
||||||
"salt": "0",
|
"salt": "0",
|
||||||
"makerFee": "0",
|
"makerFee": "0",
|
||||||
|
"makerFeeAssetData": NULL_ADDRESS,
|
||||||
"takerFee": "0",
|
"takerFee": "0",
|
||||||
|
"takerFeeAssetData": NULL_ADDRESS,
|
||||||
"makerAssetAmount": "0",
|
"makerAssetAmount": "0",
|
||||||
"takerAssetAmount": "0",
|
"takerAssetAmount": "0",
|
||||||
"expirationTimeSeconds": "0",
|
"expirationTimeSeconds": "0",
|
||||||
"exchangeAddress": NULL_ADDRESS,
|
"exchangeAddress": NULL_ADDRESS,
|
||||||
|
"chainId": 50,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ commands =
|
|||||||
pytest test
|
pytest test
|
||||||
|
|
||||||
[testenv:run_tests_against_deployment]
|
[testenv:run_tests_against_deployment]
|
||||||
|
setenv = PY_IGNORE_IMPORTMISMATCH = 1
|
||||||
commands =
|
commands =
|
||||||
pip install 0x-json-schemas
|
pip install 0x-json-schemas[dev]
|
||||||
pytest test
|
pytest --doctest-modules src test
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 1.0.0 - 2019-04-30
|
## 1.0.0 - TBD
|
||||||
|
|
||||||
- Initial release.
|
- Initial release.
|
||||||
|
@ -2,10 +2,14 @@
|
|||||||
|
|
||||||
"""setuptools module for middlewares package."""
|
"""setuptools module for middlewares package."""
|
||||||
|
|
||||||
|
# pylint: disable=import-outside-toplevel
|
||||||
|
# we import things outside of top-level because 3rd party libs may not yet be
|
||||||
|
# installed when you invoke this script
|
||||||
|
|
||||||
import subprocess # nosec
|
import subprocess # nosec
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
from os import environ, path
|
from os import environ, path
|
||||||
from sys import argv
|
from sys import argv, exit # pylint: disable=redefined-builtin
|
||||||
|
|
||||||
from distutils.command.clean import clean
|
from distutils.command.clean import clean
|
||||||
import distutils.command.build_py
|
import distutils.command.build_py
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
"""0x Python API."""
|
"""0x Python API."""
|
||||||
__import__("pkg_resources").declare_namespace(__name__)
|
__import__("pkg_resources").declare_namespace(__name__) # type: ignore
|
||||||
|
@ -3,25 +3,21 @@
|
|||||||
from eth_utils import to_checksum_address
|
from eth_utils import to_checksum_address
|
||||||
from web3 import Web3, HTTPProvider
|
from web3 import Web3, HTTPProvider
|
||||||
|
|
||||||
from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId
|
from zero_ex.contract_addresses import network_to_addresses, NetworkId
|
||||||
from zero_ex.middlewares.local_message_signer import (
|
from zero_ex.middlewares.local_message_signer import (
|
||||||
construct_local_message_signer,
|
construct_local_message_signer,
|
||||||
)
|
)
|
||||||
from zero_ex.order_utils import (
|
from zero_ex.order_utils import generate_order_hash_hex, sign_hash
|
||||||
generate_order_hash_hex,
|
|
||||||
is_valid_signature,
|
|
||||||
sign_hash,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_local_message_signer__sign_order():
|
def test_local_message_signer__sign_order():
|
||||||
"""Test signing order with the local_message_signer middleware"""
|
"""Test signing order with the local_message_signer middleware"""
|
||||||
expected_signature = (
|
expected_signature = (
|
||||||
"0x1cd17d75b891accf16030c572a64cf9e7955de63bcafa5b084439cec630ade2d7"
|
"0x1c8bdfbb3ce3ed0f38c5a358a7f49ad5f21ea9857224c2fe98c458f2fa25551d4"
|
||||||
"c00f47a2f4d5b6a4508267bf4b8527100bd97cf1af9984c0a58e42d25b13f4f0a03"
|
"d6db0157d9dfe9f9fadb8dedabb7786352843357f4ec8d0fbcbeeb619b1091f5803"
|
||||||
)
|
)
|
||||||
address = "0x5409ED021D9299bf6814279A6A1411A7e866A631"
|
address = "0x5409ED021D9299bf6814279A6A1411A7e866A631"
|
||||||
exchange = NETWORK_TO_ADDRESSES[NetworkId.GANACHE].exchange
|
exchange = network_to_addresses(NetworkId.GANACHE).exchange
|
||||||
private_key = (
|
private_key = (
|
||||||
"f2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e0164837257d"
|
"f2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e0164837257d"
|
||||||
)
|
)
|
||||||
@ -36,7 +32,9 @@ def test_local_message_signer__sign_order():
|
|||||||
"senderAddress": "0x0000000000000000000000000000000000000000",
|
"senderAddress": "0x0000000000000000000000000000000000000000",
|
||||||
"feeRecipientAddress": "0x0000000000000000000000000000000000000000",
|
"feeRecipientAddress": "0x0000000000000000000000000000000000000000",
|
||||||
"makerAssetData": (b"\x00") * 20,
|
"makerAssetData": (b"\x00") * 20,
|
||||||
|
"makerFeeAssetData": (b"\x00") * 20,
|
||||||
"takerAssetData": (b"\x00") * 20,
|
"takerAssetData": (b"\x00") * 20,
|
||||||
|
"takerFeeAssetData": (b"\x00") * 20,
|
||||||
"salt": 0,
|
"salt": 0,
|
||||||
"makerFee": 0,
|
"makerFee": 0,
|
||||||
"takerFee": 0,
|
"takerFee": 0,
|
||||||
@ -44,8 +42,11 @@ def test_local_message_signer__sign_order():
|
|||||||
"takerAssetAmount": 0,
|
"takerAssetAmount": 0,
|
||||||
"expirationTimeSeconds": 0,
|
"expirationTimeSeconds": 0,
|
||||||
}
|
}
|
||||||
order_hash = generate_order_hash_hex(order, exchange)
|
assert (
|
||||||
signature = sign_hash(ganache, to_checksum_address(address), order_hash)
|
sign_hash(
|
||||||
assert signature == expected_signature
|
web3_instance,
|
||||||
is_valid = is_valid_signature(ganache, order_hash, signature, address)[0]
|
to_checksum_address(address),
|
||||||
assert is_valid is True
|
generate_order_hash_hex(order, exchange, chain_id=1337),
|
||||||
|
)
|
||||||
|
== expected_signature
|
||||||
|
)
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 4.0.0 - TBD
|
||||||
|
|
||||||
|
- Upgraded to protocol version 3.
|
||||||
|
- `is_valid_signature()` now returns just a boolean. (Formerly, it returned a tuple consisting of the boolean and a reason string.)
|
||||||
|
- Allow `sign_hash()` to be called with EITHER a Web3.py `BaseProvider` OR an already-instantiated `Web3` client object.
|
||||||
|
|
||||||
## 3.0.1 - 2019-08-09
|
## 3.0.1 - 2019-08-09
|
||||||
|
|
||||||
- Fixed dependencies: changed `deprecated` from being an extras_require["dev"] dependency to being an install_requires dependency, since it's required not just for doc generation but also just to import the package.
|
- Fixed dependencies: changed `deprecated` from being an extras_require["dev"] dependency to being an install_requires dependency, since it's required not just for doc generation but also just to import the package.
|
||||||
|
@ -2,11 +2,15 @@
|
|||||||
|
|
||||||
"""setuptools module for order_utils package."""
|
"""setuptools module for order_utils package."""
|
||||||
|
|
||||||
|
# pylint: disable=import-outside-toplevel
|
||||||
|
# we import things outside of top-level because 3rd party libs may not yet be
|
||||||
|
# installed when you invoke this script
|
||||||
|
|
||||||
import subprocess # nosec
|
import subprocess # nosec
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
from os import environ, path
|
from os import environ, path
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from sys import argv
|
from sys import argv, exit # pylint: disable=redefined-builtin
|
||||||
|
|
||||||
from distutils.command.clean import clean
|
from distutils.command.clean import clean
|
||||||
import distutils.command.build_py
|
import distutils.command.build_py
|
||||||
@ -152,7 +156,7 @@ with open("README.md", "r") as file_handle:
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="0x-order-utils",
|
name="0x-order-utils",
|
||||||
version="3.0.1",
|
version="4.0.0",
|
||||||
description="Order utilities for 0x applications",
|
description="Order utilities for 0x applications",
|
||||||
long_description=README_MD,
|
long_description=README_MD,
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
"""0x Python API."""
|
"""0x Python API."""
|
||||||
__import__("pkg_resources").declare_namespace(__name__)
|
__import__("pkg_resources").declare_namespace(__name__) # type: ignore
|
||||||
|
@ -18,9 +18,9 @@ just this purpose. To start it:
|
|||||||
|
|
||||||
from enum import auto, Enum
|
from enum import auto, Enum
|
||||||
import json
|
import json
|
||||||
from typing import Tuple
|
from typing import cast, Tuple, Union
|
||||||
from pkg_resources import resource_string
|
|
||||||
|
|
||||||
|
from pkg_resources import resource_string
|
||||||
from mypy_extensions import TypedDict
|
from mypy_extensions import TypedDict
|
||||||
|
|
||||||
from eth_utils import keccak, remove_0x_prefix, to_bytes, to_checksum_address
|
from eth_utils import keccak, remove_0x_prefix, to_bytes, to_checksum_address
|
||||||
@ -29,9 +29,11 @@ import web3.exceptions
|
|||||||
from web3.providers.base import BaseProvider
|
from web3.providers.base import BaseProvider
|
||||||
from web3.contract import Contract
|
from web3.contract import Contract
|
||||||
|
|
||||||
from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId
|
from zero_ex.contract_addresses import network_to_addresses, NetworkId
|
||||||
import zero_ex.contract_artifacts
|
import zero_ex.contract_artifacts
|
||||||
from zero_ex.contract_wrappers.exchange.types import Order, order_to_jsdict
|
from zero_ex.contract_wrappers.exchange import Exchange
|
||||||
|
from zero_ex.contract_wrappers.exchange.types import Order
|
||||||
|
from zero_ex.contract_wrappers.order_conversions import order_to_jsdict
|
||||||
from zero_ex.dev_utils.type_assertions import (
|
from zero_ex.dev_utils.type_assertions import (
|
||||||
assert_is_address,
|
assert_is_address,
|
||||||
assert_is_hex_string,
|
assert_is_hex_string,
|
||||||
@ -48,13 +50,18 @@ class _Constants:
|
|||||||
eip191_header = b"\x19\x01"
|
eip191_header = b"\x19\x01"
|
||||||
|
|
||||||
eip712_domain_separator_schema_hash = keccak(
|
eip712_domain_separator_schema_hash = keccak(
|
||||||
b"EIP712Domain(string name,string version,address verifyingContract)"
|
b"EIP712Domain("
|
||||||
|
+ b"string name,"
|
||||||
|
+ b"string version,"
|
||||||
|
+ b"uint256 chainId,"
|
||||||
|
+ b"address verifyingContract"
|
||||||
|
+ b")"
|
||||||
)
|
)
|
||||||
|
|
||||||
eip712_domain_struct_header = (
|
eip712_domain_struct_header = (
|
||||||
eip712_domain_separator_schema_hash
|
eip712_domain_separator_schema_hash
|
||||||
+ keccak(b"0x Protocol")
|
+ keccak(b"0x Protocol")
|
||||||
+ keccak(b"2")
|
+ keccak(b"3.0.0")
|
||||||
)
|
)
|
||||||
|
|
||||||
eip712_order_schema_hash = keccak(
|
eip712_order_schema_hash = keccak(
|
||||||
@ -70,7 +77,9 @@ class _Constants:
|
|||||||
+ b"uint256 expirationTimeSeconds,"
|
+ b"uint256 expirationTimeSeconds,"
|
||||||
+ b"uint256 salt,"
|
+ b"uint256 salt,"
|
||||||
+ b"bytes makerAssetData,"
|
+ b"bytes makerAssetData,"
|
||||||
+ b"bytes takerAssetData"
|
+ b"bytes takerAssetData,"
|
||||||
|
+ b"bytes makerFeeAssetData,"
|
||||||
|
+ b"bytes takerFeeAssetData"
|
||||||
+ b")"
|
+ b")"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -87,7 +96,9 @@ class _Constants:
|
|||||||
N_SIGNATURE_TYPES = auto()
|
N_SIGNATURE_TYPES = auto()
|
||||||
|
|
||||||
|
|
||||||
def generate_order_hash_hex(order: Order, exchange_address: str) -> str:
|
def generate_order_hash_hex(
|
||||||
|
order: Order, exchange_address: str, chain_id: int
|
||||||
|
) -> str:
|
||||||
"""Calculate the hash of the given order as a hexadecimal string.
|
"""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 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>`_.
|
||||||
@ -95,27 +106,35 @@ def generate_order_hash_hex(order: Order, exchange_address: str) -> str:
|
|||||||
contract has been deployed.
|
contract has been deployed.
|
||||||
:returns: A string, of ASCII hex digits, representing the order hash.
|
:returns: A string, of ASCII hex digits, representing the order hash.
|
||||||
|
|
||||||
|
Inputs and expected result below were copied from
|
||||||
|
@0x/order-utils/test/order_hash_test.ts
|
||||||
|
|
||||||
>>> generate_order_hash_hex(
|
>>> generate_order_hash_hex(
|
||||||
... Order(
|
... Order(
|
||||||
... makerAddress="0x0000000000000000000000000000000000000000",
|
... makerAddress="0x0000000000000000000000000000000000000000",
|
||||||
... takerAddress="0x0000000000000000000000000000000000000000",
|
... takerAddress="0x0000000000000000000000000000000000000000",
|
||||||
... feeRecipientAddress="0x0000000000000000000000000000000000000000",
|
... feeRecipientAddress="0x0000000000000000000000000000000000000000",
|
||||||
... senderAddress="0x0000000000000000000000000000000000000000",
|
... senderAddress="0x0000000000000000000000000000000000000000",
|
||||||
... makerAssetAmount="1000000000000000000",
|
... makerAssetAmount="0",
|
||||||
... takerAssetAmount="1000000000000000000",
|
... takerAssetAmount="0",
|
||||||
... makerFee="0",
|
... makerFee="0",
|
||||||
... takerFee="0",
|
... takerFee="0",
|
||||||
... expirationTimeSeconds="12345",
|
... expirationTimeSeconds="0",
|
||||||
... salt="12345",
|
... salt="0",
|
||||||
... makerAssetData=((0).to_bytes(1, byteorder='big') * 20),
|
... makerAssetData=((0).to_bytes(1, byteorder='big') * 20),
|
||||||
... takerAssetData=((0).to_bytes(1, byteorder='big') * 20),
|
... takerAssetData=((0).to_bytes(1, byteorder='big') * 20),
|
||||||
|
... makerFeeAssetData=((0).to_bytes(1, byteorder='big') * 20),
|
||||||
|
... takerFeeAssetData=((0).to_bytes(1, byteorder='big') * 20),
|
||||||
... ),
|
... ),
|
||||||
... exchange_address="0x0000000000000000000000000000000000000000",
|
... exchange_address="0x1dc4c1cefef38a777b15aa20260a54e584b16c48",
|
||||||
|
... chain_id=50
|
||||||
... )
|
... )
|
||||||
'55eaa6ec02f3224d30873577e9ddd069a288c16d6fb407210eecbc501fa76692'
|
'331cb7e07a757bae130702da6646c26531798c92bcfaf671817268fd2c188531'
|
||||||
""" # noqa: E501 (line too long)
|
""" # noqa: E501 (line too long)
|
||||||
assert_is_address(exchange_address, "exchange_address")
|
assert_is_address(exchange_address, "exchange_address")
|
||||||
assert_valid(order_to_jsdict(order, exchange_address), "/orderSchema")
|
assert_valid(
|
||||||
|
order_to_jsdict(order, chain_id, exchange_address), "/orderSchema"
|
||||||
|
)
|
||||||
|
|
||||||
def pad_20_bytes_to_32(twenty_bytes: bytes):
|
def pad_20_bytes_to_32(twenty_bytes: bytes):
|
||||||
return bytes(12) + twenty_bytes
|
return bytes(12) + twenty_bytes
|
||||||
@ -125,9 +144,17 @@ def generate_order_hash_hex(order: Order, exchange_address: str) -> str:
|
|||||||
|
|
||||||
eip712_domain_struct_hash = keccak(
|
eip712_domain_struct_hash = keccak(
|
||||||
_Constants.eip712_domain_struct_header
|
_Constants.eip712_domain_struct_header
|
||||||
|
+ int_to_32_big_endian_bytes(int(chain_id))
|
||||||
+ pad_20_bytes_to_32(to_bytes(hexstr=exchange_address))
|
+ pad_20_bytes_to_32(to_bytes(hexstr=exchange_address))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def ensure_bytes(str_or_bytes: Union[str, bytes]) -> bytes:
|
||||||
|
return (
|
||||||
|
to_bytes(hexstr=cast(bytes, str_or_bytes))
|
||||||
|
if isinstance(str_or_bytes, str)
|
||||||
|
else str_or_bytes
|
||||||
|
)
|
||||||
|
|
||||||
eip712_order_struct_hash = keccak(
|
eip712_order_struct_hash = keccak(
|
||||||
_Constants.eip712_order_schema_hash
|
_Constants.eip712_order_schema_hash
|
||||||
+ pad_20_bytes_to_32(to_bytes(hexstr=order["makerAddress"]))
|
+ pad_20_bytes_to_32(to_bytes(hexstr=order["makerAddress"]))
|
||||||
@ -140,8 +167,10 @@ def generate_order_hash_hex(order: Order, exchange_address: str) -> str:
|
|||||||
+ int_to_32_big_endian_bytes(int(order["takerFee"]))
|
+ 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["expirationTimeSeconds"]))
|
||||||
+ int_to_32_big_endian_bytes(int(order["salt"]))
|
+ int_to_32_big_endian_bytes(int(order["salt"]))
|
||||||
+ keccak(to_bytes(hexstr=order["makerAssetData"].hex()))
|
+ keccak(ensure_bytes(order["makerAssetData"]))
|
||||||
+ keccak(to_bytes(hexstr=order["takerAssetData"].hex()))
|
+ keccak(ensure_bytes(order["takerAssetData"]))
|
||||||
|
+ keccak(ensure_bytes(order["makerFeeAssetData"]))
|
||||||
|
+ keccak(ensure_bytes(order["takerFeeAssetData"]))
|
||||||
)
|
)
|
||||||
|
|
||||||
return keccak(
|
return keccak(
|
||||||
@ -153,7 +182,7 @@ def generate_order_hash_hex(order: Order, exchange_address: str) -> str:
|
|||||||
|
|
||||||
def is_valid_signature(
|
def is_valid_signature(
|
||||||
provider: BaseProvider, data: str, signature: str, signer_address: str
|
provider: BaseProvider, data: str, signature: str, signer_address: str
|
||||||
) -> Tuple[bool, str]:
|
) -> bool:
|
||||||
"""Check the validity of the supplied signature.
|
"""Check the validity of the supplied signature.
|
||||||
|
|
||||||
Check if the supplied `signature`:code: corresponds to signing `data`:code:
|
Check if the supplied `signature`:code: corresponds to signing `data`:code:
|
||||||
@ -173,42 +202,25 @@ def is_valid_signature(
|
|||||||
... '0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403',
|
... '0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace225403',
|
||||||
... '0x5409ed021d9299bf6814279a6a1411a7e866a631',
|
... '0x5409ed021d9299bf6814279a6a1411a7e866a631',
|
||||||
... )
|
... )
|
||||||
(True, '')
|
True
|
||||||
""" # noqa: E501 (line too long)
|
""" # noqa: E501 (line too long)
|
||||||
assert_is_provider(provider, "provider")
|
assert_is_provider(provider, "provider")
|
||||||
assert_is_hex_string(data, "data")
|
assert_is_hex_string(data, "data")
|
||||||
assert_is_hex_string(signature, "signature")
|
assert_is_hex_string(signature, "signature")
|
||||||
assert_is_address(signer_address, "signer_address")
|
assert_is_address(signer_address, "signer_address")
|
||||||
|
|
||||||
web3_instance = Web3(provider)
|
return Exchange(
|
||||||
# false positive from pylint: disable=no-member
|
provider,
|
||||||
contract_address = NETWORK_TO_ADDRESSES[
|
network_to_addresses(
|
||||||
NetworkId(int(web3_instance.net.version))
|
NetworkId(
|
||||||
].exchange
|
int(Web3(provider).net.version) # pylint: disable=no-member
|
||||||
# false positive from pylint: disable=no-member
|
)
|
||||||
contract: Contract = web3_instance.eth.contract(
|
).exchange,
|
||||||
address=to_checksum_address(contract_address),
|
).is_valid_hash_signature.call(
|
||||||
abi=zero_ex.contract_artifacts.abi_by_name("Exchange"),
|
bytes.fromhex(remove_0x_prefix(data)),
|
||||||
|
to_checksum_address(signer_address),
|
||||||
|
bytes.fromhex(remove_0x_prefix(signature)),
|
||||||
)
|
)
|
||||||
try:
|
|
||||||
return (
|
|
||||||
contract.functions.isValidSignature(
|
|
||||||
data, to_checksum_address(signer_address), signature
|
|
||||||
).call(),
|
|
||||||
"",
|
|
||||||
)
|
|
||||||
except web3.exceptions.BadFunctionCallOutput as exception:
|
|
||||||
known_revert_reasons = [
|
|
||||||
"LENGTH_GREATER_THAN_0_REQUIRED",
|
|
||||||
"SIGNATURE_ILLEGAL",
|
|
||||||
"SIGNATURE_UNSUPPORTED",
|
|
||||||
"LENGTH_0_REQUIRED",
|
|
||||||
"LENGTH_65_REQUIRED",
|
|
||||||
]
|
|
||||||
for known_revert_reason in known_revert_reasons:
|
|
||||||
if known_revert_reason in str(exception):
|
|
||||||
return (False, known_revert_reason)
|
|
||||||
return (False, f"Unknown: {exception}")
|
|
||||||
|
|
||||||
|
|
||||||
class ECSignature(TypedDict):
|
class ECSignature(TypedDict):
|
||||||
@ -272,11 +284,14 @@ def _convert_ec_signature_to_vrs_hex(signature: ECSignature) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def sign_hash(
|
def sign_hash(
|
||||||
provider: BaseProvider, signer_address: str, hash_hex: str
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
|
signer_address: str,
|
||||||
|
hash_hex: str,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Sign a message with the given hash, and return the signature.
|
"""Sign a message with the given hash, and return the signature.
|
||||||
|
|
||||||
:param provider: A Web3 provider.
|
:param web3_or_provider: Either an instance of `web3.Web3`:code: or
|
||||||
|
`web3.providers.base.BaseProvider`:code:
|
||||||
:param signer_address: The address of the signing account.
|
:param signer_address: The address of the signing account.
|
||||||
:param hash_hex: A hex string representing the hash, like that returned
|
:param hash_hex: A hex string representing the hash, like that returned
|
||||||
from `generate_order_hash_hex()`:code:.
|
from `generate_order_hash_hex()`:code:.
|
||||||
@ -290,11 +305,20 @@ def sign_hash(
|
|||||||
... )
|
... )
|
||||||
'0x1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03'
|
'0x1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03'
|
||||||
""" # noqa: E501 (line too long)
|
""" # noqa: E501 (line too long)
|
||||||
assert_is_provider(provider, "provider")
|
web3_instance = None
|
||||||
|
if isinstance(web3_or_provider, BaseProvider):
|
||||||
|
web3_instance = Web3(web3_or_provider)
|
||||||
|
elif isinstance(web3_or_provider, Web3):
|
||||||
|
web3_instance = web3_or_provider
|
||||||
|
else:
|
||||||
|
raise TypeError(
|
||||||
|
"Expected parameter 'web3_or_provider' to be an instance of either"
|
||||||
|
+ " Web3 or BaseProvider"
|
||||||
|
)
|
||||||
|
|
||||||
assert_is_address(signer_address, "signer_address")
|
assert_is_address(signer_address, "signer_address")
|
||||||
assert_is_hex_string(hash_hex, "hash_hex")
|
assert_is_hex_string(hash_hex, "hash_hex")
|
||||||
|
|
||||||
web3_instance = Web3(provider)
|
|
||||||
# false positive from pylint: disable=no-member
|
# false positive from pylint: disable=no-member
|
||||||
signature = web3_instance.eth.sign( # type: ignore
|
signature = web3_instance.eth.sign( # type: ignore
|
||||||
signer_address, hexstr=hash_hex.replace("0x", "")
|
signer_address, hexstr=hash_hex.replace("0x", "")
|
||||||
@ -319,8 +343,11 @@ def sign_hash(
|
|||||||
).hex()
|
).hex()
|
||||||
)
|
)
|
||||||
|
|
||||||
(valid, _) = is_valid_signature(
|
valid = is_valid_signature(
|
||||||
provider, hash_hex, signature_as_vrst_hex, signer_address
|
web3_instance.provider,
|
||||||
|
hash_hex,
|
||||||
|
signature_as_vrst_hex,
|
||||||
|
signer_address,
|
||||||
)
|
)
|
||||||
|
|
||||||
if valid is True:
|
if valid is True:
|
||||||
@ -334,21 +361,26 @@ def sign_hash(
|
|||||||
1, byteorder="big"
|
1, byteorder="big"
|
||||||
).hex()
|
).hex()
|
||||||
)
|
)
|
||||||
(valid, _) = is_valid_signature(
|
valid = is_valid_signature(
|
||||||
provider, hash_hex, signature_as_vrst_hex, signer_address
|
web3_instance.provider,
|
||||||
|
hash_hex,
|
||||||
|
signature_as_vrst_hex,
|
||||||
|
signer_address,
|
||||||
)
|
)
|
||||||
|
|
||||||
if valid is True:
|
if valid is True:
|
||||||
return signature_as_vrst_hex
|
return signature_as_vrst_hex
|
||||||
|
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"Signature returned from web3 provider is in an unknown format."
|
"Signature returned from web3 provider is in an unknown format. "
|
||||||
+ " Attempted to parse as RSV and as VRS."
|
+ "Signature was: {signature}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def sign_hash_to_bytes(
|
def sign_hash_to_bytes(
|
||||||
provider: BaseProvider, signer_address: str, hash_hex: str
|
web3_or_provider: Union[Web3, BaseProvider],
|
||||||
|
signer_address: str,
|
||||||
|
hash_hex: str,
|
||||||
) -> bytes:
|
) -> bytes:
|
||||||
"""Sign a message with the given hash, and return the signature.
|
"""Sign a message with the given hash, and return the signature.
|
||||||
|
|
||||||
@ -361,5 +393,5 @@ def sign_hash_to_bytes(
|
|||||||
'1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03'
|
'1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03'
|
||||||
""" # noqa: E501 (line too long)
|
""" # noqa: E501 (line too long)
|
||||||
return remove_0x_prefix(
|
return remove_0x_prefix(
|
||||||
sign_hash(provider, signer_address, hash_hex)
|
sign_hash(web3_or_provider, signer_address, hash_hex)
|
||||||
).encode(encoding="utf_8")
|
).encode(encoding="utf_8")
|
||||||
|
@ -34,4 +34,6 @@ class Web3:
|
|||||||
...
|
...
|
||||||
...
|
...
|
||||||
|
|
||||||
|
provider: BaseProvider
|
||||||
|
|
||||||
...
|
...
|
||||||
|
@ -6,7 +6,7 @@ from zero_ex.order_utils import generate_order_hash_hex
|
|||||||
def test_get_order_hash_hex__empty_order():
|
def test_get_order_hash_hex__empty_order():
|
||||||
"""Test the hashing of an uninitialized order."""
|
"""Test the hashing of an uninitialized order."""
|
||||||
expected_hash_hex = (
|
expected_hash_hex = (
|
||||||
"faa49b35faeb9197e9c3ba7a52075e6dad19739549f153b77dfcf59408a4b422"
|
"331cb7e07a757bae130702da6646c26531798c92bcfaf671817268fd2c188531"
|
||||||
)
|
)
|
||||||
actual_hash_hex = generate_order_hash_hex(
|
actual_hash_hex = generate_order_hash_hex(
|
||||||
{
|
{
|
||||||
@ -18,6 +18,8 @@ def test_get_order_hash_hex__empty_order():
|
|||||||
),
|
),
|
||||||
"makerAssetData": (b"\x00") * 20,
|
"makerAssetData": (b"\x00") * 20,
|
||||||
"takerAssetData": (b"\x00") * 20,
|
"takerAssetData": (b"\x00") * 20,
|
||||||
|
"makerFeeAssetData": (b"\x00") * 20,
|
||||||
|
"takerFeeAssetData": (b"\x00") * 20,
|
||||||
"salt": 0,
|
"salt": 0,
|
||||||
"makerFee": 0,
|
"makerFee": 0,
|
||||||
"takerFee": 0,
|
"takerFee": 0,
|
||||||
@ -25,6 +27,7 @@ def test_get_order_hash_hex__empty_order():
|
|||||||
"takerAssetAmount": 0,
|
"takerAssetAmount": 0,
|
||||||
"expirationTimeSeconds": 0,
|
"expirationTimeSeconds": 0,
|
||||||
},
|
},
|
||||||
"0x0000000000000000000000000000000000000000",
|
"0x1dc4c1cefef38a777b15aa20260a54e584b16c48",
|
||||||
|
50,
|
||||||
)
|
)
|
||||||
assert actual_hash_hex == expected_hash_hex
|
assert actual_hash_hex == expected_hash_hex
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from web3 import Web3
|
from web3 import Web3
|
||||||
|
|
||||||
|
from zero_ex.contract_wrappers.exchange.exceptions import (
|
||||||
|
SignatureError,
|
||||||
|
SignatureErrorCodes,
|
||||||
|
)
|
||||||
from zero_ex.order_utils import is_valid_signature, sign_hash_to_bytes
|
from zero_ex.order_utils import is_valid_signature, sign_hash_to_bytes
|
||||||
|
|
||||||
|
|
||||||
@ -117,28 +121,49 @@ def test_is_valid_signature__unsupported_sig_types():
|
|||||||
|
|
||||||
To induce this error, the last byte of the signature is tweaked from 03 to
|
To induce this error, the last byte of the signature is tweaked from 03 to
|
||||||
ff."""
|
ff."""
|
||||||
(is_valid, reason) = is_valid_signature(
|
try:
|
||||||
Web3.HTTPProvider("http://127.0.0.1:8545"),
|
is_valid_signature(
|
||||||
"0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0",
|
Web3.HTTPProvider("http://127.0.0.1:8545"),
|
||||||
"0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351bc334"
|
"0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222"
|
||||||
+ "0349190569279751135161d22529dc25add4f6069af05be04cacbda2ace2254ff",
|
+ "b0",
|
||||||
"0x5409ed021d9299bf6814279a6a1411a7e866a631",
|
"0x1B61a3ed31b43c8780e905a260a35faefcc527be7516aa11c0256729b5b351b"
|
||||||
)
|
+ "c3340349190569279751135161d22529dc25add4f6069af05be04cacbda2ace"
|
||||||
assert is_valid is False
|
+ "225401",
|
||||||
assert reason == "SIGNATURE_UNSUPPORTED"
|
"0x5409ed021d9299bf6814279a6a1411a7e866a631",
|
||||||
|
)
|
||||||
|
except SignatureError as signature_error:
|
||||||
|
assert (
|
||||||
|
signature_error.errorCode
|
||||||
|
== SignatureErrorCodes.INVALID_LENGTH.value
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
pytest.fail("Expected exception")
|
||||||
|
|
||||||
|
|
||||||
def test_sign_hash_to_bytes__golden_path():
|
def test_sign_hash_to_bytes_and_validate__golden_path():
|
||||||
"""Test the happy path through sign_hash_to_bytes()."""
|
"""Test the happy path through sign_hash_to_bytes()."""
|
||||||
provider = Web3.HTTPProvider("http://127.0.0.1:8545")
|
provider = Web3.HTTPProvider("http://127.0.0.1:8545")
|
||||||
signature = sign_hash_to_bytes(
|
|
||||||
provider,
|
signing_address = Web3( # pylint: disable=no-member
|
||||||
Web3( # pylint: disable=no-member
|
provider
|
||||||
provider
|
).geth.personal.listAccounts()[0]
|
||||||
).geth.personal.listAccounts()[0],
|
|
||||||
"0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004",
|
order_hash_hex = (
|
||||||
|
"0x34decbedc118904df65f379a175bb39ca18209d6ce41d5ed549d54e6e0a95004"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
signature = sign_hash_to_bytes(provider, signing_address, order_hash_hex)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
signature
|
signature
|
||||||
== b"1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03" # noqa: E501 (line too long)
|
== b"1b117902c86dfb95fe0d1badd983ee166ad259b27acb220174cbb4460d872871137feabdfe76e05924b484789f79af4ee7fa29ec006cedce1bbf369320d034e10b03" # noqa: E501 (line too long)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
is_valid = is_valid_signature(
|
||||||
|
Web3.HTTPProvider("http://127.0.0.1:8545"),
|
||||||
|
order_hash_hex,
|
||||||
|
signature.decode("utf-8"),
|
||||||
|
signing_address,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert is_valid is True
|
||||||
|
@ -20,6 +20,7 @@ commands =
|
|||||||
pytest test
|
pytest test
|
||||||
|
|
||||||
[testenv:run_tests_against_deployment]
|
[testenv:run_tests_against_deployment]
|
||||||
|
setenv = PY_IGNORE_IMPORTMISMATCH = 1
|
||||||
commands =
|
commands =
|
||||||
pip install 0x-order-utils
|
pip install 0x-order-utils[dev]
|
||||||
pytest test
|
pytest --doctest-modules src test
|
||||||
|
@ -22,7 +22,7 @@ $ ./parallel pip uninstall $(basename $(pwd))
|
|||||||
|
|
||||||
from concurrent.futures import ProcessPoolExecutor, wait
|
from concurrent.futures import ProcessPoolExecutor, wait
|
||||||
from os import chdir
|
from os import chdir
|
||||||
from subprocess import CalledProcessError, check_output
|
from subprocess import CalledProcessError, check_output, STDOUT
|
||||||
from sys import argv
|
from sys import argv
|
||||||
|
|
||||||
PACKAGES = [
|
PACKAGES = [
|
||||||
@ -38,11 +38,14 @@ PACKAGES = [
|
|||||||
def run_cmd_on_package(package: str):
|
def run_cmd_on_package(package: str):
|
||||||
"""cd to the package dir, ./setup.py lint, cd .."""
|
"""cd to the package dir, ./setup.py lint, cd .."""
|
||||||
chdir(package)
|
chdir(package)
|
||||||
|
command = f"{' '.join(argv[1:])}"
|
||||||
try:
|
try:
|
||||||
check_output(f"{' '.join(argv[1:])}".split())
|
check_output(command.split(), stderr=STDOUT)
|
||||||
except CalledProcessError as error:
|
except CalledProcessError as error:
|
||||||
print(f"standard output from command:\n{error.output.decode('utf-8')}")
|
raise RuntimeError(
|
||||||
raise RuntimeError(f"Above exception raised in {package}, ") from error
|
f"Failure return code received from command `{command}` in package"
|
||||||
|
+ f" {package}, which produced the following output:\n"
|
||||||
|
+ f"{error.output.decode('utf-8')}") from error
|
||||||
finally:
|
finally:
|
||||||
chdir("..")
|
chdir("..")
|
||||||
|
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
"""Run the given command in all packages in parallel.
|
|
||||||
|
|
||||||
Handy for quick verification test runs, but annoying in that all of the output
|
|
||||||
is interleaved.
|
|
||||||
|
|
||||||
$ ./parallel ./setup.py lint
|
|
||||||
|
|
||||||
This will `cd` into each package, run `./setup.py lint`, then `cd ..`, all in
|
|
||||||
parallel, in a separate process for each package. The number of processes is
|
|
||||||
decided by ProcessPoolExecutor. Replace "lint" with any of "test", "clean",
|
|
||||||
"build_sphinx" (for docs), etc.
|
|
||||||
|
|
||||||
Also consider:
|
|
||||||
|
|
||||||
$ ./parallel pip install -e .[dev] # install all the packages in editable mode
|
|
||||||
|
|
||||||
$ ./parallel pip uninstall $(basename $(pwd))
|
|
||||||
|
|
||||||
>>>"""
|
|
||||||
|
|
||||||
from concurrent.futures import ProcessPoolExecutor, wait
|
|
||||||
from os import chdir
|
|
||||||
from subprocess import CalledProcessError, check_output
|
|
||||||
from sys import argv
|
|
||||||
|
|
||||||
PACKAGES = [
|
|
||||||
"contract_addresses",
|
|
||||||
"contract_artifacts",
|
|
||||||
"contract_wrappers",
|
|
||||||
"json_schemas",
|
|
||||||
"order_utils",
|
|
||||||
"middlewares",
|
|
||||||
]
|
|
||||||
|
|
||||||
def run_cmd_on_package(package: str):
|
|
||||||
"""cd to the package dir, ./setup.py lint, cd .."""
|
|
||||||
chdir(package)
|
|
||||||
try:
|
|
||||||
check_output(f"{' '.join(argv[1:])}".split())
|
|
||||||
except CalledProcessError as error:
|
|
||||||
print(f"standard output from command:\n{error.output.decode('utf-8')}")
|
|
||||||
raise RuntimeError(f"Above exception raised in {package}, ") from error
|
|
||||||
finally:
|
|
||||||
chdir("..")
|
|
||||||
|
|
||||||
with ProcessPoolExecutor() as executor:
|
|
||||||
for future in executor.map(run_cmd_on_package, PACKAGES):
|
|
||||||
# iterate over map()'s return value, to resolve the futures.
|
|
||||||
# but we don't actually care what the return values are, so just `pass`.
|
|
||||||
# if any exceptions were raised by the underlying task, they'll be
|
|
||||||
# raised as the iteration encounters them.
|
|
||||||
pass
|
|
@ -12,6 +12,7 @@ from sys import argv
|
|||||||
|
|
||||||
PACKAGES = [
|
PACKAGES = [
|
||||||
"contract_wrappers",
|
"contract_wrappers",
|
||||||
|
"contract_addresses",
|
||||||
"contract_artifacts",
|
"contract_artifacts",
|
||||||
"json_schemas",
|
"json_schemas",
|
||||||
]
|
]
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 4.0.0 - TBD
|
||||||
|
|
||||||
|
- Migrated from v2 to v3 of the 0x protocol.
|
||||||
|
|
||||||
## 3.0.0 - 2019-08-08
|
## 3.0.0 - 2019-08-08
|
||||||
|
|
||||||
- Migrated from v4 to v5 of Web3.py.
|
- Migrated from v4 to v5 of Web3.py.
|
||||||
|
@ -3,10 +3,15 @@
|
|||||||
|
|
||||||
"""setuptools module for sra_client package."""
|
"""setuptools module for sra_client package."""
|
||||||
|
|
||||||
|
# pylint: disable=import-outside-toplevel
|
||||||
|
# we import things outside of top-level because 3rd party libs may not yet be
|
||||||
|
# installed when you invoke this script
|
||||||
|
|
||||||
import subprocess # nosec
|
import subprocess # nosec
|
||||||
import distutils.command.build_py
|
import distutils.command.build_py
|
||||||
from distutils.command.clean import clean
|
from distutils.command.clean import clean
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
|
from sys import exit # pylint: disable=redefined-builtin
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
from urllib.error import URLError
|
from urllib.error import URLError
|
||||||
|
|
||||||
@ -14,7 +19,7 @@ from setuptools import setup, find_packages # noqa: H301
|
|||||||
from setuptools.command.test import test as TestCommand
|
from setuptools.command.test import test as TestCommand
|
||||||
|
|
||||||
NAME = "0x-sra-client"
|
NAME = "0x-sra-client"
|
||||||
VERSION = "3.0.0"
|
VERSION = "4.0.0"
|
||||||
# To install the library, run the following
|
# To install the library, run the following
|
||||||
#
|
#
|
||||||
# python setup.py install
|
# python setup.py install
|
||||||
@ -41,6 +46,12 @@ class CleanCommandExtension(clean):
|
|||||||
rmtree("0x_sra_client.egg-info", ignore_errors=True)
|
rmtree("0x_sra_client.egg-info", ignore_errors=True)
|
||||||
rmtree("build", ignore_errors=True)
|
rmtree("build", ignore_errors=True)
|
||||||
rmtree("dist", ignore_errors=True)
|
rmtree("dist", ignore_errors=True)
|
||||||
|
subprocess.check_call( # nosec
|
||||||
|
("docker-compose -f test/relayer/docker-compose.yml down").split()
|
||||||
|
)
|
||||||
|
subprocess.check_call( # nosec
|
||||||
|
("docker-compose -f test/relayer/docker-compose.yml rm").split()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestCommandExtension(TestCommand):
|
class TestCommandExtension(TestCommand):
|
||||||
@ -85,12 +96,15 @@ class StartTestRelayerCommand(distutils.command.build_py.build_py):
|
|||||||
("docker-compose -f test/relayer/docker-compose.yml up -d").split()
|
("docker-compose -f test/relayer/docker-compose.yml up -d").split()
|
||||||
)
|
)
|
||||||
launch_kit_ready = False
|
launch_kit_ready = False
|
||||||
print("Waiting for relayer to start accepting connections...", end="")
|
print(
|
||||||
|
"Waiting for Launch Kit Backend to start accepting connections...",
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
while not launch_kit_ready:
|
while not launch_kit_ready:
|
||||||
try:
|
try:
|
||||||
launch_kit_ready = (
|
launch_kit_ready = (
|
||||||
urlopen( # nosec
|
urlopen( # nosec
|
||||||
"http://localhost:3000/v2/asset_pairs"
|
"http://localhost:3000/v3/asset_pairs"
|
||||||
).getcode()
|
).getcode()
|
||||||
== 200
|
== 200
|
||||||
)
|
)
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
"""0x Python API."""
|
"""0x Python API."""
|
||||||
__import__("pkg_resources").declare_namespace(__name__)
|
__import__("pkg_resources").declare_namespace(__name__) # type: ignore
|
||||||
|
@ -19,7 +19,7 @@ Install the package with pip::
|
|||||||
pip install 0x-sra-client
|
pip install 0x-sra-client
|
||||||
|
|
||||||
To interact with a 0x Relayer, you need the HTTP endpoint of the Relayer you'd
|
To interact with a 0x Relayer, you need the HTTP endpoint of the Relayer you'd
|
||||||
like to connect to (eg https://api.radarrelay.com/0x/v2).
|
like to connect to (eg https://api.radarrelay.com/0x/v3).
|
||||||
|
|
||||||
For testing one can use the `0x-launch-kit-backend
|
For testing one can use the `0x-launch-kit-backend
|
||||||
<https://github.com/0xProject/0x-launch-kit-backend#table-of-contents/>`_ to host
|
<https://github.com/0xProject/0x-launch-kit-backend#table-of-contents/>`_ to host
|
||||||
@ -83,8 +83,8 @@ for this account, so the example orders below have the maker trading away ZRX.
|
|||||||
Before such an order can be valid, though, the maker must give the 0x contracts
|
Before such an order can be valid, though, the maker must give the 0x contracts
|
||||||
permission to trade their ZRX tokens:
|
permission to trade their ZRX tokens:
|
||||||
|
|
||||||
>>> from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES
|
>>> from zero_ex.contract_addresses import network_to_addresses
|
||||||
>>> contract_addresses = NETWORK_TO_ADDRESSES[network_id]
|
>>> contract_addresses = network_to_addresses(network_id)
|
||||||
>>>
|
>>>
|
||||||
>>> from zero_ex.contract_artifacts import abi_by_name
|
>>> from zero_ex.contract_artifacts import abi_by_name
|
||||||
>>> zrx_token_contract = Web3(eth_node).eth.contract(
|
>>> zrx_token_contract = Web3(eth_node).eth.contract(
|
||||||
@ -105,7 +105,8 @@ Post Order
|
|||||||
|
|
||||||
Post an order for our Maker to trade ZRX for WETH:
|
Post an order for our Maker to trade ZRX for WETH:
|
||||||
|
|
||||||
>>> from zero_ex.contract_wrappers.exchange.types import Order, order_to_jsdict
|
>>> from zero_ex.contract_wrappers.exchange.types import Order
|
||||||
|
>>> from zero_ex.contract_wrappers.order_conversions import order_to_jsdict
|
||||||
>>> from zero_ex.order_utils import (
|
>>> from zero_ex.order_utils import (
|
||||||
... asset_data_utils,
|
... asset_data_utils,
|
||||||
... sign_hash)
|
... sign_hash)
|
||||||
@ -120,9 +121,11 @@ Post an order for our Maker to trade ZRX for WETH:
|
|||||||
... makerAssetData=asset_data_utils.encode_erc20(
|
... makerAssetData=asset_data_utils.encode_erc20(
|
||||||
... contract_addresses.zrx_token
|
... contract_addresses.zrx_token
|
||||||
... ),
|
... ),
|
||||||
|
... makerFeeAssetData=asset_data_utils.encode_erc20('0x'+'00'*20),
|
||||||
... takerAssetData=asset_data_utils.encode_erc20(
|
... takerAssetData=asset_data_utils.encode_erc20(
|
||||||
... contract_addresses.ether_token
|
... contract_addresses.ether_token
|
||||||
... ),
|
... ),
|
||||||
|
... takerFeeAssetData=asset_data_utils.encode_erc20('0x'+'00'*20),
|
||||||
... salt=random.randint(1, 100000000000000000),
|
... salt=random.randint(1, 100000000000000000),
|
||||||
... makerFee=0,
|
... makerFee=0,
|
||||||
... takerFee=0,
|
... takerFee=0,
|
||||||
@ -135,7 +138,7 @@ Post an order for our Maker to trade ZRX for WETH:
|
|||||||
|
|
||||||
>>> from zero_ex.order_utils import generate_order_hash_hex
|
>>> from zero_ex.order_utils import generate_order_hash_hex
|
||||||
>>> order_hash_hex = generate_order_hash_hex(
|
>>> order_hash_hex = generate_order_hash_hex(
|
||||||
... order, contract_addresses.exchange
|
... order, contract_addresses.exchange, Web3(eth_node).eth.chainId
|
||||||
... )
|
... )
|
||||||
>>> relayer.post_order_with_http_info(
|
>>> relayer.post_order_with_http_info(
|
||||||
... network_id=network_id.value,
|
... network_id=network_id.value,
|
||||||
@ -144,7 +147,8 @@ Post an order for our Maker to trade ZRX for WETH:
|
|||||||
... exchange_address=contract_addresses.exchange,
|
... exchange_address=contract_addresses.exchange,
|
||||||
... signature=sign_hash(
|
... signature=sign_hash(
|
||||||
... eth_node, Web3.toChecksumAddress(maker_address), order_hash_hex
|
... eth_node, Web3.toChecksumAddress(maker_address), order_hash_hex
|
||||||
... )
|
... ),
|
||||||
|
... chain_id=Web3(eth_node).eth.chainId,
|
||||||
... )
|
... )
|
||||||
... )[1]
|
... )[1]
|
||||||
200
|
200
|
||||||
@ -152,24 +156,35 @@ Post an order for our Maker to trade ZRX for WETH:
|
|||||||
Get Order
|
Get Order
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
(But first sleep for a moment, to give the test relayer a chance to start up.
|
||||||
|
|
||||||
|
>>> from time import sleep
|
||||||
|
>>> sleep(0.2)
|
||||||
|
|
||||||
|
This is necessary for automated verification of these examples.)
|
||||||
|
|
||||||
Retrieve the order we just posted:
|
Retrieve the order we just posted:
|
||||||
|
|
||||||
>>> relayer.get_order("0x" + order_hash_hex)
|
>>> relayer.get_order("0x" + order_hash_hex)
|
||||||
{'meta_data': {},
|
{'meta_data': {'orderHash': '0x...',
|
||||||
'order': {'exchangeAddress': '0x...',
|
'remainingFillableTakerAssetAmount': '2'},
|
||||||
|
'order': {'chainId': 50,
|
||||||
|
'exchangeAddress': '0x...',
|
||||||
'expirationTimeSeconds': '...',
|
'expirationTimeSeconds': '...',
|
||||||
'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
|
'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
|
||||||
'makerAddress': '0x...',
|
'makerAddress': '0x...',
|
||||||
'makerAssetAmount': '2',
|
'makerAssetAmount': '2',
|
||||||
'makerAssetData': '0xf47261b0000000000000000000000000...',
|
'makerAssetData': '0xf47261b0000000000000000000000000...',
|
||||||
'makerFee': '0',
|
'makerFee': '0',
|
||||||
|
'makerFeeAssetData': '0xf47261b0000000000000000000000000...',
|
||||||
'salt': '...',
|
'salt': '...',
|
||||||
'senderAddress': '0x0000000000000000000000000000000000000000',
|
'senderAddress': '0x0000000000000000000000000000000000000000',
|
||||||
'signature': '0x...',
|
'signature': '0x...',
|
||||||
'takerAddress': '0x0000000000000000000000000000000000000000',
|
'takerAddress': '0x0000000000000000000000000000000000000000',
|
||||||
'takerAssetAmount': '2',
|
'takerAssetAmount': '2',
|
||||||
'takerAssetData': '0xf47261b0000000000000000000000000...',
|
'takerAssetData': '0xf47261b0000000000000000000000000...',
|
||||||
'takerFee': '0'}}
|
'takerFee': '0',
|
||||||
|
'takerFeeAssetData': '0xf47261b0000000000000000000000000...'}}
|
||||||
|
|
||||||
Get Orders
|
Get Orders
|
||||||
-----------
|
-----------
|
||||||
@ -178,21 +193,25 @@ Retrieve all of the Relayer's orders, a set which at this point consists solely
|
|||||||
of the one we just posted:
|
of the one we just posted:
|
||||||
|
|
||||||
>>> relayer.get_orders()
|
>>> relayer.get_orders()
|
||||||
{'records': [{'meta_data': {},
|
{'records': [{'meta_data': {'orderHash': '0x...',
|
||||||
'order': {'exchangeAddress': '0x...',
|
'remainingFillableTakerAssetAmount': '2'},
|
||||||
|
'order': {'chainId': 50,
|
||||||
|
'exchangeAddress': '0x...',
|
||||||
'expirationTimeSeconds': '...',
|
'expirationTimeSeconds': '...',
|
||||||
'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
|
'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
|
||||||
'makerAddress': '0x...',
|
'makerAddress': '0x...',
|
||||||
'makerAssetAmount': '2',
|
'makerAssetAmount': '2',
|
||||||
'makerAssetData': '0xf47261b000000000000000000000000...',
|
'makerAssetData': '0xf47261b000000000000000000000000...',
|
||||||
'makerFee': '0',
|
'makerFee': '0',
|
||||||
|
'makerFeeAssetData': '0xf47261b000000000000000000000000...',
|
||||||
'salt': '...',
|
'salt': '...',
|
||||||
'senderAddress': '0x0000000000000000000000000000000000000000',
|
'senderAddress': '0x0000000000000000000000000000000000000000',
|
||||||
'signature': '0x...',
|
'signature': '0x...',
|
||||||
'takerAddress': '0x0000000000000000000000000000000000000000',
|
'takerAddress': '0x0000000000000000000000000000000000000000',
|
||||||
'takerAssetAmount': '2',
|
'takerAssetAmount': '2',
|
||||||
'takerAssetData': '0xf47261b0000000000000000000000000...',
|
'takerAssetData': '0xf47261b0000000000000000000000000...',
|
||||||
'takerFee': '0'}}]}
|
'takerFee': '0',
|
||||||
|
'takerFeeAssetData': '0xf47261b0000000000000000000000000...'}}...]}
|
||||||
|
|
||||||
Get Asset Pairs
|
Get Asset Pairs
|
||||||
---------------
|
---------------
|
||||||
@ -233,43 +252,50 @@ consists just of our order):
|
|||||||
... ).hex(),
|
... ).hex(),
|
||||||
... )
|
... )
|
||||||
>>> orderbook
|
>>> orderbook
|
||||||
{'asks': {'records': []},
|
{'asks': {'records': [...]},
|
||||||
'bids': {'records': [{'meta_data': {},
|
'bids': {'records': [{'meta_data': {'orderHash': '0x...',
|
||||||
'order': {'exchangeAddress': '0x...',
|
'remainingFillableTakerAssetAmount': '2'},
|
||||||
|
'order': {'chainId': 50,
|
||||||
|
'exchangeAddress': '0x...',
|
||||||
'expirationTimeSeconds': '...',
|
'expirationTimeSeconds': '...',
|
||||||
'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
|
'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
|
||||||
'makerAddress': '0x...',
|
'makerAddress': '0x...',
|
||||||
'makerAssetAmount': '2',
|
'makerAssetAmount': '2',
|
||||||
'makerAssetData': '0xf47261b0000000000000000000000000...',
|
'makerAssetData': '0xf47261b0000000000000000000000000...',
|
||||||
'makerFee': '0',
|
'makerFee': '0',
|
||||||
|
'makerFeeAssetData': '0xf47261b0000000000000000000000000...',
|
||||||
'salt': '...',
|
'salt': '...',
|
||||||
'senderAddress': '0x0000000000000000000000000000000000000000',
|
'senderAddress': '0x0000000000000000000000000000000000000000',
|
||||||
'signature': '0x...',
|
'signature': '0x...',
|
||||||
'takerAddress': '0x0000000000000000000000000000000000000000',
|
'takerAddress': '0x0000000000000000000000000000000000000000',
|
||||||
'takerAssetAmount': '2',
|
'takerAssetAmount': '2',
|
||||||
'takerAssetData': '0xf47261b0000000000000000000000000...',
|
'takerAssetData': '0xf47261b0000000000000000000000000...',
|
||||||
'takerFee': '0'}}]}}
|
'takerFee': '0',
|
||||||
|
'takerFeeAssetData': '0xf47261b0000000000000000000000000...'}}...]}}
|
||||||
|
|
||||||
Select an order from the orderbook
|
Select an order from the orderbook
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
>>> from zero_ex.contract_wrappers.exchange.types import jsdict_to_order
|
>>> from zero_ex.contract_wrappers.order_conversions import jsdict_to_order
|
||||||
>>> order = jsdict_to_order(orderbook.bids.records[0].order)
|
>>> order = jsdict_to_order(orderbook.bids.records[0].order)
|
||||||
>>> from pprint import pprint
|
>>> from pprint import pprint
|
||||||
>>> pprint(order)
|
>>> pprint(order)
|
||||||
{'expirationTimeSeconds': ...,
|
{'chainId': 50,
|
||||||
|
'expirationTimeSeconds': ...,
|
||||||
'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
|
'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
|
||||||
'makerAddress': '0x...',
|
'makerAddress': '0x...',
|
||||||
'makerAssetAmount': 2,
|
'makerAssetAmount': 2,
|
||||||
'makerAssetData': b...
|
'makerAssetData': b...
|
||||||
'makerFee': 0,
|
'makerFee': 0,
|
||||||
|
'makerFeeAssetData': b...
|
||||||
'salt': ...,
|
'salt': ...,
|
||||||
'senderAddress': '0x0000000000000000000000000000000000000000',
|
'senderAddress': '0x0000000000000000000000000000000000000000',
|
||||||
'signature': '0x...',
|
'signature': '0x...',
|
||||||
'takerAddress': '0x0000000000000000000000000000000000000000',
|
'takerAddress': '0x0000000000000000000000000000000000000000',
|
||||||
'takerAssetAmount': 2,
|
'takerAssetAmount': 2,
|
||||||
'takerAssetData': b...
|
'takerAssetData': b...,
|
||||||
'takerFee': 0}
|
'takerFee': 0,
|
||||||
|
'takerFeeAssetData': b...}
|
||||||
|
|
||||||
Filling or Cancelling an Order
|
Filling or Cancelling an Order
|
||||||
------------------------------
|
------------------------------
|
||||||
@ -319,8 +345,8 @@ book. Now let's have the taker fill it:
|
|||||||
>>> from zero_ex.contract_wrappers.exchange import Exchange
|
>>> from zero_ex.contract_wrappers.exchange import Exchange
|
||||||
>>> from zero_ex.order_utils import Order
|
>>> from zero_ex.order_utils import Order
|
||||||
>>> exchange = Exchange(
|
>>> exchange = Exchange(
|
||||||
... provider=eth_node,
|
... web3_or_provider=eth_node,
|
||||||
... contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].exchange
|
... contract_address=network_to_addresses(NetworkId.GANACHE).exchange
|
||||||
... )
|
... )
|
||||||
|
|
||||||
(Due to `an Issue with the Launch Kit Backend
|
(Due to `an Issue with the Launch Kit Backend
|
||||||
@ -331,7 +357,7 @@ checksum the address in the order before filling it.)
|
|||||||
>>> exchange.fill_order.send_transaction(
|
>>> exchange.fill_order.send_transaction(
|
||||||
... order=order,
|
... order=order,
|
||||||
... taker_asset_fill_amount=order['makerAssetAmount']/2, # note the half fill
|
... taker_asset_fill_amount=order['makerAssetAmount']/2, # note the half fill
|
||||||
... signature=order['signature'].replace('0x', '').encode('utf-8'),
|
... signature=bytes.fromhex(order['signature'].replace('0x', '')),
|
||||||
... tx_params=TxParams(from_=taker_address)
|
... tx_params=TxParams(from_=taker_address)
|
||||||
... )
|
... )
|
||||||
HexBytes('0x...')
|
HexBytes('0x...')
|
||||||
|
@ -139,7 +139,7 @@ class DefaultApi(object):
|
|||||||
auth_settings = []
|
auth_settings = []
|
||||||
|
|
||||||
return self.api_client.call_api(
|
return self.api_client.call_api(
|
||||||
"/v2/asset_pairs",
|
"/v3/asset_pairs",
|
||||||
"GET",
|
"GET",
|
||||||
path_params,
|
path_params,
|
||||||
query_params,
|
query_params,
|
||||||
@ -250,7 +250,7 @@ class DefaultApi(object):
|
|||||||
auth_settings = []
|
auth_settings = []
|
||||||
|
|
||||||
return self.api_client.call_api(
|
return self.api_client.call_api(
|
||||||
"/v2/fee_recipients",
|
"/v3/fee_recipients",
|
||||||
"GET",
|
"GET",
|
||||||
path_params,
|
path_params,
|
||||||
query_params,
|
query_params,
|
||||||
@ -363,7 +363,7 @@ class DefaultApi(object):
|
|||||||
auth_settings = []
|
auth_settings = []
|
||||||
|
|
||||||
return self.api_client.call_api(
|
return self.api_client.call_api(
|
||||||
"/v2/order/{orderHash}",
|
"/v3/order/{orderHash}",
|
||||||
"GET",
|
"GET",
|
||||||
path_params,
|
path_params,
|
||||||
query_params,
|
query_params,
|
||||||
@ -497,7 +497,7 @@ class DefaultApi(object):
|
|||||||
auth_settings = []
|
auth_settings = []
|
||||||
|
|
||||||
return self.api_client.call_api(
|
return self.api_client.call_api(
|
||||||
"/v2/order_config",
|
"/v3/order_config",
|
||||||
"POST",
|
"POST",
|
||||||
path_params,
|
path_params,
|
||||||
query_params,
|
query_params,
|
||||||
@ -680,7 +680,7 @@ class DefaultApi(object):
|
|||||||
auth_settings = []
|
auth_settings = []
|
||||||
|
|
||||||
return self.api_client.call_api(
|
return self.api_client.call_api(
|
||||||
"/v2/orderbook",
|
"/v3/orderbook",
|
||||||
"GET",
|
"GET",
|
||||||
path_params,
|
path_params,
|
||||||
query_params,
|
query_params,
|
||||||
@ -718,50 +718,48 @@ class DefaultApi(object):
|
|||||||
:param bool async_req: Whether request should be asynchronous.
|
:param bool async_req: Whether request should be asynchronous.
|
||||||
:param str maker_asset_proxy_id: The maker
|
:param str maker_asset_proxy_id: The maker
|
||||||
`asset proxy id
|
`asset proxy id
|
||||||
<https://0x.org/docs/tools/0x.js#types-AssetProxyId>`__
|
<https://0x.org/docs/tools/0x.js#enumeration-assetproxyid>`__
|
||||||
(example: "0xf47261b0" for ERC20, "0x02571792" for ERC721).
|
(example: "0xf47261b0" for ERC20, "0x02571792" for ERC721).
|
||||||
:param str taker_asset_proxy_id: The taker asset
|
:param str taker_asset_proxy_id: The taker asset
|
||||||
`asset proxy id
|
`asset proxy id
|
||||||
<https://0x.org/docs/tools/0x.js#types-AssetProxyId>`__
|
<https://0x.org/docs/tools/0x.js#enumeration-assetproxyid>`__
|
||||||
(example: "0xf47261b0" for ERC20, "0x02571792" for ERC721).
|
(example: "0xf47261b0" for ERC20, "0x02571792" for ERC721).
|
||||||
:param str maker_asset_address: The contract address for the maker asset.
|
:param str maker_asset_address: The contract address for the maker asset.
|
||||||
:param str taker_asset_address: The contract address for the taker asset.
|
:param str taker_asset_address: The contract address for the taker asset.
|
||||||
:param str exchange_address: Same as exchangeAddress in the
|
:param str exchange_address: Contract address for the exchange
|
||||||
`0x Protocol v2 Specification
|
contract.
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
|
||||||
:param str sender_address: Same as senderAddress in the
|
:param str sender_address: Same as senderAddress in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str maker_asset_data: Same as makerAssetData in the
|
:param str maker_asset_data: Same as makerAssetData in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str taker_asset_data: Same as takerAssetData in the
|
:param str taker_asset_data: Same as takerAssetData in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str trader_asset_data: Same as traderAssetData in the [0x
|
:param str trader_asset_data: Same as traderAssetData in the [0x
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str maker_address: Same as makerAddress in the
|
:param str maker_address: Same as makerAddress in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str taker_address: Same as takerAddress in the
|
:param str taker_address: Same as takerAddress in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str trader_address: Same as traderAddress in the
|
:param str trader_address: Same as traderAddress in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str fee_recipient_address: Same as feeRecipientAddress in the
|
:param str fee_recipient_address: Same as feeRecipientAddress in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param int network_id: The id of the Ethereum network
|
:param int network_id: The id of the Ethereum network
|
||||||
:param int page: The number of the page to request in the collection.
|
:param int page: The number of the page to request in the collection.
|
||||||
:param int per_page: The number of records to return per page.
|
:param int per_page: The number of records to return per page.
|
||||||
@ -795,50 +793,50 @@ class DefaultApi(object):
|
|||||||
:param bool async_req: Whether request should be asynchronous.
|
:param bool async_req: Whether request should be asynchronous.
|
||||||
:param str maker_asset_proxy_id: The maker
|
:param str maker_asset_proxy_id: The maker
|
||||||
`asset proxy id
|
`asset proxy id
|
||||||
<https://0x.org/docs/tools/0x.js#types-AssetProxyId>`__
|
<https://0x.org/docs/tools/0x.js#enumeration-assetproxyid>`__
|
||||||
(example: "0xf47261b0" for ERC20, "0x02571792" for ERC721).
|
(example: "0xf47261b0" for ERC20, "0x02571792" for ERC721).
|
||||||
:param str taker_asset_proxy_id: The taker asset
|
:param str taker_asset_proxy_id: The taker asset
|
||||||
`asset proxy id
|
`asset proxy id
|
||||||
<https://0x.org/docs/tools/0x.js#types-AssetProxyId>`__
|
<https://0x.org/docs/tools/0x.js#enumeration-assetproxyid>`__
|
||||||
(example: "0xf47261b0" for ERC20, "0x02571792" for ERC721).
|
(example: "0xf47261b0" for ERC20, "0x02571792" for ERC721).
|
||||||
:param str maker_asset_address: The contract address for the maker asset.
|
:param str maker_asset_address: The contract address for the maker asset.
|
||||||
:param str taker_asset_address: The contract address for the taker asset.
|
:param str taker_asset_address: The contract address for the taker asset.
|
||||||
:param str exchange_address: Same as exchangeAddress in the [0x
|
:param str exchange_address: Same as exchangeAddress in the [0x
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str sender_address: Same as senderAddress in the
|
:param str sender_address: Same as senderAddress in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str maker_asset_data: Same as makerAssetData in the
|
:param str maker_asset_data: Same as makerAssetData in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str taker_asset_data: Same as takerAssetData in the
|
:param str taker_asset_data: Same as takerAssetData in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str trader_asset_data: Same as traderAssetData in the
|
:param str trader_asset_data: Same as traderAssetData in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str maker_address: Same as makerAddress in the
|
:param str maker_address: Same as makerAddress in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str taker_address: Same as takerAddress in the
|
:param str taker_address: Same as takerAddress in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str trader_address: Same as traderAddress in the
|
:param str trader_address: Same as traderAddress in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param str fee_recipient_address: Same as feeRecipientAddress in the
|
:param str fee_recipient_address: Same as feeRecipientAddress in the
|
||||||
`0x Protocol v2 Specification
|
`0x Protocol v3 Specification
|
||||||
<https://github.com/0xProject/0x-protocol-specification/blob/
|
<https://github.com/0xProject/0x-protocol-specification/blob/
|
||||||
master/v2/v2-specification.md#order-message-format>`__
|
master/v3/v3-specification.md#order-message-format>`__
|
||||||
:param int network_id: The id of the Ethereum network
|
:param int network_id: The id of the Ethereum network
|
||||||
:param int page: The number of the page to request in the collection.
|
:param int page: The number of the page to request in the collection.
|
||||||
:param int per_page: The number of records to return per page.
|
:param int per_page: The number of records to return per page.
|
||||||
@ -965,7 +963,7 @@ class DefaultApi(object):
|
|||||||
auth_settings = []
|
auth_settings = []
|
||||||
|
|
||||||
return self.api_client.call_api(
|
return self.api_client.call_api(
|
||||||
"/v2/orders",
|
"/v3/orders",
|
||||||
"GET",
|
"GET",
|
||||||
path_params,
|
path_params,
|
||||||
query_params,
|
query_params,
|
||||||
@ -1077,7 +1075,7 @@ class DefaultApi(object):
|
|||||||
auth_settings = []
|
auth_settings = []
|
||||||
|
|
||||||
return self.api_client.call_api(
|
return self.api_client.call_api(
|
||||||
"/v2/order",
|
"/v3/order",
|
||||||
"POST",
|
"POST",
|
||||||
path_params,
|
path_params,
|
||||||
query_params,
|
query_params,
|
||||||
|
@ -1,14 +1,36 @@
|
|||||||
# Run Launch Kit with Ganache as the backing node
|
# Run Launch Kit Backend with Ganache and Mesh instances backing it.
|
||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
ganache:
|
ganache:
|
||||||
image: "0xorg/ganache-cli:2.2.2"
|
image: "0xorg/ganache-cli:4.4.0-beta.1"
|
||||||
ports:
|
ports:
|
||||||
- "8545:8545"
|
- "8545:8545"
|
||||||
launchkit:
|
environment:
|
||||||
image: "0xorg/launch-kit-backend:74bcc39"
|
- VERSION=4.4.0-beta.1
|
||||||
|
- SNAPSHOT_NAME=0x_ganache_snapshot-v3-beta
|
||||||
|
mesh:
|
||||||
|
image: 0xorg/mesh:6.0.0-beta-0xv3
|
||||||
depends_on:
|
depends_on:
|
||||||
- ganache
|
- ganache
|
||||||
|
environment:
|
||||||
|
ETHEREUM_RPC_URL: 'http://localhost:8545'
|
||||||
|
ETHEREUM_NETWORK_ID: '50'
|
||||||
|
ETHEREUM_CHAIN_ID: '1337'
|
||||||
|
USE_BOOTSTRAP_LIST: 'true'
|
||||||
|
VERBOSITY: 3
|
||||||
|
PRIVATE_KEY_PATH: ''
|
||||||
|
BLOCK_POLLING_INTERVAL: '5s'
|
||||||
|
P2P_LISTEN_PORT: '60557'
|
||||||
|
ports:
|
||||||
|
- '60557:60557'
|
||||||
|
network_mode: "host" # to connect to ganache
|
||||||
|
command: |
|
||||||
|
sh -c "waitForGanache () { until printf 'POST /\r\nContent-Length: 26\r\n\r\n{\"method\":\"net_listening\"}' | nc localhost 8545 | grep true; do continue; done }; waitForGanache && ./mesh"
|
||||||
|
launch-kit-backend:
|
||||||
|
image: "0xorg/launch-kit-backend:v3"
|
||||||
|
depends_on:
|
||||||
|
- ganache
|
||||||
|
- mesh
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
network_mode: "host" # to connect to ganache
|
network_mode: "host" # to connect to ganache
|
||||||
@ -16,5 +38,9 @@ services:
|
|||||||
- NETWORK_ID=50
|
- NETWORK_ID=50
|
||||||
- RPC_URL=http://localhost:8545
|
- RPC_URL=http://localhost:8545
|
||||||
- WHITELIST_ALL_TOKENS=True
|
- WHITELIST_ALL_TOKENS=True
|
||||||
|
- FEE_RECIPIENT=0x0000000000000000000000000000000000000001
|
||||||
|
- MAKER_FEE_UNIT_AMOUNT=0
|
||||||
|
- TAKER_FEE_UNIT_AMOUNT=0
|
||||||
|
- MESH_ENDPOINT=ws://localhost:60557
|
||||||
command: |
|
command: |
|
||||||
sh -c "until printf 'POST /\r\nContent-Length: 26\r\n\r\n{\"method\":\"net_listening\"}' | nc localhost 8545 | grep true; do continue; done; node_modules/.bin/forever ts/lib/index.js"
|
sh -c "waitForMesh () { sleep 3; }; waitForMesh && sleep 5 && node_modules/.bin/forever ts/lib/index.js"
|
||||||
|
@ -18,7 +18,7 @@ commands =
|
|||||||
pytest test
|
pytest test
|
||||||
|
|
||||||
[testenv:run_tests_against_deployment]
|
[testenv:run_tests_against_deployment]
|
||||||
deps=pytest
|
setenv = PY_IGNORE_IMPORTMISMATCH = 1
|
||||||
commands =
|
commands =
|
||||||
pip install 0x-sra-client
|
pip install 0x-sra-client[dev]
|
||||||
pytest test
|
pytest --doctest-modules src test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user