Мой вариант использования следующий: я хотел бы, чтобы демон следил за тем, как пользователи взаимодействуют с моим смарт-контрактом. Как я это вижу, я смотрю на входящие блоки и пытаюсь декодировать входные данные с адресом to, соответствующим моему контракту. Мне не удалось найти в web3J способ декодирования данных.
1- Есть ли способ декодировать данные с помощью web3J?
2- Есть ли у меня другой способ достичь своей цели, кроме декодирования входных данных? События кажутся мне трудным выбором, так как я не смогу легко следить за всеми вещами. И эти методы не могут применяться к смарт-контрактам, которыми я не владею.
Спасибо за помощь.
Я думаю, что-то вроде первого вопроса. Если вы посмотрите, что такое транзакция, для узла это просто большая длинная строка байтов. Если байты можно преобразовать в ASCII, вы можете использовать метод
web3.toAscii()
Это может дать или не дать вам что-то. Например, вот tx a, который я сделал на Ropsten, где вы получаете обратно некоторые читаемые входные данные и некоторые нечитаемые данные: https://ropsten.etherscan.io/tx/0xe4058b8f612f20600d8aae1230d93b7b5c63398ddde0a3a6aed236659f425c0e (просто нажмите вход Convert to Ascii внизу )
Тем не менее, лучший (самый простой) способ сделать это — владеть децентрализованным приложением. Поэтому, когда они заполняют форму, вы просто сохраняете вводимые данные. Следующим лучшим, как вы сказали, является использование событий. Они раздражают, но у вас может быть только одно длинное событие в начале ваших контрактов:
contract Test {
event Input(string desc, address _party, uint _input1, string _input2);
function somefunc(uint _input1, string _input2) returns(bool success){
Input("Input",msg.sender,_input1,_input2);
return true;
}
}
Но тогда для чужих контрактов вам не повезло, так как у вас нет этого события.
ERC20 javaToken = ERC20.load(contractAddress, web3, creds, new DefaultGasProvider());
System.out.println("ALL HISTORY OF TT");
javaToken.transferEventFlowable(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST)
.subscribe(event
-> System.out.println("from: " + event._from + ", to: " + event._to + ", value: " + event._value));
Я думаю, это поможет вам
Логика, которую я использовал, выглядит следующим образом:
web3j.transactionflowable.subscribe(tx -> {
checkIfMyTransaction(tx.getTo, tx.getHash);
});
public void checkIfMyTransaction(String toAddress, String txHash){
// check data base if the address belong to my application and then following logic. This can be contract address or wallet address.
// if contract address:
EthTransaction ethTransaction=web3j.getTransactionByHash(txHash).send;
Transaction transaction=ethTransaction.getTransaction.get();
transaction.getFrom;
transaction.getBlockNumer;
// Take all info like blocknumber, blockhash etc from above call. For input data, we create new method.
decodeInput(transaction.getInput);
}
public void decodeInput(String data) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
String inputData = data;
String method = inputData.substring(0,10);
log.info("Method >>>>>> " +method);
String to = inputData.substring(10,74);
String value = inputData.substring(74);
Method refMethod = TypeDecoder.class.getDeclaredMethod("decode",String.class,int.class,Class.class);
refMethod.setAccessible(true);
Address address = (Address)refMethod.invoke(null,to,0,Address.class);
log.info("Address>>>>>> " +address.toString());
Uint256 amount = (Uint256) refMethod.invoke(null,value,0,Uint256.class);
log.info("amount >>>>>> " +amount);
}
У меня было такое же требование, и я начал взламывать его в генераторе контрактов web3j. Из-за (ИМХО) чрезмерно сложного подхода я отказался от этого и вместо этого написал для этого свою собственную автономную библиотеку Java. Вам вообще не нужен web3j, вам понадобится только ABI контракта в формате JSON.
https://github.com/rvullriede/evm-аби-декодер
Пример использования:
// Abi can be found here: https://etherscan.io/address/0x7a250d5630b4cf539739df2c5dacb4c659f2488d#code
AbiDecoder uniswapv2Abi=new AbiDecoder(pathToAbiJsonFile).getFile());
// tx: https://etherscan.io/tx/0xde2b61c91842494ac208e25a2a64d99997c382f6aaf0719d6a719b5cff1f8a07
String inputData="0x18cbafe5000000000000000000000000000000000000000000000000000000000098968000000000000000000000000000000000000000000000000000165284993ac4ac00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000d4cf8e47beac55b42ae58991785fa326d9384bd10000000000000000000000000000000000000000000000000000000062e8d8510000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2";
/**
* # Name Type Data
* ----------------------------------------------------------------------
* 0 amountIn uint256 10000000
* 1 amountOutMin uint256 6283178947560620
* 2 path address[] 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
* 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
* 3 to address 0xD4CF8e47BeAC55b42Ae58991785Fa326d9384Bd1
* 4 deadline uint256 1659426897
*/
DecodedFunctionCall decodedFunctionCall=uniswapv2Abi.decodeFunctionCall(inputData);
System.out.println(decodedFunctionCall.getName()); // prints swapExactTokensForETH
Это все еще молодой проект, если у вас возникнут проблемы (например, с конкретными контрактами), сообщите мне об этом через средство отслеживания проблем проекта github.
Надеюсь, это поможет!
Кирилл
Кирилл