@@ -1092,6 +1092,10 @@ var burnAssetsCommand = cli.Command{
10921092 Name : assetIDName ,
10931093 Usage : "the asset ID to burn units from" ,
10941094 },
1095+ cli.StringFlag {
1096+ Name : assetGroupKeyName ,
1097+ Usage : "the group key to burn units from" ,
1098+ },
10951099 cli.Uint64Flag {
10961100 Name : assetAmountName ,
10971101 Usage : "the amount of units to burn/destroy" ,
@@ -1106,15 +1110,59 @@ var burnAssetsCommand = cli.Command{
11061110 Action : burnAssets ,
11071111}
11081112
1113+ // buildAssetSpecifier validates and constructs an AssetSpecifier from
1114+ // CLI context
1115+ func buildAssetSpecifier (ctx * cli.Context ) (* taprpc.AssetSpecifier , error ) {
1116+ assetIDHex := ctx .String (assetIDName )
1117+ groupKeyHex := ctx .String (assetGroupKeyName )
1118+
1119+ // Either asset ID or group key must be provided, but not both.
1120+ if assetIDHex == "" && groupKeyHex == "" {
1121+ return nil , fmt .Errorf ("either asset ID or " +
1122+ "group key must be specified" )
1123+ }
1124+
1125+ if assetIDHex != "" && groupKeyHex != "" {
1126+ return nil , fmt .Errorf ("only one of asset ID or group key " +
1127+ "can be specified" )
1128+ }
1129+
1130+ var assetSpecifier * taprpc.AssetSpecifier
1131+ if assetIDHex != "" {
1132+ assetIDBytes , err := hex .DecodeString (assetIDHex )
1133+ if err != nil {
1134+ return nil , fmt .Errorf ("invalid asset ID: %w" , err )
1135+ }
1136+
1137+ assetSpecifier = & taprpc.AssetSpecifier {
1138+ Id : & taprpc.AssetSpecifier_AssetId {
1139+ AssetId : assetIDBytes ,
1140+ },
1141+ }
1142+ } else {
1143+ groupKeyBytes , err := hex .DecodeString (groupKeyHex )
1144+ if err != nil {
1145+ return nil , fmt .Errorf ("invalid group key: %w" , err )
1146+ }
1147+
1148+ assetSpecifier = & taprpc.AssetSpecifier {
1149+ Id : & taprpc.AssetSpecifier_GroupKey {
1150+ GroupKey : groupKeyBytes ,
1151+ },
1152+ }
1153+ }
1154+
1155+ return assetSpecifier , nil
1156+ }
1157+
11091158func burnAssets (ctx * cli.Context ) error {
11101159 if ctx .NArg () != 0 || ctx .NumFlags () == 0 {
11111160 return cli .ShowSubcommandHelp (ctx )
11121161 }
11131162
1114- assetIDHex := ctx .String (assetIDName )
1115- assetIDBytes , err := hex .DecodeString (assetIDHex )
1163+ assetSpecifier , err := buildAssetSpecifier (ctx )
11161164 if err != nil {
1117- return fmt .Errorf ("invalid asset ID" )
1165+ return fmt .Errorf ("invalid asset specifier: %w" , err )
11181166 }
11191167
11201168 burnAmount := ctx .Uint64 (assetAmountName )
@@ -1127,42 +1175,84 @@ func burnAssets(ctx *cli.Context) error {
11271175 defer cleanUp ()
11281176
11291177 if ! ctx .Bool (burnOverrideConfirmationName ) {
1130- balance , err := client .ListBalances (
1131- ctxc , & taprpc.ListBalancesRequest {
1132- GroupBy : & taprpc.ListBalancesRequest_AssetId {
1133- AssetId : true ,
1134- },
1135- AssetFilter : assetIDBytes ,
1136- },
1178+ var (
1179+ assetSpecBytes []byte
1180+ assetSpecType string
1181+ currBalance uint64
11371182 )
1138- if err != nil {
1139- return fmt .Errorf ("unable to list current asset " +
1140- "balances: %w" , err )
1141- }
11421183
1143- assetBalance , ok := balance .AssetBalances [assetIDHex ]
1144- if ! ok {
1145- return fmt .Errorf ("couldn't fetch balance for asset %x" ,
1146- assetIDBytes )
1184+ switch {
1185+ case assetSpecifier .GetAssetId () != nil :
1186+ assetSpecBytes = assetSpecifier .GetAssetId ()
1187+ assetSpecType = "Asset ID"
1188+ idHex := hex .EncodeToString (assetSpecBytes )
1189+
1190+ // nolint: lll
1191+ balance , err := client .ListBalances (ctxc ,
1192+ & taprpc.ListBalancesRequest {
1193+ GroupBy : & taprpc.ListBalancesRequest_AssetId {
1194+ AssetId : true ,
1195+ },
1196+ AssetFilter : assetSpecBytes ,
1197+ },
1198+ )
1199+ if err != nil {
1200+ return fmt .Errorf ("unable to list current " +
1201+ "asset balances: %w" , err )
1202+ }
1203+
1204+ assetBalance , ok := balance .AssetBalances [idHex ]
1205+ if ! ok {
1206+ return fmt .Errorf ("couldn't fetch balance for " +
1207+ "asset ID %x" , assetSpecBytes )
1208+ }
1209+
1210+ currBalance = assetBalance .Balance
1211+
1212+ case assetSpecifier .GetGroupKey () != nil :
1213+ assetSpecBytes = assetSpecifier .GetGroupKey ()
1214+ assetSpecType = "Group Key"
1215+ gkHex := hex .EncodeToString (assetSpecBytes )
1216+
1217+ // nolint: lll
1218+ balance , err := client .ListBalances (ctxc ,
1219+ & taprpc.ListBalancesRequest {
1220+ GroupBy : & taprpc.ListBalancesRequest_GroupKey {
1221+ GroupKey : true ,
1222+ },
1223+ AssetFilter : assetSpecBytes ,
1224+ },
1225+ )
1226+ if err != nil {
1227+ return fmt .Errorf ("unable to list current " +
1228+ "asset balances: %w" , err )
1229+ }
1230+
1231+ groupBalance , ok := balance .AssetGroupBalances [gkHex ]
1232+ if ! ok {
1233+ return fmt .Errorf ("couldn't fetch balance for " +
1234+ "group key %x" , assetSpecBytes )
1235+ }
1236+
1237+ currBalance = groupBalance .Balance
11471238 }
11481239
11491240 msg := fmt .Sprintf ("Please confirm destructive action.\n " +
1150- "Asset ID : %x\n Current available balance: %d\n " +
1241+ "%s : %x\n Current available balance: %d\n " +
11511242 "Amount to burn: %d\n Are you sure you want to " +
11521243 "irreversibly burn (destroy, remove from circulation) " +
11531244 "the specified amount of assets?\n Please answer 'yes' " +
1154- "or 'no' and press enter: " , assetIDBytes ,
1155- assetBalance .Balance , burnAmount )
1245+ "or 'no' and press enter: " ,
1246+ assetSpecType , assetSpecBytes , currBalance , burnAmount ,
1247+ )
11561248
11571249 if ! promptForConfirmation (msg ) {
11581250 return nil
11591251 }
11601252 }
11611253
11621254 resp , err := client .BurnAsset (ctxc , & taprpc.BurnAssetRequest {
1163- Asset : & taprpc.BurnAssetRequest_AssetId {
1164- AssetId : assetIDBytes ,
1165- },
1255+ AssetSpecifier : assetSpecifier ,
11661256 AmountToBurn : burnAmount ,
11671257 ConfirmationText : taprootassets .AssetBurnConfirmationText ,
11681258 })
0 commit comments