Official Java SDK for Bytom
Révision | 70a619aded1f012558ed66647d78a3a2d26d82ed (tree) |
---|---|
l'heure | 2019-03-26 19:09:16 |
Auteur | shenao78 <shenao.78@163....> |
Commiter | shenao78 |
refactor
@@ -14,8 +14,8 @@ There are various ways to install and use this sdk. We'll provide three ways to | ||
14 | 14 | ```xml |
15 | 15 | <dependency> |
16 | 16 | <groupId>io.bytom</groupId> |
17 | - <artifactId>bytom-sdk</artifactId> | |
18 | - <version>1.0.1</version> | |
17 | + <artifactId>java-sdk</artifactId> | |
18 | + <version>1.0.0</version> | |
19 | 19 | </dependency> |
20 | 20 | ``` |
21 | 21 |
@@ -301,7 +301,7 @@ public class Asset { | ||
301 | 301 | */ |
302 | 302 | public List<Asset> list(Client client) throws BytomException { |
303 | 303 | Type listType = new ParameterizedTypeImpl(List.class, new Class[]{Asset.class}); |
304 | - List<Asset> assetList = client.request("list-assets", null, listType); | |
304 | + List<Asset> assetList = client.request("list-assets", this, listType); | |
305 | 305 | logger.info("list-assets:"); |
306 | 306 | logger.info("size of assetList:"+assetList.size()); |
307 | 307 | logger.info(assetList); |
@@ -11,19 +11,6 @@ import java.lang.reflect.Type; | ||
11 | 11 | import java.util.List; |
12 | 12 | |
13 | 13 | public class UnspentOutput { |
14 | - /** | |
15 | - * The id of the account controlling this output (possibly null if a control program | |
16 | - * is specified). | |
17 | - */ | |
18 | - @SerializedName("account_id") | |
19 | - public String accountId; | |
20 | - | |
21 | - /** | |
22 | - * The alias of the account controlling this output (possibly null if a control | |
23 | - * program is specified). | |
24 | - */ | |
25 | - @SerializedName("account_alias") | |
26 | - public String accountAlias; | |
27 | 14 | |
28 | 15 | /** |
29 | 16 | * The id of the asset being controlled. |
@@ -103,11 +90,64 @@ public class UnspentOutput { | ||
103 | 90 | */ |
104 | 91 | public String id; |
105 | 92 | |
93 | + /** | |
94 | + * The id of the account controlling this output (possibly null if a control program | |
95 | + * is specified). | |
96 | + */ | |
97 | + @SerializedName("account_id") | |
98 | + public String accountId; | |
99 | + | |
100 | + /** | |
101 | + * The alias of the account controlling this output (possibly null if a control | |
102 | + * program is specified). | |
103 | + */ | |
104 | + @SerializedName("account_alias") | |
105 | + public String accountAlias; | |
106 | + | |
107 | + public Boolean unconfirmed; | |
108 | + | |
109 | + @SerializedName("smart_contract") | |
110 | + public Boolean smartContract; | |
111 | + | |
112 | + public Integer from; | |
113 | + | |
114 | + public Integer count; | |
115 | + | |
106 | 116 | public QueryBuilder setId(String id) { |
107 | 117 | this.id = id; |
108 | 118 | return this; |
109 | 119 | } |
110 | 120 | |
121 | + public QueryBuilder setAccountId(String accountId) { | |
122 | + this.accountId = accountId; | |
123 | + return this; | |
124 | + } | |
125 | + | |
126 | + public QueryBuilder setAccountAlias(String accountAlias) { | |
127 | + this.accountAlias = accountAlias; | |
128 | + return this; | |
129 | + } | |
130 | + | |
131 | + public QueryBuilder setSmartContract(boolean smartContract) { | |
132 | + this.smartContract = smartContract; | |
133 | + return this; | |
134 | + } | |
135 | + | |
136 | + public QueryBuilder setUnconfirmed(boolean unconfirmed) { | |
137 | + this.unconfirmed = unconfirmed; | |
138 | + return this; | |
139 | + } | |
140 | + | |
141 | + public QueryBuilder setFrom(Integer from) { | |
142 | + this.from = from; | |
143 | + return this; | |
144 | + } | |
145 | + | |
146 | + public QueryBuilder setCount(Integer count) { | |
147 | + this.count = count; | |
148 | + return this; | |
149 | + } | |
150 | + | |
111 | 151 | /** |
112 | 152 | * call list-unspent-outputs api |
113 | 153 | * |
@@ -1,6 +1,6 @@ | ||
1 | 1 | |
2 | 2 | |
3 | -# tx_signer | |
3 | +# tx-signer | |
4 | 4 | |
5 | 5 | Java implementation of signing transaction offline. |
6 | 6 |
@@ -0,0 +1,242 @@ | ||
1 | +# tx-signer | |
2 | +严格来说,tx-signer并不属于SDK,它是bytomd中构建交易、对交易签名两大模块的java实现版。因此,若想用tx-signer对交易进行离线签名,需要由你在本地保管好自己的私钥。 | |
3 | + | |
4 | +如果你的目的是完全脱离于bytomd全节点,可能需要自己做更多额外的工作。比如,在构建交易时,需要花费若干个utxo(Unspent Transaction Output)作为交易的输入,如果没有全节点则需要自身来维护utxo。当使用tx-signer构建完成一笔交易并签名后,若没有全节点的帮助,也需要自己实现P2P网络协议将交易广播到其他节点。 | |
5 | + | |
6 | +本文不会对以上技术细节进行讨论,而是利用bytomd全节点查询可用的utxo构建交易,对交易进行签名并序列化后,同样使用bytomd提交交易。 | |
7 | + | |
8 | +## 准备工作 | |
9 | + | |
10 | +#### 将Maven依赖引入到你的项目中 | |
11 | +1. 获取SDK源码 | |
12 | + | |
13 | + ``` | |
14 | + git clone https://github.com/Bytom/bytom-java-sdk.git | |
15 | + ``` | |
16 | + | |
17 | +2. 打包成JAR包并安装到本地的Maven仓库 | |
18 | + | |
19 | + ``` | |
20 | + $ mvn clean install -DskipTests | |
21 | + ``` | |
22 | + | |
23 | +3. 在项目的POM文件中添加依赖。其中,第一个依赖是bytomd api的封装,可用于查询可用的utxo以及提交交易;第二个依赖用于构建交易以及对交易进行离线签名。 | |
24 | + ```xml | |
25 | + <dependency> | |
26 | + <groupId>io.bytom</groupId> | |
27 | + <artifactId>java-sdk</artifactId> | |
28 | + <version>1.0.0</version> | |
29 | + </dependency> | |
30 | + | |
31 | + <dependency> | |
32 | + <groupId>io.bytom</groupId> | |
33 | + <artifactId>tx-signer</artifactId> | |
34 | + <version>1.0.0</version> | |
35 | + </dependency> | |
36 | + ``` | |
37 | + | |
38 | +## 构建交易 | |
39 | + | |
40 | +#### 普通交易 | |
41 | +**1.** 查询可用的utxo | |
42 | + | |
43 | +在本文中,以下将全部使用全节点来查询可用的utxo,你也可以构建一套自己的utxo维护方案。 | |
44 | +```java | |
45 | +Client client = Client.generateClient(); | |
46 | +UnspentOutput.QueryBuilder builder = new UnspentOutput.QueryBuilder(); | |
47 | +builder.accountAlias = "bytom"; | |
48 | +List<UnspentOutput> outputs = builder.list(client); | |
49 | +``` | |
50 | +利用SDK只需要四行代码就能查询可用的utxo(SDK具体文档详见[java-sdk documentation](java-sdk/README.md))。在QueryBuilder中可以指定是否为未确认的utxo(默认false),也可以通过from和count来进行分页查询(默认查询所有)。 | |
51 | +假设在当前账户下查询得到这样一个utxo: | |
52 | +```json | |
53 | +{ | |
54 | + "account_alias": "bytom", | |
55 | + "id": "ffdc59d0478277298de4afa458dfa7623c051a46b7a84939fb8227083411b156", | |
56 | + "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", | |
57 | + "asset_alias": "BTM", | |
58 | + "amount": 41250000000, | |
59 | + "account_id": "0G1R52O1G0A02", | |
60 | + "address": "sm1qxls6ajp6fejc0j5kp8jwt2nj3kmsqazfumrkrr", | |
61 | + "control_program_index": 1, | |
62 | + "program": "001437e1aec83a4e6587ca9609e4e5aa728db7007449", | |
63 | + "source_id": "2d3a5d920833778cc7c65d7c96fe5f3c4a1a61aa086ee093f44a0522dd499a34", | |
64 | + "source_pos": 0, | |
65 | + "valid_height": 4767, | |
66 | + "change": false, | |
67 | + "derive_rule": 0 | |
68 | +} | |
69 | + | |
70 | +``` | |
71 | + | |
72 | +**2.** 构建交易 | |
73 | + | |
74 | +现在需要往`0014c832e1579b4f96dc12dcfff39e8fe69a62d3f516`这个control program转100个BTM。代码如下: | |
75 | + | |
76 | +```java | |
77 | +String btmAssetID = "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; | |
78 | +// 下面的字段与utxo中的字段一一对应 | |
79 | +SpendInput input = new SpendInput(); | |
80 | +input.setAssetId(btmAssetID); | |
81 | +input.setAmount(41250000000L); | |
82 | +input.setProgram("001437e1aec83a4e6587ca9609e4e5aa728db7007449"); | |
83 | +input.setSourcePosition(0); | |
84 | +input.setSourceID("2d3a5d920833778cc7c65d7c96fe5f3c4a1a61aa086ee093f44a0522dd499a34"); | |
85 | +input.setChange(false); | |
86 | +input.setControlProgramIndex(1); | |
87 | +// 选择使用BIP32还是BIP44来派生地址,默认BIP44 | |
88 | +input.setBipProtocol(BIPProtocol.BIP44); | |
89 | +// 账户对应的密钥索引 | |
90 | +input.setKeyIndex(1); | |
91 | +// 自身本地保管的私钥,用于对交易进行签名 | |
92 | +input.setRootPrivateKey("4864bae85cf38bfbb347684abdbc01e311a24f99e2c7fe94f3c071d9c83d8a5a349722316972e382c339b79b7e1d83a565c6b3e7cf46847733a47044ae493257"); | |
93 | + | |
94 | +Transaction tx = new Transaction.Builder() | |
95 | + .addInput(input) | |
96 | + // 加入需要转入的output | |
97 | + .addOutput(new Output(btmAssetID, 10000000000L, "0014c832e1579b4f96dc12dcfff39e8fe69a62d3f516")) | |
98 | + // 剩余的BTM用于找零 | |
99 | + .addOutput(new Output(btmAssetID, 31250000000L, "0014bb8a039726df1b649738e9973db14a4b4fd4becf")) | |
100 | + .setTimeRange(0) | |
101 | + .build(); | |
102 | + | |
103 | +String rawTransaction = tx.rawTransaction(); | |
104 | + | |
105 | +``` | |
106 | + | |
107 | +对交易调用build方法后,自动会对交易进行本地的验证和签名操作。注意,在本地只是做简单的字段验证,本地验证通过并不代表交易合法。最后对交易调用rawTransaction方法返回交易序列化后的字符串。 | |
108 | + | |
109 | + | |
110 | +**3. 提交交易** | |
111 | + | |
112 | +本文利用bytomd全节点来提交交易: | |
113 | +```java | |
114 | +HashMap<String, Object> body = new HashMap<>(); | |
115 | +body.put("raw_transaction", "070100010160015e4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adeaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80c480c1240201160014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e6302401cb779288be890a28c5209036da1a27d9fe74a51c38e0a10db4817bcf4fd05f68580239eea7dcabf19f144c77bf13d3674b5139aa51a99ba58118386c190af0e20bcbe020b05e1b7d0825953d92bf47897be08cd7751a37adb95d6a2e5224f55ab02013dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80b095e42001160014a82f02bc37bc5ed87d5f9fca02f8a6a7d89cdd5c000149ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80d293ad03012200200824e931fb806bd77fdcd291aad3bd0a4493443a4120062bd659e64a3e0bac6600"); | |
116 | +Transaction.SubmitResponse response = client.request("submit-transaction", body, Transaction.SubmitResponse.class); | |
117 | +``` | |
118 | +交易提交成功后,response返回交易ID。 | |
119 | + | |
120 | + | |
121 | +#### 发行资产交易 | |
122 | +**1. 查询可用的utxo** | |
123 | + | |
124 | +发行资产时,需要使用BTM作为手续费,因此第一步同样需要查询当前账户下可用的utxo,由于上面已经提到,这里不再赘述。 | |
125 | + | |
126 | +**2. 查询需要发行的资产信息** | |
127 | + | |
128 | +例如,需要发行的资产id为`7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad14` | |
129 | + | |
130 | +```java | |
131 | +Asset.QueryBuilder builder = new Asset.QueryBuilder(); | |
132 | +builder.setId("7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad14"); | |
133 | +List<Asset> assets = builder.list(client); | |
134 | +``` | |
135 | + | |
136 | +假设查询得到的资产信息如下: | |
137 | +```json | |
138 | +{ | |
139 | + "type": "asset", | |
140 | + "xpubs": [ | |
141 | + "5ff7f79f0fd4eb9ccb17191b0a1ac9bed5b4a03320a06d2ff8170dd51f9ad9089c4038ec7280b5eb6745ef3d36284e67f5cf2ed2a0177d462d24abf53c0399ed" | |
142 | + ], | |
143 | + "quorum": 1, | |
144 | + "key_index": 3, | |
145 | + "derive_rule": 0, | |
146 | + "id": "7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad14", | |
147 | + "alias": "棒棒鸡", | |
148 | + "vm_version": 1, | |
149 | + "issue_program": "ae20db11f9dfa39c9e66421c530fe027218edd3d5b1cd98f24c826f4d9c0cd131a475151ad", | |
150 | + "raw_definition_byte": "7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d", | |
151 | + "definition": { | |
152 | + "decimals": 8, | |
153 | + "description": {}, | |
154 | + "name": "", | |
155 | + "symbol": "" | |
156 | + } | |
157 | +} | |
158 | +``` | |
159 | + | |
160 | +**3. 构建交易** | |
161 | + | |
162 | +现在需要发行1000个棒棒鸡资产: | |
163 | + | |
164 | +```java | |
165 | +IssuanceInput issuanceInput = new IssuanceInput(); | |
166 | +issuanceInput.setAssetId("7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad14"); | |
167 | +issuanceInput.setAmount(100000000000L); | |
168 | +// issue program | |
169 | +issuanceInput.setProgram("ae20db11f9dfa39c9e66421c530fe027218edd3d5b1cd98f24c826f4d9c0cd131a475151ad"); | |
170 | +// 可以不指定,不指定时将随机生成一个 | |
171 | +issuanceInput.setNonce("ac9d5a527f5ab00a"); | |
172 | +issuanceInput.setKeyIndex(5); | |
173 | +// raw definition byte | |
174 | +issuanceInput.setRawAssetDefinition("7b0a202022646563696d616c73223a20382c0a2020226465736372697074696f6e223a207b7d2c0a2020226e616d65223a2022222c0a20202273796d626f6c223a2022220a7d"); | |
175 | +// 该资产对应的私钥 | |
176 | +issuanceInput.setRootPrivateKey("4864bae85cf38bfbb347684abdbc01e311a24f99e2c7fe94f3c071d9c83d8a5a349722316972e382c339b79b7e1d83a565c6b3e7cf46847733a47044ae493257"); | |
177 | + | |
178 | +// 创建一个spend input作为手续费,假设当前有一个100BTM的utxo,并且使用1BTM作为手续费,则后续还要创建99BTM的找零地址 | |
179 | +SpendInput feeInput = new SpendInput(btmAssetID, 10000000000L, "0014cb9f2391bafe2bc1159b2c4c8a0f17ba1b4dd94e"); | |
180 | +feeInput.setKeyIndex(1); | |
181 | +feeInput.setChange(true); | |
182 | +feeInput.setSourceID("4b5cb973f5bef4eadde4c89b92ee73312b940e84164da0594149554cc8a2adea"); | |
183 | +feeInput.setSourcePosition(2); | |
184 | +feeInput.setControlProgramIndex(457); | |
185 | +feeInput.setRootPrivateKey("4864bae85cf38bfbb347684abdbc01e311a24f99e2c7fe94f3c071d9c83d8a5a349722316972e382c339b79b7e1d83a565c6b3e7cf46847733a47044ae493257"); | |
186 | + | |
187 | +Transaction tx = new Transaction.Builder() | |
188 | + .addInput(issuanceInput) | |
189 | + .addInput(feeInput) | |
190 | + // 该output用于接收发行的资产 | |
191 | + .addOutput(new Output("7b38dc897329a288ea31031724f5c55bcafec80468a546955023380af2faad14", 100000000000L, "001437e1aec83a4e6587ca9609e4e5aa728db7007449")) | |
192 | + // 找零 | |
193 | + .addOutput(new Output(btmAssetID, 9800000000L, "00148be1104e04734e5edaba5eea2e85793896b77c56")) | |
194 | + .setTimeRange(0) | |
195 | + .build(); | |
196 | +``` | |
197 | + | |
198 | +**4. 提交交易** | |
199 | + | |
200 | +提交交易的方式与普通交易一致。 | |
201 | + | |
202 | + | |
203 | +#### 销毁资产交易 | |
204 | + | |
205 | +销毁资产跟发行资产类似,同样需要BTM作为手续费。 | |
206 | + | |
207 | +**1. 查询可用的utxo** | |
208 | + | |
209 | +查询方式与普通交易一致。 | |
210 | + | |
211 | +**2. 构建交易** | |
212 | + | |
213 | +这里以销毁一个BTM为例,假设查询得到一个100BTM的utxo: | |
214 | + | |
215 | +```java | |
216 | +// 查询得到一个100BTM的utxo作为输入 | |
217 | +SpendInput input = new SpendInput(btmAssetID, 10000000000L, "0014f1dc52048f439ac7fd74f8106a21da78f00de48f"); | |
218 | +input.setRootPrivateKey(rootKey); | |
219 | +input.setChange(true); | |
220 | +input.setKeyIndex(1); | |
221 | +input.setControlProgramIndex(41); | |
222 | +input.setSourceID("0b2cff11d1d056d95237a5f2d06059e5395e86f60e69c1e8201ea624911c0c65"); | |
223 | +input.setSourcePosition(0); | |
224 | + | |
225 | +// 销毁资产时,可添加一段附加的文本 | |
226 | +String arbitrary = "77656c636f6d65efbc8ce6aca2e8bf8ee69da5e588b0e58e9fe5ad90e4b896e7958c"; | |
227 | +// 销毁99个BTM,剩余1个BTM作为手续费 | |
228 | +Output output = Output.newRetireOutput(btmAssetID, 9900000000L, arbitrary); | |
229 | + | |
230 | +Transaction transaction = new Transaction.Builder() | |
231 | + .addInput(input) | |
232 | + .addOutput(output) | |
233 | + .setTimeRange(2000000) | |
234 | + .build(); | |
235 | + | |
236 | +String rawTransaction = transaction.rawTransaction(); | |
237 | + | |
238 | +``` | |
239 | + | |
240 | +**4. 提交交易** | |
241 | + | |
242 | +提交交易的方式与普通交易一致。 |
@@ -32,12 +32,17 @@ public class Output { | ||
32 | 32 | */ |
33 | 33 | private Integer position; |
34 | 34 | |
35 | - public Output(String assetId, Long amount, String controlProgram) { | |
36 | - this.assetId = assetId; | |
35 | + public Output(String assetID, long amount, String controlProgram) { | |
36 | + this.assetId = assetID; | |
37 | 37 | this.amount = amount; |
38 | 38 | this.controlProgram = controlProgram; |
39 | 39 | } |
40 | 40 | |
41 | + public static Output newRetireOutput(String assetID, long amount, String arbitrary) { | |
42 | + String retireProgram = "6a" + Integer.toString(Hex.decode(arbitrary).length,16) + arbitrary; | |
43 | + return new Output(assetID, amount, retireProgram); | |
44 | + } | |
45 | + | |
41 | 46 | public byte[] serializeOutput() throws IOException { |
42 | 47 | ByteArrayOutputStream stream = new ByteArrayOutputStream(); |
43 | 48 |
@@ -1,178 +0,0 @@ | ||
1 | -package io.bytom.offline.exception; | |
2 | - | |
3 | -import com.google.gson.annotations.SerializedName; | |
4 | - | |
5 | -/** | |
6 | - * APIException wraps errors returned by the API. | |
7 | - * Each error contains a brief description in addition to a unique error code.<br> | |
8 | - * The error code can be used by Chain Support to diagnose the exact cause of the error. | |
9 | - * The mapping of error codes to messages is as follows:<br><br> | |
10 | - * | |
11 | - * <h2>General errors</h2> | |
12 | - * CH001 - Request timed out | |
13 | - * CH002 - Not found | |
14 | - * CH003 - Invalid request body | |
15 | - * CH004 - Invalid request header | |
16 | - * CH006 - Not found | |
17 | - * | |
18 | - * <h2>Account/Asset errors</h2> | |
19 | - * CH200 - Quorum must be greater than 1 and less than or equal to the length of xpubs | |
20 | - * CH201 - Invalid xpub format | |
21 | - * CH202 - At least one xpub is required | |
22 | - * CH203 - Retrieved type does not match expected type | |
23 | - * | |
24 | - * <h2>Access token errors</h2> | |
25 | - * CH300 - Malformed or empty access token id | |
26 | - * CH301 - Access tokens must be type client or network | |
27 | - * CH302 - Access token id is already in use | |
28 | - * CH310 - The access token used to authenticate this request cannot be deleted | |
29 | - * | |
30 | - * <h2>Query errors</h2> | |
31 | - * CH600 - Malformed pagination parameter `after` | |
32 | - * CH601 - Incorrect number of parameters to filter | |
33 | - * CH602 - Malformed query filter | |
34 | - * | |
35 | - * <h2>Transaction errors</h2> | |
36 | - * CH700 - Reference data does not match previous transaction's reference data<br> | |
37 | - * CH701 - Invalid action type<br> | |
38 | - * CH702 - Invalid alias on action<br> | |
39 | - * CH730 - Missing raw transaction<br> | |
40 | - * CH731 - Too many signing instructions in template for transaction<br> | |
41 | - * CH732 - Invalid transaction input index<br> | |
42 | - * CH733 - Invalid signature script component<br> | |
43 | - * CH734 - Missing signature in template<br> | |
44 | - * CH735 - Transaction rejected<br> | |
45 | - * CH760 - Insufficient funds for tx<br> | |
46 | - * CH761 - Some outputs are reserved; try again<br> | |
47 | - */ | |
48 | -public class APIException extends BytomException { | |
49 | - /** | |
50 | - * Unique identifier for the error. | |
51 | - */ | |
52 | - public String code; | |
53 | - | |
54 | - /** | |
55 | - * Message describing the general nature of the error. | |
56 | - */ | |
57 | - @SerializedName("message") | |
58 | - public String chainMessage; | |
59 | - | |
60 | - /** | |
61 | - * Additional information about the error (possibly null). | |
62 | - */ | |
63 | - public String detail; | |
64 | - | |
65 | - /** | |
66 | - * Specifies whether the error is temporary, or a change to the request is necessary. | |
67 | - */ | |
68 | - public boolean temporary; | |
69 | - | |
70 | - /** | |
71 | - * Unique identifier of the request to the server. | |
72 | - */ | |
73 | - public String requestId; | |
74 | - | |
75 | - /** | |
76 | - * HTTP status code returned by the server. | |
77 | - */ | |
78 | - public int statusCode; | |
79 | - | |
80 | - public APIException(String message) { | |
81 | - super(message); | |
82 | - } | |
83 | - | |
84 | - /** | |
85 | - * Initializes exception with its message and requestId attributes. | |
86 | - * | |
87 | - * @param message error message | |
88 | - * @param requestId unique identifier of the request | |
89 | - */ | |
90 | - public APIException(String message, String requestId) { | |
91 | - super(message); | |
92 | - this.requestId = requestId; | |
93 | - } | |
94 | - | |
95 | - /** | |
96 | - * Intitializes exception with its code, message, detail & temporary field set. | |
97 | - * | |
98 | - * @param code error code | |
99 | - * @param message error message | |
100 | - * @param detail additional error information | |
101 | - * @param temporary unique identifier of the request | |
102 | - */ | |
103 | - public APIException(String code, String message, String detail, boolean temporary) { | |
104 | - super(message); | |
105 | - this.chainMessage = message; | |
106 | - this.code = code; | |
107 | - this.detail = detail; | |
108 | - this.temporary = temporary; | |
109 | - } | |
110 | - | |
111 | - /** | |
112 | - * Initializes exception with its code, message, detail & requestId attributes. | |
113 | - * | |
114 | - * @param code error code | |
115 | - * @param message error message | |
116 | - * @param detail additional error information | |
117 | - * @param requestId unique identifier of the request | |
118 | - */ | |
119 | - public APIException(String code, String message, String detail, String requestId) { | |
120 | - super(message); | |
121 | - this.chainMessage = message; | |
122 | - this.code = code; | |
123 | - this.detail = detail; | |
124 | - this.requestId = requestId; | |
125 | - } | |
126 | - | |
127 | - /** | |
128 | - * Initializes exception with all of its attributes. | |
129 | - * | |
130 | - * @param code error code | |
131 | - * @param message error message | |
132 | - * @param detail additional error information | |
133 | - * @param temporary specifies if the error is temporary | |
134 | - * @param requestId unique identifier of the request | |
135 | - * @param statusCode HTTP status code | |
136 | - */ | |
137 | - public APIException( | |
138 | - String code, | |
139 | - String message, | |
140 | - String detail, | |
141 | - boolean temporary, | |
142 | - String requestId, | |
143 | - int statusCode) { | |
144 | - super(message); | |
145 | - this.chainMessage = message; | |
146 | - this.code = code; | |
147 | - this.detail = detail; | |
148 | - this.temporary = temporary; | |
149 | - this.requestId = requestId; | |
150 | - this.statusCode = statusCode; | |
151 | - } | |
152 | - | |
153 | - /** | |
154 | - * Constructs a detailed message of the error. | |
155 | - * | |
156 | - * @return detailed error message | |
157 | - */ | |
158 | - @Override | |
159 | - public String getMessage() { | |
160 | - String s = ""; | |
161 | - | |
162 | - if (this.code != null && this.code.length() > 0) { | |
163 | - s += "Code: " + this.code + " "; | |
164 | - } | |
165 | - | |
166 | - s += "Message: " + this.chainMessage; | |
167 | - | |
168 | - if (this.detail != null && this.detail.length() > 0) { | |
169 | - s += " Detail: " + this.detail; | |
170 | - } | |
171 | - | |
172 | - if (this.requestId != null) { | |
173 | - s += " Request-ID: " + this.requestId; | |
174 | - } | |
175 | - | |
176 | - return s; | |
177 | - } | |
178 | -} |
@@ -1,15 +0,0 @@ | ||
1 | -package io.bytom.offline.exception; | |
2 | - | |
3 | -/** | |
4 | - * BadURLException wraps errors due to malformed URLs. | |
5 | - */ | |
6 | -public class BadURLException extends BytomException { | |
7 | - /** | |
8 | - * Initializes exception with its message attribute. | |
9 | - * | |
10 | - * @param message error message | |
11 | - */ | |
12 | - public BadURLException(String message) { | |
13 | - super(message); | |
14 | - } | |
15 | -} |
@@ -1,49 +0,0 @@ | ||
1 | -package io.bytom.offline.exception; | |
2 | - | |
3 | -import com.google.gson.annotations.SerializedName; | |
4 | - | |
5 | -import java.util.List; | |
6 | - | |
7 | -/** | |
8 | - * BuildException wraps errors returned by the build-transaction endpoint. | |
9 | - */ | |
10 | -public class BuildException extends APIException { | |
11 | - | |
12 | - public BuildException(String message, String requestId) { | |
13 | - super(message, requestId); | |
14 | - } | |
15 | - | |
16 | - public static class ActionError extends APIException { | |
17 | - | |
18 | - public static class Data { | |
19 | - /** | |
20 | - * The index of the action that caused this error. | |
21 | - */ | |
22 | - @SerializedName("index") | |
23 | - public Integer index; | |
24 | - } | |
25 | - | |
26 | - public ActionError(String message, String requestId) { | |
27 | - super(message, requestId); | |
28 | - } | |
29 | - | |
30 | - /** | |
31 | - * Additional data pertaining to the error. | |
32 | - */ | |
33 | - public Data data; | |
34 | - } | |
35 | - | |
36 | - public static class Data { | |
37 | - /** | |
38 | - * A list of errors resulting from building actions. | |
39 | - */ | |
40 | - @SerializedName("actions") | |
41 | - public List<ActionError> actionErrors; | |
42 | - } | |
43 | - | |
44 | - /** | |
45 | - * Extra data associated with this error, if any. | |
46 | - */ | |
47 | - @SerializedName("data") | |
48 | - public Data data; | |
49 | -} |
@@ -1,32 +0,0 @@ | ||
1 | -package io.bytom.offline.exception; | |
2 | - | |
3 | -/** | |
4 | - * Base exception class for the Chain Core SDK. | |
5 | - */ | |
6 | -public class BytomException extends Exception { | |
7 | - /** | |
8 | - * Default constructor. | |
9 | - */ | |
10 | - public BytomException() { | |
11 | - super(); | |
12 | - } | |
13 | - | |
14 | - /** | |
15 | - * Initializes exception with its message attribute. | |
16 | - * | |
17 | - * @param message error message | |
18 | - */ | |
19 | - public BytomException(String message) { | |
20 | - super(message); | |
21 | - } | |
22 | - | |
23 | - /** | |
24 | - * Initializes a new exception while storing the original cause. | |
25 | - * | |
26 | - * @param message the error message | |
27 | - * @param cause the cause of the exception | |
28 | - */ | |
29 | - public BytomException(String message, Throwable cause) { | |
30 | - super(message, cause); | |
31 | - } | |
32 | -} |
@@ -1,25 +0,0 @@ | ||
1 | -package io.bytom.offline.exception; | |
2 | - | |
3 | -/** | |
4 | - * ConfigurationException wraps errors during client configuration. | |
5 | - */ | |
6 | -public class ConfigurationException extends BytomException { | |
7 | - /** | |
8 | - * Initializes exception with its message attribute. | |
9 | - * | |
10 | - * @param message error message | |
11 | - */ | |
12 | - public ConfigurationException(String message) { | |
13 | - super(message); | |
14 | - } | |
15 | - | |
16 | - /** | |
17 | - * Initializes new exception while storing original cause. | |
18 | - * | |
19 | - * @param message the error message | |
20 | - * @param cause the original cause | |
21 | - */ | |
22 | - public ConfigurationException(String message, Throwable cause) { | |
23 | - super(message, cause); | |
24 | - } | |
25 | -} |
@@ -1,38 +0,0 @@ | ||
1 | -package io.bytom.offline.exception; | |
2 | - | |
3 | -import com.squareup.okhttp.Response; | |
4 | - | |
5 | -import java.io.IOException; | |
6 | - | |
7 | -/** | |
8 | - * ConnectivityException wraps errors due to connectivity issues with the server. | |
9 | - */ | |
10 | -public class ConnectivityException extends BytomException { | |
11 | - /** | |
12 | - * Initializes exception with its message attribute. | |
13 | - * | |
14 | - * @param resp the server response used to create error message | |
15 | - */ | |
16 | - public ConnectivityException(Response resp) { | |
17 | - super(formatMessage(resp)); | |
18 | - } | |
19 | - | |
20 | - /** | |
21 | - * Parses the the server response into a detailed error message. | |
22 | - * | |
23 | - * @param resp the server response | |
24 | - * @return detailed error message | |
25 | - */ | |
26 | - private static String formatMessage(Response resp) { | |
27 | - String s = | |
28 | - "Response HTTP header field Chain-Request-ID is unset. There may be network issues. Please check your local network settings."; | |
29 | - // TODO(kr): include client-generated reqid here once we have that. | |
30 | - String body; | |
31 | - try { | |
32 | - body = resp.body().string(); | |
33 | - } catch (IOException ex) { | |
34 | - body = "[unable to read response body: " + ex.toString() + "]"; | |
35 | - } | |
36 | - return String.format("%s status=%d body=%s", s, resp.code(), body); | |
37 | - } | |
38 | -} |
@@ -1,25 +0,0 @@ | ||
1 | -package io.bytom.offline.exception; | |
2 | - | |
3 | -/** | |
4 | - * HTTPException wraps generic HTTP errors. | |
5 | - */ | |
6 | -public class HTTPException extends BytomException { | |
7 | - /** | |
8 | - * Initializes exception with its message attribute. | |
9 | - * | |
10 | - * @param message error message | |
11 | - */ | |
12 | - public HTTPException(String message) { | |
13 | - super(message); | |
14 | - } | |
15 | - | |
16 | - /** | |
17 | - * Initializes new exception while storing original cause. | |
18 | - * | |
19 | - * @param message the error message | |
20 | - * @param cause the original cause | |
21 | - */ | |
22 | - public HTTPException(String message, Throwable cause) { | |
23 | - super(message, cause); | |
24 | - } | |
25 | -} |
@@ -1,39 +0,0 @@ | ||
1 | -package io.bytom.offline.exception; | |
2 | - | |
3 | -/** | |
4 | - * JSONException wraps errors due to marshaling/unmarshaling json payloads. | |
5 | - */ | |
6 | -public class JSONException extends BytomException { | |
7 | - | |
8 | - /** | |
9 | - * Unique indentifier of the request to the server. | |
10 | - */ | |
11 | - public String requestId; | |
12 | - | |
13 | - /** | |
14 | - * Default constructor. | |
15 | - */ | |
16 | - public JSONException(String message) { | |
17 | - super(message); | |
18 | - } | |
19 | - | |
20 | - /** | |
21 | - * Initializes exception with its message and requestId attributes. | |
22 | - * Use this constructor in context of an API call. | |
23 | - * | |
24 | - * @param message error message | |
25 | - * @param requestId unique identifier of the request | |
26 | - */ | |
27 | - public JSONException(String message, String requestId) { | |
28 | - super(message); | |
29 | - this.requestId = requestId; | |
30 | - } | |
31 | - | |
32 | - public String getMessage() { | |
33 | - String message = "Message: " + super.getMessage(); | |
34 | - if (requestId != null) { | |
35 | - message += " Request-ID: " + requestId; | |
36 | - } | |
37 | - return message; | |
38 | - } | |
39 | -} |
@@ -1,7 +1,5 @@ | ||
1 | -package io.bytom; | |
1 | +package io.bytom.offline.api; | |
2 | 2 | |
3 | -import io.bytom.offline.api.*; | |
4 | -import org.bouncycastle.util.encoders.Hex; | |
5 | 3 | import org.junit.Test; |
6 | 4 | |
7 | 5 | public class AppTest { |
@@ -93,7 +91,6 @@ public class AppTest { | ||
93 | 91 | @Test |
94 | 92 | public void testRetire() { |
95 | 93 | String arbitrary = "77656c636f6d65efbc8ce6aca2e8bf8ee69da5e588b0e58e9fe5ad90e4b896e7958c"; |
96 | - String retireControlProgram = "6a"+Integer.toString(Hex.decode(arbitrary).length,16)+arbitrary; | |
97 | 94 | String assetId1 = "207265909236260b30942a6b00e30ceb769e0e58156b6482bac64117619c9dcf"; |
98 | 95 | |
99 | 96 | SpendInput input1 = new SpendInput(btmAssetID, 289100000L, "0014f1dc52048f439ac7fd74f8106a21da78f00de48f"); |
@@ -111,7 +108,7 @@ public class AppTest { | ||
111 | 108 | input2.setSourcePosition(1); |
112 | 109 | |
113 | 110 | Output output1 = new Output(btmAssetID, 279100000L, "001414d362694eacfa110dc20dec77d610d22340f95b"); |
114 | - Output output2 = new Output(assetId1, 10000000000L, retireControlProgram); | |
111 | + Output output2 = Output.newRetireOutput(assetId1, 10000000000L, arbitrary); | |
115 | 112 | Output output3 = new Output(assetId1, 60000000000L, "0014bb8a039726df1b649738e9973db14a4b4fd4becf"); |
116 | 113 | |
117 | 114 | Transaction transaction = new Transaction.Builder() |
@@ -1,5 +1,5 @@ | ||
1 | 1 | |
2 | -package io.bytom.api; | |
2 | +package io.bytom.offline.api; | |
3 | 3 | |
4 | 4 | import io.bytom.offline.types.*; |
5 | 5 | import org.bouncycastle.util.encoders.Hex; |
@@ -1,4 +1,4 @@ | ||
1 | -package io.bytom.api; | |
1 | +package io.bytom.offline.api; | |
2 | 2 | |
3 | 3 | import io.bytom.offline.common.Signer; |
4 | 4 | import org.bouncycastle.util.encoders.Hex; |