Skip to content

Commit

Permalink
Final implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
piomin committed Jun 22, 2018
1 parent 2077a99 commit 77e3a5d
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 53 deletions.
8 changes: 2 additions & 6 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
docker run -d --name ethereum -p 8545:8545 -p 30303:30303 ethereum/client-go --rpc --rpcaddr "0.0.0.0" --rpcapi="db,eth,net,web3,personal" --rpccorsdomain "*" --testnet --fast
docker exec -it ethereum geth attach ipc:/root/.ethereum/testnet/geth.ipc
## Introduction to Blockchain with Java using Ethereum, web3j and Spring Boot [![Twitter](https://img.shields.io/twitter/follow/piotr_minkowski.svg?style=social&logo=twitter&label=Follow%20Me)](https://twitter.com/piotr_minkowski)

https://claudiodangelis.com/ethereum/2018/02/19/exploring-ethereum-platform-accounts.html


https://github.com/matthiaszimmermann/web3j_demo/blob/master/src/main/java/org/matthiaszimmermann/web3j/util/Web3jConstants.java
Detailed description can be found here: [Introduction to Blockchain with Java using Ethereum, web3j and Spring Boot](https://piotrminkowski.wordpress.com/2018/06/22/introduction-to-blockchain-with-java-using-ethereum-web3j-and-spring-boot/)
41 changes: 41 additions & 0 deletions src/main/java/pl/piomin/service/blockchain/BlockchainApp.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,54 @@
package pl.piomin.service.blockchain;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.EthAccounts;
import org.web3j.protocol.core.methods.response.EthCoinbase;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import pl.piomin.service.blockchain.service.BlockchainService;
import rx.Subscription;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.math.BigInteger;

@SpringBootApplication
public class BlockchainApp {

private static final Logger LOGGER = LoggerFactory.getLogger(BlockchainService.class);

@Autowired
Web3j web3j;

public static void main(String[] args) {
SpringApplication.run(BlockchainApp.class, args);
}

@PostConstruct
public void listen() {
Subscription subscription = web3j.transactionObservable().subscribe(tx -> {
LOGGER.info("New tx: id={}, block={}, from={}, to={}, value={}", tx.getHash(), tx.getBlockHash(), tx.getFrom(), tx.getTo(), tx.getValue().intValue());
try {
EthCoinbase coinbase = web3j.ethCoinbase().send();
EthGetTransactionCount transactionCount = web3j.ethGetTransactionCount(tx.getFrom(), DefaultBlockParameterName.LATEST).send();
LOGGER.info("Tx count: {}", transactionCount.getTransactionCount().intValue());
if (transactionCount.getTransactionCount().intValue() % 10 == 0) {
EthGetTransactionCount tc = web3j.ethGetTransactionCount(coinbase.getAddress(), DefaultBlockParameterName.LATEST).send();
Transaction transaction = Transaction.createEtherTransaction(coinbase.getAddress(), tc.getTransactionCount(), tx.getValue(), BigInteger.valueOf(21_000), tx.getFrom(), tx.getValue());
web3j.ethSendTransaction(transaction).send();
}
} catch (IOException e) {
LOGGER.error("Error getting transactions", e);
}
});
LOGGER.info("Subscribed");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.web3j.crypto.CipherException;
import pl.piomin.service.blockchain.model.BlockchainTransaction;
import pl.piomin.service.blockchain.service.BlockchainService;

import java.io.IOException;
Expand All @@ -17,10 +20,9 @@ public class BlockchainController {
@Autowired
BlockchainService service;

@GetMapping("/execute")
public String execute() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, CipherException, IOException {
service.process();
return "ok";
@PostMapping("/transaction")
public BlockchainTransaction execute(@RequestBody BlockchainTransaction transaction) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, CipherException, IOException {
return service.process(transaction);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package pl.piomin.service.blockchain.model;

public class BlockchainTransaction {

private String id;
private int fromId;
private int toId;
private long value;
private boolean accepted;

public BlockchainTransaction() {

}

public BlockchainTransaction(int fromId, int toId, long value) {
this.fromId = fromId;
this.toId = toId;
this.value = value;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public int getFromId() {
return fromId;
}

public void setFromId(int fromId) {
this.fromId = fromId;
}

public int getToId() {
return toId;
}

public void setToId(int toId) {
this.toId = toId;
}

public long getValue() {
return value;
}

public void setValue(long value) {
this.value = value;
}

public boolean isAccepted() {
return accepted;
}

public void setAccepted(boolean accepted) {
this.accepted = accepted;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,14 @@
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.web3j.crypto.*;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.*;
import org.web3j.tx.Transfer;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;
import pl.piomin.service.blockchain.model.BlockchainTransaction;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;

@Service
public class BlockchainService {
Expand All @@ -28,49 +21,25 @@ public class BlockchainService {
@Autowired
Web3j web3j;

public void process() throws CipherException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchProviderException, IOException {
//LOGGER.info("Generating wallet file...");
//String file = WalletUtils.generateLightNewWalletFile("piot123", null);
//String to = "0x948ed3ec7cbec25961990535508a0f950ed5d247";
//Credentials c = WalletUtils.loadCredentials("piot123", "UTC--2018-06-18T14-37-57.614000000Z--816804233e3beaf65f854f9f7a76ace1d1e78f07.json");
//LOGGER.info("Generating wallet file: {}", file);
//EthGetTransactionCount egtc = web3j.ethGetTransactionCount(c.getAddress(), DefaultBlockParameterName.LATEST).send();
//LOGGER.info("Number of transactions: {}", egtc.getTransactionCount().intValue());


//try {
// TransactionReceipt r = Transfer.sendFunds(web3j, c, to, BigDecimal.valueOf(3L), Convert.Unit.ETHER).send();
// LOGGER.info("Transaction: {}", r.getBlockHash());
//} catch (Exception e) {
// LOGGER.error("Error sending transaction", e);
//}
//EthAccounts accounts = web3j.ethAccounts().send();
//accounts.getAccounts().forEach(acc -> LOGGER.info("Account: {}", acc));
//EthGetBalance balance = web3j.ethGetBalance(accounts.getAccounts().get(1), DefaultBlockParameterName.LATEST).send();
//BigInteger i = balance.getBalance();
//LOGGER.info("Balance get: {}", balance.getBalance().longValue());
//RawTransaction trx = RawTransaction.createEtherTransaction(egtc.getTransactionCount(), BigInteger.valueOf(3L), BigInteger.valueOf(100L), to, BigInteger.valueOf(10L));
//LOGGER.info("Transaction created: {}", trx.getData());
//byte[] signedMessage = TransactionEncoder.signMessage(trx, c);
//String hexValue = Numeric.toHexString(signedMessage);
//EthSendTransaction trxSent = web3j.ethSendRawTransaction(hexValue).send();
//if (trxSent.hasError()) {
// LOGGER.info("Transaction error: {}", trxSent.getError().getMessage());
//}
//LOGGER.info("Transaction sent: result={}, hash={}", trxSent.getResult(), trxSent.getTransactionHash());

EthCoinbase coinbase = web3j.ethCoinbase().send();
public BlockchainTransaction process(BlockchainTransaction trx) throws IOException {
EthAccounts accounts = web3j.ethAccounts().send();
EthGetTransactionCount transactionCount = web3j.ethGetTransactionCount(coinbase.getAddress(), DefaultBlockParameterName.LATEST).send();
Transaction transaction = Transaction.createEtherTransaction(coinbase.getAddress(), transactionCount.getTransactionCount(), BigInteger.valueOf(3L), BigInteger.valueOf(21_000), accounts.getAccounts().get(1),BigInteger.valueOf(3L));
EthGetTransactionCount transactionCount = web3j.ethGetTransactionCount(accounts.getAccounts().get(trx.getFromId()), DefaultBlockParameterName.LATEST).send();
Transaction transaction = Transaction.createEtherTransaction(accounts.getAccounts().get(trx.getFromId()), transactionCount.getTransactionCount(), BigInteger.valueOf(trx.getValue()), BigInteger.valueOf(21_000), accounts.getAccounts().get(trx.getToId()),BigInteger.valueOf(trx.getValue()));
EthSendTransaction response = web3j.ethSendTransaction(transaction).send();

if (response.getError() != null) {
trx.setAccepted(false);
LOGGER.info("Tx rejected: {}", response.getError().getMessage());
return trx;
}
trx.setAccepted(true);
String txHash = response.getTransactionHash();
LOGGER.info("Tx hash: {}", txHash);
trx.setId(txHash);
EthGetTransactionReceipt receipt = web3j.ethGetTransactionReceipt(txHash).send();
if (receipt.getTransactionReceipt().isPresent()) {
LOGGER.info("Tx receipt: {}", receipt.getTransactionReceipt().get().getCumulativeGasUsed().intValue());
}
return trx;
}

}
3 changes: 3 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
spring:
application:
name: transaction-service
server:
port: ${PORT:8090}
web3j:
Expand Down

0 comments on commit 77e3a5d

Please sign in to comment.