├── LICENSE
├── README.md
├── api-demo.iml
├── api-java-sdk
├── api-java-sdk.iml
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── com
│ │ └── tokenview
│ │ └── api
│ │ ├── client
│ │ ├── APIClient.java
│ │ ├── APICredentials.java
│ │ ├── APIHttpClient.java
│ │ ├── APIRetrofit.java
│ │ └── ApiHttp.java
│ │ ├── config
│ │ └── APIConfiguration.java
│ │ ├── constant
│ │ └── APIConstants.java
│ │ ├── enums
│ │ ├── CharsetEnum.java
│ │ ├── ContentTypeEnum.java
│ │ ├── I18nEnum.java
│ │ └── ResultCode.java
│ │ ├── exception
│ │ └── APIException.java
│ │ ├── result
│ │ └── HttpResult.java
│ │ └── service
│ │ ├── base
│ │ ├── BaseService.java
│ │ └── Impl
│ │ │ ├── BaseAPI.java
│ │ │ └── BaseServiceImpl.java
│ │ └── wallet
│ │ ├── WalletService.java
│ │ └── impl
│ │ ├── WalletAPI.java
│ │ └── WalletServiceImpl.java
│ └── test
│ └── java
│ └── com
│ └── tokenview
│ └── api
│ └── test
│ ├── base
│ ├── BaseAPITest.java
│ └── BaseConfig.java
│ ├── services
│ ├── ServicesAPITest.java
│ └── ServicesConfig.java
│ └── wallet
│ ├── WalletAPITest.java
│ └── WalletConfig.java
├── pom.xml
└── sign-java-sdk
├── pom.xml
├── sign-java-sdk.iml
└── src
├── main
└── java
│ └── com
│ └── tokenview
│ ├── account
│ └── AddressUtil.java
│ ├── bean
│ └── WalletBean.java
│ ├── enums
│ ├── Coin.java
│ └── Version.java
│ ├── params
│ ├── DashParams.java
│ ├── DogeParams.java
│ └── LitecoinParams.java
│ ├── sign
│ ├── btc
│ │ └── BTCSign.java
│ └── eth
│ │ └── ETHSign.java
│ └── utils
│ ├── BTCWalletUtil.java
│ ├── ECKeyUtil.java
│ ├── HexUtil.java
│ ├── HttpClientUtils.java
│ └── HttpUtil.java
└── test
└── java
└── com
└── tokenview
└── sign
└── test
├── BTCSignTest.java
└── ETHSignTest.java
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 tokenview-hub
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | The Tokenview api-demo Project
2 | ===
3 | * Tokenview signature and api program implementation in Java.
4 |
5 | Features
6 | ---
7 | * 120+ blockchains ,100B+ transactions ,20B+ addresses ,coin markets ,statistical information are supported
8 | * Demo code are mainly used for wallet app now,private key is kept by the developer to prevent leakage during transmission
9 | * Main crypto currency offline signature is supported
10 | * Transaction-broadcasting is supported
11 | * Fully Java ready ,with definition files and full Java source and Springboot 2.0
12 | * MIT License (including ALL dependencies) ;completely open source to do with as you please
13 |
14 | Launch your application
15 | ---
16 | * Get apikey here: https://services.tokenview.io
17 | * Download api-demo project and check how the tokenview API is called in the test class of this project ,take it as a prototype extension, modify it into the project you want, package it and add it to your application project
18 | * Check postman document and start your application : https://documenter.getpostman.com/view/5728777/SVSEvX8k?version=latest
19 |
20 | Documentation
21 | ---
22 | * Official site: https://services.tokenview.io
23 | * Multi-chain Blockchain Explorer site: https://tokenview.io
24 | * Postman document: https://documenter.getpostman.com/view/5728777/SVSEvX8k?version=latest
25 |
26 | License
27 | ---
28 | * MIT License (including all dependencies).
29 |
--------------------------------------------------------------------------------
/api-demo.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/api-java-sdk/api-java-sdk.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/api-java-sdk/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | api-demo
7 | com.tokenview
8 | 1.0.0
9 |
10 | 4.0.0
11 |
12 | com.tokenview
13 | api-java-sdk
14 | 1.0.0
15 |
16 |
17 |
18 | com.tokenview
19 | sign-java-sdk
20 | 1.0.0
21 |
22 |
23 | io.netty
24 | netty-all
25 | 4.1.36.Final
26 |
27 |
28 | com.squareup.okhttp3
29 | okhttp
30 | 3.10.0
31 |
32 |
33 | com.squareup.retrofit2
34 | retrofit
35 | 2.3.0
36 |
37 |
38 | org.slf4j
39 | slf4j-log4j12
40 | 1.8.0-beta2
41 |
42 |
43 | org.springframework
44 | spring-context
45 | 5.1.5.RELEASE
46 |
47 |
48 | com.squareup.retrofit2
49 | converter-scalars
50 | 2.3.0
51 |
52 |
53 | com.squareup.retrofit2
54 | converter-gson
55 | 2.3.0
56 |
57 |
58 | com.squareup.retrofit2
59 | adapter-rxjava
60 | 2.3.0
61 |
62 |
63 | org.apache.commons
64 | commons-lang3
65 | 3.7
66 |
67 |
68 | commons-collections
69 | commons-collections
70 | 3.2.2
71 |
72 |
73 | ch.qos.logback
74 | logback-classic
75 | 1.2.3
76 |
77 |
78 | com.google.guava
79 | guava
80 | 27.1-jre
81 |
82 |
83 | commons-codec
84 | commons-codec
85 | 1.12
86 |
87 |
88 | org.apache.commons
89 | commons-compress
90 | 1.18
91 |
92 |
93 | junit
94 | junit
95 | 4.12
96 | test
97 |
98 |
99 | org.projectlombok
100 | lombok
101 | 1.18.4
102 |
103 |
104 | com.fasterxml.jackson.core
105 | jackson-databind
106 | 2.9.5
107 |
108 |
109 | commons-beanutils
110 | commons-beanutils
111 | 1.9.3
112 |
113 |
114 | commons-collections
115 | commons-collections
116 | 3.2.1
117 |
118 |
119 | commons-lang
120 | commons-lang
121 | 2.6
122 |
123 |
124 | commons-logging
125 | commons-logging
126 | 1.1.1
127 |
128 |
129 | net.sf.ezmorph
130 | ezmorph
131 | 1.0.6
132 |
133 |
134 | net.sf.json-lib
135 | json-lib
136 | 2.2.3
137 | jdk15
138 |
139 |
140 | org.springframework
141 | spring-web
142 | 5.0.9.RELEASE
143 | test
144 |
145 |
146 | jstl
147 | jstl
148 | 1.2
149 | test
150 |
151 |
152 | com.alibaba
153 | fastjson
154 | 1.2.12
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 | org.apache.maven.plugins
163 | maven-compiler-plugin
164 |
165 | 1.8
166 | 1.8
167 |
168 |
169 |
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/client/APIClient.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.client;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.tokenview.api.config.APIConfiguration;
5 | import com.tokenview.api.constant.APIConstants;
6 | import com.tokenview.api.exception.APIException;
7 | import com.tokenview.api.result.HttpResult;
8 | import okhttp3.OkHttpClient;
9 | import org.apache.commons.lang.StringUtils;
10 | import retrofit2.Call;
11 | import retrofit2.Response;
12 | import retrofit2.Retrofit;
13 | import java.io.IOException;
14 |
15 |
16 | /**
17 | * TokenView API Client
18 | *
19 | * @author Moilk
20 | * @version 1.0.0
21 | * @date 2021/1/20 11:13
22 | */
23 | public class APIClient {
24 |
25 | private final APIConfiguration config;
26 | private final APICredentials credentials;
27 | private final OkHttpClient client;
28 | private final Retrofit retrofit;
29 | private final ApiHttp apiHttp;
30 | /**
31 | * Initialize the apis client
32 | */
33 | public APIClient(final APIConfiguration config) {
34 | if (config == null || StringUtils.isEmpty(config.getEndpoint())) {
35 | throw new RuntimeException("The APIClient params can't be empty.");
36 | }
37 | this.config = config;
38 | this.credentials = new APICredentials(config);
39 | this.client = new APIHttpClient(config, this.credentials).client();
40 | this.retrofit = new APIRetrofit(config, this.client).retrofit();
41 | this.apiHttp = new ApiHttp(config, this.client);
42 | }
43 |
44 | /**
45 | * Initialize the retrofit operation service
46 | */
47 | public T createService(final Class service) {
48 | return this.retrofit.create(service);
49 | }
50 |
51 | public ApiHttp getApiHttp() {
52 | return this.apiHttp;
53 | }
54 |
55 | /**
56 | * Synchronous send request
57 | */
58 | //解析
59 | public T executeSync(final Call call){
60 | try {
61 |
62 | final Response response = call.execute();
63 |
64 | //获取状态码
65 | final int status = response.code();
66 | //获取错误信息
67 | final String message = new StringBuilder().append(response.code()).append(" / ").append(response.message()).toString();
68 | //响应成功
69 | if (response.isSuccessful()) {
70 | return response.body();
71 | } else if (APIConstants.resultStatusArray.contains(status)) {
72 | final HttpResult result = JSON.parseObject(new String(response.errorBody().bytes()), HttpResult.class);
73 | if(result.getCode() == 0 && result.getMessage() == null){
74 | throw new APIException(result.getErrorCode(),result.getErrorMessage());
75 | }else{
76 | throw new APIException(result.getCode(), result.getMessage());
77 | }
78 | } else {
79 | throw new APIException(message);
80 | }
81 | } catch (final IOException e) {
82 | throw new APIException("APIClient executeSync exception.", e);
83 | }
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/client/APICredentials.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.client;
2 |
3 | import com.tokenview.api.config.APIConfiguration;
4 |
5 | /**
6 | * API Credentials
7 | *
8 | * @author Moilk
9 | * @version 1.0.0
10 | * @date 2021/1/18 12:24
11 | */
12 | public class APICredentials {
13 | public String getApiKey() {
14 | return apiKey;
15 | }
16 |
17 | public void setApiKey(String apiKey) {
18 | this.apiKey = apiKey;
19 | }
20 |
21 | /**
22 | * The user's secret key provided by TokenView.
23 | */
24 | private String apiKey;
25 |
26 | public APICredentials(APIConfiguration config) {
27 | super();
28 | this.apiKey = config.getApiKey();
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/client/APIHttpClient.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.client;
2 |
3 | import com.tokenview.api.config.APIConfiguration;
4 | import com.tokenview.api.constant.APIConstants;
5 | import okhttp3.OkHttpClient;
6 | import okhttp3.Request;
7 | import okhttp3.RequestBody;
8 | import okio.Buffer;
9 |
10 | import java.io.IOException;
11 | import java.util.concurrent.TimeUnit;
12 |
13 | public class APIHttpClient {
14 | private final APIConfiguration config;
15 | private final APICredentials credentials;
16 |
17 |
18 | public APIHttpClient(final APIConfiguration config, final APICredentials credentials) {
19 | this.config = config;
20 | this.credentials = credentials;
21 | }
22 |
23 | public OkHttpClient client() {
24 | final OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
25 | clientBuilder.connectTimeout(this.config.getConnectTimeout(), TimeUnit.SECONDS);
26 | clientBuilder.readTimeout(this.config.getReadTimeout(), TimeUnit.SECONDS);
27 | clientBuilder.writeTimeout(this.config.getWriteTimeout(), TimeUnit.SECONDS);
28 | clientBuilder.retryOnConnectionFailure(this.config.isRetryOnConnectionFailure());
29 | // clientBuilder.addInterceptor((Interceptor.Chain chain) -> {
30 | // final Request.Builder requestBuilder = chain.request().newBuilder();
31 | // final String timestamp = DateUtils.getUnixTime();
32 | // //打印首行时间戳
33 | //// System.out.println("时间戳timestamp={" + timestamp + "}");
34 | //// 设置模拟盘请求头
35 | //// String simulated = "1";
36 | // requestBuilder.headers(this.headers(chain.request(), timestamp));
37 | // final Request request = requestBuilder.build();
38 | // if (this.config.isPrint()) {
39 | // this.printRequest(request, timestamp);
40 | // }
41 | // return chain.proceed(request);
42 | // });
43 | return clientBuilder.build();
44 | }
45 |
46 | //返回请求路径url
47 | private String url(final Request request) {
48 | return request.url().toString();
49 | }
50 | //将请求方法转变为大写,并返回
51 | private String method(final Request request) {
52 | return request.method().toUpperCase();
53 | }
54 | //返回请求路径
55 | private String requestPath(final Request request) {
56 | String url = this.url(request);
57 | url = url.replace(this.config.getEndpoint(), APIConstants.EMPTY);
58 | String requestPath = url;
59 | if (requestPath.contains(APIConstants.QUESTION)) {
60 | requestPath = requestPath.substring(0, url.lastIndexOf(APIConstants.QUESTION));
61 | }
62 | if(this.config.getEndpoint().endsWith(APIConstants.SLASH)){
63 | requestPath = APIConstants.SLASH + requestPath;
64 | }
65 | return requestPath;
66 | }
67 |
68 | private String queryString(final Request request) {
69 | final String url = this.url(request);
70 | request.body();
71 | //请求参数为空字符串
72 | String queryString = APIConstants.EMPTY;
73 | //如果URL中包含?即存在参数的拼接
74 | if (url.contains(APIConstants.QUESTION)) {
75 | queryString = url.substring(url.lastIndexOf(APIConstants.QUESTION) + 1);
76 | }
77 | return queryString;
78 | }
79 |
80 | private String body(final Request request) throws IOException {
81 | final RequestBody requestBody = request.body();
82 | String body = APIConstants.EMPTY;
83 | if (requestBody != null) {
84 | final Buffer buffer = new Buffer();
85 | requestBody.writeTo(buffer);
86 | body = buffer.readString(APIConstants.UTF_8);
87 | }
88 | return body;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/client/APIRetrofit.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.client;
2 |
3 |
4 | import com.tokenview.api.config.APIConfiguration;
5 | import okhttp3.OkHttpClient;
6 | import retrofit2.Retrofit;
7 | import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
8 | import retrofit2.converter.gson.GsonConverterFactory;
9 | import retrofit2.converter.scalars.ScalarsConverterFactory;
10 |
11 | public class APIRetrofit {
12 | private APIConfiguration config;
13 | private OkHttpClient client;
14 |
15 | public APIRetrofit(APIConfiguration config, OkHttpClient client) {
16 | this.config = config;
17 | this.client = client;
18 | }
19 |
20 | public Retrofit retrofit() {
21 | Retrofit.Builder builder = new Retrofit.Builder();
22 | builder.client(this.client);
23 | builder.addConverterFactory(ScalarsConverterFactory.create());
24 | builder.addConverterFactory(GsonConverterFactory.create());
25 | builder.addCallAdapterFactory(RxJavaCallAdapterFactory.create());
26 | builder.baseUrl(this.config.getEndpoint());
27 | return builder.build();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/client/ApiHttp.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.client;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 | import com.tokenview.api.config.APIConfiguration;
5 | import com.tokenview.api.constant.APIConstants;
6 | import com.tokenview.api.exception.APIException;
7 | import okhttp3.*;
8 |
9 | import java.io.IOException;
10 | import java.util.Date;
11 |
12 | public class ApiHttp {
13 | private OkHttpClient client;
14 | private APIConfiguration config;
15 |
16 | static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
17 |
18 | public ApiHttp(APIConfiguration config, OkHttpClient client) {
19 | this.config = config;
20 | this.client = client;
21 | }
22 |
23 | private void printResponse(int status, String message, String body, boolean responseIsNotNull) {
24 | StringBuilder responseInfo = new StringBuilder();
25 | responseInfo.append("\n\tResponse").append("(").append(new Date()).append("):");
26 | if (responseIsNotNull) {
27 | responseInfo.append("\n\t\t").append("Status: ").append(status);
28 | responseInfo.append("\n\t\t").append("Message: ").append(message);
29 | responseInfo.append("\n\t\t").append("Response Body: ").append(body);
30 | } else {
31 | responseInfo.append("\n\t\t").append("\n\tRequest Error: response is null");
32 | }
33 | }
34 |
35 | public String url(String url) {
36 | return new StringBuilder(this.config.getEndpoint()).append(url).toString();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/config/APIConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.config;
2 |
3 | import com.tokenview.api.constant.APIConstants;
4 | import com.tokenview.api.enums.I18nEnum;
5 |
6 | /**
7 | * API configuration information
8 | *
9 | * @author Moilk
10 | * @version 1.0.0
11 | * @date 2021/1/20 14:29
12 | */
13 | public class APIConfiguration {
14 |
15 | /**
16 | * The user's api key provided by TokenView.
17 | */
18 | private String apiKey;
19 | /**
20 | * Rest api endpoint url.
21 | */
22 | private String endpoint;
23 | /**
24 | * Host connection timeout.
25 | */
26 | private long connectTimeout;
27 | /**
28 | * The host reads the information timeout.
29 | */
30 | private long readTimeout;
31 | /**
32 | * The host writes the information timeout.
33 | */
34 | private long writeTimeout;
35 | /**
36 | * Failure reconnection, default true.
37 | */
38 | private boolean retryOnConnectionFailure;
39 | /**
40 | * The print api information.
41 | */
42 | private boolean print;
43 | /**
44 | * I18nEnum
45 | */
46 | private I18nEnum i18n;
47 |
48 | public APIConfiguration() {
49 | this(null);
50 | }
51 | public APIConfiguration(String endpoint) {
52 | super();
53 | this.apiKey = null;
54 | this.endpoint = endpoint;
55 | this.connectTimeout = APIConstants.TIMEOUT;
56 | this.readTimeout = APIConstants.TIMEOUT;
57 | this.writeTimeout = APIConstants.TIMEOUT;
58 | this.retryOnConnectionFailure = true;
59 | this.print = false;
60 | this.i18n = I18nEnum.ENGLISH;
61 | }
62 |
63 | public String getApiKey() {
64 | return apiKey;
65 | }
66 |
67 | public void setApiKey(String apiKey) {
68 | this.apiKey = apiKey;
69 | }
70 |
71 | public String getEndpoint() {
72 | return endpoint;
73 | }
74 |
75 | public void setEndpoint(String endpoint) {
76 | this.endpoint = endpoint;
77 | }
78 |
79 | public long getConnectTimeout() {
80 | return connectTimeout;
81 | }
82 |
83 | public void setConnectTimeout(long connectTimeout) {
84 | this.connectTimeout = connectTimeout;
85 | }
86 |
87 | public long getReadTimeout() {
88 | return readTimeout;
89 | }
90 |
91 | public void setReadTimeout(long readTimeout) {
92 | this.readTimeout = readTimeout;
93 | }
94 |
95 | public long getWriteTimeout() {
96 | return writeTimeout;
97 | }
98 |
99 | public void setWriteTimeout(long writeTimeout) {
100 | this.writeTimeout = writeTimeout;
101 | }
102 |
103 | public boolean isRetryOnConnectionFailure() {
104 | return retryOnConnectionFailure;
105 | }
106 |
107 | public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) {
108 | this.retryOnConnectionFailure = retryOnConnectionFailure;
109 | }
110 |
111 | public boolean isPrint() {
112 | return print;
113 | }
114 |
115 | public void setPrint(boolean print) {
116 | this.print = print;
117 | }
118 |
119 | public I18nEnum getI18n() {
120 | return i18n;
121 | }
122 |
123 | public void setI18n(I18nEnum i18n) {
124 | this.i18n = i18n;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/constant/APIConstants.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.constant;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 | import com.tokenview.api.enums.ContentTypeEnum;
5 | import okhttp3.MediaType;
6 |
7 | import java.nio.charset.Charset;
8 | import java.util.Arrays;
9 | import java.util.List;
10 |
11 | public class APIConstants {
12 | /**
13 | * The default timeout is 30 seconds.
14 | */
15 | public static final long TIMEOUT = 1000 * 30;
16 | /**
17 | * All requests and responses are application/json content type and follow typical HTTP response status codes for success and failure.
18 | */
19 | public static final String CONTENT_TYPE = "Content-Type";
20 |
21 | public static final String ACCEPT = "Accept";
22 |
23 | public static final String COOKIE = "Cookie";
24 |
25 | public static final String LOCALE = "locale=";
26 |
27 | public static final MediaType JSON = MediaType.parse(ContentTypeEnum.APPLICATION_JSON.contentType());
28 |
29 | public static final Charset UTF_8 = Charset.forName("UTF-8");
30 |
31 | public static final String QUESTION = "?";
32 |
33 | public static final String EMPTY = "";
34 |
35 | public static final JSONObject NOTHING = new JSONObject();
36 |
37 | public static final List toStringTypeArray = Arrays.asList(
38 | "class java.lang.Long",
39 | "class java.lang.Integer",
40 | "long",
41 | "int");
42 | public static final List toStringTypeDoubleArray = Arrays.asList(
43 | "class java.lang.Double",
44 | "double");
45 |
46 | public static final List resultStatusArray = Arrays.asList(
47 | 400,401,429,500);
48 |
49 | public static final String BOOLEAN = "boolean";
50 | public static final String IS = "is";
51 | public static final String get = "get";
52 | public static final char a = 'a';
53 | public static final char z = 'z';
54 | public static final String ZERO_STRING = "0";
55 | public static final String DOUBLE_ZERO_STRING = "0.00";
56 |
57 | public static final String DOT1 = ".";
58 | public static final String DOT2 = "\\.";
59 | public static final String E = "E";
60 | public static final String e = "e";
61 | public static final int DEFAULT_SCALE = 2;
62 | /**
63 | * 8900000000.000000000
64 | */
65 | public static final String DOUBLE_END1 = "0+?$";
66 | /**
67 | * 8900000000.
68 | */
69 | public static final String DOUBLE_END2 = "[.]$";
70 |
71 | /**
72 | * default cursor id
73 | */
74 | public static final int ONE = 1;
75 | /**
76 | * max limit: 100
77 | */
78 | public static final int HUNDRED = 100;
79 |
80 | public static final String HLINE = "-";
81 |
82 | public static final String SLASH = "/";
83 | }
84 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/enums/CharsetEnum.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.enums;
2 |
3 | /**
4 | *
5 | * @author Moilk
6 | * @version 1.0.0
7 | * @date 2020/1/18 13:00
8 | */
9 | public enum CharsetEnum {
10 |
11 | UTF_8("UTF-8"),
12 | ISO_8859_1("ISO-8859-1"),;
13 |
14 |
15 | private String charset;
16 |
17 | CharsetEnum(String charset) {
18 | this.charset = charset;
19 | }
20 |
21 | public String charset() {
22 | return charset;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/enums/ContentTypeEnum.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.enums;
2 |
3 | /**
4 | *
5 | * @author Moilk
6 | * @version 1.0.0
7 | * @date 2020/1/18 13:00
8 | */
9 | public enum ContentTypeEnum {
10 |
11 | APPLICATION_JSON("application/json"),
12 | APPLICATION_JSON_UTF8("application/json; charset=UTF-8"),
13 | // The server does not support types
14 | APPLICATION_FORM("application/x-www-form-urlencoded; charset=UTF-8"),;
15 |
16 |
17 | private String contentType;
18 |
19 | ContentTypeEnum(String contentType) {
20 | this.contentType = contentType;
21 | }
22 |
23 | public String contentType() {
24 | return contentType;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/enums/I18nEnum.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.enums;
2 |
3 | /**
4 | * I18nEnum
5 | *
6 | * @author Moilk
7 | * @version 1.0.0
8 | * @date 2020/1/18 13:00
9 | */
10 | public enum I18nEnum {
11 | ENGLISH("en_US"),
12 | SIMPLIFIED_CHINESE("zh_CN"),
13 | TRADITIONAL_CHINESE("zh_HK"),;
14 |
15 | private String i18n;
16 |
17 | I18nEnum(String i18n) {
18 | this.i18n = i18n;
19 | }
20 |
21 | public String i18n() {
22 | return i18n;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/enums/ResultCode.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.enums;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * I18nEnum
8 | *
9 | * @author Moilk
10 | * @version 1.0.0
11 | * @date 2020/1/18 13:00
12 | */
13 | public enum ResultCode {
14 |
15 | /* 成功状态码 */
16 | SUCCESS(1, "成功"),
17 | NO_DATA(404, "无数据"),
18 |
19 | /* 参数错误:10001-19999 */
20 | PARAM_IS_INVALID(10001, "参数无效"),
21 | PARAM_IS_BLANK(10002, "参数为空"),
22 | PARAM_TYPE_BIND_ERROR(10003, "参数类型错误"),
23 | PARAM_NOT_COMPLETE(10004, "参数缺失"),
24 |
25 | /* 用户中心错误:20001-29999*/
26 | USER_NOT_LOGGED_IN(20001, "用户未登录"),
27 | USER_LOGIN_ERROR(20002, "账号不存在或密码错误"),
28 | USER_ACCOUNT_FORBIDDEN(20003, "账号已被禁用"),
29 | USER_NOT_EXIST(20004, "用户不存在"),
30 | USER_HAS_EXISTED(20005, "用户已存在"),
31 | USER_COLLECTION_EXISTED(20006, "用户收藏已存在"),
32 | USER_COLLECTION_SAVE_ERROR(20007, "用户收藏更新失败"),
33 | USER_COLLECTION_DEL_ERROR(20008, "用户收藏删除失败"),
34 | USER_COLLECTION_LOOK_ERROR(20008, "用户收藏查询失败"),
35 |
36 | /* 业务错误:30001-39999 */
37 | //SPECIFIED_QUESTIONED_USER_NOT_EXIST(30001, "某业务出现问题"),
38 |
39 | /* 系统错误:40001-49999 */
40 | SYSTEM_INNER_ERROR(40001, "系统繁忙,请稍后重试"),
41 |
42 | /* 数据错误:50001-599999 */
43 | RESULE_DATA_NONE(50001, "数据未找到"),
44 | DATA_IS_WRONG(50002, "数据有误"),
45 | DATA_ALREADY_EXISTED(50003, "数据已存在"),
46 |
47 | /* 接口错误:60001-69999 */
48 | INTERFACE_INNER_INVOKE_ERROR(60001, "内部系统接口调用异常"),
49 | INTERFACE_OUTTER_INVOKE_ERROR(60002, "外部系统接口调用异常"),
50 | INTERFACE_FORBID_VISIT(60003, "该接口禁止访问"),
51 | INTERFACE_ADDRESS_INVALID(60004, "接口地址无效"),
52 | INTERFACE_REQUEST_TIMEOUT(60005, "接口请求超时"),
53 | INTERFACE_EXCEED_LOAD(60006, "接口负载过高"),
54 |
55 | /* 权限错误:70001-79999 */
56 | PERMISSION_NO_ACCESS(70001, "无访问权限");
57 |
58 |
59 | private Integer code;
60 |
61 | private String message;
62 |
63 | ResultCode(Integer code, String message) {
64 | this.code = code;
65 | this.message = message;
66 | }
67 |
68 | public Integer code() {
69 | return this.code;
70 | }
71 |
72 | public String message() {
73 | return this.message;
74 | }
75 |
76 | public static String getMessage(String name) {
77 | for (ResultCode item : ResultCode.values()) {
78 | if (item.name().equals(name)) {
79 | return item.message;
80 | }
81 | }
82 | return name;
83 | }
84 |
85 | public static Integer getCode(String name) {
86 | for (ResultCode item : ResultCode.values()) {
87 | if (item.name().equals(name)) {
88 | return item.code;
89 | }
90 | }
91 | return null;
92 | }
93 |
94 | @Override
95 | public String toString() {
96 | return this.name();
97 | }
98 |
99 | //校验重复的code值
100 | public static void main(String[] args) {
101 | ResultCode[] ApiResultCodes = ResultCode.values();
102 | List codeList = new ArrayList();
103 | for (ResultCode ApiResultCode : ApiResultCodes) {
104 | if (codeList.contains(ApiResultCode.code)) {
105 | System.out.println(ApiResultCode.code);
106 | } else {
107 | codeList.add(ApiResultCode.code());
108 | }
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/exception/APIException.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.exception;
2 |
3 | public class APIException extends RuntimeException {
4 | private int code;
5 |
6 | public APIException(String message) {
7 | super(message);
8 | }
9 |
10 | public APIException(int code, String message) {
11 | super(message);
12 | this.code = code;
13 | }
14 |
15 |
16 | public APIException(Throwable cause) {
17 | super(cause);
18 | }
19 |
20 | public APIException(String message, Throwable cause) {
21 | super(message, cause);
22 | }
23 |
24 | @Override
25 | public String getMessage() {
26 | if (this.code != 0) {
27 | return this.code + " : " + super.getMessage();
28 | }
29 | return super.getMessage();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/result/HttpResult.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.result;
2 |
3 | public class HttpResult {
4 | private int code;
5 | private String message;
6 | private int errorCode;
7 | private String errorMessage;
8 | private String order_id;
9 | private Boolean result;
10 |
11 | public int getErrorCode() {
12 | return errorCode;
13 | }
14 |
15 | public void setErrorCode(int errorCode) {
16 | this.errorCode = errorCode;
17 | }
18 |
19 | public String getErrorMessage() {
20 | return errorMessage;
21 | }
22 |
23 | public void setErrorMessage(String errorMessage) {
24 | this.errorMessage = errorMessage;
25 | }
26 |
27 | public int getCode() {
28 | return code;
29 | }
30 |
31 | public void setCode(int code) {
32 | this.code = code;
33 | }
34 |
35 | public String getMessage() {
36 | return message;
37 | }
38 |
39 | public void setMessage(String message) {
40 | this.message = message;
41 | }
42 |
43 | public String getOrder_id() {
44 | return order_id;
45 | }
46 |
47 | public void setOrder_id(String order_id) {
48 | this.order_id = order_id;
49 | }
50 |
51 | public Boolean getResult() {
52 | return result;
53 | }
54 |
55 | public void setResult(Boolean result) {
56 | this.result = result;
57 | }
58 |
59 | @Override
60 | public String toString() {
61 | return "\t\tResponse Body:{" +
62 | "code=" + code +
63 | ", message='" + message + '\'' +
64 | ", errorCode=" + errorCode +
65 | ", errorMessage='" + errorMessage + '\'' +
66 | ", order_id='" + order_id + '\'' +
67 | ", result=" + result +
68 | '}';
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/service/base/BaseService.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.service.base;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 |
5 | public interface BaseService {
6 |
7 | //获取指定交易详情
8 | JSONObject getTransaction(String currency, String txid);
9 |
10 | //获取UTXO(类BTC)指定地址交易列表
11 | JSONObject getUTXOTransactionList(String currency, String address, String page, String size);
12 |
13 | //获取ACCOUNT(类ETH/TRX)指定地址交易列表
14 | JSONObject getACCOUNTTransactionList(String currency, String address, String page, String size);
15 |
16 | //获取UTXO(类BTC)指定地址余额
17 | JSONObject getUTXOAddressBalance(String currency, String address);
18 |
19 | //获取ACCOUNT(类ETH/TRX)指定地址余额
20 | JSONObject getACCOUNTAddressBalance(String currency, String address);
21 |
22 | //T获取ACCOUNT(ETH,ETC,NAS,NEO)指定地址信息
23 | JSONObject getACCOUNTAddressInfo(String currency, String address);
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/service/base/Impl/BaseAPI.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.service.base.Impl;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 | import retrofit2.Call;
5 | import retrofit2.http.GET;
6 | import retrofit2.http.Path;
7 |
8 | public interface BaseAPI {
9 |
10 | @GET("/tx/{currency}/{txid}")
11 | Call getTransaction(@Path("currency") String currency, @Path("txid") String txid);
12 |
13 | @GET("/address/{currency}/{address}/{page}/{size}")
14 | Call getTransactionList(@Path("currency") String currency, @Path("address") String address,
15 | @Path("page") String page, @Path("size") String size);
16 |
17 | @GET("/{currency}/address/normal/{address}/{page}/{size}")
18 | Call getACCOUNTTransactionList(@Path("currency") String currency, @Path("address") String address,
19 | @Path("page") String page, @Path("size") String size);
20 |
21 | @GET("/address/{currency}/{address}/1/1")
22 | Call getAddressBalance(@Path("currency") String currency, @Path("address") String address);
23 |
24 | @GET("/addr/b/{currency}/{address}")
25 | Call getACCOUNTAddressBalance(@Path("currency") String currency, @Path("address") String address);
26 |
27 | @GET("/{currency}/address/{address}")
28 | Call getACCOUNTAddressInfo(@Path("currency") String currency, @Path("address") String address);
29 | }
30 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/service/base/Impl/BaseServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.service.base.Impl;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 | import com.tokenview.api.client.APIClient;
5 | import com.tokenview.api.config.APIConfiguration;
6 | import com.tokenview.api.service.base.BaseService;
7 |
8 | public class BaseServiceImpl implements BaseService {
9 |
10 | private APIClient client;
11 | private BaseAPI api;
12 |
13 | public BaseServiceImpl(APIConfiguration config) {
14 | this.client = new APIClient(config);
15 | this.api = client.createService(BaseAPI.class);
16 | }
17 |
18 | @Override
19 | public JSONObject getTransaction(String currency, String txid){
20 | return this.client.executeSync(this.api.getTransaction(currency,txid));
21 | }
22 |
23 | @Override
24 | public JSONObject getUTXOTransactionList(String currency,String address,String page,String size){
25 | return this.client.executeSync(this.api.getTransactionList(currency,address,page,size));
26 | }
27 |
28 | @Override
29 | public JSONObject getACCOUNTTransactionList(String currency,String address,String page,String size){
30 | return this.client.executeSync(this.api.getACCOUNTTransactionList(currency,address,page,size));
31 | }
32 |
33 | @Override
34 | public JSONObject getUTXOAddressBalance(String currency,String address){
35 | return this.client.executeSync(this.api.getAddressBalance(currency,address));
36 | }
37 |
38 | @Override
39 | public JSONObject getACCOUNTAddressBalance(String currency,String address){
40 | return this.client.executeSync(this.api.getACCOUNTAddressBalance(currency,address));
41 | }
42 |
43 | @Override
44 | public JSONObject getACCOUNTAddressInfo(String currency,String address){
45 | return this.client.executeSync(this.api.getACCOUNTAddressInfo(currency,address));
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/service/wallet/WalletService.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.service.wallet;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 |
5 | public interface WalletService {
6 |
7 | //发送ETH/BTC交易到对应区块链
8 | JSONObject sendRawTransaction(String currency, JSONObject jo);
9 |
10 | //获取ACCOUNT(类ETH/TRX)指定地址信息
11 | JSONObject getACCOUNTAddressNonce(String currency, JSONObject jo);
12 |
13 | //获取TRX签名前内容
14 | JSONObject getTRXCreateTransaction(JSONObject jo);
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/service/wallet/impl/WalletAPI.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.service.wallet.impl;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 | import retrofit2.Call;
5 | import retrofit2.http.Body;
6 | import retrofit2.http.POST;
7 | import retrofit2.http.Path;
8 |
9 | public interface WalletAPI {
10 |
11 | @POST("/onchainwallet/{currency}")
12 | Call sendRawTransaction(@Path("currency") String currency, @Body JSONObject jsonObject);
13 |
14 | @POST("/onchainwallet/{currency}")
15 | Call getACCOUNTAddressNonce(@Path("currency") String currency, @Body JSONObject jsonObject);
16 |
17 | @POST("/onchainwallet/trx")
18 | Call getTRXCreateTransaction(@Body JSONObject jsonObject);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/api-java-sdk/src/main/java/com/tokenview/api/service/wallet/impl/WalletServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.service.wallet.impl;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 | import com.tokenview.api.client.APIClient;
5 | import com.tokenview.api.config.APIConfiguration;
6 | import com.tokenview.api.service.wallet.WalletService;
7 |
8 | public class WalletServiceImpl implements WalletService {
9 |
10 | private APIClient client;
11 | private WalletAPI api;
12 |
13 | public WalletServiceImpl(APIConfiguration config) {
14 | this.client = new APIClient(config);
15 | this.api = client.createService(WalletAPI.class);
16 | }
17 |
18 | @Override
19 | public JSONObject sendRawTransaction(String currency,JSONObject jsonObject){
20 | return this.client.executeSync(this.api.sendRawTransaction(currency,jsonObject));
21 | }
22 |
23 | @Override
24 | public JSONObject getACCOUNTAddressNonce(String currency,JSONObject jsonObject){
25 | return this.client.executeSync(this.api.getACCOUNTAddressNonce(currency,jsonObject));
26 | }
27 |
28 | @Override
29 | public JSONObject getTRXCreateTransaction(JSONObject jsonObject){
30 | return this.client.executeSync(this.api.getTRXCreateTransaction(jsonObject));
31 | }
32 |
33 |
34 |
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/api-java-sdk/src/test/java/com/tokenview/api/test/base/BaseAPITest.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.test.base;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 | import com.tokenview.api.service.base.BaseService;
5 | import com.tokenview.api.service.base.Impl.BaseServiceImpl;
6 | import org.junit.Before;
7 | import org.junit.Test;
8 |
9 | /**
10 | * TokenView API Test
11 | *
12 | * @author Moilk
13 | * @version 1.0.0
14 | * @date 2021/1/20 11:13
15 | */
16 | public class BaseAPITest extends BaseConfig{
17 |
18 | private BaseService baseService;
19 |
20 | @Before
21 | public void before() {
22 | config = config();
23 | baseService = new BaseServiceImpl(config);
24 | }
25 |
26 | /**
27 | * 查看交易详情,支持类BTC,类ETH,TRX等tokenview支持的所有币的交易查询
28 | * GET /tx/{currency}/{txid}
29 | */
30 | @Test
31 | public void testGetTransaction(){
32 | JSONObject result = baseService.getTransaction("btc","6680c65d3b1f4ab61b7096441a257de51f8bab48d0dca2f76080891ad9b0796a");
33 | toResultString("GetTransaction", result);
34 | }
35 |
36 | /**
37 | * 查看UTXO(类BTC)指定地址余额
38 | * GET /address/{currency}/{address}/{page}/{size}
39 | */
40 | @Test
41 | public void testGetUTXOAddressBalance(){
42 | JSONObject result = baseService.getUTXOAddressBalance("btc","1AqSbAsXh3zxE8Z61afpU65u4pxB9BBRcz");
43 | toResultString("GetUTXOAddressBalance", result);
44 | }
45 |
46 | /**
47 | * 查看UTXO(类BTC)指定地址交易列表
48 | * GET /address/{currency}/{address}/{page}/{size}
49 | */
50 | @Test
51 | public void testGetUTXOTransactionList(){
52 | JSONObject result = baseService.getUTXOTransactionList("btc","1LEHMmGUAzjvMFCoaoUsY46avHzCN3pUdQ","1","50");
53 | toResultString("GetUTXOTransactionList", result);
54 | }
55 |
56 | /**
57 | * 查看ACCOUNT(类ETH/TRX)指定地址余额
58 | * GET /address/{currency}/{address}/{page}/{size}
59 | */
60 | @Test
61 | public void testGetACCOUNTAddressBalance(){
62 | JSONObject result = baseService.getACCOUNTAddressBalance("eth","0xda9cacf6c13450bea275c33e83503fb705d27bbb");
63 | toResultString("GetACCOUNTAddressBalance", result);
64 | }
65 |
66 | /**
67 | * 查看获取ACCOUNT(类ETH/TRX)指定地址交易列表
68 | * GET /{currency}/address/normal/{address}/{page}/{size}
69 | */
70 | @Test
71 | public void testGetACCOUNTTransactionList(){
72 | JSONObject result = baseService.getACCOUNTTransactionList("eth","0x58b6a8a3302369daec383334672404ee733ab239","1","50");
73 | toResultString("GetACCOUNTTransactionList", result);
74 | }
75 |
76 | /**
77 | * 查看ACCOUNT(ETH,ETC,NAS,NEO)指定地址详细信息
78 | * GET /{currency}/address/{address}
79 | */
80 | @Test
81 | public void getACCOUNTAddressInfo(){
82 | JSONObject result = baseService.getACCOUNTAddressInfo("eth","0xda9cacf6c13450bea275c33e83503fb705d27bbb");
83 | toResultString("GetACCOUNTAddressInfo", result);
84 | }
85 |
86 | /**
87 | * 获取账户类型(类eth)地址信息(nonce),目前支持ETH,ETC,NAS,NEO,其他币暂时不支持
88 | *
89 | */
90 | @Test
91 | public void getACCOUNTAddressNonce(){
92 | String nonce = baseService.getACCOUNTAddressInfo("eth","0xda9cacf6c13450bea275c33e83503fb705d27bbb")
93 | .getJSONObject("data")
94 | .getString("nonce");
95 | toResultString("GetACCOUNTAddressNonce", nonce);
96 | }
97 |
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/api-java-sdk/src/test/java/com/tokenview/api/test/base/BaseConfig.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.test.base;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.tokenview.api.config.APIConfiguration;
5 | import com.tokenview.api.enums.I18nEnum;
6 | import lombok.extern.slf4j.Slf4j;
7 |
8 | @Slf4j
9 | public class BaseConfig {
10 | public APIConfiguration config;
11 |
12 | public APIConfiguration config() {
13 | APIConfiguration config = new APIConfiguration();
14 |
15 | config.setEndpoint("http://www.tokenview.com:8088/");
16 | config.setApiKey("ab2ac254-b5b3-4b13-bdea-e5d9a12319d7");
17 |
18 | config.setPrint(true);
19 | config.setI18n(I18nEnum.ENGLISH);
20 |
21 | return config;
22 | }
23 |
24 | public void toResultString(String flag, Object object) {
25 | StringBuilder stringBuilder = new StringBuilder();
26 | stringBuilder.append(flag).append(":\n").append(JSON.toJSONString(object));
27 | System.out.println(stringBuilder);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/api-java-sdk/src/test/java/com/tokenview/api/test/services/ServicesAPITest.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.test.services;
2 |
3 | /**
4 | * TokenView API Test
5 | *
6 | * @author Moilk
7 | * @version 1.0.0
8 | * @date 2021/1/20 11:44
9 | */
10 | public class ServicesAPITest extends ServicesConfig {
11 | }
12 |
--------------------------------------------------------------------------------
/api-java-sdk/src/test/java/com/tokenview/api/test/services/ServicesConfig.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.test.services;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.tokenview.api.config.APIConfiguration;
5 | import com.tokenview.api.enums.I18nEnum;
6 |
7 | public class ServicesConfig {
8 |
9 |
10 | public APIConfiguration config;
11 |
12 | public APIConfiguration config() {
13 | APIConfiguration config = new APIConfiguration();
14 | // apiKey,api注册成功后页面上有
15 | //config.setEndpoint("https://wallet.tokenview.com/");
16 | config.setEndpoint("http://www.tokenview.com:8088/");
17 | config.setApiKey("ab2ac254-b5b3-4b13-bdea-e5d9a12319d7");
18 |
19 | config.setPrint(true);
20 | config.setI18n(I18nEnum.ENGLISH);
21 |
22 | return config;
23 | }
24 |
25 | public void toResultString(String flag, Object object) {
26 | StringBuilder stringBuilder = new StringBuilder();
27 | stringBuilder.append(flag).append(":\n").append(JSON.toJSONString(object));
28 | System.out.println(stringBuilder);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/api-java-sdk/src/test/java/com/tokenview/api/test/wallet/WalletAPITest.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.test.wallet;
2 |
3 | import com.alibaba.fastjson.JSONArray;
4 | import com.alibaba.fastjson.JSONObject;
5 | import com.tokenview.api.service.wallet.WalletService;
6 | import com.tokenview.api.service.wallet.impl.WalletServiceImpl;
7 | import com.tokenview.sign.btc.BTCSign;
8 | import com.tokenview.sign.eth.ETHSign;
9 | import com.tokenview.utils.BTCWalletUtil;
10 | import com.tokenview.utils.HttpUtil;
11 | import org.junit.Before;
12 | import org.junit.Test;
13 |
14 | import java.util.ArrayList;
15 | import java.util.Arrays;
16 | import java.util.List;
17 |
18 | /**
19 | * TokenView API Test
20 | *
21 | * @author Moilk
22 | * @version 1.0.0
23 | * @date 2021/1/20 16:09
24 | */
25 | public class WalletAPITest extends WalletConfig {
26 |
27 | private WalletService walletservice;
28 |
29 | @Before
30 | public void before() {
31 | config = config();
32 | walletservice = new WalletServiceImpl(config);
33 | }
34 | /**由助记词得到eckey+wif格式私钥+hex格式私钥,适用于类BTC币和类ETH币,详细见打印信息,请注意以下两点
35 | * 类BTC币请使用BTC_MAIN_PATH
36 | * 类ETH币请使用ETH_MAIN_PATH
37 | * 使用对的chainpath才能和目前市场主流钱包生成地址相同,否则不同!!!!
38 | * @Param List
39 | */
40 | @Test
41 | public void getEckey(){
42 | List stringList = new ArrayList();
43 | stringList.add("gym");
44 | stringList.add("please");
45 | stringList.add("sauce");
46 | stringList.add("elephant");
47 | stringList.add("trap");
48 | stringList.add("bag");
49 | stringList.add("logic");
50 | stringList.add("okay");
51 | stringList.add("impulse");
52 | stringList.add("slogan");
53 | stringList.add("goose");
54 | stringList.add("birth");
55 | BTCWalletUtil.loadWalletByMnemonic("btc",stringList,"bc1q44elpv05mkdkp5qyd8fajcq2lrczpsats7zjgr","mywallet");
56 | BTCWalletUtil.loadWalletByMnemonic("eth",stringList,"bc1q44elpv05mkdkp5qyd8fajcq2lrczpsats7zjgr","mywallet");
57 | }
58 |
59 | /**
60 | * 创建账户类型(类eth)地址
61 | * @Param privateKey
62 | */
63 | @Test
64 | public void createACCOUNTAddress(){
65 | toResultString("CreateACCOUNTAddress", new ETHSign().getAddress("b71a7616b42110d8345ddc6826ec42c2f1ce24d5f4d8efeb616168d5c1ef4a1f"));
66 | }
67 |
68 | /**
69 | * 创建UTXO(类BTC)地址
70 | * @Param privateKey
71 | */
72 | @Test
73 | public void createUTXOAddress(){
74 | toResultString("CreateUTXOAddress",new BTCSign().getAddress("ab4ff104eddcc43430e0afe9487f21e1033fdc4eca9448065593d49fbc5e6b53"));
75 | }
76 |
77 |
78 | /**
79 | * 使用私钥对账户类型(类eth)地址发交易进行签名,nonce调用BaseAPI获取,gasPrice和gasLimit可使用下面固定值约 $2/笔
80 | * @Param privateKey
81 | * @Param toAddress
82 | * @Param nonce
83 | * @Param gasPrice
84 | * @Param gasLimit
85 | * @Param amount
86 | */
87 | @Test
88 | public void SignEthTransaction(){
89 | toResultString("SignEthTransaction", new ETHSign().signETHTransaction(
90 | "0xb71a7616b42110d8345ddc6826ec42c2f1ce24d5f4d8efeb616168d5c1ef4a1f",
91 | "0x9Ae75431335d2e70f8DB0b35F6C179a43756f78e",
92 | "1",
93 | 78500000000L,
94 | 21000L,
95 | 100000000L));
96 | }
97 |
98 | /**
99 | * 使用私钥对UTXO类型(类BTC)地址发交易进行签名,包含获取unspent并组装交易过程,暂不支持隔离见证bech32地址
100 | * @Param txid
101 | * @Param inputAddress(可若干个)
102 | * @Param toAddress(可若干个)
103 | * @Param toAmount(可若干个)
104 | * @Param changeAddress
105 | * @Param privateKeyWif(privateKeyHex也可只要能生成Eckey,本次测试用wif格式)
106 | */
107 | @Test
108 | public void SignBTCTransaction(){
109 | //unspent所在txid和所在地址
110 | String txid = "6680c65d3b1f4ab61b7096441a257de51f8bab48d0dca2f76080891ad9b0796a";
111 | String inputAddress="1LEHMmGUAzjvMFCoaoUsY46avHzCN3pUdQ";
112 | String toAdddress = "3Kjn9rsoQPrHQXGCJjJuuqZe46JNAseN1t";
113 | long toAmount = 10000;
114 | String changeAddress="1LEHMmGUAzjvMFCoaoUsY46avHzCN3pUdQ";
115 | String privateKeyWIF = "L2xigpefbyesCnzR5hJDFxKPD4A2qSuNHiz4utWnqEovhownw8U2";
116 |
117 | List addrList = new ArrayList<>();
118 | addrList.add(inputAddress);
119 | //可自行设置多个输出地址和金额,找零地址和金额
120 | JSONArray unspents =new HttpUtil().getUnspent(txid,addrList);
121 | long inputAmount =unspents
122 | .stream()
123 | .mapToLong(o->JSONObject.parseObject(o.toString()).getLong("value"))
124 | .sum();
125 |
126 | JSONArray outputs = new JSONArray();
127 | JSONObject outputTo = new JSONObject();
128 | outputTo.put("address",toAdddress);
129 | outputTo.put("amount",toAmount);
130 | outputs.add(outputTo);
131 | long outputToAmount = outputs
132 | .stream()
133 | .mapToLong(o -> JSONObject.parseObject(o.toString()).getLong("amount"))
134 | .sum();
135 | long outputChangeAmount = inputAmount - outputToAmount;
136 | //input金额不足输出和找零返回不签名
137 | if (outputChangeAmount<=0){
138 | return;
139 | }
140 | JSONObject outputChange = new JSONObject();
141 | outputChange.put("address",changeAddress);
142 | outputChange.put("amount",outputChangeAmount);
143 |
144 | outputs.add(outputChange);
145 |
146 | //找零金额小于等于手续费返回不签名
147 | long fee = (unspents.size() + outputs.size() * 2) * 148 - 10;
148 | if (outputChangeAmount <= fee) {
149 | return;
150 | }
151 | toResultString("SignBTCTransaction",new BTCSign().signBTCTransaction(privateKeyWIF,unspents,outputs));
152 | }
153 |
154 |
155 | /**
156 | * 广播类btc/eth/etc交易上链,对应不同method,注意替换
157 | * POST /onchainwallet/{currency}
158 | * @Param method
159 | * @Param signature
160 | * @Param currency
161 | */
162 | @Test
163 | public void testSendETHRawTransaction() {
164 |
165 | JSONObject jo =new JSONObject();
166 | jo.put("jsonrpc","2.0");
167 | jo.put("id","viewtoken");
168 | jo.put("method","eth_sendRawTransaction");
169 | jo.put("params", Arrays.asList("0xf86801851246f6f100825208949ae75431335d2e70f8db0b35f6c179a43756f78e8405f5e100801ca058b2130954d3b84918db5c0fc309dcc942b8656d88964a5f981a4a954bbb1221a0788b6b75afaea28d2e9178a6cea3d432983c10db1c778a1dcb6af009f5457701"));
170 | JSONObject onchainwallet = walletservice.sendRawTransaction("eth",jo);
171 | toResultString("SendRawTransaction", onchainwallet);
172 | }
173 | @Test
174 | public void testSendBTCRawTransaction(){
175 | JSONObject jo =new JSONObject();
176 | jo.put("jsonrpc","2.0");
177 | jo.put("id","viewtoken");
178 | jo.put("method","sendrawtransaction");
179 | jo.put("params", Arrays.asList("01000000016a79b0d91a898060f7a2dcd048ab8b1fe57d251a4496701bb64a1f3b5dc68066010000006b483045022100f5c22019fdd167dfe16988cabbe31a4eeda609abfd8369612813cd510cadca5102201270c8dca6a6b7826162d7f5b00c7a479ad32505a55e958301473bdcab72079f8121033efaa795ed22b1531127a3fd5b6e72031f6a7f4370fb67367768054ef011def0ffffffff02102700000000000017a914c64907144796b4177d6b5809c388c437385db4bb879ab00000000000001976a914d2ed73cd81bb2d516411c47a8ddb02ae5f2e7d0188ac00000000"));
180 | JSONObject onchainwallet = walletservice.sendRawTransaction("btc",jo);
181 | toResultString("SendRawTransaction", onchainwallet);
182 | }
183 |
184 |
185 |
186 |
187 | }
188 |
--------------------------------------------------------------------------------
/api-java-sdk/src/test/java/com/tokenview/api/test/wallet/WalletConfig.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.api.test.wallet;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.tokenview.api.config.APIConfiguration;
5 | import com.tokenview.api.enums.I18nEnum;
6 |
7 | public class WalletConfig {
8 |
9 | public APIConfiguration config;
10 |
11 | public APIConfiguration config() {
12 | APIConfiguration config = new APIConfiguration();
13 | // apiKey,api注册成功后页面上有
14 | config.setEndpoint("https://wallet.tokenview.com/");
15 | config.setApiKey("ab2ac254-b5b3-4b13-bdea-e5d9a12319d7");
16 |
17 | config.setPrint(true);
18 | config.setI18n(I18nEnum.ENGLISH);
19 |
20 | return config;
21 | }
22 |
23 | public void toResultString(String flag, Object object) {
24 | StringBuilder stringBuilder = new StringBuilder();
25 | stringBuilder.append(flag).append(":\n").append(JSON.toJSONString(object));
26 | System.out.println(stringBuilder);
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.tokenview
8 | api-demo
9 | pom
10 | 1.0.0
11 |
12 | sign-java-sdk
13 | api-java-sdk
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/sign-java-sdk/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | api-demo
7 | com.tokenview
8 | 1.0.0
9 |
10 | 4.0.0
11 |
12 | com.tokenview
13 | sign-java-sdk
14 | 1.0.0
15 |
16 |
17 |
18 | cash.bitcoinj
19 | bitcoinj-tools
20 | 0.14.5.2
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | org.web3j
29 | core
30 | 3.0.1
31 |
32 |
33 | jnr-ffi
34 | com.github.jnr
35 |
36 |
37 | okio
38 | com.squareup.okio
39 |
40 |
41 | bcprov-jdk15on
42 | org.bouncycastle
43 |
44 |
45 | slf4j-api
46 | org.slf4j
47 |
48 |
49 | okhttp
50 | com.squareup.okhttp3
51 |
52 |
53 | jackson-databind
54 | com.fasterxml.jackson.core
55 |
56 |
57 |
58 |
59 | org.web3j
60 | crypto
61 | 4.2.0
62 |
63 |
64 | org.slf4j
65 | slf4j-log4j12
66 | 1.8.0-beta2
67 |
68 |
69 | org.springframework
70 | spring-context
71 | 5.1.5.RELEASE
72 |
73 |
74 | com.squareup.retrofit2
75 | converter-scalars
76 | 2.3.0
77 |
78 |
79 | com.squareup.retrofit2
80 | converter-gson
81 | 2.3.0
82 |
83 |
84 | com.squareup.retrofit2
85 | adapter-rxjava
86 | 2.3.0
87 |
88 |
89 | org.apache.commons
90 | commons-lang3
91 | 3.7
92 |
93 |
94 | ch.qos.logback
95 | logback-classic
96 | 1.2.3
97 |
98 |
99 | com.google.guava
100 | guava
101 | 27.1-jre
102 |
103 |
104 | commons-codec
105 | commons-codec
106 | 1.12
107 |
108 |
109 | org.apache.commons
110 | commons-compress
111 | 1.18
112 |
113 |
114 | org.projectlombok
115 | lombok
116 | 1.18.4
117 |
118 |
119 | com.fasterxml.jackson.core
120 | jackson-databind
121 | 2.9.5
122 |
123 |
124 | commons-beanutils
125 | commons-beanutils
126 | 1.9.3
127 |
128 |
129 | commons-collections
130 | commons-collections
131 | 3.2.1
132 |
133 |
134 | commons-logging
135 | commons-logging
136 | 1.1.1
137 |
138 |
139 | net.sf.ezmorph
140 | ezmorph
141 | 1.0.6
142 |
143 |
144 | com.alibaba
145 | fastjson
146 | 1.2.12
147 |
148 |
149 | net.sf.json-lib
150 | json-lib
151 | 2.2.3
152 | jdk15
153 |
154 |
155 | org.springframework
156 | spring-web
157 | 5.0.9.RELEASE
158 | test
159 |
160 |
161 | jstl
162 | jstl
163 | 1.2
164 | test
165 |
166 |
167 | junit
168 | junit
169 | 4.12
170 | test
171 |
172 |
173 | com.madgag.spongycastle
174 | prov
175 | 1.58.0.0
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 | org.apache.httpcomponents
184 | httpclient
185 | 4.5.8
186 |
187 |
188 | org.bitcoincashj
189 | bitcoincashj-core
190 | 1.1.0-SNAPSHOT
191 |
192 |
193 |
194 | io.neow3j
195 | core
196 | 3.7.1
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 | org.apache.maven.plugins
205 | maven-compiler-plugin
206 |
207 | 1.8
208 | 1.8
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
--------------------------------------------------------------------------------
/sign-java-sdk/sign-java-sdk.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/main/java/com/tokenview/account/AddressUtil.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.account;
2 |
3 | import com.tokenview.bean.WalletBean;
4 | import com.tokenview.enums.Coin;
5 | import com.tokenview.params.DashParams;
6 | import com.tokenview.params.DogeParams;
7 | import com.tokenview.params.LitecoinParams;
8 | import com.tokenview.utils.ECKeyUtil;
9 | import org.bitcoinj.core.ECKey;
10 | import org.bitcoinj.core.NetworkParameters;
11 | import org.bitcoinj.params.MainNetParams;
12 | import org.bitcoinj.wallet.UnreadableWalletException;
13 | import org.web3j.crypto.ECKeyPair;
14 | import org.web3j.crypto.Keys;
15 | import org.web3j.utils.Numeric;
16 |
17 | public class AddressUtil {
18 |
19 | public static WalletBean generateAddress(String mnemonic, Coin coin) throws UnreadableWalletException {
20 | ECKeyPair keyPair = ECKeyUtil.generateEcKey(mnemonic, coin);
21 | ECKey ecKey = ECKey.fromPrivate(keyPair.getPrivateKey());
22 | WalletBean wallet=new WalletBean();
23 | wallet.setCoin_type(coin.getCoin());
24 | NetworkParameters parameters=null;
25 | switch (coin){
26 | case BTC:
27 | case BCH:
28 | case BSV:
29 | parameters= MainNetParams.get();
30 | wallet.setAddress(ecKey.toAddress(parameters).toBase58());
31 | wallet.setPrivateKey(ecKey.getPrivateKeyAsWiF(parameters));
32 | break;
33 | case LTC:
34 | parameters= LitecoinParams.get();
35 | wallet.setAddress(ecKey.toAddress(parameters).toBase58());
36 | wallet.setPrivateKey(ecKey.getPrivateKeyAsWiF(parameters));
37 | break;
38 | case DOGE:
39 | parameters= DogeParams.get();
40 | wallet.setAddress(ecKey.toAddress(parameters).toBase58());
41 | wallet.setPrivateKey(ecKey.getPrivateKeyAsWiF(parameters));
42 | break;
43 | case DASH:
44 | parameters= DashParams.get();
45 | wallet.setAddress(ecKey.toAddress(parameters).toBase58());
46 | wallet.setPrivateKey(ecKey.getPrivateKeyAsWiF(parameters));
47 | break;
48 | case ETH:
49 | case HT:
50 | case ETC:
51 | case PI:
52 | case WAN:
53 | case EM:
54 | String address = Keys.getAddress(keyPair);
55 | if(coin== Coin.EM){
56 | address="EM"+address;
57 | }else{
58 | address="0x"+address;
59 | }
60 | wallet.setAddress(address);
61 | String privateKey = Numeric.toHexStringNoPrefixZeroPadded(keyPair.getPrivateKey(), Keys.PRIVATE_KEY_LENGTH_IN_HEX);
62 | wallet.setPrivateKey(privateKey);
63 | break;
64 | case NEO:
65 | io.neow3j.crypto.ECKeyPair ecKeyPair= io.neow3j.crypto.ECKeyPair.create(keyPair.getPrivateKey());
66 | wallet.setAddress(ecKeyPair.getAddress());
67 | wallet.setPrivateKey(ecKeyPair.exportAsWIF());
68 | break;
69 | default:
70 | break;
71 | }
72 | wallet.setMnemonic(mnemonic);
73 | return wallet;
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/main/java/com/tokenview/bean/WalletBean.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.bean;
2 |
3 | public class WalletBean {
4 | private String coin_type;
5 | private String mnemonic;
6 | private String address;
7 | private String keystore;
8 | private String privateKey;
9 |
10 | public String getCoin_type() {
11 | return coin_type;
12 | }
13 |
14 | public void setCoin_type(String coin_type) {
15 | this.coin_type = coin_type;
16 | }
17 |
18 | public String getMnemonic() {
19 | return mnemonic;
20 | }
21 |
22 | public void setMnemonic(String mnemonic) {
23 | this.mnemonic = mnemonic;
24 | }
25 |
26 | public String getAddress() {
27 | return address;
28 | }
29 |
30 | public void setAddress(String address) {
31 | this.address = address;
32 | }
33 |
34 | public String getKeystore() {
35 | return keystore;
36 | }
37 |
38 | public void setKeystore(String keystore) {
39 | this.keystore = keystore;
40 | }
41 |
42 | public String getPrivateKey() {
43 | return privateKey;
44 | }
45 |
46 | public void setPrivateKey(String privateKey) {
47 | this.privateKey = privateKey;
48 | }
49 |
50 |
51 | @Override
52 | public String toString() {
53 | return "WalletBean{" +
54 | "coin_type='" + coin_type + '\'' +
55 | ", mnemonic='" + mnemonic + '\'' +
56 | ", address='" + address + '\'' +
57 | ", keystore='" + keystore + '\'' +
58 | ", privateKey='" + privateKey + '\'' +
59 | '}';
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/main/java/com/tokenview/enums/Coin.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.enums;
2 |
3 | public enum Coin {
4 | BTC("BTC","m/44'/0'/0'/0/0"),
5 | BCH("BCH","m/44'/145'/0'/0/0"),
6 | BSV("BSV","m/44'/145'/0'/0/0"),
7 |
8 | LTC("LTC","m/44'/2'/0'/0/0"),
9 | DOGE("Doge","m/44'/3'/0'/0/0"),
10 | DASH("Dash","m/44'/5'/0'/0/0"),
11 |
12 | NEO("NEO","m/44'/888'/0'/0/0"),
13 |
14 | EM("EM","m/44'/60'/0'/0/0"),
15 |
16 | ETH("ETH","m/44'/60'/0'/0/0"),
17 | ETC("ETC","m/44'/61'/0'/0/0"),
18 | HT("HT","m/44'/60'/0'/0/0"),
19 | PI("PI","m/44'/60'/0'/0/0"),
20 | WAN("WAN","m/44'/5718350'/0'/0/0");
21 |
22 | private String coin;
23 | private String path;
24 | Coin(String coin,String path){this.coin=coin;this.path=path;}
25 |
26 | public String getCoin(){return coin;}
27 |
28 | public String getPath(){return path;}
29 | }
30 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/main/java/com/tokenview/enums/Version.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.enums;
2 |
3 | public enum Version {
4 | BTC(1);
5 |
6 | private Integer version;
7 |
8 | Version(Integer version) {
9 | this.version = version;
10 | }
11 |
12 | public Integer getVersion() {
13 | return version;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/main/java/com/tokenview/params/DashParams.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.params;
2 |
3 | import org.bitcoinj.params.AbstractBitcoinNetParams;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | /**
8 | * @author zhaoda
9 | * @date 2019/10/17.
10 | * GitHub:
11 | * email:
12 | * description:
13 | */
14 | public class DashParams extends AbstractBitcoinNetParams {
15 | private static final Logger log = LoggerFactory.getLogger(DashParams.class);
16 |
17 | public static final int MAINNET_MAJORITY_WINDOW = 1000;
18 | public static final int MAINNET_MAJORITY_REJECT_BLOCK_OUTDATED = 950;
19 | public static final int MAINNET_MAJORITY_ENFORCE_BLOCK_UPGRADE = 750;
20 |
21 | public static final int MAINNET_MAJORITY_DIP0001_WINDOW = 4032;
22 | public static final int MAINNET_MAJORITY_DIP0001_THRESHOLD = 3226;
23 |
24 | public static final int p2shHeaderDash = 16;
25 |
26 | public static final int AddressHeaderDash = 76;
27 |
28 | public DashParams() {
29 | super();
30 | p2shHeader = p2shHeaderDash;
31 | dumpedPrivateKeyHeader = 204;
32 | addressHeader = AddressHeaderDash;
33 | acceptableAddressCodes = new int[] { addressHeader, p2shHeader};
34 | id = ID_MAINNET;
35 | interval = INTERVAL;
36 |
37 | }
38 |
39 | private static DashParams instance;
40 | public static synchronized DashParams get() {
41 | if (instance == null) {
42 | instance = new DashParams();
43 | }
44 | return instance;
45 | }
46 |
47 | @Override
48 | public String getPaymentProtocolId() {
49 | return PAYMENT_PROTOCOL_ID_MAINNET;
50 | }
51 |
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/main/java/com/tokenview/params/DogeParams.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.params;
2 |
3 | import org.bitcoinj.params.AbstractBitcoinNetParams;
4 |
5 | /**
6 | * @author zhaoda
7 | * @date 2019/10/18.
8 | * GitHub:
9 | * email:
10 | * description:
11 | */
12 | public class DogeParams extends AbstractBitcoinNetParams {
13 | public static final String ID_DOGE_MAINNET = "org.dogecoin.production";
14 | public DogeParams() {
15 | super();
16 | p2shHeader = 22;
17 | dumpedPrivateKeyHeader = 158;
18 | addressHeader = 30;
19 | acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
20 | id = ID_DOGE_MAINNET;
21 | // interval = INTERVAL;
22 | // bip32HeaderPub = 0x02facafd; //The 4 byte header that serializes in base58 to "dgub".
23 | // bip32HeaderPriv = 0x02fac398; //The 4 byte header that serializes in base58 to "dgpv".
24 | }
25 |
26 | private static DogeParams instance;
27 | public static synchronized DogeParams get() {
28 | if (instance == null) {
29 | instance = new DogeParams();
30 | }
31 | return instance;
32 | }
33 |
34 | @Override
35 | public String getPaymentProtocolId() {
36 | return "main";
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/main/java/com/tokenview/params/LitecoinParams.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.params;
2 |
3 | import org.bitcoinj.params.AbstractBitcoinNetParams;
4 |
5 | public class LitecoinParams extends AbstractBitcoinNetParams {
6 |
7 | /*
8 | 48 --> L.. addresses
9 | 50 --> the new M.. addresses
10 | Blockcypher doesn't support M address at the moment
11 | */
12 |
13 | public LitecoinParams() {
14 | super();
15 | p2shHeader = 5;
16 | dumpedPrivateKeyHeader = 176;
17 | addressHeader = 48;
18 | acceptableAddressCodes = new int[]{addressHeader, p2shHeader, 50};
19 | id = "org.litecoin.production";
20 | }
21 |
22 | private static LitecoinParams instance;
23 | public static synchronized LitecoinParams get() {
24 | if (instance == null) {
25 | instance = new LitecoinParams();
26 | }
27 | return instance;
28 | }
29 |
30 | @Override
31 | public String getPaymentProtocolId() {
32 | return "main";
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/main/java/com/tokenview/sign/btc/BTCSign.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.sign.btc;
2 |
3 | import com.alibaba.fastjson.JSONArray;
4 | import com.alibaba.fastjson.JSONObject;
5 | import com.tokenview.enums.Version;
6 | import org.bitcoinj.core.*;
7 | import org.bitcoinj.params.MainNetParams;
8 | import org.bitcoinj.script.Script;
9 | import org.spongycastle.util.encoders.Hex;
10 |
11 | public class BTCSign {
12 | public String signBTCTransaction(String privateKey,JSONArray unspents,JSONArray outputs) {
13 | String hexString = "";
14 | try {
15 | NetworkParameters params = MainNetParams.get();
16 | DumpedPrivateKey priKey = DumpedPrivateKey.fromBase58(params,privateKey);
17 | ECKey ecKey = priKey.getKey();
18 | System.out.println(ecKey.getPrivateKeyAsHex());
19 | System.out.println(ecKey.getPublicKeyAsHex());
20 | System.out.println(new String(ecKey.getPubKeyHash()));
21 | //构建交易体
22 | Transaction transaction = new Transaction(params);
23 | //交易的版本 默认的BTC,LTC ,DOGE,DASH 版本号是1, BCH BSV 版本号是:2;
24 | transaction.setVersion(Version.BTC.getVersion());
25 | long fee = (unspents.size() + outputs.size() * 2) * 148 - 10;
26 | //添加转出到的地址列表和数量
27 | for(int i = 0;i inputParameters = new ArrayList<>();
26 | inputParameters.add(new Address(toAddress));
27 | inputParameters.add(new Uint256(0L));//转出数量
28 | List> outputParameters = new ArrayList<>();
29 | //调用的合约的方法 transfer,参数,输出 等等
30 | Function function = new Function("transfer", inputParameters, outputParameters);
31 | //将合约数据转换成16进制字符串
32 | String dataStr = FunctionEncoder.encode(function);
33 | RawTransaction tx = RawTransaction.createTransaction(
34 | BigInteger.valueOf(Long.parseLong(nonce)),
35 | BigInteger.valueOf(gasPrice),//gasPrice
36 | BigInteger.valueOf(gasLimit),//gasLimit
37 | toAddress,
38 | BigInteger.valueOf(amount),//转账的"数量"
39 | "");
40 | //创建钥匙对
41 | ECKeyPair ecKeyPair = ECKeyPair.create(Numeric.toBigInt(privateKey));
42 | Credentials credentials = Credentials.create(ecKeyPair);
43 | System.out.println(credentials.getAddress());
44 | //签名交易
45 | byte[] signed = TransactionEncoder.signMessage(tx, credentials);
46 | //将签名的交易转换成16进制字符串,并用于广播交易
47 | signedStr = Numeric.toHexString(signed);
48 | } catch (Exception e) {
49 |
50 | }
51 | return signedStr;
52 | }
53 |
54 | public String getAddress(String privateKey){
55 | ECKeyPair ecKeyPair = ECKeyPair.create(Numeric.toBigInt(privateKey));
56 | Credentials credentials = Credentials.create(ecKeyPair);
57 | return credentials.getAddress();
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/main/java/com/tokenview/utils/BTCWalletUtil.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.utils;
2 |
3 |
4 | import com.tokenview.bean.WalletBean;
5 | import org.apache.commons.lang3.StringUtils;
6 | import org.bitcoinj.core.*;
7 | import org.bitcoinj.crypto.ChildNumber;
8 | import org.bitcoinj.crypto.DeterministicKey;
9 | import org.bitcoinj.crypto.HDKeyDerivation;
10 | import org.bitcoinj.params.MainNetParams;
11 | import org.bitcoinj.wallet.DeterministicSeed;
12 | import org.bouncycastle.util.encoders.Hex;
13 | import org.web3j.crypto.ECKeyPair;
14 | import org.web3j.utils.Numeric;
15 |
16 | import java.util.List;
17 |
18 |
19 | public class BTCWalletUtil {
20 |
21 | // public static boolean BTC_TEST_NET = SharedPreferencesUtil.getInstance().getBoolean(NumberConstant.IS_TEST_NET,false);
22 | public static String BTC_TEST_PATH = "m/44'/1'/0'/0/0";
23 | public static String BTC_MAIN_PATH = "m/44'/0'/0'/0/0";
24 | public static String BTC_SEGWIT_MAIN_PATH = "m/49'/0'/0'/0/0";
25 | public static String BTC_SEGWIT_TEST_PATH = "m/49'/1'/0'/0/0";
26 | public static String ETH_MAIN_PATH="m/44'/60'/0'/0/0";
27 |
28 | /**
29 | * 通过助记词生成私钥
30 | */
31 | public static WalletBean loadWalletByDeterministicSeed(DeterministicSeed ds, String pwd, String walletName) {
32 | String path;
33 | NetworkParameters params;
34 | path = BTC_MAIN_PATH;
35 | params = MainNetParams.get();
36 | ECKeyPair keyPair = getEcKeyPairByDeterministicSeed(path, ds);
37 | // loadWalletBIP49ByDeterministicSeed(ds);
38 | if (keyPair == null) return null;
39 | // 获取Base64编码的64位的私钥
40 | // String privateKey = Numeric.toHexStringNoPrefixZeroPadded(keyPair.getPrivateKey(), Keys.PRIVATE_KEY_LENGTH_IN_HEX);
41 | // //第二种方式生成
42 | // ECKeyPair ecKeyPair = generateEcKeyPair(ds);
43 | ECKey ecKey = ECKey.fromPrivate(keyPair.getPrivateKey());
44 | //获取Base58编码压缩后的私钥
45 | String privateKeyAsWiF = ecKey.getPrivateKeyAsWiF(params);
46 | String address = ecKey.toAddress(params).toString();
47 | WalletBean bean = new WalletBean();
48 | bean.setCoin_type("BTC");
49 | bean.setMnemonic(getMnemonic(ds));
50 | bean.setAddress(address);
51 | bean.setKeystore("");
52 | bean.setPrivateKey(privateKeyAsWiF);
53 | return bean;
54 | }
55 |
56 |
57 | /**
58 | * 通过助记词生成 BIP49 协议的隔离见证地址
59 | */
60 | public static WalletBean loadWalletBIP49ByDeterministicSeed(List mnemonic) {
61 | DeterministicSeed ds = getDeterministicSeed(mnemonic);
62 | String path=BTC_SEGWIT_MAIN_PATH;
63 | NetworkParameters params= MainNetParams.get();
64 | String[] pathArray = path.split("/");
65 | byte[] seedBytes = ds.getSeedBytes();
66 | DeterministicKey dkKey = HDKeyDerivation.createMasterPrivateKey(seedBytes);
67 | for (int i = 1; i < pathArray.length; i++) {
68 | ChildNumber childNumber;
69 | if (pathArray[i].endsWith("'")) {
70 | int number = Integer.parseInt(pathArray[i].substring(0, pathArray[i].length() - 1));
71 | childNumber = new ChildNumber(number, true);
72 | } else {
73 | int number = Integer.parseInt(pathArray[i]);
74 | childNumber = new ChildNumber(number, false);
75 | }
76 | dkKey = HDKeyDerivation.deriveChildKey(dkKey, childNumber);
77 | }
78 | //获取P2SH地址的过程
79 | String publicKey=Numeric.toHexStringNoPrefix(dkKey.getPubKeyHash());
80 | String redeemScript = String.format("0x0014%s", publicKey);
81 | byte[] bytes = Numeric.hexStringToByteArray(redeemScript);
82 | byte[] bytes1 = Utils.sha256hash160(bytes);
83 | String p2shAddress = Address.fromP2SHHash(params, bytes1).toBase58();
84 | System.out.println("p2sh account == "+p2shAddress);
85 | WalletBean bean=new WalletBean();
86 | bean.setCoin_type("BTC");
87 | bean.setAddress(p2shAddress);
88 | bean.setMnemonic(getMnemonic(ds));
89 | bean.setPrivateKey(dkKey.getPrivateKeyAsWiF(params));
90 | return bean;
91 | }
92 |
93 |
94 |
95 | /**
96 | * 通过助记词生成hex私钥,WIF私钥,也可生成地址
97 | */
98 | public static WalletBean loadWalletByDeterministicSeedTest(DeterministicSeed ds, String pwd, String walletName) {
99 | String path;
100 | NetworkParameters params;
101 | path = BTC_MAIN_PATH;
102 | params = MainNetParams.get();
103 | //params = TestNet3Params.get();
104 | ECKeyPair keyPair = getEcKeyPairByDeterministicSeed(path, ds);
105 | if (keyPair == null) return null;
106 | // 获取Base64编码的64位的私钥
107 | // String privateKey = Numeric.toHexStringNoPrefixZeroPadded(keyPair.getPrivateKey(), Keys.PRIVATE_KEY_LENGTH_IN_HEX);
108 | // 第二种方式生成
109 | // ECKeyPair ecKeyPair = generateEcKeyPair(ds);
110 | ECKey ecKey = ECKey.fromPrivate(keyPair.getPrivateKey());
111 | String hexPrivateKey = ecKey.getPrivateKeyAsHex();
112 | ECKey ecKey1 = ECKey.fromPrivate(Hex.decode(hexPrivateKey));
113 | Address address1 = ecKey1.toAddress(params);
114 | System.out.println("bitcoin account == "+address1);
115 | //获取Base58编码压缩后的私钥
116 | System.out.println("privateKeyHex == "+ecKey.getPrivateKeyAsHex());
117 | //ecKey.
118 | String privateKeyAsWiF = ecKey.getPrivateKeyAsWiF(params);
119 | System.out.println("privateKeyWif =="+privateKeyAsWiF);
120 | String address = ecKey.toAddress(params).toString();
121 | System.out.println("bitcoin account == "+address);
122 | WalletBean bean = new WalletBean();
123 | bean.setCoin_type("BTC");
124 | bean.setMnemonic(getMnemonic(ds));
125 | bean.setAddress(address);
126 | bean.setKeystore("");
127 | bean.setPrivateKey(privateKeyAsWiF);
128 | return bean;
129 | }
130 |
131 | /**
132 | * 通过私钥导入BTC钱包 (base58)
133 | * */
134 | public static WalletBean loadWalletByPrivateKey(String privateKey) {
135 | NetworkParameters params;
136 | params = MainNetParams.get();
137 | try {
138 | DumpedPrivateKey priKey = DumpedPrivateKey.fromBase58(params, privateKey);
139 | ECKey ecKey = priKey.getKey();
140 | String address = ecKey.toAddress(params).toString();
141 | WalletBean bean = new WalletBean();
142 | bean.setCoin_type("BTC");
143 | bean.setMnemonic(" ");
144 | bean.setAddress(address);
145 | bean.setKeystore("");
146 | bean.setPrivateKey(privateKey);
147 | return bean;
148 | }catch (Exception e){
149 | e.printStackTrace();
150 | }
151 | return null;
152 | }
153 |
154 |
155 | /**
156 | * 通过助记词生成私钥
157 | */
158 | public static WalletBean loadWalletByMnemonic(String currency,List list, String pwd, String walletName) {
159 | String path;
160 | NetworkParameters params;
161 | path = "";
162 | if (currency.equalsIgnoreCase("btc")) {
163 | path = BTC_MAIN_PATH;
164 | }
165 | if (currency.equalsIgnoreCase("eth")) {
166 | path = ETH_MAIN_PATH;
167 | }
168 | params = MainNetParams.get();
169 | DeterministicSeed ds = getDeterministicSeed(list);
170 | ECKeyPair keyPair = getEcKeyPairByDeterministicSeed(path, ds);
171 | // //获取16编码的64位的私钥
172 | // String privateKey = Numeric.toHexStringNoPrefixZeroPadded(keyPair.getPrivateKey(), Keys.PRIVATE_KEY_LENGTH_IN_HEX);
173 | // ECKeyPair ecKeyPair = generateEcKeyPair(ds);
174 | ECKey ecKey = ECKey.fromPrivate(keyPair.getPrivateKey());
175 | //获取Base58编码压缩后的私钥
176 | String privateKeyAsWiF = ecKey.getPrivateKeyAsWiF(params);
177 | String address = ecKey.toAddress(params).toString();
178 | System.out.println("privateKey ===="+ecKey.getPrivateKeyAsHex());
179 | System.out.println("account ====="+address);
180 | WalletBean bean = new WalletBean();
181 | bean.setCoin_type("BTC");
182 | bean.setMnemonic(getMnemonic(ds));
183 | bean.setAddress(address);
184 | bean.setKeystore("");
185 | bean.setPrivateKey(privateKeyAsWiF);
186 | return bean;
187 | }
188 |
189 |
190 | /**
191 | * 通过路径和种子获取私钥对
192 | */
193 | public static ECKeyPair getEcKeyPairByDeterministicSeed(String path, DeterministicSeed ds) {
194 | String[] pathArray = path.split("/");
195 | byte[] seedBytes = ds.getSeedBytes();
196 | if (seedBytes == null)
197 | return null;
198 | DeterministicKey dkKey = HDKeyDerivation.createMasterPrivateKey(seedBytes);
199 | for (int i = 1; i < pathArray.length; i++) {
200 | ChildNumber childNumber;
201 | if (pathArray[i].endsWith("'")) {
202 | int number = Integer.parseInt(pathArray[i].substring(0, pathArray[i].length() - 1));
203 | childNumber = new ChildNumber(number, true);
204 | } else {
205 | int number = Integer.parseInt(pathArray[i]);
206 | childNumber = new ChildNumber(number, false);
207 | }
208 | dkKey = HDKeyDerivation.deriveChildKey(dkKey, childNumber);
209 | }
210 | ECKeyPair keyPair = ECKeyPair.create(dkKey.getPrivKeyBytes());
211 | return keyPair;
212 | }
213 |
214 |
215 |
216 | /**
217 | * 通过路径和种子获取私钥对
218 | */
219 | public static DeterministicKey getPrivateBySeed(String path, DeterministicSeed ds) {
220 | String[] pathArray = path.split("/");
221 | byte[] seedBytes = ds.getSeedBytes();
222 | if (seedBytes == null)
223 | return null;
224 | DeterministicKey dkKey = HDKeyDerivation.createMasterPrivateKey(seedBytes);
225 | for (int i = 1; i < pathArray.length; i++) {
226 | ChildNumber childNumber;
227 | if (pathArray[i].endsWith("'")) {
228 | int number = Integer.parseInt(pathArray[i].substring(0, pathArray[i].length() - 1));
229 | childNumber = new ChildNumber(number, true);
230 | } else {
231 | int number = Integer.parseInt(pathArray[i]);
232 | childNumber = new ChildNumber(number, false);
233 | }
234 | dkKey = HDKeyDerivation.deriveChildKey(dkKey, childNumber);
235 | }
236 | // ECKeyPair keyPair = ECKeyPair.create(dkKey.getPrivKeyBytes());
237 | return dkKey;
238 | }
239 |
240 |
241 |
242 | /**
243 | * 通过助记词生成种子
244 | * */
245 | public static DeterministicSeed getDeterministicSeed(List list) {
246 | try {
247 | long creationTimeSeconds = System.currentTimeMillis() / 1000;
248 | return new DeterministicSeed(list, null, "", creationTimeSeconds);
249 | }catch (Exception e){}
250 | return null;
251 | }
252 |
253 | /**
254 | * 通过助记词生成Hex私钥
255 | * */
256 | public static String getPrivateKeyHex(List list) {
257 | try {
258 | long creationTimeSeconds = System.currentTimeMillis() / 1000;
259 | DeterministicSeed seed = new DeterministicSeed(list, null, "", creationTimeSeconds);
260 | ECKeyPair keyPair = getEcKeyPairByDeterministicSeed("m/44'/1'/0'/0/0", seed);
261 | if (keyPair == null) return null;
262 | ECKey ecKey = ECKey.fromPrivate(keyPair.getPrivateKey());
263 | String hexPrivateKey = ecKey.getPrivateKeyAsHex();
264 | return hexPrivateKey;
265 | }catch (Exception e){}
266 | return null;
267 | }
268 |
269 | /**
270 | * 通过种子生成助记词字符串
271 | */
272 | public static String getMnemonic(DeterministicSeed ds) {
273 | StringBuilder sb = new StringBuilder();
274 | List mnemonicList = ds.getMnemonicCode();
275 | for (int i = 0; mnemonicList != null && i < mnemonicList.size(); i++) {
276 | sb.append(mnemonicList.get(i) + " ");
277 | }
278 | return sb.toString().trim();
279 | }
280 |
281 | /**判断地址的有效性*/
282 | public static boolean isBTCValidAddress(String input) {
283 | if (StringUtils.isEmpty(input))return false;
284 | try {
285 | NetworkParameters networkParameters = null;
286 | networkParameters = MainNetParams.get();
287 | Address address = Address.fromBase58(networkParameters, input);
288 | if (address != null)
289 | return true;
290 | else
291 | return false;
292 | } catch (Exception e) {
293 | return false;
294 | }
295 | }
296 |
297 |
298 | }
299 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/main/java/com/tokenview/utils/ECKeyUtil.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.utils;
2 |
3 | import com.tokenview.enums.Coin;
4 | import org.bitcoinj.crypto.ChildNumber;
5 | import org.bitcoinj.crypto.DeterministicKey;
6 | import org.bitcoinj.crypto.HDKeyDerivation;
7 | import org.bitcoinj.wallet.DeterministicSeed;
8 | import org.bitcoinj.wallet.UnreadableWalletException;
9 | import org.web3j.crypto.ECKeyPair;
10 |
11 | public class ECKeyUtil {
12 |
13 |
14 | public static ECKeyPair generateEcKey(String mnemonic, Coin coin) throws UnreadableWalletException {
15 | DeterministicSeed seed = getDeterministicSeed(mnemonic);
16 | return getEcKeyPairByDeterministicSeed(coin.getPath(),seed);
17 | }
18 |
19 | private static DeterministicSeed getDeterministicSeed(String mnemonic) throws UnreadableWalletException {
20 | long creationTimeSeconds = System.currentTimeMillis() / 1000;
21 | return new DeterministicSeed(mnemonic, null, "", creationTimeSeconds);
22 | }
23 |
24 | private static ECKeyPair getEcKeyPairByDeterministicSeed(String path, DeterministicSeed ds) {
25 | String [] pathArray = path.split("/");
26 | byte[] seedBytes = ds.getSeedBytes();
27 | if (seedBytes == null)
28 | return null;
29 | DeterministicKey dkKey = HDKeyDerivation.createMasterPrivateKey(seedBytes);
30 | ChildNumber childNumber;
31 | for (int i = 1; i < pathArray.length; i++) {
32 | if (pathArray[i].endsWith("'")) {
33 | int number = Integer.parseInt(pathArray[i].substring(0, pathArray[i].length() - 1));
34 | childNumber = new ChildNumber(number, true);
35 | } else {
36 | int number = Integer.parseInt(pathArray[i]);
37 | childNumber = new ChildNumber(number, false);
38 | }
39 | dkKey = HDKeyDerivation.deriveChildKey(dkKey, childNumber);
40 | }
41 | return ECKeyPair.create(dkKey.getPrivKeyBytes());
42 | }
43 |
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/main/java/com/tokenview/utils/HexUtil.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.utils;
2 |
3 | /**
4 | * @author zhaoda
5 | * @date 2020/6/1.
6 | * GitHub:
7 | * email:
8 | * description:
9 | */
10 | public class HexUtil {
11 | private static final char[] digits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
12 | public static final byte[] emptybytes = new byte[0];
13 |
14 | public HexUtil() {
15 | }
16 |
17 | public static String byte2HexStr(byte b) {
18 | char[] buf = new char[]{'\u0000', digits[b & 15]};
19 | b = (byte)(b >>> 4);
20 | buf[0] = digits[b & 15];
21 | return new String(buf);
22 | }
23 |
24 | public static String bytes2HexStr(byte[] bytes) {
25 | if (bytes != null && bytes.length != 0) {
26 | char[] buf = new char[2 * bytes.length];
27 |
28 | for(int i = 0; i < bytes.length; ++i) {
29 | byte b = bytes[i];
30 | buf[2 * i + 1] = digits[b & 15];
31 | b = (byte)(b >>> 4);
32 | buf[2 * i + 0] = digits[b & 15];
33 | }
34 |
35 | return new String(buf);
36 | } else {
37 | return null;
38 | }
39 | }
40 |
41 | public static byte hexStr2Byte(String str) {
42 | return str != null && str.length() == 1 ? char2Byte(str.charAt(0)) : 0;
43 | }
44 |
45 | public static byte char2Byte(char ch) {
46 | if (ch >= '0' && ch <= '9') {
47 | return (byte)(ch - 48);
48 | } else if (ch >= 'a' && ch <= 'f') {
49 | return (byte)(ch - 97 + 10);
50 | } else {
51 | return ch >= 'A' && ch <= 'F' ? (byte)(ch - 65 + 10) : 0;
52 | }
53 | }
54 |
55 | public static byte[] hexStr2Bytes(String str) {
56 | if (str != null && !str.equals("")) {
57 | byte[] bytes = new byte[str.length() / 2];
58 |
59 | for(int i = 0; i < bytes.length; ++i) {
60 | char high = str.charAt(i * 2);
61 | char low = str.charAt(i * 2 + 1);
62 | bytes[i] = (byte)(char2Byte(high) * 16 + char2Byte(low));
63 | }
64 |
65 | return bytes;
66 | } else {
67 | return emptybytes;
68 | }
69 | }
70 |
71 | public static void main(String[] args) {
72 | try {
73 | byte[] bytes = "Hello WebSocket World?".getBytes("gbk");
74 | System.out.println(bytes2HexStr(bytes));
75 | } catch (Exception var3) {
76 | var3.printStackTrace();
77 | }
78 |
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/main/java/com/tokenview/utils/HttpClientUtils.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.utils;
2 |
3 | import com.alibaba.fastjson.JSONArray;
4 | import com.alibaba.fastjson.JSONObject;
5 | import com.google.common.collect.Lists;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.apache.commons.lang3.StringUtils;
8 | import org.apache.http.HttpEntity;
9 | import org.apache.http.NameValuePair;
10 | import org.apache.http.client.config.RequestConfig;
11 | import org.apache.http.client.entity.UrlEncodedFormEntity;
12 | import org.apache.http.client.methods.*;
13 | import org.apache.http.client.utils.URIBuilder;
14 | import org.apache.http.config.Registry;
15 | import org.apache.http.config.RegistryBuilder;
16 | import org.apache.http.conn.socket.ConnectionSocketFactory;
17 | import org.apache.http.conn.socket.PlainConnectionSocketFactory;
18 | import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
19 | import org.apache.http.entity.ContentType;
20 | import org.apache.http.entity.StringEntity;
21 | import org.apache.http.impl.client.CloseableHttpClient;
22 | import org.apache.http.impl.client.HttpClients;
23 | import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
24 | import org.apache.http.message.BasicNameValuePair;
25 | import org.apache.http.util.EntityUtils;
26 | import org.slf4j.Logger;
27 | import org.slf4j.LoggerFactory;
28 |
29 | import javax.net.ssl.*;
30 | import java.io.BufferedReader;
31 | import java.io.IOException;
32 | import java.io.InputStream;
33 | import java.io.InputStreamReader;
34 | import java.net.URISyntaxException;
35 | import java.nio.charset.Charset;
36 | import java.security.KeyManagementException;
37 | import java.security.NoSuchAlgorithmException;
38 | import java.security.cert.CertificateException;
39 | import java.util.*;
40 |
41 | @Deprecated
42 | @Slf4j
43 | public final class HttpClientUtils {
44 |
45 | private static final Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
46 |
47 | public static String get(final String url, final Map params, final Map headerMap) {
48 | HttpGet httpGet = null;
49 | try {
50 | URIBuilder ub = new URIBuilder(url);
51 | List pairs = Lists.newArrayList();
52 |
53 | if (params != null && !params.isEmpty()) {
54 | for (Map.Entry entry : params.entrySet()) {
55 | pairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
56 | }
57 |
58 | ub.setParameters(pairs);
59 | }
60 | httpGet = new HttpGet(ub.build());
61 | } catch (URISyntaxException e) {
62 | e.printStackTrace();
63 | }
64 | return execute(httpGet, headerMap);
65 | }
66 |
67 | public static String get(final String url, final Map headerMap) {
68 | return get(url, null, headerMap);
69 | }
70 |
71 | public static JSONObject getReturnObject(final String url, final Map headerMap) {
72 | String str = get(url, null, headerMap);
73 | JSONObject json = null;
74 | try {
75 | json = JSONObject.parseObject(str);
76 | } catch (Exception e) {
77 | log.info("this resquest return not json object" + str);
78 | json = new JSONObject();
79 | }
80 |
81 | return json;
82 | }
83 |
84 | public static JSONArray getReturnArray(final String url, final Map headerMap) {
85 | String str = get(url, null, headerMap);
86 | JSONArray json = null;
87 | try {
88 | json = JSONArray.parseArray(str);
89 | } catch (Exception e) {
90 | log.info("this resquest return not json array" + str);
91 | json = new JSONArray();
92 | }
93 |
94 | return json;
95 | }
96 |
97 | public static String post(final String url, final Map params,
98 | final Map headerMap) {
99 | return post(url, params, headerMap, "utf-8");
100 | }
101 |
102 | public static String post(final String url, final Map params) {
103 | return post(url, params, null, "utf-8");
104 | }
105 |
106 | public static String post(final String url, final Map params, final Map headerMap,
107 | final String charset) {
108 | final HttpPost request = new HttpPost(url);
109 | if (params != null && params.size() > 0) {
110 | List paramList = null;
111 | final Set> entrySet = params.entrySet();
112 | paramList = new ArrayList<>();
113 | for (final Iterator> it = entrySet.iterator(); it.hasNext(); ) {
114 | final Map.Entry entry = it.next();
115 | final String key = entry.getKey();
116 | final Object value = entry.getValue();
117 | if (key != null && value != null) {
118 | final NameValuePair nvp = new BasicNameValuePair(key, value.toString());
119 | paramList.add(nvp);
120 | }
121 | }
122 | try {
123 | if (StringUtils.isEmpty(charset)) {
124 | request.setEntity(new UrlEncodedFormEntity(paramList));
125 | } else {
126 | request.setEntity(new UrlEncodedFormEntity(paramList, Charset.forName(charset)));
127 | }
128 | } catch (final Exception e) {
129 | logger.error("HttpClientUtils post", e);
130 | return null;
131 | }
132 | }
133 | return execute(request, headerMap);
134 | }
135 |
136 | public static String post(final String url, final HttpEntity entity, final Map headerMap) {
137 | final HttpPost request = new HttpPost(url);
138 | request.setEntity(entity);
139 | return execute(request, headerMap);
140 | }
141 |
142 | public static String execute(final HttpRequestBase request, final Map headerMap) {
143 | return execute(null, request, headerMap);
144 | }
145 |
146 | public static String execute(CloseableHttpClient httpclient, final HttpRequestBase request,
147 | final Map headerMap) {
148 | return execute(null, request, headerMap, 30000, 30000);
149 | }
150 |
151 | public static String execute(final HttpRequestBase request,
152 | final Map headerMap, int socketTimeout, int connectTimeout) {
153 | return execute(null, request, headerMap, socketTimeout, connectTimeout);
154 | }
155 |
156 | private static String execute(CloseableHttpClient httpclient, final HttpRequestBase request,
157 | final Map headerMap, int socketTimeout, int connectTimeout) {
158 | final StringBuffer log = new StringBuffer(
159 | "HttpClientUtils execute method:" + request.getMethod() + " url:" + request.getURI());
160 |
161 | boolean isClose = false;
162 | if (httpclient == null) {
163 | httpclient = HttpClients.createDefault();
164 | isClose = true;
165 | }
166 | InputStream resStream = null;
167 | InputStreamReader inputStreamReader = null;
168 | BufferedReader br = null;
169 | String result = "";
170 |
171 | if (headerMap != null && headerMap.size() > 0) {
172 | final Iterator iterator = headerMap.keySet().iterator();
173 | while (iterator.hasNext()) {
174 | final String key = iterator.next();
175 | request.setHeader(key, headerMap.get(key));
176 | }
177 | }
178 |
179 | try {
180 | final RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(
181 | connectTimeout)
182 | .build();
183 | request.setConfig(requestConfig);
184 | final CloseableHttpResponse response = httpclient.execute(request);
185 |
186 | try {
187 |
188 | final HttpEntity entity = response.getEntity();
189 |
190 | if (entity != null) {
191 | resStream = entity.getContent();
192 | try {
193 | inputStreamReader = new InputStreamReader(resStream);
194 | br = new BufferedReader(inputStreamReader);
195 | final StringBuffer resBuffer = new StringBuffer();
196 | String resTemp = "";
197 | while ((resTemp = br.readLine()) != null) {
198 | resBuffer.append(resTemp);
199 | }
200 | result = resBuffer.toString();
201 | } finally {
202 | if (br != null) {
203 | br.close();
204 | }
205 | if (inputStreamReader != null) {
206 | inputStreamReader.close();
207 | }
208 | if (resStream != null) {
209 | resStream.close();
210 | }
211 | }
212 | }
213 | } finally {
214 | response.close();
215 | }
216 | } catch (final Exception e) {
217 | request.abort();
218 | logger.error(log.toString(), e);
219 | } finally {
220 | request.abort();
221 | try {
222 | if (isClose) {
223 | httpclient.close();
224 | }
225 | } catch (final IOException e) {
226 | logger.error(log.toString(), e);
227 | }
228 | }
229 | return result;
230 | }
231 |
232 | public static JSONObject post(String url, JSONObject params, Map header) {
233 | try {
234 |
235 | //创建post方式请求对象
236 | HttpPost httpPost = new HttpPost(url);
237 | if (header != null) {
238 | for (Map.Entry entry : header.entrySet()) {
239 | httpPost.setHeader(entry.getKey(), entry.getValue());
240 | }
241 | } else {
242 | //设置header信息
243 | httpPost.setHeader("Content-type", "application/json;charset=utf-8");
244 | httpPost.setHeader("Accept", "application/json;charset=utf-8");
245 | }
246 |
247 | //
248 | StringEntity requestEntity = new StringEntity(
249 | params.toJSONString(),
250 | ContentType.APPLICATION_JSON);
251 | httpPost.setEntity(requestEntity);
252 |
253 | log.debug("请求地址:" + url);
254 | log.debug("请求参数:" + params.toJSONString());
255 |
256 | return JSONObject.parseObject(send(httpPost, "UTF-8"));
257 | } catch (Exception e) {
258 | e.printStackTrace();
259 | }
260 |
261 | return null;
262 | }
263 |
264 | public static String httpsGet(String url, Map header) {
265 | try {
266 | //创建post方式请求对象
267 | HttpGet httpGet = new HttpGet(url);
268 |
269 | if (header != null) {
270 | for (Map.Entry entry : header.entrySet()) {
271 | httpGet.setHeader(entry.getKey(), entry.getValue());
272 | }
273 | }
274 |
275 | //设置header信息
276 | httpGet.setHeader("Content-type", "application/json;charset=utf-8");
277 | httpGet.setHeader("Accept", "application/json;charset=utf-8");
278 |
279 | log.debug("请求地址:" + url);
280 |
281 | return send(httpGet, "UTF-8");
282 | } catch (Exception e) {
283 | e.printStackTrace();
284 | }
285 |
286 | return null;
287 | }
288 |
289 | private static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
290 | SSLContext sc = SSLContext.getInstance("TLSv1.2");
291 |
292 | // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
293 | X509TrustManager trustManager = new X509TrustManager() {
294 | @Override
295 | public void checkClientTrusted(
296 | java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
297 | String paramString) throws CertificateException {
298 | }
299 |
300 | @Override
301 | public void checkServerTrusted(
302 | java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
303 | String paramString) throws CertificateException {
304 | }
305 |
306 | @Override
307 | public java.security.cert.X509Certificate[] getAcceptedIssuers() {
308 | return null;
309 | }
310 | };
311 |
312 | sc.init(null, new TrustManager[] {trustManager}, null);
313 | return sc;
314 | }
315 |
316 | public static String send(HttpRequestBase requestBase, String encoding)
317 | throws KeyManagementException, NoSuchAlgorithmException, IOException {
318 | String body = "";
319 | //采用绕过验证的方式处理https请求
320 | SSLContext sslcontext = createIgnoreVerifySSL();
321 |
322 | // 设置协议http和https对应的处理socket链接工厂的对象
323 | Registry socketFactoryRegistry = RegistryBuilder.create()
324 | .register("http", PlainConnectionSocketFactory.INSTANCE)
325 | .register("https", new SSLConnectionSocketFactory(sslcontext))
326 | .build();
327 | PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
328 | HttpClients.custom().setConnectionManager(connManager);
329 |
330 | //创建自定义的httpclient对象
331 | CloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).setSSLHostnameVerifier(
332 | new TrustAnyHostnameVerifier()).build();
333 |
334 | //CloseableHttpClient client = HttpClients.createDefault();
335 |
336 | //执行请求操作,并拿到结果(同步阻塞)
337 | CloseableHttpResponse response = client.execute(requestBase);
338 | //获取结果实体
339 | HttpEntity entity = response.getEntity();
340 | if (entity != null) {
341 | //按指定编码转换结果实体为String类型
342 | body = EntityUtils.toString(entity, encoding);
343 | }
344 | EntityUtils.consume(entity);
345 | //释放链接
346 | response.close();
347 | client.close();
348 | connManager.close();
349 | return body;
350 | }
351 |
352 | private static class TrustAnyHostnameVerifier implements HostnameVerifier {
353 | @Override
354 | public boolean verify(String hostname, SSLSession session) {
355 | return true;
356 | }
357 | }
358 |
359 | public static String put(final String url, final HttpEntity entity, final Map headerMap) {
360 | final HttpPut request = new HttpPut(url);
361 | request.setEntity(entity);
362 | return execute(request, headerMap);
363 | }
364 |
365 | public static String put(final String url, final Map headerMap) {
366 | final HttpPut request = new HttpPut(url);
367 | return execute(request, headerMap);
368 | }
369 |
370 | }
371 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/main/java/com/tokenview/utils/HttpUtil.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.utils;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONArray;
5 | import com.alibaba.fastjson.JSONObject;
6 | import lombok.extern.slf4j.Slf4j;
7 |
8 | import java.util.HashMap;
9 | import java.util.List;
10 |
11 | @Slf4j
12 | public class HttpUtil {
13 |
14 | private String get(String url) {
15 | return HttpClientUtils.get(url, new HashMap<>());
16 | }
17 |
18 | public JSONObject getTransactionDetail(String tx){
19 | StringBuffer url = new StringBuffer("https://chain.api.btc.com/v3/tx/");
20 | url.append(tx);
21 | url.append("?verbose=3");
22 | String result = null;
23 | try {
24 | result = get(url.toString());
25 | } catch (Exception e) {
26 | log.info(e.getMessage(), e);
27 | }
28 | return JSONObject.parseObject(result);
29 | }
30 |
31 | public JSONArray getUnspent(String txid,List addrList){
32 | JSONObject result =new HttpUtil().getTransactionDetail(txid).getJSONObject("data");
33 | long height =result.getLong("block_height");
34 | JSONArray outputsArray = result.getJSONArray("outputs");
35 | JSONArray unspents = new JSONArray();
36 | int index =0;
37 | for (Object o : outputsArray){
38 | Object io = JSONObject.parseObject(o.toString()).get("addresses");
39 | String address = String.valueOf(io).replace("[\"","").replace("\"]","");
40 | if (addrList.contains(address)){
41 | JSONObject txJson = JSONObject.parseObject(o.toString());
42 | txJson.put("txid",txid);
43 | txJson.put("tx_output_n",index);
44 | txJson.put("block_height",height);
45 | unspents.add(txJson);
46 | }
47 | index++;
48 | }
49 | log.info(JSON.toJSONString(unspents));
50 | return unspents;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/test/java/com/tokenview/sign/test/BTCSignTest.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.sign.test;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONArray;
5 | import com.alibaba.fastjson.JSONObject;
6 | import com.tokenview.sign.btc.BTCSign;
7 | import com.tokenview.utils.HttpUtil;
8 | import lombok.extern.slf4j.Slf4j;
9 | import org.junit.Test;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | @Slf4j
15 | public class BTCSignTest {
16 |
17 | @Test
18 | public void testGetUnspent(){
19 | String txid = "13c6235ee5e6403606f1539bc872813ac14a90521da6248ffbf63913a8675573";
20 | List addrList = new ArrayList<>();
21 | addrList.add("1LEHMmGUAzjvMFCoaoUsY46avHzCN3pUdQ");
22 | JSONArray unspents =new HttpUtil().getUnspent(txid,addrList);
23 | log.info(JSON.toJSONString(unspents));
24 | }
25 |
26 |
27 | @Test
28 | public void testBTCSign(){
29 | //unspent所在txid和所在地址
30 | String txid = "6680c65d3b1f4ab61b7096441a257de51f8bab48d0dca2f76080891ad9b0796a";
31 | List addrList = new ArrayList<>();
32 | addrList.add("1LEHMmGUAzjvMFCoaoUsY46avHzCN3pUdQ");
33 | //可自行设置多个输出地址和金额,找零地址和金额
34 | JSONArray unspents =new HttpUtil().getUnspent(txid,addrList);
35 | long inputAmount =unspents
36 | .stream()
37 | .mapToLong(o->JSONObject.parseObject(o.toString()).getLong("value"))
38 | .sum();
39 |
40 | JSONArray outputs = new JSONArray();
41 | JSONObject outputTo = new JSONObject();
42 | outputTo.put("account","16SzvWdCrYsVsMuRp43TfqvGvibBah7s17");
43 | outputTo.put("amount",10000);
44 | outputs.add(outputTo);
45 | long outputToAmount = outputs
46 | .stream()
47 | .mapToLong(o -> JSONObject.parseObject(o.toString()).getLong("amount"))
48 | .sum();
49 | long outputChangeAmount = inputAmount - outputToAmount;
50 | //input金额不足输出和找零返回不签名
51 | if (outputChangeAmount<=0){
52 | return;
53 | }
54 | JSONObject outputChange = new JSONObject();
55 | outputChange.put("account","1LEHMmGUAzjvMFCoaoUsY46avHzCN3pUdQ");
56 | outputChange.put("amount",outputChangeAmount);
57 |
58 | outputs.add(outputChange);
59 |
60 | //找零金额小于等于手续费返回不签名
61 | long fee = (unspents.size() + outputs.size() * 2) * 148 - 10;
62 | if (outputChangeAmount <= fee) {
63 | return;
64 | }
65 |
66 | String signature = new BTCSign().signBTCTransaction("L2xigpefbyesCnzR5hJDFxKPD4A2qSuNHiz4utWnqEovhownw8U2",unspents,outputs);
67 | log.info(signature);
68 | }
69 |
70 | @Test
71 | public void testGetAddress(){
72 | log.info(new BTCSign().getAddress("d71405cd1c95271e4c17569494100856d9e8706e081702ec5ec91a5b20ce1957"));
73 | }
74 |
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/sign-java-sdk/src/test/java/com/tokenview/sign/test/ETHSignTest.java:
--------------------------------------------------------------------------------
1 | package com.tokenview.sign.test;
2 |
3 | import com.tokenview.sign.eth.ETHSign;
4 | import com.tokenview.utils.BTCWalletUtil;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.junit.Test;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | @Slf4j
12 | public class ETHSignTest {
13 |
14 | @Test
15 | public void testGetPrivateKeyFromStrList() {
16 | List stringList = new ArrayList();
17 | stringList.add("gym");
18 | stringList.add("please");
19 | stringList.add("sauce");
20 | stringList.add("elephant");
21 | stringList.add("trap");
22 | stringList.add("bag");
23 | stringList.add("logic");
24 | stringList.add("okay");
25 | stringList.add("impulse");
26 | stringList.add("slogan");
27 | stringList.add("goose");
28 | stringList.add("birth");
29 | BTCWalletUtil.loadWalletByMnemonic("eth",stringList,",","");
30 | }
31 |
32 | @Test
33 | public void testGetAddress() {
34 | String address = new ETHSign().getAddress("b71a7616b42110d8345ddc6826ec42c2f1ce24d5f4d8efeb616168d5c1ef4a1f");
35 | log.info(address);
36 | }
37 |
38 | @Test
39 | public void testETHSign() {
40 |
41 | String sinature = new ETHSign().signETHTransaction(
42 | "0xb71a7616b42110d8345ddc6826ec42c2f1ce24d5f4d8efeb616168d5c1ef4a1f",
43 | "0x9Ae75431335d2e70f8DB0b35F6C179a43756f78e",
44 | "1",
45 | 78500000000L,
46 | 21000L,
47 | 80000000000L);
48 | log.info(sinature);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------