hswick / exw3 Goto Github PK
View Code? Open in Web Editor NEWHigh level Ethereum RPC Client for Elixir
License: Apache License 2.0
High level Ethereum RPC Client for Elixir
License: Apache License 2.0
Howdy @hswick,
I'd love to take over maintenance of exw3
. I've started creating a few hygiene PR's and I'm currently working on fixing the test suite.
I'm the author of a few Elixir projects e.g.
https://github.com/fremantle-capital/tai
https://github.com/fremantle-industries/workbench
Feel free to hit me up on email for more details.
Hi!
I have a problem with ExW3.Contract.call method and ABI.TypeDecoder.decode_type.
Solidity function:
function get_DFA(uint dfaID) public returns (DFA memory) { DFA storage dfa = dfa_pool[dfaID]; return dfa; }
Elixir function:
def sc_call(sc_abi_path, sc_address, sc_name, sc_method, sc_method_args \\ []) do
ExW3.Contract.start_link()
sc_abi = ExW3.Abi.load_abi(sc_abi_path)
ExW3.Contract.register(String.to_atom(sc_name), abi: sc_abi)
ExW3.Contract.at(String.to_atom(sc_name), sc_address)
ExW3.Contract.call(String.to_atom(sc_name), String.to_atom(sc_method), sc_method_args)
end
When I call this method from ElixirApp, I get a error
ElixirApp.Utils.Ethereum.sc_call("data/DFAPool.abi", "0x39Df1178CCBeC6d48A81969b6f67f13F3B4CC6E3", "DFAPool", "get_DFA", [1])
00:35:02.056 [error] GenServer ContractManager terminating
** (FunctionClauseError) no function clause matching in ABI.TypeDecoder.decode_type/2
(ex_abi 0.5.3) lib/abi/type_decoder.ex:244: ABI.TypeDecoder.decode_type(:tuple, <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...>>)
(ex_abi 0.5.3) lib/abi/type_decoder.ex:270: anonymous fn/3 in ABI.TypeDecoder.decode_type/2
(elixir 1.11.4) lib/enum.ex:2193: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.3) lib/abi/type_decoder.ex:265: ABI.TypeDecoder.decode_type/2
(ex_abi 0.5.3) lib/abi/type_decoder.ex:189: anonymous fn/3 in ABI.TypeDecoder.do_decode_raw/2
(elixir 1.11.4) lib/enum.ex:2193: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.3) lib/abi/type_decoder.ex:184: ABI.TypeDecoder.do_decode_raw/2
(ex_abi 0.5.3) lib/abi/type_decoder.ex:178: ABI.TypeDecoder.decode_raw/2
Last message (from #PID<0.255.0>): {:call, {:DFAPool, :get_DFA, [1]}}
I don't understand what's happened.
Hello guys!
First off I wanna thank you for the awesome, although concise library!
But this section/feature on Readme, got me thinking, maybe could we automate this?
To compile the test solidity contracts after making a change run this command:
$ solc --abi --bin --overwrite -o test/examples/build test/examples/contracts/*.sol
And such, I did as a MVP, a simple implementation, that you can check out here. I did some changes, implemented better automations, and error treatments. But unfortunately I couldn't create a branch here ๐ข .
So Here's my request, can we got my PR here, and such we can get this working? I already integrated with the library, and tested in a sample Phoenix Framework Project:
While sending a transaction only gas
parameter is being used, but in some solutions, others are of use as well.
Parameters I'm saying of can be found here
Would be nice to have unit converters. This is a handy web3 util, that should be included here as well
This is the the error I am getting when trying to compile. I'm using a Mac Air with an M1 processor. Any ideas how to fix this?
$ mix compile
==> ex_keccak
Compiling 1 file (.ex)
== Compilation error in file lib/ex_keccak.ex ==
** (ErlangError) Erlang error: :enoent
(elixir 1.13.2) lib/system.ex:1044: System.cmd("cargo", ["metadata", "--format-version=1"], [cd: "native/exkeccak"])
(rustler 0.22.2) lib/rustler/compiler/config.ex:81: Rustler.Compiler.Config.external_resources/2
(rustler 0.22.2) lib/rustler/compiler/config.ex:69: Rustler.Compiler.Config.build/1
(rustler 0.22.2) lib/rustler/compiler.ex:9: Rustler.Compiler.compile_crate/2
lib/ex_keccak.ex:2: (module)
could not compile dependency :ex_keccak, "mix compile" failed. Errors may have been logged above. You can recompile this dependency with "mix deps.compile ex_keccak", update it with "mix deps.update ex_keccak" or clean it with "mix deps.clean ex_keccak"
Update the ex doc version, and use it properly. Then list the hosted site on the README
I create 2 diff contracts, one with set function receiving integer as parameter, the other receiving string.
First works fine and the second one fails with this message:
{:error,
%{
"code" => -32000,
"data" => %{
"0xe20bb21666d462cfec33dad694cae424fadd38cdc4820970c8769f2e7690f149" => %{
"error" => "revert",
"program_counter" => 5281,
"return" => "0x"
},
"name" => "RuntimeError",
"stack" => "RuntimeError: VM Exception while processing transaction: revert\n at Function.RuntimeError.fromResults (/tmp/.mount_ganachjrwblU/resources/static/node/node_modules/ganache-core/lib/utils/runtimeerror.js:94:13)\n at BlockchainDouble.processBlock (/tmp/.mount_ganachjrwblU/resources/static/node/node_modules/ganache-core/lib/blockchain_double.js:627:24)\n at runMicrotasks (<anonymous>)\n at processTicksAndRejections (internal/process/task_queues.js:93:5)"
},
"message" => "VM Exception while processing transaction: revert"
}}
I've tried converting string to hex and didn't work either.
Please add an example on readme on how to format string before passing it to contract function.
In the following function
@spec call(atom(), atom(), list()) :: {:ok, any()}
@doc "Use a Contract's method with an eth_call"
def call(contract_name, method_name, args \\ []) do
GenServer.call(ContractManager, {:call, {contract_name, method_name, args}})
end
the GenServer
request times out quite a few times while accessing data on the mainnet (because the default timeout is 5 seconds).
The timeout of Ethereumex.HttpClient
can be set to :infinity
, but the request times out at exw3
.
Will it be helpful in allowing setting the GenServer timeout as a config value?
Right now EventListener module uses the loop receive pattern. However, I'm learning that this is an antipattern, in that using basic processes is like using assembly language.
I also have a suspicion that EventPoller's behavior could be rolled into the EventListener GenServer which might decrease the amount of code.
For the most part any time someone interacts with the blockchain they want some feedback. However, there are cases of fire and forget and the easiest way to implement this would be to provide a send method that uses GenServer cast instead of call.
Leaving this issue open for others to comment on.
Add more topics for indexing specific fields for events
Could you please provide an example of sending ERC20 tokens using ExW3? I have the following ABI:
// transfer
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"type": "function"
}
and would like to send USDT from one ethereum address to another.
Would be useful (possibly more performant) to grab a batch of changes for a list of filters.
This would mean less trips over the wire to the Ethereum node.
I'm getting a MatchError raised by ex_abi when I use this library to call a contract's method that returns an array of uint256
. Initially I thought it was a bug in ex_abi but based on the evidence provided in poanetwork/ex_abi#98 it seems that there might something wrong on how this library is handling the response from the RPC call and passing that to ex_abi for decoding.
The issue I reference in ex_abi has all the required information to reproduce the bug
Encoded data seems to be wrapped in an extra tuple see #107 for details
One suggestion I've received is to have a single process that handles all the requests for every contract. This seems to be a more idiomatic style for Elixir apps, where this process is in charge of any Contract related service. One benefit would be that this single process would be easier to pass around different modules, and you would only have to start it in the Application supervisor.
I was going to implement this and realized it is a very involved change because it completely changes the way state is handled starting from init to every single call. This would also be a very breaking change, so I think it is best to sit on it, and see what others think.
Time to update the ethereumex and abi versions since they have been active lately.
For contracts that have been compiled with pragma experimental ABIEncoderV2;
, and return an array for example:
function actors() external view returns (address[] memory) {
return actorList.values;
}
ExW3 doesn't return, hogs the CPU and the memory.
ExW3.Contract.start_link()
ExW3.Contract.register(:Contract, abi: ExW3.Abi.load_abi("path/to/abis/erc721.json"))
ExW3.Contract.at(:Contract, "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d")
url = Spool.Chain.Helpers.get_endpoint_for_network(1)
Application.put_env(:ethereumex, :url, url)
ExW3.Contract.call(:Contract, :symbol)
[error] GenServer ContractManager terminating
** (MatchError) no match of right hand side value: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>
(ex_abi 0.5.16) lib/abi/type_decoder.ex:238: ABI.TypeDecoder.decode_bytes/4
(ex_abi 0.5.16) lib/abi/type_decoder.ex:327: anonymous fn/3 in ABI.TypeDecoder.decode_type/3
(elixir 1.14.1) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.16) lib/abi/type_decoder.ex:325: ABI.TypeDecoder.decode_type/3
(ex_abi 0.5.16) lib/abi/type_decoder.ex:188: anonymous fn/3 in ABI.TypeDecoder.do_decode_raw/2
(elixir 1.14.1) lib/enum.ex:2468: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.16) lib/abi/type_decoder.ex:185: ABI.TypeDecoder.do_decode_raw/2
(ex_abi 0.5.16) lib/abi/type_decoder.ex:179: ABI.TypeDecoder.decode_raw/2
(exw3 0.6.1) lib/exw3/abi.ex:52: ExW3.Abi.decode_output/3
(exw3 0.6.1) lib/exw3/contract.ex:214: ExW3.Contract.eth_call_helper/4
(exw3 0.6.1) lib/exw3/contract.ex:480: ExW3.Contract.handle_call/3
(stdlib 4.1.1) gen_server.erl:1149: :gen_server.try_handle_call/4
(stdlib 4.1.1) gen_server.erl:1178: :gen_server.handle_msg/6
(stdlib 4.1.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message (from #PID<0.840.0>): {:call, {:Contract, :symbol, []}}
Here is a quick fix
ethereumex explains a way to do this, but it requires the Blockchain hex package. Considering, that the entire Blockchain project probably isnt necessary for this feature, it may make sense to extract those parts out.
The thinking would be something like this (taken from etheremex README):
eth_send_raw_transaction example - Payable smart contract call
Calling a smart contract method that requires computation will cost you gas or ether (if that method requires payment also). This means you will have to sign your transactions using the private key that owns some ethereum. In order to send signed transactions you will need both ABI and Blockchain hex packages.
abi_encoded_data = ABI.encode("transferFrom(address,address,uint)", [from_address, to_address, token_id])
contract_address = "0x123" |> String.slice(2..-1) |> Base.decode16(case: :mixed)
transaction_data = %Blockchain.Transaction{
data: abi_encoded_data,
gas_limit: 100_000,
gas_price: 16_000_000_000,
init: <<>>,
nonce: 5,
to: contract_address,
value: 0
}
|> Blockchain.Transaction.Signature.sign_transaction(private_key)
|> Blockchain.Transaction.serialize()
|> ExRLP.encode()
|> Base.encode16(case: :lower)
Ethereumex.HttpClient.eth_send_raw_transaction("0x" <> transaction_data)
Hi,
I am using permissioned DLT -> Quorum from Consensys (previously JPMorgan). This is basically "enterprise functionaliy" rich version of Ethereum. Most important one are private contracts and private transactions.
For instance:
https://docs.goquorum.consensys.net/en/stable/HowTo/Use/DevelopingSmartContracts/#creating-private-transactionscontracts
Can I handle this with exw3? Deployment of such contract, calling it later?
Can't really see from the documentation.
Thanks
When attempting to consume a String in a contract function, ExW3 seems to handle encoding improperly, causing variables to mix and or set improperly in the contracts state.
Smart Contract Example:
pragma solidity >=0.4.22 <0.9.0;
contract Tester {
address public currentAddr;
uint256 public currentInt;
string public sym;
function setOnlyStringBefore(string memory _sym, address new_addr, uint256 new_int) public {
currentAddr = new_addr;
currentInt = new_int;
sym = _sym;
}
function setOnlyStringAfter(address new_addr, uint256 new_int, string memory _sym) public {
currentAddr = new_addr;
currentInt = new_int;
sym = _sym;
}
function setOnlyAddrAndInt(address new_addr, uint256 new_int) public {
currentAddr = new_addr;
currentInt = new_int;
}
}
string
is set before address
and uint256
in smart contract function parametersUsing ExW3 ->
ExW3.Contract.send(:Tester, :setOnlyStringBefore, ["name", "0x0255bff90b8787f06cf13ab325997cbf3b139c1d", 10], %{from: @contracts_owner, gas: 6000000})
{:ok, "0x1c6ac0864e8e6418cfc743200ee74ad06bb2442bd5842fd73c2d12bb835db0dc"}
In Truffle ->
truffle(k8s)> let test = await Tester.deployed()
truffle(k8s)> test.sym()
Thrown:
{ Error: invalid codepoint at offset 14; unexpected continuation byte (argument="bytes", value={"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":2,"13":85,"14":191,"15":249,"16":11,"17":135,"18":135,"19":240,"20":108,"21":241,"22":58,"23":179,"24":37,"25":153,"26":124,"27":191,"28":59,"29":19,"30":156,"31":29,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":10,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":0,"77":0,"78":0,"79":0,"80":0,"81":0,"82":0,"83":0,"84":0,"85":0,"86":0,"87":0,"88":0,"89":0,"90":0,"91":0,"92":0,"93":0,"94":0,"95":4}, code=INVALID_ARGUMENT, version=strings/5.0.5)
at evalmachine.<anonymous>:0:6
at sigintHandlersWrap (vm.js:288:15)
at Script.runInContext (vm.js:130:14)
at runScript (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/console.js:251:1)
at Console.interpret (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/console.js:266:1)
at bound (domain.js:402:14)
at REPLServer.runBound [as eval] (domain.js:415:12)
at REPLServer.onLine (repl.js:642:10)
at REPLServer.emit (events.js:198:13)
at REPLServer.EventEmitter.emit (domain.js:448:20)
at REPLServer.Interface._onLine (readline.js:308:10)
at REPLServer.Interface._line (readline.js:656:8)
at REPLServer.Interface._ttyWrite (readline.js:937:14)
at REPLServer.self._ttyWrite (repl.js:715:7)
at ReadStream.onkeypress (readline.js:184:10)
at ReadStream.emit (events.js:198:13)
at ReadStream.EventEmitter.emit (domain.js:448:20)
at emitKeys (internal/readline.js:424:14)
at emitKeys.next (<anonymous>)
at ReadStream.onData (readline.js:1073:36)
at ReadStream.emit (events.js:198:13)
at ReadStream.EventEmitter.emit (domain.js:448:20)
at addChunk (_stream_readable.js:288:12)
at readableAddChunk (_stream_readable.js:269:11)
at ReadStream.Readable.push (_stream_readable.js:224:10)
at TTY.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)
reason:
'invalid codepoint at offset 14; unexpected continuation byte',
code: 'INVALID_ARGUMENT',
argument: 'bytes',
value:
Uint8Array [
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2,
85,
191,
249,
11,
135,
135,
240,
108,
241,
58,
179,
37,
153,
124,
191,
59,
19,
156,
29,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
10,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
4 ],
baseType: 'string',
name: null,
type: 'string',
hijackedStack:
'Error: invalid codepoint at offset 14; unexpected continuation byte (argument="bytes", value={"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":2,"13":
truffle(k8s)> test.currentAddr()
'0x0000000000000000000000000000000000000060'
truffle(k8s)> test.currentInt()
<BN: 255bff90b8787f06cf13ab325997cbf3b139c1d>
sym
is set as a byte array and the address
and uint256
values are swapped. They are passed in as[name, new_addr, new_int]
and the function consumes them as
(string memory _sym, address new_addr, uint256 new_int)
however you can see in the above .currentAddr()
and .currentInt()
that the addr is set as a hex encoded value of 10 and the int is set as a BigNumber conversion of the address.
truffle(k8s)> test.setOnlyStringBefore("Name", "0xfe5e669eD4C62A7D4621A604BcC1029171814046", 10)
{ tx:
'0x1e7f54778810d2ea33b604dc2e1791b05b69540cd77a2357e8572f3f3f580588',
receipt:
{ blockHash:
'0x28a3a821daf8b6d8844b330f355ac74e46ee46c900f1be5b748c166357b044c2',
blockNumber: 878,
contractAddress: null,
cumulativeGasUsed: 85007,
from: '0xfe5e669ed4c62a7d4621a604bcc1029171814046',
gasUsed: 85007,
logs: [],
logsBloom:
'0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
status: true,
to: '0x3c7d058ccb934c732674e28b4c45bcc722fb0004',
transactionHash:
'0x1e7f54778810d2ea33b604dc2e1791b05b69540cd77a2357e8572f3f3f580588',
transactionIndex: 0,
rawLogs: [] },
logs: [] }
truffle(k8s)> test.sym()
'Name'
truffle(k8s)> test.currentAddr()
'0xfe5e669eD4C62A7D4621A604BcC1029171814046'
truffle(k8s)> test.currentInt()
<BN: a>
string
is set after address
and uint256
in smart contract function parametersExW3.Contract.send(:Tester, :setOnlyStringAfter, [10, "0x0255bff90b8787f06cf13ab325997cbf3b139c1d", "name"], %{from: @contracts_owner, gas: 6000000})
{:ok, "0xcb1e0f29d7a0fa5bc7822c2d9302b12cc5a22b02a52323d3ac3bad1a01b64634"}
In Truffle ->
truffle(k8s)> let test = await Tester.deployed()
truffle(k8s)> test.sym()
''
//// <--- Value never got set
truffle(k8s)> web3.eth.getTransactionReceipt("0xcb1e0f29d7a0fa5bc7822c2d9302b12cc5a22b02a52323d3ac3bad1a01b64634")
{ blockHash:
'0x146459c31989cc9cfe8ae9025c31701566b5a3da14b74f8e69b97bfe4290d983',
blockNumber: 877,
contractAddress: null,
cumulativeGasUsed: 24203,
from: '0xfe5e669ed4c62a7d4621a604bcc1029171814046',
gasUsed: '0x5e8b',
logs: [],
logsBloom:
'0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
status: false,
to: '0x3c7d058ccb934c732674e28b4c45bcc722fb0004',
transactionHash:
'0xcb1e0f29d7a0fa5bc7822c2d9302b12cc5a22b02a52323d3ac3bad1a01b64634',
transactionIndex: 0 }
I'm trying to call an abi's :symbol
method in an erc721 smartcontract but get an error whenever I call a method that returns and abi function output with "string"
type. Methods that return address
or uint256
work fine... Is this an issue with exw3 or ex_abi? I noticed that this repo doesn't test for smart-contracts calls that have return outputs of "string"
GenServer ContractManager terminating
** (MatchError) no match of right hand side value: <<0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>
(ex_abi 0.5.5) lib/abi/type_decoder.ex:238: ABI.TypeDecoder.decode_bytes/4
(ex_abi 0.5.5) lib/abi/type_decoder.ex:333: anonymous fn/3 in ABI.TypeDecoder.decode_type/3
(elixir 1.11.4) lib/enum.ex:2193: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.5) lib/abi/type_decoder.ex:331: ABI.TypeDecoder.decode_type/3
(ex_abi 0.5.5) lib/abi/type_decoder.ex:188: anonymous fn/3 in ABI.TypeDecoder.do_decode_raw/2
(elixir 1.11.4) lib/enum.ex:2193: Enum."-reduce/3-lists^foldl/2-0-"/3
(ex_abi 0.5.5) lib/abi/type_decoder.ex:185: ABI.TypeDecoder.do_decode_raw/2
(ex_abi 0.5.5) lib/abi/type_decoder.ex:179: ABI.TypeDecoder.decode_raw/2
(exw3 0.6.0) lib/exw3/abi.ex:52: ExW3.Abi.decode_output/3
(exw3 0.6.0) lib/exw3/contract.ex:214: ExW3.Contract.eth_call_helper/4
(exw3 0.6.0) lib/exw3/contract.ex:480: ExW3.Contract.handle_call/3
(stdlib 3.14.2.1) gen_server.erl:715: :gen_server.try_handle_call/4
(stdlib 3.14.2.1) gen_server.erl:744: :gen_server.handle_msg/6
(stdlib 3.14.2.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message (from #PID<0.639.0>): {:call, {:"0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D", :symbol, []}}
This issues is occurring on this line when the output decoded type is "string"
https://github.com/hswick/exw3/blob/master/lib/exw3/abi.ex#L49
A nice enhancement would be to make it easy to interact with the client asynchronously. What I'm thinking is that the Contract process acts as a Supervision tree for Tasks to be created for interacting with the blockchain.
The idea is that send_async and call_async return tasks that have to be awaited on using Task.await. Also these tasks would be managed with the Supervision tree.
Reasoning behind this is that it will probably be a common pattern when people need this functionality to asynchronously so this library can make it very easy.
Support event listeners
Travis is now using old Elixir
and OTP,
which causes mix test
command to fail, but Travis still thinks that it has not failed, because it checks status of the last command and the command is the whole script, which last line simply kills parity
so it is always successful.
The command "bash travis_test.sh" exited with 0.
Does this library support signing transactions with a given PK? I can't seem to find any details in the documentation.
I don't want to use accounts since I'll be using Alchemy RPC.
accounts = ExW3.accounts()
simple_storage_abi = ExW3.Abi.load_abi("abi/MyContract.abi")
ExW3.Contract.start_link
ExW3.Contract.register(:MyContract, abi: simple_storage_abi)
ExW3.Contract.at(:MyContract, Application.get_env(:ethereumex, :contract_address) |> Base.encode16(case: :lower) )
ExW3.Contract.send(:MyContract, :MyFunction, [1, "Foo"], %{from: Enum.at(accounts, 0), gas: 50_000})
"AssertionError [ERR_ASSERTION]: The field to must have byte length of 20\n at Transaction.setter [as to] (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/node_modules/ethereumjs-util/src/object.ts:57:9)\n at /tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/utils/transaction.js:116:23\n at Array.forEach ()\n at initData (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/utils/transaction.js:110:18)\n at new Transaction (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/utils/transaction.js:168:5)\n at Function.fromJSON (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/utils/transaction.js:228:16)\n at StateManager.queueTransaction (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/statemanager.js:371:22)\n at GethApiDouble.eth_sendTransaction (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/subproviders/geth_api_double.js:325:14)\n at GethApiDouble.handleRequest (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/subproviders/geth_api_double.js:109:10)\n at next (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/node_modules/web3-provider-engine/index.js:136:18)\n at GethDefaults.handleRequest (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/subproviders/gethdefaults.js:15:12)\n at next (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/node_modules/web3-provider-engine/index.js:136:18)\n at SubscriptionSubprovider.FilterSubprovider.handleRequest (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/node_modules/web3-provider-engine/subproviders/filters.js:89:7)\n at SubscriptionSubprovider.handleRequest (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/node_modules/web3-provider-engine/subproviders/subscriptions.js:137:49)\n at next (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/node_modules/web3-provider-engine/index.js:136:18)\n at DelayedBlockFilter.handleRequest (/tmp/.mount_ganachnT4wTL/resources/static/node/node_modules/ganache-core/lib/subproviders/delayedblockfilter.js:31:3)"
Thanks @pik694 exw3 will throw an error message if you don't include gas, from, or contract address in a transaction. Which helps with debugging.
Right now the error messages look like this:
** (MatchError) no match of right hand side value: {:error, :missing_gas}
Which is useful, and does tell what is going wrong. But I think it would be better if we could have a more readable and clear error message like
(MissingOptionsError) transaction request is missing the :gas field
I am trying to call a function with the following function signature:
get(bytes32)
I tried the following:
ExW3.Contract.call(:my_contract, :get, ["63cb2f697029ee491b58939796e9013087104b816ce0f51e731e9b03cc50c3b9"])
I get the following error:
[error] GenServer ContractManager terminating
** (RuntimeError) size mismatch for bytes32: "63cb2f697029ee491b58939796e9013087104b816ce0f51e731e9b03cc50c3b9"
lib/abi/type_encoder.ex:178: ABI.TypeEncoder.encode_type/2
lib/abi/type_encoder.ex:199: anonymous fn/2 in ABI.TypeEncoder.encode_type/2
(elixir) lib/enum.ex:1940: Enum."-reduce/3-lists^foldl/2-0-"/3
lib/abi/type_encoder.ex:191: ABI.TypeEncoder.encode_type/2
lib/abi/type_encoder.ex:141: ABI.TypeEncoder.do_encode/3
(exw3) lib/exw3.ex:442: ExW3.encode_method_call/3
(exw3) lib/exw3.ex:697: ExW3.Contract.eth_call_helper/4
(exw3) lib/exw3.ex:959: ExW3.Contract.handle_call/3
Is the hex string supposed to be encoded in a different format before providing in the arguments?
Right now get_filter_changes can return a feed of logs parsed to the contract's events. Would be great to open up the capability to do this for get_logs so you can use the same parsing for both current and historical blocks. Easiest way may be to open up two methods. 1 that would take an ABI, convert it and return the event_attributes and then either open up format_log_data or refactor the format logs code in the Genserver call for :get_filter_changes and make that public. get_logs probably should not be a genserver call as someone may make tons of calls going through 10k's of blocks historically.
Happy to submit this or open to another alternatives!
The current version 0.4.4
is quite old and out of date ๐
Hi,
I'm using exw3 to deploy a ETH 2 Validator Deposit Contract via a Mix Task:
https://github.com/timjp87/panacea/blob/master/apps/beaconchain/lib/mix/tasks/deploy.ex
However, when I run "mix deploy" it can't access ExthCrypto.Hash.Keccak.kec/1 which should be available through the ethereumex dependency, right?
16:56:05.451 [info] Deploying validator deposit contract.
16:56:05.493 [info] Started Ethereumex Application.
16:56:05.595 [info] Got list of accounts from RPC.
16:56:05.596 [info] Started contract manager.
16:56:05.597 [info] Loaded contract ABI.
16:56:05.597 [info] Contract registered.
16:56:05.614 [error] GenServer ContractManager terminating
** (UndefinedFunctionError) function ExthCrypto.Hash.Keccak.kec/1 is undefined (module ExthCrypto.Hash.Keccak is not available)
ExthCrypto.Hash.Keccak.kec("Deposit(bytes,bytes)")
lib/exw3.ex:293: ExW3.encode_event/1
lib/exw3.ex:587: anonymous fn/1 in ExW3.Contract.init_events/1
(elixir) lib/enum.ex:1327: Enum."-map/2-lists^map/1-0-"/2
lib/exw3.ex:583: ExW3.Contract.init_events/1
lib/exw3.ex:720: ExW3.Contract.register_helper/1
lib/exw3.ex:742: ExW3.Contract.handle_cast/2
(stdlib) gen_server.erl:637: :gen_server.try_dispatch/4```
There should be a throw triggered if the args count given is not the same as the input types of the abi. But I need to test this more.
As well, need to ensure the error message is good.
I have been running into a case where if I use ExW3 with a solidity smart contract that needs a bytes
function argument it will fail. I think this might be related to how the encoding works within ExW3, however when I bypass ExW3 and use ABI directly it works:
ABI.encode("setTest(bytes)", [encoded_data])
From what I can tell, there seems to be an extra 64 bytes of data being included in the ExW3 version that I am not sure where it is coming from.
Example:
# Fails when submitted as part of the transaction
# the variable `abi` was parsed from the contract abi file using ExW3
ExW3.Abi.encode_method_call(abi, "setTest", [<<1,2,3,4>>])
"0af724830000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000040102030400000000000000000000000000000000000000000000000000000000"
# Works when submitted as part of the transaction
ABI.encode("setTest(bytes)", [<<1,2,3,4>>]) |> Base.encode16(case: :lower)
"0af72483000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000040102030400000000000000000000000000000000000000000000000000000000"
Looking at the output it seems to be include a second "0x2" block of 64 bytes so I think something is getting wrapped twice.
At the moment when you try to check the receipt of a transaction tx_receipt/1
with a hash of a transaction which has not been mined yet, the function will raise a BadMapError
I think it should be better to return an error ({:error, :not_mined}
in this case) so we don't cut operations of related functions outside of the library,
Adding type specs would be useful
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.