First auto-gen'd Python contract wrapper: ERC20 (#1878)
* abi-gen-wrappers: fix half-baked folder rename
* .circleci: give cache more descriptive name
* abi-gen: rename type field. tsName->langLocalName
* contract-artifacts: add devdoc to ERC20Token.json
Artifact changes crafted manually: re-generated artifacts from within
@0x/contracts-erc20, and then copied them into @0x/contract-artifacts,
but only committed the changes that added devdoc.
Modified @0x/contracts-erc20/compiler.json to include devdoc in the
hopes that next time contract-artifacts are re-generated en masse, the
devdoc output will just come along for the ride.
Compiling ERC20 TypeScript wrappers after adding devdoc to the artifacts
revealed some inconsistencies in the types. ethereum-types'
DevdocOutput REQUIRED many fields which are not always present,
depending the devdoc contents itself. Relaxing the requirement had some
ramifications.
* abi-gen: Python!
Lots more to come, but so far generating typed methods with some
parameter validation and with reasonable docstrings; enough to make
ERC20 work.
* existing erc20 python wrapper: re-order methods
In order to minimize the diff in the upcoming commit of the
auto-generated version.
* existing erc20 python wrapper: rename method
Rename method _erc20 to _get_contract_instance.
* existing erc20 python wrapper: rename vars
Rename method parameters to match names used in contract methods.
* existing erc20 python wrapper: correction
Contract method `allowance` previously was returning a transaction hash,
but it's a const method, so changed it to return the int that the
underlying method returns.
* contract_wrappers.py: pull in generated code
Custom setup.py command to pull in code previously generated into
../../packages/abi-gen-wrappers/src/generated-wrappers/py.
Changes to existing wrapper code reflect differences between the old,
manually-written wrapper and the new, auto-generated wrapper.
Reconfigured Circle CI to give Python build access to the output of the
TypeScript build, in order to import the generated wrappers from there.
* abi-gen: sanitize docstrings for pycodestyle lint
* abi-gen-templates.py: expose ABI from template
Use ABI given by template, not gotten by name from
zero_ex.contract_artifacts.
Also, expose ABI as a static method.
* py wrappers: contract addr to ctor, not methods
In all Python wrappers (old, manual ones; and new, generated ones), have
client pass the contract address to the wrapper's constructor, rather
than to the individual method calls.
* py wrappers: remove unused param `account_address`
* py wrappers: document use of `private_key`
* Rename file erc20_wrapper.py to erc20_token.py
To match the name of the underlying contract.
* Update CHANGELOG.json's
* git rm erc20_token.py
No need to keep it checked in. Doing so would require manual overhead
of keeping the generated copy in sync with the generation code, which
may get overlooked and cause confusion for others. Authoritative source
will be the published package on PyPI.
* abi-gen-templates: tweak CHANGELOG wording
Co-Authored-By: Fabio B <kandinsky454@protonmail.ch>
* Include transaction parameters in const calls too
* Doc contract_address param to gen'd wrapper ctor
* make myself a CODEOWNER of abi-gen*
* rename ids: langLocalName -> languageSpecificName
* Move Python generation to its own packages/ folder
* Stop duplicating contract artifacts in Python pkg!
Thanks to the way we're now using the `./setup.py pre_install`
convention, there's no longer a need to check the artifacts in to the
Python package.
* move py templates BACK to abi-gen-templates
I got a little overzealous in the previous commit that moved ALL the
python stuff into the new packages/python-contract-wrappers folder.
* Update known-good test output: prettify
* add getABIEncodedTransationData to gen'd code
It was added into the template in the following commit, but the
corresponding checked-in generated code was not updated accordingly.
f51c4f9617
* Fix missed instance of languageSpecificName change
* abi-gen: refine pipeline for testing gen'd code
- generate wrappers for test fixture contracts (dummy, etc) not in `yarn
build` but in `yarn test`
- rename folder test/generated-test/generated-wrappers to
test/generated-test/known-good, and stop writing test output to there,
instead writing it to a new test/generated-test/output folder.
- sol-compile test fixture contracts in every test run
- run unit tests separately from tests of generated and built TypeScript
wrappers. The existing `yarn run_mocha` will run unit tests, and
there's a new `yarn run_contract_wrapper_tests`.
* abi-gen: test Python gen [known test failures]
Also generate TypeScript wrapper test code into a TypeScript folder
(alongside the newly created Python folder).
Known-good code manually corrected (from generated code) to reflect
known problems that still need to be addressed. Namely:
- base contract and tx params should be imported from canonical
package, not relative path. relative path is working for wrapping
OUR contracts, but would not be usable in a more general
context.
- return type missing for some generated methods.
These outstanding problems are currently causing this test to fail.
* fix failing abi-gen test: missing return types
* fix failing abi-gen test: qualify imports
* in py wrapper, simplify base class initialization
per
https://github.com/0xProject/0x-monorepo/pull/1878#discussion_r299248641
* move 3rd party typings to typescript-typings
* make package python-contract-wrappers private
* make Xianny CODEOWNER of base-contract & templates
* abi-gen: clarify --help for --backend
* remove superfluous CHANGELOG entry
This commit is contained in:
parent
f77aaaf2e0
commit
d9378e9a8f
@ -29,6 +29,10 @@ jobs:
|
||||
key: repo-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo
|
||||
- save_cache:
|
||||
key: python-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- ~/repo/packages/python-contract-wrappers/generated
|
||||
build-website:
|
||||
resource_class: medium+
|
||||
docker:
|
||||
@ -210,14 +214,17 @@ jobs:
|
||||
- run: sudo chown -R circleci:circleci /usr/local/bin
|
||||
- run: sudo chown -R circleci:circleci /usr/local/lib/python3.7
|
||||
- restore_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
key: python-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
command: |
|
||||
cd python-packages
|
||||
python -m ensurepip
|
||||
./pre_install
|
||||
./install
|
||||
- save_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- '/usr/local/bin'
|
||||
- '/usr/local/lib/python3.7/site-packages'
|
||||
@ -258,14 +265,14 @@ jobs:
|
||||
- run: sudo chown -R circleci:circleci /usr/local/bin
|
||||
- run: sudo chown -R circleci:circleci /usr/local/lib/python3.7
|
||||
- restore_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
command: |
|
||||
cd python-packages/order_utils
|
||||
python -m ensurepip
|
||||
python -m pip install .
|
||||
- save_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
paths:
|
||||
- '/usr/local/bin'
|
||||
- '/usr/local/lib/python3.7/site-packages'
|
||||
@ -286,11 +293,14 @@ jobs:
|
||||
- run: sudo chown -R circleci:circleci /usr/local/bin
|
||||
- run: sudo chown -R circleci:circleci /usr/local/lib/python3.7
|
||||
- restore_cache:
|
||||
key: deps9-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
key: installed-py-{{ .Branch }}-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- restore_cache:
|
||||
key: python-contract-wrappers-{{ .Environment.CIRCLE_SHA1 }}
|
||||
- run:
|
||||
command: |
|
||||
python -m ensurepip
|
||||
cd python-packages
|
||||
./pre_install
|
||||
./install
|
||||
./lint
|
||||
static-tests:
|
||||
@ -419,6 +429,8 @@ workflows:
|
||||
- static-tests-python:
|
||||
requires:
|
||||
- test-python
|
||||
- test-python
|
||||
- test-python:
|
||||
requires:
|
||||
- build
|
||||
# skip python tox run for now, as we don't yet have multiple test environments to support.
|
||||
#- test-rest-python
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -96,11 +96,14 @@ contracts/extensions/generated-artifacts/
|
||||
contracts/exchange-forwarder/generated-artifacts/
|
||||
contracts/dev-utils/generated-artifacts/
|
||||
/packages/abi-gen/test/generated-test/generated-artifacts
|
||||
/packages/abi-gen/test/generated-test/output
|
||||
packages/sol-tracing-utils/test/fixtures/artifacts/
|
||||
packages/metacoin/artifacts/
|
||||
python-packages/contract_artifacts/src/zero_ex/contract_artifacts/artifacts/
|
||||
|
||||
# generated contract wrappers
|
||||
packages/abi-gen-wrappers/wrappers
|
||||
packages/abi-gen-wrappers/src/generated-wrappers/
|
||||
packages/python-contract-wrappers/generated/
|
||||
contracts/coordinator/generated-wrappers/
|
||||
contracts/exchange/generated-wrappers/
|
||||
contracts/asset-proxy/generated-wrappers/
|
||||
|
@ -25,7 +25,7 @@ lib
|
||||
/contracts/dev-utils/generated-wrappers
|
||||
/contracts/dev-utils/generated-artifacts
|
||||
/packages/abi-gen/test/generated-test/generated-artifacts
|
||||
/packages/abi-gen/test/generated-test/generated-wrappers
|
||||
/packages/abi-gen/test/generated-test/known-good
|
||||
/packages/abi-gen-wrappers/src/generated-wrappers
|
||||
/packages/contract-artifacts/artifacts
|
||||
/python-packages/contract_artifacts/src/zero_ex/contract_artifacts/artifacts
|
||||
|
@ -11,10 +11,10 @@ packages/website/ @BMillman19 @fragosti @fabioberger @steveklebanoff
|
||||
|
||||
# Dev tools & setup
|
||||
.circleci/ @LogvinovLeon
|
||||
packages/abi-gen/ @LogvinovLeon
|
||||
packages/base-contract/ @LogvinovLeon
|
||||
packages/abi-gen/ @feuGeneA
|
||||
packages/base-contract/ @xianny
|
||||
packages/connect/ @fragosti
|
||||
packages/abi-gen-templates/ @LogvinovLeon
|
||||
packages/abi-gen-templates/ @feuGeneA @xianny
|
||||
packages/contract-addresses/ @albrow
|
||||
packages/contract-artifacts/ @albrow
|
||||
packages/dev-utils/ @LogvinovLeon @fabioberger
|
||||
@ -23,6 +23,7 @@ packages/ethereum-types/ @LogvinovLeon
|
||||
packages/metacoin/ @LogvinovLeon
|
||||
packages/monorepo-scripts/ @fabioberger
|
||||
packages/order-utils/ @fabioberger @LogvinovLeon
|
||||
packages/python-contract-wrappers/ @feuGeneA
|
||||
packages/sol-compiler/ @LogvinovLeon
|
||||
packages/sol-coverage/ @LogvinovLeon
|
||||
packages/sol-profiler/ @LogvinovLeon
|
||||
|
@ -9,6 +9,10 @@
|
||||
{
|
||||
"note": "Move `getABITransactionData` to `callAsync` template",
|
||||
"pr": 1863
|
||||
},
|
||||
{
|
||||
"note": "Initial support for Python",
|
||||
"pr": 1878
|
||||
}
|
||||
]
|
||||
},
|
||||
|
57
packages/abi-gen-templates/Python/contract.handlebars
Normal file
57
packages/abi-gen-templates/Python/contract.handlebars
Normal file
@ -0,0 +1,57 @@
|
||||
"""Generated wrapper for {{contractName}} 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 {{contractName}}(BaseContractWrapper):
|
||||
"""Wrapper class for {{contractName}} 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={{contractName}}.abi()
|
||||
)
|
||||
{{#each methods}}
|
||||
{{> call contractName=../contractName}}
|
||||
{{/each}}
|
||||
{{#each events}}
|
||||
{{> event}}
|
||||
{{/each}}
|
||||
|
||||
@staticmethod
|
||||
def abi():
|
||||
"""Return the ABI to the underlying contract."""
|
||||
return json.loads(
|
||||
'{{{ABI}}}' # noqa: E501 (line-too-long)
|
||||
)
|
41
packages/abi-gen-templates/Python/partials/call.handlebars
Normal file
41
packages/abi-gen-templates/Python/partials/call.handlebars
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
def {{this.languageSpecificName}}(
|
||||
self,
|
||||
{{> typed_params inputs=inputs}}
|
||||
tx_params: Optional[TxParams] = None,
|
||||
{{^this.constant}}
|
||||
view_only: bool = False,
|
||||
{{/this.constant}}
|
||||
) ->{{#if outputs}}{{~> return_type outputs=outputs~}}{{else}} None{{/if}}:
|
||||
"""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}}
|
||||
:param tx_params: transaction parameters
|
||||
:param view_only: whether to use transact() or call()
|
||||
|
||||
:returns: transaction hash
|
||||
{{/if}}
|
||||
"""
|
||||
{{#each this.inputs}}
|
||||
{{#if (equal type 'address')}}
|
||||
{{this.name}} = self._validate_and_checksum_address({{this.name}})
|
||||
{{else if (equal type 'uint256')}}
|
||||
# safeguard against fractional inputs
|
||||
{{this.name}} = int({{this.name}})
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
func = self._get_contract_instance(
|
||||
self._contract_address
|
||||
).functions.{{this.name}}(
|
||||
{{> params}}
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only={{#if this.constant}}True{{else}}view_only{{/if}}
|
||||
)
|
14
packages/abi-gen-templates/Python/partials/event.handlebars
Normal file
14
packages/abi-gen-templates/Python/partials/event.handlebars
Normal file
@ -0,0 +1,14 @@
|
||||
def get_{{languageSpecificName}}_event(
|
||||
self, token_address: str, tx_hash: Union[HexBytes, bytes]
|
||||
) -> Tuple[AttributeDict]:
|
||||
"""Get log entry for {{name}} event.
|
||||
|
||||
:param tx_hash: hash of transaction emitting {{name}} event.
|
||||
"""
|
||||
tx_receipt = self._web3_eth.getTransactionReceipt(tx_hash)
|
||||
token_address = self._validate_and_checksum_address(token_address)
|
||||
return (
|
||||
self._get_contract_instance(token_address)
|
||||
.events.{{name}}()
|
||||
.processReceipt(tx_receipt)
|
||||
)
|
@ -0,0 +1,3 @@
|
||||
{{#each inputs}}
|
||||
{{name}}{{#if @last}}{{else}},{{/if}}
|
||||
{{/each}}
|
@ -0,0 +1,13 @@
|
||||
{{#if this.constant}}
|
||||
{{#if outputs.length}}
|
||||
{{#singleReturnValue}}
|
||||
{{#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~}}
|
@ -0,0 +1,3 @@
|
||||
{{#each inputs}}
|
||||
{{name}}: {{#parameterType type components}}{{/parameterType}},
|
||||
{{/each}}
|
@ -1,3 +1,3 @@
|
||||
public {{this.tsName}} = {
|
||||
public {{languageSpecificName}} = {
|
||||
{{> callAsync}}
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
public {{this.tsName}} = {
|
||||
public {{languageSpecificName}} = {
|
||||
async sendTransactionAsync(
|
||||
{{> typed_params inputs=inputs}}
|
||||
txData?: Partial<TxData> | undefined,
|
||||
@ -15,7 +15,7 @@ public {{this.tsName}} = {
|
||||
data: encodedData,
|
||||
},
|
||||
self._web3Wrapper.getContractDefaults(),
|
||||
self.{{this.tsName}}.estimateGasAsync.bind(
|
||||
self.{{languageSpecificName}}.estimateGasAsync.bind(
|
||||
self,
|
||||
{{> params inputs=inputs}}
|
||||
),
|
||||
@ -34,9 +34,9 @@ public {{this.tsName}} = {
|
||||
{{/each}}
|
||||
const self = this as any as {{contractName}}Contract;
|
||||
{{#if inputs}}
|
||||
const txHashPromise = self.{{this.tsName}}.sendTransactionAsync({{> params input=inputs}}, txData);
|
||||
const txHashPromise = self.{{languageSpecificName}}.sendTransactionAsync({{> params input=inputs}}, txData);
|
||||
{{else}}
|
||||
const txHashPromise = self.{{this.tsName}}.sendTransactionAsync(txData);
|
||||
const txHashPromise = self.{{languageSpecificName}}.sendTransactionAsync(txData);
|
||||
{{/if}}
|
||||
return new PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs>(
|
||||
txHashPromise,
|
||||
|
@ -15,7 +15,7 @@
|
||||
"lint": "tslint --format stylish --project .",
|
||||
"fix": "tslint --fix --format stylish --project .",
|
||||
"pre_build": "yarn generate_contract_wrappers",
|
||||
"clean": "shx rm -rf lib wrappers",
|
||||
"clean": "shx rm -rf lib src/generated-wrappers",
|
||||
"generate_contract_wrappers": "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 src/generated-wrappers --backend ethers"
|
||||
},
|
||||
"config": {
|
||||
|
@ -64,6 +64,15 @@ export class EthBalanceCheckerContract extends BaseContract {
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
getABIEncodedTransactionData(
|
||||
addresses: string[],
|
||||
): string {
|
||||
assert.isArray('addresses', addresses);
|
||||
const self = this as any as EthBalanceCheckerContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('getEthBalances(address[])', [addresses
|
||||
]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public static async deployFrom0xArtifactAsync(
|
||||
artifact: ContractArtifact | SimpleContractArtifact,
|
||||
|
@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "2.1.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Initial support for Python",
|
||||
"pr": 1878
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.0.11",
|
||||
"changes": [
|
||||
|
@ -1,5 +1,5 @@
|
||||
diff $1 $2
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: Run 'yarn generate_contract_wrappers' to update ./test/generated_test/generated-wrappers"
|
||||
echo "ERROR: Freshly generated code does not match known-good, commited output. If you're confident that the freshly generated code should be considered known-good, then copy it into there and commit it."
|
||||
exit 1
|
||||
fi
|
||||
|
@ -11,13 +11,14 @@
|
||||
"lint": "tslint --format stylish --project . && yarn lint-contracts",
|
||||
"lint-contracts": "solhint -c ../../contracts/.solhint.json contracts/**/**/**/**/*.sol",
|
||||
"fix": "tslint --fix --format stylish --project . && yarn lint-contracts",
|
||||
"clean": "shx rm -rf lib test/generated-test/lib",
|
||||
"build": "tsc -b && yarn build:test",
|
||||
"prebuild:test": "run-s compile:sol generate_contract_wrappers",
|
||||
"build:test": "tsc --project test/generated-test/tsconfig.json",
|
||||
"clean": "shx rm -rf lib test/generated-test/output",
|
||||
"build": "tsc -b",
|
||||
"build_contracts_to_wrap": "run-s compile:sol",
|
||||
"build_contract_wrappers": "tsc --project test/generated-test/tsconfig.json",
|
||||
"build:ci": "yarn build",
|
||||
"test": "run-s run_mocha tmp_generate_contract_wrappers diff_contract_wrappers tmp_remove_contract_wrappers",
|
||||
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js test/generated-test/lib/**/*_test.js --timeout 100000 --bail --exit",
|
||||
"test": "run-s run_mocha build_contracts_to_wrap generate_contract_wrappers diff_contract_wrappers # build_contract_wrappers run_contract_wrapper_tests HACK: note this is commented out. building those contract wrappers is broken on development right now",
|
||||
"run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/*_test.js --timeout 100000 --bail --exit",
|
||||
"run_contract_wrapper_tests": "mocha --require source-map-support/register --require make-promises-safe test/generated-test/output/TypeScript/lib/**/*_test.js --timeout 100000 --bail --exit",
|
||||
"test:circleci": "yarn test:coverage",
|
||||
"test:coverage": "nyc npm run test --all && yarn coverage:report:lcov",
|
||||
"coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info",
|
||||
@ -27,10 +28,12 @@
|
||||
"clean:sol": "rm -rf test/generated-test/generated-artifacts",
|
||||
"compile:sol": "sol-compiler",
|
||||
"watch:sol": "sol-compiler -w",
|
||||
"generate_contract_wrappers": "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/generated-test/generated-wrappers --backend ethers",
|
||||
"tmp_generate_contract_wrappers": "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 ./tmp/generated-wrappers --backend ethers",
|
||||
"tmp_remove_contract_wrappers": "rm -rf ./tmp/generated-wrappers",
|
||||
"diff_contract_wrappers": "./diff.sh ./tmp/generated-wrappers ./test/generated-test/generated-wrappers",
|
||||
"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/generated-test/output/TypeScript/src --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/generated-test/output/Python --language Python",
|
||||
"diff_contract_wrappers": "run-p diff_typescript diff_python",
|
||||
"diff_typescript": "./diff.sh ./test/generated-test/known-good/TypeScript ./test/generated-test/output/TypeScript/src",
|
||||
"diff_python": "./diff.sh ./test/generated-test/known-good/Python ./test/generated-test/output/Python",
|
||||
"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",
|
||||
@ -57,6 +60,8 @@
|
||||
"@0x/typescript-typings": "^4.2.2",
|
||||
"@0x/utils": "^4.3.3",
|
||||
"chalk": "^2.3.0",
|
||||
"change-case": "^3.0.2",
|
||||
"cli-format": "^3.0.9",
|
||||
"ethereum-types": "^2.1.2",
|
||||
"glob": "^7.1.2",
|
||||
"handlebars": "^4.0.11",
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
import { AbiEncoder, abiUtils, logUtils } from '@0x/utils';
|
||||
import chalk from 'chalk';
|
||||
import { AbiDefinition, ConstructorAbi, EventAbi, MethodAbi } from 'ethereum-types';
|
||||
import * as changeCase from 'change-case';
|
||||
import * as cliFormat from 'cli-format';
|
||||
import { AbiDefinition, ConstructorAbi, DevdocOutput, EventAbi, MethodAbi } from 'ethereum-types';
|
||||
import { sync as globSync } from 'glob';
|
||||
import * as Handlebars from 'handlebars';
|
||||
import * as _ from 'lodash';
|
||||
@ -43,7 +45,7 @@ const args = yargs
|
||||
normalize: true,
|
||||
})
|
||||
.option('backend', {
|
||||
describe: `The backing Ethereum library your app uses. Either 'web3' or 'ethers'. Ethers auto-converts small ints to numbers whereas Web3 doesn't.`,
|
||||
describe: `The backing Ethereum library your app uses. For TypeScript, either 'web3' or 'ethers'. Ethers auto-converts small ints to numbers whereas Web3 doesn't. For Python, the only possibility is Web3.py`,
|
||||
type: 'string',
|
||||
choices: [ContractsBackend.Web3, ContractsBackend.Ethers],
|
||||
default: DEFAULT_BACKEND,
|
||||
@ -53,6 +55,12 @@ const args = yargs
|
||||
type: 'number',
|
||||
default: DEFAULT_NETWORK_ID,
|
||||
})
|
||||
.option('language', {
|
||||
describe: 'Language of output file to generate',
|
||||
type: 'string',
|
||||
choices: ['TypeScript', 'Python'],
|
||||
default: 'TypeScript',
|
||||
})
|
||||
.example(
|
||||
"$0 --abis 'src/artifacts/**/*.json' --out 'src/contracts/generated/' --partials 'src/templates/partials/**/*.handlebars' --template 'src/templates/contract.handlebars'",
|
||||
'Full usage example',
|
||||
@ -71,11 +79,42 @@ function registerPartials(): void {
|
||||
}
|
||||
}
|
||||
|
||||
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input, args.backend));
|
||||
Handlebars.registerHelper('assertionType', utils.solTypeToAssertion.bind(utils));
|
||||
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output, args.backend));
|
||||
if (args.language === 'TypeScript') {
|
||||
Handlebars.registerHelper('parameterType', utils.solTypeToTsType.bind(utils, ParamKind.Input, args.backend));
|
||||
Handlebars.registerHelper('assertionType', utils.solTypeToAssertion.bind(utils));
|
||||
Handlebars.registerHelper('returnType', utils.solTypeToTsType.bind(utils, ParamKind.Output, args.backend));
|
||||
} else if (args.language === 'Python') {
|
||||
Handlebars.registerHelper('equal', (lhs, rhs, options) => {
|
||||
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(
|
||||
'sanitizeDevdocDetails',
|
||||
(methodName: string, devdocDetails: string, indent: number, options) => {
|
||||
// wrap to 80 columns, assuming given indent, so that generated
|
||||
// docstrings can pass pycodestyle checks.
|
||||
if (devdocDetails === undefined || devdocDetails.length === 0) {
|
||||
return '';
|
||||
}
|
||||
const columnsPerRow = 80;
|
||||
return new Handlebars.SafeString(
|
||||
`\n${cliFormat.wrap(devdocDetails || '', {
|
||||
paddingLeft: ' '.repeat(indent),
|
||||
width: columnsPerRow - indent,
|
||||
ansi: false,
|
||||
})}\n`,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
registerPartials();
|
||||
|
||||
function makeLanguageSpecificName(methodName: string): string {
|
||||
return args.language === 'Python' ? changeCase.snake(methodName) : methodName;
|
||||
}
|
||||
|
||||
if (_.isEmpty(abiFileNames)) {
|
||||
logUtils.log(`${chalk.red(`No ABI files found.`)}`);
|
||||
logUtils.log(`Please make sure you've passed the correct folder name and that the files have
|
||||
@ -90,12 +129,16 @@ for (const abiFileName of abiFileNames) {
|
||||
logUtils.log(`Processing: ${chalk.bold(namedContent.name)}...`);
|
||||
const parsedContent = JSON.parse(namedContent.content);
|
||||
let ABI;
|
||||
let devdoc: DevdocOutput;
|
||||
if (_.isArray(parsedContent)) {
|
||||
ABI = parsedContent; // ABI file
|
||||
} else if (parsedContent.abi !== undefined) {
|
||||
ABI = parsedContent.abi; // Truffle artifact
|
||||
} else if (parsedContent.compilerOutput.abi !== undefined) {
|
||||
ABI = parsedContent.compilerOutput.abi; // 0x artifact
|
||||
if (parsedContent.compilerOutput.devdoc !== undefined) {
|
||||
devdoc = parsedContent.compilerOutput.devdoc;
|
||||
}
|
||||
}
|
||||
if (ABI === undefined) {
|
||||
logUtils.log(`${chalk.red(`ABI not found in ${abiFileName}.`)}`);
|
||||
@ -106,7 +149,16 @@ for (const abiFileName of abiFileNames) {
|
||||
}
|
||||
|
||||
const outFileName = utils.makeOutputFileName(namedContent.name);
|
||||
const outFilePath = `${args.output}/${outFileName}.ts`;
|
||||
const outFileExtension = (() => {
|
||||
if (args.language === 'TypeScript') {
|
||||
return 'ts';
|
||||
} else if (args.language === 'Python') {
|
||||
return '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)}`);
|
||||
@ -127,26 +179,39 @@ for (const abiFileName of abiFileNames) {
|
||||
input.name = `index_${inputIndex}`;
|
||||
}
|
||||
});
|
||||
const functionSignature = new AbiEncoder.Method(methodAbi).getSignature();
|
||||
const languageSpecificName: string = makeLanguageSpecificName(sanitizedMethodAbis[methodAbiIndex].name);
|
||||
// This will make templates simpler
|
||||
const methodData = {
|
||||
...methodAbi,
|
||||
singleReturnValue: methodAbi.outputs.length === 1,
|
||||
hasReturnValue: methodAbi.outputs.length !== 0,
|
||||
tsName: sanitizedMethodAbis[methodAbiIndex].name,
|
||||
functionSignature: new AbiEncoder.Method(methodAbi).getSignature(),
|
||||
languageSpecificName,
|
||||
functionSignature,
|
||||
devdoc: devdoc ? devdoc.methods[functionSignature] : undefined,
|
||||
};
|
||||
return methodData;
|
||||
});
|
||||
|
||||
const eventAbis = ABI.filter((abi: AbiDefinition) => abi.type === ABI_TYPE_EVENT) as EventAbi[];
|
||||
const eventsData = _.map(eventAbis, (eventAbi, eventAbiIndex: number) => {
|
||||
const languageSpecificName = makeLanguageSpecificName(eventAbi.name);
|
||||
|
||||
const eventData = {
|
||||
...eventAbi,
|
||||
languageSpecificName,
|
||||
};
|
||||
return eventData;
|
||||
});
|
||||
|
||||
const contextData = {
|
||||
contractName: namedContent.name,
|
||||
ctor,
|
||||
ABI: JSON.stringify(ABI),
|
||||
methods: methodsData,
|
||||
events: eventAbis,
|
||||
events: eventsData,
|
||||
};
|
||||
const renderedTsCode = template(contextData);
|
||||
utils.writeOutputFile(outFilePath, renderedTsCode);
|
||||
const renderedCode = template(contextData);
|
||||
utils.writeOutputFile(outFilePath, renderedCode);
|
||||
logUtils.log(`Created: ${chalk.bold(outFilePath)}`);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ export enum ContractsBackend {
|
||||
export interface Method extends MethodAbi {
|
||||
singleReturnValue: boolean;
|
||||
hasReturnValue: boolean;
|
||||
tsName: string;
|
||||
languageSpecificName: string;
|
||||
functionSignature: string;
|
||||
}
|
||||
|
||||
|
@ -98,6 +98,45 @@ export const utils = {
|
||||
throw new Error(`Unknown Solidity type found: ${solType}`);
|
||||
}
|
||||
},
|
||||
solTypeToPyType(paramKind: ParamKind, backend: ContractsBackend, 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}]`;
|
||||
return arrayPyType;
|
||||
} else {
|
||||
const solTypeRegexToPyType = [
|
||||
{ regex: '^string$', pyType: 'str' },
|
||||
{ regex: '^address$', pyType: 'str' },
|
||||
{ regex: '^bool$', pyType: 'bool' },
|
||||
{ regex: '^u?int\\d*$', pyType: 'int' },
|
||||
{ regex: '^bytes\\d*$', pyType: 'bytes' },
|
||||
];
|
||||
for (const regexAndTxType of solTypeRegexToPyType) {
|
||||
const { regex, pyType } = regexAndTxType;
|
||||
if (solType.match(regex)) {
|
||||
return pyType;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
throw new Error(`Unknown Solidity type found: ${solType}`);
|
||||
}
|
||||
},
|
||||
isUnionType(tsType: string): boolean {
|
||||
return tsType === 'number|BigNumber';
|
||||
},
|
||||
|
@ -0,0 +1,207 @@
|
||||
"""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 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":"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,51 @@
|
||||
"""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,95 @@
|
||||
"""Generated wrapper for TestLibDummy 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 TestLibDummy(BaseContractWrapper):
|
||||
"""Wrapper class for TestLibDummy 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=TestLibDummy.abi()
|
||||
)
|
||||
|
||||
def public_add_constant(
|
||||
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.publicAddConstant(
|
||||
x
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func,
|
||||
tx_params=tx_params,
|
||||
view_only=True
|
||||
)
|
||||
|
||||
def public_add_one(
|
||||
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.publicAddOne(
|
||||
x
|
||||
)
|
||||
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":"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)
|
||||
)
|
@ -23,12 +23,17 @@ import { assert } from '@0x/assert';
|
||||
import * as ethers from 'ethers';
|
||||
// tslint:enable:no-unused-variable
|
||||
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class AbiGenDummyContract extends BaseContract {
|
||||
public simpleRequire = {
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
|
||||
async callAsync(
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<void
|
||||
> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
@ -37,7 +42,7 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const self = this as any as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('simpleRequire()', []);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
@ -51,20 +56,28 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('simpleRequire()');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
|
||||
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('simpleRequire()', []);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public ecrecoverFn = {
|
||||
async callAsync(
|
||||
hash: string,
|
||||
v: number | BigNumber,
|
||||
v: number|BigNumber,
|
||||
r: string,
|
||||
s: string,
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<string> {
|
||||
): Promise<string
|
||||
> {
|
||||
assert.isString('hash', hash);
|
||||
assert.isNumberOrBigNumber('v', v);
|
||||
assert.isString('r', r);
|
||||
@ -77,12 +90,11 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('ecrecoverFn(bytes32,uint8,bytes32,bytes32)', [
|
||||
hash,
|
||||
const self = this as any as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('ecrecoverFn(bytes32,uint8,bytes32,bytes32)', [hash,
|
||||
v,
|
||||
r,
|
||||
s,
|
||||
s
|
||||
]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
@ -96,13 +108,36 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('ecrecoverFn(bytes32,uint8,bytes32,bytes32)');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
|
||||
const result = abiEncoder.strictDecodeReturnValue<string
|
||||
>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
getABIEncodedTransactionData(
|
||||
hash: string,
|
||||
v: number|BigNumber,
|
||||
r: string,
|
||||
s: string,
|
||||
): string {
|
||||
assert.isString('hash', hash);
|
||||
assert.isNumberOrBigNumber('v', v);
|
||||
assert.isString('r', r);
|
||||
assert.isString('s', s);
|
||||
const self = this as any as AbiGenDummyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('ecrecoverFn(bytes32,uint8,bytes32,bytes32)', [hash,
|
||||
v,
|
||||
r,
|
||||
s
|
||||
]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public revertWithConstant = {
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
|
||||
async callAsync(
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<void
|
||||
> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
@ -111,7 +146,7 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const self = this as any as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('revertWithConstant()', []);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
@ -125,13 +160,24 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('revertWithConstant()');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
|
||||
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('revertWithConstant()', []);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public simpleRevert = {
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
|
||||
async callAsync(
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<void
|
||||
> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
@ -140,7 +186,7 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const self = this as any as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('simpleRevert()', []);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
@ -154,13 +200,24 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('simpleRevert()');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
|
||||
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('simpleRevert()', []);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public requireWithConstant = {
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
|
||||
async callAsync(
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<void
|
||||
> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
@ -169,7 +226,7 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const self = this as any as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('requireWithConstant()', []);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
@ -183,13 +240,25 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('requireWithConstant()');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
|
||||
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('requireWithConstant()', []);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public simplePureFunctionWithInput = {
|
||||
async callAsync(x: BigNumber, callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
|
||||
async callAsync(
|
||||
x: BigNumber,
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<BigNumber
|
||||
> {
|
||||
assert.isBigNumber('x', x);
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
@ -199,8 +268,9 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('simplePureFunctionWithInput(uint256)', [x]);
|
||||
const self = this as any as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('simplePureFunctionWithInput(uint256)', [x
|
||||
]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
@ -213,13 +283,27 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('simplePureFunctionWithInput(uint256)');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
|
||||
const result = abiEncoder.strictDecodeReturnValue<BigNumber
|
||||
>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
getABIEncodedTransactionData(
|
||||
x: BigNumber,
|
||||
): string {
|
||||
assert.isBigNumber('x', x);
|
||||
const self = this as any as AbiGenDummyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('simplePureFunctionWithInput(uint256)', [x
|
||||
]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public simplePureFunction = {
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
|
||||
async callAsync(
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<BigNumber
|
||||
> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
@ -228,7 +312,7 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const self = this as any as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('simplePureFunction()', []);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
@ -242,13 +326,24 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('simplePureFunction()');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
|
||||
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('simplePureFunction()', []);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public pureFunctionWithConstant = {
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
|
||||
async callAsync(
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<BigNumber
|
||||
> {
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
schemas.numberSchema,
|
||||
@ -257,7 +352,7 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as AbiGenDummyContract;
|
||||
const self = this as any as AbiGenDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('pureFunctionWithConstant()', []);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
@ -271,10 +366,17 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('pureFunctionWithConstant()');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
|
||||
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('pureFunctionWithConstant()', []);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public static async deployFrom0xArtifactAsync(
|
||||
artifact: ContractArtifact | SimpleContractArtifact,
|
||||
@ -292,7 +394,7 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
return AbiGenDummyContract.deployAsync(bytecode, abi, provider, txDefaults);
|
||||
return AbiGenDummyContract.deployAsync(bytecode, abi, provider, txDefaults, );
|
||||
}
|
||||
public static async deployAsync(
|
||||
bytecode: string,
|
||||
@ -308,13 +410,17 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
]);
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const constructorAbi = BaseContract._lookupConstructorAbi(abi);
|
||||
[] = BaseContract._formatABIDataItemList(constructorAbi.inputs, [], BaseContract._bigNumberToString);
|
||||
[] = BaseContract._formatABIDataItemList(
|
||||
constructorAbi.inputs,
|
||||
[],
|
||||
BaseContract._bigNumberToString,
|
||||
);
|
||||
const iface = new ethers.utils.Interface(abi);
|
||||
const deployInfo = iface.deployFunction;
|
||||
const txData = deployInfo.encode(bytecode, []);
|
||||
const web3Wrapper = new Web3Wrapper(provider);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{ data: txData },
|
||||
{data: txData},
|
||||
txDefaults,
|
||||
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
|
||||
);
|
||||
@ -322,12 +428,7 @@ export class AbiGenDummyContract extends BaseContract {
|
||||
logUtils.log(`transactionHash: ${txHash}`);
|
||||
const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
||||
logUtils.log(`AbiGenDummy successfully deployed at ${txReceipt.contractAddress}`);
|
||||
const contractInstance = new AbiGenDummyContract(
|
||||
abi,
|
||||
txReceipt.contractAddress as string,
|
||||
provider,
|
||||
txDefaults,
|
||||
);
|
||||
const contractInstance = new AbiGenDummyContract(abi, txReceipt.contractAddress as string, provider, txDefaults);
|
||||
contractInstance.constructorArgs = [];
|
||||
return contractInstance;
|
||||
}
|
@ -23,6 +23,7 @@ import { assert } from '@0x/assert';
|
||||
import * as ethers from 'ethers';
|
||||
// tslint:enable:no-unused-variable
|
||||
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
@ -43,7 +44,7 @@ export class LibDummyContract extends BaseContract {
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
return LibDummyContract.deployAsync(bytecode, abi, provider, txDefaults);
|
||||
return LibDummyContract.deployAsync(bytecode, abi, provider, txDefaults, );
|
||||
}
|
||||
public static async deployAsync(
|
||||
bytecode: string,
|
||||
@ -59,13 +60,17 @@ export class LibDummyContract extends BaseContract {
|
||||
]);
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const constructorAbi = BaseContract._lookupConstructorAbi(abi);
|
||||
[] = BaseContract._formatABIDataItemList(constructorAbi.inputs, [], BaseContract._bigNumberToString);
|
||||
[] = BaseContract._formatABIDataItemList(
|
||||
constructorAbi.inputs,
|
||||
[],
|
||||
BaseContract._bigNumberToString,
|
||||
);
|
||||
const iface = new ethers.utils.Interface(abi);
|
||||
const deployInfo = iface.deployFunction;
|
||||
const txData = deployInfo.encode(bytecode, []);
|
||||
const web3Wrapper = new Web3Wrapper(provider);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{ data: txData },
|
||||
{data: txData},
|
||||
txDefaults,
|
||||
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
|
||||
);
|
@ -23,12 +23,18 @@ import { assert } from '@0x/assert';
|
||||
import * as ethers from 'ethers';
|
||||
// tslint:enable:no-unused-variable
|
||||
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class TestLibDummyContract extends BaseContract {
|
||||
public publicAddConstant = {
|
||||
async callAsync(x: BigNumber, callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
|
||||
async callAsync(
|
||||
x: BigNumber,
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<BigNumber
|
||||
> {
|
||||
assert.isBigNumber('x', x);
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
@ -38,8 +44,9 @@ export class TestLibDummyContract extends BaseContract {
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as TestLibDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('publicAddConstant(uint256)', [x]);
|
||||
const self = this as any as TestLibDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('publicAddConstant(uint256)', [x
|
||||
]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
@ -52,13 +59,28 @@ export class TestLibDummyContract extends BaseContract {
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('publicAddConstant(uint256)');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
|
||||
const result = abiEncoder.strictDecodeReturnValue<BigNumber
|
||||
>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
getABIEncodedTransactionData(
|
||||
x: BigNumber,
|
||||
): string {
|
||||
assert.isBigNumber('x', x);
|
||||
const self = this as any as TestLibDummyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('publicAddConstant(uint256)', [x
|
||||
]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public publicAddOne = {
|
||||
async callAsync(x: BigNumber, callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
|
||||
async callAsync(
|
||||
x: BigNumber,
|
||||
callData: Partial<CallData> = {},
|
||||
defaultBlock?: BlockParam,
|
||||
): Promise<BigNumber
|
||||
> {
|
||||
assert.isBigNumber('x', x);
|
||||
assert.doesConformToSchema('callData', callData, schemas.callDataSchema, [
|
||||
schemas.addressSchema,
|
||||
@ -68,8 +90,9 @@ export class TestLibDummyContract extends BaseContract {
|
||||
if (defaultBlock !== undefined) {
|
||||
assert.isBlockParam('defaultBlock', defaultBlock);
|
||||
}
|
||||
const self = (this as any) as TestLibDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('publicAddOne(uint256)', [x]);
|
||||
const self = this as any as TestLibDummyContract;
|
||||
const encodedData = self._strictEncodeArguments('publicAddOne(uint256)', [x
|
||||
]);
|
||||
const callDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{
|
||||
to: self.address,
|
||||
@ -82,10 +105,20 @@ export class TestLibDummyContract extends BaseContract {
|
||||
BaseContract._throwIfRevertWithReasonCallResult(rawCallResult);
|
||||
const abiEncoder = self._lookupAbiEncoder('publicAddOne(uint256)');
|
||||
// tslint:disable boolean-naming
|
||||
const result = abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
|
||||
const result = abiEncoder.strictDecodeReturnValue<BigNumber
|
||||
>(rawCallResult);
|
||||
// tslint:enable boolean-naming
|
||||
return result;
|
||||
},
|
||||
getABIEncodedTransactionData(
|
||||
x: BigNumber,
|
||||
): string {
|
||||
assert.isBigNumber('x', x);
|
||||
const self = this as any as TestLibDummyContract;
|
||||
const abiEncodedTransactionData = self._strictEncodeArguments('publicAddOne(uint256)', [x
|
||||
]);
|
||||
return abiEncodedTransactionData;
|
||||
},
|
||||
};
|
||||
public static async deployFrom0xArtifactAsync(
|
||||
artifact: ContractArtifact | SimpleContractArtifact,
|
||||
@ -103,7 +136,7 @@ export class TestLibDummyContract extends BaseContract {
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const bytecode = artifact.compilerOutput.evm.bytecode.object;
|
||||
const abi = artifact.compilerOutput.abi;
|
||||
return TestLibDummyContract.deployAsync(bytecode, abi, provider, txDefaults);
|
||||
return TestLibDummyContract.deployAsync(bytecode, abi, provider, txDefaults, );
|
||||
}
|
||||
public static async deployAsync(
|
||||
bytecode: string,
|
||||
@ -119,13 +152,17 @@ export class TestLibDummyContract extends BaseContract {
|
||||
]);
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
const constructorAbi = BaseContract._lookupConstructorAbi(abi);
|
||||
[] = BaseContract._formatABIDataItemList(constructorAbi.inputs, [], BaseContract._bigNumberToString);
|
||||
[] = BaseContract._formatABIDataItemList(
|
||||
constructorAbi.inputs,
|
||||
[],
|
||||
BaseContract._bigNumberToString,
|
||||
);
|
||||
const iface = new ethers.utils.Interface(abi);
|
||||
const deployInfo = iface.deployFunction;
|
||||
const txData = deployInfo.encode(bytecode, []);
|
||||
const web3Wrapper = new Web3Wrapper(provider);
|
||||
const txDataWithDefaults = await BaseContract._applyDefaultsToTxDataAsync(
|
||||
{ data: txData },
|
||||
{data: txData},
|
||||
txDefaults,
|
||||
web3Wrapper.estimateGasAsync.bind(web3Wrapper),
|
||||
);
|
||||
@ -133,12 +170,7 @@ export class TestLibDummyContract extends BaseContract {
|
||||
logUtils.log(`transactionHash: ${txHash}`);
|
||||
const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
|
||||
logUtils.log(`TestLibDummy successfully deployed at ${txReceipt.contractAddress}`);
|
||||
const contractInstance = new TestLibDummyContract(
|
||||
abi,
|
||||
txReceipt.contractAddress as string,
|
||||
provider,
|
||||
txDefaults,
|
||||
);
|
||||
const contractInstance = new TestLibDummyContract(abi, txReceipt.contractAddress as string, provider, txDefaults);
|
||||
contractInstance.constructorArgs = [];
|
||||
return contractInstance;
|
||||
}
|
@ -1,14 +1,16 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"extends": "../../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"resolveJsonModule": true,
|
||||
"outDir": "lib",
|
||||
"outDir": "./output/lib",
|
||||
"rootDir": "."
|
||||
},
|
||||
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
|
||||
"files": [
|
||||
"./generated-artifacts/AbiGenDummy.json",
|
||||
"./generated-artifacts/LibDummy.json",
|
||||
"./generated-artifacts/TestLibDummy.json"
|
||||
"./generated-artifacts/TestLibDummy.json",
|
||||
"./output/src/abi_gen_dummy.ts",
|
||||
"./output/src/lib_dummy.ts",
|
||||
"./output/src/test_lib_dummy.ts"
|
||||
]
|
||||
}
|
||||
|
@ -4,6 +4,11 @@
|
||||
"outDir": "lib",
|
||||
"rootDir": "."
|
||||
},
|
||||
"exclude": ["./test/generated-test/**/*"],
|
||||
"exclude": [
|
||||
"./test/generated-test/**/*",
|
||||
"./src/artifacts.ts",
|
||||
"./src/wrappers.ts",
|
||||
"prior two elements refer to code generated by contracts-gen for test fixture contracts"
|
||||
],
|
||||
"include": ["./src/**/*", "./test/*"]
|
||||
}
|
||||
|
@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "2.1.3",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Made most fields in DevdocOutput optional, as they may not all be present just because devdoc is",
|
||||
"pr": 1878
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"version": "2.1.2",
|
||||
"changes": [
|
||||
|
BIN
packages/pipeline/pipeline.env.gpg
Normal file
BIN
packages/pipeline/pipeline.env.gpg
Normal file
Binary file not shown.
11
packages/python-contract-wrappers/CHANGELOG.json
Normal file
11
packages/python-contract-wrappers/CHANGELOG.json
Normal file
@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Initial commit. Functionality tested for ERC20Token wrapper",
|
||||
"pr": 1878
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
41
packages/python-contract-wrappers/README.md
Normal file
41
packages/python-contract-wrappers/README.md
Normal file
@ -0,0 +1,41 @@
|
||||
## @0x/python-contract-wrappers
|
||||
|
||||
Python wrappers around the 0x smart contracts, generated using @0x/abi-gen.
|
||||
|
||||
The code generated by this package's `build` script is consumed by
|
||||
`../../python-packages/contract_wrappers/setup.py`'s `pre_install` command.
|
||||
The code generated by this package should not be used directly.
|
||||
|
||||
## Contributing
|
||||
|
||||
We welcome improvements and fixes from the wider community! To report bugs within this package, please create an issue in this repository.
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Install dependencies
|
||||
|
||||
If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them:
|
||||
|
||||
```bash
|
||||
yarn config set workspaces-experimental true
|
||||
```
|
||||
|
||||
Then install dependencies
|
||||
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory:
|
||||
|
||||
```bash
|
||||
PKG=@0x/python-contract-wrappers yarn build
|
||||
```
|
||||
|
||||
### Clean
|
||||
|
||||
```bash
|
||||
yarn clean
|
||||
```
|
34
packages/python-contract-wrappers/package.json
Normal file
34
packages/python-contract-wrappers/package.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "@0x/python-contract-wrappers",
|
||||
"version": "1.0.0",
|
||||
"engines": {
|
||||
"node": ">=6.12"
|
||||
},
|
||||
"private": true,
|
||||
"description": "Python wrappers for 0x smart contracts, generated via abi-gen",
|
||||
"scripts": {
|
||||
"generate": "abi-gen --abis ${npm_package_config_abis} --template ../abi-gen-templates/Python/contract.handlebars --partials '../abi-gen-templates/Python/partials/**/*.handlebars' --output generated --language Python",
|
||||
"build": "yarn generate",
|
||||
"build:ci": "yarn build",
|
||||
"clean": "shx rm -rf generated"
|
||||
},
|
||||
"config": {
|
||||
"abis": "../contract-artifacts/artifacts/ERC20Token.json"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/0xProject/0x-monorepo.git"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/0xProject/0x-monorepo/issues"
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/packages/python-contract-wrappers/README.md",
|
||||
"devDependencies": {
|
||||
"@0x/abi-gen": "^2.0.10",
|
||||
"shx": "^0.2.2"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "restricted"
|
||||
}
|
||||
}
|
@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "2.0.13",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Confirm devdoc components exist before using them",
|
||||
"pr": 1878
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1558712885,
|
||||
"version": "2.0.12",
|
||||
|
1
packages/typescript-typings/types/cli-format/index.d.ts
vendored
Normal file
1
packages/typescript-typings/types/cli-format/index.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
declare module 'cli-format';
|
@ -16,6 +16,12 @@ We welcome improvements and fixes from the wider community! To report bugs withi
|
||||
|
||||
Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started.
|
||||
|
||||
### Pull in artifacts from TypeScript build environment
|
||||
|
||||
```bash
|
||||
./setup.py pre_install
|
||||
```
|
||||
|
||||
### Install Code and Dependencies
|
||||
|
||||
```bash
|
||||
|
@ -3,7 +3,7 @@
|
||||
"""setuptools module for contract_artifacts package."""
|
||||
|
||||
import subprocess # nosec
|
||||
from shutil import rmtree
|
||||
from shutil import copytree, rmtree
|
||||
from os import environ, path
|
||||
from sys import argv
|
||||
|
||||
@ -13,6 +13,35 @@ 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 artifacts."""
|
||||
|
||||
description = "Pull in the artifacts that live in the TypeScript package."
|
||||
|
||||
def run(self):
|
||||
"""Copy files from TS build area to local src, & `black` them."""
|
||||
pkgdir = path.dirname(path.realpath(argv[0]))
|
||||
rmtree(
|
||||
path.join(
|
||||
pkgdir, "src", "zero_ex", "contract_artifacts", "artifacts"
|
||||
),
|
||||
ignore_errors=True,
|
||||
)
|
||||
copytree(
|
||||
path.join(
|
||||
pkgdir,
|
||||
"..",
|
||||
"..",
|
||||
"packages",
|
||||
"contract-artifacts",
|
||||
"artifacts",
|
||||
),
|
||||
path.join(
|
||||
pkgdir, "src", "zero_ex", "contract_artifacts", "artifacts"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class LintCommand(distutils.command.build_py.build_py):
|
||||
"""Custom setuptools command class for running linters."""
|
||||
|
||||
@ -138,6 +167,7 @@ setup(
|
||||
author="F. Eugene Aumson",
|
||||
author_email="feuGeneA@users.noreply.github.com",
|
||||
cmdclass={
|
||||
"pre_install": PreInstallCommand,
|
||||
"clean": CleanCommandExtension,
|
||||
"lint": LintCommand,
|
||||
"test": TestCommandExtension,
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,54 +0,0 @@
|
||||
{
|
||||
"schemaVersion": "2.0.0",
|
||||
"contractName": "CoordinatorRegistry",
|
||||
"compilerOutput": {
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [{ "name": "coordinatorEndpoint", "type": "string" }],
|
||||
"name": "setCoordinatorEndpoint",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [{ "name": "coordinatorOperator", "type": "address" }],
|
||||
"name": "getCoordinatorEndpoint",
|
||||
"outputs": [{ "name": "coordinatorEndpoint", "type": "string" }],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{ "inputs": [], "payable": false, "stateMutability": "nonpayable", "type": "constructor" },
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{ "indexed": false, "name": "coordinatorOperator", "type": "address" },
|
||||
{ "indexed": false, "name": "coordinatorEndpoint", "type": "string" }
|
||||
],
|
||||
"name": "CoordinatorEndpointSet",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"devdoc": {
|
||||
"methods": {
|
||||
"getCoordinatorEndpoint(address)": {
|
||||
"details": "Gets the endpoint for a Coordinator.",
|
||||
"params": { "coordinatorOperator": "operator of the Coordinator endpoint." }
|
||||
},
|
||||
"setCoordinatorEndpoint(string)": {
|
||||
"details": "Called by a Coordinator operator to set the endpoint of their Coordinator.",
|
||||
"params": { "coordinatorEndpoint": "endpoint of the Coordinator." }
|
||||
}
|
||||
}
|
||||
},
|
||||
"evm": {
|
||||
"bytecode": {
|
||||
"object": "0x608060405234801561001057600080fd5b506104b5806100206000396000f3fe608060405234801561001057600080fd5b5060043610610052577c010000000000000000000000000000000000000000000000000000000060003504635b2388be81146100575780636c90fedb1461006c575b600080fd5b61006a6100653660046102ff565b610095565b005b61007f61007a3660046102d9565b6100f0565b60405161008c91906103d8565b60405180910390f35b3360008181526020819052604090206100af9084846101c4565b507fd060052768902f3eecb84b8eae9d3a2608a1a9e60811a33968b46b8d552f266e8184846040516100e3939291906103ae565b60405180910390a1505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602081815260409182902080548351601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001861615020190931692909204918201849004840281018401909452808452606093928301828280156101b85780601f1061018d576101008083540402835291602001916101b8565b820191906000526020600020905b81548152906001019060200180831161019b57829003601f168201915b50505050509050919050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610223578280017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00823516178555610250565b82800160010185558215610250579182015b82811115610250578235825591602001919060010190610235565b5061025c929150610260565b5090565b61027a91905b8082111561025c5760008155600101610266565b90565b600061028982356103ed565b9392505050565b600080601f830184136102a257600080fd5b50813567ffffffffffffffff8111156102ba57600080fd5b6020830191508360018202830111156102d257600080fd5b9250929050565b6000602082840312156102eb57600080fd5b60006102f7848461027d565b949350505050565b6000806020838503121561031257600080fd5b823567ffffffffffffffff81111561032957600080fd5b61033585828601610290565b92509250509250929050565b61034a816103ed565b82525050565b6000828452602084019350610366838584610417565b61036f83610453565b9093019392505050565b6000610384826103e9565b808452610398816020860160208601610423565b6103a181610453565b9093016020019392505050565b604081016103bc8286610341565b81810360208301526103cf818486610350565b95945050505050565b602080825281016102898184610379565b5190565b60006103f8826103fe565b92915050565b73ffffffffffffffffffffffffffffffffffffffff1690565b82818337506000910152565b60005b8381101561043e578181015183820152602001610426565b8381111561044d576000848401525b50505050565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169056fea265627a7a72305820d8fc8bc6ec7167e671f9f87937212d93c49d5fbe171bbdfa06c846e5ac76151b6c6578706572696d656e74616cf50037"
|
||||
}
|
||||
}
|
||||
},
|
||||
"networks": {}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,134 +0,0 @@
|
||||
{
|
||||
"schemaVersion": "2.0.0",
|
||||
"contractName": "ERC20Token",
|
||||
"compilerOutput": {
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [{ "name": "_spender", "type": "address" }, { "name": "_value", "type": "uint256" }],
|
||||
"name": "approve",
|
||||
"outputs": [{ "name": "", "type": "bool" }],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [{ "name": "", "type": "uint256" }],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{ "name": "_from", "type": "address" },
|
||||
{ "name": "_to", "type": "address" },
|
||||
{ "name": "_value", "type": "uint256" }
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [{ "name": "", "type": "bool" }],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [{ "name": "_owner", "type": "address" }],
|
||||
"name": "balanceOf",
|
||||
"outputs": [{ "name": "", "type": "uint256" }],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [{ "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" }],
|
||||
"name": "transfer",
|
||||
"outputs": [{ "name": "", "type": "bool" }],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [{ "name": "_owner", "type": "address" }, { "name": "_spender", "type": "address" }],
|
||||
"name": "allowance",
|
||||
"outputs": [{ "name": "", "type": "uint256" }],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{ "indexed": true, "name": "_from", "type": "address" },
|
||||
{ "indexed": true, "name": "_to", "type": "address" },
|
||||
{ "indexed": false, "name": "_value", "type": "uint256" }
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{ "indexed": true, "name": "_owner", "type": "address" },
|
||||
{ "indexed": true, "name": "_spender", "type": "address" },
|
||||
{ "indexed": false, "name": "_value", "type": "uint256" }
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"devdoc": {
|
||||
"methods": {
|
||||
"allowance(address,address)": {
|
||||
"params": {
|
||||
"_owner": "The address of the account owning tokens",
|
||||
"_spender": "The address of the account able to transfer the tokens"
|
||||
},
|
||||
"return": "Amount of remaining tokens allowed to spent"
|
||||
},
|
||||
"approve(address,uint256)": {
|
||||
"details": "`msg.sender` approves `_spender` to spend `_value` tokens",
|
||||
"params": {
|
||||
"_spender": "The address of the account able to transfer the tokens",
|
||||
"_value": "The amount of wei to be approved for transfer"
|
||||
},
|
||||
"return": "Always true if the call has enough gas to complete execution"
|
||||
},
|
||||
"balanceOf(address)": {
|
||||
"details": "Query the balance of owner",
|
||||
"params": { "_owner": "The address from which the balance will be retrieved" },
|
||||
"return": "Balance of owner"
|
||||
},
|
||||
"totalSupply()": { "details": "Query total supply of token", "return": "Total supply of token" },
|
||||
"transfer(address,uint256)": {
|
||||
"details": "send `value` token to `to` from `msg.sender`",
|
||||
"params": {
|
||||
"_to": "The address of the recipient",
|
||||
"_value": "The amount of token to be transferred"
|
||||
},
|
||||
"return": "True if transfer was successful"
|
||||
},
|
||||
"transferFrom(address,address,uint256)": {
|
||||
"details": "send `value` token to `to` from `from` on the condition it is approved by `from`",
|
||||
"params": {
|
||||
"_from": "The address of the sender",
|
||||
"_to": "The address of the recipient",
|
||||
"_value": "The amount of token to be transferred"
|
||||
},
|
||||
"return": "True if transfer was successful"
|
||||
}
|
||||
}
|
||||
},
|
||||
"evm": {
|
||||
"bytecode": {
|
||||
"object": "0x608060405234801561001057600080fd5b506106a0806100206000396000f3006080604052600436106100775763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663095ea7b3811461007c57806318160ddd146100c157806323b872dd146100e857806370a082311461011f578063a9059cbb1461014d578063dd62ed3e1461017e575b600080fd5b34801561008857600080fd5b506100ad73ffffffffffffffffffffffffffffffffffffffff600435166024356101b2565b604080519115158252519081900360200190f35b3480156100cd57600080fd5b506100d6610225565b60408051918252519081900360200190f35b3480156100f457600080fd5b506100ad73ffffffffffffffffffffffffffffffffffffffff6004358116906024351660443561022b565b34801561012b57600080fd5b506100d673ffffffffffffffffffffffffffffffffffffffff60043516610487565b34801561015957600080fd5b506100ad73ffffffffffffffffffffffffffffffffffffffff600435166024356104af565b34801561018a57600080fd5b506100d673ffffffffffffffffffffffffffffffffffffffff6004358116906024351661063c565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b60025490565b73ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260408120548211156102bf57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f45524332305f494e53554646494349454e545f42414c414e4345000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8416600090815260016020908152604080832033845290915290205482111561035e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f45524332305f494e53554646494349454e545f414c4c4f57414e434500000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205482810110156103f457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f55494e543235365f4f564552464c4f5700000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff80841660008181526020818152604080832080548801905593881680835284832080548890039055600182528483203384528252918490208054879003905583518681529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35060019392505050565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b3360009081526020819052604081205482111561052d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f45524332305f494e53554646494349454e545f42414c414e4345000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205482810110156105c357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f55494e543235365f4f564552464c4f5700000000000000000000000000000000604482015290519081900360640190fd5b336000818152602081815260408083208054879003905573ffffffffffffffffffffffffffffffffffffffff871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600192915050565b73ffffffffffffffffffffffffffffffffffffffff9182166000908152600160209081526040808320939094168252919091522054905600a165627a7a72305820203a592c9390a8a005821d7dffa1c27ae97bf827d8ef17cfee3a8a70776b22d90029"
|
||||
}
|
||||
}
|
||||
},
|
||||
"networks": {}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,32 +0,0 @@
|
||||
{
|
||||
"schemaVersion": "2.0.0",
|
||||
"contractName": "EthBalanceChecker",
|
||||
"compilerOutput": {
|
||||
"abi": [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [{ "name": "addresses", "type": "address[]" }],
|
||||
"name": "getEthBalances",
|
||||
"outputs": [{ "name": "", "type": "uint256[]" }],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
"devdoc": {
|
||||
"methods": {
|
||||
"getEthBalances(address[])": {
|
||||
"details": "Batch fetches ETH balances",
|
||||
"params": { "addresses": "Array of addresses." },
|
||||
"return": "Array of ETH balances."
|
||||
}
|
||||
}
|
||||
},
|
||||
"evm": {
|
||||
"bytecode": {
|
||||
"object": "0x608060405234801561001057600080fd5b506101e5806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063a0901e5114610030575b600080fd5b6100d36004803603602081101561004657600080fd5b81019060208101813564010000000081111561006157600080fd5b82018360208201111561007357600080fd5b8035906020019184602083028401116401000000008311171561009557600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550610123945050505050565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561010f5781810151838201526020016100f7565b505050509050019250505060405180910390f35b6060808251604051908082528060200260200182016040528015610151578160200160208202803883390190505b50905060005b835181146101a95783818151811061016b57fe5b602002602001015173ffffffffffffffffffffffffffffffffffffffff163182828151811061019657fe5b6020908102919091010152600101610157565b509291505056fea265627a7a72305820c934dc478ccdc0f8a6d0fb6135610c21efcb23a2fd5075c6d2c4891b449b70f964736f6c63430005090032"
|
||||
}
|
||||
}
|
||||
},
|
||||
"networks": {}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,114 +0,0 @@
|
||||
{
|
||||
"schemaVersion": "2.0.0",
|
||||
"contractName": "IAssetProxy",
|
||||
"compilerOutput": {
|
||||
"abi": [
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [{ "name": "target", "type": "address" }],
|
||||
"name": "addAuthorizedAddress",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [{ "name": "target", "type": "address" }],
|
||||
"name": "removeAuthorizedAddress",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [{ "name": "target", "type": "address" }, { "name": "index", "type": "uint256" }],
|
||||
"name": "removeAuthorizedAddressAtIndex",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{ "name": "assetData", "type": "bytes" },
|
||||
{ "name": "from", "type": "address" },
|
||||
{ "name": "to", "type": "address" },
|
||||
{ "name": "amount", "type": "uint256" }
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getProxyId",
|
||||
"outputs": [{ "name": "", "type": "bytes4" }],
|
||||
"payable": false,
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "getAuthorizedAddresses",
|
||||
"outputs": [{ "name": "", "type": "address[]" }],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [{ "name": "newOwner", "type": "address" }],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
"devdoc": {
|
||||
"methods": {
|
||||
"addAuthorizedAddress(address)": {
|
||||
"details": "Authorizes an address.",
|
||||
"params": { "target": "Address to authorize." }
|
||||
},
|
||||
"getAuthorizedAddresses()": {
|
||||
"details": "Gets all authorized addresses.",
|
||||
"return": "Array of authorized addresses."
|
||||
},
|
||||
"getProxyId()": {
|
||||
"details": "Gets the proxy id associated with the proxy address.",
|
||||
"return": "Proxy id."
|
||||
},
|
||||
"removeAuthorizedAddress(address)": {
|
||||
"details": "Removes authorizion of an address.",
|
||||
"params": { "target": "Address to remove authorization from." }
|
||||
},
|
||||
"removeAuthorizedAddressAtIndex(address,uint256)": {
|
||||
"details": "Removes authorizion of an address.",
|
||||
"params": {
|
||||
"index": "Index of target in authorities array.",
|
||||
"target": "Address to remove authorization from."
|
||||
}
|
||||
},
|
||||
"transferFrom(bytes,address,address,uint256)": {
|
||||
"details": "Transfers assets. Either succeeds or throws.",
|
||||
"params": {
|
||||
"amount": "Amount of asset to transfer.",
|
||||
"assetData": "Byte array encoded for the respective asset proxy.",
|
||||
"from": "Address to transfer asset from.",
|
||||
"to": "Address to transfer asset to."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"evm": { "bytecode": { "object": "0x" } }
|
||||
},
|
||||
"networks": {}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
{
|
||||
"schemaVersion": "2.0.0",
|
||||
"contractName": "IValidator",
|
||||
"compilerOutput": {
|
||||
"abi": [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [
|
||||
{ "name": "hash", "type": "bytes32" },
|
||||
{ "name": "signerAddress", "type": "address" },
|
||||
{ "name": "signature", "type": "bytes" }
|
||||
],
|
||||
"name": "isValidSignature",
|
||||
"outputs": [{ "name": "isValid", "type": "bool" }],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
"devdoc": {
|
||||
"methods": {
|
||||
"isValidSignature(bytes32,address,bytes)": {
|
||||
"details": "Verifies that a signature is valid.",
|
||||
"params": {
|
||||
"hash": "Message hash that is signed.",
|
||||
"signature": "Proof of signing.",
|
||||
"signerAddress": "Address that should have signed the given hash."
|
||||
},
|
||||
"return": "Validity of order signature."
|
||||
}
|
||||
}
|
||||
},
|
||||
"evm": { "bytecode": { "object": "0x" } }
|
||||
},
|
||||
"networks": {}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
{
|
||||
"schemaVersion": "2.0.0",
|
||||
"contractName": "IWallet",
|
||||
"compilerOutput": {
|
||||
"abi": [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [{ "name": "hash", "type": "bytes32" }, { "name": "signature", "type": "bytes" }],
|
||||
"name": "isValidSignature",
|
||||
"outputs": [{ "name": "isValid", "type": "bool" }],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
],
|
||||
"devdoc": {
|
||||
"methods": {
|
||||
"isValidSignature(bytes32,bytes)": {
|
||||
"details": "Verifies that a signature is valid.",
|
||||
"params": { "hash": "Message hash that is signed.", "signature": "Proof of signing." },
|
||||
"return": "Validity of order signature."
|
||||
}
|
||||
}
|
||||
},
|
||||
"evm": { "bytecode": { "object": "0x" } }
|
||||
},
|
||||
"networks": {}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,157 +0,0 @@
|
||||
{
|
||||
"schemaVersion": "2.0.0",
|
||||
"contractName": "WETH9",
|
||||
"compilerOutput": {
|
||||
"abi": [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "name",
|
||||
"outputs": [{ "name": "", "type": "string" }],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [{ "name": "guy", "type": "address" }, { "name": "wad", "type": "uint256" }],
|
||||
"name": "approve",
|
||||
"outputs": [{ "name": "", "type": "bool" }],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [{ "name": "", "type": "uint256" }],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{ "name": "src", "type": "address" },
|
||||
{ "name": "dst", "type": "address" },
|
||||
{ "name": "wad", "type": "uint256" }
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [{ "name": "", "type": "bool" }],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [{ "name": "wad", "type": "uint256" }],
|
||||
"name": "withdraw",
|
||||
"outputs": [],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "decimals",
|
||||
"outputs": [{ "name": "", "type": "uint8" }],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [{ "name": "", "type": "address" }],
|
||||
"name": "balanceOf",
|
||||
"outputs": [{ "name": "", "type": "uint256" }],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "symbol",
|
||||
"outputs": [{ "name": "", "type": "string" }],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [{ "name": "dst", "type": "address" }, { "name": "wad", "type": "uint256" }],
|
||||
"name": "transfer",
|
||||
"outputs": [{ "name": "", "type": "bool" }],
|
||||
"payable": false,
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [],
|
||||
"name": "deposit",
|
||||
"outputs": [],
|
||||
"payable": true,
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [{ "name": "", "type": "address" }, { "name": "", "type": "address" }],
|
||||
"name": "allowance",
|
||||
"outputs": [{ "name": "", "type": "uint256" }],
|
||||
"payable": false,
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{ "payable": true, "stateMutability": "payable", "type": "fallback" },
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{ "indexed": true, "name": "_owner", "type": "address" },
|
||||
{ "indexed": true, "name": "_spender", "type": "address" },
|
||||
{ "indexed": false, "name": "_value", "type": "uint256" }
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{ "indexed": true, "name": "_from", "type": "address" },
|
||||
{ "indexed": true, "name": "_to", "type": "address" },
|
||||
{ "indexed": false, "name": "_value", "type": "uint256" }
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{ "indexed": true, "name": "_owner", "type": "address" },
|
||||
{ "indexed": false, "name": "_value", "type": "uint256" }
|
||||
],
|
||||
"name": "Deposit",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{ "indexed": true, "name": "_owner", "type": "address" },
|
||||
{ "indexed": false, "name": "_value", "type": "uint256" }
|
||||
],
|
||||
"name": "Withdrawal",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"devdoc": { "methods": {} },
|
||||
"evm": {
|
||||
"bytecode": {
|
||||
"object": "0x60c0604052600d60808190527f577261707065642045746865720000000000000000000000000000000000000060a090815261003e91600091906100a3565b506040805180820190915260048082527f57455448000000000000000000000000000000000000000000000000000000006020909201918252610083916001916100a3565b506002805460ff1916601217905534801561009d57600080fd5b5061013e565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100e457805160ff1916838001178555610111565b82800160010185558215610111579182015b828111156101115782518255916020019190600101906100f6565b5061011d929150610121565b5090565b61013b91905b8082111561011d5760008155600101610127565b90565b6107688061014d6000396000f3006080604052600436106100ae5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100b8578063095ea7b31461014257806318160ddd1461018757806323b872dd146101ae5780632e1a7d4d146101e5578063313ce567146101fd57806370a082311461022857806395d89b4114610256578063a9059cbb1461026b578063d0e30db0146100ae578063dd62ed3e1461029c575b6100b66102d0565b005b3480156100c457600080fd5b506100cd61031f565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101075781810151838201526020016100ef565b50505050905090810190601f1680156101345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561014e57600080fd5b5061017373ffffffffffffffffffffffffffffffffffffffff600435166024356103cb565b604080519115158252519081900360200190f35b34801561019357600080fd5b5061019c61043e565b60408051918252519081900360200190f35b3480156101ba57600080fd5b5061017373ffffffffffffffffffffffffffffffffffffffff60043581169060243516604435610443565b3480156101f157600080fd5b506100b66004356105e3565b34801561020957600080fd5b50610212610678565b6040805160ff9092168252519081900360200190f35b34801561023457600080fd5b5061019c73ffffffffffffffffffffffffffffffffffffffff60043516610681565b34801561026257600080fd5b506100cd610693565b34801561027757600080fd5b5061017373ffffffffffffffffffffffffffffffffffffffff6004351660243561070b565b3480156102a857600080fd5b5061019c73ffffffffffffffffffffffffffffffffffffffff6004358116906024351661071f565b33600081815260036020908152604091829020805434908101909155825190815291517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9281900390910190a2565b6000805460408051602060026001851615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156103c35780601f10610398576101008083540402835291602001916103c3565b820191906000526020600020905b8154815290600101906020018083116103a657829003601f168201915b505050505081565b33600081815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b303190565b73ffffffffffffffffffffffffffffffffffffffff831660009081526003602052604081205482111561047557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841633148015906104eb575073ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105655773ffffffffffffffffffffffffffffffffffffffff8416600090815260046020908152604080832033845290915290205482111561052d57600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526004602090815260408083203384529091529020805483900390555b73ffffffffffffffffffffffffffffffffffffffff808516600081815260036020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b336000908152600360205260409020548111156105ff57600080fd5b33600081815260036020526040808220805485900390555183156108fc0291849190818181858888f1935050505015801561063e573d6000803e3d6000fd5b5060408051828152905133917f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65919081900360200190a250565b60025460ff1681565b60036020526000908152604090205481565b60018054604080516020600284861615610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190941693909304601f810184900484028201840190925281815292918301828280156103c35780601f10610398576101008083540402835291602001916103c3565b6000610718338484610443565b9392505050565b6004602090815260009283526040808420909152908252902054815600a165627a7a72305820228981f11f47ad9630080069b0a81423fcfba5aa8e0f478a579c4bc080ba7e820029"
|
||||
}
|
||||
}
|
||||
},
|
||||
"networks": {}
|
||||
}
|
@ -1,124 +0,0 @@
|
||||
{
|
||||
"schemaVersion": "2.0.0",
|
||||
"contractName": "ZRXToken",
|
||||
"compilerOutput": {
|
||||
"abi": [
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "name",
|
||||
"outputs": [{ "name": "", "type": "string" }],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [{ "name": "_spender", "type": "address" }, { "name": "_value", "type": "uint256" }],
|
||||
"name": "approve",
|
||||
"outputs": [{ "name": "", "type": "bool" }],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "totalSupply",
|
||||
"outputs": [{ "name": "", "type": "uint256" }],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [
|
||||
{ "name": "_from", "type": "address" },
|
||||
{ "name": "_to", "type": "address" },
|
||||
{ "name": "_value", "type": "uint256" }
|
||||
],
|
||||
"name": "transferFrom",
|
||||
"outputs": [{ "name": "", "type": "bool" }],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "decimals",
|
||||
"outputs": [{ "name": "", "type": "uint8" }],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [{ "name": "_owner", "type": "address" }],
|
||||
"name": "balanceOf",
|
||||
"outputs": [{ "name": "", "type": "uint256" }],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [],
|
||||
"name": "symbol",
|
||||
"outputs": [{ "name": "", "type": "string" }],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": false,
|
||||
"inputs": [{ "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" }],
|
||||
"name": "transfer",
|
||||
"outputs": [{ "name": "", "type": "bool" }],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"constant": true,
|
||||
"inputs": [{ "name": "_owner", "type": "address" }, { "name": "_spender", "type": "address" }],
|
||||
"name": "allowance",
|
||||
"outputs": [{ "name": "", "type": "uint256" }],
|
||||
"payable": false,
|
||||
"type": "function"
|
||||
},
|
||||
{ "inputs": [], "payable": false, "type": "constructor" },
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{ "indexed": true, "name": "_from", "type": "address" },
|
||||
{ "indexed": true, "name": "_to", "type": "address" },
|
||||
{ "indexed": false, "name": "_value", "type": "uint256" }
|
||||
],
|
||||
"name": "Transfer",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{ "indexed": true, "name": "_owner", "type": "address" },
|
||||
{ "indexed": true, "name": "_spender", "type": "address" },
|
||||
{ "indexed": false, "name": "_value", "type": "uint256" }
|
||||
],
|
||||
"name": "Approval",
|
||||
"type": "event"
|
||||
}
|
||||
],
|
||||
"devdoc": {
|
||||
"methods": {
|
||||
"transferFrom(address,address,uint256)": {
|
||||
"details": "ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance.",
|
||||
"params": {
|
||||
"_from": "Address to transfer from.",
|
||||
"_to": "Address to transfer to.",
|
||||
"_value": "Amount to transfer."
|
||||
},
|
||||
"return": "Success of transfer."
|
||||
}
|
||||
}
|
||||
},
|
||||
"evm": {
|
||||
"bytecode": {
|
||||
"object": "0x60606040526b033b2e3c9fd0803ce8000000600355341561001c57fe5b5b600354600160a060020a0333166000908152602081905260409020555b5b61078d8061004a6000396000f300606060405236156100965763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde038114610098578063095ea7b31461014657806318160ddd1461018657806323b872dd146101a8578063313ce567146101ee57806370a082311461021457806395d89b411461024f578063a9059cbb146102fd578063dd62ed3e1461033d575bfe5b34156100a057fe5b6100a861037e565b60408051602080825283518183015283519192839290830191850190808383821561010c575b80518252602083111561010c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016100ce565b505050905090810190601f1680156101385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014e57fe5b61017273ffffffffffffffffffffffffffffffffffffffff600435166024356103b5565b604080519115158252519081900360200190f35b341561018e57fe5b61019661042d565b60408051918252519081900360200190f35b34156101b057fe5b61017273ffffffffffffffffffffffffffffffffffffffff60043581169060243516604435610433565b604080519115158252519081900360200190f35b34156101f657fe5b6101fe6105d4565b6040805160ff9092168252519081900360200190f35b341561021c57fe5b61019673ffffffffffffffffffffffffffffffffffffffff600435166105d9565b60408051918252519081900360200190f35b341561025757fe5b6100a8610605565b60408051602080825283518183015283519192839290830191850190808383821561010c575b80518252602083111561010c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016100ce565b505050905090810190601f1680156101385780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561030557fe5b61017273ffffffffffffffffffffffffffffffffffffffff6004351660243561063c565b604080519115158252519081900360200190f35b341561034557fe5b61019673ffffffffffffffffffffffffffffffffffffffff60043581169060243516610727565b60408051918252519081900360200190f35b60408051808201909152601181527f30782050726f746f636f6c20546f6b656e000000000000000000000000000000602082015281565b73ffffffffffffffffffffffffffffffffffffffff338116600081815260016020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60035481565b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832033909516835293815283822054928252819052918220548390108015906104835750828110155b80156104b6575073ffffffffffffffffffffffffffffffffffffffff841660009081526020819052604090205483810110155b156105c65773ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220805487019055918716815220805484900390557fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156105585773ffffffffffffffffffffffffffffffffffffffff808616600090815260016020908152604080832033909416835292905220805484900390555b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a3600191506105cb565b600091505b5b509392505050565b601281565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602081905260409020545b919050565b60408051808201909152600381527f5a52580000000000000000000000000000000000000000000000000000000000602082015281565b73ffffffffffffffffffffffffffffffffffffffff3316600090815260208190526040812054829010801590610699575073ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205482810110155b156107185773ffffffffffffffffffffffffffffffffffffffff33811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a3506001610427565b506000610427565b5b92915050565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600160209081526040808320938516835292905220545b929150505600a165627a7a723058201b5b70cf82a73dec658c2e60ab9a0f8e2ba01a74b66a6f5b0402f56d2ea0ffcf0029"
|
||||
}
|
||||
}
|
||||
},
|
||||
"networks": {}
|
||||
}
|
@ -3,4 +3,4 @@ disable=C0330,line-too-long,fixme,too-few-public-methods,too-many-ancestors
|
||||
# C0330 is "bad hanging indent". we use indents per `black`.
|
||||
|
||||
[SIMILARITIES]
|
||||
min-similarity-lines=6
|
||||
min-similarity-lines=12
|
||||
|
@ -3,10 +3,11 @@
|
||||
"""setuptools module for contract_wrappers package."""
|
||||
|
||||
import subprocess # nosec
|
||||
from shutil import rmtree
|
||||
from shutil import copy, rmtree
|
||||
from os import environ, path
|
||||
from pathlib import Path
|
||||
from sys import argv
|
||||
from importlib.util import find_spec
|
||||
|
||||
from distutils.command.clean import clean
|
||||
import distutils.command.build_py
|
||||
@ -14,6 +15,38 @@ from setuptools import find_packages, setup
|
||||
from setuptools.command.test import test as TestCommand
|
||||
|
||||
|
||||
BLACK_COMMAND = "black --line-length 79"
|
||||
|
||||
|
||||
class PreInstallCommand(distutils.command.build_py.build_py):
|
||||
"""Custom setuptools command class for pulling in generated code."""
|
||||
|
||||
description = "Pull in code generated by TypeScript"
|
||||
|
||||
def run(self):
|
||||
"""Copy files from TS build area to local src, & `black` them."""
|
||||
pkgdir = path.dirname(path.realpath(argv[0]))
|
||||
copy(
|
||||
path.join(
|
||||
pkgdir,
|
||||
"..",
|
||||
"..",
|
||||
"packages",
|
||||
"python-contract-wrappers",
|
||||
"generated",
|
||||
"erc20_token.py",
|
||||
),
|
||||
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()
|
||||
)
|
||||
|
||||
|
||||
class TestCommandExtension(TestCommand):
|
||||
"""Run pytest tests."""
|
||||
|
||||
@ -33,7 +66,7 @@ class LintCommand(distutils.command.build_py.build_py):
|
||||
"""Run linter shell commands."""
|
||||
lint_commands = [
|
||||
# formatter:
|
||||
"black --line-length 79 --check --diff src test setup.py".split(),
|
||||
(BLACK_COMMAND + " --check --diff src test setup.py").split(),
|
||||
# style guide checker (formerly pep8):
|
||||
"pycodestyle src test setup.py".split(),
|
||||
# docstring style checker:
|
||||
@ -152,6 +185,7 @@ setup(
|
||||
author_email="feuGeneA@users.noreply.github.com",
|
||||
cmdclass={
|
||||
"clean": CleanCommandExtension,
|
||||
"pre_install": PreInstallCommand,
|
||||
"lint": LintCommand,
|
||||
"test": TestCommandExtension,
|
||||
"test_publish": TestPublishCommand,
|
||||
|
@ -91,19 +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
|
||||
>>> erc20_wrapper = ERC20Token(ganache)
|
||||
>>> zrx_wrapper = ERC20Token(
|
||||
... provider=ganache,
|
||||
... contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].zrx_token,
|
||||
... )
|
||||
>>> weth_wrapper = ERC20Token(
|
||||
... provider=ganache,
|
||||
... contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].ether_token,
|
||||
... )
|
||||
|
||||
>>> erc20_proxy_addr = NETWORK_TO_ADDRESSES[NetworkId.GANACHE].erc20_proxy
|
||||
|
||||
>>> tx = erc20_wrapper.approve(
|
||||
... zrx_address,
|
||||
>>> tx = zrx_wrapper.approve(
|
||||
... erc20_proxy_addr,
|
||||
... to_wei(100, 'ether'),
|
||||
... tx_params=TxParams(from_=maker_address),
|
||||
... )
|
||||
|
||||
>>> tx = erc20_wrapper.approve(
|
||||
... weth_address,
|
||||
>>> tx = weth_wrapper.approve(
|
||||
... erc20_proxy_addr,
|
||||
... to_wei(100, 'ether'),
|
||||
... tx_params=TxParams(from_=taker_address),
|
||||
@ -157,7 +162,10 @@ fill. This example fills the order completely, but partial fills are possible
|
||||
too.
|
||||
|
||||
>>> from zero_ex.contract_wrappers import Exchange
|
||||
>>> exchange_contract = Exchange(ganache)
|
||||
>>> exchange_contract = Exchange(
|
||||
... provider=ganache,
|
||||
... contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].exchange,
|
||||
... )
|
||||
>>> tx_hash = exchange_contract.fill_order(
|
||||
... order=order,
|
||||
... taker_amount=order["takerAssetAmount"],
|
||||
@ -288,5 +296,5 @@ HexBytes('0x...')
|
||||
"""
|
||||
|
||||
from .tx_params import TxParams
|
||||
from .erc20_wrapper import ERC20Token
|
||||
from .erc20_token import ERC20Token
|
||||
from .exchange_wrapper import Exchange
|
||||
|
@ -15,24 +15,28 @@ class BaseContractWrapper:
|
||||
It provides functionality for instantiating a contract instance,
|
||||
calling view functions, and calling functions which require
|
||||
transactions.
|
||||
|
||||
:param provider: instance of :class:`web3.providers.base.BaseProvider`
|
||||
:param account_address: default None, str of account address
|
||||
:param private_key: default None, str of private_key
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
account_address: str = None,
|
||||
contract_address: str,
|
||||
private_key: str = None,
|
||||
):
|
||||
"""Create an instance of BaseContractWrapper."""
|
||||
"""Create an instance of BaseContractWrapper.
|
||||
|
||||
:param provider: instance of :class:`web3.providers.base.BaseProvider`
|
||||
: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:.
|
||||
"""
|
||||
self._provider = provider
|
||||
self._account_address = account_address
|
||||
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(
|
||||
contract_address
|
||||
)
|
||||
|
||||
self._can_send_tx = False
|
||||
if self._web3_eth.defaultAccount or self._web3_eth.accounts:
|
||||
@ -98,7 +102,6 @@ class BaseContractWrapper:
|
||||
# pylint: disable=too-many-arguments
|
||||
def execute_method(
|
||||
self,
|
||||
address: str,
|
||||
abi: dict,
|
||||
method: str,
|
||||
args: Optional[Union[list, tuple]] = None,
|
||||
@ -107,7 +110,6 @@ class BaseContractWrapper:
|
||||
) -> str:
|
||||
"""Execute the method on a contract instance.
|
||||
|
||||
:param address: string of contract address
|
||||
:param abi: dict of contract ABI
|
||||
:param method: string name of method to call
|
||||
:param args: default None, list or tuple of arguments for the method
|
||||
@ -117,7 +119,9 @@ class BaseContractWrapper:
|
||||
|
||||
:returns: str of transaction hash
|
||||
"""
|
||||
contract_instance = self._contract_instance(address=address, abi=abi)
|
||||
contract_instance = self._contract_instance(
|
||||
address=self._contract_address, abi=abi
|
||||
)
|
||||
if args is None:
|
||||
args = []
|
||||
if hasattr(contract_instance.functions, method):
|
||||
@ -126,5 +130,7 @@ class BaseContractWrapper:
|
||||
func=func, tx_params=tx_params, view_only=view_only
|
||||
)
|
||||
raise Exception(
|
||||
"No method {} found on contract {}.".format(address, method)
|
||||
"No method {} found on contract {}.".format(
|
||||
self._contract_address, method
|
||||
)
|
||||
)
|
||||
|
@ -1,202 +0,0 @@
|
||||
"""Wrapper for Ethereum ERC20 Token smart contract."""
|
||||
|
||||
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_artifacts import abi_by_name
|
||||
|
||||
from ._base_contract_wrapper import BaseContractWrapper
|
||||
from .tx_params import TxParams
|
||||
|
||||
|
||||
class ERC20Token(BaseContractWrapper):
|
||||
"""Wrapper class for Ethereum ERC20 smart contract."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
account_address: str = None,
|
||||
private_key: str = None,
|
||||
):
|
||||
"""Get an instance of wrapper for ERC20 smart contract.
|
||||
|
||||
:param provider: instance of :class:`web3.providers.base.BaseProvider`
|
||||
"""
|
||||
super(ERC20Token, self).__init__(
|
||||
provider=provider,
|
||||
account_address=account_address,
|
||||
private_key=private_key,
|
||||
)
|
||||
|
||||
def _erc20(self, token_address):
|
||||
"""Get an instance of the ERC20 smart contract at a specific address.
|
||||
|
||||
:returns: ERC20 contract object
|
||||
"""
|
||||
return self._contract_instance(
|
||||
address=token_address, abi=abi_by_name("ERC20Token")
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def transfer(
|
||||
self,
|
||||
token_address: str,
|
||||
to_address: str,
|
||||
value: int,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
view_only: bool = False,
|
||||
) -> Union[HexBytes, bytes]:
|
||||
"""Transfer the balance from owner's account to another account.
|
||||
|
||||
:param value: integer amount to send
|
||||
:param tx_params: transaction parameters
|
||||
:param view_only: whether to use transact() or call()
|
||||
|
||||
:returns: transaction hash
|
||||
"""
|
||||
token_address = self._validate_and_checksum_address(token_address)
|
||||
to_address = self._validate_and_checksum_address(to_address)
|
||||
# safeguard against fractional inputs
|
||||
value = int(value)
|
||||
func = self._erc20(token_address).functions.transfer(to_address, value)
|
||||
return self._invoke_function_call(
|
||||
func=func, tx_params=tx_params, view_only=view_only
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def approve(
|
||||
self,
|
||||
token_address: str,
|
||||
spender_address: str,
|
||||
value: int,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
view_only: bool = False,
|
||||
) -> Union[HexBytes, bytes]:
|
||||
"""Approve an address to spend up to `value`:code: of your tokens.
|
||||
|
||||
:param value: amount of allowance
|
||||
:param tx_params: transaction options
|
||||
:param view_only: whether to use transact() or call()
|
||||
|
||||
:returns: transaction hash
|
||||
"""
|
||||
token_address = self._validate_and_checksum_address(token_address)
|
||||
spender_address = self._validate_and_checksum_address(spender_address)
|
||||
# safeguard against fractional inputs
|
||||
value = int(value)
|
||||
func = self._erc20(token_address).functions.approve(
|
||||
spender_address, value
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func, tx_params=tx_params, view_only=view_only
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def transfer_from(
|
||||
self,
|
||||
token_address: str,
|
||||
authorized_address: str,
|
||||
to_address: str,
|
||||
value: int,
|
||||
tx_params: Optional[TxParams] = None,
|
||||
view_only: bool = False,
|
||||
) -> Union[HexBytes, bytes]:
|
||||
"""Transfer tokens from `authorized_address`:code: to another address.
|
||||
|
||||
Note that the `authorized_address`:code: must have already called
|
||||
`approve`:code: for the `spender_address`:code:.
|
||||
|
||||
:param authorized_address: address you have been authorized to transfer
|
||||
tokens from
|
||||
:param value: amount to send
|
||||
:param tx_params: transaction parameters
|
||||
:param view_only: whether to use transact() or call()
|
||||
|
||||
:returns: transaction hash
|
||||
"""
|
||||
token_address = self._validate_and_checksum_address(token_address)
|
||||
authorized_address = self._validate_and_checksum_address(
|
||||
authorized_address
|
||||
)
|
||||
to_address = self._validate_and_checksum_address(to_address)
|
||||
# safeguard against fractional inputs
|
||||
value = int(value)
|
||||
func = self._erc20(token_address).functions.transferFrom(
|
||||
authorized_address, to_address, value
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func, tx_params=tx_params, view_only=view_only
|
||||
)
|
||||
|
||||
def total_supply(self, token_address: str) -> int:
|
||||
"""Get total supply of a given ERC20 Token.
|
||||
|
||||
:returns: amount of tokens
|
||||
"""
|
||||
token_address = self._validate_and_checksum_address(token_address)
|
||||
func = self._erc20(token_address).functions.totalSupply()
|
||||
return self._invoke_function_call(
|
||||
func=func, tx_params=None, view_only=True
|
||||
)
|
||||
|
||||
def balance_of(self, token_address: str, owner_address: str) -> int:
|
||||
"""Get token balance of a given owner address.
|
||||
|
||||
:returns: amount of tokens
|
||||
"""
|
||||
token_address = self._validate_and_checksum_address(token_address)
|
||||
owner_address = self._validate_and_checksum_address(owner_address)
|
||||
func = self._erc20(token_address).functions.balanceOf(owner_address)
|
||||
return self._invoke_function_call(
|
||||
func=func, tx_params=None, view_only=True
|
||||
)
|
||||
|
||||
def allowance(
|
||||
self, token_address: str, owner_address: str, spender_address: str
|
||||
) -> Union[HexBytes, bytes]:
|
||||
"""Get the amount of tokens approved for a spender.
|
||||
|
||||
:returns: amount of tokens
|
||||
"""
|
||||
token_address = self._validate_and_checksum_address(token_address)
|
||||
owner_address = self._validate_and_checksum_address(owner_address)
|
||||
spender_address = self._validate_and_checksum_address(spender_address)
|
||||
func = self._erc20(token_address).functions.allowance(
|
||||
owner_address, spender_address
|
||||
)
|
||||
return self._invoke_function_call(
|
||||
func=func, tx_params=None, view_only=True
|
||||
)
|
||||
|
||||
def get_transfer_event(
|
||||
self, token_address: str, tx_hash: Union[HexBytes, bytes]
|
||||
) -> Tuple[AttributeDict]:
|
||||
"""Get the result of a transfer from its transaction hash.
|
||||
|
||||
:param tx_hash: hash of transfer transaction
|
||||
"""
|
||||
tx_receipt = self._web3_eth.getTransactionReceipt(tx_hash)
|
||||
token_address = self._validate_and_checksum_address(token_address)
|
||||
return (
|
||||
self._erc20(token_address)
|
||||
.events.Transfer()
|
||||
.processReceipt(tx_receipt)
|
||||
)
|
||||
|
||||
def get_approval_event(
|
||||
self, token_address: str, tx_hash: Union[HexBytes, bytes]
|
||||
) -> Tuple[AttributeDict]:
|
||||
"""Get the result of an approval event from its transaction hash.
|
||||
|
||||
:param tx_hash: hash of approval transaction
|
||||
"""
|
||||
tx_receipt = self._web3_eth.getTransactionReceipt(tx_hash)
|
||||
token_address = self._validate_and_checksum_address(token_address)
|
||||
return (
|
||||
self._erc20(token_address)
|
||||
.events.Approval()
|
||||
.processReceipt(tx_receipt)
|
||||
)
|
@ -32,18 +32,17 @@ class Exchange(BaseContractWrapper):
|
||||
def __init__(
|
||||
self,
|
||||
provider: BaseProvider,
|
||||
account_address: str = None,
|
||||
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 account_address: str of account address
|
||||
:param private_key: str of private_key
|
||||
"""
|
||||
super(Exchange, self).__init__(
|
||||
provider=provider,
|
||||
account_address=account_address,
|
||||
contract_address=contract_address,
|
||||
private_key=private_key,
|
||||
)
|
||||
self._web3_net = self._web3.net # pylint: disable=no-member
|
||||
|
@ -40,24 +40,21 @@ def erc20_proxy_address():
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def weth_address():
|
||||
"""Get address of Wrapped Ether (WETH) token for the Ganache network."""
|
||||
return NETWORK_TO_ADDRESSES[NetworkId.GANACHE].ether_token
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def weth_asset_data(weth_address): # pylint: disable=redefined-outer-name
|
||||
def weth_asset_data(): # pylint: disable=redefined-outer-name
|
||||
"""Get 0x asset data for Wrapped Ether (WETH) token."""
|
||||
return asset_data_utils.encode_erc20(weth_address)
|
||||
return asset_data_utils.encode_erc20(
|
||||
NETWORK_TO_ADDRESSES[NetworkId.GANACHE].ether_token
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def weth_instance(
|
||||
web3_eth, weth_address
|
||||
): # pylint: disable=redefined-outer-name
|
||||
def weth_instance(web3_eth): # pylint: disable=redefined-outer-name
|
||||
"""Get an instance of the WrapperEther contract."""
|
||||
return web3_eth.contract(
|
||||
address=to_checksum_address(weth_address), abi=abi_by_name("WETH9")
|
||||
address=to_checksum_address(
|
||||
NETWORK_TO_ADDRESSES[NetworkId.GANACHE].ether_token
|
||||
),
|
||||
abi=abi_by_name("WETH9"),
|
||||
)
|
||||
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
import pytest
|
||||
from eth_utils import to_checksum_address
|
||||
|
||||
from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId
|
||||
from zero_ex.contract_artifacts import abi_by_name
|
||||
from zero_ex.contract_wrappers._base_contract_wrapper import (
|
||||
BaseContractWrapper,
|
||||
@ -12,18 +13,19 @@ from zero_ex.contract_wrappers._base_contract_wrapper import (
|
||||
@pytest.fixture(scope="module")
|
||||
def contract_wrapper(ganache_provider):
|
||||
"""Get a BaseContractWrapper instance for testing."""
|
||||
return BaseContractWrapper(provider=ganache_provider)
|
||||
return BaseContractWrapper(
|
||||
provider=ganache_provider,
|
||||
contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].ether_token,
|
||||
)
|
||||
|
||||
|
||||
def test_contract_wrapper__execute_method(
|
||||
accounts,
|
||||
contract_wrapper, # pylint: disable=redefined-outer-name
|
||||
erc20_proxy_address,
|
||||
weth_address, # pylint: disable=redefined-outer-name
|
||||
):
|
||||
"""Test :function:`BaseContractWrapper.execute` method."""
|
||||
acc1_allowance = contract_wrapper.execute_method(
|
||||
address=weth_address,
|
||||
abi=abi_by_name("WETH9"),
|
||||
method="allowance",
|
||||
view_only=True,
|
||||
@ -36,7 +38,6 @@ def test_contract_wrapper__execute_method(
|
||||
|
||||
with pytest.raises(Exception):
|
||||
contract_wrapper.execute_method(
|
||||
address=weth_address,
|
||||
abi=abi_by_name("WETH9"),
|
||||
method="send",
|
||||
view_only=True,
|
||||
|
@ -4,6 +4,7 @@ from decimal import Decimal
|
||||
|
||||
import pytest
|
||||
|
||||
from zero_ex.contract_addresses import NETWORK_TO_ADDRESSES, NetworkId
|
||||
from zero_ex.contract_wrappers import ERC20Token, TxParams
|
||||
|
||||
|
||||
@ -13,22 +14,19 @@ MAX_ALLOWANCE = int("{:.0f}".format(Decimal(2) ** 256 - 1))
|
||||
@pytest.fixture(scope="module")
|
||||
def erc20_wrapper(ganache_provider):
|
||||
"""Get an instance of ERC20Token wrapper class for testing."""
|
||||
return ERC20Token(ganache_provider)
|
||||
return ERC20Token(
|
||||
ganache_provider, NETWORK_TO_ADDRESSES[NetworkId.GANACHE].ether_token
|
||||
)
|
||||
|
||||
|
||||
def test_erc20_wrapper__balance_of(
|
||||
accounts,
|
||||
erc20_wrapper, # pylint: disable=redefined-outer-name
|
||||
weth_address,
|
||||
weth_instance, # pylint: disable=redefined-outer-name
|
||||
):
|
||||
"""Test getting baance of an account for an ERC20 token."""
|
||||
acc1_original_weth_balance = erc20_wrapper.balance_of(
|
||||
weth_address, accounts[0]
|
||||
)
|
||||
acc2_original_weth_balance = erc20_wrapper.balance_of(
|
||||
weth_address, accounts[1]
|
||||
)
|
||||
acc1_original_weth_balance = erc20_wrapper.balance_of(accounts[0])
|
||||
acc2_original_weth_balance = erc20_wrapper.balance_of(accounts[1])
|
||||
|
||||
expected_difference = 1 * 10 ** 18
|
||||
|
||||
@ -38,8 +36,8 @@ def test_erc20_wrapper__balance_of(
|
||||
weth_instance.functions.deposit().transact(
|
||||
{"from": accounts[1], "value": expected_difference}
|
||||
)
|
||||
acc1_weth_balance = erc20_wrapper.balance_of(weth_address, accounts[0])
|
||||
acc2_weth_balance = erc20_wrapper.balance_of(weth_address, accounts[1])
|
||||
acc1_weth_balance = erc20_wrapper.balance_of(accounts[0])
|
||||
acc2_weth_balance = erc20_wrapper.balance_of(accounts[1])
|
||||
|
||||
assert (
|
||||
acc1_weth_balance - acc1_original_weth_balance == expected_difference
|
||||
@ -53,27 +51,24 @@ def test_erc20_wrapper__approve(
|
||||
accounts,
|
||||
erc20_proxy_address,
|
||||
erc20_wrapper, # pylint: disable=redefined-outer-name
|
||||
weth_address, # pylint: disable=redefined-outer-name
|
||||
):
|
||||
"""Test approving one account to spend balance from another account."""
|
||||
erc20_wrapper.approve(
|
||||
weth_address,
|
||||
erc20_proxy_address,
|
||||
MAX_ALLOWANCE,
|
||||
tx_params=TxParams(from_=accounts[0]),
|
||||
)
|
||||
erc20_wrapper.approve(
|
||||
weth_address,
|
||||
erc20_proxy_address,
|
||||
MAX_ALLOWANCE,
|
||||
tx_params=TxParams(from_=accounts[1]),
|
||||
)
|
||||
|
||||
acc_1_weth_allowance = erc20_wrapper.allowance(
|
||||
weth_address, accounts[0], erc20_proxy_address
|
||||
accounts[0], erc20_proxy_address
|
||||
)
|
||||
acc_2_weth_allowance = erc20_wrapper.allowance(
|
||||
weth_address, accounts[1], erc20_proxy_address
|
||||
accounts[1], erc20_proxy_address
|
||||
)
|
||||
|
||||
assert acc_1_weth_allowance == MAX_ALLOWANCE
|
||||
|
@ -5,6 +5,7 @@ import random
|
||||
import pytest
|
||||
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.json_schemas import assert_valid
|
||||
from zero_ex.order_utils import generate_order_hash_hex, Order, sign_hash
|
||||
@ -13,7 +14,10 @@ from zero_ex.order_utils import generate_order_hash_hex, Order, sign_hash
|
||||
@pytest.fixture(scope="module")
|
||||
def exchange_wrapper(ganache_provider):
|
||||
"""Get an Exchange wrapper instance."""
|
||||
return Exchange(provider=ganache_provider)
|
||||
return Exchange(
|
||||
provider=ganache_provider,
|
||||
contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].exchange,
|
||||
)
|
||||
|
||||
|
||||
def create_test_order(
|
||||
|
21
python-packages/pre_install
Executable file
21
python-packages/pre_install
Executable file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""Run setup.py command `pre_install` for all packages that have one."""
|
||||
|
||||
from os import chdir, path
|
||||
import subprocess
|
||||
|
||||
PACKAGES = [
|
||||
"contract_wrappers",
|
||||
"contract_artifacts",
|
||||
]
|
||||
|
||||
for package in PACKAGES:
|
||||
print(f"Running command `pre_install` in package {package}")
|
||||
chdir(package)
|
||||
subprocess.check_call(
|
||||
(
|
||||
path.join(".", "setup.py") + " pre_install"
|
||||
).split()
|
||||
)
|
||||
chdir("..")
|
@ -316,7 +316,11 @@ book. Now let's have the taker fill it:
|
||||
|
||||
>>> from zero_ex.contract_wrappers import Exchange, TxParams
|
||||
>>> from zero_ex.order_utils import Order
|
||||
>>> Exchange(eth_node).fill_order(
|
||||
>>> exchange = Exchange(
|
||||
... provider=eth_node,
|
||||
... contract_address=NETWORK_TO_ADDRESSES[NetworkId.GANACHE].exchange
|
||||
... )
|
||||
>>> exchange.fill_order(
|
||||
... order=order,
|
||||
... taker_amount=order['makerAssetAmount']/2, # note the half fill
|
||||
... signature=order['signature'],
|
||||
@ -330,7 +334,7 @@ Cancelling
|
||||
Note that the above fill was partial: it only filled half of the order. Now
|
||||
we'll have our maker cancel the remaining order:
|
||||
|
||||
>>> Exchange(eth_node).cancel_order(
|
||||
>>> exchange.cancel_order(
|
||||
... order=order,
|
||||
... tx_params=TxParams(from_=maker_address)
|
||||
... )
|
||||
|
Loading…
x
Reference in New Issue
Block a user