// contract Escrow's clause
clauseApprove = "00000000"
- clauseReject = "1b000000"
- escrowEnding = "2a000000"
+ clauseReject = "1a000000"
+ escrowEnding = "28000000"
+
+ // contract LoanCollateral's clause
+ clauseRepay = "00000000"
+ clauseDefault = "1b000000"
+ loanCollateralEnding = "26000000"
+
+ // contract CallOption's clause
+ clauseExercise string = "00000000"
+ clauseExpire string = "20000000"
+ callOptionEnding string = "2c000000"
)
var (
errBadContractArguments = errors.New("bad contract arguments")
)
+// common receiver template, the clause takes only one parameter without Signature in the contract that contains only one clause,
+// 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"
+var buildCommonRecvReqFmt = `
+ {"actions": [
+ {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "data", "raw_data": {"value": "%s"}}]},
+ {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
+ {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount": %s, "account_id": "%s"}
+ ]}`
+
+var buildCommonRecvReqFmtByAlias = `
+ {"actions": [
+ {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "data", "raw_data": {"value": "%s"}}]},
+ {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
+ {"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"}
+ ]}`
+
// contract is LockWithPublicKey
var buildLockWithPublicKeyReqFmt = `
{"actions": [
{"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"}
]}`
-// contract is RevealPreimage
-var buildRevealPreimageReqFmt = `
- {"actions": [
- {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "data", "raw_data": {"value": "%s"}}]},
- {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
- {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount": %s, "account_id": "%s"}
- ]}`
-
-var buildRevealPreimageReqFmtByAlias = `
- {"actions": [
- {"type": "spend_account_unspent_output", "output_id": "%s", "arguments": [{"type": "data", "raw_data": {"value": "%s"}}]},
- {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
- {"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"}
- ]}`
-
// contract is TradeOffer's clause trade, the code of clause contains only two statement with "lock payment with program" and "unlock value"
var buildTradeOfferClauseTradeReqFmt = `
{"actions": [
{"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"}
]}`
+// 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"
+var buildLoanCollateralClauseRepayReqFmt = `
+ {"actions": [
+ {"type": "spend_account_unspent_output", "output_id":"%s", "arguments": [{"type": "data", "raw_data": {"value": "%s"}}]},
+ {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
+ {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
+ {"type": "spend_account", "asset_id": "%s", "amount": %s, "account_id": "%s"},
+ {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount":%s, "account_id": "%s"}
+ ]}`
+
+var buildLoanCollateralClauseRepayReqFmtByAlias = `
+ {"actions": [
+ {"type": "spend_account_unspent_output", "output_id":"%s", "arguments": [{"type": "data", "raw_data": {"value": "%s"}}]},
+ {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
+ {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
+ {"type": "spend_account", "asset_alias": "%s", "amount": %s, "account_alias": "%s"},
+ {"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"}
+ ]}`
+
+// contract is CallOption's clause exercise, the code of clause contains only two statement with "lock payment with program" and "unlock value"
+var buildCallOptionClauseExerciseReqFmt = `
+ {"actions": [
+ {"type": "spend_account_unspent_output", "output_id":"%s", "arguments": [{"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}},
+ {"type": "data", "raw_data": {"value": "%s"}}]},
+ {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"},
+ {"type": "spend_account", "asset_id": "%s", "amount": %s, "account_id": "%s"},
+ {"type": "spend_account", "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "amount":%s, "account_id": "%s"},
+ {"type": "control_program", "asset_id": "%s", "amount": %s, "control_program": "%s"}
+ ]}`
+
+var buildCallOptionClauseExerciseReqFmtByAlias = `
+ {"actions": [
+ {"type": "spend_account_unspent_output", "output_id":"%s", "arguments": [{"type": "raw_tx_signature", "raw_data": {"xpub": "%s", "derivation_path": ["%s", "%s"]}},
+ {"type": "data", "raw_data": {"value": "%s"}}]},
+ {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"},
+ {"type": "spend_account", "asset_alias": "%s", "amount": %s, "account_alias": "%s"},
+ {"type": "spend_account", "asset_alias": "BTM", "amount": %s, "account_alias": "%s"},
+ {"type": "control_program", "asset_alias": "%s", "amount": %s, "control_program": "%s"}
+ ]}`
+
// contract arguments
type baseContractArg struct {
accountInfo string
specArgs[0], contractName, clauseApprove, clauseReject, escrowEnding)
}
+ case "LoanCollateral":
+ switch {
+ case len(specArgs) <= 0:
+ err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> (<innerAccountID|alias> <innerAssetID|alias> <innerAmount> <innerProgram> <controlProgram>) | (<controlProgram>) [flags]\n", usage)
+ case specArgs[0] == clauseRepay:
+ if len(specArgs) != 6 {
+ err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> <innerAccountID|alias> <innerAssetID|alias> <innerAmount> <innerProgram> <controlProgram> [flags]\n", usage)
+ return
+ }
+
+ inner := &innerContractArg{
+ innerAccountInfo: specArgs[1],
+ innerAssetInfo: specArgs[2],
+ innerAmount: specArgs[3],
+ innerProgram: specArgs[4],
+ }
+ controlProgram := specArgs[5]
+ buildReqStr, err = addLoanCollateralArg(baseArg, specArgs[0], inner, controlProgram)
+
+ case specArgs[0] == clauseDefault:
+ if len(specArgs) != 2 {
+ err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> <controlProgram> [flags]\n", usage)
+ return
+ }
+
+ controlProgram := specArgs[1]
+ buildReqStr, err = addLoanCollateralArg(baseArg, specArgs[0], nil, controlProgram)
+
+ case specArgs[0] == loanCollateralEnding:
+ err = errors.WithDetailf(errBadContractArguments, "Clause ending was selected in contract %s, ending exit\n", contractName)
+ default:
+ err = errors.WithDetailf(errBadContractArguments, "selected clause [%s] error, contract %s's clause must in set:[%s, %s, %s]\n",
+ specArgs[0], contractName, clauseRepay, clauseDefault, loanCollateralEnding)
+ }
+
+ case "CallOption":
+ switch {
+ case len(specArgs) <= 0:
+ err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> (<innerAccountID|alias> <innerAssetID|alias> <innerAmount> <innerProgram> <rootPub> <path1> <path2>) | (<controlProgram>) [flags]\n", usage)
+ case specArgs[0] == clauseExercise:
+ if len(specArgs) != 8 {
+ err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> <innerAccountID|alias> <innerAssetID|alias> <innerAmount> <innerProgram> <rootPub> <path1> <path2> [flags]\n", usage)
+ return
+ }
+
+ inner := &innerContractArg{
+ innerAccountInfo: specArgs[1],
+ innerAssetInfo: specArgs[2],
+ innerAmount: specArgs[3],
+ innerProgram: specArgs[4],
+ }
+
+ pubInfo := &basePubInfo{
+ rootPub: specArgs[5],
+ path1: specArgs[6],
+ path2: specArgs[7],
+ }
+ buildReqStr, err = addCallOptionArg(baseArg, specArgs[0], inner, pubInfo, "")
+
+ case specArgs[0] == clauseExpire:
+ if len(specArgs) != 2 {
+ err = errors.WithDetailf(errBadContractArguments, "%s <clauseSelector> <controlProgram> [flags]\n", usage)
+ return
+ }
+
+ controlProgram := specArgs[1]
+ buildReqStr, err = addCallOptionArg(baseArg, specArgs[0], nil, nil, controlProgram)
+
+ case specArgs[0] == callOptionEnding:
+ err = errors.WithDetailf(errBadContractArguments, "Clause ending was selected in contract %s, ending exit\n", contractName)
+ default:
+ err = errors.WithDetailf(errBadContractArguments, "selected clause [%s] error, contract %s's clause must in set:[%s, %s, %s]\n",
+ specArgs[0], contractName, clauseExercise, clauseExpire, callOptionEnding)
+ }
+
default:
err = errors.WithDetailf(errBadContractArguments, "Invalid contract template name [%s]", contractName)
}
}
func addLockWithPublicKeyArg(baseArg baseContractArg, pubInfo basePubInfo) (buildReqStr string) {
- buildReqStr = fmt.Sprintf(buildLockWithPublicKeyReqFmt, baseArg.outputID, pubInfo.rootPub, pubInfo.path1, pubInfo.path2,
- baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
+ buildReqFmt := buildLockWithPublicKeyReqFmt
if baseArg.alias {
- buildReqStr = fmt.Sprintf(buildLockWithPublicKeyReqFmtByAlias, baseArg.outputID, pubInfo.rootPub, pubInfo.path1, pubInfo.path2,
- baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
+ buildReqFmt = buildLockWithPublicKeyReqFmtByAlias
}
+ buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, pubInfo.rootPub, pubInfo.path1, pubInfo.path2,
+ baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
+
return
}
func addLockWithMultiSigArg(baseArg baseContractArg, pubInfos [2]basePubInfo) (buildReqStr string) {
- buildReqStr = fmt.Sprintf(buildLockWithMultiSigReqFmt, baseArg.outputID, pubInfos[0].rootPub, pubInfos[0].path1, pubInfos[0].path2,
- pubInfos[1].rootPub, pubInfos[1].path1, pubInfos[1].path2,
- baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
+ buildReqFmt := buildLockWithMultiSigReqFmt
if baseArg.alias {
- buildReqStr = fmt.Sprintf(buildLockWithMultiSigReqFmtByAlias, baseArg.outputID, pubInfos[0].rootPub, pubInfos[0].path1, pubInfos[0].path2,
- pubInfos[1].rootPub, pubInfos[1].path1, pubInfos[1].path2,
- baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
+ buildReqFmt = buildLockWithMultiSigReqFmtByAlias
}
+ buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, pubInfos[0].rootPub, pubInfos[0].path1, pubInfos[0].path2,
+ pubInfos[1].rootPub, pubInfos[1].path1, pubInfos[1].path2,
+ baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
+
return
}
func addLockWithPublicKeyHashArg(baseArg baseContractArg, pubInfo basePubInfo, pubkey string) (buildReqStr string) {
- buildReqStr = fmt.Sprintf(buildLockWithPublicKeyHashReqFmt, baseArg.outputID, pubkey, pubInfo.rootPub, pubInfo.path1, pubInfo.path2,
- baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
- if alias {
- buildReqStr = fmt.Sprintf(buildLockWithPublicKeyHashReqFmtByAlias, baseArg.outputID, pubkey, pubInfo.rootPub, pubInfo.path1, pubInfo.path2,
- baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
+ buildReqFmt := buildLockWithPublicKeyHashReqFmt
+ if baseArg.alias {
+ buildReqFmt = buildLockWithPublicKeyHashReqFmtByAlias
}
+ buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, pubkey, pubInfo.rootPub, pubInfo.path1, pubInfo.path2,
+ baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
+
return
}
func addRevealPreimageArg(baseArg baseContractArg, value string) (buildReqStr string) {
- buildReqStr = fmt.Sprintf(buildRevealPreimageReqFmt, baseArg.outputID, value,
- baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
+ buildReqFmt := buildCommonRecvReqFmt
if baseArg.alias {
- buildReqStr = fmt.Sprintf(buildRevealPreimageReqFmtByAlias, baseArg.outputID, value,
- baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
+ buildReqFmt = buildCommonRecvReqFmtByAlias
}
+ buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, value,
+ baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
+
return
}
return
}
- buildReqStr = fmt.Sprintf(buildTradeOfferClauseTradeReqFmt, baseArg.outputID, clauseTrade,
+ buildReqFmt := buildTradeOfferClauseTradeReqFmt
+ if baseArg.alias {
+ buildReqFmt = buildTradeOfferClauseTradeReqFmtByAlias
+ }
+
+ buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, selector,
innerArg.innerAssetInfo, innerArg.innerAmount, innerArg.innerProgram,
innerArg.innerAssetInfo, innerArg.innerAmount, innerArg.innerAccountInfo,
baseArg.btmGas, baseArg.accountInfo,
baseArg.assetInfo, baseArg.amount, baseArg.program)
- if baseArg.alias {
- buildReqStr = fmt.Sprintf(buildTradeOfferClauseTradeReqFmtByAlias, baseArg.outputID, clauseTrade,
- innerArg.innerAssetInfo, innerArg.innerAmount, innerArg.innerProgram,
- innerArg.innerAssetInfo, innerArg.innerAmount, innerArg.innerAccountInfo,
- baseArg.btmGas, baseArg.accountInfo,
- baseArg.assetInfo, baseArg.amount, baseArg.program)
- }
case clauseCancel:
if pubInfo == nil {
return
}
- buildReqStr = fmt.Sprintf(buildTradeOfferClauseCancelReqFmt, baseArg.outputID, pubInfo.rootPub, pubInfo.path1, pubInfo.path2, clauseCancel,
- baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
+ buildReqFmt := buildTradeOfferClauseCancelReqFmt
if baseArg.alias {
- buildReqStr = fmt.Sprintf(buildTradeOfferClauseCancelReqFmtByAlias, baseArg.outputID, pubInfo.rootPub, pubInfo.path1, pubInfo.path2, clauseCancel,
- baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
+ buildReqFmt = buildTradeOfferClauseCancelReqFmtByAlias
}
+ buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, pubInfo.rootPub, pubInfo.path1, pubInfo.path2, selector,
+ baseArg.assetInfo, baseArg.amount, baseArg.program, baseArg.btmGas, baseArg.accountInfo)
+
default:
err = errors.New("Invalid contract clause selector")
}
return
}
- buildReqStr = fmt.Sprintf(buildEscrowReqFmt, baseArg.outputID, pubInfo.rootPub, pubInfo.path1, pubInfo.path2, selector,
+ buildReqFmt := buildEscrowReqFmt
+ if baseArg.alias {
+ buildReqFmt = buildEscrowReqFmtByAlias
+ }
+
+ buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, pubInfo.rootPub, pubInfo.path1, pubInfo.path2, selector,
+ baseArg.assetInfo, baseArg.amount, controlProgram, baseArg.btmGas, baseArg.accountInfo)
+
+ default:
+ err = errors.New("Invalid contract clause selector")
+ }
+
+ return
+}
+
+func addLoanCollateralArg(baseArg baseContractArg, selector string, innerArg *innerContractArg, controlProgram string) (buildReqStr string, err error) {
+ switch selector {
+ case clauseRepay:
+ if innerArg == nil {
+ err = errors.New("Contract LoanCollateral's clause repay argument is nil")
+ return
+ }
+
+ buildReqFmt := buildLoanCollateralClauseRepayReqFmt
+ if baseArg.alias {
+ buildReqFmt = buildLoanCollateralClauseRepayReqFmtByAlias
+ }
+
+ buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, selector,
+ innerArg.innerAssetInfo, innerArg.innerAmount, innerArg.innerProgram,
+ baseArg.assetInfo, baseArg.amount, controlProgram,
+ innerArg.innerAssetInfo, innerArg.innerAmount, innerArg.innerAccountInfo,
+ baseArg.btmGas, baseArg.accountInfo)
+
+ case clauseDefault:
+ buildReqFmt := buildCommonRecvReqFmt
+ if baseArg.alias {
+ buildReqFmt = buildCommonRecvReqFmtByAlias
+ }
+
+ buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, selector,
baseArg.assetInfo, baseArg.amount, controlProgram, baseArg.btmGas, baseArg.accountInfo)
+
+ default:
+ err = errors.New("Invalid contract clause selector")
+ }
+
+ return
+}
+
+func addCallOptionArg(baseArg baseContractArg, selector string, innerArg *innerContractArg, pubInfo *basePubInfo, controlProgram string) (buildReqStr string, err error) {
+ switch selector {
+ case clauseExercise:
+ if innerArg == nil || pubInfo == nil {
+ err = errors.New("Contract CallOption's clause exercise argument is nil")
+ return
+ }
+
+ buildReqFmt := buildCallOptionClauseExerciseReqFmt
if baseArg.alias {
- buildReqStr = fmt.Sprintf(buildEscrowReqFmtByAlias, baseArg.outputID, pubInfo.rootPub, pubInfo.path1, pubInfo.path2, selector,
- baseArg.assetInfo, baseArg.amount, controlProgram, baseArg.btmGas, baseArg.accountInfo)
+ buildReqFmt = buildCallOptionClauseExerciseReqFmtByAlias
}
+ buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, pubInfo.rootPub, pubInfo.path1, pubInfo.path2, selector,
+ innerArg.innerAssetInfo, innerArg.innerAmount, innerArg.innerProgram,
+ innerArg.innerAssetInfo, innerArg.innerAmount, innerArg.innerAccountInfo,
+ baseArg.btmGas, baseArg.accountInfo,
+ baseArg.assetInfo, baseArg.amount, baseArg.program)
+
+ case clauseExpire:
+ buildReqFmt := buildCommonRecvReqFmt
+ if baseArg.alias {
+ buildReqFmt = buildCommonRecvReqFmtByAlias
+ }
+
+ buildReqStr = fmt.Sprintf(buildReqFmt, baseArg.outputID, selector,
+ baseArg.assetInfo, baseArg.amount, controlProgram, baseArg.btmGas, baseArg.accountInfo)
+
default:
err = errors.New("Invalid contract clause selector")
}