Skip to content

Commit fb7f721

Browse files
committed
1. Added Transfer class for simplifying Ether transactions in line with working with smart contracts.
2. Added generated Greeter. 3. Creation of isIntegerValue utility function. 4. Added Gradle shadow plugin for building fat jars. 5. Created command line tools for managing wallets. 6. Bumped version.
1 parent 2a4113b commit fb7f721

File tree

16 files changed

+569
-109
lines changed

16 files changed

+569
-109
lines changed

README.rst

Lines changed: 2 additions & 2 deletions
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

Lines changed: 5 additions & 2 deletions
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

Lines changed: 2 additions & 2 deletions
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
Lines changed: 49 additions & 0 deletions
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

Lines changed: 30 additions & 0 deletions
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

Lines changed: 2 additions & 66 deletions
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

Lines changed: 93 additions & 0 deletions
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)