OSDN Git Service

eea20ca9472f31ce91c89b4bdf2764bdbc3b1102
[bytom/vapor.git] / cmd / vaporcli / commands / template.go
1 package commands
2
3 import (
4         "fmt"
5
6         "github.com/vapor/errors"
7 )
8
9 const (
10         // contract TradeOffer's clause
11         clauseTrade      = "00000000"
12         clauseCancel     = "13000000"
13         tradeOfferEnding = "1a000000"
14
15         // contract Escrow's clause
16         clauseApprove = "00000000"
17         clauseReject  = "1a000000"
18         escrowEnding  = "28000000"
19
20         // contract LoanCollateral's clause
21         clauseRepay          = "00000000"
22         clauseDefault        = "1b000000"
23         loanCollateralEnding = "26000000"
24
25         // contract CallOption's clause
26         clauseExercise   string = "00000000"
27         clauseExpire     string = "20000000"
28         callOptionEnding string = "2c000000"
29 )
30
31 var (
32         errBadContractArguments = errors.New("bad contract arguments")
33 )
34
35 // common receiver template, the clause takes only one parameter without Signature in the contract that contains only one clause,
36 // or the clause takes no parameters in the contract with multiple clauses. In addition, clause's statement like "lock payment with program" or "unlock value"
37 var buildCommonRecvReqFmt = `
38         {"actions": [
39                 {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "data", "raw_data": {"value": "%s"}}]},
40                 {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
41                 {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount": %s, "account_id": "%s"}
42         ]}`
43
44 var buildCommonRecvReqFmtByAlias = `
45         {"actions": [
46                 {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "data", "raw_data": {"value": "%s"}}]},
47                 {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
48                 {"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"}
49         ]}`
50
51 // contract is LockWithPublicKey
52 var buildLockWithPublicKeyReqFmt = `
53         {"actions": [
54                 {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}}]},
55                 {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
56                 {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount": %s, "account_id": "%s"}
57         ]}`
58
59 var buildLockWithPublicKeyReqFmtByAlias = `
60         {"actions": [
61                 {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}}]},
62                 {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
63                 {"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"}
64         ]}`
65
66 // contract is LockWithMultiSig
67 var buildLockWithMultiSigReqFmt = `
68         {"actions": [
69                 {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}},
70                                 {"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}}]},
71                 {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
72                 {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount": %s, "account_id": "%s"}
73         ]}`
74
75 var buildLockWithMultiSigReqFmtByAlias = `
76         {"actions": [
77                 {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}},
78                                 {"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}}]},
79                 {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
80                 {"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"}
81         ]}`
82
83 // contract is LockWithPublicKeyHash
84 var buildLockWithPublicKeyHashReqFmt = `
85         {"actions": [
86                 {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "data", "raw_data": {"value": "%s"}},
87                                 {"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}}]},
88                 {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
89                 {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount": %s, "account_id": "%s"}
90         ]}`
91
92 var buildLockWithPublicKeyHashReqFmtByAlias = `
93         {"actions": [
94                 {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "data", "raw_data": {"value": "%s"}},
95                                 {"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}}]},
96                 {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
97                 {"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"}
98         ]}`
99
100 // contract is TradeOffer's clause trade, the code of clause contains only two statement with "lock payment with program" and "unlock value"
101 var buildTradeOfferClauseTradeReqFmt = `
102         {"actions": [
103                 {"type": "spend_account_unspent_output", "output_id":"%s", "arguments": [{"type": "data", "raw_data": {"value": "%s"}}]},
104                 {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
105                 {"type": "spend_account", "asset_id": "%s", "amount": %s, "account_id": "%s"},
106                 {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount":%s, "account_id": "%s"},
107                 {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"}
108         ]}`
109
110 var buildTradeOfferClauseTradeReqFmtByAlias = `
111         {"actions": [
112                 {"type": "spend_account_unspent_output", "output_id":"%s", "arguments": [{"type": "data", "raw_data": {"value": "%s"}}]},
113                 {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
114                 {"type": "spend_account", "asset_alias": "%s", "amount": %s, "account_alias": "%s"},
115                 {"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"},
116                 {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"}
117         ]}`
118
119 // contract is TradeOffer's clause cancel
120 var buildTradeOfferClauseCancelReqFmt = `
121         {"actions": [
122                 {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}},
123                                 {"type": "data", "raw_data": {"value": "%s"}}]},
124                 {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
125                 {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount": %s, "account_id": "%s"}
126         ]}`
127
128 var buildTradeOfferClauseCancelReqFmtByAlias = `
129         {"actions": [
130                 {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}},
131                                 {"type": "data", "raw_data": {"value": "%s"}}]},
132                 {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
133                 {"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"}
134         ]}`
135
136 // contract is Escrow
137 var buildEscrowReqFmt = `
138         {"actions": [
139                 {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}},
140                                 {"type": "data", "raw_data": {"value": "%s"}}]},
141                 {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
142                 {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount":%s, "account_id": "%s"}
143         ]}`
144
145 var buildEscrowReqFmtByAlias = `
146         {"actions": [
147                 {"type": "spend_account_unspent_output", "output_id":"%s", "arguments": [{"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}},
148                                 {"type": "data", "raw_data": {"value": "%s"}}]},
149                 {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
150                 {"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"}
151         ]}`
152
153 // contract is LoanCollateral's clause repay, the code of clause contains only two statement with "lock payment with program" and "lock value with control_program"
154 var buildLoanCollateralClauseRepayReqFmt = `
155         {"actions": [
156                 {"type": "spend_account_unspent_output", "output_id":"%s", "arguments": [{"type": "data", "raw_data": {"value": "%s"}}]},
157                 {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
158                 {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
159                 {"type": "spend_account", "asset_id": "%s", "amount": %s, "account_id": "%s"},
160                 {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount":%s, "account_id": "%s"}
161         ]}`
162
163 var buildLoanCollateralClauseRepayReqFmtByAlias = `
164         {"actions": [
165                 {"type": "spend_account_unspent_output", "output_id":"%s", "arguments": [{"type": "data", "raw_data": {"value": "%s"}}]},
166                 {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
167                 {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
168                 {"type": "spend_account", "asset_alias": "%s", "amount": %s, "account_alias": "%s"},
169                 {"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"}
170         ]}`
171
172 // contract is CallOption's clause exercise, the code of clause contains only two statement with "lock payment with program" and "unlock value"
173 var buildCallOptionClauseExerciseReqFmt = `
174         {"actions": [
175                 {"type": "spend_account_unspent_output", "output_id":"%s", "arguments": [{"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}},
176                                 {"type": "data", "raw_data": {"value": "%s"}}]},
177                 {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
178                 {"type": "spend_account", "asset_id": "%s", "amount": %s, "account_id": "%s"},
179                 {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount":%s, "account_id": "%s"},
180                 {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"}
181         ]}`
182
183 var buildCallOptionClauseExerciseReqFmtByAlias = `
184         {"actions": [
185                 {"type": "spend_account_unspent_output", "output_id":"%s", "arguments": [{"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}},
186                                 {"type": "data", "raw_data": {"value": "%s"}}]},
187                 {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
188                 {"type": "spend_account", "asset_alias": "%s", "amount": %s, "account_alias": "%s"},
189                 {"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"},
190                 {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"}
191         ]}`
192
193 // contract arguments
194 type baseContractArg struct {
195         accountInfo string
196         assetInfo   string
197         amount      string
198         alias       bool
199         program     string
200         btmGas      string
201         outputID    string
202 }
203
204 type basePubInfo struct {
205         rootPub string
206         path1   string
207         path2   string
208 }
209
210 type innerContractArg struct {
211         innerAccountInfo string
212         innerAssetInfo   string
213         innerAmount      string
214         innerProgram     string
215 }
216
217 // addContractArgs add arguments for template contracts
218 func addContractArgs(contractName string, baseArg baseContractArg, specArgs []string, usage string) (buildReqStr string, err error) {
219         switch contractName {
220         case "LockWithPublicKey":
221                 if len(specArgs) != 3 {
222                         err = errors.WithDetailf(errBadContractArguments, "%s <rootPub> <path1> <path2> [flags]\n", usage)
223                         return
224                 }
225
226                 pubInfo := basePubInfo{
227                         rootPub: specArgs[0],
228                         path1:   specArgs[1],
229                         path2:   specArgs[2],
230                 }
231                 buildReqStr = addLockWithPublicKeyArg(baseArg, pubInfo)
232
233         case "LockWithMultiSig":
234                 if len(specArgs) != 6 {
235                         err = errors.WithDetailf(errBadContractArguments, "%s <rootPub1> <path11> <path12> <rootPub2> <path21> <path22> [flags]\n", usage)
236                         return
237                 }
238
239                 pubInfos := [2]basePubInfo{
240                         {
241                                 rootPub: specArgs[0],
242                                 path1:   specArgs[1],
243                                 path2:   specArgs[2],
244                         },
245                         {
246                                 rootPub: specArgs[3],
247                                 path1:   specArgs[4],
248                                 path2:   specArgs[5],
249                         },
250                 }
251                 buildReqStr = addLockWithMultiSigArg(baseArg, pubInfos)
252
253         case "LockWithPublicKeyHash":
254                 if len(specArgs) != 4 {
255                         err = errors.WithDetailf(errBadContractArguments, "%s <pubKey> <rootPub> <path1> <path2> [flags]\n", usage)
256                         return
257                 }
258
259                 pubkey := specArgs[0]
260                 pubInfo := basePubInfo{
261                         rootPub: specArgs[1],
262                         path1:   specArgs[2],
263                         path2:   specArgs[3],
264                 }
265                 buildReqStr = addLockWithPublicKeyHashArg(baseArg, pubInfo, pubkey)
266
267         case "RevealPreimage":
268                 if len(specArgs) != 1 {
269                         err = errors.WithDetailf(errBadContractArguments, "%s <value> [flags]\n", usage)
270                         return
271                 }
272
273                 value := specArgs[0]
274                 buildReqStr = addRevealPreimageArg(baseArg, value)
275
276         case "TradeOffer":
277                 switch {
278                 case len(specArgs) <= 0:
279                         err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> (<innerAccountID|alias> <innerAssetID|alias> <innerAmount> <innerProgram>) | (<rootPub> <path1> <path2>) [flags]\n", usage)
280                 case specArgs[0] == clauseTrade:
281                         if len(specArgs) != 5 {
282                                 err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> <innerAccountID|alias> <innerAssetID|alias> <innerAmount> <innerProgram> [flags]\n", usage)
283                                 return
284                         }
285
286                         inner := &innerContractArg{
287                                 innerAccountInfo: specArgs[1],
288                                 innerAssetInfo:   specArgs[2],
289                                 innerAmount:      specArgs[3],
290                                 innerProgram:     specArgs[4],
291                         }
292                         buildReqStr, err = addTradeOfferArg(baseArg, clauseTrade, inner, nil)
293
294                 case specArgs[0] == clauseCancel:
295                         if len(specArgs) != 4 {
296                                 err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> <rootPub> <path1> <path2> [flags]\n", usage)
297                                 return
298                         }
299
300                         pubInfo := &basePubInfo{
301                                 rootPub: specArgs[1],
302                                 path1:   specArgs[2],
303                                 path2:   specArgs[3],
304                         }
305                         buildReqStr, err = addTradeOfferArg(baseArg, clauseCancel, nil, pubInfo)
306
307                 case specArgs[0] == tradeOfferEnding:
308                         err = errors.WithDetailf(errBadContractArguments, "Clause ending was selected in contract %s, ending exit\n", contractName)
309                 default:
310                         err = errors.WithDetailf(errBadContractArguments, "selected clause [%s] error, contract %s's clause must in set [%s, %s, %s]\n",
311                                 specArgs[0], contractName, clauseTrade, clauseCancel, tradeOfferEnding)
312                 }
313
314         case "Escrow":
315                 switch {
316                 case len(specArgs) <= 0:
317                         err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> <rootPub> <path1> <path2> <controlProgram> [flags]\n", usage)
318                 case specArgs[0] == clauseApprove || specArgs[0] == clauseReject:
319                         if len(specArgs) != 5 {
320                                 err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> <rootPub> <path1> <path2> <controlProgram> [flags]\n", usage)
321                                 return
322                         }
323
324                         pubInfo := &basePubInfo{
325                                 rootPub: specArgs[1],
326                                 path1:   specArgs[2],
327                                 path2:   specArgs[3],
328                         }
329                         controlProgram := specArgs[4]
330                         buildReqStr, err = addEscrowArg(baseArg, specArgs[0], pubInfo, controlProgram)
331
332                 case specArgs[0] == escrowEnding:
333                         err = errors.WithDetailf(errBadContractArguments, "Clause ending was selected in contract %s, ending exit\n", contractName)
334                 default:
335                         err = errors.WithDetailf(errBadContractArguments, "selected clause [%s] error, contract %s's clause must in set [%s, %s, %s]\n",
336                                 specArgs[0], contractName, clauseApprove, clauseReject, escrowEnding)
337                 }
338
339         case "LoanCollateral":
340                 switch {
341                 case len(specArgs) <= 0:
342                         err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> (<innerAccountID|alias> <innerAssetID|alias> <innerAmount> <innerProgram> <controlProgram>) | (<controlProgram>) [flags]\n", usage)
343                 case specArgs[0] == clauseRepay:
344                         if len(specArgs) != 6 {
345                                 err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> <innerAccountID|alias> <innerAssetID|alias> <innerAmount> <innerProgram> <controlProgram> [flags]\n", usage)
346                                 return
347                         }
348
349                         inner := &innerContractArg{
350                                 innerAccountInfo: specArgs[1],
351                                 innerAssetInfo:   specArgs[2],
352                                 innerAmount:      specArgs[3],
353                                 innerProgram:     specArgs[4],
354                         }
355                         controlProgram := specArgs[5]
356                         buildReqStr, err = addLoanCollateralArg(baseArg, specArgs[0], inner, controlProgram)
357
358                 case specArgs[0] == clauseDefault:
359                         if len(specArgs) != 2 {
360                                 err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> <controlProgram> [flags]\n", usage)
361                                 return
362                         }
363
364                         controlProgram := specArgs[1]
365                         buildReqStr, err = addLoanCollateralArg(baseArg, specArgs[0], nil, controlProgram)
366
367                 case specArgs[0] == loanCollateralEnding:
368                         err = errors.WithDetailf(errBadContractArguments, "Clause ending was selected in contract %s, ending exit\n", contractName)
369                 default:
370                         err = errors.WithDetailf(errBadContractArguments, "selected clause [%s] error, contract %s's clause must in set:[%s, %s, %s]\n",
371                                 specArgs[0], contractName, clauseRepay, clauseDefault, loanCollateralEnding)
372                 }
373
374         case "CallOption":
375                 switch {
376                 case len(specArgs) <= 0:
377                         err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> (<innerAccountID|alias> <innerAssetID|alias> <innerAmount> <innerProgram> <rootPub> <path1> <path2>) | (<controlProgram>) [flags]\n", usage)
378                 case specArgs[0] == clauseExercise:
379                         if len(specArgs) != 8 {
380                                 err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> <innerAccountID|alias> <innerAssetID|alias> <innerAmount> <innerProgram> <rootPub> <path1> <path2> [flags]\n", usage)
381                                 return
382                         }
383
384                         inner := &innerContractArg{
385                                 innerAccountInfo: specArgs[1],
386                                 innerAssetInfo:   specArgs[2],
387                                 innerAmount:      specArgs[3],
388                                 innerProgram:     specArgs[4],
389                         }
390
391                         pubInfo := &basePubInfo{
392                                 rootPub: specArgs[5],
393                                 path1:   specArgs[6],
394                                 path2:   specArgs[7],
395                         }
396                         buildReqStr, err = addCallOptionArg(baseArg, specArgs[0], inner, pubInfo, "")
397
398                 case specArgs[0] == clauseExpire:
399                         if len(specArgs) != 2 {
400                                 err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> <controlProgram> [flags]\n", usage)
401                                 return
402                         }
403
404                         controlProgram := specArgs[1]
405                         buildReqStr, err = addCallOptionArg(baseArg, specArgs[0], nil, nil, controlProgram)
406
407                 case specArgs[0] == callOptionEnding:
408                         err = errors.WithDetailf(errBadContractArguments, "Clause ending was selected in contract %s, ending exit\n", contractName)
409                 default:
410                         err = errors.WithDetailf(errBadContractArguments, "selected clause [%s] error, contract %s's clause must in set:[%s, %s, %s]\n",
411                                 specArgs[0], contractName, clauseExercise, clauseExpire, callOptionEnding)
412                 }
413
414         default:
415                 err = errors.WithDetailf(errBadContractArguments, "Invalid contract template name [%s]", contractName)
416         }
417
418         return
419 }
420
421 func addLockWithPublicKeyArg(baseArg baseContractArg, pubInfo basePubInfo) (buildReqStr string) {
422         buildReqFmt := buildLockWithPublicKeyReqFmt
423         if baseArg.alias {
424                 buildReqFmt = buildLockWithPublicKeyReqFmtByAlias
425         }
426
427         buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, pubInfo.rootPub, pubInfo.path1, pubInfo.path2,
428                 baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
429
430         return
431 }
432
433 func addLockWithMultiSigArg(baseArg baseContractArg, pubInfos [2]basePubInfo) (buildReqStr string) {
434         buildReqFmt := buildLockWithMultiSigReqFmt
435         if baseArg.alias {
436                 buildReqFmt = buildLockWithMultiSigReqFmtByAlias
437         }
438
439         buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, pubInfos[0].rootPub, pubInfos[0].path1, pubInfos[0].path2,
440                 pubInfos[1].rootPub, pubInfos[1].path1, pubInfos[1].path2,
441                 baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
442
443         return
444 }
445
446 func addLockWithPublicKeyHashArg(baseArg baseContractArg, pubInfo basePubInfo, pubkey string) (buildReqStr string) {
447         buildReqFmt := buildLockWithPublicKeyHashReqFmt
448         if baseArg.alias {
449                 buildReqFmt = buildLockWithPublicKeyHashReqFmtByAlias
450         }
451
452         buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, pubkey, pubInfo.rootPub, pubInfo.path1, pubInfo.path2,
453                 baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
454
455         return
456 }
457
458 func addRevealPreimageArg(baseArg baseContractArg, value string) (buildReqStr string) {
459         buildReqFmt := buildCommonRecvReqFmt
460         if baseArg.alias {
461                 buildReqFmt = buildCommonRecvReqFmtByAlias
462         }
463
464         buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, value,
465                 baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
466
467         return
468 }
469
470 func addTradeOfferArg(baseArg baseContractArg, selector string, innerArg *innerContractArg, pubInfo *basePubInfo) (buildReqStr string, err error) {
471         switch selector {
472         case clauseTrade:
473                 if innerArg == nil {
474                         err = errors.New("Contract TradeOffer's clause trade argument is nil")
475                         return
476                 }
477
478                 buildReqFmt := buildTradeOfferClauseTradeReqFmt
479                 if baseArg.alias {
480                         buildReqFmt = buildTradeOfferClauseTradeReqFmtByAlias
481                 }
482
483                 buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, selector,
484                         innerArg.innerAssetInfo, innerArg.innerAmount, innerArg.innerProgram,
485                         innerArg.innerAssetInfo, innerArg.innerAmount, innerArg.innerAccountInfo,
486                         baseArg.btmGas, baseArg.accountInfo,
487                         baseArg.assetInfo, baseArg.amount, baseArg.program)
488
489         case clauseCancel:
490                 if pubInfo == nil {
491                         err = errors.New("Contract TradeOffer's clause cancel argument is nil")
492                         return
493                 }
494
495                 buildReqFmt := buildTradeOfferClauseCancelReqFmt
496                 if baseArg.alias {
497                         buildReqFmt = buildTradeOfferClauseCancelReqFmtByAlias
498                 }
499
500                 buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, pubInfo.rootPub, pubInfo.path1, pubInfo.path2, selector,
501                         baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
502
503         default:
504                 err = errors.New("Invalid contract clause selector")
505         }
506
507         return
508 }
509
510 func addEscrowArg(baseArg baseContractArg, selector string, pubInfo *basePubInfo, controlProgram string) (buildReqStr string, err error) {
511         switch selector {
512         case clauseApprove, clauseReject:
513                 if pubInfo == nil {
514                         err = errors.New("Contract Escrow's clause argument is nil")
515                         return
516                 }
517
518                 buildReqFmt := buildEscrowReqFmt
519                 if baseArg.alias {
520                         buildReqFmt = buildEscrowReqFmtByAlias
521                 }
522
523                 buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, pubInfo.rootPub, pubInfo.path1, pubInfo.path2, selector,
524                         baseArg.assetInfo, baseArg.amount, controlProgram, baseArg.btmGas, baseArg.accountInfo)
525
526         default:
527                 err = errors.New("Invalid contract clause selector")
528         }
529
530         return
531 }
532
533 func addLoanCollateralArg(baseArg baseContractArg, selector string, innerArg *innerContractArg, controlProgram string) (buildReqStr string, err error) {
534         switch selector {
535         case clauseRepay:
536                 if innerArg == nil {
537                         err = errors.New("Contract LoanCollateral's clause repay argument is nil")
538                         return
539                 }
540
541                 buildReqFmt := buildLoanCollateralClauseRepayReqFmt
542                 if baseArg.alias {
543                         buildReqFmt = buildLoanCollateralClauseRepayReqFmtByAlias
544                 }
545
546                 buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, selector,
547                         innerArg.innerAssetInfo, innerArg.innerAmount, innerArg.innerProgram,
548                         baseArg.assetInfo, baseArg.amount, controlProgram,
549                         innerArg.innerAssetInfo, innerArg.innerAmount, innerArg.innerAccountInfo,
550                         baseArg.btmGas, baseArg.accountInfo)
551
552         case clauseDefault:
553                 buildReqFmt := buildCommonRecvReqFmt
554                 if baseArg.alias {
555                         buildReqFmt = buildCommonRecvReqFmtByAlias
556                 }
557
558                 buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, selector,
559                         baseArg.assetInfo, baseArg.amount, controlProgram, baseArg.btmGas, baseArg.accountInfo)
560
561         default:
562                 err = errors.New("Invalid contract clause selector")
563         }
564
565         return
566 }
567
568 func addCallOptionArg(baseArg baseContractArg, selector string, innerArg *innerContractArg, pubInfo *basePubInfo, controlProgram string) (buildReqStr string, err error) {
569         switch selector {
570         case clauseExercise:
571                 if innerArg == nil || pubInfo == nil {
572                         err = errors.New("Contract CallOption's clause exercise argument is nil")
573                         return
574                 }
575
576                 buildReqFmt := buildCallOptionClauseExerciseReqFmt
577                 if baseArg.alias {
578                         buildReqFmt = buildCallOptionClauseExerciseReqFmtByAlias
579                 }
580
581                 buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, pubInfo.rootPub, pubInfo.path1, pubInfo.path2, selector,
582                         innerArg.innerAssetInfo, innerArg.innerAmount, innerArg.innerProgram,
583                         innerArg.innerAssetInfo, innerArg.innerAmount, innerArg.innerAccountInfo,
584                         baseArg.btmGas, baseArg.accountInfo,
585                         baseArg.assetInfo, baseArg.amount, baseArg.program)
586
587         case clauseExpire:
588                 buildReqFmt := buildCommonRecvReqFmt
589                 if baseArg.alias {
590                         buildReqFmt = buildCommonRecvReqFmtByAlias
591                 }
592
593                 buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, selector,
594                         baseArg.assetInfo, baseArg.amount, controlProgram, baseArg.btmGas, baseArg.accountInfo)
595
596         default:
597                 err = errors.New("Invalid contract clause selector")
598         }
599
600         return
601 }