Skip to content

Commit 6755ddd

Browse files
committed
cmd: add group_key flag to tapcli assets burn
1 parent 56e571c commit 6755ddd

File tree

1 file changed

+120
-23
lines changed

1 file changed

+120
-23
lines changed

cmd/commands/assets.go

Lines changed: 120 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import (
88
"strconv"
99
"strings"
1010

11+
"github.com/btcsuite/btcd/btcec/v2"
1112
"github.com/btcsuite/btcd/wire"
1213
taprootassets "github.com/lightninglabs/taproot-assets"
1314
"github.com/lightninglabs/taproot-assets/address"
15+
"github.com/lightninglabs/taproot-assets/asset"
1416
"github.com/lightninglabs/taproot-assets/tapcfg"
1517
"github.com/lightninglabs/taproot-assets/taprpc"
1618
wrpc "github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc"
@@ -1092,6 +1094,10 @@ var burnAssetsCommand = cli.Command{
10921094
Name: assetIDName,
10931095
Usage: "the asset ID to burn units from",
10941096
},
1097+
cli.StringFlag{
1098+
Name: assetGroupKeyName,
1099+
Usage: "the group key to burn units from",
1100+
},
10951101
cli.Uint64Flag{
10961102
Name: assetAmountName,
10971103
Usage: "the amount of units to burn/destroy",
@@ -1106,15 +1112,66 @@ var burnAssetsCommand = cli.Command{
11061112
Action: burnAssets,
11071113
}
11081114

1115+
// buildAssetSpecifier validates and constructs an asset.Specifier from
1116+
// CLI context
1117+
func buildAssetSpecifier(ctx *cli.Context) (*asset.Specifier, error) {
1118+
assetIDHex := ctx.String(assetIDName)
1119+
groupKeyHex := ctx.String(assetGroupKeyName)
1120+
1121+
// At least one of asset ID or group key must be provided.
1122+
if assetIDHex == "" && groupKeyHex == "" {
1123+
return nil, fmt.Errorf("either asset ID or " +
1124+
"group key must be specified")
1125+
}
1126+
1127+
var (
1128+
assetID *asset.ID
1129+
groupKey *btcec.PublicKey
1130+
err error
1131+
)
1132+
1133+
// Parse asset ID if provided.
1134+
if assetIDHex != "" {
1135+
assetIDBytes, err := hex.DecodeString(assetIDHex)
1136+
if err != nil {
1137+
return nil, fmt.Errorf("invalid asset ID: %w", err)
1138+
}
1139+
1140+
var id asset.ID
1141+
copy(id[:], assetIDBytes)
1142+
assetID = &id
1143+
}
1144+
1145+
// Parse group key if provided.
1146+
if groupKeyHex != "" {
1147+
groupKeyBytes, err := hex.DecodeString(groupKeyHex)
1148+
if err != nil {
1149+
return nil, fmt.Errorf("invalid group key: %w", err)
1150+
}
1151+
1152+
groupKey, err = btcec.ParsePubKey(groupKeyBytes)
1153+
if err != nil {
1154+
return nil, fmt.Errorf("invalid group key: %w", err)
1155+
}
1156+
}
1157+
1158+
// Construct the asset specifier.
1159+
assetSpecifier, err := asset.NewSpecifier(assetID, groupKey, nil, true)
1160+
if err != nil {
1161+
return nil, fmt.Errorf("invalid asset specifier: %w", err)
1162+
}
1163+
1164+
return &assetSpecifier, nil
1165+
}
1166+
11091167
func burnAssets(ctx *cli.Context) error {
11101168
if ctx.NArg() != 0 || ctx.NumFlags() == 0 {
11111169
return cli.ShowSubcommandHelp(ctx)
11121170
}
11131171

1114-
assetIDHex := ctx.String(assetIDName)
1115-
assetIDBytes, err := hex.DecodeString(assetIDHex)
1172+
assetSpecifier, err := buildAssetSpecifier(ctx)
11161173
if err != nil {
1117-
return fmt.Errorf("invalid asset ID")
1174+
return fmt.Errorf("invalid asset specifier: %w", err)
11181175
}
11191176

11201177
burnAmount := ctx.Uint64(assetAmountName)
@@ -1126,42 +1183,82 @@ func burnAssets(ctx *cli.Context) error {
11261183
client, cleanUp := getClient(ctx)
11271184
defer cleanUp()
11281185

1186+
assetIDBytes, groupKeyBytes := assetSpecifier.AsBytes()
1187+
11291188
if !ctx.Bool(burnOverrideConfirmationName) {
1130-
balance, err := client.ListBalances(
1131-
ctxc, &taprpc.ListBalancesRequest{
1132-
GroupBy: &taprpc.ListBalancesRequest_AssetId{
1133-
AssetId: true,
1189+
var currBalance uint64
1190+
1191+
// When both asset ID and group key are provided,
1192+
// prioritize asset ID for balance checking since
1193+
// it's more specific.
1194+
switch {
1195+
case len(assetIDBytes) > 0:
1196+
// nolint: lll
1197+
balance, err := client.ListBalances(ctxc,
1198+
&taprpc.ListBalancesRequest{
1199+
GroupBy: &taprpc.ListBalancesRequest_AssetId{
1200+
AssetId: true,
1201+
},
1202+
AssetFilter: assetIDBytes,
11341203
},
1135-
AssetFilter: assetIDBytes,
1136-
},
1137-
)
1138-
if err != nil {
1139-
return fmt.Errorf("unable to list current asset "+
1140-
"balances: %w", err)
1141-
}
1204+
)
1205+
if err != nil {
1206+
return fmt.Errorf("unable to list current "+
1207+
"asset balances: %w", err)
1208+
}
1209+
1210+
idHex := hex.EncodeToString(assetIDBytes)
1211+
assetBalance, ok := balance.AssetBalances[idHex]
1212+
if !ok {
1213+
return fmt.Errorf("couldn't fetch balance for "+
1214+
"asset ID %x", assetIDBytes)
1215+
}
1216+
1217+
currBalance = assetBalance.Balance
1218+
1219+
case len(groupKeyBytes) > 0:
1220+
// nolint: lll
1221+
balance, err := client.ListBalances(ctxc,
1222+
&taprpc.ListBalancesRequest{
1223+
GroupBy: &taprpc.ListBalancesRequest_GroupKey{
1224+
GroupKey: true,
1225+
},
1226+
AssetFilter: groupKeyBytes,
1227+
},
1228+
)
1229+
if err != nil {
1230+
return fmt.Errorf("unable to list current "+
1231+
"asset balances: %w", err)
1232+
}
11421233

1143-
assetBalance, ok := balance.AssetBalances[assetIDHex]
1144-
if !ok {
1145-
return fmt.Errorf("couldn't fetch balance for asset %x",
1146-
assetIDBytes)
1234+
gkHex := hex.EncodeToString(groupKeyBytes)
1235+
groupBalance, ok := balance.AssetGroupBalances[gkHex]
1236+
if !ok {
1237+
return fmt.Errorf("couldn't fetch balance for "+
1238+
"group key %x", groupKeyBytes)
1239+
}
1240+
1241+
currBalance = groupBalance.Balance
11471242
}
11481243

11491244
msg := fmt.Sprintf("Please confirm destructive action.\n"+
1150-
"Asset ID: %x\nCurrent available balance: %d\n"+
1245+
"%s\nCurrent available balance: %d\n"+
11511246
"Amount to burn: %d\n Are you sure you want to "+
11521247
"irreversibly burn (destroy, remove from circulation) "+
11531248
"the specified amount of assets?\nPlease answer 'yes' "+
1154-
"or 'no' and press enter: ", assetIDBytes,
1155-
assetBalance.Balance, burnAmount)
1249+
"or 'no' and press enter: ",
1250+
assetSpecifier.String(), currBalance, burnAmount,
1251+
)
11561252

11571253
if !promptForConfirmation(msg) {
11581254
return nil
11591255
}
11601256
}
11611257

11621258
resp, err := client.BurnAsset(ctxc, &taprpc.BurnAssetRequest{
1163-
Asset: &taprpc.BurnAssetRequest_AssetId{
1164-
AssetId: assetIDBytes,
1259+
AssetSpecifier: &taprpc.AssetSpecifier{
1260+
Id: assetIDBytes,
1261+
GroupKey: groupKeyBytes,
11651262
},
11661263
AmountToBurn: burnAmount,
11671264
ConfirmationText: taprootassets.AssetBurnConfirmationText,

0 commit comments

Comments
 (0)