diff --git a/.circleci/config.yml b/.circleci/config.yml
index 278485a..53fec70 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,27 +1,48 @@
-version: 2.1
+version: '2.1'
jobs:
analyze:
docker:
- - image: 'cimg/openjdk:11.0'
+ - image: 'cimg/openjdk:21.0.2'
steps:
- checkout
- run:
name: Analyze on SonarCloud
- command: mvn verify sonar:sonar
-
-executors:
- jdk:
- docker:
- - image: 'cimg/openjdk:11.0'
+ command: mvn web3j:generate-sources verify sonar:sonar -DskipTests
+ test:
+ executor: machine_executor_amd64
+ steps:
+ - checkout
+ - run:
+ name: Install OpenJDK 21
+ command: |
+ java -version
+ sudo apt-get update && sudo apt-get install openjdk-21-jdk
+ sudo update-alternatives --set java /usr/lib/jvm/java-21-openjdk-amd64/bin/java
+ sudo update-alternatives --set javac /usr/lib/jvm/java-21-openjdk-amd64/bin/javac
+ java -version
+ export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
+ - run:
+ name: Generate Sources
+ command: mvn web3j:generate-sources
+ - run:
+ name: Maven Tests
+ command: mvn test
orbs:
maven: circleci/maven@1.4.1
+executors:
+ machine_executor_amd64:
+ machine:
+ image: ubuntu-2204:2023.10.1
+ environment:
+ architecture: "amd64"
+ platform: "linux/amd64"
+
workflows:
maven_test:
jobs:
- - maven/test:
- executor: jdk
+ - test
- analyze:
context: SonarCloud
\ No newline at end of file
diff --git a/contract-service/pom.xml b/contract-service/pom.xml
index 8c877c4..2911a11 100644
--- a/contract-service/pom.xml
+++ b/contract-service/pom.xml
@@ -25,11 +25,67 @@
org.springframework.boot
spring-boot-starter-web
+
+ org.web3j
+ core
+ ${web3j.version}
+
+
+ org.web3j
+ tuples
+ ${web3j.version}
+
+
+ org.web3j
+ abi
+ ${web3j.version}
+
+
+ org.web3j
+ crypto
+ ${web3j.version}
+
org.springframework.boot
spring-boot-starter-test
test
+
+ org.testcontainers
+ testcontainers
+ ${testcontainers.version}
+ test
+
+
+ org.testcontainers
+ junit-jupiter
+ ${testcontainers.version}
+ test
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ add-source
+ generate-sources
+
+ add-source
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contract-service/src/main/java/pl/piomin/services/contract/ContractApp.java b/contract-service/src/main/java/pl/piomin/services/contract/ContractApp.java
index 1f9c0a7..4824e54 100644
--- a/contract-service/src/main/java/pl/piomin/services/contract/ContractApp.java
+++ b/contract-service/src/main/java/pl/piomin/services/contract/ContractApp.java
@@ -14,27 +14,27 @@
@SpringBootApplication
public class ContractApp {
- private static final Logger LOGGER = LoggerFactory.getLogger(ContractApp.class);
-
+ private static final Logger LOGGER = LoggerFactory.getLogger(ContractApp.class);
+
@Autowired
Web3j web3j;
@Autowired
ContractService service;
-
+
public static void main(String[] args) {
SpringApplication.run(ContractApp.class, args);
}
@PostConstruct
public void listen() {
- web3j.transactionObservable().subscribe(tx -> {
- if (tx.getTo() != null && tx.getTo().equals(service.getOwnerAccount())) {
- LOGGER.info("New tx: id={}, block={}, from={}, to={}, value={}", tx.getHash(), tx.getBlockHash(), tx.getFrom(), tx.getTo(), tx.getValue().intValue());
- service.processContracts(tx.getValue().longValue());
- } else {
- LOGGER.info("Not matched: id={}, to={}", tx.getHash(), tx.getTo());
- }
- });
+ web3j.transactionFlowable().subscribe(tx -> {
+ if (tx.getTo() != null && tx.getTo().equals(service.getOwnerAccount())) {
+ LOGGER.info("New tx: id={}, block={}, from={}, to={}, value={}", tx.getHash(), tx.getBlockHash(), tx.getFrom(), tx.getTo(), tx.getValue().intValue());
+ service.processContracts(tx.getValue().longValue());
+ } else {
+ LOGGER.info("Not matched: id={}, to={}", tx.getHash(), tx.getTo());
+ }
+ });
}
-
+
}
diff --git a/contract-service/src/main/java/pl/piomin/services/contract/controller/ContractController.java b/contract-service/src/main/java/pl/piomin/services/contract/controller/ContractController.java
index 2d8d103..456a44d 100644
--- a/contract-service/src/main/java/pl/piomin/services/contract/controller/ContractController.java
+++ b/contract-service/src/main/java/pl/piomin/services/contract/controller/ContractController.java
@@ -16,15 +16,15 @@ public class ContractController {
@Autowired
ContractService service;
-
+
@GetMapping("/owner")
public String getOwnerAccount() {
- return service.getOwnerAccount();
+ return service.getOwnerAccount();
}
-
+
@PostMapping
public Contract createContract(@RequestBody Contract newContract) throws Exception {
- return service.createContract(newContract);
+ return service.createContract(newContract);
}
-
+
}
diff --git a/contract-service/src/main/java/pl/piomin/services/contract/model/Contract.java b/contract-service/src/main/java/pl/piomin/services/contract/model/Contract.java
index e23b43a..b9a57c5 100644
--- a/contract-service/src/main/java/pl/piomin/services/contract/model/Contract.java
+++ b/contract-service/src/main/java/pl/piomin/services/contract/model/Contract.java
@@ -2,32 +2,32 @@
public class Contract {
- private int fee;
- private String receiver;
- private String address;
+ private int fee;
+ private String receiver;
+ private String address;
- public int getFee() {
- return fee;
- }
+ public int getFee() {
+ return fee;
+ }
- public void setFee(int fee) {
- this.fee = fee;
- }
+ public void setFee(int fee) {
+ this.fee = fee;
+ }
- public String getReceiver() {
- return receiver;
- }
+ public String getReceiver() {
+ return receiver;
+ }
- public void setReceiver(String receiver) {
- this.receiver = receiver;
- }
+ public void setReceiver(String receiver) {
+ this.receiver = receiver;
+ }
- public String getAddress() {
- return address;
- }
+ public String getAddress() {
+ return address;
+ }
- public void setAddress(String address) {
- this.address = address;
- }
+ public void setAddress(String address) {
+ this.address = address;
+ }
}
diff --git a/contract-service/src/main/java/pl/piomin/services/contract/model/Transaction.java b/contract-service/src/main/java/pl/piomin/services/contract/model/Transaction.java
index a6caa9a..f9a8a77 100644
--- a/contract-service/src/main/java/pl/piomin/services/contract/model/Transaction.java
+++ b/contract-service/src/main/java/pl/piomin/services/contract/model/Transaction.java
@@ -2,23 +2,23 @@
public class Transaction {
- private String contract;
- private long amount;
+ private String contract;
+ private long amount;
- public String getContract() {
- return contract;
- }
+ public String getContract() {
+ return contract;
+ }
- public void setContract(String contract) {
- this.contract = contract;
- }
+ public void setContract(String contract) {
+ this.contract = contract;
+ }
- public long getAmount() {
- return amount;
- }
+ public long getAmount() {
+ return amount;
+ }
- public void setAmount(long amount) {
- this.amount = amount;
- }
+ public void setAmount(long amount) {
+ this.amount = amount;
+ }
}
diff --git a/contract-service/src/main/java/pl/piomin/services/contract/model/Transactionfee.java b/contract-service/src/main/java/pl/piomin/services/contract/model/Transactionfee.java
deleted file mode 100644
index 8f5cfad..0000000
--- a/contract-service/src/main/java/pl/piomin/services/contract/model/Transactionfee.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package pl.piomin.services.contract.model;
-
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import org.web3j.abi.EventEncoder;
-import org.web3j.abi.FunctionEncoder;
-import org.web3j.abi.TypeReference;
-import org.web3j.abi.datatypes.Address;
-import org.web3j.abi.datatypes.Bool;
-import org.web3j.abi.datatypes.Event;
-import org.web3j.abi.datatypes.Function;
-import org.web3j.abi.datatypes.Type;
-import org.web3j.abi.datatypes.generated.Uint256;
-import org.web3j.crypto.Credentials;
-import org.web3j.protocol.Web3j;
-import org.web3j.protocol.core.DefaultBlockParameter;
-import org.web3j.protocol.core.RemoteCall;
-import org.web3j.protocol.core.methods.request.EthFilter;
-import org.web3j.protocol.core.methods.response.Log;
-import org.web3j.protocol.core.methods.response.TransactionReceipt;
-import org.web3j.tx.Contract;
-import org.web3j.tx.TransactionManager;
-import rx.Observable;
-import rx.functions.Func1;
-
-/**
- *
Auto generated code.
- *
Do not modify!
- *
Please use the web3j command line tools,
- * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the
- * codegen module to update.
- *
- *
Generated with web3j version 3.4.0.
- */
-public class Transactionfee extends Contract {
- private static final String BINARY = "608060405234801561001057600080fd5b506040516040806102c783398101604052805160209091015160018054600160a060020a03909316600160a060020a03199093169290921790915560005561026a8061005d6000396000f30060806040526004361061006c5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166310fb7bc6811461007157806327e235e314610098578063d0f452dd146100c6578063ddca3f43146100d0578063f7260d3e146100e5575b600080fd5b34801561007d57600080fd5b50610086610123565b60408051918252519081900360200190f35b3480156100a457600080fd5b5061008673ffffffffffffffffffffffffffffffffffffffff60043516610140565b6100ce610152565b005b3480156100dc57600080fd5b5061008661021c565b3480156100f157600080fd5b506100fa610222565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b60015473ffffffffffffffffffffffffffffffffffffffff163190565b60026020526000908152604090205481565b600080548190606490340260015460405192909104935073ffffffffffffffffffffffffffffffffffffffff169083156108fc029084906000818181858888f16001805473ffffffffffffffffffffffffffffffffffffffff90811660009081526002602090815260409182902080548c01905592548151338152921692820192909252808201899052821515606082015290519196507f4a7ca93981c43b6021cfef8fa7764ad1a6abd748f97622b8fc50d887bf603c6495508190036080019350915050a15050565b60005481565b60015473ffffffffffffffffffffffffffffffffffffffff16815600a165627a7a7230582056902cd076d831b0bb2b8ffad0441a608f0fc2f58ca92718e460b34e34f24cad0029";
-
- public static final String FUNC_GETRECEIVERBALANCE = "getReceiverBalance";
-
- public static final String FUNC_BALANCES = "balances";
-
- public static final String FUNC_SENDTRX = "sendTrx";
-
- public static final String FUNC_FEE = "fee";
-
- public static final String FUNC_RECEIVER = "receiver";
-
- public static final Event SENT_EVENT = new Event("Sent",
- Arrays.>asList(),
- Arrays.>asList(new TypeReference() {}, new TypeReference() {}, new TypeReference() {}, new TypeReference() {}));
- ;
-
- protected Transactionfee(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
- super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
- }
-
- protected Transactionfee(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
- super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
- }
-
- public RemoteCall getReceiverBalance() {
- final Function function = new Function(FUNC_GETRECEIVERBALANCE,
- Arrays.asList(),
- Arrays.>asList(new TypeReference() {}));
- return executeRemoteCallSingleValueReturn(function, BigInteger.class);
- }
-
- public RemoteCall balances(String param0) {
- final Function function = new Function(FUNC_BALANCES,
- Arrays.asList(new org.web3j.abi.datatypes.Address(param0)),
- Arrays.>asList(new TypeReference() {}));
- return executeRemoteCallSingleValueReturn(function, BigInteger.class);
- }
-
- public RemoteCall sendTrx(BigInteger weiValue) {
- final Function function = new Function(
- FUNC_SENDTRX,
- Arrays.asList(),
- Collections.>emptyList());
- return executeRemoteCallTransaction(function, weiValue);
- }
-
- public RemoteCall fee() {
- final Function function = new Function(FUNC_FEE,
- Arrays.asList(),
- Arrays.>asList(new TypeReference() {}));
- return executeRemoteCallSingleValueReturn(function, BigInteger.class);
- }
-
- public RemoteCall receiver() {
- final Function function = new Function(FUNC_RECEIVER,
- Arrays.asList(),
- Arrays.>asList(new TypeReference() {}));
- return executeRemoteCallSingleValueReturn(function, String.class);
- }
-
- public static RemoteCall deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit, String _receiver, BigInteger _fee) {
- String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(_receiver),
- new org.web3j.abi.datatypes.generated.Uint256(_fee)));
- return deployRemoteCall(Transactionfee.class, web3j, credentials, gasPrice, gasLimit, BINARY, encodedConstructor);
- }
-
- public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, String _receiver, BigInteger _fee) {
- String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new org.web3j.abi.datatypes.Address(_receiver),
- new org.web3j.abi.datatypes.generated.Uint256(_fee)));
- return deployRemoteCall(Transactionfee.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, encodedConstructor);
- }
-
- public List getSentEvents(TransactionReceipt transactionReceipt) {
- List valueList = extractEventParametersWithLog(SENT_EVENT, transactionReceipt);
- ArrayList responses = new ArrayList(valueList.size());
- for (Contract.EventValuesWithLog eventValues : valueList) {
- SentEventResponse typedResponse = new SentEventResponse();
- typedResponse.log = eventValues.getLog();
- typedResponse.from = (String) eventValues.getNonIndexedValues().get(0).getValue();
- typedResponse.to = (String) eventValues.getNonIndexedValues().get(1).getValue();
- typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue();
- typedResponse.sent = (Boolean) eventValues.getNonIndexedValues().get(3).getValue();
- responses.add(typedResponse);
- }
- return responses;
- }
-
- public Observable sentEventObservable(EthFilter filter) {
- return web3j.ethLogObservable(filter).map(new Func1() {
- @Override
- public SentEventResponse call(Log log) {
- Contract.EventValuesWithLog eventValues = extractEventParametersWithLog(SENT_EVENT, log);
- SentEventResponse typedResponse = new SentEventResponse();
- typedResponse.log = log;
- typedResponse.from = (String) eventValues.getNonIndexedValues().get(0).getValue();
- typedResponse.to = (String) eventValues.getNonIndexedValues().get(1).getValue();
- typedResponse.amount = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue();
- typedResponse.sent = (Boolean) eventValues.getNonIndexedValues().get(3).getValue();
- return typedResponse;
- }
- });
- }
-
- public Observable sentEventObservable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) {
- EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress());
- filter.addSingleTopic(EventEncoder.encode(SENT_EVENT));
- return sentEventObservable(filter);
- }
-
- public static Transactionfee load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
- return new Transactionfee(contractAddress, web3j, credentials, gasPrice, gasLimit);
- }
-
- public static Transactionfee load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
- return new Transactionfee(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
- }
-
- public static class SentEventResponse {
- public Log log;
-
- public String from;
-
- public String to;
-
- public BigInteger amount;
-
- public Boolean sent;
- }
-}
diff --git a/contract-service/src/main/java/pl/piomin/services/contract/service/ContractService.java b/contract-service/src/main/java/pl/piomin/services/contract/service/ContractService.java
index e71f451..72ebf3e 100644
--- a/contract-service/src/main/java/pl/piomin/services/contract/service/ContractService.java
+++ b/contract-service/src/main/java/pl/piomin/services/contract/service/ContractService.java
@@ -1,16 +1,5 @@
package pl.piomin.services.contract.service;
-import java.io.IOException;
-import java.math.BigInteger;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-
-import javax.annotation.PostConstruct;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -26,9 +15,18 @@
import org.web3j.protocol.core.methods.response.EthGetBalance;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
-
import pl.piomin.services.contract.model.Contract;
-import pl.piomin.services.contract.model.Transactionfee;
+import pl.piomin.services.contract.model.TransactionFee;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
@Service
public class ContractService {
@@ -37,60 +35,60 @@ public class ContractService {
private static final String PASSWORD = "piot123";
private static final BigInteger GAS_PRICE = BigInteger.valueOf(1L);
private static final BigInteger GAS_LIMIT = BigInteger.valueOf(500_000L);
-
+
@Autowired
Web3j web3j;
Credentials credentials;
private List contracts = new ArrayList<>();
-
+
@PostConstruct
- public void init() throws IOException, CipherException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException {
- String file = WalletUtils.generateLightNewWalletFile(PASSWORD, null);
- credentials = WalletUtils.loadCredentials(PASSWORD, file);
- LOGGER.info("Credentials created: file={}, address={}", file, credentials.getAddress());
- EthCoinbase coinbase = web3j.ethCoinbase().send();
- EthGetTransactionCount transactionCount = web3j.ethGetTransactionCount(coinbase.getAddress(), DefaultBlockParameterName.LATEST).send();
- Transaction transaction = Transaction.createEtherTransaction(coinbase.getAddress(), transactionCount.getTransactionCount(), BigInteger.valueOf(20_000_000_000L), BigInteger.valueOf(21_000), credentials.getAddress(),BigInteger.valueOf(25_000_000_000_000_000L));
- web3j.ethSendTransaction(transaction).send();
- EthGetBalance balance = web3j.ethGetBalance(credentials.getAddress(), DefaultBlockParameterName.LATEST).send();
- LOGGER.info("Balance: {}", balance.getBalance().longValue());
+ public void init() throws IOException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, CipherException {
+ String file = WalletUtils.generateLightNewWalletFile(PASSWORD, null);
+ credentials = WalletUtils.loadCredentials(PASSWORD, file);
+ LOGGER.info("Credentials created: file={}, address={}", file, credentials.getAddress());
+ EthCoinbase coinbase = web3j.ethCoinbase().send();
+ EthGetTransactionCount transactionCount = web3j.ethGetTransactionCount(coinbase.getAddress(), DefaultBlockParameterName.LATEST).send();
+ Transaction transaction = Transaction.createEtherTransaction(coinbase.getAddress(), transactionCount.getTransactionCount(), BigInteger.valueOf(20_000_000_000L), BigInteger.valueOf(21_000), credentials.getAddress(), BigInteger.valueOf(25_000_000_000_000_000L));
+ web3j.ethSendTransaction(transaction).send();
+ EthGetBalance balance = web3j.ethGetBalance(credentials.getAddress(), DefaultBlockParameterName.LATEST).send();
+ LOGGER.info("Balance: {}", balance.getBalance().longValue());
}
-
+
public String getOwnerAccount() {
- return credentials.getAddress();
+ return credentials.getAddress();
}
-
+
public Contract createContract(Contract newContract) throws Exception {
- String file = WalletUtils.generateLightNewWalletFile(PASSWORD, null);
- Credentials receiverCredentials = WalletUtils.loadCredentials(PASSWORD, file);
- LOGGER.info("Credentials created: file={}, address={}", file, credentials.getAddress());
- Transactionfee contract = Transactionfee.deploy(web3j, credentials, GAS_PRICE, GAS_LIMIT, receiverCredentials.getAddress(), BigInteger.valueOf(newContract.getFee())).send();
- newContract.setReceiver(receiverCredentials.getAddress());
- newContract.setAddress(contract.getContractAddress());
- contracts.add(contract.getContractAddress());
- LOGGER.info("New contract deployed: address={}", contract.getContractAddress());
- Optional tr = contract.getTransactionReceipt();
- if (tr.isPresent()) {
- LOGGER.info("Transaction receipt: from={}, to={}, gas={}", tr.get().getFrom(), tr.get().getTo(), tr.get().getGasUsed().intValue());
- }
- return newContract;
+ String file = WalletUtils.generateLightNewWalletFile(PASSWORD, null);
+ Credentials receiverCredentials = WalletUtils.loadCredentials(PASSWORD, file);
+ LOGGER.info("Credentials created: file={}, address={}", file, credentials.getAddress());
+ TransactionFee contract = TransactionFee.deploy(web3j, credentials, GAS_PRICE, GAS_LIMIT, receiverCredentials.getAddress(), BigInteger.valueOf(newContract.getFee())).send();
+ newContract.setReceiver(receiverCredentials.getAddress());
+ newContract.setAddress(contract.getContractAddress());
+ contracts.add(contract.getContractAddress());
+ LOGGER.info("New contract deployed: address={}", contract.getContractAddress());
+ Optional tr = contract.getTransactionReceipt();
+ if (tr.isPresent()) {
+ LOGGER.info("Transaction receipt: from={}, to={}, gas={}", tr.get().getFrom(), tr.get().getTo(), tr.get().getGasUsed().intValue());
+ }
+ return newContract;
}
-
+
public void processContracts(long transactionAmount) {
- contracts.forEach(it -> {
- Transactionfee contract = Transactionfee.load(it, web3j, credentials, GAS_PRICE, GAS_LIMIT);
- try {
- TransactionReceipt tr = contract.sendTrx(BigInteger.valueOf(transactionAmount)).send();
- LOGGER.info("Transaction receipt: from={}, to={}, gas={}", tr.getFrom(), tr.getTo(), tr.getGasUsed().intValue());
- LOGGER.info("Get receiver: {}", contract.getReceiverBalance().send().longValue());
- EthFilter filter = new EthFilter(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST, contract.getContractAddress());
- web3j.ethLogObservable(filter).subscribe(log -> {
- LOGGER.info("Log: {}", log.getData());
- });
- } catch (Exception e) {
- LOGGER.error("Error during contract execution", e);
- }
- });
+ contracts.forEach(it -> {
+ TransactionFee contract = TransactionFee.load(it, web3j, credentials, GAS_PRICE, GAS_LIMIT);
+ try {
+ TransactionReceipt tr = contract.sendTrx(BigInteger.valueOf(transactionAmount)).send();
+ LOGGER.info("Transaction receipt: from={}, to={}, gas={}", tr.getFrom(), tr.getTo(), tr.getGasUsed().intValue());
+ LOGGER.info("Get receiver: {}", contract.getReceiverBalance().send().longValue());
+ EthFilter filter = new EthFilter(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST, contract.getContractAddress());
+ web3j.ethLogFlowable(filter).subscribe(log -> {
+ LOGGER.info("Log: {}", log.getData());
+ });
+ } catch (Exception e) {
+ LOGGER.error("Error during contract execution", e);
+ }
+ });
}
-
+
}
diff --git a/contract-service/src/main/resources/fee.sol b/contract-service/src/main/resources/fee.sol
new file mode 100644
index 0000000..c139f2e
--- /dev/null
+++ b/contract-service/src/main/resources/fee.sol
@@ -0,0 +1,33 @@
+pragma solidity ^0.4.21;
+
+contract TransactionFee {
+
+ // (1)
+ uint public fee;
+ // (2)
+ address public receiver;
+ // (3)
+ mapping (address => uint) public balances;
+ // (4)
+ event Sent(address from, address to, uint amount, bool sent);
+
+ // (5)
+ constructor(address _receiver, uint _fee) public {
+ receiver = _receiver;
+ fee = _fee;
+ }
+
+ // (6)
+ function getReceiverBalance() public view returns(uint) {
+ return receiver.balance;
+ }
+
+ // (7)
+ function sendTrx() public payable {
+ uint value = msg.value * fee / 100;
+ bool sent = receiver.send(value);
+ balances[receiver] += (value);
+ emit Sent(msg.sender, receiver, value, sent);
+ }
+
+}
\ No newline at end of file
diff --git a/contract-service/src/test/java/pl/piomin/services/contract/ContractTest.java b/contract-service/src/test/java/pl/piomin/services/contract/ContractTest.java
index 8abf377..79d7cf0 100644
--- a/contract-service/src/test/java/pl/piomin/services/contract/ContractTest.java
+++ b/contract-service/src/test/java/pl/piomin/services/contract/ContractTest.java
@@ -1,15 +1,16 @@
package pl.piomin.services.contract;
-import java.math.BigInteger;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.WalletUtils;
import org.web3j.protocol.Web3j;
@@ -20,63 +21,79 @@
import org.web3j.protocol.core.methods.response.EthGetBalance;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
+import org.web3j.tx.RawTransactionManager;
+import org.web3j.tx.TransactionManager;
+import pl.piomin.services.contract.model.TransactionFee;
-import pl.piomin.services.contract.model.Transactionfee;
+import java.math.BigInteger;
@SpringBootTest
-@RunWith(SpringRunner.class)
+@Testcontainers
public class ContractTest {
- private static final Logger LOGGER = LoggerFactory.getLogger(ContractTest.class);
- public static final BigInteger GAS_PRICE = BigInteger.valueOf(1L);
+ private static final Logger LOGGER = LoggerFactory.getLogger(ContractTest.class);
+ public static final BigInteger GAS_PRICE = BigInteger.valueOf(1L);
public static final BigInteger GAS_LIMIT = BigInteger.valueOf(500_000L);
public static final BigInteger AMOUNT = BigInteger.valueOf(10_000L);
public static final BigInteger FEE = BigInteger.valueOf(10L);
-
- @Autowired
+
+ @Autowired
Web3j web3j;
- Credentials credentialsFrom;
- Credentials credentialsTo;
-
- @Before
- public void before() throws Exception {
+ Credentials credentialsFrom;
+ Credentials credentialsTo;
+
+ @Container
+ static final GenericContainer clientEthereum = new GenericContainer("ethereum/client-go")
+ .withCommand("--http", "--http.corsdomain=*", "--http.addr=0.0.0.0", "--dev")
+ .withExposedPorts(8545);
+
+ @DynamicPropertySource
+ static void registerCeProperties(DynamicPropertyRegistry registry) {
+ registry.add("web3j.client-address",
+ () -> String.format("http://localhost:%d", clientEthereum.getFirstMappedPort()));
+ }
+
+ @BeforeEach
+ public void before() throws Exception {
// String file = WalletUtils.generateLightNewWalletFile("piot123", null);
// String file = "src/test/resources/john_smith.json";
- credentialsFrom = WalletUtils.loadCredentials("piot123", "src/test/resources/john_smith.json");
- credentialsTo = WalletUtils.loadCredentials("piot123", "src/test/resources/jason_sullivan.json");
- LOGGER.info("Credentials: address={}", credentialsFrom.getAddress());
- EthCoinbase coinbase = web3j.ethCoinbase().send();
- EthGetTransactionCount transactionCount = web3j.ethGetTransactionCount(coinbase.getAddress(), DefaultBlockParameterName.LATEST).send();
- Transaction transaction = Transaction.createEtherTransaction(coinbase.getAddress(), transactionCount.getTransactionCount(), BigInteger.valueOf(20_000_000_000L), BigInteger.valueOf(21_000), credentialsFrom.getAddress(),BigInteger.valueOf(25_000_000_000_000_000L));
- web3j.ethSendTransaction(transaction).send();
- EthGetBalance balance = web3j.ethGetBalance(credentialsFrom.getAddress(), DefaultBlockParameterName.LATEST).send();
- LOGGER.info("Balance: {}", balance.getBalance().longValue());
- }
-
- @Test
- public void testTransactionFeeContract() throws Exception {
- Transactionfee contract = Transactionfee.deploy(web3j, credentialsFrom, GAS_PRICE, GAS_LIMIT, "0xd7850bd94f189ce38ce5729052926094997de310", FEE).send();
- EthGetBalance balance = web3j.ethGetBalance(credentialsTo.getAddress(), DefaultBlockParameterName.LATEST).send();
- EthFilter filter = new EthFilter(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST, contract.getContractAddress());
- LOGGER.info("Sending to: account={}, balance={}", "0xd7850bd94f189ce38ce5729052926094997de310", balance.getBalance().longValue());
- for (int i=0; i<3; i++) {
- TransactionReceipt tr = contract.sendTrx(AMOUNT).send();
- LOGGER.info("Transaction receipt: from={}, to={}, gas={}", tr.getFrom(), tr.getTo(), tr.getGasUsed().intValue());
- balance = web3j.ethGetBalance(credentialsFrom.getAddress(), DefaultBlockParameterName.LATEST).send();
- LOGGER.info("From balance after: account={}, balance={}", "0xd7850bd94f189ce38ce5729052926094997de310", balance.getBalance().longValue());
- balance = web3j.ethGetBalance(credentialsTo.getAddress(), DefaultBlockParameterName.LATEST).send();
- LOGGER.info("To balance after: account={}, balance={}", "0xd7850bd94f189ce38ce5729052926094997de310", balance.getBalance().longValue());
- LOGGER.info("Contract: account={}, balance={}", "0xd7850bd94f189ce38ce5729052926094997de310", contract.balances(credentialsTo.getAddress()).send().longValue());
- LOGGER.info("Get receiver: {}", contract.getReceiverBalance().send().longValue());
+ credentialsFrom = WalletUtils.loadCredentials("piot123", "src/test/resources/john_smith.json");
+ credentialsTo = WalletUtils.loadCredentials("piot123", "src/test/resources/jason_sullivan.json");
+ LOGGER.info("Credentials: address={}", credentialsFrom.getAddress());
+ EthCoinbase coinbase = web3j.ethCoinbase().send();
+ EthGetTransactionCount transactionCount = web3j.ethGetTransactionCount(coinbase.getAddress(), DefaultBlockParameterName.LATEST).send();
+ Transaction transaction = Transaction.createEtherTransaction(coinbase.getAddress(), transactionCount.getTransactionCount(), BigInteger.valueOf(20_000_000_000L), BigInteger.valueOf(21_000), credentialsFrom.getAddress(), BigInteger.valueOf(25_000_000_000_000_000L));
+ web3j.ethSendTransaction(transaction).send();
+ EthGetBalance balance = web3j.ethGetBalance(credentialsFrom.getAddress(), DefaultBlockParameterName.LATEST).send();
+ LOGGER.info("Balance: {}", balance.getBalance().longValue());
+ }
+
+ @Test
+ public void testTransactionFeeContract() throws Exception {
+ long chainId = 56;
+ TransactionManager txManager = new RawTransactionManager(web3j, credentialsFrom, chainId);
+ TransactionFee contract = TransactionFee.deploy(web3j, credentialsFrom, GAS_PRICE, GAS_LIMIT, "0xd7850bd94f189ce38ce5729052926094997de310", FEE).send();
+ EthGetBalance balance = web3j.ethGetBalance(credentialsTo.getAddress(), DefaultBlockParameterName.LATEST).send();
+ EthFilter filter = new EthFilter(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST, contract.getContractAddress());
+ LOGGER.info("Sending to: account={}, balance={}", "0xd7850bd94f189ce38ce5729052926094997de310", balance.getBalance().longValue());
+ for (int i = 0; i < 3; i++) {
+ TransactionReceipt tr = contract.sendTrx(AMOUNT).send();
+ LOGGER.info("Transaction receipt: from={}, to={}, gas={}", tr.getFrom(), tr.getTo(), tr.getGasUsed().intValue());
+ balance = web3j.ethGetBalance(credentialsFrom.getAddress(), DefaultBlockParameterName.LATEST).send();
+ LOGGER.info("From balance after: account={}, balance={}", "0xd7850bd94f189ce38ce5729052926094997de310", balance.getBalance().longValue());
+ balance = web3j.ethGetBalance(credentialsTo.getAddress(), DefaultBlockParameterName.LATEST).send();
+ LOGGER.info("To balance after: account={}, balance={}", "0xd7850bd94f189ce38ce5729052926094997de310", balance.getBalance().longValue());
+ LOGGER.info("Contract: account={}, balance={}", "0xd7850bd94f189ce38ce5729052926094997de310", contract.balances(credentialsTo.getAddress()).send().longValue());
+ LOGGER.info("Get receiver: {}", contract.getReceiverBalance().send().longValue());
// LOGGER.info("Contract To: account={}, balance={}", tr.getTo(), contract.balances(tr.getTo()).send().longValue());
// balance = web3j.ethGetBalance(tr.getTo(), DefaultBlockParameterName.LATEST).send();
// LOGGER.info("Contract To 2: account={}, balance={}", credentialsTo.getAddress(), balance.getBalance().longValue());
- }
-
- web3j.ethLogObservable(filter).subscribe(log -> {
- LOGGER.info("Log: {}", log.getData());
- });
- Thread.sleep(2000);
- }
-
+ }
+
+ web3j.ethLogFlowable(filter).subscribe(log -> {
+ LOGGER.info("Log: {}", log.getData());
+ });
+ Thread.sleep(2000);
+ }
+
}
diff --git a/pom.xml b/pom.xml
index 1b497e2..37ce1b0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,27 +1,49 @@
-
- 4.0.0
+
+ 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.0.3.RELEASE
-
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.18
+
- pl.piomin.services
- sample-spring-blockchain-contract
- 1.0-SNAPSHOT
- pom
+ pl.piomin.services
+ sample-spring-blockchain-contract
+ 1.0-SNAPSHOT
+ pom
-
- 11
- piomin_sample-spring-blockchain-contract
- piomin
- https://sonarcloud.io
-
+
+ 11
+ piomin_sample-spring-blockchain-contract
+ piomin
+ https://sonarcloud.io
+ 1.19.6
+ 4.10.0
+
-
- contract-service
- transaction-service
-
+
+ contract-service
+ transaction-service
+
+
+
+
+ org.web3j
+ web3j-maven-plugin
+ 4.11.0
+
+ pl.piomin.services.contract.model
+ contract-service/src/main/generated
+
+ contract-service/src/main/resources
+
+ **/*.sol
+
+
+
+
+
+
\ No newline at end of file
diff --git a/transaction-service/pom.xml b/transaction-service/pom.xml
index 7367cec..c286d07 100644
--- a/transaction-service/pom.xml
+++ b/transaction-service/pom.xml
@@ -1,33 +1,34 @@
-
- 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.0.3.RELEASE
-
- transaction-service
- pl.piomin.services
- 1.0-SNAPSHOT
+
+ 4.0.0
+
+ pl.piomin.services
+ sample-spring-blockchain-contract
+ 1.0-SNAPSHOT
+
+ transaction-service
+ pl.piomin.services
+ 1.0-SNAPSHOT
-
- ${project.artifactId}
-
+
+ ${project.artifactId}
+
+
+
+
+ org.web3j
+ web3j-spring-boot-starter
+ 1.6.0
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
-
-
- org.web3j
- web3j-spring-boot-starter
- 1.6.0
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
-
\ No newline at end of file
diff --git a/transaction-service/src/main/resources/application.yml b/transaction-service/src/main/resources/application.yml
index 67bb24b..c20d461 100644
--- a/transaction-service/src/main/resources/application.yml
+++ b/transaction-service/src/main/resources/application.yml
@@ -4,7 +4,7 @@ spring:
server:
port: ${PORT:8091}
web3j:
- client-address: http://192.168.99.100:8545
+ client-address: http://localhost:8545
contract-service:
url: http://localhost:8090/contract/owner
\ No newline at end of file