|
76 | 76 | import org.web3j.protocol.core.JsonRpc2_0Web3j;
|
77 | 77 | import org.web3j.protocol.core.methods.request.EthFilter;
|
78 | 78 | import org.web3j.protocol.core.methods.response.EthBlock;
|
79 |
| -import org.web3j.protocol.core.methods.response.EthCall; |
80 | 79 | import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
|
81 | 80 | import org.web3j.protocol.core.methods.response.EthGetTransactionReceipt;
|
82 | 81 | import org.web3j.protocol.core.methods.response.EthLog;
|
@@ -356,17 +355,17 @@ public CompletableFuture<Transaction> invokeSmartContract(
|
356 | 355 |
|
357 | 356 | // if we are expecting a return value, we try to invoke as a method call, otherwise, we try a transaction
|
358 | 357 | if (outputParameters.size() > 0) {
|
359 |
| - Transaction resultFromEthCall = invokeFunctionByMethodCall(encodedFunction, smartContractAddress, outputs, function.getOutputParameters()); |
360 |
| - |
361 |
| - if (resultFromEthCall != null) { |
362 |
| - return CompletableFuture.completedFuture(resultFromEthCall); |
363 |
| - } else { |
364 |
| - CompletableFuture<Transaction> future = new CompletableFuture<>(); |
365 |
| - future.completeExceptionally(new InvokeSmartContractFunctionFailure("Failed to invoke read-only smart contract function")); |
366 |
| - return future; |
367 |
| - } |
| 358 | + return this.invokeFunctionByMethodCall( |
| 359 | + encodedFunction, |
| 360 | + smartContractAddress, |
| 361 | + outputs, |
| 362 | + function.getOutputParameters()); |
368 | 363 | } else {
|
369 |
| - return this.invokeFunctionByTransaction(waitFor, encodedFunction, smartContractAddress, timeoutMillis); |
| 364 | + return this.invokeFunctionByTransaction( |
| 365 | + waitFor, |
| 366 | + encodedFunction, |
| 367 | + smartContractAddress, |
| 368 | + timeoutMillis); |
370 | 369 | }
|
371 | 370 | } catch (Exception e) {
|
372 | 371 | log.error("Decoding smart contract function call failed. Reason: {}", e.getMessage());
|
@@ -572,37 +571,34 @@ private EthFilter generateFilter(String smartContractAddress, Event event, int p
|
572 | 571 | return filter;
|
573 | 572 | }
|
574 | 573 |
|
575 |
| - private Transaction invokeFunctionByMethodCall(String encodedFunction, String scAddress, List<Parameter> outputs, |
576 |
| - List<TypeReference<Type>> returnTypes) throws InvokeSmartContractFunctionFailure { |
577 |
| - try { |
578 |
| - org.web3j.protocol.core.methods.request.Transaction transaction = org.web3j.protocol.core.methods.request.Transaction |
579 |
| - .createEthCallTransaction(credentials.getAddress(), scAddress, encodedFunction); |
580 |
| - EthCall ethCall = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send(); |
581 |
| - List<Type> decoded = FunctionReturnDecoder.decode(ethCall.getValue(), returnTypes); |
582 |
| - |
583 |
| - if (returnTypes.size() != decoded.size()) |
584 |
| - throw new InvokeSmartContractFunctionFailure("Failed to invoke function by ethCall"); |
585 |
| - |
586 |
| - Transaction tx = new LinearChainTransaction(); |
587 |
| - tx.setState(TransactionState.RETURN_VALUE); |
588 |
| - List<Parameter> returnedValues = new ArrayList<>(); |
589 |
| - |
590 |
| - for (int i = 0; i < decoded.size(); i++) { |
591 |
| - returnedValues.add(Parameter |
592 |
| - .builder() |
593 |
| - .name(outputs.get(i).getName()) |
594 |
| - .value(ParameterDecoder.decode(decoded.get(i))) |
595 |
| - .build()); |
596 |
| - } |
| 574 | + private CompletableFuture<Transaction> invokeFunctionByMethodCall(String encodedFunction, String scAddress, List<Parameter> outputs, |
| 575 | + List<TypeReference<Type>> returnTypes) { |
| 576 | + org.web3j.protocol.core.methods.request.Transaction transaction = org.web3j.protocol.core.methods.request.Transaction |
| 577 | + .createEthCallTransaction(credentials.getAddress(), scAddress, encodedFunction); |
| 578 | + |
| 579 | + return web3j.ethCall(transaction, DefaultBlockParameterName.LATEST) |
| 580 | + .sendAsync() |
| 581 | + .thenApply(ethCall -> FunctionReturnDecoder.decode(ethCall.getValue(), returnTypes)) |
| 582 | + .thenApply(decoded -> { |
| 583 | + if (returnTypes.size() != decoded.size()) |
| 584 | + throw new InvokeSmartContractFunctionFailure("Failed to invoke read-only Ethereum smart contract function"); |
| 585 | + |
| 586 | + Transaction tx = new LinearChainTransaction(); |
| 587 | + tx.setState(TransactionState.RETURN_VALUE); |
| 588 | + List<Parameter> returnedValues = new ArrayList<>(); |
| 589 | + |
| 590 | + for (int i = 0; i < decoded.size(); i++) { |
| 591 | + returnedValues.add(Parameter |
| 592 | + .builder() |
| 593 | + .name(outputs.get(i).getName()) |
| 594 | + .value(ParameterDecoder.decode(decoded.get(i))) |
| 595 | + .build()); |
| 596 | + } |
597 | 597 |
|
598 |
| - tx.setReturnValues(returnedValues); |
| 598 | + tx.setReturnValues(returnedValues); |
599 | 599 |
|
600 |
| - return tx; |
601 |
| - } catch (Exception e) { |
602 |
| - log.debug("Failed to execute smart contract function via eth_call. Reason: {}", e.getMessage()); |
603 |
| - // this is important so we know we should try a transaction |
604 |
| - return null; |
605 |
| - } |
| 600 | + return tx; |
| 601 | + }); |
606 | 602 | }
|
607 | 603 |
|
608 | 604 | private CompletableFuture<Transaction> invokeFunctionByTransaction(long waitFor, String encodedFunction, String scAddress, long timeoutMillis) {
|
@@ -652,21 +648,17 @@ private CompletableFuture<TransactionReceipt> waitUntilTransactionIsMined(final
|
652 | 648 | result.completeExceptionally(exception);
|
653 | 649 | } else {
|
654 | 650 | EthGetTransactionReceipt receipt = web3j.ethGetTransactionReceipt(txHash).send();
|
655 |
| - if(receipt != null && receipt.getTransactionReceipt().isPresent()) { |
| 651 | + if (receipt != null && receipt.getTransactionReceipt().isPresent()) { |
656 | 652 | result.complete(receipt.getResult());
|
657 | 653 | }
|
658 | 654 | }
|
659 |
| - |
660 | 655 | } catch (IOException e) {
|
661 | 656 | result.completeExceptionally(e);
|
662 | 657 | }
|
663 | 658 | });
|
664 | 659 |
|
665 | 660 | //dispose the flowable when the CompletableFuture completes (either when detecting an event, or manually)
|
666 |
| - result.whenComplete( |
667 |
| - (v, e) -> { |
668 |
| - subscription.dispose(); |
669 |
| - }); |
| 661 | + result.whenComplete((v, e) -> subscription.dispose()); |
670 | 662 |
|
671 | 663 | return result;
|
672 | 664 | }
|
|
0 commit comments