10 errFailedGetSignData = errors.New("Failed to get sign data")
13 type HTLCAccount struct {
20 type HTLCContractArgs struct {
21 SenderPublicKey string
22 RecipientPublicKey string
27 type compileLockHTLCContractResponse struct {
28 Program string `json:"program"`
31 var compileLockHTLCContractPayload = `{
32 "contract":"contract HTLC(sender: PublicKey, recipient: PublicKey, blockHeight: Integer, hash: Hash) locks valueAmount of valueAsset { clause complete(preimage: String, sig: Signature) {verify sha256(preimage) == hash verify checkTxSig(recipient, sig) unlock valueAmount of valueAsset} clause cancel(sig: Signature) {verify above(blockHeight) verify checkTxSig(sender, sig) unlock valueAmount of valueAsset}}",
49 func compileLockHTLCContract(contractArgs HTLCContractArgs) (string, error) {
50 payload := []byte(fmt.Sprintf(
51 compileLockHTLCContractPayload,
52 contractArgs.SenderPublicKey,
53 contractArgs.RecipientPublicKey,
54 strconv.FormatUint(contractArgs.BlockHeight, 10),
57 res := new(compileLockHTLCContractResponse)
58 if err := request(compileURL, payload, res); err != nil {
61 return res.Program, nil
64 var buildLockHTLCContractTransactionPayload = `{
70 "use_unconfirmed":true,
71 "type": "spend_account"
76 "control_program": "%s",
77 "type": "control_program"
82 "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
83 "use_unconfirmed":true,
84 "type": "spend_account"
88 "base_transaction": null
91 func buildLockHTLCContractTransaction(account HTLCAccount, contractValue AssetAmount, contractControlProgram string) (interface{}, error) {
92 payload := []byte(fmt.Sprintf(
93 buildLockHTLCContractTransactionPayload,
95 strconv.FormatUint(contractValue.Amount, 10),
97 strconv.FormatUint(contractValue.Amount, 10),
99 contractControlProgram,
101 strconv.FormatUint(account.TxFee, 10),
103 res := new(interface{})
104 if err := request(buildTransactionURL, payload, res); err != nil {
110 // type SigningInstruction struct {
111 // Position uint64 `json:"position"`
112 // WitnessComponents []interface{} `json:"witness_components"`
115 type buildUnlockHTLCContractTransactionResponse struct {
116 RawTransaction string `json:"raw_transaction"`
117 SigningInstructions []interface{} `json:"signing_instructions"`
118 TxFee uint64 `json:"fee"`
119 AllowAdditionalActions bool `json:"allow_additional_actions"`
122 var buildUnlockHTLCContractTransactionPayload = `{
125 "type": "spend_account_unspent_output",
126 "use_unconfirmed":true,
133 "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
134 "use_unconfirmed":true,
135 "type": "spend_account"
140 "control_program": "%s",
141 "type": "control_program"
145 "base_transaction": null
148 func buildUnlockHTLCContractTransaction(account HTLCAccount, contractUTXOID string, contractValue AssetAmount) (*buildUnlockHTLCContractTransactionResponse, error) {
149 payload := []byte(fmt.Sprintf(
150 buildUnlockHTLCContractTransactionPayload,
153 strconv.FormatUint(account.TxFee, 10),
154 strconv.FormatUint(contractValue.Amount, 10),
158 res := new(buildUnlockHTLCContractTransactionResponse)
159 if err := request(buildTransactionURL, payload, res); err != nil {
162 // signingInst, err := json.Marshal(res.SigningInstructions[1])
166 // fmt.Println("signingInst:", string(signingInst))
170 type TransactionInput struct {
171 AssetID string `json:"asset_id"`
172 ControlProgram string `json:"control_program"`
173 SignData string `json:"sign_data"`
176 type decodeRawTransactionResponse struct {
177 TransactionInputs []TransactionInput `json:"inputs"`
180 var decodeRawTransactionPayload = `{
181 "raw_transaction":"%s"
184 func decodeRawTransaction(rawTransaction string, contractValue AssetAmount) (string, string, error) {
185 payload := []byte(fmt.Sprintf(
186 decodeRawTransactionPayload,
189 res := new(decodeRawTransactionResponse)
190 if err := request(decodeRawTransactionURL, payload, res); err != nil {
194 for _, v := range res.TransactionInputs {
195 if v.AssetID == contractValue.Asset {
196 return v.ControlProgram, v.SignData, nil
199 return "", "", errFailedGetSignData
202 type signUnlockHTLCContractTransactionRequest struct {
203 Password string `json:"password"`
204 Transaction buildUnlockHTLCContractTransactionResponse `json:"transaction"`
207 var signUnlockHTLCContractTransactionPayload = `{
210 "raw_transaction": "%s",
211 "signing_instructions": [
214 "witness_components": [
232 "allow_additional_actions": false
236 // func signUnlockHTLCContractTransaction(account HTLCAccount, preimage, recipientSig, rawTransaction string) (string, error) {
237 // rawSigningInstruction, err := json.Marshal(buildTxResp.SigningInstructions[1])
242 // fmt.Println("rawSigningInstruction string:", string(rawSigningInstruction))
244 // payload := []byte(fmt.Sprintf(
245 // signUnlockHTLCContractTransactionPayload,
250 // string(rawSigningInstruction),
251 // strconv.FormatUint(account.TxFee, 10),
253 // res := new(signTransactionResponse)
254 // if err := request(signTransactionURL, payload, res); err != nil {
258 // return res.Tx.RawTransaction, nil
261 // DeployHTLCContract deploy HTLC contract.
262 func DeployHTLCContract(account HTLCAccount, contractValue AssetAmount, contractArgs HTLCContractArgs) (string, error) {
263 // compile locked HTLC cotnract
264 HTLCContractControlProgram, err := compileLockHTLCContract(contractArgs)
269 // build locked HTLC contract
270 txLocked, err := buildLockHTLCContractTransaction(account, contractValue, HTLCContractControlProgram)
275 // sign locked HTLC contract transaction
276 signedTransaction, err := signTransaction(account.Password, txLocked)
281 // submit signed HTLC contract transaction
282 txID, err := submitTransaction(signedTransaction)
287 // get HTLC contract output ID
288 contractUTXOID, err := getContractUTXOID(txID, HTLCContractControlProgram)
292 return contractUTXOID, nil
295 // // CallHTLCContract call HTLC contract.
296 // func CallHTLCContract(account HTLCAccount, contractUTXOID, preimage, recipientSig string, contractArgs HTLCContractArgs, contractValue AssetAmount) (string, string, string, error) {
297 // // build unlocked contract transaction
298 // buildTxResp, err := buildUnlockHTLCContractTransaction(account, contractUTXOID, contractValue)
300 // return "", "", "", err
303 // fmt.Println("raw transaction:", buildTxResp.RawTransaction)
304 // contractControlProgram, signData, err := decodeRawTransaction(buildTxResp.RawTransaction, contractValue)
308 // fmt.Println("contractControlProgram:", contractControlProgram)
309 // fmt.Println("signData:", signData)
311 // return buildTxResp.RawTransaction, contractControlProgram, signData, nil
313 // // // sign unlocked HTLC contract transaction
314 // // signedTransaction, err := signUnlockHTLCContractTransaction(account, preimage, recipientSig, *buildTxResp)
315 // // if err != nil {
316 // // return "", "", err
319 // // // submit signed HTLC contract transaction
320 // // txID, err := submitTransaction(signedTransaction)
321 // // if err != nil {
322 // // return "", "", err
325 // // return "", txID, nil