OSDN Git Service

delete commnets
[bytom/shuttle.git] / swap / contract.go
1 package swap
2
3 import (
4         "encoding/json"
5         "errors"
6         "fmt"
7         "strconv"
8 )
9
10 var (
11         errFailedGetContractUTXOID = errors.New("Failed to get contract UTXO ID")
12 )
13
14 type Account struct {
15         AccountID    string `json:"id"`
16         AccountAlias string `json:"alias"`
17 }
18
19 type AccountsResponse struct {
20         Status string    `json:"status"`
21         Data   []Account `json:"data"`
22 }
23
24 func ListAccounts() []Account {
25         data := []byte(`{}`)
26         body := request(listAccountsURL, data)
27
28         accountsResp := new(AccountsResponse)
29         if err := json.Unmarshal(body, accountsResp); err != nil {
30                 fmt.Println(err)
31         }
32         return accountsResp.Data
33 }
34
35 type Address struct {
36         AccountAlias   string `json:"account_alias"`
37         AccountID      string `json:"account_id"`
38         Address        string `json:"address"`
39         ControlProgram string `json:"control_program"`
40         Change         bool   `json:"change"`
41         KeyIndex       uint64 `json:"key_index"`
42 }
43
44 type AddressesResponse struct {
45         Status string    `json:"status"`
46         Data   []Address `json:"data"`
47 }
48
49 func ListAddresses(accountAlias string) []Address {
50         data := []byte(`{"account_alias": "` + accountAlias + `"}`)
51         body := request(listAddressesURL, data)
52
53         addresses := new(AddressesResponse)
54         if err := json.Unmarshal(body, addresses); err != nil {
55                 fmt.Println(err)
56         }
57         return addresses.Data
58 }
59
60 type Balance struct {
61         AccountID string `json:"account_id"`
62         Amount    uint64 `json:"amount"`
63 }
64
65 type BalancesResponse struct {
66         Status string    `json:"status"`
67         Data   []Balance `json:"data"`
68 }
69
70 func ListBalances(accountAlias string) []Balance {
71         data := []byte(`{"account_alias": "` + accountAlias + `"}`)
72         body := request(listBalancesURL, data)
73
74         balancesResp := new(BalancesResponse)
75         if err := json.Unmarshal(body, balancesResp); err != nil {
76                 fmt.Println(err)
77         }
78         return balancesResp.Data
79 }
80
81 type PubkeyInfo struct {
82         Pubkey string   `json:"pubkey"`
83         Path   []string `json:"derivation_path"`
84 }
85
86 type KeyInfo struct {
87         XPubkey     string       `json:"root_xpub"`
88         PubkeyInfos []PubkeyInfo `json:"pubkey_infos"`
89 }
90
91 type PubkeysResponse struct {
92         Status string  `json:"status"`
93         Data   KeyInfo `json:"data"`
94 }
95
96 func ListPubkeys(accountAlias string) KeyInfo {
97         data := []byte(`{"account_alias": "` + accountAlias + `"}`)
98         body := request(listPubkeysURL, data)
99
100         pubkeysResp := new(PubkeysResponse)
101         if err := json.Unmarshal(body, pubkeysResp); err != nil {
102                 fmt.Println(err)
103         }
104         return pubkeysResp.Data
105 }
106
107 type ContractInfo struct {
108         Program string `json:"program"`
109 }
110
111 type ContractResponse struct {
112         Status string       `json:"status"`
113         Data   ContractInfo `json:"data"`
114 }
115
116 func CompileLockContract(assetRequested, seller, cancelKey string, amountRequested uint64) ContractInfo {
117         data := []byte(`{
118                 "contract":"contract TradeOffer(assetRequested: Asset, amountRequested: Amount, seller: Program, cancelKey: PublicKey) locks valueAmount of valueAsset { clause trade() { lock amountRequested of assetRequested with seller unlock valueAmount of valueAsset } clause cancel(sellerSig: Signature) { verify checkTxSig(cancelKey, sellerSig) unlock valueAmount of valueAsset}}",
119                 "args":[
120                         {
121                                 "string":"` + assetRequested + `"
122                         },
123                         {
124                                 "integer":` + strconv.FormatUint(amountRequested, 10) + `
125                         },
126                         {
127                                 "string":"` + seller + `"
128                         },
129                         {
130                                 "string":"` + cancelKey + `"
131                         }
132                 ]
133         }`)
134         body := request(compileURL, data)
135
136         contract := new(ContractResponse)
137         if err := json.Unmarshal(body, contract); err != nil {
138                 fmt.Println(err)
139         }
140         return contract.Data
141 }
142
143 // BuildLockTransaction build locked contract transaction.
144 func BuildLockTransaction(accountIDLocked, assetIDLocked, contractControlProgram string, amountLocked, txFee uint64) []byte {
145         data := []byte(`{
146                 "actions":[
147                         {
148                                 "account_id":"` + accountIDLocked + `",
149                                 "amount":` + strconv.FormatUint(amountLocked, 10) + `,
150                                 "asset_id":"` + assetIDLocked + `",
151                                 "type":"spend_account"
152                         },
153                         {
154                                 "amount":` + strconv.FormatUint(amountLocked, 10) + `,
155                                 "asset_id":"` + assetIDLocked + `",
156                                 "control_program":"` + contractControlProgram + `",
157                                 "type":"control_program"
158                         },
159                         {
160                                 "account_id":"` + accountIDLocked + `",
161                                 "amount":` + strconv.FormatUint(txFee, 10) + `,
162                                 "asset_id":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
163                                 "type":"spend_account"
164                         }
165                 ],
166                 "ttl":0,
167                 "base_transaction":null
168         }`)
169         body := request(buildTransactionURL, data)
170         return body
171 }
172
173 type SignedTransaction struct {
174         RawTransaction string `json:"raw_transaction"`
175 }
176
177 type TransactionData struct {
178         SignedTransaction SignedTransaction `json:"transaction"`
179 }
180
181 type signedTransactionResponse struct {
182         Status string          `json:"status"`
183         Data   TransactionData `json:"data"`
184 }
185
186 // SignTransaction sign built contract transaction.
187 func SignTransaction(password, transaction string) string {
188         data := []byte(`{
189                 "password": "` + password + `",
190                 "transaction` + transaction[25:])
191         body := request(signTransactionURL, data)
192
193         signedTransaction := new(signedTransactionResponse)
194         if err := json.Unmarshal(body, signedTransaction); err != nil {
195                 fmt.Println(err)
196         }
197         return signedTransaction.Data.SignedTransaction.RawTransaction
198 }
199
200 type TransactionID struct {
201         TxID string `json:"tx_id"`
202 }
203
204 type submitedTransactionResponse struct {
205         Status string        `json:"status"`
206         Data   TransactionID `json:"data"`
207 }
208
209 // SubmitTransaction submit raw singed contract transaction.
210 func SubmitTransaction(rawTransaction string) string {
211         data := []byte(`{"raw_transaction": "` + rawTransaction + `"}`)
212         body := request(submitTransactionURL, data)
213
214         submitedTransaction := new(submitedTransactionResponse)
215         if err := json.Unmarshal(body, submitedTransaction); err != nil {
216                 fmt.Println(err)
217         }
218         return submitedTransaction.Data.TxID
219 }
220
221 type TransactionOutput struct {
222         TransactionOutputID string `json:"id"`
223         ControlProgram      string `json:"control_program"`
224 }
225
226 type GotTransactionInfo struct {
227         TransactionOutputs []TransactionOutput `json:"outputs"`
228 }
229
230 type getTransactionResponse struct {
231         Status string             `json:"status"`
232         Data   GotTransactionInfo `json:"data"`
233 }
234
235 // GetContractUTXOID get contract UTXO ID by transaction ID and contract control program.
236 func GetContractUTXOID(transactionID, controlProgram string) (string, error) {
237         data := []byte(`{"tx_id":"` + transactionID + `"}`)
238         body := request(getTransactionURL, data)
239
240         getTransactionResponse := new(getTransactionResponse)
241         if err := json.Unmarshal(body, getTransactionResponse); err != nil {
242                 fmt.Println(err)
243         }
244
245         for _, v := range getTransactionResponse.Data.TransactionOutputs {
246                 if v.ControlProgram == controlProgram {
247                         return v.TransactionOutputID, nil
248                 }
249         }
250
251         return "", errFailedGetContractUTXOID
252 }
253
254 // BuildUnlockContractTransaction build unlocked contract transaction.
255 func BuildUnlockContractTransaction(accountIDUnlocked, contractUTXOID, seller, assetIDLocked, assetRequested, buyerContolProgram string, amountRequested, amountLocked, txFee uint64) []byte {
256         data := []byte(`{
257                 "actions":[
258                         {
259                                 "type":"spend_account_unspent_output",
260                                 "arguments":[
261                                         {
262                                                 "type":"integer",
263                                                 "raw_data":{
264                                                         "value":0
265                                                 }
266                                         }
267                                 ],
268                                 "use_unconfirmed":true,
269                                 "output_id":"` + contractUTXOID + `"
270                         },
271                         {
272                                 "amount":` + strconv.FormatUint(amountRequested, 10) + `,
273                                 "asset_id":"` + assetRequested + `",
274                                 "control_program":"` + seller + `",
275                                 "type":"control_program"
276                         },
277                         {
278                                 "account_id":"` + accountIDUnlocked + `",
279                                 "amount":` + strconv.FormatUint(amountRequested, 10) + `,
280                                 "asset_id":"` + assetRequested + `",
281                                 "use_unconfirmed":true,
282                                 "type":"spend_account"
283                         },
284                         {
285                                 "account_id":"` + accountIDUnlocked + `",
286                                 "amount":` + strconv.FormatUint(txFee, 10) + `,
287                                 "asset_id":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
288                                 "use_unconfirmed":true,
289                                 "type":"spend_account"
290                         },
291                         {
292                                 "amount":` + strconv.FormatUint(amountLocked, 10) + `,
293                                 "asset_id":"` + assetIDLocked + `",
294                                 "control_program":"` + buyerContolProgram + `",
295                                 "type":"control_program"
296                         }
297                 ],
298                 "ttl":0,
299                 "base_transaction":null
300         }`)
301         body := request(buildTransactionURL, data)
302         return body
303 }