@@ -8,18 +8,31 @@ import (
8
8
"sync"
9
9
"time"
10
10
11
+ "bytes"
12
+
11
13
"github.com/btcsuite/btcd/btcutil"
14
+ "github.com/btcsuite/btcd/btcutil/psbt"
15
+ "github.com/lightninglabs/taproot-assets/asset"
12
16
"github.com/lightninglabs/taproot-assets/tapcfg"
17
+ "github.com/lightninglabs/taproot-assets/tappsbt"
13
18
"github.com/lightninglabs/taproot-assets/taprpc"
19
+ wrpc "github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc"
20
+ "github.com/lightninglabs/taproot-assets/taprpc/mintrpc"
14
21
"github.com/lightninglabs/taproot-assets/taprpc/priceoraclerpc"
15
22
"github.com/lightninglabs/taproot-assets/taprpc/rfqrpc"
16
23
"github.com/lightninglabs/taproot-assets/taprpc/tapchannelrpc"
24
+ "github.com/lightninglabs/taproot-assets/taprpc/tapdevrpc"
17
25
"github.com/lightninglabs/taproot-assets/taprpc/universerpc"
26
+ "github.com/lightninglabs/taproot-assets/tapsend"
27
+ "github.com/lightningnetwork/lnd/keychain"
18
28
"github.com/lightningnetwork/lnd/lnrpc"
29
+ "github.com/lightningnetwork/lnd/lnwallet/chainfee"
19
30
"github.com/lightningnetwork/lnd/lnwire"
20
31
"github.com/lightningnetwork/lnd/macaroons"
21
32
"google.golang.org/grpc"
33
+ "google.golang.org/grpc/codes"
22
34
"google.golang.org/grpc/credentials"
35
+ "google.golang.org/grpc/status"
23
36
"gopkg.in/macaroon.v2"
24
37
)
25
38
@@ -63,7 +76,10 @@ type TapdClient struct {
63
76
tapchannelrpc.TaprootAssetChannelsClient
64
77
priceoraclerpc.PriceOracleClient
65
78
rfqrpc.RfqClient
79
+ wrpc.AssetWalletClient
80
+ mintrpc.MintClient
66
81
universerpc.UniverseClient
82
+ tapdevrpc.TapDevClient
67
83
68
84
cfg * TapdConfig
69
85
assetNameCache map [string ]string
@@ -242,3 +258,231 @@ func getClientConn(config *TapdConfig) (*grpc.ClientConn, error) {
242
258
243
259
return conn , nil
244
260
}
261
+
262
+ // FundAndSignVpacket funds ands signs a vpacket.
263
+ func (t * TapdClient ) FundAndSignVpacket (ctx context.Context ,
264
+ vpkt * tappsbt.VPacket ) (* tappsbt.VPacket , error ) {
265
+
266
+ // Fund the packet.
267
+ var buf bytes.Buffer
268
+ err := vpkt .Serialize (& buf )
269
+ if err != nil {
270
+ return nil , err
271
+ }
272
+
273
+ fundResp , err := t .FundVirtualPsbt (
274
+ ctx , & wrpc.FundVirtualPsbtRequest {
275
+ Template : & wrpc.FundVirtualPsbtRequest_Psbt {
276
+ Psbt : buf .Bytes (),
277
+ },
278
+ },
279
+ )
280
+ if err != nil {
281
+ return nil , err
282
+ }
283
+
284
+ // Sign the packet.
285
+ signResp , err := t .SignVirtualPsbt (
286
+ ctx , & wrpc.SignVirtualPsbtRequest {
287
+ FundedPsbt : fundResp .FundedPsbt ,
288
+ },
289
+ )
290
+ if err != nil {
291
+ return nil , err
292
+ }
293
+
294
+ return tappsbt .NewFromRawBytes (
295
+ bytes .NewReader (signResp .SignedPsbt ), false ,
296
+ )
297
+ }
298
+
299
+ // PrepareAndCommitVirtualPsbts prepares and commits virtual psbts.
300
+ func (t * TapdClient ) PrepareAndCommitVirtualPsbts (ctx context.Context ,
301
+ vpkt * tappsbt.VPacket , feeRateSatPerKVByte chainfee.SatPerVByte ) (
302
+ * psbt.Packet , []* tappsbt.VPacket , []* tappsbt.VPacket ,
303
+ * wrpc.CommitVirtualPsbtsResponse , error ) {
304
+
305
+ htlcVPackets , err := tappsbt .Encode (vpkt )
306
+ if err != nil {
307
+ return nil , nil , nil , nil , err
308
+ }
309
+
310
+ htlcBtcPkt , err := tapsend .PrepareAnchoringTemplate (
311
+ []* tappsbt.VPacket {vpkt },
312
+ )
313
+ if err != nil {
314
+ return nil , nil , nil , nil , err
315
+ }
316
+
317
+ var buf bytes.Buffer
318
+ err = htlcBtcPkt .Serialize (& buf )
319
+ if err != nil {
320
+ return nil , nil , nil , nil , err
321
+ }
322
+
323
+ commitResponse , err := t .AssetWalletClient .CommitVirtualPsbts (
324
+ ctx , & wrpc.CommitVirtualPsbtsRequest {
325
+ AnchorPsbt : buf .Bytes (),
326
+ Fees : & wrpc.CommitVirtualPsbtsRequest_SatPerVbyte {
327
+ SatPerVbyte : uint64 (feeRateSatPerKVByte ),
328
+ },
329
+ AnchorChangeOutput : & wrpc.CommitVirtualPsbtsRequest_Add {
330
+ Add : true ,
331
+ },
332
+ VirtualPsbts : [][]byte {
333
+ htlcVPackets ,
334
+ },
335
+ },
336
+ )
337
+ if err != nil {
338
+ return nil , nil , nil , nil , err
339
+ }
340
+
341
+ fundedPacket , err := psbt .NewFromRawBytes (
342
+ bytes .NewReader (commitResponse .AnchorPsbt ), false ,
343
+ )
344
+ if err != nil {
345
+ return nil , nil , nil , nil , err
346
+ }
347
+
348
+ activePackets := make (
349
+ []* tappsbt.VPacket , len (commitResponse .VirtualPsbts ),
350
+ )
351
+ for idx := range commitResponse .VirtualPsbts {
352
+ activePackets [idx ], err = tappsbt .Decode (
353
+ commitResponse .VirtualPsbts [idx ],
354
+ )
355
+ if err != nil {
356
+ return nil , nil , nil , nil , err
357
+ }
358
+ }
359
+
360
+ passivePackets := make (
361
+ []* tappsbt.VPacket , len (commitResponse .PassiveAssetPsbts ),
362
+ )
363
+ for idx := range commitResponse .PassiveAssetPsbts {
364
+ passivePackets [idx ], err = tappsbt .Decode (
365
+ commitResponse .PassiveAssetPsbts [idx ],
366
+ )
367
+ if err != nil {
368
+ return nil , nil , nil , nil , err
369
+ }
370
+ }
371
+
372
+ return fundedPacket , activePackets , passivePackets , commitResponse , nil
373
+ }
374
+
375
+ // LogAndPublish logs and publishes the virtual psbts.
376
+ func (t * TapdClient ) LogAndPublish (ctx context.Context , btcPkt * psbt.Packet ,
377
+ activeAssets []* tappsbt.VPacket , passiveAssets []* tappsbt.VPacket ,
378
+ commitResp * wrpc.CommitVirtualPsbtsResponse ) (* taprpc.SendAssetResponse ,
379
+ error ) {
380
+
381
+ var buf bytes.Buffer
382
+ err := btcPkt .Serialize (& buf )
383
+ if err != nil {
384
+ return nil , err
385
+ }
386
+
387
+ request := & wrpc.PublishAndLogRequest {
388
+ AnchorPsbt : buf .Bytes (),
389
+ VirtualPsbts : make ([][]byte , len (activeAssets )),
390
+ PassiveAssetPsbts : make ([][]byte , len (passiveAssets )),
391
+ ChangeOutputIndex : commitResp .ChangeOutputIndex ,
392
+ LndLockedUtxos : commitResp .LndLockedUtxos ,
393
+ }
394
+
395
+ for idx := range activeAssets {
396
+ request .VirtualPsbts [idx ], err = tappsbt .Encode (
397
+ activeAssets [idx ],
398
+ )
399
+ if err != nil {
400
+ return nil , err
401
+ }
402
+ }
403
+ for idx := range passiveAssets {
404
+ request .PassiveAssetPsbts [idx ], err = tappsbt .Encode (
405
+ passiveAssets [idx ],
406
+ )
407
+ if err != nil {
408
+ return nil , err
409
+ }
410
+ }
411
+
412
+ resp , err := t .PublishAndLogTransfer (ctx , request )
413
+ if err != nil {
414
+ return nil , err
415
+ }
416
+
417
+ return resp , nil
418
+ }
419
+
420
+ // CheckBalanceById checks the balance of an asset by its id.
421
+ func (t * TapdClient ) CheckBalanceById (ctx context.Context , assetId []byte ,
422
+ requestedBalance btcutil.Amount ) error {
423
+
424
+ // Check if we have enough funds to do the swap.
425
+ balanceResp , err := t .ListBalances (
426
+ ctx , & taprpc.ListBalancesRequest {
427
+ GroupBy : & taprpc.ListBalancesRequest_AssetId {
428
+ AssetId : true ,
429
+ },
430
+ AssetFilter : assetId ,
431
+ },
432
+ )
433
+ if err != nil {
434
+ return err
435
+ }
436
+
437
+ // Check if we have enough funds to do the swap.
438
+ balance , ok := balanceResp .AssetBalances [hex .EncodeToString (
439
+ assetId ,
440
+ )]
441
+ if ! ok {
442
+ return status .Error (
443
+ codes .Internal , "internal error" ,
444
+ )
445
+ }
446
+ if balance .Balance < uint64 (requestedBalance ) {
447
+ return status .Error (
448
+ codes .Internal , "internal error" ,
449
+ )
450
+ }
451
+
452
+ return nil
453
+ }
454
+
455
+ // DeriveNewKeys derives a new internal and script key.
456
+ func (t * TapdClient ) DeriveNewKeys (ctx context.Context ) (asset.ScriptKey ,
457
+ keychain.KeyDescriptor , error ) {
458
+ scriptKeyDesc , err := t .NextScriptKey (
459
+ ctx , & wrpc.NextScriptKeyRequest {
460
+ KeyFamily : uint32 (asset .TaprootAssetsKeyFamily ),
461
+ },
462
+ )
463
+ if err != nil {
464
+ return asset.ScriptKey {}, keychain.KeyDescriptor {}, err
465
+ }
466
+
467
+ scriptKey , err := taprpc .UnmarshalScriptKey (scriptKeyDesc .ScriptKey )
468
+ if err != nil {
469
+ return asset.ScriptKey {}, keychain.KeyDescriptor {}, err
470
+ }
471
+
472
+ internalKeyDesc , err := t .NextInternalKey (
473
+ ctx , & wrpc.NextInternalKeyRequest {
474
+ KeyFamily : uint32 (asset .TaprootAssetsKeyFamily ),
475
+ },
476
+ )
477
+ if err != nil {
478
+ return asset.ScriptKey {}, keychain.KeyDescriptor {}, err
479
+ }
480
+ internalKeyLnd , err := taprpc .UnmarshalKeyDescriptor (
481
+ internalKeyDesc .InternalKey ,
482
+ )
483
+ if err != nil {
484
+ return asset.ScriptKey {}, keychain.KeyDescriptor {}, err
485
+ }
486
+
487
+ return * scriptKey , internalKeyLnd , nil
488
+ }
0 commit comments