问题
I have many questions about the workflow ( sequence ) of interacting with the smart contract from Java application, so I will first explain what I have done and then put my questions, and if something wrong in my understanding please let me know.
1- I have written smart contract 2- Use truffle to get the smart contract java wrapper.(contract.java) 3- Use testrpc to test the contract
I have 2 class uses testrpc accounts (credentials) to interact with the smart contract and call its functions
Each class (node1.java, node2.java) call a function in the smart contract called (send) to send their data to the chain.
I have added an event which trigger if the 2 nodes have sent there data
What I don't understand is, how I can let the java code ( Let say MainProgram.class) always check for that event. Because I need to check if both nodes send their data, then I will call another function to analyse this data.
How I can manage, control and check what transactions have been done or not, I mean how I can use the events in java code and let the code run forever and check if the this event happen, do action.
Hope I can explain what I need clearly
Thank you in advance.
回答1:
My answer to one of your previous questions applies here. Yes, you will probably want to setup a dedicated process to listen for events. But, you don't need an account or even be the owner or client of a smart contract to listen to events on the public blockchain (This is why it's considered "public").
To listen to events, all you need are the contract ABI and the contract's address. Both should be easy for you to get. You can set up a listener on all of the events this contract emits. From the web3j documentation:
You use the EthFilter type to specify the topics that you wish to apply to the filter. This can include the address of the smart contract you wish to apply the filter to. You can also provide specific topics to filter on. Where the individual topics represent indexed parameters on the smart contract:
EthFilter filter = new EthFilter(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST, <contract-address>) [.addSingleTopic(...) | .addOptionalTopics(..., ...) | ...];
This filter can then be created using a similar syntax to the block and transaction filters above:
web3j.ethLogObservable(filter).subscribe(log -> { ... });
Specifying the block parameters let you decide how far back in the history you want to start processing events. Keep in mind that in Ethereum, events are actually logs on the blockchain. When you listen for events, you're actually looking for activity in the logs as blocks are added to the chain. Therefore, you can go as far back in history as you want and look at older blocks to process old events as well.
To listen to all events in your contract, you would just do:
EthFilter filter = new EthFilter(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST, <CONTRACT_ADDRESS>);
web3.ethLogObservable(filter).subscribe(log -> System.out.println(log.toString());
IMPORTANT NOTE ON THE CONTRACT ADDRESS WITH ETHFILTER - There is a bug in Web3j for the contract address in EthFilter
. The API doesn't like the leading '0x' in the contract address. To get around this, if you're using the contract object, send the contract address in using contract.getContractAddress().substring(2);
If you're interested in specific events, you need to add a topic to your filter. The example below will listen for all MyEvent
events thrown which contains a single indexed address parameter and two non-indexed uint256
params:
Web3j web3j = Web3j.build(new HttpService());
Event event = new Event("MyEvent",
Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}, new TypeReference<Uint256>() {}));
EthFilter filter = new EthFilter(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST, <CONTRACT_ADDRESS>);
filter.addSingleTopic(EventEncoder.encode(event));
web3j.ethLogObservable(filter).subscribe(log -> System.out.println(log.toString()));
The above can run in any server process. Within the server process, you can connect to the network either through a local node (the default localhost when using new HttpService()
). Or, you can sign up with Infura, create an API key, and use and use their node cluster (example Ropsten URL: new HttpService("https://ropsten.infura.io/<YOUR_API_KEY>");
)
来源:https://stackoverflow.com/questions/49083825/interacting-with-the-smart-contract-from-java-application-we3j