-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Constructor Function #595
Conversation
@harpangell7 this feature is captured here in #577 which defines an alternate API for this functionality which is more inline with the existing API for contract functions and events. Please note that @zheli has claimed that issue, however, there is no open pull request at this time. I would encourage you to reach out to @zheli prior to investing time in converting this PR to match #577 (assuming you are interested in claiming the bounty). |
Also, for contributions to be something we can merge, this would need to have tests and documentation written to cover the new functionality. |
Honestly man, I'm not sure I feel comfortable asking for money lol. I just did it because I needed the functionality. I would hate to claim a bounty and not be able to produce. I will keep your tests and documentation in mind though. And I really do appreciate all the work that YOU do!! I'll just use the new API when its released, until then, I have my fork. lol |
I only mention the bounty to be sure there's as little contention as possible. You are welcome to contribute the feature of your own altruistic/whatever motivation. Either way works. |
Well I needed to learn the tests anyways. So I added them and the documentation. But now my "check" with Travis it fails. :( Aslo, the tests dont assert the deploying to the chain, only that they can sign and return the correct signed transaction details. I couldn't find the tests on the sendRawTransaction(). |
@harpangell7 I have only done some research on current library interface and how it can be done, there is no serious code have been written yet. I would be happy to let you claim this issue (#577) if you want to. |
Yeah I'd love to give it a try!! Give me 2 days, and if I cant figure it out, then I'll need some help. |
@harpangell7 I don't know how to say this, but I actually made some progress on my pull request today... maybe we can work on it together and share the bounty? 😂 |
Thats fine, I'm working on the constructor api now. So if you want to tackle the fallback and we can meet in the middle? |
@harpangell7 I think one of us should branch off from the other's branch to make it easier to track changes:) Maybe you can also tell me briefly how do you want the new constructor to work? Right now I just need to ask @pipermerriam or @carver what do they mean by deprecating |
@zheli go ahead and take this one. I was working on it but got busy and you claimed it first. But to answer your question I think they just mean deprecating contract.deloy() and making the contract.constructor().transact() the new deploy method. I'm curious to see how it turns out though! |
@zheli I made a push to show you how I would do it. |
@harpangell7 thx man! Regarding to |
Oh interesting, I was thinking they meant the literal constructor, as contract(abi, bytecode) already init()'s the class, therefore, calling the constructor on the class made more sense to me. See the language is def lost. lol I also read the fallback as literally contract.fallback(*args, **kwargs).estimateGas(). This would eliminate the need to check for an actually function called fallback, because that function would be called using contract.functions.fallback(*args, **kwargs).estimateGas(). But its really up to them. lol |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets see if I can answer all the questions.
We do actually mean a function named constructor
so the literal API would be contract_instance.constructor(*args, **kwargs).transact({...})
I'm fine with you two working collaboratively on this. I'd prefer that the two of you determine how you want to split the bounty if you work on this collaboratively. I'd prefer to not be tasked with making that subjective decision.
@harpangell7 RE: the signing and sendRawTransaction testing.
I think your tests which assert things about the signed data are not really testing the correct thing, or at least, they are opaque in terms of what they are testing. Instead, an approach that I think will produce better tests would be:
- use
c.constructor(...).buildTransaction()
to build the txn dict. - send normal deploy transaction with
c.constructor(...).transact()
- compare built transaction with the
transact()
transaction and see that their data fields match.
'nonce': w3.eth.getTransactionCount(w3.eth.coinbase), | ||
'chainId': None | ||
} | ||
>>> contract_data = token_contract.constructor(web3.eth.accounts[1], 12345).buildTransaction(transaction) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code example seems wrong. The return value from token_contract.constructor(...).build_transaction(...)
should be a transaction dictionary. Then, that returned dictionary should be what is passed into web3.eth.account.signTransaction
.
Make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that makes sense and I will add it now
#assert Web3.toHex(signed.hash) == tx_hash | ||
|
||
#account = acct.privateKeyToAccount(private_key) | ||
#assert account.signTransaction(txn) == signed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like this test has all of it's assertions commented out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will Finish
), | ||
ids=['web3js_example', '31byte_r_and_s'], | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
odd extra whitespace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix
), | ||
ids=['web3js_example', '31byte_r_and_s'], | ||
) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
odd extra whitespace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will Fix
ids=['web3js_example', '31byte_r_and_s'], | ||
) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra whitespace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will Fix
web3/contract.py
Outdated
@@ -268,6 +287,52 @@ def deploy(cls, transaction=None, args=None, kwargs=None): | |||
txn_hash = cls.web3.eth.sendTransaction(deploy_transaction) | |||
return txn_hash | |||
|
|||
@classmethod | |||
@deprecated_for("contract.<constructor>.buildTransaction") | |||
def deploy_data(cls, transaction=None, args=None, kwargs=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we remove this method since it was never part of the original API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
web3/contract.py
Outdated
@@ -1039,6 +1195,93 @@ def call_contract_function(abi, | |||
return normalized_data | |||
|
|||
|
|||
# Transact Constructor | |||
# TODO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
leftover comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I leave my functions as TODO's until finished.
Gotcha, yeah the tests were definitely not perfected but I have a good place to start now. |
@pipermerriam I'm running into some trouble with the tests now. When I call contract.constructor().buildTransaction() the result transaction doesn't include the "to" or the "nonce" fields. If I then try to pass this into the signTransaction I get the "TypeError: Not all fields initialized". So then if I try to enter the 'to' field, I have it giving me the 'ValueError: Cannot specify |
cc @carver ^ might be something we need to address with how sign transaction validates contract deployment transactions. Regarding signing the transactions. As for tests, I don't think you should need to sign the transaction as you should be able to simply submit it over |
Cool that's roughly the approach I was going to suggest @harpangell7 . My instinct is that |
@pipermerriam @carver So buildTransaction() adds the default chainId and this is giving me a "eth_tester.exceptions.ValidationError: Only the keys 'data/from/gas/gas_price/nonce/to/value' are allowed. Got extra keys: 'chainId'". when I try to run web3.eth.sendTransaction. I've confirmed that this is only a testing error, as I can use buildTransaction({'chainId': 1}) just fine in my program. |
@carver So I was incorrect in stating that it will auto 'to' to "". The reason it was doing that was because I hacked in built_transaction['to'] = '' just before returning to the user. Will there ever be an instance when they can deploy to a specific address? Not to sound stupid, but I want to make sure. With the current hack though, when you sign the transaction, it changes the "" to None. |
Can you open an issue on
Nope, the defined way to deploy a contract is to leave the |
@carver Purrfect! |
@carver I’m just waiting on the eth-tester issue before I submit again... |
Would love to see this working. |
@nueverest Please subscribe to #666 which will be updated when the problem is fixed (even if this particular PR doesn't get merged) |
Resolved in #693 |
*self.args, | ||
**self.kwargs) | ||
|
||
built_transaction['to'] = '' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here was my suggestion to fix that bug. #739
There was no easy way to deploy a contract with a signed raw transaction.
How was it fixed?
By adding the deploy_data function. It can be used like so....
`
`
Cute Animal Picture