Ok! I solved it.
First i created my own Contract, which is extend Contract from org.web3j.tx. Overrided two methods (i need to receive multiple values from contract): executeCallMultipleValueReturnAsync, executeCallMultipleValueReturn but with identical content as in Contract and created own executeCall method, which is identical to private executeCall from web3j Contract, but instead of pass DefaultBlockParameterName.LATEST to web3j.ethCall i am passing new DefaultBlockParameterNumber(blockNumber) with desired blockNumber as BigInteger. So here is:
public class MyEthereumContract extends Contract {
private String contractAddress;
private BigInteger blockNumber;
protected MyEthereumContract(String contractBinary, String contractAddress, Web3j web3j,
TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
super(contractBinary, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
}
protected MyEthereumContract(String contractBinary, String contractAddress, Web3j web3j, Credentials credentials,
BigInteger gasPrice, BigInteger gasLimit) {
super(contractBinary, contractAddress, web3j, credentials, gasPrice, gasLimit);
}
protected MyEthereumContract(String contractBinary, String contractAddress, Web3j web3j, Credentials credentials,
BigInteger gasPrice, BigInteger gasLimit,
BigInteger blockNumber) {
super(contractBinary, contractAddress, web3j, credentials, gasPrice, gasLimit);
this.contractAddress = contractAddress;
this.blockNumber = blockNumber;
}
@Override
protected CompletableFuture<List<Type>> executeCallMultipleValueReturnAsync(Function function) {
return Async.run(() -> executeCallMultipleValueReturn(function));
}
@Override
protected List<Type> executeCallMultipleValueReturn(
Function function) throws InterruptedException, ExecutionException {
return executeCall(function);
}
private List<Type> executeCall(
Function function) throws InterruptedException, ExecutionException {
String encodedFunction = FunctionEncoder.encode(function);
org.web3j.protocol.core.methods.response.EthCall ethCall = web3j.ethCall(
Transaction.createEthCallTransaction(
transactionManager.getFromAddress(), contractAddress, encodedFunction),
new DefaultBlockParameterNumber(blockNumber))
.sendAsync().get();
String value = ethCall.getValue();
return FunctionReturnDecoder.decode(value, function.getOutputParameters());
}
}
Than i added new constructor to class, generated from contract, which i am calling from load method
Take a look at the code generated by the wrappers
Function name()
for a ERC20
public RemoteCall<String> name() {
final Function function = new Function(FUNC_NAME,
Arrays.<Type>asList(),
Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
return executeRemoteCallSingleValueReturn(function, String.class);
}
And transferFrom()
for ERC20
public RemoteCall<TransactionReceipt> transferFrom(String _from, String _to, BigInteger _value) {
final Function function = new Function(
FUNC_TRANSFERFROM,
Arrays.<Type>asList(new org.web3j.abi.datatypes.Address(_from),
new org.web3j.abi.datatypes.Address(_to),
new org.web3j.abi.datatypes.generated.Uint256(_value)),
Collections.<TypeReference<?>>emptyList());
return executeRemoteCallTransaction(function);
}
When called it will execute a function executeRemoteCallXXXXX(function)
.
To construct a dynamic class you have to construct function
which you pass the name of the function to invoke, a list with input parameters and a list with output parameters. See here https://github.com/web3j/web3j/blob/a0ece8b8fb76397c24592cc9d59578cdabbf751c/abi/src/main/java/org/web3j/abi/datatypes/Function.java#L17-L22.
public Function(String name, List<Type> inputParameters,
List<TypeReference<?>> outputParameters) {
this.name = name;
this.inputParameters = inputParameters;
this.outputParameters = convert(outputParameters);
}
Best Answer
I guess sort of for the first question. If you look at what a transaction is, to a node its just a big long byte string. If the bytes are convertible to ASCII, you can use use the
That may or may not give you something. For instance, here's a tx a I did on Ropsten where you get some readable input data back and some non-readable data: https://ropsten.etherscan.io/tx/0xe4058b8f612f20600d8aae1230d93b7b5c63398ddde0a3a6aed236659f425c0e (just click the input Convert to Ascii at the bottom)
That said, the best (easiest) way to do this is to own the dapp. So when they fill out a form, you just save the input data. The next best like you said is to use Events. They are annoying, but you could have just one long event at the beginning of your contracts:
But then for other people's contracts your out of luck since you don't have this event.