Closed Amplitude88 closed 1 year ago
I have a similar problem my network is fuji test
run:
cli.transact_and_wait(contract, 'setGreeting', '123')
error:
/Users/sai/.rvm/gems/ruby-3.0.3/gems/eth-0.5.6/lib/eth/client.rb:469:in `send_command': the method eth_sendTransaction is not available (IOError)
Really hope there is stable Ruby version for ETH operations
Dont think so. Even there is no activity to help the community. I'Ve also asked in the Ruby discord. Even no response. I ask myself what is gonna happen with the ruby community? Please help us
I have a similar problem my network is fuji test
run:
cli.transact_and_wait(contract, 'setGreeting', '123')
error:
/Users/sai/.rvm/gems/ruby-3.0.3/gems/eth-0.5.6/lib/eth/client.rb:469:in `send_command': the method eth_sendTransaction is not available (IOError)
I don't know much either, but ... It looks like Fuji Test which doesn't support eth_sendTransaction. (For it to support that, it would need to know your private key, but it's a shared public node.)
You need to either sign the transaction yourself and then send via eth_sendRawTransaction or use a provider that can hold private keys like MetaMask in the browser.
Ex: contract = Eth::Contract.from_abi(abi: abi, address: contract_address, name: "yourContractName") contract.key = Eth::Key.new(priv: '0xyour_client_account_private_key') cli.transact(contract, 'setGreeting', '123', sender_key: contract.key)
Dont think so. Even there is no activity to help the community. I'Ve also asked in the Ruby discord. Even no response. I ask myself what is gonna happen with the ruby community? Please help us
Looks like web3 is a radioactive topic in the ruby community, a real shame ...
To help debug this issue could you please provide:
I spent hours today debugging my problem and got various obscure error messages (e.g. it started with ArgumentError: wrong number of arguments (given 1, expected 0) from <internal:nilclass>:10:in to_i'
) and it turned out all that was wrong was the URL provided to the ETH client, e.g. it should have been something like: https://eth-mainnet.alchemyapi.io/jsonrpc/18lHSAeZttzI4wJvHpXlJGHK4ZDNCTCP
(provided incl. that auth token on https://explorer.alchemyapi.io). Example request that worked for me is from the README file for client.call(ens_registry, "old")
.
@sai1024 your issue is unrelated, the error message says that send_transaction is not available because you don't have access to the remote private keys. you would need to pass a key to sign the transaction as @Liteo explained:
https://github.com/q9f/eth.rb/issues/136#issuecomment-1187611738
@Amplitude88 I cannot comment on the Ruby Discord as I do not use Discord but feel free to join our Telegram group: https://t.me/ruby_eth
I understand the documentation is very minimal: https://github.com/q9f/eth.rb/wiki/Smart-Contracts#your-own-contract-from-file
Could you tell me what information you are missing though? What error message do you get?
@q9f
The main problem is, that im not in able to send any payload. I dont know how i can put the data into the payload. That means i dont know, how i can interact with an contract. For example i will call Eth::Contract.from_abi() , i will receive an object. This object give me the called contract, right?. Then i want to pass my transaction data, to build a transaction object which i then will sign and send afterwards. How can i do this?
@q9f
The main problem is, that im not in able to send any payload. I dont know how i can put the data into the payload. That means i dont know, how i can interact with an contract. For example i will call Eth::Contract.from_abi() , i will receive an object. This object give me the called contract, right?. Then i want to pass my transaction data, to build a transaction object which i then will sign and send afterwards. How can i do this?
Gotcha. So, you want to transact with the contract, not call it. See this answer: https://ethereum.stackexchange.com/a/768/87
But putting terminology aside, here is what you want to do. You don't want to create a transaction object, the library can handle this for you.
# Create a client / RPC endpoint and set default fees
goerli = Client.create "https://goerli.infura.io/v3/31b..30c"
# => #<Eth::Client::Http:0x000055a0ec933dd8
# @gas_limit=21000,
# @host="goerli.infura.io",
# @id=0,
# @max_fee_per_gas=0.2e11,
# @max_priority_fee_per_gas=0,
# @port=443,
# @ssl=true,
# @uri=#<URI::HTTPS https://goerli.infura.io/v3/31b..30c>>
goerli.max_priority_fee_per_gas = 2 * Unit::GWEI
# => 0.2e10
goerli.max_fee_per_gas = 69 * Unit::GWEI
# => 0.69e11
# Load some account to sign transactions with later
signer = JSON.load File.open "/path/to/UTC--2019-01-30T13-26-55.927410794Z--e0a2bd4258d2768837baa26a28fe71dc079f84c7-goerli"
# => {"address"=>"e0a2bd4258d2768837baa26a28fe71dc079f84c7",
# "crypto"=>
# {"cipher"=>"aes-128-ctr",
# "ciphertext"=>"700..39c",
# "cipherparams"=>{"iv"=>"555..00e"},
# "kdf"=>"scrypt",
# "kdfparams"=>
# {"dklen"=>32,
# "n"=>262144,
# "p"=>1,
# "r"=>8,
# "salt"=>"2bb..93c"},
# "mac"=>"dfc..079"},
# "id"=>"3332ffa0-6511-43dd-a4e3-937b00e180d1",
# "version"=>3}
signer = Key::Decrypter.perform signer, "password"
# => #<Eth::Key:0x000055b04afad430
# @private_key=
# #<Secp256k1::PrivateKey:0x000055b04afac6c0
# @data="G?*\..\x86">,
# @public_key=#<Secp256k1::PublicKey:0x000055b04afac670>>
signer.address.to_s
# => "0xe0a2Bd4258D2768837BAa26A28fE71Dc079f84c7"
# Create a contract from an ABI and address
house_address = Address.new "0x2d234b332E94257f6538290Ae335eEF94B0974F0"
# => #<Eth::Address:0x000055a0ec8b3ed0 @address="0x2d234b332E94257f6538290Ae335eEF94B0974F0">
house_name = "House"
# => "House"
house_abi = '[{"inputs":[{"internalType":"uint64","name":"_subscriptionId","type":"uint64"},{"internalType":"uint256","name":"_minBalance","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidBet","type":"error"},{"inputs":[],"name":"InvalidWithdraw","type":"error"},{"inputs":[{"internalType":"address","name":"have","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"OnlyCoordinatorCanFulfill","type":"error"},{"inputs":[],"name":"RequestError","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"rebet","type":"bool"},{"indexed":false,"internalType":"uint8","name":"direction","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"result","type":"uint8"},{"indexed":false,"internalType":"address","name":"better","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Result","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"cashOut","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_player","type":"address"}],"name":"getWinnings","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_direction","type":"uint8"}],"name":"makeBet","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"requestIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_vrf","type":"address"}],"name":"setVRFCoordinator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]'
# => "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"_subscriptionId\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"_minBalance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidWithdraw\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"want\",\"type\":\"address\"}],\"name\":\"OnlyCoordinatorCanFulfill\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RequestError\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"rebet\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"direction\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"result\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"better\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Result\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"cashOut\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_player\",\"type\":\"address\"}],\"name\":\"getWinnings\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"_direction\",\"type\":\"uint8\"}],\"name\":\"makeBet\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"randomWords\",\"type\":\"uint256[]\"}],\"name\":\"rawFulfillRandomWords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"requestIds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_vrf\",\"type\":\"address\"}],\"name\":\"setVRFCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]"
house = Eth::Contract.from_abi(name: house_name, address: house_address, abi: house_abi)
# => #<Eth::Contract::House:0x000055a0ec4bcf98>
house.address.to_s
# => "0x2d234b332E94257f6538290Ae335eEF94B0974F0"
# To read the contract, use `call`
goerli.call(house, "getBalance")
# => 0
goerli.call(house, "getWinnings", Key.new.address.to_s)
# => 0
# To write to the contract, use `transact` (or better `transact_and_wait`)
goerli.transact_and_wait(house, "cashOut", 999999999999999999, sender_key: signer)
# => "0x67e9b96b99e51737231c17bc492e37e023e87372253627647ea4a2a7ebf04918"
goerli.transact_and_wait(house, "withdraw", 999999999999999999, Key.new.address.to_s, sender_key: signer)
# => "0x7032d1bcc23b8f6881eabdbf64ddbb22ae333ad6c02027d8dc5924c0445bdf24"
Note, how you can just pass arguments to the function call and transact. Don't forget to provide a sender key.
Please let me know if this is more clear now.
I added it to the wiki: https://github.com/q9f/eth.rb/wiki/Smart-Contracts#writing-to-a-smart-contract-transact
Let me know if there is anything else!
Hi,
im new to this gem but i already have experience with other web3 SDK's. My Question is:
How can i call a contract function for example "SwapExactETHForToken" and put Token A and Token B into the payload? And how can i send the transaction afterwards? Sorry i dont understand the documentation.
I have use Eth::Contract.from_abi because i think that this is the wrapper for the contract itself. Then i want to use my client to build the transaction payload: client.transact(contract, "SwapExactETHForToken").
But it didnt work....
How can i put the TokenA and TokenB into the transaction?
For example in Javascript:
let encoded_tx = tx_builder.encodeABI();
after this i sign the transaction. Could you tell me if i can do the same with this Ruby Gem? Or could you explain to me how i can call a contract function and als put data into the payload to send the transaction afterwards?
Thanks in advance