- contract TradeOffer(assetRequested: Asset,& i- X% X% ^9 U. w, e G
- amountRequested: Amount,
- seller: Program,
- cancelKey: PublicKey) locks offered {+ e; o% I% d8 G1 T$ F# X/ j
- clause trade() requires payment: amountRequested of assetRequested {
- lock payment with seller: ] }; P1 Y& u
- unlock offered$ s. b' x) L# \+ Y0 j6 T; h9 k) `5 {
- }
- clause cancel(sellerSig: Signature) {
- verify checkTxSig(cancelKey, sellerSig)
- unlock offered
- }
- }
导读: 初次接触比原只能合约的请点击比原智能合约入门 和 Equity 语言入门 学习,方便更好的理解该文档
锁定合约
第一步:调用create-account-receiver 生成 control_program
以下是相关代码片段:% m( e& y- W6 s
sendHttpPost("{\"account_id\":\"0IJVD7MNG0A02\"}","create-account-receiver","http://127.0.0.1:9888","");' C9 I# t0 I! T
第二步调用list-pubkeys 获取 pubkey, o* J6 F+ H8 W( o/ P/ ?
4 v4 B7 y! b" L, E* t- R) E) `6 v
以下是相关代码片段:9 [% k& x0 N+ i; m2 k: @1 S% H5 {
sendHttpPost("{\"account_id\":\"0IJVD7MNG0A02\"}","list-pubkeys","http://127.0.0.1:9888","");2 \' F2 |: \3 D b
第三步: 将1 2步获取的值调用compile接口编译合约获得program 合约程序
0 w4 o# |9 s( z/ K2 n' ~ w* v
以下是相关代码片段:9 V3 J- k; [) q" G+ B* P
- JSONObject param=new JSONObject();. \) G! l2 t4 h, T
- JSONArray agrs=new JSONArray();
- //合约的四个参数值
- JSONObject assetParam=new JSONObject();
- assetParam.put("string","81d097312645696daea84b761d2898d950d8fba0de06c9267d8513b16663dd3a");& ^) n# w' v! n/ g
- agrs.put(assetParam);
- JSONObject amountParam=new JSONObject(); X) Y i& y6 \6 i, L
- amountParam.put("integer",200000000l); U& l( n* q. y- P; s
- agrs.put(amountParam);9 t! v; n) u( c% c
- JSONObject programParam=new JSONObject();, @2 E0 h# _$ D" N4 _6 y
- programParam.put("string",control_program);8 N0 n) o- P* e: d4 M9 Z% v
- agrs.put(programParam);
- JSONObject publicKeyParam=new JSONObject();3 L" F6 ]9 s* a
- publicKeyParam.put("string",pubkey);5 f& Y! J! ?4 ]9 Z* k
- agrs.put(publicKeyParam);
- param.put("agrs",agrs);
- param.put("contract","contract TradeOffer(assetRequested: Asset, amountRequested: Amount, seller: Program, cancelKey: PublicKey) locks offered { clause trade() requires payment: amountRequested of assetRequested { lock payment with seller unlock offered } clause cancel(sellerSig: Signature) { verify checkTxSig(cancelKey, sellerSig) unlock offered } }");( S9 v( T- t' R! z7 b
- //调用编译合约4 {# Z1 b, y2 x, n1 o5 C
- sendHttpPost(param.toString(),"list-pubkeys","http://127.0.0.1:9888","");
第四步:将program 传入build-transaction接口去build一个交易的到data4 B9 b, y& G( m$ I2 o/ ~' S
以下是相关代码片段:' h/ Q' \" H1 ~0 }2 ]
- param=new JSONObject();
- agrs=new JSONArray();4 X3 t( e5 O" _- h
- JSONObject spendAccount=new JSONObject();( i/ u7 V/ u) g2 Y$ Q: x
- spendAccount.put("account_id","0H757LPD00A02");0 q+ }( \) y6 i8 K" E
- spendAccount.put("amount",9909099090000l);
- spendAccount.put("asset_id","161b9767b664df907fa926a31f9e835236e57f3e9ccc5f80c12bd97723322652");4 y5 ?+ i2 h9 b" V( m1 R
- spendAccount.put("type","spend_account");" Y: j M0 M% ~# v$ K! x1 M
- agrs.put(spendAccount);( y% A4 H$ j; K3 p; T
- JSONObject controlAccount=new JSONObject();
- controlAccount.put("control_program",program);
- controlAccount.put("amount",9909099090000l);
- controlAccount.put("asset_id","161b9767b664df907fa926a31f9e835236e57f3e9ccc5f80c12bd97723322652");
- controlAccount.put("type","control_program");4 k( N# X K- x6 `' y9 |
- agrs.put(controlAccount);
- JSONObject spendAccount2=new JSONObject();; g- v: X s+ F* ?. N$ {; K0 O/ l
- spendAccount2.put("account_id","0H757LPD00A02");
- spendAccount2.put("amount",6000000l);7 `9 h0 B- R2 f _, X8 q
- spendAccount2.put("asset_id","ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
- spendAccount2.put("type","spend_account");: V6 n7 R# U6 i4 `( |6 r) ^
- agrs.put(spendAccount2);6 B' I% e$ P4 m. b* Q. ]
- param.put("actions",agrs);* u, z, ~. s; [
- param.put("ttl",0);9 H+ R# Z8 e+ C; R
- sendHttpPost(param.toString(),"build-transaction","http://127.0.0.1:9888","");
第五步:输入密码调用sign-transaction签名第四步build的data 得到raw_transaction
9 r8 a! \: P* ]4 U/ Y V# S
* `) I8 g0 i/ y; }1 \
以下是相关代码片段:
param=new JSONObject();2 }5 d; `6 d i+ [, w% h: X
param.put("password","xxx");
param.put("transaction",data);5 V, q# w% E2 s* }9 ]9 [8 i% {$ f
sendHttpPost(param.toString(),"sign-transaction","http://127.0.0.1:9888","");9 N. I) J' ?/ E& K6 a
第六步:调用submit-transactions提交交易
以下是相关代码片段:, p2 ^& A, T: _/ w
param=new JSONObject();7 r- k5 X4 ~% W# R
param.put("raw_transaction",raw_transaction);: W" W1 P. `: b$ M ?; `& r
sendHttpPost(param.toString(),"submit-transactions","http://127.0.0.1:9888","");" X$ z+ ]( f( n) y A/ _8 |$ d
解锁/取消合约$ s2 F- W% P# g& g# o# y
首先需要decode出生成合约时候的参数
调用list-unspent-outputs 获取生成的合约信息获取program
以下是相关代码片段:6 ~$ @" r' Y& z3 p; x/ l9 Z1 D
param=new JSONObject();* B1 a0 W X8 t# U$ Q
param.put("id",outputid);! r& D9 o, a$ M( @, l+ g/ j% j
param.put("smart_contract",true);
sendHttpPost(param.toString(),"list-unspent-outputs","http://127.0.0.1:9888","");' e, c$ j j C) { b5 u4 F
调用decode-program 传入获取生成的合约参数信息
以下是相关代码片段:9 U9 Z. j* u% @
param=new JSONObject();. I# Q8 ]7 v7 w: X9 e# t
param.put("program",program);( ?4 N9 z. q$ t& [4 \! ^
sendHttpPost(param.toString(),"decode-program","http://127.0.0.1:9888","");" S" _$ G# I2 l/ w* G/ {8 I$ ~
需要注意的是decode出来的为值是逆序的(后续会有文章详细介绍)$ B8 y1 w7 l6 Y9 a4 o
解锁/取消其实就是把生成合约的步骤中的第三步去掉,替换调用生成合约第四步的参数即可
取消合约的构造参数如下:& ^+ a+ V) _" f$ v3 _9 i. e
, M6 w" v$ N9 s
- spendAccountUnspentOutput = arguments: [{
- type: 'raw_tx_signature',& U" W! A2 r8 Q# @5 ~7 E
- // 生成合约第二步的pubkeylist 详情
- raw_data: {# V( U* d0 _; \( ?' c5 O+ E! H7 c
- derivation_path: pubkeylist.pubkey_infos[0].derivation_path,% X& H) w) ?# a8 X& O/ t
- xpub: pubkeylist.root_xpub
- }( f/ D8 r, _7 S8 q
- }, {
- type: 'data',9 S p; {, z: \3 ?0 x7 z
- raw_data: {: _ m: w; J2 _
- // 参数偏移量 在一个合约里是固定的 . N' g, \( Y( g! @0 b+ d% l- P3 x
- value: '13000000'$ O$ C) \* ?& J/ L
- }
- }],0 V8 U) T ]2 B
- output_id: output_id,: o8 v6 A% a, L" j2 w. G0 T
- type: 'spend_account_unspent_output'
- }
- const controlAction = {9 @9 t; X/ x/ M7 V: w. P6 K/ X
- type: 'control_program',& I/ n+ N7 {& P N- `
- amount: 100000000,
- asset_id: asset_id,
- control_program:control_program
- }
- const gasAction = {
- type: 'spend_account',: }% A7 l' r b2 T7 ], |
- account_id:account_id," N0 \: [# { r4 p3 F
- asset_alias: 'BTM',6 J+ E" E; P S1 R8 ^7 W" { a
- amount: 50000000
- }
执行合约的参数构造如下:- O( C6 w5 B; t5 A A
- const spendAccountUnspentOutput = {/ s1 R* l2 F: {
- arguments: [{# L5 o8 K, w- l5 t! L; m( R
- type: 'data',
- raw_data: {; ^1 \- `3 D/ s% l" k
- // 执行合约输入资产偏移量
- value: '00000000'
- }
- }],* x" Z+ k" J+ h9 G
- output_id: output_id,
- type: 'spend_account_unspent_output'9 G L H8 M. S8 @( W- l
- }
- // 合约执行提供的资产
- const issueControlAction = {, T0 x! x* P$ g9 p: Z% ]3 n! E
- control_program: control_program,: P% d g% n1 V* `* K+ ?4 X/ m
- amount: 100000000," l7 A- j8 I# L% w& ]- i, U% N
- asset_id: asset_id,& B$ ?$ v3 W' J7 x8 X& [
- type: 'control_program') J+ n# W$ l* E
- }
- // 合约执行提供的资产2 [9 m& A/ N) e
- const issueSpendAction = {, m$ I: N+ U) c2 E- u4 U
- account_id: account_id,
- amount: 100000000,
- asset_id: asset_id,4 m3 ]- ^2 i1 v" J# C5 S( C; s' b0 J# |. M. \
- type: 'spend_account'
- }5 ?( m0 x+ V8 s# x0 j8 ?, E: q
- // 旷工费8 _5 M- y/ b# _. I$ F2 l `: I6 j. Q
- const gasAction = {
- type: 'spend_account',
- account_id: account_id,
- asset_alias: 'BTM',6 K8 H' O7 Q- q9 O. w b; k
- amount: 50000000- v" _/ }4 G; @
- }4 G+ }) H' l+ F, Q' ~5 l4 p B- T
- // 合约执行获得资产对象
- const controlAction = {
- type: 'control_program',9 q% l7 @2 }3 W1 ]8 j( F6 ~
- amount: 100000000, ?* f5 _; N0 ^
- asset_id: asset_id,' W% i6 V4 ]0 _" i @
- control_program: compileData.control_program9 D7 f% I: x4 ~! u* Y0 d
- }
build 操作其实就是指定输入输出的过程,详情请查看 官方build文档 和 官方api文档9 a7 h* Q) f2 e) i P9 D& V9 Z
备注
调用比原基于okhttp接口javautil 如下:
- public static String sendHttpPost(String bodyStr,String method,String bytomApiserverUrl,String bytomApiserverToken) throws IOException {
- OkHttpClient client = new OkHttpClient();, u7 `( h2 F2 s0 b7 s4 I6 y8 @
- MediaType mediaType = MediaType.parse("application/json");
- RequestBody body = RequestBody.create(mediaType, bodyStr); M3 @6 V8 w4 M7 n8 _2 ^
- Request request = new Request.Builder()
- .url(bytomApiserverUrl+"/"+method)$ d$ X/ q4 L m
- .post(body)
- .addHeader("cache-control", "no-cache")2 i5 c: j) u/ Z# r0 |" h
- .addHeader("Connection", "close")
- .build();9 C2 m0 e) t; v, B# }/ R4 y
- if (bytomApiserverUrl==null || bytomApiserverUrl.contains("127.0.0.1") || bytomApiserverUrl.contains("localhost")){
- }else {/ q! K4 g+ t8 Z( a
- byte[] encodedAuth = Base64.encodeBase64(bytomApiserverToken.getBytes(Charset.forName("US-ASCII")));' c/ P' L, s, C$ J8 I
- String authHeader = "Basic " + new String(encodedAuth);( N! H; }) ]4 Z3 l9 A5 G/ c
- request = new Request.Builder()% M5 L1 ]6 b) i
- .url(bytomApiserverUrl+"/"+method) c! k. ]4 _# E6 z3 v0 U ~1 k* d
- .post(body)
- .addHeader("authorization", authHeader)9 F* e& q( S: u7 {7 F( Z5 s
- .addHeader("cache-control", "no-cache")( l7 @$ ?1 N0 B& G
- .addHeader("Connection", "close"); }* K! A, H0 p7 ^5 N
- .build();0 Y! e9 J) S/ v; g% W, r$ u
- }
- Response response = client.newCall(request).execute();* U- }7 Q5 U, _, P
- return response.body().string();( w0 @- x' [6 F3 L9 @4 i+ I
- }
8 u# N: t+ }6 \: {6 \& K" l# S9 u
比原项目仓库:- Q7 a- X. W4 V4 E: B
Github地址:https://github.com/Bytom/bytom, p0 E% z& T) F: E# |
Gitee地址:https://gitee.com/BytomBlockchain/bytom