Skip to content

Commit adc5ecc

Browse files
authored
Merge pull request #10 from web3j/android
1. Added Transfer class for simplifying Ether transactions in line wi…
2 parents 2a4113b + fb7f721 commit adc5ecc

File tree

16 files changed

+569
-109
lines changed

16 files changed

+569
-109
lines changed

README.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,15 @@ Maven
6868
<dependency>
6969
<groupId>org.web3j</groupId>
7070
<artifactId>core</artifactId>
71-
<version>1.0.1</version>
71+
<version>1.0.2</version>
7272
</dependency>
7373
7474
Gradle
7575
------
7676

7777
.. code-block:: groovy
7878
79-
compile ('org.web3j:core:1.0.1')
79+
compile ('org.web3j:core:1.0.2')
8080
8181
8282
Start a client

build.gradle

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ buildscript {
33
mavenCentral()
44
}
55
dependencies {
6-
classpath "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.5.3"
6+
classpath 'io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.5.3'
7+
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.4'
78
}
89
}
910

@@ -21,9 +22,10 @@ apply plugin: 'maven'
2122
apply plugin: 'signing'
2223
apply plugin: 'idea'
2324
apply plugin: 'io.codearte.nexus-staging'
25+
apply plugin: 'com.github.johnrengelman.shadow'
2426

2527
group 'org.web3j'
26-
version '1.0.1'
28+
version '1.0.2'
2729

2830
sourceCompatibility = 1.8
2931

@@ -59,6 +61,7 @@ ext {
5961

6062
repositories {
6163
mavenCentral()
64+
jcenter()
6265
}
6366

6467
// See https://www.petrikainulainen.net/programming/gradle/getting-started-with-gradle-integration-testing/

docs/source/getting_started.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ Maven
1111
<dependency>
1212
<groupId>org.web3j</groupId>
1313
<artifactId>core</artifactId>
14-
<version>1.0.1</version>
14+
<version>1.0.2</version>
1515
</dependency>
1616
1717
Gradle
1818
------
1919

2020
.. code-block:: groovy
2121
22-
compile ('org.web3j:core:1.0.1')
22+
compile ('org.web3j:core:1.0.2')
2323
2424
2525
Start a client
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package org.web3j.generated;
2+
3+
import java.lang.String;
4+
import java.math.BigInteger;
5+
import java.util.Arrays;
6+
import java.util.Collections;
7+
import java.util.concurrent.Future;
8+
import org.web3j.abi.Contract;
9+
import org.web3j.abi.FunctionEncoder;
10+
import org.web3j.abi.TypeReference;
11+
import org.web3j.abi.datatypes.Function;
12+
import org.web3j.abi.datatypes.Utf8String;
13+
import org.web3j.crypto.Credentials;
14+
import org.web3j.protocol.Web3j;
15+
import org.web3j.protocol.core.methods.response.TransactionReceipt;
16+
17+
/**
18+
* <p>Auto generated code.<br>
19+
* <strong>Do not modifiy!</strong><br>
20+
* Please use {@link org.web3j.codegen.SolidityFunctionWrapperGenerator} to update.</p>
21+
*/
22+
public final class Greeter extends Contract {
23+
private static final String BINARY = "606060405260405161026938038061026983398101604052805101600080546c0100000000000000000000000033810204600160a060020a03199091161790558060016000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1060b357805160ff19168380011785555b5060a29291505b8082111560e057600081556001016090565b505050610185806100e46000396000f35b828001600101855582156089579182015b82811115608957825182600050559160200191906001019060c4565b509056606060405260e060020a600035046341c0e1b58114610029578063cfae321714610070575b610002565b34610002576100de6000543373ffffffffffffffffffffffffffffffffffffffff9081169116141561014e5760005473ffffffffffffffffffffffffffffffffffffffff16ff5b3461000257604080516020808201835260008252600180548451600282841615610100026000190190921691909104601f81018490048402820184019095528481526100e094909283018282801561017b5780601f106101505761010080835404028352916020019161017b565b005b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156101405780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b565b820191906000526020600020905b81548152906001019060200180831161015e57829003601f168201915b505050505090509056";
24+
25+
private Greeter(String contractAddress, Web3j web3j, Credentials credentials) {
26+
super(contractAddress, web3j, credentials);
27+
}
28+
29+
public Future<TransactionReceipt> kill() {
30+
Function function = new Function<>("kill", Arrays.asList(), Collections.emptyList());
31+
return executeTransactionAsync(function);
32+
}
33+
34+
public Future<Utf8String> greet() {
35+
Function function = new Function<>("greet",
36+
Arrays.asList(),
37+
Arrays.asList(new TypeReference<Utf8String>() {}));
38+
return executeCallSingleValueReturnAsync(function);
39+
}
40+
41+
public static Future<Greeter> deploy(Web3j web3j, Credentials credentials, BigInteger initialValue, Utf8String _greeting) {
42+
String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(_greeting));
43+
return deployAsync(Greeter.class, web3j, credentials, BINARY, encodedConstructor, initialValue);
44+
}
45+
46+
public static Greeter load(String contractAddress, Web3j web3j, Credentials credentials) {
47+
return new Greeter(contractAddress, web3j, credentials);
48+
}
49+
}

src/integration-test/java/org/web3j/protocol/scenarios/SendEtherIT.java

+30
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package org.web3j.protocol.scenarios;
22

3+
import java.math.BigDecimal;
34
import java.math.BigInteger;
45

56
import org.junit.Test;
67

8+
import org.web3j.abi.Transfer;
79
import org.web3j.protocol.core.methods.request.Transaction;
810
import org.web3j.protocol.core.methods.response.EthSendTransaction;
911
import org.web3j.protocol.core.methods.response.TransactionReceipt;
@@ -17,6 +19,7 @@
1719
* Simple integration test to demonstrate sending of Ether between parties.
1820
*/
1921
public class SendEtherIT extends Scenario {
22+
2023
@Test
2124
public void testTransferEther() throws Exception {
2225
unlockAccount();
@@ -38,4 +41,31 @@ public void testTransferEther() throws Exception {
3841

3942
assertThat(transactionReceipt.getTransactionHash(), is(transactionHash));
4043
}
44+
45+
/*
46+
Valid transaction reciept:
47+
"{"jsonrpc":"2.0",
48+
"id":1,
49+
"result":{
50+
"blockHash":"0x35a865cf2ba4efc3642b17a651f9e896dfebcdea39bfd0741b6f629e1be31a27",
51+
"blockNumber":"0x1c155f",
52+
"contractAddress":null,
53+
"cumulativeGasUsed":"0x5208",
54+
"from":"0x19e03255f667bdfd50a32722df860b1eeaf4d635",
55+
"gasUsed":"0x5208",
56+
"logs":[
57+
58+
],
59+
"root":"327e1e81c85cb710fe81cb8c0f824e9e49c3bf200e5e1149f589140145df10e3",
60+
"to":"0x9c98e381edc5fe1ac514935f3cc3edaa764cf004",
61+
"transactionHash":"0x16e41aa9d97d1c3374a4cb9599febdb24d4d5648b607c99e01a8e79e3eab2c34",
62+
"transactionIndex":"0x0"
63+
}
64+
*/
65+
@Test
66+
public void testTransfer() throws Exception {
67+
TransactionReceipt transactionReceipt = Transfer.sendFunds(
68+
parity, ALICE, BOB.getAddress(), BigDecimal.valueOf(0.2), Convert.Unit.ETHER);
69+
assertFalse(transactionReceipt.getBlockHash().isEmpty());
70+
}
4171
}

src/main/java/org/web3j/abi/Contract.java

+2-66
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,27 @@
1313
import org.web3j.abi.datatypes.Function;
1414
import org.web3j.abi.datatypes.Type;
1515
import org.web3j.crypto.Credentials;
16-
import org.web3j.crypto.TransactionEncoder;
1716
import org.web3j.protocol.Web3j;
1817
import org.web3j.protocol.core.DefaultBlockParameterName;
1918
import org.web3j.protocol.core.methods.request.RawTransaction;
2019
import org.web3j.protocol.core.methods.request.Transaction;
2120
import org.web3j.protocol.core.methods.response.*;
2221
import org.web3j.protocol.exceptions.TransactionTimeoutException;
23-
import org.web3j.utils.Numeric;
2422

2523

2624
/**
2725
* Solidity contract type abstraction for interacting with smart contracts via native Java types.
2826
*/
29-
public abstract class Contract {
27+
public abstract class Contract extends ManagedTransaction {
3028

3129
private static final BigInteger GAS_PRICE = BigInteger.valueOf(50_000_000_000L);
3230
private static final BigInteger GAS_LIMIT = BigInteger.valueOf(2_000_000);
3331

34-
private static final int SLEEP_DURATION = 15000;
35-
private static final int ATTEMPTS = 40;
36-
3732
private String contractAddress;
38-
private Web3j web3j;
39-
private Credentials credentials;
4033

4134
protected Contract(String contractAddress, Web3j web3j, Credentials credentials) {
35+
super(web3j, credentials);
4236
this.contractAddress = contractAddress;
43-
this.web3j = web3j;
44-
this.credentials = credentials;
4537
}
4638

4739
public String getContractAddress() {
@@ -138,21 +130,6 @@ protected TransactionReceipt executeTransaction(
138130
return signAndSend(rawTransaction);
139131
}
140132

141-
private TransactionReceipt signAndSend(RawTransaction rawTransaction)
142-
throws InterruptedException, ExecutionException, TransactionTimeoutException{
143-
byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
144-
String hexValue = Numeric.toHexString(signedMessage);
145-
146-
// This might be a good candidate for using functional composition with CompletableFutures
147-
EthSendTransaction transactionResponse = web3j.ethSendRawTransaction(hexValue)
148-
.sendAsync().get();
149-
150-
String transactionHash = transactionResponse.getTransactionHash();
151-
152-
return waitForTransactionReceipt(transactionHash);
153-
}
154-
155-
156133
/**
157134
* Execute the provided function as a transaction asynchronously.
158135
*
@@ -173,47 +150,6 @@ protected Future<TransactionReceipt> executeTransactionAsync(Function function)
173150
return result;
174151
}
175152

176-
private BigInteger getNonce(String address) throws InterruptedException, ExecutionException {
177-
EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(
178-
address, DefaultBlockParameterName.LATEST).sendAsync().get();
179-
180-
return ethGetTransactionCount.getTransactionCount();
181-
}
182-
183-
private TransactionReceipt waitForTransactionReceipt(
184-
String transactionHash) throws InterruptedException, ExecutionException,
185-
TransactionTimeoutException {
186-
187-
return getTransactionReceipt(transactionHash, SLEEP_DURATION, ATTEMPTS);
188-
}
189-
190-
private TransactionReceipt getTransactionReceipt(
191-
String transactionHash, int sleepDuration, int attempts)
192-
throws InterruptedException, ExecutionException, TransactionTimeoutException {
193-
194-
Optional<TransactionReceipt> receiptOptional =
195-
sendTransactionReceiptRequest(transactionHash);
196-
for (int i = 0; i < attempts; i++) {
197-
if (!receiptOptional.isPresent()) {
198-
Thread.sleep(sleepDuration);
199-
receiptOptional = sendTransactionReceiptRequest(transactionHash);
200-
} else {
201-
return receiptOptional.get();
202-
}
203-
}
204-
205-
throw new TransactionTimeoutException("Transaction receipt was not generated after " +
206-
((sleepDuration * attempts) / 1000 + " seconds"));
207-
}
208-
209-
private Optional<TransactionReceipt> sendTransactionReceiptRequest(
210-
String transactionHash) throws InterruptedException, ExecutionException {
211-
EthGetTransactionReceipt transactionReceipt =
212-
web3j.ethGetTransactionReceipt(transactionHash).sendAsync().get();
213-
214-
return transactionReceipt.getTransactionReceipt();
215-
}
216-
217153
protected EventValues extractEventParameters(
218154
Event event, TransactionReceipt transactionReceipt) {
219155

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package org.web3j.abi;
2+
3+
import java.math.BigInteger;
4+
import java.util.Optional;
5+
import java.util.concurrent.ExecutionException;
6+
7+
import org.web3j.crypto.Credentials;
8+
import org.web3j.crypto.TransactionEncoder;
9+
import org.web3j.protocol.Web3j;
10+
import org.web3j.protocol.core.DefaultBlockParameterName;
11+
import org.web3j.protocol.core.methods.request.RawTransaction;
12+
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
13+
import org.web3j.protocol.core.methods.response.EthGetTransactionReceipt;
14+
import org.web3j.protocol.core.methods.response.EthSendTransaction;
15+
import org.web3j.protocol.core.methods.response.TransactionReceipt;
16+
import org.web3j.protocol.exceptions.TransactionTimeoutException;
17+
import org.web3j.utils.Numeric;
18+
19+
20+
/**
21+
* Generic transaction manager
22+
*/
23+
public abstract class ManagedTransaction {
24+
25+
private static final BigInteger GAS_PRICE = BigInteger.valueOf(50_000_000_000L);
26+
private static final BigInteger GAS_LIMIT = BigInteger.valueOf(2_000_000);
27+
28+
private static final int SLEEP_DURATION = 15000;
29+
private static final int ATTEMPTS = 40;
30+
31+
protected Web3j web3j;
32+
protected Credentials credentials;
33+
34+
protected ManagedTransaction(Web3j web3j, Credentials credentials) {
35+
this.web3j = web3j;
36+
this.credentials = credentials;
37+
}
38+
39+
protected TransactionReceipt signAndSend(RawTransaction rawTransaction)
40+
throws InterruptedException, ExecutionException, TransactionTimeoutException{
41+
byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
42+
String hexValue = Numeric.toHexString(signedMessage);
43+
44+
// This might be a good candidate for using functional composition with CompletableFutures
45+
EthSendTransaction transactionResponse = web3j.ethSendRawTransaction(hexValue)
46+
.sendAsync().get();
47+
48+
String transactionHash = transactionResponse.getTransactionHash();
49+
50+
return waitForTransactionReceipt(transactionHash);
51+
}
52+
53+
protected BigInteger getNonce(String address) throws InterruptedException, ExecutionException {
54+
EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(
55+
address, DefaultBlockParameterName.LATEST).sendAsync().get();
56+
57+
return ethGetTransactionCount.getTransactionCount();
58+
}
59+
60+
private TransactionReceipt waitForTransactionReceipt(
61+
String transactionHash) throws InterruptedException, ExecutionException,
62+
TransactionTimeoutException {
63+
64+
return getTransactionReceipt(transactionHash, SLEEP_DURATION, ATTEMPTS);
65+
}
66+
67+
private TransactionReceipt getTransactionReceipt(
68+
String transactionHash, int sleepDuration, int attempts)
69+
throws InterruptedException, ExecutionException, TransactionTimeoutException {
70+
71+
Optional<TransactionReceipt> receiptOptional =
72+
sendTransactionReceiptRequest(transactionHash);
73+
for (int i = 0; i < attempts; i++) {
74+
if (!receiptOptional.isPresent()) {
75+
Thread.sleep(sleepDuration);
76+
receiptOptional = sendTransactionReceiptRequest(transactionHash);
77+
} else {
78+
return receiptOptional.get();
79+
}
80+
}
81+
82+
throw new TransactionTimeoutException("Transaction receipt was not generated after " +
83+
((sleepDuration * attempts) / 1000 + " seconds"));
84+
}
85+
86+
private Optional<TransactionReceipt> sendTransactionReceiptRequest(
87+
String transactionHash) throws InterruptedException, ExecutionException {
88+
EthGetTransactionReceipt transactionReceipt =
89+
web3j.ethGetTransactionReceipt(transactionHash).sendAsync().get();
90+
91+
return transactionReceipt.getTransactionReceipt();
92+
}
93+
}

0 commit comments

Comments
 (0)