16

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":[]}

1 Answer 1

13

Filters work a little bit different. Filters require LOGs to be emitted from an EVM execution (i.e. a contract). Solidity makes this easy for you by allowing you to fire events (compiled events generate LOGs).

Let's take the following contract:

contract T {
    event res(uint indexed out)
    function echo(uint in) {
         res(i);
    }
}

When the method echo is invoked on the contract it fires the solidity event res. These events can be caught using the eth_newFilter and queried using eth_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 the keccak hash of the event's definition (i.e. res(uint)): keccak("res(uint)"). This then becomes the first argument for the eth_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:

curl -X POST --data '{"jsonrpc":"2.0","method":"eth_newFilter","params":[{"address": "0xaddress", topics:["KECCAK_HASH", "0x6"], "fromBlock":"latest","toBlock":"latest"}],"id":2}' localhost:8545 {"id":2,"jsonrpc":"2.0","result":"0x0"}

Now whenever the method echo(6) is invoked on the contract you'll be able to query the result using the eth_getFilterChanges.

Please see the solidity docs on events for more information.

3
  • 1
    I'm curious how you'd accomplish that same task using web3.js. I believe it would work via github.com/ethereum/wiki/wiki/JavaScript-API#contract-allevents but I can't find any good examples for how to construct the topics array. Commented May 18, 2016 at 19:06
  • @Jeffrey W. top github.com/ethereum/wiki/wiki/JSON-RPC#eth_newFilter said that: A note on specifying topic filters: Topics are order-dependent. A transaction with a log with topics [A, B] will be matched by the following topic filters: [] "anything" [A] "A in first position (and anything after)" [null, B] "anything in first position AND B in second position (and anything after)" [A, B] "A in first position AND B in second position (and anything after)" [[A, B], [A, B]] "(A OR B) in first position AND (A OR B) in second position (and anything after)" what does topics means?it seems Arra
    – Jim Green
    Commented Aug 12, 2016 at 9:12
  • 1
    do you know how I can capture all "Transfer" events triggered by a contract on past blocks? Example: say token T wasn created so I'd like to cature every transfer transaction since its creation so I can see where all of the tokens went. Thanks
    – Diego
    Commented Mar 1, 2018 at 19:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.