Auto-gen Python Exchange wrapper (#1919)
* Rename existing wrapper, to match contract name * base contract: make member var public * json_schemas.py: stop storing copies of schemas! * .gitignore generated erc20_token.py wrapper * json schemas: allow uppercase digits in address * existing exchange wrapper: re-order methods to match method order in Solidity contract, to reduce noise in upcoming diffs of newly generated code vs. old manually-written code. * existing exchange wrapper: rename method params To match contract method param names * existing exchange wrapper: remove redundant member * existing exchange wrapper: make signatures bytes Not strings. * abi-gen/test-cli: show context on diff failure * abi-gen-templates/Py: fix broken event interface Previous changes had removed the `token_address` parameter from all generated methods, but this instance was missed because there weren't tests/examples using events for the first contract for which wrappers were generated (ERC20Token). * abi-gen: remove unused method parameters * abi-gen: convert Py method params to snake case * abi-gen: rewrite Python tuple handling * python-generated-wrappers: include Exchange * abi-gen-templates/Py: easy linter fixes * abi-gen-templates/Py: satisfy docstring linters * abi-gen-templates/Py: normalize bytes before use * contract_wrappers.py: replace Exchange w/generated * contract_wrappers.py: rm manually written Exchange * contract_wrappers.py/doctest: rename variables * abi-gen: fix misspelling in docstring Co-Authored-By: Fabio B <me@fabioberger.com> * Py docs: error on warning, and test build in CI * abi-gen: doc Py bytes params as requiring UTF-8 * abi-gen: git mv diff.sh test-cli/ * abi-gen: put Py wrapper in module folder, not file This leaves space for user-defined additions to the same module, such as for custom types, as shown herein. * abi-gen: customizable param validation for Python * contract_wrappers.py: JSON schema Order validation * CircleCI Build Artifacts For abi-gen command-line test output, for generated Python contract wrappers as output by abi-gen, for generated Python contract wrappers as reformatted and included in the Python package area, and for the "build" output folder in each Python package, which includes the generated documentation. * CHANGELOG updates for all components * abi-gen: grammar in comments Co-Authored-By: Fabio B <me@fabioberger.com> * abi-gen: CHANGELOG spelling correction Co-Authored-By: Fabio B <me@fabioberger.com> * order_utils.py: reverse (chronological) CHANGELOG * abi-gen-templates: reset CHANGELOG patch version * CHANGELOGs: use multiple entries where appropriate * abi-gen: enable devdoc solc output in test-cli * abi-gen-templates/Py: consolidate return type * abi-gen/test-cli: non-pure fixture contract method Added a method to the "dummy" test fixture contract that isn't pure. All of the other prior method cases were pure. * abi-gen/Py: fix const methods missing return type * abi-gen/Py: fix wrong return types on some methods Specifically, wrapper methods wrapping contract methods that modify contract state and return no return value. There was no test case for this. Now there is. * contract_wrappers.py: rm generated code in `clean` * Parallelize Py monorepo scripts (test, lint, etc)
This commit is contained in:
@@ -33,6 +33,10 @@ jobs:
|
||||
key: python-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/python-contract-wrappers/generated
|
||||
- store_artifacts:
|
||||
path: ~/repo/packages/python-contract-wrappers/generated
|
||||
- store_artifacts:
|
||||
path: ~/repo/packages/abi-gen/test-cli/output
|
||||
build-website:
|
||||
resource_class: medium+
|
||||
docker:
|
||||
@@ -204,7 +208,8 @@ jobs:
|
||||
- run:
|
||||
command: |
|
||||
cd python-packages
|
||||
./cmd_pkgs_in_dep_order.py coverage run setup.py test
|
||||
./parallel coverage run setup.py test
|
||||
./build_docs
|
||||
- save_cache:
|
||||
key: coverage-python-contract-addresses-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
@@ -229,6 +234,24 @@ jobs:
|
||||
key: coverage-python-sra-client-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/python-packages/sra_client/.coverage
|
||||
- store_artifacts:
|
||||
path: ~/repo/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/erc20_token/__init__.py
|
||||
- store_artifacts:
|
||||
path: ~/repo/python-packages/contract_wrappers/src/zero_ex/contract_wrappers/exchange/__init__.py
|
||||
- store_artifacts:
|
||||
path: ~/repo/python-packages/contract_addresses/build
|
||||
- store_artifacts:
|
||||
path: ~/repo/python-packages/contract_artifacts/build
|
||||
- store_artifacts:
|
||||
path: ~/repo/python-packages/contract_wrappers/build
|
||||
- store_artifacts:
|
||||
path: ~/repo/python-packages/json_schemas/build
|
||||
- store_artifacts:
|
||||
path: ~/repo/python-packages/middlewares/build
|
||||
- store_artifacts:
|
||||
path: ~/repo/python-packages/order_utils/build
|
||||
- store_artifacts:
|
||||
path: ~/repo/python-packages/sra_client/build
|
||||
test-rest-python:
|
||||
working_directory: ~/repo
|
||||
docker:
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@@ -113,6 +113,8 @@ contracts/erc1155/generated-wrappers/
|
||||
contracts/extensions/generated-wrappers/
|
||||
contracts/exchange-forwarder/generated-wrappers/
|
||||
contracts/dev-utils/generated-wrappers/
|
||||
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
|
||||
|
||||
# cli test output
|
||||
packages/abi-gen/test-cli/output
|
||||
@@ -132,3 +134,6 @@ python-packages/*/dist
|
||||
__pycache__
|
||||
python-packages/*/src/*.egg-info
|
||||
python-packages/*/.coverage
|
||||
|
||||
# python keeps package-local copies of json schemas
|
||||
python-packages/json_schemas/src/zero_ex/json_schemas/schemas
|
||||
|
@@ -35,3 +35,6 @@ packages/sol-coverage/test/fixtures/artifacts
|
||||
.pytest_cache
|
||||
.mypy_cache
|
||||
.tox
|
||||
packages/abi-gen/test-cli/fixtures/artifacts/AbiGenDummy.json
|
||||
packages/abi-gen/test-cli/fixtures/artifacts/LibDummy.json
|
||||
packages/abi-gen/test-cli/fixtures/artifacts/TestLibDummy.json
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "6.0.13",
|
||||
"changes": [
|
||||
{
|
||||
"note": "re-export new ethereum-types type, TupleDataItem",
|
||||
"pr": 1919
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563193019,
|
||||
"version": "6.0.12",
|
||||
|
@@ -131,6 +131,7 @@ export {
|
||||
ConstructorAbi,
|
||||
FallbackAbi,
|
||||
DataItem,
|
||||
TupleDataItem,
|
||||
ConstructorStateMutability,
|
||||
StateMutability,
|
||||
Web3JsProvider,
|
||||
|
@@ -1,4 +1,25 @@
|
||||
[
|
||||
{
|
||||
"version": "2.3.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Python: fix broken event handling",
|
||||
"pr": 1919
|
||||
},
|
||||
{
|
||||
"note": "Python: custom validator class support",
|
||||
"pr": 1919
|
||||
},
|
||||
{
|
||||
"note": "Python: linter fixes",
|
||||
"pr": 1919
|
||||
},
|
||||
{
|
||||
"note": "Python: normalize bytes parameters in wrapper methods",
|
||||
"pr": 1919
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563006338,
|
||||
"version": "2.2.1",
|
||||
|
@@ -1,8 +1,17 @@
|
||||
"""Generated wrapper for {{contractName}} Solidity contract."""
|
||||
|
||||
import json
|
||||
from typing import Optional, Tuple, Union
|
||||
# pylint: disable=too-many-arguments
|
||||
|
||||
import json
|
||||
from typing import ( # pylint: disable=unused-import
|
||||
Any,
|
||||
List,
|
||||
Optional,
|
||||
Tuple,
|
||||
Union,
|
||||
)
|
||||
|
||||
from mypy_extensions import TypedDict # pylint: disable=unused-import
|
||||
from hexbytes import HexBytes
|
||||
from web3.datastructures import AttributeDict
|
||||
from web3.providers.base import BaseProvider
|
||||
@@ -11,13 +20,55 @@ from zero_ex.contract_wrappers._base_contract_wrapper import BaseContractWrapper
|
||||
from zero_ex.contract_wrappers.tx_params import TxParams
|
||||
|
||||
|
||||
class {{contractName}}ValidatorBase:
|
||||
"""Base class for validating inputs to {{contractName}} methods."""
|
||||
def __init__(
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
contract_address: str,
|
||||
private_key: str = None,
|
||||
):
|
||||
"""Initialize the instance."""
|
||||
|
||||
def assert_valid(
|
||||
self, method_name: str, parameter_name: str, argument_value: Any
|
||||
):
|
||||
"""Raise an exception if method input is not valid.
|
||||
|
||||
:param method_name: Name of the method whose input is to be validated.
|
||||
:param parameter_name: Name of the parameter whose input is to be
|
||||
validated.
|
||||
:param argument_value: Value of argument to parameter to be validated.
|
||||
"""
|
||||
|
||||
|
||||
# Try to import a custom validator class definition; if there isn't one,
|
||||
# declare one that we can instantiate for the default argument to the
|
||||
# constructor for {{contractName}} below.
|
||||
try:
|
||||
# both mypy and pylint complain about what we're doing here, but this
|
||||
# works just fine, so their messages have been disabled here.
|
||||
from . import ( # type: ignore # pylint: disable=import-self
|
||||
{{contractName}}Validator,
|
||||
)
|
||||
except ImportError:
|
||||
|
||||
class {{contractName}}Validator({{contractName}}ValidatorBase): # type: ignore
|
||||
"""No-op input validator."""
|
||||
|
||||
|
||||
{{tupleDefinitions ABIString}}
|
||||
|
||||
|
||||
# pylint: disable=too-many-public-methods
|
||||
class {{contractName}}(BaseContractWrapper):
|
||||
"""Wrapper class for {{contractName}} Solidity contract."""
|
||||
"""Wrapper class for {{contractName}} Solidity contract.{{docBytesIfNecessary ABIString}}"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
contract_address: str,
|
||||
validator: {{contractName}}Validator = None,
|
||||
private_key: str = None,
|
||||
):
|
||||
"""Get an instance of wrapper for smart contract.
|
||||
@@ -34,6 +85,11 @@ class {{contractName}}(BaseContractWrapper):
|
||||
private_key=private_key,
|
||||
)
|
||||
|
||||
if not validator:
|
||||
validator = {{contractName}}Validator(provider, contract_address, private_key)
|
||||
|
||||
self.validator = validator
|
||||
|
||||
def _get_contract_instance(self, token_address):
|
||||
"""Get an instance of the smart contract at a specific address.
|
||||
|
||||
@@ -55,3 +111,5 @@ class {{contractName}}(BaseContractWrapper):
|
||||
return json.loads(
|
||||
'{{{ABIString}}}' # noqa: E501 (line-too-long)
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-lines
|
||||
|
@@ -6,31 +6,44 @@
|
||||
{{^this.constant}}
|
||||
view_only: bool = False,
|
||||
{{/this.constant}}
|
||||
) ->{{#if outputs}}{{~> return_type outputs=outputs~}}{{else}} None{{/if}}:
|
||||
) -> {{> return_type outputs=outputs~}}:
|
||||
"""Execute underlying, same-named contract method.
|
||||
{{sanitizeDevdocDetails this.name this.devdoc.details 8}}
|
||||
{{#each this.devdoc.params}}
|
||||
:param {{@key}}: {{this}}
|
||||
{{/each}}
|
||||
{{#if this.constant}}
|
||||
{{#if this.devdoc.return}}:returns: {{this.devdoc.return}}{{/if}}
|
||||
{{else}}
|
||||
{{sanitizeDevdocDetails this.name this.devdoc.details 8}}{{~#if this.devdoc.params~}}{{#each this.devdoc.params}}
|
||||
{{makeParameterDocstringRole @key this 8}}{{/each}}{{/if}}
|
||||
:param tx_params: transaction parameters
|
||||
{{#if this.constant~}}
|
||||
{{#if this.devdoc.return}}
|
||||
{{makeReturnDocstringRole this.devdoc.return 8}}{{/if}}
|
||||
{{else}}
|
||||
:param view_only: whether to use transact() or call()
|
||||
|
||||
:returns: transaction hash
|
||||
:returns: if param `view_only`:code: is `True`:code:, then returns the
|
||||
value returned from the underlying function; else returns the
|
||||
transaction hash.
|
||||
{{/if}}
|
||||
"""
|
||||
{{#each this.inputs}}
|
||||
self.validator.assert_valid(
|
||||
method_name='{{../name}}',
|
||||
parameter_name='{{name}}',
|
||||
argument_value={{toPythonIdentifier name}},
|
||||
)
|
||||
{{#if (equal type 'address')}}
|
||||
{{this.name}} = self._validate_and_checksum_address({{this.name}})
|
||||
{{toPythonIdentifier this.name}} = self._validate_and_checksum_address({{toPythonIdentifier this.name}})
|
||||
{{else if (equal type 'uint256')}}
|
||||
# safeguard against fractional inputs
|
||||
{{this.name}} = int({{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}}
|
||||
{{/each}}
|
||||
func = self._get_contract_instance(
|
||||
self._contract_address
|
||||
self.contract_address
|
||||
).functions.{{this.name}}(
|
||||
{{> params}}
|
||||
)
|
||||
|
@@ -1,14 +1,13 @@
|
||||
def get_{{languageSpecificName}}_event(
|
||||
self, token_address: str, tx_hash: Union[HexBytes, bytes]
|
||||
self, tx_hash: Union[HexBytes, bytes]
|
||||
) -> Tuple[AttributeDict]:
|
||||
"""Get log entry for {{name}} event.
|
||||
|
||||
:param tx_hash: hash of transaction emitting {{name}} event.
|
||||
{{makeEventParameterDocstringRole name 8}}
|
||||
"""
|
||||
tx_receipt = self._web3_eth.getTransactionReceipt(tx_hash)
|
||||
token_address = self._validate_and_checksum_address(token_address)
|
||||
return (
|
||||
self._get_contract_instance(token_address)
|
||||
self._get_contract_instance(self.contract_address)
|
||||
.events.{{name}}()
|
||||
.processReceipt(tx_receipt)
|
||||
)
|
||||
|
@@ -1,3 +1,3 @@
|
||||
{{#each inputs}}
|
||||
{{name}}{{#if @last}}{{else}},{{/if}}
|
||||
{{toPythonIdentifier name}}{{#if @last}}{{else}},{{/if}}
|
||||
{{/each}}
|
||||
|
@@ -1,13 +1,14 @@
|
||||
{{#if this.constant}}
|
||||
{{~#if outputs~}}
|
||||
{{^if this.constant}}
|
||||
Union[
|
||||
{{~/if~}}
|
||||
{{#if outputs.length}}
|
||||
{{#singleReturnValue}}
|
||||
{{#returnType outputs.0.type outputs.0.components}}{{~/returnType~}}
|
||||
{{#returnType outputs.0.type outputs.0.components}}{{~/returnType~}}
|
||||
{{/singleReturnValue}}
|
||||
{{^singleReturnValue}}
|
||||
[{{#each outputs}}{{#returnType type components}}{{/returnType}}{{#unless @last}}, {{/unless}}{{/each}}]
|
||||
{{/singleReturnValue}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{^if this.constant}}
|
||||
Union[HexBytes, bytes]
|
||||
{{~/if~}}
|
||||
{{else}}None
|
||||
{{/if}}{{^if this.constant}}, Union[HexBytes, bytes]]{{/if~}}
|
||||
{{else}}{{#if this.constant}}None{{else}}Union[None, Union[HexBytes, bytes]]{{/if}}{{/if~}}
|
||||
|
@@ -1,3 +1,3 @@
|
||||
{{#each inputs}}
|
||||
{{name}}: {{#parameterType type components}}{{/parameterType}},
|
||||
{{toPythonIdentifier name}}: {{#parameterType type components}}{{/parameterType}},
|
||||
{{/each}}
|
||||
|
@@ -1,4 +1,37 @@
|
||||
[
|
||||
{
|
||||
"version": "3.1.1",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Python method parameters are now in snake case",
|
||||
"pr": 1919
|
||||
},
|
||||
{
|
||||
"note": "Python wrappers now support tuples in method parameters",
|
||||
"pr": 1919
|
||||
},
|
||||
{
|
||||
"note": "document Python method's bytes params as requiring UTF-8",
|
||||
"pr": 1919
|
||||
},
|
||||
{
|
||||
"note": "generate Python output into a contract-named folder, not a file (eg exchange/__init__.py rather than exchange.py) leaving space for user-defined additions to the same module, such as for custom types, as used by the Exchange wrapper's manually-written type aliases in the contract_wrappers.exchange.types Python module",
|
||||
"pr": 1919
|
||||
},
|
||||
{
|
||||
"note": "support for customizable parameter validation for Python wrappers",
|
||||
"pr": 1919
|
||||
},
|
||||
{
|
||||
"note": "wrap Python docstrings better, for pydocstyle compliance",
|
||||
"pr": 1919
|
||||
},
|
||||
{
|
||||
"note": "lots of fixes to satisfy linters of generated Python code",
|
||||
"pr": 1919
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563047529,
|
||||
"version": "2.1.1",
|
||||
|
@@ -17,7 +17,8 @@
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
"evm.deployedBytecode.sourceMap"
|
||||
"evm.deployedBytecode.sourceMap",
|
||||
"devdoc"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@
|
||||
"generate_contract_wrappers": "run-p gen_typescript gen_python",
|
||||
"gen_typescript": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/partials/**/*.handlebars' --output ./test-cli/output/typescript --backend ethers",
|
||||
"gen_python": "abi-gen --abis ${npm_package_config_abis} --template ../../node_modules/@0x/abi-gen-templates/Python/contract.handlebars --partials '../../node_modules/@0x/abi-gen-templates/Python/partials/**/*.handlebars' --output ./test-cli/output/python --language Python",
|
||||
"diff_contract_wrappers": "./diff.sh ./test-cli/expected-output ./test-cli/output",
|
||||
"diff_contract_wrappers": "test-cli/diff.sh ./test-cli/expected-output ./test-cli/output",
|
||||
"coverage:report:text": "istanbul report text",
|
||||
"coverage:report:html": "istanbul report html && open coverage/index.html",
|
||||
"profiler:report:html": "istanbul report html && open coverage/index.html",
|
||||
|
@@ -4,7 +4,16 @@ import { AbiEncoder, abiUtils, logUtils } from '@0x/utils';
|
||||
import chalk from 'chalk';
|
||||
import * as changeCase from 'change-case';
|
||||
import * as cliFormat from 'cli-format';
|
||||
import { AbiDefinition, ConstructorAbi, ContractAbi, DevdocOutput, EventAbi, MethodAbi } from 'ethereum-types';
|
||||
import {
|
||||
AbiDefinition,
|
||||
ConstructorAbi,
|
||||
ContractAbi,
|
||||
DataItem,
|
||||
DevdocOutput,
|
||||
EventAbi,
|
||||
MethodAbi,
|
||||
TupleDataItem,
|
||||
} from 'ethereum-types';
|
||||
import { sync as globSync } from 'glob';
|
||||
import * as Handlebars from 'handlebars';
|
||||
import * as _ from 'lodash';
|
||||
@@ -102,8 +111,9 @@ function registerPythonHelpers(): void {
|
||||
return lhs === rhs;
|
||||
});
|
||||
Handlebars.registerHelper('safeString', (str, options) => new Handlebars.SafeString(str));
|
||||
Handlebars.registerHelper('parameterType', utils.solTypeToPyType.bind(utils, ParamKind.Input, args.backend));
|
||||
Handlebars.registerHelper('returnType', utils.solTypeToPyType.bind(utils, ParamKind.Output, args.backend));
|
||||
Handlebars.registerHelper('parameterType', utils.solTypeToPyType.bind(utils));
|
||||
Handlebars.registerHelper('returnType', utils.solTypeToPyType.bind(utils));
|
||||
Handlebars.registerHelper('toPythonIdentifier', utils.toPythonIdentifier.bind(utils));
|
||||
Handlebars.registerHelper(
|
||||
'sanitizeDevdocDetails',
|
||||
(methodName: string, devdocDetails: string, indent: number, options) => {
|
||||
@@ -116,12 +126,111 @@ function registerPythonHelpers(): void {
|
||||
return new Handlebars.SafeString(
|
||||
`\n${cliFormat.wrap(devdocDetails || '', {
|
||||
paddingLeft: ' '.repeat(indent),
|
||||
width: columnsPerRow - indent,
|
||||
width: columnsPerRow,
|
||||
ansi: false,
|
||||
})}\n`,
|
||||
);
|
||||
},
|
||||
);
|
||||
Handlebars.registerHelper(
|
||||
'makeParameterDocstringRole',
|
||||
(name: string, description: string, indent: number, options) => {
|
||||
let docstring = `:param ${name}:`;
|
||||
if (description && description.length > 0) {
|
||||
docstring = `${docstring} ${description}`;
|
||||
}
|
||||
return new Handlebars.SafeString(utils.wrapPythonDocstringRole(docstring, indent));
|
||||
},
|
||||
);
|
||||
Handlebars.registerHelper(
|
||||
'makeReturnDocstringRole',
|
||||
(description: string, indent: number, options) =>
|
||||
new Handlebars.SafeString(utils.wrapPythonDocstringRole(`:returns: ${description}`, indent)),
|
||||
);
|
||||
Handlebars.registerHelper(
|
||||
'makeEventParameterDocstringRole',
|
||||
(eventName: string, indent: number, options) =>
|
||||
new Handlebars.SafeString(
|
||||
utils.wrapPythonDocstringRole(
|
||||
`:param tx_hash: hash of transaction emitting ${eventName} event`,
|
||||
indent,
|
||||
),
|
||||
),
|
||||
);
|
||||
Handlebars.registerHelper('tupleDefinitions', (abisJSON: string, options) => {
|
||||
const abis: AbiDefinition[] = JSON.parse(abisJSON);
|
||||
// build an array of objects, each of which has one key, the Python
|
||||
// name of a tuple, with a string value holding the Python
|
||||
// definition of that tuple. Using a key-value object conveniently
|
||||
// filters duplicate references to the same tuple.
|
||||
const tupleDefinitions: { [pythonTupleName: string]: string } = {};
|
||||
for (const abi of abis) {
|
||||
let parameters: DataItem[] = [];
|
||||
if (abi.hasOwnProperty('inputs')) {
|
||||
// HACK(feuGeneA): using "as MethodAbi" below, but abi
|
||||
// could just as well be ConstructorAbi, EventAbi, etc. We
|
||||
// just need to tell the TypeScript compiler that it's NOT
|
||||
// FallbackAbi, or else it would complain, "Property
|
||||
// 'inputs' does not exist on type 'AbiDefinition'.
|
||||
// Property 'inputs' does not exist on type
|
||||
// 'FallbackAbi'.", despite the enclosing if statement.
|
||||
// tslint:disable:no-unnecessary-type-assertion
|
||||
parameters = parameters.concat((abi as MethodAbi).inputs);
|
||||
}
|
||||
if (abi.hasOwnProperty('outputs')) {
|
||||
// HACK(feuGeneA): same as described above, except here we
|
||||
// KNOW that it's a MethodAbi, given the enclosing if
|
||||
// statement, because that's the only AbiDefinition subtype
|
||||
// that actually has an outputs field.
|
||||
parameters = parameters.concat((abi as MethodAbi).outputs);
|
||||
}
|
||||
for (const parameter of parameters) {
|
||||
if (parameter.type === 'tuple') {
|
||||
tupleDefinitions[
|
||||
utils.makePythonTupleName((parameter as TupleDataItem).components)
|
||||
] = utils.makePythonTupleClassBody((parameter as TupleDataItem).components);
|
||||
}
|
||||
}
|
||||
}
|
||||
const tupleDeclarations = [];
|
||||
for (const pythonTupleName in tupleDefinitions) {
|
||||
if (tupleDefinitions[pythonTupleName]) {
|
||||
tupleDeclarations.push(
|
||||
`class ${pythonTupleName}(TypedDict):\n """Python representation of a tuple or struct.\n\n A tuple found in an ABI may have been written in Solidity as a literal\n tuple, or it may have been written as a parameter with a Solidity\n \`struct\`:code: data type; there's no way to tell which, based solely on the\n ABI, and the name of a Solidity \`struct\`:code: is not conveyed through the\n ABI. This class represents a tuple that appeared in a method definition.\n Its name is derived from a hash of that tuple's field names, and every\n method whose ABI refers to a tuple with that same list of field names will\n have a generated wrapper method that refers to this class.\n\n Any members of type \`bytes\`:code: should be encoded as UTF-8, which can be\n accomplished via \`str.encode("utf_8")\`:code:\n """${
|
||||
tupleDefinitions[pythonTupleName]
|
||||
}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
return new Handlebars.SafeString(tupleDeclarations.join('\n\n'));
|
||||
});
|
||||
Handlebars.registerHelper('docBytesIfNecessary', (abisJSON: string, options) => {
|
||||
const abis: AbiDefinition[] = JSON.parse(abisJSON);
|
||||
// see if any ABIs accept params of type bytes, and if so then emit
|
||||
// explanatory documentation string.
|
||||
for (const abi of abis) {
|
||||
if (abi.hasOwnProperty('inputs')) {
|
||||
// HACK(feuGeneA): using "as MethodAbi" below, but abi
|
||||
// could just as well be ConstructorAbi, EventAbi, etc. We
|
||||
// just need to tell the TypeScript compiler that it's NOT
|
||||
// FallbackAbi, or else it would complain, "Property
|
||||
// 'inputs' does not exist on type 'AbiDefinition'.
|
||||
// Property 'inputs' does not exist on type
|
||||
// 'FallbackAbi'.", despite the enclosing if statement.
|
||||
// tslint:disable:no-unnecessary-type-assertion
|
||||
if ((abi as MethodAbi).inputs) {
|
||||
for (const input of (abi as MethodAbi).inputs) {
|
||||
if (input.type === 'bytes') {
|
||||
return new Handlebars.SafeString(
|
||||
'\n\n All method parameters of type `bytes`:code: should be encoded as UTF-8,\n which can be accomplished via `str.encode("utf_8")`:code:.\n ',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return '';
|
||||
});
|
||||
}
|
||||
if (args.language === 'TypeScript') {
|
||||
registerTypeScriptHelpers();
|
||||
@@ -168,16 +277,17 @@ for (const abiFileName of abiFileNames) {
|
||||
}
|
||||
|
||||
const outFileName = utils.makeOutputFileName(namedContent.name);
|
||||
const outFileExtension = (() => {
|
||||
const outFilePath = (() => {
|
||||
if (args.language === 'TypeScript') {
|
||||
return 'ts';
|
||||
return `${args.output}/${outFileName}.ts`;
|
||||
} else if (args.language === 'Python') {
|
||||
return 'py';
|
||||
const directory = `${args.output}/${outFileName}`;
|
||||
mkdirp.sync(directory);
|
||||
return `${directory}/__init__.py`;
|
||||
} else {
|
||||
throw new Error(`Unexpected language '${args.language}'`);
|
||||
}
|
||||
})();
|
||||
const outFilePath = `${args.output}/${outFileName}.${outFileExtension}`;
|
||||
|
||||
if (utils.isOutputFileUpToDate(outFilePath, [abiFileName, args.template, ...partialTemplateFileNames])) {
|
||||
logUtils.log(`Already up to date: ${chalk.bold(outFilePath)}`);
|
||||
|
@@ -1,3 +1,7 @@
|
||||
import { createHash } from 'crypto';
|
||||
|
||||
import * as changeCase from 'change-case';
|
||||
import * as cliFormat from 'cli-format';
|
||||
import { AbiType, ConstructorAbi, DataItem } from 'ethereum-types';
|
||||
import * as fs from 'fs';
|
||||
import * as _ from 'lodash';
|
||||
@@ -98,12 +102,12 @@ export const utils = {
|
||||
throw new Error(`Unknown Solidity type found: ${solType}`);
|
||||
}
|
||||
},
|
||||
solTypeToPyType(paramKind: ParamKind, backend: ContractsBackend, solType: string, components?: DataItem[]): string {
|
||||
solTypeToPyType(solType: string, components?: DataItem[]): string {
|
||||
const trailingArrayRegex = /\[\d*\]$/;
|
||||
if (solType.match(trailingArrayRegex)) {
|
||||
const arrayItemSolType = solType.replace(trailingArrayRegex, '');
|
||||
const arrayItemPyType = utils.solTypeToPyType(paramKind, backend, arrayItemSolType, components);
|
||||
const arrayPyType = `Array[${arrayItemPyType}]`;
|
||||
const arrayItemPyType = utils.solTypeToPyType(arrayItemSolType, components);
|
||||
const arrayPyType = `List[${arrayItemPyType}]`;
|
||||
return arrayPyType;
|
||||
} else {
|
||||
const solTypeRegexToPyType = [
|
||||
@@ -121,18 +125,7 @@ export const utils = {
|
||||
}
|
||||
const TUPLE_TYPE_REGEX = '^tuple$';
|
||||
if (solType.match(TUPLE_TYPE_REGEX)) {
|
||||
const componentsType = _.map(components, component => {
|
||||
const componentValueType = utils.solTypeToPyType(
|
||||
paramKind,
|
||||
backend,
|
||||
component.type,
|
||||
component.components,
|
||||
);
|
||||
const componentType = `'${component.name}': ${componentValueType}`;
|
||||
return componentType;
|
||||
});
|
||||
const pyType = `TypedDict('${solType}(${components})', {${componentsType.join(',')}}`;
|
||||
return pyType;
|
||||
return utils.makePythonTupleName(components as DataItem[]);
|
||||
}
|
||||
throw new Error(`Unknown Solidity type found: ${solType}`);
|
||||
}
|
||||
@@ -190,4 +183,171 @@ export const utils = {
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* simply concatenate all of the names of the components, and convert that
|
||||
* concatenation into PascalCase to conform to Python convention.
|
||||
*/
|
||||
makePythonTupleName(tupleComponents: DataItem[]): string {
|
||||
const lengthOfHashSuffix = 8;
|
||||
return `Tuple0x${createHash('MD5')
|
||||
.update(_.map(tupleComponents, component => component.name).join('_'))
|
||||
.digest()
|
||||
.toString('hex')
|
||||
.substring(0, lengthOfHashSuffix)}`;
|
||||
},
|
||||
/**
|
||||
* @returns a string that is a Python code snippet that's intended to be
|
||||
* used as the second parameter to a TypedDict() instantiation; value
|
||||
* looks like "{ 'python_dict_key': python_type, ... }".
|
||||
*/
|
||||
makePythonTupleClassBody(tupleComponents: DataItem[]): string {
|
||||
let toReturn: string = '';
|
||||
for (const tupleComponent of tupleComponents) {
|
||||
toReturn = `${toReturn}\n\n ${tupleComponent.name}: ${utils.solTypeToPyType(
|
||||
tupleComponent.type,
|
||||
tupleComponent.components,
|
||||
)}`;
|
||||
}
|
||||
toReturn = `${toReturn}`;
|
||||
return toReturn;
|
||||
},
|
||||
/**
|
||||
* used to generate Python-parseable identifier names for parameters to
|
||||
* contract methods.
|
||||
*/
|
||||
toPythonIdentifier(input: string): string {
|
||||
let snakeCased = changeCase.snake(input);
|
||||
const pythonReservedWords = [
|
||||
'False',
|
||||
'None',
|
||||
'True',
|
||||
'and',
|
||||
'as',
|
||||
'assert',
|
||||
'break',
|
||||
'class',
|
||||
'continue',
|
||||
'def',
|
||||
'del',
|
||||
'elif',
|
||||
'else',
|
||||
'except',
|
||||
'finally',
|
||||
'for',
|
||||
'from',
|
||||
'global',
|
||||
'if',
|
||||
'import',
|
||||
'in',
|
||||
'is',
|
||||
'lambda',
|
||||
'nonlocal',
|
||||
'not',
|
||||
'or',
|
||||
'pass',
|
||||
'raise',
|
||||
'return',
|
||||
'try',
|
||||
'while',
|
||||
'with',
|
||||
'yield',
|
||||
];
|
||||
const pythonBuiltins = [
|
||||
'abs',
|
||||
'delattr',
|
||||
'hash',
|
||||
'memoryview',
|
||||
'set',
|
||||
'all',
|
||||
'dict',
|
||||
'help',
|
||||
'min',
|
||||
'setattr',
|
||||
'any',
|
||||
'dir',
|
||||
'hex',
|
||||
'next',
|
||||
'slice',
|
||||
'ascii',
|
||||
'divmod',
|
||||
'id',
|
||||
'object',
|
||||
'sorted',
|
||||
'bin',
|
||||
'enumerate',
|
||||
'input',
|
||||
'oct',
|
||||
'staticmethod',
|
||||
'bool',
|
||||
'eval',
|
||||
'int',
|
||||
'open',
|
||||
'str',
|
||||
'breakpoint',
|
||||
'exec',
|
||||
'isinstance',
|
||||
'ord',
|
||||
'sum',
|
||||
'bytearray',
|
||||
'filter',
|
||||
'issubclass',
|
||||
'pow',
|
||||
'super',
|
||||
'bytes',
|
||||
'float',
|
||||
'iter',
|
||||
'print',
|
||||
'tuple',
|
||||
'callable',
|
||||
'format',
|
||||
'len',
|
||||
'property',
|
||||
'type',
|
||||
'chr',
|
||||
'frozenset',
|
||||
'list',
|
||||
'range',
|
||||
'vars',
|
||||
'classmethod',
|
||||
'getattr',
|
||||
'locals',
|
||||
'repr',
|
||||
'zip',
|
||||
'compile',
|
||||
'globals',
|
||||
'map',
|
||||
'reversed',
|
||||
'__import__',
|
||||
'complex',
|
||||
'hasattr',
|
||||
'max',
|
||||
'round',
|
||||
];
|
||||
if (
|
||||
pythonReservedWords.includes(snakeCased) ||
|
||||
pythonBuiltins.includes(snakeCased) ||
|
||||
/*changeCase strips leading underscores :(*/ input[0] === '_'
|
||||
) {
|
||||
snakeCased = `_${snakeCased}`;
|
||||
}
|
||||
return snakeCased;
|
||||
},
|
||||
/**
|
||||
* Python docstrings are used to generate documentation, and that
|
||||
* transformation supports annotation of parameters, return types, etc, via
|
||||
* re-Structured Text "interpreted text roles". Per the pydocstyle linter,
|
||||
* such annotations should be line-wrapped at 80 columns, with a hanging
|
||||
* indent of 4 columns. This function simply returns an accordingly
|
||||
* wrapped and hanging-indented `role` string.
|
||||
*/
|
||||
wrapPythonDocstringRole(docstring: string, indent: number): string {
|
||||
const columnsPerIndent = 4;
|
||||
const columnsPerRow = 80;
|
||||
return cliFormat.wrap(docstring, {
|
||||
paddingLeft: ' '.repeat(indent),
|
||||
width: columnsPerRow,
|
||||
ansi: false,
|
||||
hangingIndent: ' '.repeat(columnsPerIndent),
|
||||
});
|
||||
},
|
||||
};
|
||||
|
@@ -1,4 +1,6 @@
|
||||
diff -r $1 $2
|
||||
diff -r -U 5 $1 $2
|
||||
# -r tells diff to compare folders recursively.
|
||||
# "-U 5" tells diff to output a "unified" format, with 5 lines of context.
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: Freshly generated output does not match expected output. If you're confident that the expected output should be updated, copy it in there and commit it."
|
||||
exit 1
|
@@ -1,243 +0,0 @@
|
||||
"""Generated wrapper for AbiGenDummy Solidity contract."""
|
||||
|
||||
import json
|
||||
from typing import Optional, Tuple, Union
|
||||
|
||||
from hexbytes import HexBytes
|
||||
from web3.datastructures import AttributeDict
|
||||
from web3.providers.base import BaseProvider
|
||||
|
||||
from zero_ex.contract_wrappers._base_contract_wrapper import BaseContractWrapper
|
||||
from zero_ex.contract_wrappers.tx_params import TxParams
|
||||
|
||||
|
||||
class AbiGenDummy(BaseContractWrapper):
|
||||
"""Wrapper class for AbiGenDummy Solidity contract."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
contract_address: str,
|
||||
private_key: str = None,
|
||||
):
|
||||
"""Get an instance of wrapper for smart contract.
|
||||
|
||||
:param provider: instance of :class:`web3.providers.base.BaseProvider`
|
||||
:param contract_address: where the contract has been deployed
|
||||
:param private_key: If specified, transactions will be signed locally,
|
||||
via Web3.py's `eth.account.signTransaction()`:code:, before being
|
||||
sent via `eth.sendRawTransaction()`:code:.
|
||||
"""
|
||||
super().__init__(
|
||||
provider=provider,
|
||||
contract_address=contract_address,
|
||||
private_key=private_key,
|
||||
)
|
||||
|
||||
def _get_contract_instance(self, token_address):
|
||||
"""Get an instance of the smart contract at a specific address.
|
||||
|
||||
:returns: contract object
|
||||
"""
|
||||
return self._contract_instance(
|
||||
address=token_address, abi=AbiGenDummy.abi()
|
||||
)
|
||||
|
||||
def simple_require(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> None:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self._contract_address
|
||||
).functions.simpleRequire(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def ecrecover_fn(
|
||||
self,
|
||||
hash: bytes,
|
||||
v: int,
|
||||
r: bytes,
|
||||
s: bytes,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> str:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self._contract_address
|
||||
).functions.ecrecoverFn(
|
||||
hash,
|
||||
v,
|
||||
r,
|
||||
s
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def revert_with_constant(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> None:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self._contract_address
|
||||
).functions.revertWithConstant(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def simple_revert(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> None:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self._contract_address
|
||||
).functions.simpleRevert(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def require_with_constant(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> None:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self._contract_address
|
||||
).functions.requireWithConstant(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def with_address_input(
|
||||
self,
|
||||
x: str,
|
||||
a: int,
|
||||
b: int,
|
||||
y: str,
|
||||
c: int,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> str:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
|
||||
"""
|
||||
x = self._validate_and_checksum_address(x)
|
||||
# safeguard against fractional inputs
|
||||
a = int(a)
|
||||
# safeguard against fractional inputs
|
||||
b = int(b)
|
||||
y = self._validate_and_checksum_address(y)
|
||||
# safeguard against fractional inputs
|
||||
c = int(c)
|
||||
func = self._get_contract_instance(
|
||||
self._contract_address
|
||||
).functions.withAddressInput(
|
||||
x,
|
||||
a,
|
||||
b,
|
||||
y,
|
||||
c
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def simple_pure_function_with_input(
|
||||
self,
|
||||
x: int,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> int:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
|
||||
"""
|
||||
# safeguard against fractional inputs
|
||||
x = int(x)
|
||||
func = self._get_contract_instance(
|
||||
self._contract_address
|
||||
).functions.simplePureFunctionWithInput(
|
||||
x
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def simple_pure_function(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> int:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self._contract_address
|
||||
).functions.simplePureFunction(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def pure_function_with_constant(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> int:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self._contract_address
|
||||
).functions.pureFunctionWithConstant(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def abi():
|
||||
"""Return the ABI to the underlying contract."""
|
||||
return json.loads(
|
||||
'[{"constant":true,"inputs":[],"name":"simpleRequire","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"hash","type":"bytes32"},{"name":"v","type":"uint8"},{"name":"r","type":"bytes32"},{"name":"s","type":"bytes32"}],"name":"ecrecoverFn","outputs":[{"name":"signerAddress","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"revertWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"simpleRevert","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"requireWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"address"},{"name":"a","type":"uint256"},{"name":"b","type":"uint256"},{"name":"y","type":"address"},{"name":"c","type":"uint256"}],"name":"withAddressInput","outputs":[{"name":"z","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"uint256"}],"name":"simplePureFunctionWithInput","outputs":[{"name":"sum","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"simplePureFunction","outputs":[{"name":"result","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"pureFunctionWithConstant","outputs":[{"name":"someConstant","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"}]' # noqa: E501 (line-too-long)
|
||||
)
|
@@ -0,0 +1,619 @@
|
||||
"""Generated wrapper for AbiGenDummy Solidity contract."""
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
|
||||
import json
|
||||
from typing import ( # pylint: disable=unused-import
|
||||
Any,
|
||||
List,
|
||||
Optional,
|
||||
Tuple,
|
||||
Union,
|
||||
)
|
||||
|
||||
from mypy_extensions import TypedDict # pylint: disable=unused-import
|
||||
from hexbytes import HexBytes
|
||||
from web3.datastructures import AttributeDict
|
||||
from web3.providers.base import BaseProvider
|
||||
|
||||
from zero_ex.contract_wrappers._base_contract_wrapper import BaseContractWrapper
|
||||
from zero_ex.contract_wrappers.tx_params import TxParams
|
||||
|
||||
|
||||
class AbiGenDummyValidatorBase:
|
||||
"""Base class for validating inputs to AbiGenDummy methods."""
|
||||
def __init__(
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
contract_address: str,
|
||||
private_key: str = None,
|
||||
):
|
||||
"""Initialize the instance."""
|
||||
|
||||
def assert_valid(
|
||||
self, method_name: str, parameter_name: str, argument_value: Any
|
||||
):
|
||||
"""Raise an exception if method input is not valid.
|
||||
|
||||
:param method_name: Name of the method whose input is to be validated.
|
||||
:param parameter_name: Name of the parameter whose input is to be
|
||||
validated.
|
||||
:param argument_value: Value of argument to parameter to be validated.
|
||||
"""
|
||||
|
||||
|
||||
# Try to import a custom validator class definition; if there isn't one,
|
||||
# declare one that we can instantiate for the default argument to the
|
||||
# constructor for AbiGenDummy below.
|
||||
try:
|
||||
# both mypy and pylint complain about what we're doing here, but this
|
||||
# works just fine, so their messages have been disabled here.
|
||||
from . import ( # type: ignore # pylint: disable=import-self
|
||||
AbiGenDummyValidator,
|
||||
)
|
||||
except ImportError:
|
||||
|
||||
class AbiGenDummyValidator(AbiGenDummyValidatorBase): # type: ignore
|
||||
"""No-op input validator."""
|
||||
|
||||
|
||||
class Tuple0xc9bdd2d5(TypedDict):
|
||||
"""Python representation of a tuple or struct.
|
||||
|
||||
A tuple found in an ABI may have been written in Solidity as a literal
|
||||
tuple, or it may have been written as a parameter with a Solidity
|
||||
`struct`:code: data type; there's no way to tell which, based solely on the
|
||||
ABI, and the name of a Solidity `struct`:code: is not conveyed through the
|
||||
ABI. This class represents a tuple that appeared in a method definition.
|
||||
Its name is derived from a hash of that tuple's field names, and every
|
||||
method whose ABI refers to a tuple with that same list of field names will
|
||||
have a generated wrapper method that refers to this class.
|
||||
|
||||
Any members of type `bytes`:code: should be encoded as UTF-8, which can be
|
||||
accomplished via `str.encode("utf_8")`:code:
|
||||
"""
|
||||
|
||||
innerStruct: Tuple0xcf8ad995
|
||||
|
||||
description: str
|
||||
|
||||
class Tuple0xcf8ad995(TypedDict):
|
||||
"""Python representation of a tuple or struct.
|
||||
|
||||
A tuple found in an ABI may have been written in Solidity as a literal
|
||||
tuple, or it may have been written as a parameter with a Solidity
|
||||
`struct`:code: data type; there's no way to tell which, based solely on the
|
||||
ABI, and the name of a Solidity `struct`:code: is not conveyed through the
|
||||
ABI. This class represents a tuple that appeared in a method definition.
|
||||
Its name is derived from a hash of that tuple's field names, and every
|
||||
method whose ABI refers to a tuple with that same list of field names will
|
||||
have a generated wrapper method that refers to this class.
|
||||
|
||||
Any members of type `bytes`:code: should be encoded as UTF-8, which can be
|
||||
accomplished via `str.encode("utf_8")`:code:
|
||||
"""
|
||||
|
||||
someBytes: bytes
|
||||
|
||||
anInteger: int
|
||||
|
||||
aDynamicArrayOfBytes: List[bytes]
|
||||
|
||||
aString: str
|
||||
|
||||
|
||||
# pylint: disable=too-many-public-methods
|
||||
class AbiGenDummy(BaseContractWrapper):
|
||||
"""Wrapper class for AbiGenDummy Solidity contract.
|
||||
|
||||
All method parameters of type `bytes`:code: should be encoded as UTF-8,
|
||||
which can be accomplished via `str.encode("utf_8")`:code:.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
contract_address: str,
|
||||
validator: AbiGenDummyValidator = None,
|
||||
private_key: str = None,
|
||||
):
|
||||
"""Get an instance of wrapper for smart contract.
|
||||
|
||||
:param provider: instance of :class:`web3.providers.base.BaseProvider`
|
||||
:param contract_address: where the contract has been deployed
|
||||
:param private_key: If specified, transactions will be signed locally,
|
||||
via Web3.py's `eth.account.signTransaction()`:code:, before being
|
||||
sent via `eth.sendRawTransaction()`:code:.
|
||||
"""
|
||||
super().__init__(
|
||||
provider=provider,
|
||||
contract_address=contract_address,
|
||||
private_key=private_key,
|
||||
)
|
||||
|
||||
if not validator:
|
||||
validator = AbiGenDummyValidator(provider, contract_address, private_key)
|
||||
|
||||
self.validator = validator
|
||||
|
||||
def _get_contract_instance(self, token_address):
|
||||
"""Get an instance of the smart contract at a specific address.
|
||||
|
||||
:returns: contract object
|
||||
"""
|
||||
return self._contract_instance(
|
||||
address=token_address, abi=AbiGenDummy.abi()
|
||||
)
|
||||
|
||||
def simple_require(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> None:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.simpleRequire(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def accepts_an_array_of_bytes(
|
||||
self,
|
||||
a: List[bytes],
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> None:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
a method that accepts an array of bytes
|
||||
|
||||
:param a: the array of bytes being accepted
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
self.validator.assert_valid(
|
||||
method_name='acceptsAnArrayOfBytes',
|
||||
parameter_name='a',
|
||||
argument_value=a,
|
||||
)
|
||||
a = [
|
||||
bytes.fromhex(a_element.decode("utf-8"))
|
||||
for a_element in a
|
||||
]
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.acceptsAnArrayOfBytes(
|
||||
a
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def ecrecover_fn(
|
||||
self,
|
||||
_hash: bytes,
|
||||
v: int,
|
||||
r: bytes,
|
||||
s: bytes,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> str:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
self.validator.assert_valid(
|
||||
method_name='ecrecoverFn',
|
||||
parameter_name='hash',
|
||||
argument_value=_hash,
|
||||
)
|
||||
self.validator.assert_valid(
|
||||
method_name='ecrecoverFn',
|
||||
parameter_name='v',
|
||||
argument_value=v,
|
||||
)
|
||||
self.validator.assert_valid(
|
||||
method_name='ecrecoverFn',
|
||||
parameter_name='r',
|
||||
argument_value=r,
|
||||
)
|
||||
self.validator.assert_valid(
|
||||
method_name='ecrecoverFn',
|
||||
parameter_name='s',
|
||||
argument_value=s,
|
||||
)
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.ecrecoverFn(
|
||||
_hash,
|
||||
v,
|
||||
r,
|
||||
s
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def accepts_bytes(
|
||||
self,
|
||||
a: bytes,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> None:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
self.validator.assert_valid(
|
||||
method_name='acceptsBytes',
|
||||
parameter_name='a',
|
||||
argument_value=a,
|
||||
)
|
||||
a = bytes.fromhex(a.decode("utf-8"))
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.acceptsBytes(
|
||||
a
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def revert_with_constant(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> None:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.revertWithConstant(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def simple_revert(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> None:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.simpleRevert(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def nested_struct_output(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> Tuple0xc9bdd2d5:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.nestedStructOutput(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def require_with_constant(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> None:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.requireWithConstant(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def with_address_input(
|
||||
self,
|
||||
x: str,
|
||||
a: int,
|
||||
b: int,
|
||||
y: str,
|
||||
c: int,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> str:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
self.validator.assert_valid(
|
||||
method_name='withAddressInput',
|
||||
parameter_name='x',
|
||||
argument_value=x,
|
||||
)
|
||||
x = self._validate_and_checksum_address(x)
|
||||
self.validator.assert_valid(
|
||||
method_name='withAddressInput',
|
||||
parameter_name='a',
|
||||
argument_value=a,
|
||||
)
|
||||
# safeguard against fractional inputs
|
||||
a = int(a)
|
||||
self.validator.assert_valid(
|
||||
method_name='withAddressInput',
|
||||
parameter_name='b',
|
||||
argument_value=b,
|
||||
)
|
||||
# safeguard against fractional inputs
|
||||
b = int(b)
|
||||
self.validator.assert_valid(
|
||||
method_name='withAddressInput',
|
||||
parameter_name='y',
|
||||
argument_value=y,
|
||||
)
|
||||
y = self._validate_and_checksum_address(y)
|
||||
self.validator.assert_valid(
|
||||
method_name='withAddressInput',
|
||||
parameter_name='c',
|
||||
argument_value=c,
|
||||
)
|
||||
# safeguard against fractional inputs
|
||||
c = int(c)
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.withAddressInput(
|
||||
x,
|
||||
a,
|
||||
b,
|
||||
y,
|
||||
c
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def struct_input(
|
||||
self,
|
||||
s: Tuple0xcf8ad995,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> None:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
self.validator.assert_valid(
|
||||
method_name='structInput',
|
||||
parameter_name='s',
|
||||
argument_value=s,
|
||||
)
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.structInput(
|
||||
s
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def non_pure_method(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
view_only: bool = False,
|
||||
) -> Union[int, Union[HexBytes, bytes]]:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
:param view_only: whether to use transact() or call()
|
||||
|
||||
:returns: if param `view_only`:code: is `True`:code:, then returns the
|
||||
value returned from the underlying function; else returns the
|
||||
transaction hash.
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.nonPureMethod(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=view_only
|
||||
)
|
||||
|
||||
def simple_pure_function_with_input(
|
||||
self,
|
||||
x: int,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> int:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
self.validator.assert_valid(
|
||||
method_name='simplePureFunctionWithInput',
|
||||
parameter_name='x',
|
||||
argument_value=x,
|
||||
)
|
||||
# safeguard against fractional inputs
|
||||
x = int(x)
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.simplePureFunctionWithInput(
|
||||
x
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def non_pure_method_that_returns_nothing(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
view_only: bool = False,
|
||||
) -> Union[None, Union[HexBytes, bytes]]:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
:param view_only: whether to use transact() or call()
|
||||
|
||||
:returns: if param `view_only`:code: is `True`:code:, then returns the
|
||||
value returned from the underlying function; else returns the
|
||||
transaction hash.
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.nonPureMethodThatReturnsNothing(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=view_only
|
||||
)
|
||||
|
||||
def simple_pure_function(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> int:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.simplePureFunction(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def nested_struct_input(
|
||||
self,
|
||||
n: Tuple0xc9bdd2d5,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> None:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
self.validator.assert_valid(
|
||||
method_name='nestedStructInput',
|
||||
parameter_name='n',
|
||||
argument_value=n,
|
||||
)
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.nestedStructInput(
|
||||
n
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def struct_output(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> Tuple0xcf8ad995:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
a method that returns a struct
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
:returns: a Struct struct
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.structOutput(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def pure_function_with_constant(
|
||||
self,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
) -> int:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
func = self._get_contract_instance(
|
||||
self.contract_address
|
||||
).functions.pureFunctionWithConstant(
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
def get_an_event_event(
|
||||
self, tx_hash: Union[HexBytes, bytes]
|
||||
) -> Tuple[AttributeDict]:
|
||||
"""Get log entry for AnEvent event.
|
||||
|
||||
:param tx_hash: hash of transaction emitting AnEvent event
|
||||
"""
|
||||
tx_receipt = self._web3_eth.getTransactionReceipt(tx_hash)
|
||||
return (
|
||||
self._get_contract_instance(self.contract_address)
|
||||
.events.AnEvent()
|
||||
.processReceipt(tx_receipt)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def abi():
|
||||
"""Return the ABI to the underlying contract."""
|
||||
return json.loads(
|
||||
'[{"constant":true,"inputs":[],"name":"simpleRequire","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"bytes[]"}],"name":"acceptsAnArrayOfBytes","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"hash","type":"bytes32"},{"name":"v","type":"uint8"},{"name":"r","type":"bytes32"},{"name":"s","type":"bytes32"}],"name":"ecrecoverFn","outputs":[{"name":"signerAddress","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"bytes"}],"name":"acceptsBytes","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"revertWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"simpleRevert","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"nestedStructOutput","outputs":[{"components":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"innerStruct","type":"tuple"},{"name":"description","type":"string"}],"name":"","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"requireWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"address"},{"name":"a","type":"uint256"},{"name":"b","type":"uint256"},{"name":"y","type":"address"},{"name":"c","type":"uint256"}],"name":"withAddressInput","outputs":[{"name":"z","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"s","type":"tuple"}],"name":"structInput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"nonPureMethod","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"uint256"}],"name":"simplePureFunctionWithInput","outputs":[{"name":"sum","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"nonPureMethodThatReturnsNothing","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"simplePureFunction","outputs":[{"name":"result","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"innerStruct","type":"tuple"},{"name":"description","type":"string"}],"name":"n","type":"tuple"}],"name":"nestedStructInput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"structOutput","outputs":[{"components":[{"name":"someBytes","type":"bytes"},{"name":"anInteger","type":"uint32"},{"name":"aDynamicArrayOfBytes","type":"bytes[]"},{"name":"aString","type":"string"}],"name":"s","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"pureFunctionWithConstant","outputs":[{"name":"someConstant","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"param","type":"uint8"}],"name":"AnEvent","type":"event"}]' # noqa: E501 (line-too-long)
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-lines
|
@@ -1,51 +0,0 @@
|
||||
"""Generated wrapper for LibDummy Solidity contract."""
|
||||
|
||||
import json
|
||||
from typing import Optional, Tuple, Union
|
||||
|
||||
from hexbytes import HexBytes
|
||||
from web3.datastructures import AttributeDict
|
||||
from web3.providers.base import BaseProvider
|
||||
|
||||
from zero_ex.contract_wrappers._base_contract_wrapper import BaseContractWrapper
|
||||
from zero_ex.contract_wrappers.tx_params import TxParams
|
||||
|
||||
|
||||
class LibDummy(BaseContractWrapper):
|
||||
"""Wrapper class for LibDummy Solidity contract."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
contract_address: str,
|
||||
private_key: str = None,
|
||||
):
|
||||
"""Get an instance of wrapper for smart contract.
|
||||
|
||||
:param provider: instance of :class:`web3.providers.base.BaseProvider`
|
||||
:param contract_address: where the contract has been deployed
|
||||
:param private_key: If specified, transactions will be signed locally,
|
||||
via Web3.py's `eth.account.signTransaction()`:code:, before being
|
||||
sent via `eth.sendRawTransaction()`:code:.
|
||||
"""
|
||||
super().__init__(
|
||||
provider=provider,
|
||||
contract_address=contract_address,
|
||||
private_key=private_key,
|
||||
)
|
||||
|
||||
def _get_contract_instance(self, token_address):
|
||||
"""Get an instance of the smart contract at a specific address.
|
||||
|
||||
:returns: contract object
|
||||
"""
|
||||
return self._contract_instance(
|
||||
address=token_address, abi=LibDummy.abi()
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def abi():
|
||||
"""Return the ABI to the underlying contract."""
|
||||
return json.loads(
|
||||
'[]' # noqa: E501 (line-too-long)
|
||||
)
|
@@ -0,0 +1,109 @@
|
||||
"""Generated wrapper for LibDummy Solidity contract."""
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
|
||||
import json
|
||||
from typing import ( # pylint: disable=unused-import
|
||||
Any,
|
||||
List,
|
||||
Optional,
|
||||
Tuple,
|
||||
Union,
|
||||
)
|
||||
|
||||
from mypy_extensions import TypedDict # pylint: disable=unused-import
|
||||
from hexbytes import HexBytes
|
||||
from web3.datastructures import AttributeDict
|
||||
from web3.providers.base import BaseProvider
|
||||
|
||||
from zero_ex.contract_wrappers._base_contract_wrapper import BaseContractWrapper
|
||||
from zero_ex.contract_wrappers.tx_params import TxParams
|
||||
|
||||
|
||||
class LibDummyValidatorBase:
|
||||
"""Base class for validating inputs to LibDummy methods."""
|
||||
def __init__(
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
contract_address: str,
|
||||
private_key: str = None,
|
||||
):
|
||||
"""Initialize the instance."""
|
||||
|
||||
def assert_valid(
|
||||
self, method_name: str, parameter_name: str, argument_value: Any
|
||||
):
|
||||
"""Raise an exception if method input is not valid.
|
||||
|
||||
:param method_name: Name of the method whose input is to be validated.
|
||||
:param parameter_name: Name of the parameter whose input is to be
|
||||
validated.
|
||||
:param argument_value: Value of argument to parameter to be validated.
|
||||
"""
|
||||
|
||||
|
||||
# Try to import a custom validator class definition; if there isn't one,
|
||||
# declare one that we can instantiate for the default argument to the
|
||||
# constructor for LibDummy below.
|
||||
try:
|
||||
# both mypy and pylint complain about what we're doing here, but this
|
||||
# works just fine, so their messages have been disabled here.
|
||||
from . import ( # type: ignore # pylint: disable=import-self
|
||||
LibDummyValidator,
|
||||
)
|
||||
except ImportError:
|
||||
|
||||
class LibDummyValidator(LibDummyValidatorBase): # type: ignore
|
||||
"""No-op input validator."""
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# pylint: disable=too-many-public-methods
|
||||
class LibDummy(BaseContractWrapper):
|
||||
"""Wrapper class for LibDummy Solidity contract."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
contract_address: str,
|
||||
validator: LibDummyValidator = None,
|
||||
private_key: str = None,
|
||||
):
|
||||
"""Get an instance of wrapper for smart contract.
|
||||
|
||||
:param provider: instance of :class:`web3.providers.base.BaseProvider`
|
||||
:param contract_address: where the contract has been deployed
|
||||
:param private_key: If specified, transactions will be signed locally,
|
||||
via Web3.py's `eth.account.signTransaction()`:code:, before being
|
||||
sent via `eth.sendRawTransaction()`:code:.
|
||||
"""
|
||||
super().__init__(
|
||||
provider=provider,
|
||||
contract_address=contract_address,
|
||||
private_key=private_key,
|
||||
)
|
||||
|
||||
if not validator:
|
||||
validator = LibDummyValidator(provider, contract_address, private_key)
|
||||
|
||||
self.validator = validator
|
||||
|
||||
def _get_contract_instance(self, token_address):
|
||||
"""Get an instance of the smart contract at a specific address.
|
||||
|
||||
:returns: contract object
|
||||
"""
|
||||
return self._contract_instance(
|
||||
address=token_address, abi=LibDummy.abi()
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def abi():
|
||||
"""Return the ABI to the underlying contract."""
|
||||
return json.loads(
|
||||
'[]' # noqa: E501 (line-too-long)
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-lines
|
@@ -1,8 +1,17 @@
|
||||
"""Generated wrapper for TestLibDummy Solidity contract."""
|
||||
|
||||
import json
|
||||
from typing import Optional, Tuple, Union
|
||||
# pylint: disable=too-many-arguments
|
||||
|
||||
import json
|
||||
from typing import ( # pylint: disable=unused-import
|
||||
Any,
|
||||
List,
|
||||
Optional,
|
||||
Tuple,
|
||||
Union,
|
||||
)
|
||||
|
||||
from mypy_extensions import TypedDict # pylint: disable=unused-import
|
||||
from hexbytes import HexBytes
|
||||
from web3.datastructures import AttributeDict
|
||||
from web3.providers.base import BaseProvider
|
||||
@@ -11,6 +20,47 @@ from zero_ex.contract_wrappers._base_contract_wrapper import BaseContractWrapper
|
||||
from zero_ex.contract_wrappers.tx_params import TxParams
|
||||
|
||||
|
||||
class TestLibDummyValidatorBase:
|
||||
"""Base class for validating inputs to TestLibDummy methods."""
|
||||
def __init__(
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
contract_address: str,
|
||||
private_key: str = None,
|
||||
):
|
||||
"""Initialize the instance."""
|
||||
|
||||
def assert_valid(
|
||||
self, method_name: str, parameter_name: str, argument_value: Any
|
||||
):
|
||||
"""Raise an exception if method input is not valid.
|
||||
|
||||
:param method_name: Name of the method whose input is to be validated.
|
||||
:param parameter_name: Name of the parameter whose input is to be
|
||||
validated.
|
||||
:param argument_value: Value of argument to parameter to be validated.
|
||||
"""
|
||||
|
||||
|
||||
# Try to import a custom validator class definition; if there isn't one,
|
||||
# declare one that we can instantiate for the default argument to the
|
||||
# constructor for TestLibDummy below.
|
||||
try:
|
||||
# both mypy and pylint complain about what we're doing here, but this
|
||||
# works just fine, so their messages have been disabled here.
|
||||
from . import ( # type: ignore # pylint: disable=import-self
|
||||
TestLibDummyValidator,
|
||||
)
|
||||
except ImportError:
|
||||
|
||||
class TestLibDummyValidator(TestLibDummyValidatorBase): # type: ignore
|
||||
"""No-op input validator."""
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# pylint: disable=too-many-public-methods
|
||||
class TestLibDummy(BaseContractWrapper):
|
||||
"""Wrapper class for TestLibDummy Solidity contract."""
|
||||
|
||||
@@ -18,6 +68,7 @@ class TestLibDummy(BaseContractWrapper):
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
contract_address: str,
|
||||
validator: TestLibDummyValidator = None,
|
||||
private_key: str = None,
|
||||
):
|
||||
"""Get an instance of wrapper for smart contract.
|
||||
@@ -34,6 +85,11 @@ class TestLibDummy(BaseContractWrapper):
|
||||
private_key=private_key,
|
||||
)
|
||||
|
||||
if not validator:
|
||||
validator = TestLibDummyValidator(provider, contract_address, private_key)
|
||||
|
||||
self.validator = validator
|
||||
|
||||
def _get_contract_instance(self, token_address):
|
||||
"""Get an instance of the smart contract at a specific address.
|
||||
|
||||
@@ -50,12 +106,18 @@ class TestLibDummy(BaseContractWrapper):
|
||||
) -> int:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
self.validator.assert_valid(
|
||||
method_name='publicAddConstant',
|
||||
parameter_name='x',
|
||||
argument_value=x,
|
||||
)
|
||||
# safeguard against fractional inputs
|
||||
x = int(x)
|
||||
func = self._get_contract_instance(
|
||||
self._contract_address
|
||||
self.contract_address
|
||||
).functions.publicAddConstant(
|
||||
x
|
||||
)
|
||||
@@ -72,12 +134,18 @@ class TestLibDummy(BaseContractWrapper):
|
||||
) -> int:
|
||||
"""Execute underlying, same-named contract method.
|
||||
|
||||
:param tx_params: transaction parameters
|
||||
|
||||
"""
|
||||
self.validator.assert_valid(
|
||||
method_name='publicAddOne',
|
||||
parameter_name='x',
|
||||
argument_value=x,
|
||||
)
|
||||
# safeguard against fractional inputs
|
||||
x = int(x)
|
||||
func = self._get_contract_instance(
|
||||
self._contract_address
|
||||
self.contract_address
|
||||
).functions.publicAddOne(
|
||||
x
|
||||
)
|
||||
@@ -93,3 +161,5 @@ class TestLibDummy(BaseContractWrapper):
|
||||
return json.loads(
|
||||
'[{"constant":true,"inputs":[{"name":"x","type":"uint256"}],"name":"publicAddConstant","outputs":[{"name":"result","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"x","type":"uint256"}],"name":"publicAddOne","outputs":[{"name":"result","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"}]' # noqa: E501 (line-too-long)
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-lines
|
@@ -23,6 +23,16 @@ import { assert } from '@0x/assert';
|
||||
import * as ethers from 'ethers';
|
||||
// tslint:enable:no-unused-variable
|
||||
|
||||
export type AbiGenDummyEventArgs = AbiGenDummyAnEventEventArgs;
|
||||
|
||||
export enum AbiGenDummyEvents {
|
||||
AnEvent = 'AnEvent',
|
||||
}
|
||||
|
||||
export interface AbiGenDummyAnEventEventArgs extends DecodedLogArgs {
|
||||
param: number;
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
@@ -65,6 +75,46 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public acceptsAnArrayOfBytes = {
|
||||
async callAsync(a: string[], callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
|
||||
assert.isArray('a', a);
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('acceptsAnArrayOfBytes(bytes[])', [a]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
callDataWithDefaults.from = callDataWithDefaults.from
|
||||
? callDataWithDefaults.from.toLowerCase()
|
||||
: callDataWithDefaults.from;
|
||||
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('acceptsAnArrayOfBytes(bytes[])');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
getABIEncodedTransactionData(a: string[]): string {
|
||||
assert.isArray('a', a);
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('acceptsAnArrayOfBytes(bytes[])', [a]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public ecrecoverFn = {
|
||||
async callAsync(
|
||||
hash: string,
|
||||
@@ -126,6 +176,46 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public acceptsBytes = {
|
||||
async callAsync(a: string, callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
|
||||
assert.isString('a', a);
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('acceptsBytes(bytes)', [a]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
callDataWithDefaults.from = callDataWithDefaults.from
|
||||
? callDataWithDefaults.from.toLowerCase()
|
||||
: callDataWithDefaults.from;
|
||||
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('acceptsBytes(bytes)');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
getABIEncodedTransactionData(a: string): string {
|
||||
assert.isString('a', a);
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('acceptsBytes(bytes)', [a]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public revertWithConstant = {
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
@@ -202,6 +292,53 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public nestedStructOutput = {
|
||||
async callAsync(
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<{
|
||||
innerStruct: { someBytes: string; anInteger: number; aDynamicArrayOfBytes: string[]; aString: string };
|
||||
description: string;
|
||||
}> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('nestedStructOutput()', []);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
callDataWithDefaults.from = callDataWithDefaults.from
|
||||
? callDataWithDefaults.from.toLowerCase()
|
||||
: callDataWithDefaults.from;
|
||||
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('nestedStructOutput()');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<{
|
||||
innerStruct: { someBytes: string; anInteger: number; aDynamicArrayOfBytes: string[]; aString: string };
|
||||
description: string;
|
||||
}>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
getABIEncodedTransactionData(): string {
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('nestedStructOutput()', []);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public requireWithConstant = {
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
@@ -302,6 +439,150 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public structInput = {
|
||||
async callAsync(
|
||||
s: { someBytes: string; anInteger: number | BigNumber; aDynamicArrayOfBytes: string[]; aString: string },
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<void> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('structInput((bytes,uint32,bytes[],string))', [s]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
callDataWithDefaults.from = callDataWithDefaults.from
|
||||
? callDataWithDefaults.from.toLowerCase()
|
||||
: callDataWithDefaults.from;
|
||||
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('structInput((bytes,uint32,bytes[],string))');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
getABIEncodedTransactionData(s: {
|
||||
someBytes: string;
|
||||
anInteger: number | BigNumber;
|
||||
aDynamicArrayOfBytes: string[];
|
||||
aString: string;
|
||||
}): string {
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments(
|
||||
'structInput((bytes,uint32,bytes[],string))',
|
||||
[s],
|
||||
);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public nonPureMethod = {
|
||||
async sendTransactionAsync(txData?: Partial<TxData> | undefined): Promise<string> {
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('nonPureMethod()', []);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
self.nonPureMethod.estimateGasAsync.bind(self),
|
||||
);
|
||||
if (txDataWithDefaults.from !== undefined) {
|
||||
txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase();
|
||||
}
|
||||
|
||||
const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
return txHash;
|
||||
},
|
||||
awaitTransactionSuccessAsync(
|
||||
txData?: Partial<TxData>,
|
||||
pollingIntervalMs?: number,
|
||||
timeoutMs?: number,
|
||||
): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const txHashPromise = self.nonPureMethod.sendTransactionAsync(txData);
|
||||
return new PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs>(
|
||||
txHashPromise,
|
||||
(async (): Promise<TransactionReceiptWithDecodedLogs> => {
|
||||
// When the transaction hash resolves, wait for it to be mined.
|
||||
return self._web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await txHashPromise,
|
||||
pollingIntervalMs,
|
||||
timeoutMs,
|
||||
);
|
||||
})(),
|
||||
);
|
||||
},
|
||||
async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('nonPureMethod()', []);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
if (txDataWithDefaults.from !== undefined) {
|
||||
txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase();
|
||||
}
|
||||
|
||||
const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
||||
return gas;
|
||||
},
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('nonPureMethod()', []);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
callDataWithDefaults.from = callDataWithDefaults.from
|
||||
? callDataWithDefaults.from.toLowerCase()
|
||||
: callDataWithDefaults.from;
|
||||
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('nonPureMethod()');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
getABIEncodedTransactionData(): string {
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('nonPureMethod()', []);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public simplePureFunctionWithInput = {
|
||||
async callAsync(x: BigNumber, callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
|
||||
assert.isBigNumber('x', x);
|
||||
@@ -342,6 +623,100 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public nonPureMethodThatReturnsNothing = {
|
||||
async sendTransactionAsync(txData?: Partial<TxData> | undefined): Promise<string> {
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('nonPureMethodThatReturnsNothing()', []);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
self.nonPureMethodThatReturnsNothing.estimateGasAsync.bind(self),
|
||||
);
|
||||
if (txDataWithDefaults.from !== undefined) {
|
||||
txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase();
|
||||
}
|
||||
|
||||
const txHash = await self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
return txHash;
|
||||
},
|
||||
awaitTransactionSuccessAsync(
|
||||
txData?: Partial<TxData>,
|
||||
pollingIntervalMs?: number,
|
||||
timeoutMs?: number,
|
||||
): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const txHashPromise = self.nonPureMethodThatReturnsNothing.sendTransactionAsync(txData);
|
||||
return new PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs>(
|
||||
txHashPromise,
|
||||
(async (): Promise<TransactionReceiptWithDecodedLogs> => {
|
||||
// When the transaction hash resolves, wait for it to be mined.
|
||||
return self._web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await txHashPromise,
|
||||
pollingIntervalMs,
|
||||
timeoutMs,
|
||||
);
|
||||
})(),
|
||||
);
|
||||
},
|
||||
async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('nonPureMethodThatReturnsNothing()', []);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...txData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
if (txDataWithDefaults.from !== undefined) {
|
||||
txDataWithDefaults.from = txDataWithDefaults.from.toLowerCase();
|
||||
}
|
||||
|
||||
const gas = await self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
||||
return gas;
|
||||
},
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('nonPureMethodThatReturnsNothing()', []);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
callDataWithDefaults.from = callDataWithDefaults.from
|
||||
? callDataWithDefaults.from.toLowerCase()
|
||||
: callDataWithDefaults.from;
|
||||
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('nonPureMethodThatReturnsNothing()');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
getABIEncodedTransactionData(): string {
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('nonPureMethodThatReturnsNothing()', []);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public simplePureFunction = {
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
@@ -380,6 +755,116 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public nestedStructInput = {
|
||||
async callAsync(
|
||||
n: {
|
||||
innerStruct: {
|
||||
someBytes: string;
|
||||
anInteger: number | BigNumber;
|
||||
aDynamicArrayOfBytes: string[];
|
||||
aString: string;
|
||||
};
|
||||
description: string;
|
||||
},
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<void> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments(
|
||||
'nestedStructInput(((bytes,uint32,bytes[],string),string))',
|
||||
[n],
|
||||
);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
callDataWithDefaults.from = callDataWithDefaults.from
|
||||
? callDataWithDefaults.from.toLowerCase()
|
||||
: callDataWithDefaults.from;
|
||||
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('nestedStructInput(((bytes,uint32,bytes[],string),string))');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
getABIEncodedTransactionData(n: {
|
||||
innerStruct: {
|
||||
someBytes: string;
|
||||
anInteger: number | BigNumber;
|
||||
aDynamicArrayOfBytes: string[];
|
||||
aString: string;
|
||||
};
|
||||
description: string;
|
||||
}): string {
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments(
|
||||
'nestedStructInput(((bytes,uint32,bytes[],string),string))',
|
||||
[n],
|
||||
);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public structOutput = {
|
||||
async callAsync(
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<{ someBytes: string; anInteger: number; aDynamicArrayOfBytes: string[]; aString: string }> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
schemas.jsNumber,
|
||||
]);
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('structOutput()', []);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
...callData,
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
);
|
||||
callDataWithDefaults.from = callDataWithDefaults.from
|
||||
? callDataWithDefaults.from.toLowerCase()
|
||||
: callDataWithDefaults.from;
|
||||
|
||||
const rawCallResult = await self._web3Wrapper.callAsync(callDataWithDefaults, defaultBlock);
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('structOutput()');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<{
|
||||
someBytes: string;
|
||||
anInteger: number;
|
||||
aDynamicArrayOfBytes: string[];
|
||||
aString: string;
|
||||
}>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
getABIEncodedTransactionData(): string {
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('structOutput()', []);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public pureFunctionWithConstant = {
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
@@ -483,6 +968,20 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
stateMutability: 'pure',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
name: 'a',
|
||||
type: 'bytes[]',
|
||||
},
|
||||
],
|
||||
name: 'acceptsAnArrayOfBytes',
|
||||
outputs: [],
|
||||
payable: false,
|
||||
stateMutability: 'pure',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
@@ -514,6 +1013,20 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
stateMutability: 'pure',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
name: 'a',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
name: 'acceptsBytes',
|
||||
outputs: [],
|
||||
payable: false,
|
||||
stateMutability: 'pure',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
@@ -532,6 +1045,48 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
stateMutability: 'pure',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
name: 'nestedStructOutput',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'tuple',
|
||||
components: [
|
||||
{
|
||||
name: 'innerStruct',
|
||||
type: 'tuple',
|
||||
components: [
|
||||
{
|
||||
name: 'someBytes',
|
||||
type: 'bytes',
|
||||
},
|
||||
{
|
||||
name: 'anInteger',
|
||||
type: 'uint32',
|
||||
},
|
||||
{
|
||||
name: 'aDynamicArrayOfBytes',
|
||||
type: 'bytes[]',
|
||||
},
|
||||
{
|
||||
name: 'aString',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'pure',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
@@ -576,6 +1131,52 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
stateMutability: 'pure',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
name: 's',
|
||||
type: 'tuple',
|
||||
components: [
|
||||
{
|
||||
name: 'someBytes',
|
||||
type: 'bytes',
|
||||
},
|
||||
{
|
||||
name: 'anInteger',
|
||||
type: 'uint32',
|
||||
},
|
||||
{
|
||||
name: 'aDynamicArrayOfBytes',
|
||||
type: 'bytes[]',
|
||||
},
|
||||
{
|
||||
name: 'aString',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
name: 'structInput',
|
||||
outputs: [],
|
||||
payable: false,
|
||||
stateMutability: 'pure',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: false,
|
||||
inputs: [],
|
||||
name: 'nonPureMethod',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'uint256',
|
||||
},
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
@@ -595,6 +1196,15 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
stateMutability: 'pure',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: false,
|
||||
inputs: [],
|
||||
name: 'nonPureMethodThatReturnsNothing',
|
||||
outputs: [],
|
||||
payable: false,
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
@@ -609,6 +1219,80 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
stateMutability: 'pure',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [
|
||||
{
|
||||
name: 'n',
|
||||
type: 'tuple',
|
||||
components: [
|
||||
{
|
||||
name: 'innerStruct',
|
||||
type: 'tuple',
|
||||
components: [
|
||||
{
|
||||
name: 'someBytes',
|
||||
type: 'bytes',
|
||||
},
|
||||
{
|
||||
name: 'anInteger',
|
||||
type: 'uint32',
|
||||
},
|
||||
{
|
||||
name: 'aDynamicArrayOfBytes',
|
||||
type: 'bytes[]',
|
||||
},
|
||||
{
|
||||
name: 'aString',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
name: 'nestedStructInput',
|
||||
outputs: [],
|
||||
payable: false,
|
||||
stateMutability: 'pure',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
name: 'structOutput',
|
||||
outputs: [
|
||||
{
|
||||
name: 's',
|
||||
type: 'tuple',
|
||||
components: [
|
||||
{
|
||||
name: 'someBytes',
|
||||
type: 'bytes',
|
||||
},
|
||||
{
|
||||
name: 'anInteger',
|
||||
type: 'uint32',
|
||||
},
|
||||
{
|
||||
name: 'aDynamicArrayOfBytes',
|
||||
type: 'bytes[]',
|
||||
},
|
||||
{
|
||||
name: 'aString',
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'pure',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
@@ -623,6 +1307,19 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
stateMutability: 'pure',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{
|
||||
name: 'param',
|
||||
type: 'uint8',
|
||||
indexed: false,
|
||||
},
|
||||
],
|
||||
name: 'AnEvent',
|
||||
outputs: [],
|
||||
type: 'event',
|
||||
},
|
||||
] as ContractAbi;
|
||||
return abi;
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@@ -3,17 +3,20 @@
|
||||
"contractName": "LibDummy",
|
||||
"compilerOutput": {
|
||||
"abi": [],
|
||||
"devdoc": {
|
||||
"methods": {}
|
||||
},
|
||||
"evm": {
|
||||
"bytecode": {
|
||||
"linkReferences": {},
|
||||
"object": "0x60556023600b82828239805160001a607314601657fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72305820a278ce8d53a26107b2f2ba78687fa040ee9ab2ecf0e44ebff0f9410c586e0c6d64736f6c634300050a0032",
|
||||
"opcodes": "PUSH1 0x55 PUSH1 0x23 PUSH1 0xB DUP3 DUP3 DUP3 CODECOPY DUP1 MLOAD PUSH1 0x0 BYTE PUSH1 0x73 EQ PUSH1 0x16 JUMPI INVALID JUMPDEST ADDRESS PUSH1 0x0 MSTORE PUSH1 0x73 DUP2 MSTORE8 DUP3 DUP2 RETURN INVALID PUSH20 0x0 ADDRESS EQ PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 LOG2 PUSH25 0xCE8D53A26107B2F2BA78687FA040EE9AB2ECF0E44EBFF0F941 0xc PC PUSH15 0xC6D64736F6C634300050A00320000 ",
|
||||
"object": "0x60556023600b82828239805160001a607314601657fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72305820b14322cd05aa1dcae66812e472d3ab85cced78118ea7f9a5098d073b2accc45964736f6c634300050a0032",
|
||||
"opcodes": "PUSH1 0x55 PUSH1 0x23 PUSH1 0xB DUP3 DUP3 DUP3 CODECOPY DUP1 MLOAD PUSH1 0x0 BYTE PUSH1 0x73 EQ PUSH1 0x16 JUMPI INVALID JUMPDEST ADDRESS PUSH1 0x0 MSTORE PUSH1 0x73 DUP2 MSTORE8 DUP3 DUP2 RETURN INVALID PUSH20 0x0 ADDRESS EQ PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 0xb1 NUMBER 0x22 0xcd SDIV 0xaa SAR 0xca 0xe6 PUSH9 0x12E472D3AB85CCED78 GT DUP15 0xa7 0xf9 0xa5 MULMOD DUP14 SMOD EXTCODESIZE 0x2a 0xcc 0xc4 MSIZE PUSH5 0x736F6C6343 STOP SDIV EXP STOP ORIGIN ",
|
||||
"sourceMap": "606:385:1:-;;132:2:-1;166:7;155:9;146:7;137:37;255:7;249:14;246:1;241:23;235:4;232:33;222:2;;269:9;222:2;293:9;290:1;283:20;323:4;314:7;306:22;347:7;338;331:24"
|
||||
},
|
||||
"deployedBytecode": {
|
||||
"linkReferences": {},
|
||||
"object": "0x73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72305820a278ce8d53a26107b2f2ba78687fa040ee9ab2ecf0e44ebff0f9410c586e0c6d64736f6c634300050a0032",
|
||||
"opcodes": "PUSH20 0x0 ADDRESS EQ PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 LOG2 PUSH25 0xCE8D53A26107B2F2BA78687FA040EE9AB2ECF0E44EBFF0F941 0xc PC PUSH15 0xC6D64736F6C634300050A00320000 ",
|
||||
"object": "0x73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72305820b14322cd05aa1dcae66812e472d3ab85cced78118ea7f9a5098d073b2accc45964736f6c634300050a0032",
|
||||
"opcodes": "PUSH20 0x0 ADDRESS EQ PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 DUP1 REVERT INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 0xb1 NUMBER 0x22 0xcd SDIV 0xaa SAR 0xca 0xe6 PUSH9 0x12E472D3AB85CCED78 GT DUP15 0xa7 0xf9 0xa5 MULMOD DUP14 SMOD EXTCODESIZE 0x2a 0xcc 0xc4 MSIZE PUSH5 0x736F6C6343 STOP SDIV EXP STOP ORIGIN ",
|
||||
"sourceMap": "606:385:1:-;;;;;;;;"
|
||||
}
|
||||
}
|
||||
@@ -48,7 +51,8 @@
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
"evm.deployedBytecode.sourceMap"
|
||||
"evm.deployedBytecode.sourceMap",
|
||||
"devdoc"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@@ -42,17 +42,20 @@
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
"devdoc": {
|
||||
"methods": {}
|
||||
},
|
||||
"evm": {
|
||||
"bytecode": {
|
||||
"linkReferences": {},
|
||||
"object": "0x608060405234801561001057600080fd5b5060d78061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806322935e921460375780632b82fdf0146063575b600080fd5b605160048036036020811015604b57600080fd5b5035607d565b60408051918252519081900360200190f35b605160048036036020811015607757600080fd5b5035608c565b60006086826095565b92915050565b6000608682609c565b6104d20190565b6001019056fea265627a7a72305820c97345939b2d163165dee7bdfbbd7ca281c5bdaea7b03de53b0ceb32b097cdf864736f6c634300050a0032",
|
||||
"opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xD7 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x32 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x22935E92 EQ PUSH1 0x37 JUMPI DUP1 PUSH4 0x2B82FDF0 EQ PUSH1 0x63 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x4B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x7D JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x77 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x8C JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x95 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x9C JUMP JUMPDEST PUSH2 0x4D2 ADD SWAP1 JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 0xc9 PUSH20 0x45939B2D163165DEE7BDFBBD7CA281C5BDAEA7B0 RETURNDATASIZE 0xe5 EXTCODESIZE 0xc 0xeb ORIGIN 0xb0 SWAP8 0xcd 0xf8 PUSH5 0x736F6C6343 STOP SDIV EXP STOP ORIGIN ",
|
||||
"object": "0x608060405234801561001057600080fd5b5060d78061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c806322935e921460375780632b82fdf0146063575b600080fd5b605160048036036020811015604b57600080fd5b5035607d565b60408051918252519081900360200190f35b605160048036036020811015607757600080fd5b5035608c565b60006086826095565b92915050565b6000608682609c565b6104d20190565b6001019056fea265627a7a72305820ddb720d14b34694daaefebcbd729af6ae04fa2232481812dd8fde63d6a4c32c164736f6c634300050a0032",
|
||||
"opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xD7 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x32 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x22935E92 EQ PUSH1 0x37 JUMPI DUP1 PUSH4 0x2B82FDF0 EQ PUSH1 0x63 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x4B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x7D JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x77 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x8C JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x95 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x9C JUMP JUMPDEST PUSH2 0x4D2 ADD SWAP1 JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 0xdd 0xb7 KECCAK256 0xd1 0x4b CALLVALUE PUSH10 0x4DAAEFEBCBD729AF6AE0 0x4f LOG2 0x23 0x24 DUP2 DUP2 0x2d 0xd8 REVERT 0xe6 RETURNDATASIZE PUSH11 0x4C32C164736F6C63430005 EXP STOP ORIGIN ",
|
||||
"sourceMap": "632:346:2:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;632:346:2;;;;;;;"
|
||||
},
|
||||
"deployedBytecode": {
|
||||
"linkReferences": {},
|
||||
"object": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c806322935e921460375780632b82fdf0146063575b600080fd5b605160048036036020811015604b57600080fd5b5035607d565b60408051918252519081900360200190f35b605160048036036020811015607757600080fd5b5035608c565b60006086826095565b92915050565b6000608682609c565b6104d20190565b6001019056fea265627a7a72305820c97345939b2d163165dee7bdfbbd7ca281c5bdaea7b03de53b0ceb32b097cdf864736f6c634300050a0032",
|
||||
"opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x32 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x22935E92 EQ PUSH1 0x37 JUMPI DUP1 PUSH4 0x2B82FDF0 EQ PUSH1 0x63 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x4B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x7D JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x77 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x8C JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x95 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x9C JUMP JUMPDEST PUSH2 0x4D2 ADD SWAP1 JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 0xc9 PUSH20 0x45939B2D163165DEE7BDFBBD7CA281C5BDAEA7B0 RETURNDATASIZE 0xe5 EXTCODESIZE 0xc 0xeb ORIGIN 0xb0 SWAP8 0xcd 0xf8 PUSH5 0x736F6C6343 STOP SDIV EXP STOP ORIGIN ",
|
||||
"object": "0x6080604052348015600f57600080fd5b506004361060325760003560e01c806322935e921460375780632b82fdf0146063575b600080fd5b605160048036036020811015604b57600080fd5b5035607d565b60408051918252519081900360200190f35b605160048036036020811015607757600080fd5b5035608c565b60006086826095565b92915050565b6000608682609c565b6104d20190565b6001019056fea265627a7a72305820ddb720d14b34694daaefebcbd729af6ae04fa2232481812dd8fde63d6a4c32c164736f6c634300050a0032",
|
||||
"opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x32 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x22935E92 EQ PUSH1 0x37 JUMPI DUP1 PUSH4 0x2B82FDF0 EQ PUSH1 0x63 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x4B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x7D JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH1 0x51 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x77 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH1 0x8C JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x95 JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x86 DUP3 PUSH1 0x9C JUMP JUMPDEST PUSH2 0x4D2 ADD SWAP1 JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP INVALID LOG2 PUSH6 0x627A7A723058 KECCAK256 0xdd 0xb7 KECCAK256 0xd1 0x4b CALLVALUE PUSH10 0x4DAAEFEBCBD729AF6AE0 0x4f LOG2 0x23 0x24 DUP2 DUP2 0x2d 0xd8 REVERT 0xe6 RETURNDATASIZE PUSH11 0x4C32C164736F6C63430005 EXP STOP ORIGIN ",
|
||||
"sourceMap": "632:346:2:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;632:346:2;;;;;;;;;;;;;;;;;;;;;;;;833:143;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;833:143:2;;:::i;:::-;;;;;;;;;;;;;;;;694:133;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;694:133:2;;:::i;833:143::-;917:14;954:15;:1;:13;:15::i;:::-;947:22;833:143;-1:-1:-1;;833:143:2:o;694:133::-;773:14;810:10;:1;:8;:10::i;842:147:1:-;704:4;965:17;;842:147::o;715:121::-;828:1;824:5;;715:121::o"
|
||||
}
|
||||
}
|
||||
@@ -91,7 +94,8 @@
|
||||
"evm.bytecode.object",
|
||||
"evm.bytecode.sourceMap",
|
||||
"evm.deployedBytecode.object",
|
||||
"evm.deployedBytecode.sourceMap"
|
||||
"evm.deployedBytecode.sourceMap",
|
||||
"devdoc"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@@ -16,6 +16,8 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
pragma solidity ^0.5.5;
|
||||
|
||||
|
||||
@@ -98,4 +100,36 @@ contract AbiGenDummy
|
||||
return x;
|
||||
}
|
||||
|
||||
event AnEvent(uint8 param);
|
||||
|
||||
function acceptsBytes(bytes memory a) public pure {}
|
||||
|
||||
/// @dev a method that accepts an array of bytes
|
||||
/// @param a the array of bytes being accepted
|
||||
function acceptsAnArrayOfBytes(bytes[] memory a) public pure {}
|
||||
|
||||
struct Struct {
|
||||
bytes someBytes;
|
||||
uint32 anInteger;
|
||||
bytes[] aDynamicArrayOfBytes;
|
||||
string aString;
|
||||
}
|
||||
|
||||
function structInput(Struct memory s) public pure {}
|
||||
|
||||
/// @dev a method that returns a struct
|
||||
/// @return a Struct struct
|
||||
function structOutput() public pure returns(Struct memory s) {}
|
||||
|
||||
struct NestedStruct {
|
||||
Struct innerStruct;
|
||||
string description;
|
||||
}
|
||||
|
||||
function nestedStructInput(NestedStruct memory n) public pure {}
|
||||
function nestedStructOutput() public pure returns(NestedStruct memory) {}
|
||||
|
||||
uint someState;
|
||||
function nonPureMethod() public returns(uint) { return someState += 1; }
|
||||
function nonPureMethodThatReturnsNothing() public { someState += 1; }
|
||||
}
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "9.1.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "re-export new ethereum-types type, TupleDataItem",
|
||||
"pr": 1919
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563193019,
|
||||
"version": "9.1.7",
|
||||
|
@@ -105,6 +105,7 @@ export {
|
||||
ConstructorAbi,
|
||||
FallbackAbi,
|
||||
DataItem,
|
||||
TupleDataItem,
|
||||
ConstructorStateMutability,
|
||||
StateMutability,
|
||||
Web3JsProvider,
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "2.1.4",
|
||||
"changes": [
|
||||
{
|
||||
"note": "new interface TupleDataItem, a DataItem that definitely has a `components` field",
|
||||
"pr": 1919
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.1.3",
|
||||
"changes": [
|
||||
|
@@ -131,6 +131,10 @@ export interface DataItem {
|
||||
components?: DataItem[];
|
||||
}
|
||||
|
||||
export interface TupleDataItem extends DataItem {
|
||||
components: DataItem[];
|
||||
}
|
||||
|
||||
export enum OpCode {
|
||||
// 0s: Stop and Arithmetic Operations
|
||||
Stop = 'STOP',
|
||||
|
@@ -1,4 +1,12 @@
|
||||
[
|
||||
{
|
||||
"version": "3.1.11",
|
||||
"changes": [
|
||||
{
|
||||
"note": "permit mixed-case addresses"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563006338,
|
||||
"version": "3.0.11",
|
||||
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"id": "/addressSchema",
|
||||
"type": "string",
|
||||
"pattern": "^0x[0-9a-f]{40}$"
|
||||
"pattern": "^0x[0-9a-fA-F]{40}$"
|
||||
}
|
||||
|
@@ -91,13 +91,7 @@ describe('Schema', () => {
|
||||
validateAgainstSchema(testCases, addressSchema);
|
||||
});
|
||||
it('should fail for invalid addresses', () => {
|
||||
const testCases = [
|
||||
'0x',
|
||||
'0',
|
||||
'0x00',
|
||||
'0xzzzzzzB11a196601eD2ce54B665CaFEca0347D42',
|
||||
'0x8b0292B11a196601eD2ce54B665CaFEca0347D42',
|
||||
];
|
||||
const testCases = ['0x', '0', '0x00', '0xzzzzzzB11a196601eD2ce54B665CaFEca0347D42'];
|
||||
const shouldFail = true;
|
||||
validateAgainstSchema(testCases, addressSchema, shouldFail);
|
||||
});
|
||||
@@ -730,7 +724,7 @@ describe('Schema', () => {
|
||||
validateAgainstSchema(testCases, relayerApiOrdersChannelSubscribeSchema);
|
||||
});
|
||||
it('should fail for invalid orders channel websocket subscribe message', () => {
|
||||
const checksummedAddress = '0xA2b31daCf30a9C50ca473337c01d8A201ae33e32';
|
||||
const bogusAddress = '0xz2b31daCf30a9C50ca473337c01d8A201ae33e32';
|
||||
const testCases = [
|
||||
{
|
||||
type: 'subscribe',
|
||||
@@ -743,7 +737,7 @@ describe('Schema', () => {
|
||||
payload: {
|
||||
makerAssetProxyId: '0x02571792',
|
||||
takerAssetProxyId: '0xf47261b0',
|
||||
makerAssetAddress: checksummedAddress,
|
||||
makerAssetAddress: bogusAddress,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@@ -5,6 +5,10 @@
|
||||
{
|
||||
"note": "Initial commit. Functionality tested for ERC20Token wrapper",
|
||||
"pr": 1878
|
||||
},
|
||||
{
|
||||
"note": "Include the Exchange contract in the list of generation targets",
|
||||
"pr": 1919
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@
|
||||
"clean": "shx rm -rf generated"
|
||||
},
|
||||
"config": {
|
||||
"abis": "../contract-artifacts/artifacts/ERC20Token.json"
|
||||
"abis": "../contract-artifacts/artifacts/{Exchange,ERC20Token}.json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "3.1.10",
|
||||
"changes": [
|
||||
{
|
||||
"note": "re-export new ethereum-types types, TupleDataItem",
|
||||
"pr": 1919
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563006338,
|
||||
"version": "3.1.9",
|
||||
|
@@ -4,6 +4,7 @@ export {
|
||||
CompilerOptions,
|
||||
CompilerSettings,
|
||||
DataItem,
|
||||
TupleDataItem,
|
||||
DevdocOutput,
|
||||
ErrorSeverity,
|
||||
ErrorType,
|
||||
|
@@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "6.0.8",
|
||||
"changes": [
|
||||
{
|
||||
"note": "re-export new ethereum-types types, TupleDataItem",
|
||||
"pr": 1919
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1563006338,
|
||||
"version": "6.0.7",
|
||||
|
@@ -43,6 +43,7 @@ export {
|
||||
ConstructorAbi,
|
||||
FallbackAbi,
|
||||
DataItem,
|
||||
TupleDataItem,
|
||||
ConstructorStateMutability,
|
||||
StateMutability,
|
||||
Web3JsProvider,
|
||||
|
3
python-packages/build_docs
Executable file
3
python-packages/build_docs
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
./parallel ./setup.py build_sphinx
|
@@ -186,6 +186,7 @@ setup(
|
||||
"build_sphinx": {
|
||||
"source_dir": ("setup.py", "src"),
|
||||
"build_dir": ("setup.py", "build/docs"),
|
||||
"warning_is_error": ("setup.py", "true"),
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@@ -60,15 +60,6 @@ class LintCommand(distutils.command.build_py.build_py):
|
||||
"mypy src setup.py".split(),
|
||||
# security issue checker:
|
||||
"bandit -r src ./setup.py".split(),
|
||||
# HACK: ensure contract artifacts match the authoritative copies:
|
||||
# this is a hack. ideally we would symlink to the authoritative
|
||||
# copies, but a problem with setuptools is preventing it from
|
||||
# following symlinks when gathering package_data. see
|
||||
# https://github.com/pypa/setuptools/issues/415.
|
||||
(
|
||||
"diff src/zero_ex/contract_artifacts/artifacts"
|
||||
+ " ../../packages/contract-artifacts/artifacts"
|
||||
).split(),
|
||||
# general linter:
|
||||
"pylint src setup.py".split(),
|
||||
# pylint takes relatively long to run, so it runs last, to enable
|
||||
@@ -225,6 +216,7 @@ setup(
|
||||
"build_sphinx": {
|
||||
"source_dir": ("setup.py", "src"),
|
||||
"build_dir": ("setup.py", "build/docs"),
|
||||
"warning_is_error": ("setup.py", "true"),
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@@ -1,6 +1,3 @@
|
||||
[MESSAGES CONTROL]
|
||||
disable=C0330,line-too-long,fixme,too-few-public-methods,too-many-ancestors
|
||||
disable=C0330,line-too-long,fixme,too-few-public-methods,too-many-ancestors,duplicate-code
|
||||
# C0330 is "bad hanging indent". we use indents per `black`.
|
||||
|
||||
[SIMILARITIES]
|
||||
min-similarity-lines=12
|
||||
|
@@ -1,5 +1,9 @@
|
||||
# Changelog
|
||||
|
||||
## 2.0.0 - TBD
|
||||
|
||||
- Completely new implementation of the Exchange wrapper, virtually all auto-generated from the Solidity contract. Breaking changes include method parameter name changes and accepting of signatures as bytes.
|
||||
|
||||
## 1.0.0 - 2019-04-30
|
||||
|
||||
- Initial release.
|
||||
|
@@ -4,7 +4,7 @@
|
||||
|
||||
import subprocess # nosec
|
||||
from shutil import copy, rmtree
|
||||
from os import environ, path
|
||||
from os import environ, path, remove
|
||||
from pathlib import Path
|
||||
from sys import argv
|
||||
from importlib.util import find_spec
|
||||
@@ -34,17 +34,37 @@ class PreInstallCommand(distutils.command.build_py.build_py):
|
||||
"packages",
|
||||
"python-contract-wrappers",
|
||||
"generated",
|
||||
"erc20_token.py",
|
||||
"erc20_token",
|
||||
"__init__.py",
|
||||
),
|
||||
path.join(
|
||||
pkgdir, "src", "zero_ex", "contract_wrappers", "erc20_token"
|
||||
),
|
||||
)
|
||||
copy(
|
||||
path.join(
|
||||
pkgdir,
|
||||
"..",
|
||||
"..",
|
||||
"packages",
|
||||
"python-contract-wrappers",
|
||||
"generated",
|
||||
"exchange",
|
||||
"__init__.py",
|
||||
),
|
||||
path.join(
|
||||
pkgdir, "src", "zero_ex", "contract_wrappers", "exchange"
|
||||
),
|
||||
path.join(pkgdir, "src", "zero_ex", "contract_wrappers"),
|
||||
)
|
||||
if find_spec("black") is None:
|
||||
subprocess.check_call("pip install black".split()) # nosec
|
||||
subprocess.check_call( # nosec
|
||||
(
|
||||
BLACK_COMMAND + " src/zero_ex/contract_wrappers/erc20_token.py"
|
||||
).split()
|
||||
black_command = (
|
||||
BLACK_COMMAND
|
||||
+ " src/zero_ex/contract_wrappers/erc20_token/__init__.py"
|
||||
+ " src/zero_ex/contract_wrappers/exchange/__init__.py"
|
||||
)
|
||||
print(f"Running command `{black_command}`...")
|
||||
subprocess.check_call(black_command.split()) # nosec
|
||||
|
||||
|
||||
class TestCommandExtension(TestCommand):
|
||||
@@ -112,6 +132,9 @@ class CleanCommandExtension(clean):
|
||||
rmtree(".tox", ignore_errors=True)
|
||||
rmtree(".pytest_cache", ignore_errors=True)
|
||||
rmtree("src/0x_contract_wrappers.egg-info", ignore_errors=True)
|
||||
# generated files:
|
||||
remove("src/zero_ex/contract_wrappers/exchange/__init__.py")
|
||||
remove("src/zero_ex/contract_wrappers/erc20_token/__init__.py")
|
||||
|
||||
|
||||
class TestPublishCommand(distutils.command.build_py.build_py):
|
||||
@@ -255,6 +278,7 @@ setup(
|
||||
"build_sphinx": {
|
||||
"source_dir": ("setup.py", "src"),
|
||||
"build_dir": ("setup.py", "build/docs"),
|
||||
"warning_is_error": ("setup.py", "true"),
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@@ -31,6 +31,38 @@ zero_ex.contract_wrappers.TxParams
|
||||
.. autoclass:: zero_ex.contract_wrappers.TxParams
|
||||
:members:
|
||||
|
||||
zero_ex.contract_wrappers.exchange.types
|
||||
========================================
|
||||
|
||||
.. automodule:: zero_ex.contract_wrappers.exchange.types
|
||||
|
||||
.. autoclass:: zero_ex.contract_wrappers.exchange.types.Order
|
||||
|
||||
.. autoclass:: zero_ex.contract_wrappers.exchange.types.OrderInfo
|
||||
|
||||
.. autoclass:: zero_ex.contract_wrappers.exchange.types.FillResults
|
||||
|
||||
.. autoclass:: zero_ex.contract_wrappers.exchange.types.MatchedFillResults
|
||||
|
||||
zero_ex.contract_wrappers.exchange: Generated Tuples
|
||||
====================================================
|
||||
|
||||
.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0x260219a2
|
||||
|
||||
This is the generated class representing `the Order struct <https://0x.org/docs/contracts#structs-Order>`_.
|
||||
|
||||
.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0xbb41e5b3
|
||||
|
||||
This is the generated class representing `the FillResults struct <https://0x.org/docs/contracts#structs-FillResults>`_.
|
||||
|
||||
.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0x054ca44e
|
||||
|
||||
This is the generated class representing `the MatchedFillResults struct <https://0x.org/docs/contracts#structs-MatchedFillResults>`_.
|
||||
|
||||
.. autoclass:: zero_ex.contract_wrappers.exchange.Tuple0xb1e4a1ae
|
||||
|
||||
This is the generated class representing `the OrderInfo struct <https://0x.org/docs/contracts#structs-OrderInfo>`_.
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
|
@@ -91,24 +91,24 @@ we need to tell the WETH token contract to let the 0x contracts transfer our
|
||||
balance:
|
||||
|
||||
>>> from zero_ex.contract_wrappers import ERC20Token
|
||||
>>> zrx_wrapper = ERC20Token(
|
||||
>>> zrx_token = ERC20Token(
|
||||
... provider=ganache,
|
||||
... contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].zrx_token,
|
||||
... )
|
||||
>>> weth_wrapper = ERC20Token(
|
||||
>>> weth_token = ERC20Token(
|
||||
... provider=ganache,
|
||||
... contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].ether_token,
|
||||
... )
|
||||
|
||||
>>> erc20_proxy_addr = NETWORK_TO_ADDRESSES[NetworkId.GANACHE].erc20_proxy
|
||||
|
||||
>>> tx = zrx_wrapper.approve(
|
||||
>>> tx = zrx_token.approve(
|
||||
... erc20_proxy_addr,
|
||||
... to_wei(100, 'ether'),
|
||||
... tx_params=TxParams(from_=maker_address),
|
||||
... )
|
||||
|
||||
>>> tx = weth_wrapper.approve(
|
||||
>>> tx = weth_token.approve(
|
||||
... erc20_proxy_addr,
|
||||
... to_wei(100, 'ether'),
|
||||
... tx_params=TxParams(from_=taker_address),
|
||||
@@ -117,8 +117,8 @@ balance:
|
||||
Constructing an order
|
||||
---------------------
|
||||
|
||||
>>> from zero_ex.order_utils import asset_data_utils, Order
|
||||
>>> from eth_utils import remove_0x_prefix
|
||||
>>> from zero_ex.contract_wrappers.exchange.types import Order
|
||||
>>> from zero_ex.order_utils import asset_data_utils
|
||||
>>> from datetime import datetime, timedelta
|
||||
>>> import random
|
||||
>>> order = Order(
|
||||
@@ -143,8 +143,8 @@ For this order to be valid, our Maker must sign a hash of it:
|
||||
>>> from zero_ex.order_utils import generate_order_hash_hex
|
||||
>>> order_hash_hex = generate_order_hash_hex(order, exchange_address)
|
||||
|
||||
>>> from zero_ex.order_utils import sign_hash
|
||||
>>> maker_signature = sign_hash(
|
||||
>>> from zero_ex.order_utils import sign_hash_to_bytes
|
||||
>>> maker_signature = sign_hash_to_bytes(
|
||||
... ganache, Web3.toChecksumAddress(maker_address), order_hash_hex
|
||||
... )
|
||||
|
||||
@@ -162,13 +162,13 @@ fill. This example fills the order completely, but partial fills are possible
|
||||
too.
|
||||
|
||||
>>> from zero_ex.contract_wrappers import Exchange
|
||||
>>> exchange_contract = Exchange(
|
||||
>>> exchange = Exchange(
|
||||
... provider=ganache,
|
||||
... contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].exchange,
|
||||
... )
|
||||
>>> tx_hash = exchange_contract.fill_order(
|
||||
>>> tx_hash = exchange.fill_order(
|
||||
... order=order,
|
||||
... taker_amount=order["takerAssetAmount"],
|
||||
... taker_asset_fill_amount=order["takerAssetAmount"],
|
||||
... signature=maker_signature,
|
||||
... tx_params=TxParams(from_=taker_address)
|
||||
... )
|
||||
@@ -176,10 +176,10 @@ too.
|
||||
Once the transaction is mined, we can get the details of our exchange through
|
||||
the exchange wrapper:
|
||||
|
||||
>>> exchange_contract.get_fill_event(tx_hash)
|
||||
>>> exchange.get_fill_event(tx_hash)
|
||||
(AttributeDict({'args': ...({'makerAddress': ...}), 'event': 'Fill', ...}),)
|
||||
>>> from pprint import pprint
|
||||
>>> pprint(exchange_contract.get_fill_event(tx_hash)[0].args.__dict__)
|
||||
>>> pprint(exchange.get_fill_event(tx_hash)[0].args.__dict__)
|
||||
{'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
|
||||
'makerAddress': '0x...',
|
||||
'makerAssetData': b...,
|
||||
@@ -191,7 +191,7 @@ the exchange wrapper:
|
||||
'takerAssetData': b...,
|
||||
'takerAssetFilledAmount': 100000000000000000,
|
||||
'takerFeePaid': 0}
|
||||
>>> exchange_contract.get_fill_event(tx_hash)[0].args.takerAssetFilledAmount
|
||||
>>> exchange.get_fill_event(tx_hash)[0].args.takerAssetFilledAmount
|
||||
100000000000000000
|
||||
|
||||
Cancelling an order
|
||||
@@ -217,23 +217,23 @@ A Maker can cancel an order that has yet to be filled.
|
||||
... )
|
||||
... )
|
||||
|
||||
>>> tx_hash = exchange_contract.cancel_order(
|
||||
>>> tx_hash = exchange.cancel_order(
|
||||
... order=order, tx_params=TxParams(from_=maker_address)
|
||||
... )
|
||||
|
||||
Once the transaction is mined, we can get the details of the cancellation
|
||||
through the Exchange wrapper:
|
||||
|
||||
>>> exchange_contract.get_cancel_event(tx_hash)
|
||||
>>> exchange.get_cancel_event(tx_hash)
|
||||
(AttributeDict({'args': ...({'makerAddress': ...}), 'event': 'Cancel', ...}),)
|
||||
>>> pprint(exchange_contract.get_cancel_event(tx_hash)[0].args.__dict__)
|
||||
>>> pprint(exchange.get_cancel_event(tx_hash)[0].args.__dict__)
|
||||
{'feeRecipientAddress': '0x0000000000000000000000000000000000000000',
|
||||
'makerAddress': '0x...',
|
||||
'makerAssetData': b...,
|
||||
'orderHash': b...,
|
||||
'senderAddress': '0x...',
|
||||
'takerAssetData': b...}
|
||||
>>> exchange_contract.get_cancel_event(tx_hash)[0].args.feeRecipientAddress
|
||||
>>> exchange.get_cancel_event(tx_hash)[0].args.feeRecipientAddress
|
||||
'0x0000000000000000000000000000000000000000'
|
||||
|
||||
Batching orders
|
||||
@@ -258,10 +258,10 @@ is an example where the taker fills two orders in one transaction:
|
||||
... (datetime.utcnow() + timedelta(days=1)).timestamp()
|
||||
... )
|
||||
... )
|
||||
>>> signature_1 = sign_hash(
|
||||
>>> signature_1 = sign_hash_to_bytes(
|
||||
... ganache,
|
||||
... Web3.toChecksumAddress(maker_address),
|
||||
... generate_order_hash_hex(order_1, exchange_contract.address)
|
||||
... generate_order_hash_hex(order_1, exchange.contract_address)
|
||||
... )
|
||||
>>> order_2 = Order(
|
||||
... makerAddress=maker_address,
|
||||
@@ -279,17 +279,17 @@ is an example where the taker fills two orders in one transaction:
|
||||
... (datetime.utcnow() + timedelta(days=1)).timestamp()
|
||||
... )
|
||||
... )
|
||||
>>> signature_2 = sign_hash(
|
||||
>>> signature_2 = sign_hash_to_bytes(
|
||||
... ganache,
|
||||
... Web3.toChecksumAddress(maker_address),
|
||||
... generate_order_hash_hex(order_2, exchange_contract.address)
|
||||
... generate_order_hash_hex(order_2, exchange.contract_address)
|
||||
... )
|
||||
|
||||
Fill order_1 and order_2 together:
|
||||
|
||||
>>> exchange_contract.batch_fill_orders(
|
||||
>>> exchange.batch_fill_orders(
|
||||
... orders=[order_1, order_2],
|
||||
... taker_amounts=[1, 2],
|
||||
... taker_asset_fill_amounts=[1, 2],
|
||||
... signatures=[signature_1, signature_2],
|
||||
... tx_params=TxParams(from_=taker_address))
|
||||
HexBytes('0x...')
|
||||
@@ -297,4 +297,4 @@ HexBytes('0x...')
|
||||
|
||||
from .tx_params import TxParams
|
||||
from .erc20_token import ERC20Token
|
||||
from .exchange_wrapper import Exchange
|
||||
from .exchange import Exchange
|
||||
|
@@ -34,7 +34,7 @@ class BaseContractWrapper:
|
||||
self._private_key = private_key
|
||||
self._web3 = Web3(provider)
|
||||
self._web3_eth = self._web3.eth # pylint: disable=no-member
|
||||
self._contract_address = self._validate_and_checksum_address(
|
||||
self.contract_address = self._validate_and_checksum_address(
|
||||
contract_address
|
||||
)
|
||||
|
||||
@@ -120,7 +120,7 @@ class BaseContractWrapper:
|
||||
:returns: str of transaction hash
|
||||
"""
|
||||
contract_instance = self._contract_instance(
|
||||
address=self._contract_address, abi=abi
|
||||
address=self.contract_address, abi=abi
|
||||
)
|
||||
if args is None:
|
||||
args = []
|
||||
@@ -131,6 +131,6 @@ class BaseContractWrapper:
|
||||
)
|
||||
raise Exception(
|
||||
"No method {} found on contract {}.".format(
|
||||
self._contract_address, method
|
||||
self.contract_address, method
|
||||
)
|
||||
)
|
||||
|
@@ -0,0 +1,200 @@
|
||||
"""Conveniences for handling types representing Exchange Solidity structs.
|
||||
|
||||
The `TypedDict`:code: classes in the .exchange module represent tuples
|
||||
encountered in the Exchange contract's ABI. However, they have weird names,
|
||||
containing hashes of the tuple's field names, because the name of a Solidity
|
||||
`struct`:code: isn't conveyed through the ABI. This module provides type
|
||||
aliases with human-friendly names.
|
||||
|
||||
Converting between the JSON wire format and the types accepted by Web3.py (eg
|
||||
`bytes` vs `str`) can be onerous. This module provides conveniences for
|
||||
converting Exchange structs between JSON and Python objects.
|
||||
"""
|
||||
|
||||
from copy import copy
|
||||
from typing import cast, Dict
|
||||
|
||||
from eth_utils import remove_0x_prefix
|
||||
|
||||
from zero_ex.json_schemas import assert_valid
|
||||
|
||||
from . import (
|
||||
Tuple0xbb41e5b3,
|
||||
Tuple0x260219a2,
|
||||
Tuple0x054ca44e,
|
||||
Tuple0xb1e4a1ae,
|
||||
)
|
||||
|
||||
|
||||
# Would rather not repeat ourselves below, but base classes are mentioned in
|
||||
# the class docstrings because of a bug in sphinx rendering. Using the `..
|
||||
# autoclass` directive, with the `:show-inheritance:` role, results in docs
|
||||
# being rendered with just "Bases: dict", and no mention of the direct ancestor
|
||||
# of each of these classes.
|
||||
|
||||
|
||||
class FillResults(Tuple0xbb41e5b3):
|
||||
"""The `FillResults`:code: Solidity struct.
|
||||
|
||||
Also known as
|
||||
`zero_ex.contract_wrappers.exchange.Tuple0xbb41e5b3`:py:class:.
|
||||
"""
|
||||
|
||||
|
||||
class Order(Tuple0x260219a2):
|
||||
"""The `Order`:code: Solidity struct.
|
||||
|
||||
Also known as
|
||||
`zero_ex.contract_wrappers.exchange.Tuple0x260219a2`:py:class:.
|
||||
"""
|
||||
|
||||
|
||||
class MatchedFillResults(Tuple0x054ca44e):
|
||||
"""The `MatchedFillResults`:code: Solidity struct.
|
||||
|
||||
Also known as
|
||||
`zero_ex.contract_wrappers.exchange.Tuple0x054ca44e`:py:class:.
|
||||
"""
|
||||
|
||||
|
||||
class OrderInfo(Tuple0xb1e4a1ae):
|
||||
"""The `OrderInfo`:code: Solidity struct.
|
||||
|
||||
Also known as
|
||||
`zero_ex.contract_wrappers.exchange.Tuple0xb1e4a1ae`:py:class:.
|
||||
"""
|
||||
|
||||
|
||||
def order_to_jsdict(
|
||||
order: Order,
|
||||
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,
|
||||
... },
|
||||
... ))
|
||||
{'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
|
@@ -0,0 +1,47 @@
|
||||
"""Validate inputs to the Exchange contract."""
|
||||
|
||||
from typing import Any
|
||||
|
||||
from web3.providers.base import BaseProvider
|
||||
|
||||
from zero_ex import json_schemas
|
||||
|
||||
from . import ExchangeValidatorBase
|
||||
from .types import order_to_jsdict
|
||||
|
||||
|
||||
class ExchangeValidator(ExchangeValidatorBase):
|
||||
"""Validate inputs to Exchange methods."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
contract_address: str,
|
||||
private_key: str = None,
|
||||
):
|
||||
"""Initialize the class."""
|
||||
super().__init__(provider, contract_address, private_key)
|
||||
self.contract_address = contract_address
|
||||
|
||||
def assert_valid(
|
||||
self, method_name: str, parameter_name: str, argument_value: Any
|
||||
) -> None:
|
||||
"""Raise an exception if method input is not valid.
|
||||
|
||||
:param method_name: Name of the method whose input is to be validated.
|
||||
:param parameter_name: Name of the parameter whose input is to be
|
||||
validated.
|
||||
:param argument_value: Value of argument to parameter to be validated.
|
||||
"""
|
||||
if parameter_name == "order":
|
||||
json_schemas.assert_valid(
|
||||
order_to_jsdict(argument_value, self.contract_address),
|
||||
"/orderSchema",
|
||||
)
|
||||
|
||||
if parameter_name == "orders":
|
||||
for order in argument_value:
|
||||
json_schemas.assert_valid(
|
||||
order_to_jsdict(order, self.contract_address),
|
||||
"/orderSchema",
|
||||
)
|
@@ -1,327 +0,0 @@
|
||||
"""Wrapper for 0x Exchange smart contract."""
|
||||
|
||||
from typing import List, Optional, Tuple, Union
|
||||
from itertools import repeat
|
||||
|
||||
from eth_utils import remove_0x_prefix
|
||||
from hexbytes import HexBytes
|
||||
from web3.providers.base import BaseProvider
|
||||
from web3.datastructures import AttributeDict
|
||||
|
||||
from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId
|
||||
from zero_ex.contract_artifacts import abi_by_name
|
||||
from zero_ex.json_schemas import assert_valid
|
||||
from zero_ex.order_utils import (
|
||||
Order,
|
||||
generate_order_hash_hex,
|
||||
is_valid_signature,
|
||||
order_to_jsdict,
|
||||
)
|
||||
|
||||
from ._base_contract_wrapper import BaseContractWrapper
|
||||
from .tx_params import TxParams
|
||||
|
||||
|
||||
class CancelDisallowedError(Exception):
|
||||
"""Exception for when Cancel is not allowed."""
|
||||
|
||||
|
||||
class Exchange(BaseContractWrapper):
|
||||
"""Wrapper class for 0x Exchange smart contract."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
contract_address: str,
|
||||
private_key: str = None,
|
||||
):
|
||||
"""Get an instance of the 0x Exchange smart contract wrapper.
|
||||
|
||||
:param provider: instance of :class:`web3.providers.base.BaseProvider`
|
||||
:param private_key: str of private_key
|
||||
"""
|
||||
super(Exchange, self).__init__(
|
||||
provider=provider,
|
||||
contract_address=contract_address,
|
||||
private_key=private_key,
|
||||
)
|
||||
self._web3_net = self._web3.net # pylint: disable=no-member
|
||||
self.address = NETWORK_TO_ADDRESSES[
|
||||
NetworkId(int(self._web3_net.version))
|
||||
].exchange
|
||||
self._exchange = self._contract_instance(
|
||||
address=self.address, abi=abi_by_name("Exchange")
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def fill_order(
|
||||
self,
|
||||
order: Order,
|
||||
taker_amount: int,
|
||||
signature: str,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
view_only: bool = False,
|
||||
) -> Union[HexBytes, bytes]:
|
||||
"""Fill a signed order with given amount of taker asset.
|
||||
|
||||
This is the most basic way to fill an order. All of the other methods
|
||||
call fillOrder under the hood with additional logic. This function
|
||||
will attempt to fill the amount specified by the caller. However, if
|
||||
the remaining fillable amount is less than the amount specified, the
|
||||
remaining amount will be filled. Partial fills are allowed when
|
||||
filling orders.
|
||||
|
||||
See the specification docs for `fillOrder
|
||||
<https://github.com/0xProject/0x-protocol-specification/blob/master
|
||||
/v2/v2-specification.md#fillorder>`_.
|
||||
|
||||
:param order: instance of :class:`zero_ex.order_utils.Order`
|
||||
:param taker_amount: integer taker amount in Wei (1 Wei is 10e-18 ETH)
|
||||
:param signature: str or hexstr or bytes of order hash signature
|
||||
:param tx_params: default None, :class:`TxParams` transaction params
|
||||
:param view_only: default False, boolean of whether to transact or
|
||||
view only
|
||||
|
||||
:returns: transaction hash
|
||||
"""
|
||||
assert_valid(order_to_jsdict(order, self.address), "/orderSchema")
|
||||
is_valid_signature(
|
||||
self._provider,
|
||||
generate_order_hash_hex(order, self.address),
|
||||
signature,
|
||||
order["makerAddress"],
|
||||
)
|
||||
# safeguard against fractional inputs
|
||||
taker_fill_amount = int(taker_amount)
|
||||
normalized_signature = bytes.fromhex(remove_0x_prefix(signature))
|
||||
func = self._exchange.functions.fillOrder(
|
||||
order, taker_fill_amount, normalized_signature
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func, tx_params=tx_params, view_only=view_only
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def batch_fill_orders(
|
||||
self,
|
||||
orders: List[Order],
|
||||
taker_amounts: List[int],
|
||||
signatures: List[str],
|
||||
tx_params: Optional[TxParams] = None,
|
||||
view_only: bool = False,
|
||||
) -> Union[HexBytes, bytes]:
|
||||
"""Call `fillOrder` sequentially for orders, amounts and signatures.
|
||||
|
||||
:param orders: list of instances of :class:`zero_ex.order_utils.Order`
|
||||
:param taker_amounts: list of integer taker amounts in Wei
|
||||
:param signatures: list of str|hexstr|bytes of order hash signature
|
||||
:param tx_params: default None, :class:`TxParams` transaction params
|
||||
:param view_only: default False, boolean of whether to transact or
|
||||
view only
|
||||
|
||||
:returns: transaction hash
|
||||
"""
|
||||
order_jsdicts = [
|
||||
order_to_jsdict(order, self.address) for order in orders
|
||||
]
|
||||
map(assert_valid, order_jsdicts, repeat("/orderSchema"))
|
||||
# safeguard against fractional inputs
|
||||
normalized_fill_amounts = [
|
||||
int(taker_fill_amount) for taker_fill_amount in taker_amounts
|
||||
]
|
||||
normalized_signatures = [
|
||||
bytes.fromhex(remove_0x_prefix(signature))
|
||||
for signature in signatures
|
||||
]
|
||||
func = self._exchange.functions.batchFillOrders(
|
||||
orders, normalized_fill_amounts, normalized_signatures
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func, tx_params=tx_params, view_only=view_only
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def fill_or_kill_order(
|
||||
self,
|
||||
order: Order,
|
||||
taker_amount: int,
|
||||
signature: str,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
view_only: bool = False,
|
||||
) -> Union[HexBytes, bytes]:
|
||||
"""Attemp to `fillOrder`, revert if fill is not exact amount.
|
||||
|
||||
:param order: instance of :class:`zero_ex.order_utils.Order`
|
||||
:param taker_amount: integer taker amount in Wei (1 Wei is 10e-18 ETH)
|
||||
:param signature: str or hexstr or bytes of order hash signature
|
||||
:param tx_params: default None, :class:`TxParams` transaction params
|
||||
:param view_only: default False, boolean of whether to transact or
|
||||
view only
|
||||
|
||||
:returns: transaction hash
|
||||
"""
|
||||
assert_valid(order_to_jsdict(order, self.address), "/orderSchema")
|
||||
is_valid_signature(
|
||||
self._provider,
|
||||
generate_order_hash_hex(order, self.address),
|
||||
signature,
|
||||
order["makerAddress"],
|
||||
)
|
||||
# safeguard against fractional inputs
|
||||
taker_fill_amount = int(taker_amount)
|
||||
normalized_signature = bytes.fromhex(remove_0x_prefix(signature))
|
||||
func = self._exchange.functions.fillOrKillOrder(
|
||||
order, taker_fill_amount, normalized_signature
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func, tx_params=tx_params, view_only=view_only
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def batch_fill_or_kill_orders(
|
||||
self,
|
||||
orders: List[Order],
|
||||
taker_amounts: List[int],
|
||||
signatures: List[str],
|
||||
tx_params: Optional[TxParams] = None,
|
||||
view_only: bool = False,
|
||||
) -> Union[HexBytes, bytes]:
|
||||
"""Call `fillOrKillOrder` sequentially for orders.
|
||||
|
||||
:param orders: list of instances of :class:`zero_ex.order_utils.Order`
|
||||
:param taker_amounts: list of integer taker amounts in Wei
|
||||
:param signatures: list of str|hexstr|bytes of order hash signature
|
||||
:param tx_params: default None, :class:`TxParams` transaction params
|
||||
:param view_only: default False, boolean of whether to transact or
|
||||
view only
|
||||
|
||||
:returns: transaction hash
|
||||
"""
|
||||
order_jsdicts = [
|
||||
order_to_jsdict(order, self.address) for order in orders
|
||||
]
|
||||
map(assert_valid, order_jsdicts, repeat("/orderSchema"))
|
||||
# safeguard against fractional inputs
|
||||
normalized_fill_amounts = [
|
||||
int(taker_fill_amount) for taker_fill_amount in taker_amounts
|
||||
]
|
||||
normalized_signatures = [
|
||||
bytes.fromhex(remove_0x_prefix(signature))
|
||||
for signature in signatures
|
||||
]
|
||||
func = self._exchange.functions.batchFillOrKillOrders(
|
||||
orders, normalized_fill_amounts, normalized_signatures
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func, tx_params=tx_params, view_only=view_only
|
||||
)
|
||||
|
||||
def cancel_order(
|
||||
self,
|
||||
order: Order,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
view_only: bool = False,
|
||||
) -> Union[HexBytes, bytes]:
|
||||
"""Cancel an order.
|
||||
|
||||
See the specification docs for `cancelOrder
|
||||
<https://github.com/0xProject/0x-protocol-specification/blob/master
|
||||
/v2/v2-specification.md#cancelorder>`_.
|
||||
|
||||
:param order: instance of :class:`zero_ex.order_utils.Order`
|
||||
:param tx_params: default None, :class:`TxParams` transaction params
|
||||
:param view_only: default False, boolean of whether to transact or
|
||||
view only
|
||||
|
||||
:returns: transaction hash
|
||||
"""
|
||||
assert_valid(order_to_jsdict(order, self.address), "/orderSchema")
|
||||
maker_address = self._validate_and_checksum_address(
|
||||
order["makerAddress"]
|
||||
)
|
||||
|
||||
if tx_params and tx_params.from_:
|
||||
self._raise_if_maker_not_canceller(
|
||||
maker_address,
|
||||
self._validate_and_checksum_address(tx_params.from_),
|
||||
)
|
||||
elif self._web3_eth.defaultAccount:
|
||||
self._raise_if_maker_not_canceller(
|
||||
maker_address, self._web3_eth.defaultAccount
|
||||
)
|
||||
func = self._exchange.functions.cancelOrder(order)
|
||||
return self._invoke_function_call(
|
||||
func=func, tx_params=tx_params, view_only=view_only
|
||||
)
|
||||
|
||||
def batch_cancel_orders(
|
||||
self,
|
||||
orders: List[Order],
|
||||
tx_params: Optional[TxParams] = None,
|
||||
view_only: bool = False,
|
||||
) -> Union[HexBytes, bytes]:
|
||||
"""Call `cancelOrder` sequentially for provided orders.
|
||||
|
||||
:param orders: list of instance of :class:`zero_ex.order_utils.Order`
|
||||
:param tx_params: default None, :class:`TxParams` transaction params
|
||||
:param view_only: default False, boolean of whether to transact or
|
||||
view only
|
||||
|
||||
:returns: transaction hash
|
||||
"""
|
||||
order_jsdicts = [
|
||||
order_to_jsdict(order, self.address) for order in orders
|
||||
]
|
||||
map(assert_valid, order_jsdicts, repeat("/orderSchema"))
|
||||
maker_addresses = [
|
||||
self._validate_and_checksum_address(order["makerAddress"])
|
||||
for order in orders
|
||||
]
|
||||
if tx_params and tx_params.from_:
|
||||
map(
|
||||
self._raise_if_maker_not_canceller,
|
||||
maker_addresses,
|
||||
repeat(tx_params.from_),
|
||||
)
|
||||
elif self._web3_eth.defaultAccount:
|
||||
map(
|
||||
self._raise_if_maker_not_canceller,
|
||||
maker_addresses,
|
||||
repeat(self._web3_eth.defaultAccount),
|
||||
)
|
||||
func = self._exchange.functions.batchCancelOrders(orders)
|
||||
return self._invoke_function_call(
|
||||
func=func, tx_params=tx_params, view_only=view_only
|
||||
)
|
||||
|
||||
def get_fill_event(
|
||||
self, tx_hash: Union[HexBytes, bytes]
|
||||
) -> Tuple[AttributeDict]:
|
||||
"""Get fill event for a fill transaction.
|
||||
|
||||
:param tx_hash: `HexBytes` hash of fill transaction
|
||||
|
||||
:returns: fill event
|
||||
"""
|
||||
tx_receipt = self._web3_eth.getTransactionReceipt(tx_hash)
|
||||
return self._exchange.events.Fill().processReceipt(tx_receipt)
|
||||
|
||||
def get_cancel_event(
|
||||
self, tx_hash: Union[HexBytes, bytes]
|
||||
) -> Tuple[AttributeDict]:
|
||||
"""Get cancel event for cancel transaction.
|
||||
|
||||
:param tx_hash: `HexBytes` hash of cancel transaction
|
||||
"""
|
||||
tx_receipt = self._web3_eth.getTransactionReceipt(tx_hash)
|
||||
return self._exchange.events.Cancel().processReceipt(tx_receipt)
|
||||
|
||||
@staticmethod
|
||||
def _raise_if_maker_not_canceller(maker_address, canceller_address):
|
||||
"""Raise exception is maker is not same as canceller."""
|
||||
if maker_address != canceller_address:
|
||||
raise CancelDisallowedError(
|
||||
"Order with makerAddress {} can not be cancelled by {}".format(
|
||||
maker_address, canceller_address
|
||||
)
|
||||
)
|
@@ -7,8 +7,9 @@ from eth_utils import remove_0x_prefix
|
||||
|
||||
from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId
|
||||
from zero_ex.contract_wrappers import Exchange, TxParams
|
||||
from zero_ex.contract_wrappers.exchange.types import Order
|
||||
from zero_ex.json_schemas import assert_valid
|
||||
from zero_ex.order_utils import generate_order_hash_hex, Order, sign_hash
|
||||
from zero_ex.order_utils import generate_order_hash_hex, sign_hash_to_bytes
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
@@ -28,20 +29,20 @@ def create_test_order(
|
||||
taker_asset_data,
|
||||
):
|
||||
"""Create a test order."""
|
||||
order: Order = {
|
||||
"makerAddress": maker_address.lower(),
|
||||
"takerAddress": "0x0000000000000000000000000000000000000000",
|
||||
"feeRecipientAddress": "0x0000000000000000000000000000000000000000",
|
||||
"senderAddress": "0x0000000000000000000000000000000000000000",
|
||||
"makerAssetAmount": maker_asset_amount,
|
||||
"takerAssetAmount": taker_asset_amount,
|
||||
"makerFee": 0,
|
||||
"takerFee": 0,
|
||||
"expirationTimeSeconds": 100000000000000,
|
||||
"salt": random.randint(1, 1000000000),
|
||||
"makerAssetData": maker_asset_data,
|
||||
"takerAssetData": taker_asset_data,
|
||||
}
|
||||
order = Order(
|
||||
makerAddress=maker_address.lower(),
|
||||
takerAddress="0x0000000000000000000000000000000000000000",
|
||||
feeRecipientAddress="0x0000000000000000000000000000000000000000",
|
||||
senderAddress="0x0000000000000000000000000000000000000000",
|
||||
makerAssetAmount=maker_asset_amount,
|
||||
takerAssetAmount=taker_asset_amount,
|
||||
makerFee=0,
|
||||
takerFee=0,
|
||||
expirationTimeSeconds=100000000000000,
|
||||
salt=random.randint(1, 1000000000),
|
||||
makerAssetData=maker_asset_data,
|
||||
takerAssetData=taker_asset_data,
|
||||
)
|
||||
return order
|
||||
|
||||
|
||||
@@ -69,16 +70,16 @@ def test_exchange_wrapper__fill_order(
|
||||
"""Test filling an order."""
|
||||
taker = accounts[0]
|
||||
maker = accounts[1]
|
||||
exchange_address = exchange_wrapper.address
|
||||
exchange_address = exchange_wrapper.contract_address
|
||||
order = create_test_order(maker, 1, weth_asset_data, 1, weth_asset_data)
|
||||
order_hash = generate_order_hash_hex(
|
||||
order=order, exchange_address=exchange_address
|
||||
)
|
||||
order_signature = sign_hash(ganache_provider, maker, order_hash)
|
||||
order_signature = sign_hash_to_bytes(ganache_provider, maker, order_hash)
|
||||
|
||||
tx_hash = exchange_wrapper.fill_order(
|
||||
order=order,
|
||||
taker_amount=order["takerAssetAmount"],
|
||||
taker_asset_fill_amount=order["takerAssetAmount"],
|
||||
signature=order_signature,
|
||||
tx_params=TxParams(from_=taker),
|
||||
)
|
||||
@@ -98,7 +99,7 @@ def test_exchange_wrapper__batch_fill_orders(
|
||||
"""Test filling a batch of orders."""
|
||||
taker = accounts[0]
|
||||
maker = accounts[1]
|
||||
exchange_address = exchange_wrapper.address
|
||||
exchange_address = exchange_wrapper.contract_address
|
||||
orders = []
|
||||
order_1 = create_test_order(maker, 1, weth_asset_data, 1, weth_asset_data)
|
||||
order_2 = create_test_order(maker, 1, weth_asset_data, 1, weth_asset_data)
|
||||
@@ -109,13 +110,13 @@ def test_exchange_wrapper__batch_fill_orders(
|
||||
for order in orders
|
||||
]
|
||||
order_signatures = [
|
||||
sign_hash(ganache_provider, maker, order_hash)
|
||||
sign_hash_to_bytes(ganache_provider, maker, order_hash)
|
||||
for order_hash in order_hashes
|
||||
]
|
||||
taker_amounts = [order["takerAssetAmount"] for order in orders]
|
||||
tx_hash = exchange_wrapper.batch_fill_orders(
|
||||
orders=orders,
|
||||
taker_amounts=taker_amounts,
|
||||
taker_asset_fill_amounts=taker_amounts,
|
||||
signatures=order_signatures,
|
||||
tx_params=TxParams(from_=taker),
|
||||
)
|
||||
|
@@ -1,13 +1,3 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env bash
|
||||
|
||||
"""Script to install all packages in editable mode (pip install -e .)."""
|
||||
|
||||
from os import path
|
||||
import subprocess
|
||||
|
||||
# install all packages
|
||||
subprocess.check_call(
|
||||
(
|
||||
path.join(".", "cmd_pkgs_in_dep_order.py") + " pip install -e .[dev]"
|
||||
).split()
|
||||
)
|
||||
./parallel pip install -e .[dev]
|
||||
|
@@ -5,7 +5,7 @@
|
||||
import distutils.command.build_py
|
||||
from distutils.command.clean import clean
|
||||
import subprocess # nosec
|
||||
from shutil import rmtree
|
||||
from shutil import copytree, rmtree
|
||||
from os import environ, path
|
||||
from sys import argv
|
||||
|
||||
@@ -13,6 +13,26 @@ from setuptools import find_packages, setup
|
||||
from setuptools.command.test import test as TestCommand
|
||||
|
||||
|
||||
class PreInstallCommand(distutils.command.build_py.build_py):
|
||||
"""Custom setuptools command class for pulling in schemas."""
|
||||
|
||||
description = "Pull in the schemas that live in the TypeScript package."
|
||||
|
||||
def run(self):
|
||||
"""Copy files from TS area to local src."""
|
||||
pkgdir = path.dirname(path.realpath(argv[0]))
|
||||
rmtree(
|
||||
path.join(pkgdir, "src", "zero_ex", "json_schemas", "schemas"),
|
||||
ignore_errors=True,
|
||||
)
|
||||
copytree(
|
||||
path.join(
|
||||
pkgdir, "..", "..", "packages", "json-schemas", "schemas"
|
||||
),
|
||||
path.join(pkgdir, "src", "zero_ex", "json_schemas", "schemas"),
|
||||
)
|
||||
|
||||
|
||||
class TestCommandExtension(TestCommand):
|
||||
"""Run pytest tests."""
|
||||
|
||||
@@ -41,15 +61,6 @@ class LintCommand(distutils.command.build_py.build_py):
|
||||
"mypy src test setup.py".split(),
|
||||
# security issue checker:
|
||||
"bandit -r src ./setup.py".split(),
|
||||
# HACK: ensure json schemas don't differ from the authoritative
|
||||
# copies: this is a hack. ideally we would symlink to the
|
||||
# authoritative copies, but a problem with setuptools is preventing
|
||||
# it from following symlinks when gathering package_data. see
|
||||
# https://github.com/pypa/setuptools/issues/415.
|
||||
(
|
||||
"diff src/zero_ex/json_schemas/schemas"
|
||||
+ " ../../packages/json-schemas/schemas"
|
||||
).split(),
|
||||
# general linter:
|
||||
"pylint src test setup.py".split(),
|
||||
# pylint takes relatively long to run, so it runs last, to enable
|
||||
@@ -138,6 +149,7 @@ setup(
|
||||
author="F. Eugene Aumson",
|
||||
author_email="feuGeneA@users.noreply.github.com",
|
||||
cmdclass={
|
||||
"pre_install": PreInstallCommand,
|
||||
"clean": CleanCommandExtension,
|
||||
"lint": LintCommand,
|
||||
"test": TestCommandExtension,
|
||||
@@ -196,6 +208,7 @@ setup(
|
||||
"build_sphinx": {
|
||||
"source_dir": ("setup.py", "src"),
|
||||
"build_dir": ("setup.py", "build/docs"),
|
||||
"warning_is_error": ("setup.py", "true"),
|
||||
}
|
||||
},
|
||||
)
|
||||
|
@@ -61,9 +61,10 @@ def assert_valid(data: Mapping, schema_id: str) -> None:
|
||||
|
||||
>>> from zero_ex.json_schemas import assert_valid
|
||||
>>> from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId
|
||||
>>> from zero_ex.order_utils import (
|
||||
... asset_data_utils, Order, order_to_jsdict
|
||||
>>> 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
|
||||
>>> import random
|
||||
>>> from datetime import datetime, timedelta
|
||||
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"id": "/addressSchema",
|
||||
"type": "string",
|
||||
"pattern": "^0x[0-9a-f]{40}$"
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"id": "/AssetPairsRequestOptsSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"assetDataA": { "$ref": "/hexSchema" },
|
||||
"assetDataB": { "$ref": "/hexSchema" }
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"id": "/blockParamSchema",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"enum": ["latest", "earliest", "pending"]
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"id": "/blockRangeSchema",
|
||||
"properties": {
|
||||
"fromBlock": { "$ref": "/blockParamSchema" },
|
||||
"toBlock": { "$ref": "/blockParamSchema" }
|
||||
},
|
||||
"type": "object"
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"id": "/callDataSchema",
|
||||
"properties": {
|
||||
"from": { "$ref": "/addressSchema" },
|
||||
"to": { "$ref": "/addressSchema" },
|
||||
"value": {
|
||||
"oneOf": [{ "$ref": "/numberSchema" }, { "$ref": "/jsNumberSchema" }]
|
||||
},
|
||||
"gas": {
|
||||
"oneOf": [{ "$ref": "/numberSchema" }, { "$ref": "/jsNumberSchema" }]
|
||||
},
|
||||
"gasPrice": {
|
||||
"oneOf": [{ "$ref": "/numberSchema" }, { "$ref": "/jsNumberSchema" }]
|
||||
},
|
||||
"data": {
|
||||
"type": "string",
|
||||
"pattern": "^0x[0-9a-f]*$"
|
||||
},
|
||||
"nonce": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
||||
},
|
||||
"required": [],
|
||||
"type": "object",
|
||||
"additionalProperties": false
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"id": "/ecSignatureParameterSchema",
|
||||
"type": "string",
|
||||
"pattern": "^0[xX][0-9A-Fa-f]{64}$"
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"id": "/ecSignatureSchema",
|
||||
"properties": {
|
||||
"v": {
|
||||
"type": "number",
|
||||
"minimum": 27,
|
||||
"maximum": 28
|
||||
},
|
||||
"r": { "$ref": "/ecSignatureParameterSchema" },
|
||||
"s": { "$ref": "/ecSignatureParameterSchema" }
|
||||
},
|
||||
"required": ["v", "r", "s"],
|
||||
"type": "object"
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"id": "/eip712TypedDataSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"types": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"EIP712Domain": { "type": "array" }
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": { "type": "string" },
|
||||
"type": { "type": "string" }
|
||||
},
|
||||
"required": ["name", "type"]
|
||||
}
|
||||
},
|
||||
"required": ["EIP712Domain"]
|
||||
},
|
||||
"primaryType": { "type": "string" },
|
||||
"domain": { "type": "object" },
|
||||
"message": { "type": "object" }
|
||||
},
|
||||
"required": ["types", "primaryType", "domain", "message"]
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"id": "/hexSchema",
|
||||
"type": "string",
|
||||
"pattern": "^0x(([0-9a-f][0-9a-f])+)?$"
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"id": "/indexFilterValuesSchema",
|
||||
"additionalProperties": {
|
||||
"oneOf": [{ "$ref": "/numberSchema" }, { "$ref": "/addressSchema" }, { "$ref": "/orderHashSchema" }]
|
||||
},
|
||||
"type": "object"
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"id": "/jsNumberSchema",
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"id": "/numberSchema",
|
||||
"type": "string",
|
||||
"pattern": "^\\d+(\\.\\d+)?$"
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "/orderCancellationRequestsSchema",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"properties": {
|
||||
"order": { "$ref": "/orderSchema" },
|
||||
"takerTokenCancelAmount": { "$ref": "/wholeNumberSchema" }
|
||||
},
|
||||
"required": ["order", "takerTokenCancelAmount"],
|
||||
"type": "object"
|
||||
}
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"id": "/OrderConfigRequestSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"makerAddress": { "$ref": "/addressSchema" },
|
||||
"takerAddress": { "$ref": "/addressSchema" },
|
||||
"makerAssetAmount": { "$ref": "/wholeNumberSchema" },
|
||||
"takerAssetAmount": { "$ref": "/wholeNumberSchema" },
|
||||
"makerAssetData": { "$ref": "/hexSchema" },
|
||||
"takerAssetData": { "$ref": "/hexSchema" },
|
||||
"exchangeAddress": { "$ref": "/addressSchema" },
|
||||
"expirationTimeSeconds": { "$ref": "/wholeNumberSchema" }
|
||||
},
|
||||
"required": [
|
||||
"makerAddress",
|
||||
"takerAddress",
|
||||
"makerAssetAmount",
|
||||
"takerAssetAmount",
|
||||
"makerAssetData",
|
||||
"takerAssetData",
|
||||
"exchangeAddress",
|
||||
"expirationTimeSeconds"
|
||||
]
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "/orderFillOrKillRequestsSchema",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"properties": {
|
||||
"signedOrder": { "$ref": "/signedOrderSchema" },
|
||||
"fillTakerAmount": { "$ref": "/wholeNumberSchema" }
|
||||
},
|
||||
"required": ["signedOrder", "fillTakerAmount"],
|
||||
"type": "object"
|
||||
}
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "/orderFillRequestsSchema",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"properties": {
|
||||
"signedOrder": { "$ref": "/signedOrderSchema" },
|
||||
"takerTokenFillAmount": { "$ref": "/wholeNumberSchema" }
|
||||
},
|
||||
"required": ["signedOrder", "takerTokenFillAmount"],
|
||||
"type": "object"
|
||||
}
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"id": "/orderHashSchema",
|
||||
"type": "string",
|
||||
"pattern": "^0x[0-9a-fA-F]{64}$"
|
||||
}
|
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"id": "/orderSchema",
|
||||
"properties": {
|
||||
"makerAddress": { "$ref": "/addressSchema" },
|
||||
"takerAddress": { "$ref": "/addressSchema" },
|
||||
"makerFee": { "$ref": "/wholeNumberSchema" },
|
||||
"takerFee": { "$ref": "/wholeNumberSchema" },
|
||||
"senderAddress": { "$ref": "/addressSchema" },
|
||||
"makerAssetAmount": { "$ref": "/wholeNumberSchema" },
|
||||
"takerAssetAmount": { "$ref": "/wholeNumberSchema" },
|
||||
"makerAssetData": { "$ref": "/hexSchema" },
|
||||
"takerAssetData": { "$ref": "/hexSchema" },
|
||||
"salt": { "$ref": "/wholeNumberSchema" },
|
||||
"exchangeAddress": { "$ref": "/addressSchema" },
|
||||
"feeRecipientAddress": { "$ref": "/addressSchema" },
|
||||
"expirationTimeSeconds": { "$ref": "/wholeNumberSchema" }
|
||||
},
|
||||
"required": [
|
||||
"makerAddress",
|
||||
"takerAddress",
|
||||
"makerFee",
|
||||
"takerFee",
|
||||
"senderAddress",
|
||||
"makerAssetAmount",
|
||||
"takerAssetAmount",
|
||||
"makerAssetData",
|
||||
"takerAssetData",
|
||||
"salt",
|
||||
"exchangeAddress",
|
||||
"feeRecipientAddress",
|
||||
"expirationTimeSeconds"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
@@ -1,52 +0,0 @@
|
||||
{
|
||||
"id": "/orderWatcherWebSocketRequestSchema",
|
||||
"type": "object",
|
||||
"definitions": {
|
||||
"signedOrderParam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"signedOrder": { "$ref": "/signedOrderSchema" }
|
||||
},
|
||||
"required": ["signedOrder"]
|
||||
},
|
||||
"orderHashParam": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"orderHash": { "$ref": "/hexSchema" }
|
||||
},
|
||||
"required": ["orderHash"]
|
||||
}
|
||||
},
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": { "type": "number" },
|
||||
"jsonrpc": { "type": "string" },
|
||||
"method": { "enum": ["ADD_ORDER"] },
|
||||
"params": { "$ref": "#/definitions/signedOrderParam" }
|
||||
},
|
||||
"required": ["id", "jsonrpc", "method", "params"]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": { "type": "number" },
|
||||
"jsonrpc": { "type": "string" },
|
||||
"method": { "enum": ["REMOVE_ORDER"] },
|
||||
"params": { "$ref": "#/definitions/orderHashParam" }
|
||||
},
|
||||
"required": ["id", "jsonrpc", "method", "params"]
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": { "type": "number" },
|
||||
"jsonrpc": { "type": "string" },
|
||||
"method": { "enum": ["GET_STATS"] },
|
||||
"params": {}
|
||||
},
|
||||
"required": ["id", "jsonrpc", "method"]
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"id": "/orderWatcherWebSocketUtf8MessageSchema",
|
||||
"properties": {
|
||||
"utf8Data": { "type": "string" }
|
||||
},
|
||||
"required": [
|
||||
"utf8Data"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"id": "/OrderbookRequestSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"baseAssetData": { "$ref": "/hexSchema" },
|
||||
"quoteAssetData": { "$ref": "/hexSchema" }
|
||||
},
|
||||
"required": ["baseAssetData", "quoteAssetData"]
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"id": "/OrdersRequestOptsSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"makerAssetProxyId": { "$ref": "/hexSchema" },
|
||||
"takerAssetProxyId": { "$ref": "/hexSchema" },
|
||||
"makerAssetAddress": { "$ref": "/addressSchema" },
|
||||
"takerAssetAddress": { "$ref": "/addressSchema" },
|
||||
"exchangeAddress": { "$ref": "/addressSchema" },
|
||||
"senderAddress": { "$ref": "/addressSchema" },
|
||||
"makerAssetData": { "$ref": "/hexSchema" },
|
||||
"takerAssetData": { "$ref": "/hexSchema" },
|
||||
"traderAssetData": { "$ref": "/hexSchema" },
|
||||
"makerAddress": { "$ref": "/addressSchema" },
|
||||
"takerAddress": { "$ref": "/addressSchema" },
|
||||
"traderAddress": { "$ref": "/addressSchema" },
|
||||
"feeRecipientAddress": { "$ref": "/addressSchema" }
|
||||
}
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"id": "/ordersSchema",
|
||||
"type": "array",
|
||||
"items": { "$ref": "/orderSchema" }
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"id": "/PagedRequestOptsSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"page": { "type": "number" },
|
||||
"perPage": { "type": "number" }
|
||||
}
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"id": "/paginatedCollectionSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"total": { "type": "number" },
|
||||
"perPage": { "type": "number" },
|
||||
"page": { "type": "number" }
|
||||
},
|
||||
"required": ["total", "perPage", "page"]
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"id": "/relayerApiAssetDataPairsResponseSchema",
|
||||
"type": "object",
|
||||
"allOf": [
|
||||
{ "$ref": "/paginatedCollectionSchema" },
|
||||
{
|
||||
"properties": {
|
||||
"records": { "$ref": "/relayerApiAssetDataPairsSchema" }
|
||||
},
|
||||
"required": ["records"]
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "/relayerApiAssetDataPairsSchema",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"properties": {
|
||||
"assetDataA": { "$ref": "/relayerApiAssetDataTradeInfoSchema" },
|
||||
"assetDataB": { "$ref": "/relayerApiAssetDataTradeInfoSchema" }
|
||||
},
|
||||
"required": ["assetDataA", "assetDataB"],
|
||||
"type": "object"
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"id": "/relayerApiAssetDataTradeInfoSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"assetData": { "$ref": "/hexSchema" },
|
||||
"minAmount": { "$ref": "/wholeNumberSchema" },
|
||||
"maxAmount": { "$ref": "/wholeNumberSchema" },
|
||||
"precision": { "type": "number" }
|
||||
},
|
||||
"required": ["assetData"]
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"id": "/relayerApiErrorResponseSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"code": { "type": "integer", "minimum": 100, "maximum": 103 },
|
||||
"reason": { "type": "string" },
|
||||
"validationErrors": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"field": { "type": "string" },
|
||||
"code": { "type": "integer", "minimum": 1000, "maximum": 1006 },
|
||||
"reason": { "type": "string" }
|
||||
},
|
||||
"required": ["field", "code", "reason"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["code", "reason"]
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"id": "/relayerApiFeeRecipientsResponseSchema",
|
||||
"type": "object",
|
||||
"allOf": [
|
||||
{ "$ref": "/paginatedCollectionSchema" },
|
||||
{
|
||||
"properties": {
|
||||
"records": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "/addressSchema" }
|
||||
}
|
||||
},
|
||||
"required": ["records"]
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"id": "/relayerApiOrderConfigPayloadSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"makerAddress": { "$ref": "/addressSchema" },
|
||||
"takerAddress": { "$ref": "/addressSchema" },
|
||||
"makerAssetAmount": { "$ref": "/wholeNumberSchema" },
|
||||
"takerAssetAmount": { "$ref": "/wholeNumberSchema" },
|
||||
"makerAssetData": { "$ref": "/hexSchema" },
|
||||
"takerAssetData": { "$ref": "/hexSchema" },
|
||||
"exchangeAddress": { "$ref": "/addressSchema" },
|
||||
"expirationTimeSeconds": { "$ref": "/wholeNumberSchema" }
|
||||
},
|
||||
"required": [
|
||||
"makerAddress",
|
||||
"takerAddress",
|
||||
"makerAssetAmount",
|
||||
"takerAssetAmount",
|
||||
"makerAssetData",
|
||||
"takerAssetData",
|
||||
"exchangeAddress",
|
||||
"expirationTimeSeconds"
|
||||
]
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"id": "/relayerApiOrderConfigResponseSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"makerFee": { "$ref": "/wholeNumberSchema" },
|
||||
"takerFee": { "$ref": "/wholeNumberSchema" },
|
||||
"feeRecipientAddress": { "$ref": "/addressSchema" },
|
||||
"senderAddress": { "$ref": "/addressSchema" }
|
||||
},
|
||||
"required": ["makerFee", "takerFee", "feeRecipientAddress", "senderAddress"]
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"id": "/relayerApiOrderSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order": { "$ref": "/orderSchema" },
|
||||
"metaData": { "type": "object" }
|
||||
},
|
||||
"required": ["order", "metaData"]
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"id": "/relayerApiOrderbookResponseSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bids": { "$ref": "/relayerApiOrdersResponseSchema" },
|
||||
"asks": { "$ref": "/relayerApiOrdersResponseSchema" }
|
||||
},
|
||||
"required": ["bids", "asks"]
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"id": "/relayerApiOrdersChannelSubscribePayloadSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"makerAssetProxyId": { "$ref": "/hexSchema" },
|
||||
"takerAssetProxyId": { "$ref": "/hexSchema" },
|
||||
"networkId": { "type": "number" },
|
||||
"makerAssetAddress": { "$ref": "/addressSchema" },
|
||||
"takerAssetAddress": { "$ref": "/addressSchema" },
|
||||
"makerAssetData": { "$ref": "/hexSchema" },
|
||||
"takerAssetData": { "$ref": "/hexSchema" },
|
||||
"traderAssetData": { "$ref": "/hexSchema" }
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"id": "/relayerApiOrdersChannelSubscribeSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": { "enum": ["subscribe"] },
|
||||
"channel": { "enum": ["orders"] },
|
||||
"requestId": { "type": "string" },
|
||||
"payload": { "$ref": "/relayerApiOrdersChannelSubscribePayloadSchema" }
|
||||
},
|
||||
"required": ["type", "channel", "requestId"]
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"id": "/relayerApiOrdersChannelUpdateSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": { "enum": ["update"] },
|
||||
"channel": { "enum": ["orders"] },
|
||||
"requestId": { "type": "string" },
|
||||
"payload": { "$ref": "/relayerApiOrdersSchema" }
|
||||
},
|
||||
"required": ["type", "channel", "requestId"]
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"id": "/relayerApiOrdersResponseSchema",
|
||||
"type": "object",
|
||||
"allOf": [
|
||||
{ "$ref": "/paginatedCollectionSchema" },
|
||||
{
|
||||
"properties": {
|
||||
"records": { "$ref": "/relayerApiOrdersSchema" }
|
||||
},
|
||||
"required": ["records"]
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"id": "/relayerApiOrdersSchema",
|
||||
"type": "array",
|
||||
"items": { "$ref": "/relayerApiOrderSchema" }
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"id": "/RequestOptsSchema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"networkId": { "type": "number" }
|
||||
}
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "/signedOrderSchema",
|
||||
"allOf": [
|
||||
{ "$ref": "/orderSchema" },
|
||||
{
|
||||
"properties": {
|
||||
"signature": { "$ref": "/hexSchema" }
|
||||
},
|
||||
"required": ["signature"]
|
||||
}
|
||||
]
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user