- contract TradeOffer(assetRequested: Asset,
- amountRequested: Amount,- }. W+ O! x/ J: X
- seller: Program,
- cancelKey: PublicKey) locks offered {
- clause trade() requires payment: amountRequested of assetRequested {+ }: l+ I! k/ C, t$ |/ D2 R3 @
- lock payment with seller
- unlock offered! a# K7 _( m- P- C; L- X
- }
- clause cancel(sellerSig: Signature) {
- verify checkTxSig(cancelKey, sellerSig)
- unlock offered1 D! ?/ U9 j H& ~2 U, Y* V/ G0 C0 Q
- }5 l- {* F( Q/ J8 n, C; |7 S' S
- }
导读: 初次接触比原只能合约的请点击比原智能合约入门 和 Equity 语言入门 学习,方便更好的理解该文档
锁定合约" v# o! p: g' {( ~. n
第一步:调用create-account-receiver 生成 control_program7 _$ q. s+ F- _1 F. R% J( F: T
& R( d$ p; F% B9 C3 {4 e. }1 q
以下是相关代码片段:
sendHttpPost("{\"account_id\":\"0IJVD7MNG0A02\"}","create-account-receiver","http://127.0.0.1:9888","");
第二步调用list-pubkeys 获取 pubkey* y2 J0 V/ `! |# y
1 n- l; Q: X. W- t6 r; _! {" B0 M5 r
以下是相关代码片段:! K2 B0 i2 R4 W
sendHttpPost("{\"account_id\":\"0IJVD7MNG0A02\"}","list-pubkeys","http://127.0.0.1:9888","");
第三步: 将1 2步获取的值调用compile接口编译合约获得program 合约程序
0 m! G3 z8 d6 e: t( W- I3 r9 }+ M3 @
以下是相关代码片段:
- JSONObject param=new JSONObject();! l3 ]4 z3 U* Z2 y' [9 \; m
- JSONArray agrs=new JSONArray();
- //合约的四个参数值; R' k4 l7 f6 b* W8 I' L% U
- JSONObject assetParam=new JSONObject();- R; P. q: i* d/ K5 u |, ]
- assetParam.put("string","81d097312645696daea84b761d2898d950d8fba0de06c9267d8513b16663dd3a");6 Y6 p9 V) K/ E# K( ~0 a
- agrs.put(assetParam);
- JSONObject amountParam=new JSONObject();) `! G8 g/ }! ?) p" \: I9 B% Q
- amountParam.put("integer",200000000l);6 w( `; T# c% R5 \# F
- agrs.put(amountParam);, u2 q& c( g+ Q8 ` T ?
- JSONObject programParam=new JSONObject();
- programParam.put("string",control_program);
- agrs.put(programParam);
- JSONObject publicKeyParam=new JSONObject();9 J# ~- a9 q! M w) C* @
- publicKeyParam.put("string",pubkey);2 K; M; ?/ B3 J. x# Z* ]: L
- agrs.put(publicKeyParam);% ]4 n, W1 @' v3 ^- w
- param.put("agrs",agrs);5 O) h, x0 @, t- X6 l% a
- 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 } }");
- //调用编译合约
- sendHttpPost(param.toString(),"list-pubkeys","http://127.0.0.1:9888","");
第四步:将program 传入build-transaction接口去build一个交易的到data- |1 e) Y* v9 @- g5 B7 r ^
: Z3 b$ b1 L$ U9 o9 z
以下是相关代码片段:+ _% v% y# P" J
- param=new JSONObject();
- agrs=new JSONArray();
- JSONObject spendAccount=new JSONObject();/ t) g# _) c V
- spendAccount.put("account_id","0H757LPD00A02");. S7 V5 J, N) h3 s# g
- spendAccount.put("amount",9909099090000l);
- spendAccount.put("asset_id","161b9767b664df907fa926a31f9e835236e57f3e9ccc5f80c12bd97723322652");( W/ M. E2 x9 z' ^% Y
- spendAccount.put("type","spend_account");
- agrs.put(spendAccount); V# s% Q4 j% s7 ]- k% c! W
- JSONObject controlAccount=new JSONObject();
- controlAccount.put("control_program",program);+ E: J& e3 W% |% K" G9 z2 j9 F
- controlAccount.put("amount",9909099090000l);5 |" v9 j2 ]4 \- h6 i$ `
- controlAccount.put("asset_id","161b9767b664df907fa926a31f9e835236e57f3e9ccc5f80c12bd97723322652");0 O2 Q6 S6 ^* g, F$ U; r# T
- controlAccount.put("type","control_program");
- agrs.put(controlAccount);
- JSONObject spendAccount2=new JSONObject();) e$ Z8 P N0 ^5 b- M' d, R
- spendAccount2.put("account_id","0H757LPD00A02");8 Q/ {9 I: d! Q1 W$ v& X! ?
- spendAccount2.put("amount",6000000l);- D* C2 a! C' E1 x( a
- spendAccount2.put("asset_id","ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");0 M8 Y/ n L, @0 A4 z
- spendAccount2.put("type","spend_account");
- agrs.put(spendAccount2);
- param.put("actions",agrs);+ F; i, n: _1 z5 L3 Q
- param.put("ttl",0);! x) o) O) Z: k5 O, K
- sendHttpPost(param.toString(),"build-transaction","http://127.0.0.1:9888","");
第五步:输入密码调用sign-transaction签名第四步build的data 得到raw_transaction
3 w0 K, ^( e' ?1 k
% q l/ T0 P+ N7 \& {& |" T1 F2 l
以下是相关代码片段:
param=new JSONObject();
param.put("password","xxx");0 I! n, k2 n1 T4 u4 Q. b0 R
param.put("transaction",data);
sendHttpPost(param.toString(),"sign-transaction","http://127.0.0.1:9888","");
第六步:调用submit-transactions提交交易
+ P/ o& J0 q( D+ Z
以下是相关代码片段:% w2 J" v a8 N! f" Q/ T& u3 `
param=new JSONObject();: ^3 \# ^' i( V R) x9 G
param.put("raw_transaction",raw_transaction);2 | ~ f, D P! A, _( y* I2 q# w
sendHttpPost(param.toString(),"submit-transactions","http://127.0.0.1:9888","");
解锁/取消合约/ t. _: @( A7 G4 @6 n% g
首先需要decode出生成合约时候的参数
调用list-unspent-outputs 获取生成的合约信息获取program0 j$ p; ~$ `: g6 w! y
2 e. v$ ?' l5 \. @& N7 g3 D; n
以下是相关代码片段:6 }* J0 V0 {+ Y: b5 x9 |
param=new JSONObject();
param.put("id",outputid);0 q: _2 D& h0 |5 S \
param.put("smart_contract",true);; I1 _3 D. ]( s' t, q
sendHttpPost(param.toString(),"list-unspent-outputs","http://127.0.0.1:9888","");5 ?. Z* b7 K7 @: v% g
调用decode-program 传入获取生成的合约参数信息
以下是相关代码片段:$ f. Y' n4 u9 ~* _1 a' a. J
param=new JSONObject();
param.put("program",program);# w1 s9 b% x y) x, p! v2 S! e# b
sendHttpPost(param.toString(),"decode-program","http://127.0.0.1:9888",""); c- i3 h+ Q0 M+ n2 y
需要注意的是decode出来的为值是逆序的(后续会有文章详细介绍)2 L' `! P: w0 Q6 K
解锁/取消其实就是把生成合约的步骤中的第三步去掉,替换调用生成合约第四步的参数即可0 a8 F) \, h3 j& ^- I
取消合约的构造参数如下:
0 j3 O5 @+ w+ c( }( X
- spendAccountUnspentOutput = arguments: [{
- type: 'raw_tx_signature',
- // 生成合约第二步的pubkeylist 详情1 ~& Q' `$ \, M9 ]: O
- raw_data: {) t. v4 R( h( m0 O2 e& y) J
- derivation_path: pubkeylist.pubkey_infos[0].derivation_path,' n( Q. y! v3 U4 A
- xpub: pubkeylist.root_xpub
- }
- }, {
- type: 'data',
- raw_data: {
- // 参数偏移量 在一个合约里是固定的 $ z: t: A/ R" z& x& h ]
- value: '13000000'
- }
- }],
- output_id: output_id,# m% v, `& Y1 g, j1 Z& S/ W" G
- type: 'spend_account_unspent_output'2 E% D- Q x0 Y/ z/ l* V; T
- }+ O5 \; Y# U2 ]8 l( c% o' t7 ?$ a8 y
- const controlAction = {
- type: 'control_program',( H0 F4 O W# O" `
- amount: 100000000,
- asset_id: asset_id,
- control_program:control_program% `9 l, @* [; p8 Z4 {; d* w8 c9 m. h; m
- }) d7 }; e0 c7 m9 L& N p
- const gasAction = {
- type: 'spend_account',
- account_id:account_id,
- asset_alias: 'BTM',1 ~3 b" K0 E% h* _' y
- amount: 50000000
- }
执行合约的参数构造如下:
& N0 s9 Z" c& W. ^
- const spendAccountUnspentOutput = {! V0 p; g. J) L* m2 C
- arguments: [{8 E& j3 o! y. i2 e
- type: 'data',% c3 h$ k+ V+ b: Y( W
- raw_data: {
- // 执行合约输入资产偏移量; q) d& f$ \" p% B' Y$ |4 d
- value: '00000000'( c7 T' K) J, B; ~: M, {
- }
- }],# Q$ [) J1 U& t9 L+ R
- output_id: output_id,. s; x/ q& J$ E3 a
- type: 'spend_account_unspent_output') y( B( b: Z7 L& [1 G5 [, N
- }4 J6 J& S% `4 b+ O5 E3 j) F
- // 合约执行提供的资产
- const issueControlAction = {9 n5 ?. B7 r9 w8 ]) `
- control_program: control_program,, |! b) L9 M8 F
- amount: 100000000,/ B3 Q9 Z3 w# i% S, A3 J) R
- asset_id: asset_id,
- type: 'control_program'
- }4 ^8 h5 m# C( b: L& h
- // 合约执行提供的资产
- const issueSpendAction = {" h% S$ ~1 o" [3 L
- account_id: account_id,9 P" e7 y l8 `4 E/ `0 h/ D( W
- amount: 100000000,: l. I) @- p: h
- asset_id: asset_id,, \& d* ~: X! W V5 `% }! s3 x
- type: 'spend_account'
- }9 I: u. ]9 j; g8 |# B- w
- // 旷工费
- const gasAction = {
- type: 'spend_account',
- account_id: account_id,1 J2 H0 n5 b1 ]; _1 z
- asset_alias: 'BTM',7 j$ Q' B2 C6 v1 }# Z' p" ]
- amount: 500000009 I$ W3 U: x( w5 _. T$ X9 c
- }
- // 合约执行获得资产对象7 i+ z7 _$ G9 N+ }" s& A6 Z
- const controlAction = {; e9 I C% }- d% C0 \
- type: 'control_program',
- amount: 100000000,0 l" P% A! l& g# l
- asset_id: asset_id,1 n' d! o& r1 ^3 k0 Z. }
- control_program: compileData.control_program; G6 N" ?8 e' Q6 W, K
- }
build 操作其实就是指定输入输出的过程,详情请查看 官方build文档 和 官方api文档2 n/ P# b2 k9 c( o+ O
备注
调用比原基于okhttp接口javautil 如下:6 v G" ]' D" h
- public static String sendHttpPost(String bodyStr,String method,String bytomApiserverUrl,String bytomApiserverToken) throws IOException {* M8 I% ~2 `6 c# {
- OkHttpClient client = new OkHttpClient();0 Z" t0 A( E) [& L# K
- MediaType mediaType = MediaType.parse("application/json");
- RequestBody body = RequestBody.create(mediaType, bodyStr);# I3 Z2 h, h" s9 `; ?- ~9 |
- Request request = new Request.Builder(); r6 J# C$ y3 ?- l0 Y
- .url(bytomApiserverUrl+"/"+method)
- .post(body)5 p$ F$ s! T9 R0 T* A5 J; Z/ F
- .addHeader("cache-control", "no-cache") g; e( \0 F: E9 Q% i: K
- .addHeader("Connection", "close")1 x0 S& j" J4 f* @6 B S; _
- .build();! H8 e; h! X; Y/ q4 f
- if (bytomApiserverUrl==null || bytomApiserverUrl.contains("127.0.0.1") || bytomApiserverUrl.contains("localhost")){! F' m' O: p2 v2 B/ {
- }else {. G: [0 l& w( G" N2 W
- byte[] encodedAuth = Base64.encodeBase64(bytomApiserverToken.getBytes(Charset.forName("US-ASCII")));
- String authHeader = "Basic " + new String(encodedAuth);
- request = new Request.Builder()& |4 `# e9 U8 i
- .url(bytomApiserverUrl+"/"+method)6 \3 X: V4 J# m' h
- .post(body)& I& z' m+ {3 B! W! i: U S
- .addHeader("authorization", authHeader)' y; {- F3 u5 R% b1 |) A- T k
- .addHeader("cache-control", "no-cache")
- .addHeader("Connection", "close")2 L" l9 t8 B5 x0 B
- .build();
- } Z& `+ S* X2 t$ b
- Response response = client.newCall(request).execute();, ^5 ]9 g) x# h Z, e/ b, W* ^5 O; H
- return response.body().string();) D/ B3 {: i s8 _! M6 y
- }
6 ]4 \) Y D3 Z' S9 z
. \( j5 Q( m2 X! ~' I
比原项目仓库:$ i( l$ p- i r- U. w2 }
Github地址:https://github.com/Bytom/bytom$ `; p6 |( y6 O# n( l- {4 L, [: @3 A
Gitee地址:https://gitee.com/BytomBlockchain/bytom