sendTransaction(@PathVariable String type, @Valid @RequestBody SendTransactionDTO sendTransactionDTO) throws Exception {
61 | String serviceName = BlockServiceUtil.getServiceName(type);
62 | BlockResult result = blockChainService.sendTransaction(serviceName, sendTransactionDTO.getPass(), sendTransactionDTO.getFrom(), sendTransactionDTO.getTo(), sendTransactionDTO.getValue());
63 | return success(result);
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/controller/Controller.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.controller;
2 |
3 | import com.mvc.polymorphic.model.dto.BalanceDTO;
4 | import com.mvc.polymorphic.model.dto.TransactionCountDTO;
5 | import com.mvc.polymorphic.service.ContractService;
6 | import com.mvc.polymorphic.service.RpcService;
7 | import io.swagger.annotations.Api;
8 | import io.swagger.annotations.ApiOperation;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.web.bind.annotation.*;
11 |
12 | /**
13 | * Controller for our ERC-20 contract API.
14 | */
15 | @Api("ERC-20 token standard API")
16 | @RestController
17 | public class Controller {
18 | @Autowired
19 | private ContractService ContractService;
20 |
21 | @Autowired
22 | private RpcService rpcService;
23 |
24 | @ApiOperation("Get token balance for address")
25 | @RequestMapping(
26 | value = "/{contractAddress}/eth_getBalance", method = RequestMethod.POST)
27 | public Object balanceOf(
28 | @PathVariable String contractAddress,
29 | @RequestBody final BalanceDTO balanceDTO) {
30 | return ContractService.balanceOf(contractAddress, balanceDTO.getAddress());
31 | }
32 |
33 | // @RequestMapping(value = "/{contractAddress}/eth_sendTransaction", method = RequestMethod.POST)
34 | // public Object approveAndCall(@PathVariable String contractAddress, @RequestBody SendTransactionDTO sendTransactionDTO) throws Exception {
35 | // Transaction transaction = new Transaction(sendTransactionDTO.getFrom(), sendTransactionDTO.getNonce(), sendTransactionDTO.getGasPrice(), sendTransactionDTO.getGas(), sendTransactionDTO.getTo(),
36 | // sendTransactionDTO.getValue().toBigInteger(),
37 | // sendTransactionDTO.getData());
38 | // return rpcService.eth_sendTransaction(transaction, sendTransactionDTO.getPass(), contractAddress);
39 | // }
40 |
41 | @RequestMapping(value = "/{contractAddress}/txList", method = RequestMethod.POST)
42 | private Object txList(@PathVariable String contractAddress, @RequestBody TransactionCountDTO transactionCountDTO) {
43 | return rpcService.txList(transactionCountDTO.getAddress());
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/controller/DemoController.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.controller;
2 |
3 | import com.mvc.polymorphic.configuration.TokenConfig;
4 | import io.swagger.annotations.Api;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.bind.annotation.RestController;
9 |
10 | @Api("Some Demos")
11 | @RestController
12 | @RequestMapping("/demo")
13 | public class DemoController {
14 |
15 | @Autowired
16 | private TokenConfig tokenConfig;
17 |
18 | @GetMapping("/config")
19 | public Object config() {
20 | return tokenConfig.getUrl();
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/controller/EthereumController.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.controller;
2 |
3 | import com.mvc.polymorphic.model.dto.*;
4 | import com.mvc.polymorphic.service.RpcService;
5 | import com.mvc.polymorphic.utils.FileUtil;
6 | import com.mvc.polymorphic.utils.RSACoder;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.web.bind.annotation.*;
9 | import org.springframework.web.multipart.MultipartFile;
10 |
11 | import javax.servlet.http.HttpServletRequest;
12 |
13 | /**
14 | * all demo in this controller
15 | */
16 | @RestController
17 | @RequestMapping("ethereum")
18 | public class EthereumController {
19 |
20 | @Autowired
21 | private RpcService rpcService;
22 |
23 | /**
24 | * getBalance
25 | *
26 | * @param balanceDTO
27 | * @return
28 | */
29 | @RequestMapping(value = "eth_getBalance", method = RequestMethod.POST)
30 | public Object eth_getBalance(HttpServletRequest request, @RequestBody final BalanceDTO balanceDTO) throws Exception {
31 | return rpcService.eth_getBalance(balanceDTO.getAddress(), balanceDTO.getBlockId());
32 | }
33 |
34 | /**
35 | * getTransactionByHash
36 | *
37 | * @return
38 | */
39 | @RequestMapping(value = "eth_getTransactionByHash", method = RequestMethod.POST)
40 | public Object eth_getTransactionByHash(@RequestBody TransactionByHashDTO transactionByHashDTO) throws Exception {
41 | return rpcService.eth_getTransactionByHash(transactionByHashDTO.getTransactionHash());
42 | }
43 |
44 | /**
45 | * sendRawTransaction
46 | *
47 | * @param rawTransactionDTO
48 | * @return
49 | * @throws Exception
50 | */
51 | @RequestMapping(value = "eth_sendRawTransaction", method = RequestMethod.POST)
52 | public Object ethSendRawTransaction(@RequestBody RawTransactionDTO rawTransactionDTO) throws Exception {
53 | return rpcService.ethSendRawTransaction(rawTransactionDTO.getSignedMessage());
54 | }
55 |
56 | /**
57 | * sendTransaction
58 | *
59 | * @param sendTransactionDTO
60 | * @return
61 | * @throws Exception
62 | */
63 | // @RequestMapping(value = "eth_sendTransaction", method = RequestMethod.POST)
64 | // public Object eth_sendTransaction(@RequestBody SendTransactionDTO sendTransactionDTO) throws Exception {
65 | // Transaction transaction = new Transaction(sendTransactionDTO.getFrom(), sendTransactionDTO.getNonce(), sendTransactionDTO.getGasPrice(), sendTransactionDTO.getGas(), sendTransactionDTO.getTo(),
66 | // Convert.toWei(sendTransactionDTO.getValue(), Convert.Unit.ETHER).toBigInteger(),
67 | // sendTransactionDTO.getData());
68 | // return rpcService.eth_sendTransaction(transaction, sendTransactionDTO.getPass());
69 | // }
70 |
71 | /**
72 | * search user list
73 | *
74 | * @return
75 | * @throws Exception
76 | */
77 | @RequestMapping(value = "personal_listAccounts", method = RequestMethod.POST)
78 | public Object personal_listAccounts() throws Exception {
79 | return rpcService.personal_listAccounts();
80 | }
81 |
82 | /**
83 | * create new Account
84 | *
85 | * @return
86 | * @throws Exception
87 | */
88 | @RequestMapping(value = "personal_newAccount", method = RequestMethod.POST)
89 | public Object personal_newAccount(@RequestBody NewAccountDTO newAccountDTO) throws Exception {
90 | return rpcService.personal_newAccount(newAccountDTO.getPassphrase());
91 | }
92 |
93 | /**
94 | * import key
95 | *
96 | * @return
97 | * @throws Exception
98 | */
99 | @RequestMapping(value = "personal_importRawKey", method = RequestMethod.POST)
100 | public Object personal_importRawKey(@RequestBody ImportRawKeyDTO importRawKeyDTO) throws Exception {
101 | return rpcService.personal_importRawKey(importRawKeyDTO.getKeydata(), importRawKeyDTO.getPassphrase());
102 | }
103 |
104 | /**
105 | * get publickey for RSA
106 | *
107 | * @return
108 | * @throws Exception
109 | */
110 | @RequestMapping(value = "publicKey", method = RequestMethod.POST)
111 | public Object publicKey() throws Exception {
112 | return RSACoder.getPublicKey();
113 | }
114 |
115 | /**
116 | * get TransactionCount for nonce
117 | *
118 | * @return
119 | * @throws Exception
120 | */
121 | @RequestMapping(value = "transactionCount", method = RequestMethod.POST)
122 | public Object getTransactionCount(@RequestBody TransactionCountDTO transactionCountDTO) throws Exception {
123 | return rpcService.getTransactionCount(transactionCountDTO.getAddress());
124 | }
125 |
126 | /**
127 | * personal by keyDate
128 | * @param file
129 | * @param passhphrase
130 | * @return
131 | * @throws Exception
132 | */
133 | @RequestMapping(value = "personalByKeyDate", method = RequestMethod.POST)
134 | public Object eth_personalByKeyDate(@RequestParam("file") MultipartFile file, @RequestParam String passhphrase) throws Exception {
135 | String source = FileUtil.readFile(file.getInputStream());
136 | return rpcService.eth_personalByKeyDate(source, passhphrase);
137 | }
138 |
139 | /**
140 | * personal by privateKey
141 | * @param personalByPrivateKeyDTO
142 | * @return
143 | * @throws Exception
144 | */
145 | @RequestMapping(value = "personalByPrivateKey", method = RequestMethod.POST)
146 | public Object eth_personalByPrivateKey(@RequestBody PersonalByPrivateKeyDTO personalByPrivateKeyDTO) throws Exception {
147 | return rpcService.eth_personalByPrivateKey(personalByPrivateKeyDTO.getPrivateKey());
148 | }
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/exceptions/ExceededGasException.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.exceptions;
2 |
3 | public class ExceededGasException extends Throwable {
4 | public ExceededGasException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/Account.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import lombok.*;
5 |
6 | @Builder(builderClassName="Builder", toBuilder=true)
7 | @Setter
8 | @Getter
9 | @NoArgsConstructor
10 | @AllArgsConstructor
11 | @JsonIgnoreProperties(ignoreUnknown = true)
12 | @ToString
13 | public class Account {
14 | private String passphrase;
15 | private String address;
16 | private long balance;
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/ApprovalEventResponse.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class ApprovalEventResponse {
7 | private String owner;
8 | private String spender;
9 | private long value;
10 |
11 | public ApprovalEventResponse() { }
12 |
13 | public ApprovalEventResponse(
14 | HumanStandardToken.ApprovalEventResponse approvalEventResponse) {
15 | this.owner = approvalEventResponse._owner.toString();
16 | this.spender = approvalEventResponse._spender.toString();
17 | this.value = approvalEventResponse._value.getValue().longValueExact();
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/Block.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import lombok.*;
5 |
6 | @Builder(builderClassName="Builder", toBuilder=true)
7 | @Setter
8 | @Getter
9 | @NoArgsConstructor
10 | @AllArgsConstructor
11 | @JsonIgnoreProperties(ignoreUnknown = true)public class Block {
12 | private String nonce;
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/EthTransaction.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import lombok.*;
5 |
6 |
7 | @Builder(builderClassName="Builder", toBuilder=true)
8 | @Getter
9 | @Setter
10 | @NoArgsConstructor
11 | @AllArgsConstructor
12 | @JsonIgnoreProperties(ignoreUnknown = true)
13 | public class EthTransaction {
14 | private String data;
15 | private String from;
16 | private String to;
17 | private long gas;
18 | private long gasPrice;
19 | private long value;
20 | // private long nonce;
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/Filter.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import lombok.*;
5 |
6 | @Builder(builderClassName="Builder", toBuilder=true)
7 | @Getter
8 | @Setter
9 | @NoArgsConstructor
10 | @AllArgsConstructor
11 | @JsonIgnoreProperties(ignoreUnknown = true)
12 | public class Filter {
13 | private String fromBlock = "0x0";
14 | private String toBlock = "lastest";
15 | private String address;
16 | private String topics;
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/HumanStandardToken.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model;
2 |
3 | import org.web3j.abi.EventEncoder;
4 | import org.web3j.abi.EventValues;
5 | import org.web3j.abi.FunctionEncoder;
6 | import org.web3j.abi.TypeReference;
7 | import org.web3j.abi.datatypes.*;
8 | import org.web3j.abi.datatypes.generated.Uint256;
9 | import org.web3j.abi.datatypes.generated.Uint8;
10 | import org.web3j.crypto.Credentials;
11 | import org.web3j.protocol.Web3j;
12 | import org.web3j.protocol.core.DefaultBlockParameter;
13 | import org.web3j.protocol.core.methods.request.EthFilter;
14 | import org.web3j.protocol.core.methods.response.Log;
15 | import org.web3j.protocol.core.methods.response.TransactionReceipt;
16 | import org.web3j.protocol.exceptions.TransactionException;
17 | import org.web3j.tx.Contract;
18 | import org.web3j.tx.TransactionManager;
19 | import rx.Observable;
20 | import rx.functions.Func1;
21 |
22 | import java.io.IOException;
23 | import java.math.BigInteger;
24 | import java.util.ArrayList;
25 | import java.util.Arrays;
26 | import java.util.Collections;
27 | import java.util.List;
28 | import java.util.concurrent.Future;
29 |
30 | /**
31 | * Auto generated code.
32 | * Do not modify!
33 | *
34 | * Generated with web3j version 2.2.1.
35 | */
36 | public final class HumanStandardToken extends Contract {
37 | private static final String BINARY = "60a0604052600460608190527f48302e3100000000000000000000000000000000000000000000000000000000608090815261003e91600691906100d7565b50341561004757fe5b604051610b8f380380610b8f833981016040908152815160208301519183015160608401519193928301929091015b600160a060020a033316600090815260016020908152604082208690559085905583516100a991600391908601906100d7565b506004805460ff191660ff841617905580516100cc9060059060208401906100d7565b505b50505050610177565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061011857805160ff1916838001178555610145565b82800160010185558215610145579182015b8281111561014557825182559160200191906001019061012a565b5b50610152929150610156565b5090565b61017491905b80821115610152576000815560010161015c565b5090565b90565b610a09806101866000396000f300606060405236156100935763ffffffff60e060020a60003504166306fdde0381146100a9578063095ea7b31461013957806318160ddd1461016c57806323b872dd1461018e578063313ce567146101c757806354fd4d50146101ed57806370a082311461027d57806395d89b41146102ab578063a9059cbb1461033b578063cae9ca511461036e578063dd62ed3e146103e5575b341561009b57fe5b6100a75b60006000fd5b565b005b34156100b157fe5b6100b9610419565b6040805160208082528351818301528351919283929083019185019080838382156100ff575b8051825260208311156100ff57601f1990920191602091820191016100df565b505050905090810190601f16801561012b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014157fe5b610158600160a060020a03600435166024356104a7565b604080519115158252519081900360200190f35b341561017457fe5b61017c610512565b60408051918252519081900360200190f35b341561019657fe5b610158600160a060020a0360043581169060243516604435610518565b604080519115158252519081900360200190f35b34156101cf57fe5b6101d761060e565b6040805160ff9092168252519081900360200190f35b34156101f557fe5b6100b9610617565b6040805160208082528351818301528351919283929083019185019080838382156100ff575b8051825260208311156100ff57601f1990920191602091820191016100df565b505050905090810190601f16801561012b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561028557fe5b61017c600160a060020a03600435166106a5565b60408051918252519081900360200190f35b34156102b357fe5b6100b96106c4565b6040805160208082528351818301528351919283929083019185019080838382156100ff575b8051825260208311156100ff57601f1990920191602091820191016100df565b505050905090810190601f16801561012b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561034357fe5b610158600160a060020a0360043516602435610752565b604080519115158252519081900360200190f35b341561037657fe5b604080516020600460443581810135601f8101849004840285018401909552848452610158948235600160a060020a03169460248035956064949293919092019181908401838280828437509496506107fe95505050505050565b604080519115158252519081900360200190f35b34156103ed57fe5b61017c600160a060020a03600435811690602435166109b0565b60408051918252519081900360200190f35b6003805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561049f5780601f106104745761010080835404028352916020019161049f565b820191906000526020600020905b81548152906001019060200180831161048257829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294825280832086905580518681529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060015b92915050565b60005481565b600160a060020a0383166000908152600160205260408120548290108015906105685750600160a060020a0380851660009081526002602090815260408083203390941683529290522054829010155b80156105745750600082115b1561060257600160a060020a03808416600081815260016020908152604080832080548801905588851680845281842080548990039055600283528184203390961684529482529182902080548790039055815186815291519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a3506001610606565b5060005b5b9392505050565b60045460ff1681565b6006805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561049f5780601f106104745761010080835404028352916020019161049f565b820191906000526020600020905b81548152906001019060200180831161048257829003601f168201915b505050505081565b600160a060020a0381166000908152600160205260409020545b919050565b6005805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561049f5780601f106104745761010080835404028352916020019161049f565b820191906000526020600020905b81548152906001019060200180831161048257829003601f168201915b505050505081565b600160a060020a03331660009081526001602052604081205482901080159061077b5750600082115b156107ef57600160a060020a03338116600081815260016020908152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a350600161050c565b50600061050c565b5b92915050565b600160a060020a03338116600081815260026020908152604080832094881680845294825280832087905580518781529051929493927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a383600160a060020a031660405180807f72656365697665417070726f76616c28616464726573732c75696e743235362c81526020017f616464726573732c627974657329000000000000000000000000000000000000815250602e019050604051809103902060e060020a9004338530866040518563ffffffff1660e060020a0281526004018085600160a060020a0316600160a060020a0316815260200184815260200183600160a060020a0316600160a060020a03168152602001828051906020019080838360008314610950575b80518252602083111561095057601f199092019160209182019101610930565b505050905090810190601f16801561097c5780820380516001836020036101000a031916815260200191505b509450505050506000604051808303816000876161da5a03f19250505015156109a55760006000fd5b5060015b9392505050565b600160a060020a038083166000908152600260209081526040808320938516835292905220545b929150505600a165627a7a7230582095fa82c5fd259e30fb0a7f8bfebb52ec799ca55b26bdbbea3153c6cebdb2fd080029";
38 |
39 | private HumanStandardToken(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
40 | super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
41 | }
42 |
43 | private HumanStandardToken(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
44 | super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
45 | }
46 |
47 | public List getTransferEvents(TransactionReceipt transactionReceipt) {
48 | final Event event = new Event("Transfer",
49 | Arrays.>asList(new TypeReference() {}, new TypeReference() {}),
50 | Arrays.>asList(new TypeReference() {}));
51 | List valueList = extractEventParameters(event, transactionReceipt);
52 | ArrayList responses = new ArrayList(valueList.size());
53 | for (EventValues eventValues : valueList) {
54 | TransferEventResponse typedResponse = new TransferEventResponse();
55 | typedResponse._from = (Address) eventValues.getIndexedValues().get(0);
56 | typedResponse._to = (Address) eventValues.getIndexedValues().get(1);
57 | typedResponse._value = (Uint256) eventValues.getNonIndexedValues().get(0);
58 | responses.add(typedResponse);
59 | }
60 | return responses;
61 | }
62 |
63 | public Observable transferEventObservable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) {
64 | final Event event = new Event("Transfer",
65 | Arrays.>asList(new TypeReference() {}, new TypeReference() {}),
66 | Arrays.>asList(new TypeReference() {}));
67 | EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress());
68 | filter.addSingleTopic(EventEncoder.encode(event));
69 | return web3j.ethLogObservable(filter).map(new Func1() {
70 | @Override
71 | public TransferEventResponse call(Log log) {
72 | EventValues eventValues = extractEventParameters(event, log);
73 | TransferEventResponse typedResponse = new TransferEventResponse();
74 | typedResponse._from = (Address) eventValues.getIndexedValues().get(0);
75 | typedResponse._to = (Address) eventValues.getIndexedValues().get(1);
76 | typedResponse._value = (Uint256) eventValues.getNonIndexedValues().get(0);
77 | return typedResponse;
78 | }
79 | });
80 | }
81 |
82 | public List getApprovalEvents(TransactionReceipt transactionReceipt) {
83 | final Event event = new Event("Approval",
84 | Arrays.>asList(new TypeReference() {}, new TypeReference() {}),
85 | Arrays.>asList(new TypeReference() {}));
86 | List valueList = extractEventParameters(event, transactionReceipt);
87 | ArrayList responses = new ArrayList(valueList.size());
88 | for (EventValues eventValues : valueList) {
89 | ApprovalEventResponse typedResponse = new ApprovalEventResponse();
90 | typedResponse._owner = (Address) eventValues.getIndexedValues().get(0);
91 | typedResponse._spender = (Address) eventValues.getIndexedValues().get(1);
92 | typedResponse._value = (Uint256) eventValues.getNonIndexedValues().get(0);
93 | responses.add(typedResponse);
94 | }
95 | return responses;
96 | }
97 |
98 | public Observable approvalEventObservable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) {
99 | final Event event = new Event("Approval",
100 | Arrays.>asList(new TypeReference() {}, new TypeReference() {}),
101 | Arrays.>asList(new TypeReference() {}));
102 | EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress());
103 | filter.addSingleTopic(EventEncoder.encode(event));
104 | return web3j.ethLogObservable(filter).map(new Func1() {
105 | @Override
106 | public ApprovalEventResponse call(Log log) {
107 | EventValues eventValues = extractEventParameters(event, log);
108 | ApprovalEventResponse typedResponse = new ApprovalEventResponse();
109 | typedResponse._owner = (Address) eventValues.getIndexedValues().get(0);
110 | typedResponse._spender = (Address) eventValues.getIndexedValues().get(1);
111 | typedResponse._value = (Uint256) eventValues.getNonIndexedValues().get(0);
112 | return typedResponse;
113 | }
114 | });
115 | }
116 |
117 | public Future name() throws IOException {
118 | Function function = new Function("name",
119 | Arrays.asList(),
120 | Arrays.>asList(new TypeReference() {}));
121 | return executeCallSingleValueReturn(function);
122 | }
123 |
124 | public TransactionReceipt approve(Address _spender, Uint256 _value) throws IOException, TransactionException {
125 | Function function = new Function("approve", Arrays.asList(_spender, _value), Collections.>emptyList());
126 | return executeTransaction(function);
127 | }
128 |
129 | public Future totalSupply() throws IOException {
130 | Function function = new Function("totalSupply",
131 | Arrays.asList(),
132 | Arrays.>asList(new TypeReference() {}));
133 | return executeCallSingleValueReturn(function);
134 | }
135 |
136 | public TransactionReceipt transferFrom(Address _from, Address _to, Uint256 _value) throws IOException, TransactionException {
137 | Function function = new Function("transferFrom", Arrays.asList(_from, _to, _value), Collections.>emptyList());
138 | return executeTransaction(function);
139 | }
140 |
141 | public Future decimals() throws IOException {
142 | Function function = new Function("decimals",
143 | Arrays.asList(),
144 | Arrays.>asList(new TypeReference() {}));
145 | return executeCallSingleValueReturn(function);
146 | }
147 |
148 | public Future version() throws IOException {
149 | Function function = new Function("version",
150 | Arrays.asList(),
151 | Arrays.>asList(new TypeReference() {}));
152 | return executeCallSingleValueReturn(function);
153 | }
154 |
155 | public Uint256 balanceOf(Address _owner) throws IOException {
156 | Function function = new Function("balanceOf",
157 | Arrays.asList(_owner),
158 | Arrays.>asList(new TypeReference() {}));
159 | return executeCallSingleValueReturn(function);
160 | }
161 |
162 | public Future symbol() throws IOException {
163 | Function function = new Function("symbol",
164 | Arrays.asList(),
165 | Arrays.>asList(new TypeReference() {}));
166 | return executeCallSingleValueReturn(function);
167 | }
168 |
169 | public TransactionReceipt transfer(Address _to, Uint256 _value) throws IOException, TransactionException {
170 | Function function = new Function("transfer", Arrays.asList(_to, _value), Collections.>emptyList());
171 | return executeTransaction(function);
172 | }
173 |
174 | public TransactionReceipt approveAndCall(Address _spender, Uint256 _value, DynamicBytes _extraData) throws IOException, TransactionException {
175 | Function function = new Function("approveAndCall", Arrays.asList(_spender, _value, _extraData), Collections.>emptyList());
176 | return executeTransaction(function);
177 | }
178 |
179 | public Future allowance(Address _owner, Address _spender) throws IOException {
180 | Function function = new Function("allowance",
181 | Arrays.asList(_owner, _spender),
182 | Arrays.>asList(new TypeReference() {}));
183 | return executeCallSingleValueReturn(function);
184 | }
185 |
186 | public static HumanStandardToken deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit, BigInteger initialWeiValue, Uint256 _initialAmount, Utf8String _tokenName, Uint8 _decimalUnits, Utf8String _tokenSymbol) throws IOException, TransactionException {
187 | String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol));
188 | return deploy(HumanStandardToken.class, web3j, credentials, gasPrice, gasLimit, BINARY, encodedConstructor, initialWeiValue);
189 | }
190 |
191 | public static HumanStandardToken deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, BigInteger initialWeiValue, Uint256 _initialAmount, Utf8String _tokenName, Uint8 _decimalUnits, Utf8String _tokenSymbol) throws IOException, TransactionException {
192 | String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol));
193 | return deploy(HumanStandardToken.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, encodedConstructor, initialWeiValue);
194 | }
195 |
196 | public static HumanStandardToken load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
197 | return new HumanStandardToken(contractAddress, web3j, credentials, gasPrice, gasLimit);
198 | }
199 |
200 | public static HumanStandardToken load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
201 | return new HumanStandardToken(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
202 | }
203 |
204 | public static class TransferEventResponse {
205 | public Address _from;
206 |
207 | public Address _to;
208 |
209 | public Uint256 _value;
210 | }
211 |
212 | public static class ApprovalEventResponse {
213 | public Address _owner;
214 |
215 | public Address _spender;
216 |
217 | public Uint256 _value;
218 | }
219 |
220 | }
221 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/JsonCredentials.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model;
2 |
3 | import lombok.Data;
4 | import org.web3j.crypto.Credentials;
5 |
6 | @Data
7 | public class JsonCredentials {
8 |
9 | private String publicKey;
10 | private String privateKey;
11 | private String address;
12 |
13 |
14 | public JsonCredentials(Credentials credentials) {
15 | this.address = credentials.getAddress();
16 | this.privateKey = credentials.getEcKeyPair().getPrivateKey().toString(16);
17 | this.publicKey = credentials.getEcKeyPair().getPublicKey().toString(16);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/Method.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import lombok.*;
5 |
6 | import javax.validation.constraints.NotNull;
7 |
8 | @Builder(builderClassName="Builder", toBuilder=true)
9 | @Getter
10 | @Setter
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @JsonIgnoreProperties(ignoreUnknown = true)
14 | public class Method {
15 | @NotNull
16 | private Object[] args;
17 | private String name;
18 | public Object[] getArgs() {
19 | if (args != null) {
20 | return args;
21 | }
22 | return new Object[0];
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/NodeConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model;
2 |
3 | import lombok.Data;
4 | import org.springframework.boot.context.properties.ConfigurationProperties;
5 | import org.springframework.stereotype.Component;
6 |
7 | /**
8 | * Node configuration bean.
9 | */
10 | @Data
11 | @ConfigurationProperties
12 | @Component
13 | public class NodeConfiguration {
14 |
15 | private String nodeEndpoint;
16 | private String fromAddress;
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/Receipt.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4 | import com.mvc.polymorphic.utils.EthereumUtil;
5 | import lombok.*;
6 | import org.apache.commons.lang3.StringUtils;
7 |
8 | import java.io.Serializable;
9 |
10 | @Builder(builderClassName="Builder", toBuilder=true)
11 | @Setter
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @JsonIgnoreProperties(ignoreUnknown = true)
15 | @ToString(of= {"contractAddress", "accountAddr"}, includeFieldNames = false)
16 | public class Receipt implements Serializable {
17 | @Getter
18 | private String transactionHash;
19 | @Getter
20 | private String contractAddress;
21 | @Getter
22 | private String blockHash;
23 | private String transactionIndex;
24 | private String blockNumber;
25 | private String cumulativeGasUsed;
26 | private String gasUsed;
27 | private Type type;
28 | @Getter
29 | @Setter
30 | private String accountAddr;
31 |
32 | public enum Type {CREATE, MODIFY};
33 |
34 | public long getTransactionIndex() {
35 | return decrypt(transactionIndex);
36 | }
37 |
38 | public long getBlockNumber() {
39 | return decrypt(blockNumber);
40 | }
41 |
42 | public long getCumulativeGasUsed() {
43 | return decrypt(cumulativeGasUsed);
44 | }
45 |
46 | public long getGasUsed() {
47 | return decrypt(gasUsed);
48 | }
49 |
50 | private static long decrypt(final String data) {
51 | if (StringUtils.isNotBlank(data)) {
52 | return EthereumUtil.decryptQuantity(data);
53 | }
54 | return 0;
55 |
56 | }
57 |
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/TransactionResponse.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 |
6 | /**
7 | * TransactionResponse wrapper.
8 | */
9 | @Getter
10 | @Setter
11 | public class TransactionResponse {
12 |
13 | private String transactionHash;
14 | private T event;
15 |
16 | TransactionResponse() { }
17 |
18 | public TransactionResponse(String transactionHash) {
19 | this(transactionHash, null);
20 | }
21 |
22 | public TransactionResponse(String transactionHash, T event) {
23 | this.transactionHash = transactionHash;
24 | this.event = event;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/TransferEventResponse.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class TransferEventResponse {
7 | private String from;
8 | private String to;
9 | private long value;
10 |
11 | public TransferEventResponse() {
12 | }
13 |
14 | public TransferEventResponse(
15 | HumanStandardToken.TransferEventResponse transferEventResponse) {
16 | this.from = transferEventResponse._from.toString();
17 | this.to = transferEventResponse._to.toString();
18 | this.value = transferEventResponse._value.getValue().longValueExact();
19 | }
20 | }
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/dto/BalanceDTO.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model.dto;
2 |
3 | import lombok.Data;
4 |
5 | import java.io.Serializable;
6 |
7 | @Data
8 | public class BalanceDTO implements Serializable {
9 | private String address;
10 | private String blockId;
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/dto/ExportAccountDTO.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model.dto;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class ExportAccountDTO {
7 | private String address;
8 | private String passphrase;
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/dto/ImportRawKeyDTO.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model.dto;
2 |
3 |
4 | import lombok.Data;
5 |
6 | @Data
7 | public class ImportRawKeyDTO {
8 |
9 | private String keydata;
10 | private String passphrase;
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/dto/NewAccountDTO.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model.dto;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class NewAccountDTO {
7 |
8 | private String passphrase;
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/dto/PersonalByPrivateKeyDTO.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model.dto;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class PersonalByPrivateKeyDTO {
7 |
8 | private String privateKey;
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/dto/RawTransactionDTO.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model.dto;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class RawTransactionDTO {
7 |
8 | private String signedMessage;
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/dto/SendTransactionDTO.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model.dto;
2 |
3 | import lombok.Data;
4 |
5 | import javax.validation.constraints.NotNull;
6 | import java.io.Serializable;
7 | import java.math.BigDecimal;
8 |
9 | /**
10 | * @author ethands
11 | */
12 | @Data
13 | public class SendTransactionDTO implements Serializable {
14 | private static final long serialVersionUID = 6477321453043666156L;
15 | @NotNull
16 | private String pass;
17 | @NotNull
18 | private String from;
19 | @NotNull
20 | private String to;
21 | @NotNull
22 | private BigDecimal value;
23 |
24 | }
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/dto/TransactionByHashDTO.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model.dto;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class TransactionByHashDTO {
7 | private String transactionHash;
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/model/dto/TransactionCountDTO.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.model.dto;
2 |
3 | import lombok.Data;
4 |
5 | @Data
6 | public class TransactionCountDTO {
7 |
8 | private String address;
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/mvc/polymorphic/service/BchService.java:
--------------------------------------------------------------------------------
1 | package com.mvc.polymorphic.service;
2 |
3 | import com.mvc.bitcoincashj.core.*;
4 | import com.mvc.bitcoincashj.core.listeners.TransactionConfidenceEventListener;
5 | import com.mvc.bitcoincashj.kits.WalletAppKit;
6 | import com.mvc.bitcoincashj.params.MainNetParams;
7 | import com.mvc.bitcoincashj.params.TestNet3Params;
8 | import com.mvc.bitcoincashj.script.Script;
9 | import com.mvc.bitcoincashj.wallet.Wallet;
10 | import com.mvc.bitcoincashj.wallet.listeners.KeyChainEventListener;
11 | import com.mvc.bitcoincashj.wallet.listeners.ScriptsChangeEventListener;
12 | import com.mvc.bitcoincashj.wallet.listeners.WalletCoinsReceivedEventListener;
13 | import com.mvc.bitcoincashj.wallet.listeners.WalletCoinsSentEventListener;
14 | import com.mvc.polymorphic.common.BlockChainService;
15 | import com.mvc.polymorphic.common.BlockResult;
16 | import com.mvc.polymorphic.common.bean.BchTransaction;
17 | import lombok.extern.java.Log;
18 | import org.springframework.stereotype.Service;
19 | import org.springframework.util.StringUtils;
20 |
21 | import java.io.File;
22 | import java.math.BigDecimal;
23 | import java.util.Arrays;
24 | import java.util.HashMap;
25 | import java.util.List;
26 | import java.util.Map;
27 |
28 | /**
29 | * bcc service
30 | *
31 | * @author qiyichen
32 | * @create 2018/4/12 13:43
33 | */
34 | @Service("BchService")
35 | @Log
36 | public class BchService extends BlockChainService {
37 |
38 | private WalletAppKit kit;
39 | private final static String DEFAULT_FILE_PREFIX = "DEFAULT_FILE_PREFIX";
40 | private final static String TEST_KEY = "local";
41 | private final static String TOKEN_NAME = "bch";
42 | private static Boolean initFinished = false;
43 |
44 | @Override
45 | protected BlockResult getBalance(String address) {
46 | Object result = kit.wallet().getBalance().toFriendlyString();
47 | return tokenSuccess(TOKEN_NAME, result);
48 | }
49 |
50 | @Override
51 | protected BlockResult getTransactionByHash(String transactionHash) {
52 | Transaction trans = kit.wallet().getTransaction(Sha256Hash.wrap(transactionHash));
53 | BchTransaction transaction = BchTransaction.build(trans, kit.wallet());
54 | return tokenSuccess(TOKEN_NAME, transaction);
55 | }
56 |
57 | @Override
58 | protected BlockResult sendTransaction(String pass, String from, String toAddress, BigDecimal data) {
59 | String blockEnv = tokenConfig.getEnv().get(TOKEN_NAME);
60 | if (!initFinished) {
61 | return tokenFail(TOKEN_NAME, String.format("wallet is async, please wait, now height is %s", kit.wallet().getLastBlockSeenHeight()));
62 | }
63 | log.info("send money to: " + toAddress);
64 | Coin value = Coin.parseCoin(String.valueOf(data));
65 | // if the wallet have more than 1 ecKey, we need to choose one for pay
66 | Address to = Address.fromBase58(kit.params(), toAddress);
67 | Wallet.SendResult result = null;
68 | try {
69 | if (TEST_KEY.equalsIgnoreCase(blockEnv)) {
70 | kit.peerGroup().setMaxConnections(4);
71 | }
72 | result = kit.wallet().sendCoins(kit.peerGroup(), to, value, true);
73 | } catch (Exception e) {
74 | return tokenFail(TOKEN_NAME, e.getMessage());
75 | } finally {
76 | if (!kit.wallet().isEncrypted()) {
77 | kit.wallet().encrypt(pass);
78 | }
79 | }
80 | log.info("coins sent. transaction hash: " + result.tx.getHashAsString());
81 | return tokenSuccess(TOKEN_NAME, result.tx.getHashAsString());
82 | }
83 |
84 | @Override
85 | protected BlockResult newAccount(String pass) {
86 | if (!initFinished) {
87 | return tokenFail(TOKEN_NAME, String.format("wallet is async, please wait, now height is %s", kit.wallet().getLastBlockSeenHeight()));
88 | }
89 | Address address = kit.wallet().freshReceiveAddress();
90 | kit.wallet().addWatchedAddress(address);
91 | return tokenSuccess(TOKEN_NAME, address.toString());
92 | }
93 |
94 | @Override
95 | protected BlockResult getConfirmation(String transactionHash) {
96 | BchTransaction transaction = (BchTransaction) getTransactionByHash(transactionHash).getResult();
97 | return tokenSuccess(TOKEN_NAME, transaction.getDepth());
98 | }
99 |
100 | @Override
101 | protected void onTransaction(Object... objects) {
102 | System.out.println("db save");
103 | }
104 |
105 | @Override
106 | public void run(String... args) throws Exception {
107 |
108 | if (!StringUtils.isEmpty(tokenConfig.getEnv().get(TOKEN_NAME))) {
109 | String blockEnv = tokenConfig.getEnv().get(TOKEN_NAME);
110 | String blockPath = tokenConfig.getPath().get(TOKEN_NAME).get(blockEnv);
111 | WalletAppKit kit = new WalletAppKit(getNetWork(blockEnv), new File(blockPath + blockEnv), DEFAULT_FILE_PREFIX);
112 | this.kit = kit;
113 | System.out.println("BCH Service initialized and nothing happened.");
114 | startListen();
115 | // init wallet
116 | if (kit.wallet().getImportedKeys().size() == 0) {
117 | String pass = tokenConfig.getPass().get(TOKEN_NAME).get(blockEnv);
118 | ECKey ecKey = new ECKey();
119 | kit.wallet().encrypt(pass);
120 | kit.wallet().importKeysAndEncrypt(Arrays.asList(ecKey), pass);
121 | kit.wallet().addWatchedAddress(ecKey.toAddress(kit.params()));
122 | }
123 | initFinished = true;
124 | } else {
125 | log.info("BCH not supported!");
126 | }
127 | }
128 |
129 | private void startListen() {
130 | log.info("Start peer group");
131 | kit.startAsync();
132 | kit.awaitRunning();
133 | log.info("Downloading block chain");
134 | log.info("start listen");
135 | kit.wallet().addCoinsReceivedEventListener(new WalletCoinsReceivedEventListener() {
136 | @Override
137 | public void onCoinsReceived(Wallet wallet, Transaction transaction, Coin coin, Coin coin1) {
138 | System.out.println("coins received");
139 | Map map = new HashMap<>();
140 | onTransaction(map);
141 | }
142 | });
143 |
144 | kit.wallet().addCoinsSentEventListener(new WalletCoinsSentEventListener() {
145 | @Override
146 | public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
147 | System.out.println("coins sent");
148 | Map map = new HashMap<>();
149 | onTransaction(map);
150 | }
151 | });
152 |
153 | kit.wallet().addKeyChainEventListener(new KeyChainEventListener() {
154 | @Override
155 | public void onKeysAdded(List keys) {
156 | System.out.println("new key added");
157 | Map map = new HashMap<>();
158 | onTransaction(map);
159 | }
160 | });
161 |
162 | kit.wallet().addScriptsChangeEventListener(new ScriptsChangeEventListener() {
163 | @Override
164 | public void onScriptsChanged(Wallet wallet, List