- contract TradeOffer(assetRequested: Asset,1 n* W# ?! L/ f, e9 B2 n9 h' c& L
- amountRequested: Amount, b: { ^8 {! I0 Z
- seller: Program,5 K/ b5 ~% {' I
- cancelKey: PublicKey) locks offered {
- clause trade() requires payment: amountRequested of assetRequested {0 e/ o" ?, u/ }
- lock payment with seller
- unlock offered
- }
- clause cancel(sellerSig: Signature) {
- verify checkTxSig(cancelKey, sellerSig), ^) h8 l3 E* F. b; {- h; S
- unlock offered. q* a; @9 C& L" C& a% G2 m
- }
- }
导读: 初次接触比原只能合约的请点击比原智能合约入门 和 Equity 语言入门 学习,方便更好的理解该文档4 Y! G% Q1 o, Z9 {9 x' l
锁定合约& Z* M4 g: X8 x: U/ q+ T/ t
第一步:调用create-account-receiver 生成 control_program
. o1 E$ t( k2 ?; `1 U0 l+ H
以下是相关代码片段:4 n8 U1 j) R3 s4 k- `% N
sendHttpPost("{\"account_id\":\"0IJVD7MNG0A02\"}","create-account-receiver","http://127.0.0.1:9888","");* A2 f' `7 C) e6 L; O5 D
第二步调用list-pubkeys 获取 pubkey
8 \/ m! A' z& g; E! l; J! P& n
以下是相关代码片段:
sendHttpPost("{\"account_id\":\"0IJVD7MNG0A02\"}","list-pubkeys","http://127.0.0.1:9888","");. X3 E4 [! w3 D$ s" \5 D/ X' }
第三步: 将1 2步获取的值调用compile接口编译合约获得program 合约程序
6 _$ a* C, G, r4 O. z" B5 W* K
以下是相关代码片段:
- JSONObject param=new JSONObject();' ~! d4 S1 r8 z0 _
- JSONArray agrs=new JSONArray();
- //合约的四个参数值
- JSONObject assetParam=new JSONObject();
- assetParam.put("string","81d097312645696daea84b761d2898d950d8fba0de06c9267d8513b16663dd3a");
- agrs.put(assetParam);
- JSONObject amountParam=new JSONObject();5 s$ {! `& O! W" C O9 }
- amountParam.put("integer",200000000l);
- agrs.put(amountParam);
- JSONObject programParam=new JSONObject();7 s/ H& ]* }1 {/ w/ C
- programParam.put("string",control_program);
- agrs.put(programParam);
- JSONObject publicKeyParam=new JSONObject();& P K a; Y4 K
- publicKeyParam.put("string",pubkey);+ z5 A p# O! ^' N7 q) D
- 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 } }");
- //调用编译合约
- sendHttpPost(param.toString(),"list-pubkeys","http://127.0.0.1:9888","");
第四步:将program 传入build-transaction接口去build一个交易的到data2 c+ @) r- X4 `" @+ L
, C5 ]& `' y. t& x N
以下是相关代码片段:+ x2 S8 l' n$ ?( w
- param=new JSONObject();
- agrs=new JSONArray();
- JSONObject spendAccount=new JSONObject();8 G# S( w4 Z$ `8 H4 Y$ @" q- b
- spendAccount.put("account_id","0H757LPD00A02");
- spendAccount.put("amount",9909099090000l);" R* m. ~! z1 V# M+ ]3 h5 }7 c9 e6 h, ?% s
- spendAccount.put("asset_id","161b9767b664df907fa926a31f9e835236e57f3e9ccc5f80c12bd97723322652");5 C4 E2 ~2 [) K( I6 R
- spendAccount.put("type","spend_account");4 z6 |, B% O/ D& s) q, i
- agrs.put(spendAccount);# Z( q& h! Q! f+ @" V" ^: M3 j8 U
- JSONObject controlAccount=new JSONObject();
- controlAccount.put("control_program",program); K* I( T& K2 O9 k4 |' ?8 r* I, {
- controlAccount.put("amount",9909099090000l);+ N9 q* u4 S/ v5 S
- controlAccount.put("asset_id","161b9767b664df907fa926a31f9e835236e57f3e9ccc5f80c12bd97723322652");
- controlAccount.put("type","control_program");# ~* r# ^+ t+ R* _6 W9 F: L; A
- agrs.put(controlAccount);9 t5 M% {/ n4 p3 R$ I: z
- JSONObject spendAccount2=new JSONObject();
- spendAccount2.put("account_id","0H757LPD00A02");; f+ G' D+ ?! j+ `
- spendAccount2.put("amount",6000000l);& m( S' ~* w2 B1 ^
- spendAccount2.put("asset_id","ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
- spendAccount2.put("type","spend_account");
- agrs.put(spendAccount2);. q# U6 \. B. _6 ^9 Z' D
- param.put("actions",agrs);7 F3 \" s/ b8 C, K! w) }1 I1 `2 v
- param.put("ttl",0);6 {* |7 j/ ^8 d$ t' @
- sendHttpPost(param.toString(),"build-transaction","http://127.0.0.1:9888","");
第五步:输入密码调用sign-transaction签名第四步build的data 得到raw_transaction% n$ T5 ]1 P9 x* |8 L! K' k5 _
以下是相关代码片段:
param=new JSONObject();
param.put("password","xxx");" @5 V7 J& z$ M6 ]6 ~
param.put("transaction",data);
sendHttpPost(param.toString(),"sign-transaction","http://127.0.0.1:9888","");
第六步:调用submit-transactions提交交易6 c6 H5 g% i& j, x8 z
( ? N1 y; B T
以下是相关代码片段:
param=new JSONObject();1 A* E% b' N+ n2 I7 }4 p( t. \
param.put("raw_transaction",raw_transaction);. b1 A$ {5 V1 W* F
sendHttpPost(param.toString(),"submit-transactions","http://127.0.0.1:9888","");
解锁/取消合约 t: J3 U% O/ n( L& W3 x
首先需要decode出生成合约时候的参数
调用list-unspent-outputs 获取生成的合约信息获取program
8 C* z6 l0 K! m& | [8 p
以下是相关代码片段:
param=new JSONObject();
param.put("id",outputid);
param.put("smart_contract",true);
sendHttpPost(param.toString(),"list-unspent-outputs","http://127.0.0.1:9888","");
调用decode-program 传入获取生成的合约参数信息+ F: T6 |& h2 F
以下是相关代码片段:% y5 g; h' F9 X
param=new JSONObject();- U0 f9 J: D3 `" B3 d4 ^
param.put("program",program);: S- p& I6 v5 D6 X
sendHttpPost(param.toString(),"decode-program","http://127.0.0.1:9888","");/ P1 z+ i8 ~2 q4 h2 B" X
需要注意的是decode出来的为值是逆序的(后续会有文章详细介绍)
解锁/取消其实就是把生成合约的步骤中的第三步去掉,替换调用生成合约第四步的参数即可
取消合约的构造参数如下:! v' n) Z/ _2 l6 i! ^. J
, ?% c( c; H7 i
- spendAccountUnspentOutput = arguments: [{
- type: 'raw_tx_signature',
- // 生成合约第二步的pubkeylist 详情
- raw_data: {
- derivation_path: pubkeylist.pubkey_infos[0].derivation_path,( ~0 T. \/ f1 E& a" m7 f1 L
- xpub: pubkeylist.root_xpub
- }
- }, {- k. a' Z- [8 }. i/ p# v# d
- type: 'data',
- raw_data: {* B. ~4 n) W3 P4 i% E" {6 m
- // 参数偏移量 在一个合约里是固定的
- value: '13000000'
- }
- }],
- output_id: output_id,
- type: 'spend_account_unspent_output'9 h- O M9 J& v2 w4 \5 e
- }0 N0 y- M& i/ q8 {1 A$ m9 F* e
- const controlAction = {: Y0 y6 C6 \& E5 k; m6 Y( m
- type: 'control_program',
- amount: 100000000,
- asset_id: asset_id,
- control_program:control_program* \6 u- X& y; j+ T1 @; c9 D3 s
- }, C& Z8 B6 d# o3 F& R
- const gasAction = {4 R( [ s) d$ H; v4 q% E
- type: 'spend_account',
- account_id:account_id,# _2 ~" k- \: f: F3 R* U7 n8 }
- asset_alias: 'BTM',) i. k+ _* ?4 P8 ~# F5 A' J
- amount: 50000000/ c, N6 o! M& x) }
- }
执行合约的参数构造如下:
( H- s" W7 o8 W, q# z
- const spendAccountUnspentOutput = {
- arguments: [{6 l. T% e% Q$ o8 p* x$ f* T
- type: 'data',
- raw_data: {$ C7 m: f8 ~; F x5 J* E
- // 执行合约输入资产偏移量
- value: '00000000'
- }
- }],
- output_id: output_id,$ f" T* V% `! s' M" C% m- ^8 J. X/ ~
- type: 'spend_account_unspent_output'0 s, e; k6 m3 r
- }
- // 合约执行提供的资产
- const issueControlAction = {$ m4 X6 v* ]$ N- J5 s9 G3 z
- control_program: control_program,
- amount: 100000000,9 \6 @5 I* d& T3 e( l1 ^2 g
- asset_id: asset_id,
- type: 'control_program'
- }
- // 合约执行提供的资产
- const issueSpendAction = {
- account_id: account_id,
- amount: 100000000,# k& |6 f6 {! L9 k, ~1 @) S
- asset_id: asset_id,
- type: 'spend_account'/ `0 g0 `6 U( D2 ~/ L2 {
- }
- // 旷工费+ D9 P' {& g' F2 ]& M' e5 i
- const gasAction = {4 Q; m+ V% V( m r
- type: 'spend_account',% o8 V# x: O! n d) Y4 n
- account_id: account_id,
- asset_alias: 'BTM',
- amount: 500000007 U: `& \) I3 v* e$ d4 O
- }) T; Y; N% w- |$ B7 A
- // 合约执行获得资产对象
- const controlAction = {; A: y- @( q1 W) k, j% g
- type: 'control_program',
- amount: 100000000,2 U( p3 s( E' j5 G5 x* K) N& V
- asset_id: asset_id,
- control_program: compileData.control_program$ r% m0 ^( T" C* G3 Y7 U+ }
- }
build 操作其实就是指定输入输出的过程,详情请查看 官方build文档 和 官方api文档0 {2 [) c# y5 y
备注
调用比原基于okhttp接口javautil 如下:
- public static String sendHttpPost(String bodyStr,String method,String bytomApiserverUrl,String bytomApiserverToken) throws IOException {; y& M( O4 q8 Q" W7 v
- OkHttpClient client = new OkHttpClient();' ~' W/ F$ \/ q, [# }% U# r" K
- MediaType mediaType = MediaType.parse("application/json");
- RequestBody body = RequestBody.create(mediaType, bodyStr);7 T- U5 f: U& r
- Request request = new Request.Builder()1 K; V) U& c' p8 n/ f
- .url(bytomApiserverUrl+"/"+method)/ K1 A8 x! j5 d" |( a
- .post(body)
- .addHeader("cache-control", "no-cache")6 D' H1 [1 K/ x- P: L @; }
- .addHeader("Connection", "close")) O! P5 V! p- ^5 f
- .build();0 L% [$ L( _$ Y' b- U
- if (bytomApiserverUrl==null || bytomApiserverUrl.contains("127.0.0.1") || bytomApiserverUrl.contains("localhost")){$ y% I- q$ p! D( V6 c+ a- F4 M, Y9 J
- }else {3 r/ q( J- v$ R( U) F0 S4 K- c! J o
- byte[] encodedAuth = Base64.encodeBase64(bytomApiserverToken.getBytes(Charset.forName("US-ASCII")));
- String authHeader = "Basic " + new String(encodedAuth);
- request = new Request.Builder()) |& l; p9 u( h% P/ |
- .url(bytomApiserverUrl+"/"+method)
- .post(body) b4 u0 R, ]' a% T
- .addHeader("authorization", authHeader)
- .addHeader("cache-control", "no-cache")
- .addHeader("Connection", "close")- I) z! v2 K5 E1 z( l# O0 U
- .build();2 p8 |, G! u, q) E3 U% s3 _. }
- }9 {7 d. @& M0 k! ^ w* u& z
- Response response = client.newCall(request).execute();9 d3 r$ s/ R& {. }
- return response.body().string();8 q! X# S! P* u7 M+ D
- }
0 k! ^' W6 W/ F( C
6 X& [" d! H: A0 z
比原项目仓库:2 F& [+ N" A0 ~
Github地址:https://github.com/Bytom/bytom
Gitee地址:https://gitee.com/BytomBlockchain/bytom