web3-eth
web3-eth copied to clipboard
Sending a transaction
Is there a way to call a function (i.e. send a transaction) with this library? If I wanted to programmatically call a function that updates blockchain state, what's the best way to do it?
Signing transactions is not implemented in this GEM.
@astudnev Do you have a plan to implement it?
No direct plan, but would be very nice
I am thinking to implement it.... Any ideas? Someone wants to collaborate?
Don't mean to steal anyone's thunder. But I have basic functionality for sendTransaction (not ready yet for arrays) in my library here https://github.com/hswick/w3 and I am looking for collaborators as I can only work on it part time.
There is also https://github.com/EthWorks/ethereum.rb which is fairly developed
Hey people, why reinvent the wheel, for signing transactions you can use https://github.com/se3000/ruby-eth - would be more useful to try and fix some of the quirks of that library (one of them I will fix as soon as time permits...)
Then you can simply do:
#=================
web3 = Web3::Eth::Rpc.new host: 'ropsten.infura.io',
port: 443,
connect_options: {
open_timeout: 20,
read_timeout: 140,
use_ssl: true,
rpc_path: '/keyxxxxxx'
}
res = web3.eth.getTransactionCount ['.....acct.......', 'pending'] tc = res.to_i(16)
tx = Eth::Tx.new({ data: "0x075624e1", # this is incrementTwice() - to do: hex data from any function input gas_limit: 210_000, gas_price: 20_000_000, nonce: tc, to: "0xc015edDe79C543A4a7aa7e54EC590cB9cCC5E6ae", value: 0, })
key = Eth::Key.new priv: '....acct_private_key.....' tx.sign key puts tx.hash res = web3.eth.sendRawTransaction([tx.hex]) #=================
The more tricky part (from my point of view) is to properly encode the data - this seems to be possible with web3-eth but need to test it.
@hswick - apart from the signing, all the necessary functions to send transactions seem to be implemented in a pretty comprehensive way in the Ethereum.rb gem (https://github.com/EthWorks/ethereum.rb) which does have some minor quirks but generally works (only with parity at the moment). However, that gem does not expose most of its useful functions, such as input data encoding, so instead of trying to redo, we could work on doing that. What do you think?
@alex-kampa I like the simplicity of ruby-eth for signing transactions. Anyone looking on this thread would probably benefit from the use of it.
In regards to ethereum.rb I address this in my README. I'm a fairly opinionated person (as I think conviction makes good software), and I have actually been stealing some of the internals for w3 from ethereum.rb (which I reference). It isn't a matter of functionality, it is about design. My design isn't based on just becoming feature parity with something like web3.js, it is about surpassing it.
@hswick I just went through your w3 library, it looks promising. I'll check it out.
I'm also trying to send transaction as @woniesong92 my code here
key = Eth::Key.new priv: privateKey
gas_limit = 200000
gas_price = $web3.eth.gasPrice().to_i(16)
nonce = $web3.eth.getTransactionCount([key.address, 'pending']).to_i(16)
tx = Eth::Tx.new({
gas_limit: 210000,
gas_price: gas_price,
nonce: nonce,
from: key.address,
to: address_to,
value: amount,
data: ""
})
tx.sign(key)
result = $web3.eth.sendRawTransaction(tx.hex)
then error respose
{
"status": 500,
"error": "Internal Server Error",
"exception": "#<RuntimeError: Error code 400 on request https://rinkeby.infura.io/kEICAYHkrSFjduGKSOR5 {\"jsonrpc\":\"2.0\",\"method\":\"eth_sendRawTransaction\",\"params\":\"0xf86480843b9aca0083033450945dc73424b8bb75d22cd728dc8dbb2aad77f5fd4680801ba096c8949ec52baa4ef55fdedbc138ed330717a7495ecc70cffd7d4ce05d4cb389a06f3c88b4323cd4f6f0d8bfdb51e788faff621733d48f77622cd598341edb6b15\",\"id\":6401146}>",
"traces": {
"Application Trace": [
{
"id": 5,
"trace": "app/walletapi/eth_client.rb:45:in `drawal'"
},
{
"id": 6,
"trace": "app/controllers/api/v1/wallets_controller.rb:137:in `withdrawal'"
}
],
"Framework Trace": [
{
"id": 0,
"trace": "web3-eth (0.2.16) lib/web3/eth/rpc.rb:44:in `block in request'"
please help me.
Any luck with that problem @marknguyen85?
Hello @alex-kampa,
In your example above:
tx = Eth::Tx.new({
data: "0x075624e1", # this is incrementTwice() - to do: hex data from any function input
gas_limit: 210_000,
gas_price: 20_000_000,
nonce: tc,
to: "0xc015edDe79C543A4a7aa7e54EC590cB9cCC5E6ae",
value: 0,
})
Could you please be more clear as to what goes in the data field? it seems this is what @marknguyen85 Could be missing as well?
Thank you very much.
i've resolved with code below
result = $web3.eth.sendRawTransaction([tx.hex])
@jlstr i think data is not require
Awesome thanks!
@marknguyen85 May I ask one follow up Question, How do you get a contract object?
I'm trying to load it from a Ruby Hash:
contract = web3.eth.contract(Abi)
contract_instance = contract.at('0x0.....')
Where Abi
is the standard Contract, ie. a Ruby Array behind the scenes
But it does not work!
The above does not allow me to do:
contract_instance.balanceOf('0x....')
Throws NoMethodError and I wonder If the ABI has to be in a specific format? any ideas,
Please Help.
@jlstr I'm also problems as you with methods of constract instance
@jlstr I found the cause of the error, Abi must be formatted string instead of array ex Abi = []
format to => Abi = '[]'
Awesome! Thank you @marknguyen85, And How are you calling contract methods?
@jlstr
as you, i don't know how to calling contract methods. When call contract method alway get error
Function transfer is not constant: transfer, requires to sign transaction
i found in this gem code
def call_contract contract_address, method_name, args
function = functions[method_name]
raise "No method found in ABI: #{method_name}" unless function
raise "Function #{method_name} is not constant: #{method_name}, requires to sign transaction" unless function.constant
function.do_call web3_rpc, contract_address, args
end
=>
raise "Function #{method_name} is not constant: #{method_name}, requires to sign transaction"
have you any idea for this processing?
Hello @marknguyen85, I have figured it out, and let me tell you, you're in the right track, but the key is that you have to serialize the entire contract method you'll call according to the ABI Spec. Once serialized, you will get a long HEX string that looks like: 0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001
That hex string goes in the data field of the TX:
tx = Eth::Tx.new({ data: hex_data, gas_limit: 210_000, gas_price: gas_price, nonce: nonce, to: contract_address, from: address_that_is_signing_this_transaction, value: 0 })
The rest is exactly as you have in your example, but remember that the to will always be the contract's address in Ethereum.
Let me know if require any further help. -Jose
@jlstr thanks you. I have read the link that you submitted (ABI Spec) but don't know how to create data_hash. Can you just me how to generate param hex?
00000000000000000000000000000000000000000000000000000000000000045
or
0000000000000000000000000000000000000000000000000000000000000001
The answer to your Question is very broad, in the hex strings you have pasted above, what are you trying to represent? a number (uint256)?
I will teach you how I personally generate a uint256 as an example so that you have an idea of what to do next, let say you want to pass the decimal value 10 to a smart contract's method:
value = 10
First you have to convert it into WEI, easy enough, just multiply by a 10^18 constant
value = value * 1_000_000_000_000_000_000
Now, you have to convert it to hexadecimal:
hex_value = "%x" % (value)
Finally, pad the hexadecimal value with 0s to complete a 64 bit long hex string that's required by Ethereum:
hex_value = hex_value.rjust(64, "0")
This example will translate a decimal number like 10 into a uint256 type, I have examples for other types, but I hope this will give you an idea of how to do it.
Kindly, Jose
@jlstr thanks
@jlstr - some of the encoding was also done by @hswick at https://github.com/hswick/w3/blob/master/lib/w3/encoder.rb
It does not seem to handle all cases though - for example arrays as inputs are probably a bit tricky, and this includes strings which are handled like arrays as far as i know. If anyone here manages to do the encoding in the most generic way, please let us know.
BTW, the specs for the encoding are here: http://solidity.readthedocs.io/en/develop/abi-spec.html
Thank you @alex-kampa I did use that very same spec in order to do the parsing, too bad it's so coarse.