Skip to content

Commit b6a1e8f

Browse files
committed
commit
1 parent 8153a9a commit b6a1e8f

File tree

7 files changed

+250
-135
lines changed

7 files changed

+250
-135
lines changed

README.MD

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,27 @@
11
# assembly script contract code template
22

3-
## build wasm binary
3+
## compile only
44

5-
```shell script
6-
npm run asbuild
7-
```
5+
1. clone or download this repository
86

9-
## deploy contract
7+
2. execute `npm install` to install dependencies
108

11-
```shell script
12-
node ./deploy.js
13-
```
9+
3. write your contract code at assembly/index.ts
1410

15-
## 代币合约
11+
4. execute command `java -jar cmd-*.jar compile -s assembly/index.ts -o index.wasm -a node_modules/.bin/asc`
1612

17-
```shell script
18-
# 编译
19-
npx run asbuild:coin
2013

21-
# 部署合约
22-
node tests/deploy-coin.js
14+
## compile and deploy
2315

24-
# 查看账户余额
25-
node tests/view-coin-balance.js
16+
1. clone or download this repository
2617

27-
# 充值
28-
node tests/call-coin-charge.js
18+
2. execute `npm install` to install dependencies
19+
20+
3. write your contract code at assembly/index.ts
21+
22+
4. configure your tds server at cmd-config.json
23+
24+
5. download latest cmd tool cmd-1.0-SNAPSHOT.jar at [release page](https://github.com/TrustedDataFramework/assembly-script-template/releases)
25+
26+
6. execute command `java -jar cmd-*.jar deploy -c cmd-config.json`
2927

30-
# 转账
31-
node tests/call-coin-transfer.js
32-
```

cmd-config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"version": "",
3-
"entry-point": "",
3+
"host": "",
4+
"port": "",
45
"source": "assembly/index.ts",
56
"private-key": "",
67
"asc-path": "node_modules/.bin/asc"
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.tds.cmd;
2+
3+
import lombok.NonNull;
4+
import lombok.RequiredArgsConstructor;
5+
import lombok.SneakyThrows;
6+
import org.apache.tika.io.IOUtils;
7+
8+
import java.io.InputStream;
9+
10+
@RequiredArgsConstructor
11+
public class AscWrapper {
12+
@NonNull
13+
private final String ascPath;
14+
15+
@SneakyThrows
16+
public byte[] compile(@NonNull String source) {
17+
String cmd = ascPath + " " + source + " --optimize -b";
18+
Process p = Runtime.getRuntime().exec(cmd);
19+
InputStream in = p.getInputStream();
20+
return IOUtils.toByteArray(in);
21+
}
22+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package org.tds.cmd;
2+
3+
4+
import com.beust.jcommander.Parameter;
5+
import com.beust.jcommander.Parameters;
6+
import lombok.SneakyThrows;
7+
8+
import java.nio.file.Files;
9+
import java.nio.file.Paths;
10+
import java.nio.file.StandardOpenOption;
11+
import java.util.Arrays;
12+
13+
@Parameters(commandDescription = "compile source file to wasm binary")
14+
public class Compile {
15+
@Parameter(names = {"--source", "-s"}, description = "wasm contract source file")
16+
private String source;
17+
18+
@Parameter(names = {"--output", "-p"}, description = "target file")
19+
private String output;
20+
21+
@Parameter(names = {"--ascPath", "-a"}, description = "asc file path, often located in node_modules/.bin/")
22+
private String ascPath;
23+
24+
private String beforeExtension(String file) {
25+
if (file.isEmpty())
26+
return file;
27+
char[] chars = file.toCharArray();
28+
int i = -1;
29+
for (int j = 0; j < chars.length; j++) {
30+
if (chars[j] == '.') i = j;
31+
}
32+
if (i < 0)
33+
return file;
34+
return new String(Arrays.copyOfRange(chars, 0, i));
35+
}
36+
37+
public void withDefault() {
38+
if (ascPath == null || ascPath.isEmpty())
39+
ascPath = "node_modules/.bin/asc";
40+
if (output == null || output.isEmpty()) {
41+
output = beforeExtension(source) + ".wasm";
42+
}
43+
}
44+
45+
@SneakyThrows
46+
public void run() {
47+
withDefault();
48+
AscWrapper wrapper = new AscWrapper(ascPath);
49+
Files.write(Paths.get(output), wrapper.compile(source), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
50+
}
51+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package org.tds.cmd;
2+
3+
import com.beust.jcommander.Parameter;
4+
import com.beust.jcommander.Parameters;
5+
import lombok.SneakyThrows;
6+
import org.tdf.common.util.HexBytes;
7+
import org.tdf.sunflower.consensus.poa.PoAConstants;
8+
import org.tdf.sunflower.state.Address;
9+
import org.tdf.sunflower.types.CryptoContext;
10+
import org.tdf.sunflower.types.Transaction;
11+
12+
import java.io.File;
13+
14+
import static org.tds.cmd.Main.OBJECT_MAPPER;
15+
16+
@Parameters(commandDescription = "compile and deploy contract to tds server")
17+
public class Deploy {
18+
@Parameter(names = {"--source", "-s"}, description = "wasm contract source file")
19+
private String source;
20+
@Parameter(names = {"--privateKey", "-k"}, description = "your tds private key")
21+
private String privateKey;
22+
@Parameter(names = {"--ascPath", "-a"}, description = "asc file path, often located in node_modules/.bin/")
23+
private String ascPath;
24+
@Parameter(names = {"--host", "-h"}, description = "tds server host")
25+
private String host;
26+
@Parameter(names = {"--port", "-p"}, description = "tds server port")
27+
private int port;
28+
29+
@Parameter(names = {"--config", "-c"}, description = "deploy configuration file, overrided by command line options")
30+
private String config;
31+
32+
private void setConfig(Config config) {
33+
if (this.source == null || this.source.isEmpty())
34+
this.source = config.getSource();
35+
36+
if (this.privateKey == null || this.privateKey.isEmpty())
37+
this.privateKey = config.getPrivateKey();
38+
39+
if (this.ascPath == null || this.ascPath.isEmpty())
40+
this.ascPath = config.getAscPath();
41+
42+
if (this.host == null || this.host.isEmpty())
43+
this.host = config.getHost();
44+
45+
if (this.port == 0)
46+
this.port = config.getPort();
47+
}
48+
49+
@SneakyThrows
50+
private void loadJsonConfig() {
51+
if (config != null && !config.isEmpty()) {
52+
File f = new File(config);
53+
if (f.exists() && !f.isDirectory()) {
54+
Config c = OBJECT_MAPPER.readValue(f, Config.class);
55+
setConfig(c);
56+
}
57+
}
58+
}
59+
60+
@SneakyThrows
61+
public void run() {
62+
loadJsonConfig();
63+
HexBytes publicKey = HexBytes.fromBytes(CryptoContext.getPkFromSk(HexBytes.decode(privateKey)));
64+
HttpUtil util = new HttpUtil(host, port);
65+
AscWrapper wrapper = new AscWrapper(ascPath);
66+
HexBytes address = Address.fromPublicKey(publicKey);
67+
Transaction tx = new Transaction(
68+
PoAConstants.TRANSACTION_VERSION,
69+
Transaction.Type.CONTRACT_DEPLOY.code,
70+
System.currentTimeMillis() / 1000,
71+
util.getLatestNonce(address) + 1,
72+
publicKey,
73+
0, 0,
74+
HexBytes.EMPTY,
75+
HexBytes.EMPTY,
76+
HexBytes.EMPTY
77+
);
78+
79+
tx.setPayload(HexBytes.fromBytes(wrapper.compile(source)));
80+
byte[] sig = CryptoContext.sign(HexBytes.fromHex(privateKey).getBytes(), tx.getSignaturePlain());
81+
tx.setSignature(HexBytes.fromBytes(sig));
82+
System.out.println("deploy contract " + source + " address = " + tx.createContractAddress());
83+
System.out.println("tds server response: \n" + util.sendTransaction(tx));
84+
}
85+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package org.tds.cmd;
2+
3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import lombok.NonNull;
5+
import lombok.RequiredArgsConstructor;
6+
import lombok.SneakyThrows;
7+
import org.apache.commons.codec.Charsets;
8+
import org.apache.http.HttpEntity;
9+
import org.apache.http.HttpResponse;
10+
import org.apache.http.HttpStatus;
11+
import org.apache.http.client.HttpClient;
12+
import org.apache.http.client.methods.HttpGet;
13+
import org.apache.http.client.methods.HttpPost;
14+
import org.apache.http.entity.ContentType;
15+
import org.apache.http.entity.StringEntity;
16+
import org.apache.http.impl.client.HttpClientBuilder;
17+
import org.apache.http.util.EntityUtils;
18+
import org.tdf.common.util.HexBytes;
19+
import org.tdf.sunflower.types.Transaction;
20+
21+
import static org.tds.cmd.Main.OBJECT_MAPPER;
22+
23+
@RequiredArgsConstructor
24+
public class HttpUtil {
25+
@NonNull
26+
private final String host;
27+
private final int port;
28+
private HttpClient client = HttpClientBuilder.create().build();
29+
30+
@SneakyThrows
31+
public long getLatestNonce(HexBytes address) {
32+
String getUrl = "http://" + host + ":" + port + "/rpc/account/" + address.toHex();
33+
HttpGet get = new HttpGet(getUrl);
34+
HttpResponse getResponse = client.execute(get);
35+
if (getResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
36+
String data = EntityUtils.toString(getResponse.getEntity(), Charsets.UTF_8);
37+
JsonNode n = OBJECT_MAPPER.readValue(data, JsonNode.class);
38+
return n.get("data").get("nonce").asLong();
39+
}
40+
throw new RuntimeException("get nonce failed http error " + getResponse.getStatusLine().getStatusCode());
41+
}
42+
43+
44+
@SneakyThrows
45+
public String sendTransaction(Transaction tx) {
46+
String postUrl = "http://" + host + ":" + port + "/rpc/transaction";
47+
HttpPost post = new HttpPost(postUrl);
48+
HttpEntity entity = new StringEntity(OBJECT_MAPPER.writeValueAsString(tx), ContentType.APPLICATION_JSON);
49+
post.setEntity(entity);
50+
HttpResponse postResponse = client.execute(post);
51+
if (postResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
52+
HttpEntity resEntity = postResponse.getEntity();
53+
return EntityUtils.toString(resEntity);
54+
}
55+
throw new RuntimeException("send transaction failed http error " + postResponse.getStatusLine().getStatusCode());
56+
}
57+
}

0 commit comments

Comments
 (0)