I am trying to create mini-service which would allow me to subscribe for incoming Ethereum transactions (coinbase example).
I thought that in Ethereum it could be done with eth_newFilter
and eth_getFilterChanges
(JSON RPC) methods but I am doing something wrong. Could you please give any clue or maybe I completely misunderstood the concept of the filters? I know that there is eth_newPendingTransactionFilter
method, but I thought maybe there is a better way to achieve my goal? Right now I am following these steps:
Start geth
I know that I shouldn't open RPC like this, but right now I have done this for simplicity.
geth --dev --rpc --rpcapi "personal,miner,db,shh,admin,eth" --rpcaddr "localhost" --rpcport "8545"
Check accounts:
➜ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_accounts","params": [],"id":1}' localhost:8545
{"id":1,"jsonrpc":"2.0","result":[]}
Create two accounts:
➜ curl -X POST --data '{"jsonrpc":"2.0","method":"personal_newAccount","params":["password"],"id":1}' localhost:8545
{"id":1,"jsonrpc":"2.0","result":"0x0199147554059ce1fa572600256dd6030db19658"}
➜ curl -X POST --data '{"jsonrpc":"2.0","method":"personal_newAccount","params":["password"],"id":1}' localhost:8545
{"id":1,"jsonrpc":"2.0","result":"0x350060daba130bed0809126c67240d38f27c4cff"}
Start miner:
➜ curl -X POST --data '{"jsonrpc":"2.0","method":"miner_start","params":["1"],"id":1}' localhost:8545
{"id":1,"jsonrpc":"2.0","result":true}
Create new filter:
➜ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newFilter","params":[{"address": "0x350060daba130bed0809126c67240d38f27c4cff", "fromBlock":"latest","toBlock":"latest"}],"id":2}' localhost:8545
{"id":2,"jsonrpc":"2.0","result":"0x0"}
Unlock account and send transaction:
➜ curl -X POST --data '{"jsonrpc":"2.0","method":"personal_unlockAccount","params":["0x0199147554059ce1fa572600256dd6030db19658","password"],"id":1}' localhost:8545
{"id":1,"jsonrpc":"2.0","result":true}
➜ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_sendTransaction","params":[{"from": "0x0199147554059ce1fa572600256dd6030db19658","to": "0x350060daba130bed0809126c67240d38f27c4cff", "value":"0x1" }],"id":1}' localhost:8545
{"id":1,"jsonrpc":"2.0","result":"0xd0e910765a920b30fc2e70de6fc4557e74ad69c584d810f70188d254db7119bb"}
Wait for transaction proceed by local node:
➜ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x350060daba130bed0809126c67240d38f27c4cff"],"id":1}' localhost:8545
{"id":1,"jsonrpc":"2.0","result":"0x01"}
Check filter and got nothing 🙁
➜ curl -X POST --data '{"jsonrpc":"2.0","method":"eth_getFilterChanges","params":["0x00"],"id":1}' localhost:8545
{"id":1,"jsonrpc":"2.0","result":[]}
Best Answer
Filters work a little bit different. Filters require
LOG
s to be emitted from an EVM execution (i.e. a contract). Solidity makes this easy for you by allowing you to fireevent
s (compiledevent
s generateLOG
s).Let's take the following contract:
When the method
echo
is invoked on the contract it fires the solidity eventres
. These events can be caught using theeth_newFilter
and queried usingeth_getFilterChanges
.When creating a filter for a specific event (e.g.
res
) we need to derive the event signature first. Signatures are generated using the first 4 bytes of thekeccak
hash of the event's definition (i.e.res(uint)
):keccak("res(uint)")
. This then becomes the first argument for theeth_newFilter
's topics.Any of the arguments in the definition of the event that have the
indexed
keyword (as in the example contract listed above) can also be used to filter on. Let's say we only want to catch events for the number 6, we would then construct the following JSON-RPC:Now whenever the method
echo(6)
is invoked on the contract you'll be able to query the result using theeth_getFilterChanges
.Please see the solidity docs on events for more information.