Skip to content

Commit 83dcd9a

Browse files
committed
swaps: CreateRefundTransaction
1 parent 37d1148 commit 83dcd9a

File tree

1 file changed

+131
-2
lines changed

1 file changed

+131
-2
lines changed

mobile/swaps.go

Lines changed: 131 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"bytes"
55
"encoding/hex"
66
"fmt"
7-
"io/ioutil"
7+
"io"
88
"net/http"
99

1010
"github.com/BoltzExchange/boltz-client/boltz"
@@ -174,7 +174,7 @@ func CreateReverseClaimTransaction(endpoint string, id string, claimLeaf string,
174174
defer resp.Body.Close()
175175

176176
// Read response
177-
body, err := ioutil.ReadAll(resp.Body)
177+
body, err := io.ReadAll(resp.Body)
178178
if err != nil {
179179
return fmt.Errorf("failed to read response body: %v", err)
180180
}
@@ -187,3 +187,132 @@ func CreateReverseClaimTransaction(endpoint string, id string, claimLeaf string,
187187

188188
return nil
189189
}
190+
191+
func CreateRefundTransaction(endpoint string, id string, claimLeaf string, refundLeaf string, transactionHex string, privateKey string, servicePubKey string, feeRate int32, timeoutBlockHeight int32, destinationAddress string, lockupAddress string, isTestnet bool) (string, error) {
192+
var toCurrency = boltz.CurrencyBtc
193+
194+
var network *boltz.Network
195+
if isTestnet {
196+
network = boltz.TestNet
197+
} else {
198+
network = boltz.MainNet
199+
}
200+
201+
boltzApi := &boltz.Api{URL: endpoint}
202+
203+
// Decode the hex string to bytes
204+
privKeyBytes, err := hex.DecodeString(privateKey)
205+
if err != nil {
206+
fmt.Printf("Failed to decode hex string: %v\n", err)
207+
return "", fmt.Errorf("failed to decode hex string: %v", err)
208+
}
209+
210+
// Create the private key using btcec
211+
keys, _ := btcec.PrivKeyFromBytes(privKeyBytes)
212+
213+
// Decode the hex string to bytes
214+
servicePubKeyBytes, err := hex.DecodeString(servicePubKey)
215+
if err != nil {
216+
return "", fmt.Errorf("error decoding service public key hex: %s", err)
217+
}
218+
219+
// Parse the public key
220+
servicePubKeyFormatted, err := secp256k1.ParsePubKey(servicePubKeyBytes)
221+
if err != nil {
222+
return "", fmt.Errorf("error parsing service public key %s", err)
223+
}
224+
225+
// Creating the swapTree
226+
swapTree := &boltz.SwapTree{
227+
ClaimLeaf: leaf(claimLeaf),
228+
RefundLeaf: leaf(refundLeaf),
229+
}
230+
fmt.Println("SwapTree created successfully")
231+
232+
if err := swapTree.Init(false, false, keys, servicePubKeyFormatted); err != nil {
233+
return "", fmt.Errorf("error initializing swap tree %s", err)
234+
}
235+
236+
satPerVbyte := float64(feeRate)
237+
238+
lockupTransaction, err := boltz.NewTxFromHex(toCurrency, transactionHex, nil)
239+
if err != nil {
240+
return "", fmt.Errorf("error constructing lockup tx %v", err)
241+
}
242+
fmt.Println("Lockup transaction constructed successfully")
243+
244+
vout, _, err := lockupTransaction.FindVout(network, lockupAddress)
245+
if err != nil {
246+
return "", fmt.Errorf("error finding vout %s", err)
247+
}
248+
249+
refundTransaction, _, err := boltz.ConstructTransaction(
250+
network,
251+
boltz.CurrencyBtc,
252+
[]boltz.OutputDetails{
253+
{
254+
SwapId: id,
255+
SwapType: boltz.NormalSwap,
256+
Address: destinationAddress,
257+
LockupTransaction: lockupTransaction,
258+
Vout: vout,
259+
Preimage: []byte{},
260+
PrivateKey: keys,
261+
TimeoutBlockHeight: uint32(timeoutBlockHeight),
262+
SwapTree: swapTree,
263+
Cooperative: true,
264+
},
265+
},
266+
satPerVbyte,
267+
boltzApi,
268+
)
269+
270+
if err != nil {
271+
return "", fmt.Errorf("could not create refund transaction: %w", err)
272+
}
273+
fmt.Println("Refund transaction constructed successfully")
274+
275+
txHex, err := refundTransaction.Serialize()
276+
if err != nil {
277+
return "", fmt.Errorf("could not serialize refund transaction: %w", err)
278+
}
279+
fmt.Println("Refund transaction serialized successfully")
280+
281+
var broadcastUrl string
282+
if isTestnet {
283+
broadcastUrl = "https://mempool.space/testnet/api/tx"
284+
} else {
285+
broadcastUrl = "https://mempool.space/api/tx"
286+
}
287+
288+
// Create HTTP request
289+
req, err := http.NewRequest("POST", broadcastUrl, bytes.NewBufferString(txHex))
290+
if err != nil {
291+
return "", fmt.Errorf("failed to create HTTP request: %v", err)
292+
}
293+
req.Header.Set("Content-Type", "application/json")
294+
295+
// Execute HTTP request
296+
client := &http.Client{}
297+
resp, err := client.Do(req)
298+
if err != nil {
299+
return "", fmt.Errorf("failed to send HTTP request: %v", err)
300+
}
301+
defer resp.Body.Close()
302+
303+
// Read response
304+
body, err := io.ReadAll(resp.Body)
305+
if err != nil {
306+
return "", fmt.Errorf("failed to read response body: %v", err)
307+
}
308+
309+
if resp.StatusCode != http.StatusOK {
310+
return "", fmt.Errorf("non-200 response: %d, body: %s", resp.StatusCode, string(body))
311+
}
312+
313+
txid := string(body)
314+
fmt.Printf("Transaction broadcasted successfully: %s\n", txid)
315+
fmt.Println("Transaction broadcasted successfully")
316+
317+
return txid, nil
318+
}

0 commit comments

Comments
 (0)