From a60e12ca27c3a0d34eeb96ddaa9beae6095a5839 Mon Sep 17 00:00:00 2001 From: Cameron Cooper Date: Wed, 10 Dec 2025 10:30:20 -0600 Subject: [PATCH] accept an address in the place of a puzzle hash argument --- README.md | 4 +- .../get_coin_records_by_puzzle_hash.go | 18 ++-- .../get_coin_records_by_puzzle_hashes.go | 86 ++++++++++--------- internal/cmd/coinset/util.go | 15 ++++ 4 files changed, 70 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 40c1ff4..9b90b93 100644 --- a/README.md +++ b/README.md @@ -92,8 +92,8 @@ The following table shows all available CLI commands organized by functionality: | | `get_coin_records_by_hints ` | Retrieve coin records by multiple hints | | | `get_coin_records_by_names ` | Retrieve coin records by multiple names | | | `get_coin_records_by_parent_ids ` | Retrieve coin records by parent IDs | -| | `get_coin_records_by_puzzle_hash ` | Retrieve coin records by puzzle hash | -| | `get_coin_records_by_puzzle_hashes ` | Retrieve coin records by multiple puzzle hashes | +| | `get_coin_records_by_puzzle_hash ` | Retrieve coin records by puzzle hash or address | +| | `get_coin_records_by_puzzle_hashes ...` | Retrieve coin records by multiple puzzle hashes or addressees | | **Block Operations** | `get_block ` | Retrieve a full block by header hash | | | `get_blocks ` | Retrieve multiple blocks in a height range | | | `get_block_record ` | Retrieve a block record by header hash | diff --git a/internal/cmd/coinset/get_coin_records_by_puzzle_hash.go b/internal/cmd/coinset/get_coin_records_by_puzzle_hash.go index fe0067c..026b802 100644 --- a/internal/cmd/coinset/get_coin_records_by_puzzle_hash.go +++ b/internal/cmd/coinset/get_coin_records_by_puzzle_hash.go @@ -1,8 +1,6 @@ package cmd import ( - "fmt" - "github.com/spf13/cobra" ) @@ -20,21 +18,23 @@ func init() { } var getCoinRecordsByPuzzleHashCmd = &cobra.Command{ - Use: "get_coin_records_by_puzzle_hash ", + Use: "get_coin_records_by_puzzle_hash ", Args: func(cmd *cobra.Command, args []string) error { if err := cobra.ExactArgs(1)(cmd, args); err != nil { return err } - if isHex(args[0]) { - return nil + _, err := convertAddressOrPuzzleHash(args[0]) + if err != nil { + return err } - return fmt.Errorf("invalid hex value specified: %s", args[0]) + return nil }, - Short: "Retrieves coin records by their puzzle hash", - Long: "Retrieves coin records by their puzzle hash", + Short: "Retrieves coin records by their puzzle hash or address", + Long: "Retrieves coin records by their puzzle hash or address", Run: func(cmd *cobra.Command, args []string) { + puzzleHash, _ := convertAddressOrPuzzleHash(args[0]) jsonData := map[string]interface{}{} - jsonData["puzzle_hash"] = formatHex(args[0]) + jsonData["puzzle_hash"] = puzzleHash if crByPuzzleHashIncludeSpentCoins { jsonData["include_spent_coins"] = true } diff --git a/internal/cmd/coinset/get_coin_records_by_puzzle_hashes.go b/internal/cmd/coinset/get_coin_records_by_puzzle_hashes.go index d8e55fe..247b61a 100644 --- a/internal/cmd/coinset/get_coin_records_by_puzzle_hashes.go +++ b/internal/cmd/coinset/get_coin_records_by_puzzle_hashes.go @@ -1,56 +1,58 @@ package cmd import ( - "fmt" + "fmt" - "github.com/spf13/cobra" + "github.com/spf13/cobra" ) var ( - crByPuzzleHashesIncludeSpentCoins bool - crByPuzzleHashesStart int - crByPuzzleHashesEnd int + crByPuzzleHashesIncludeSpentCoins bool + crByPuzzleHashesStart int + crByPuzzleHashesEnd int ) func init() { - getCoinRecordsByPuzzleHashesCmd.Flags().BoolVarP(&crByPuzzleHashesIncludeSpentCoins, "include-spent-coins", "s", false, "Include spent coins") - getCoinRecordsByPuzzleHashesCmd.Flags().IntVarP(&crByPuzzleHashesStart, "start-height", "", -1, "Start height") - getCoinRecordsByPuzzleHashesCmd.Flags().IntVarP(&crByPuzzleHashesEnd, "end-height", "", -1, "End height") - rootCmd.AddCommand(getCoinRecordsByPuzzleHashesCmd) + getCoinRecordsByPuzzleHashesCmd.Flags().BoolVarP(&crByPuzzleHashesIncludeSpentCoins, "include-spent-coins", "s", false, "Include spent coins") + getCoinRecordsByPuzzleHashesCmd.Flags().IntVarP(&crByPuzzleHashesStart, "start-height", "", -1, "Start height") + getCoinRecordsByPuzzleHashesCmd.Flags().IntVarP(&crByPuzzleHashesEnd, "end-height", "", -1, "End height") + rootCmd.AddCommand(getCoinRecordsByPuzzleHashesCmd) } var getCoinRecordsByPuzzleHashesCmd = &cobra.Command{ - Use: "get_coin_records_by_puzzle_hashes ...", - Args: func(cmd *cobra.Command, args []string) error { - if len(args) < 1 { - return fmt.Errorf("at least one puzzle hash is required") - } - for _, name := range args { - if !isHex(name) { - return fmt.Errorf("invalid hex value specified: %s", name) - } - } - return nil - }, - Short: "Retrieves coin records by their puzzle hashes", - Long: "Retrieves coin records by their puzzle hashes", - Run: func(cmd *cobra.Command, args []string) { - var puzzleHashes []string - for _, puzzleHash := range args { - puzzleHashes = append(puzzleHashes, formatHex(puzzleHash)) - } - jsonData := map[string]interface{}{ - "puzzle_hashes": puzzleHashes, - } - if crByPuzzleHashesIncludeSpentCoins { - jsonData["include_spent_coins"] = true - } - if crByPuzzleHashesStart != -1 { - jsonData["start_height"] = crByPuzzleHashesStart - } - if crByPuzzleHashesEnd != -1 { - jsonData["end_height"] = crByPuzzleHashesEnd - } - makeRequest("get_coin_records_by_puzzle_hashes", jsonData) - }, + Use: "get_coin_records_by_puzzle_hashes ...", + Args: func(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return fmt.Errorf("at least one puzzle hash or address is required") + } + for _, input := range args { + _, err := convertAddressOrPuzzleHash(input) + if err != nil { + return fmt.Errorf("invalid input '%s': %v", input, err) + } + } + return nil + }, + Short: "Retrieves coin records by their puzzle hashes or addresses", + Long: "Retrieves coin records by their puzzle hashes or addresses", + Run: func(cmd *cobra.Command, args []string) { + var puzzleHashes []string + for _, input := range args { + puzzleHash, _ := convertAddressOrPuzzleHash(input) + puzzleHashes = append(puzzleHashes, puzzleHash) + } + jsonData := map[string]interface{}{ + "puzzle_hashes": puzzleHashes, + } + if crByPuzzleHashesIncludeSpentCoins { + jsonData["include_spent_coins"] = true + } + if crByPuzzleHashesStart != -1 { + jsonData["start_height"] = crByPuzzleHashesStart + } + if crByPuzzleHashesEnd != -1 { + jsonData["end_height"] = crByPuzzleHashesEnd + } + makeRequest("get_coin_records_by_puzzle_hashes", jsonData) + }, } diff --git a/internal/cmd/coinset/util.go b/internal/cmd/coinset/util.go index 525a154..ac68f7d 100644 --- a/internal/cmd/coinset/util.go +++ b/internal/cmd/coinset/util.go @@ -8,6 +8,7 @@ import ( "regexp" "github.com/TylerBrock/colorjson" + "github.com/chia-network/go-chia-libs/pkg/bech32m" "github.com/chia-network/go-chia-libs/pkg/rpc" "github.com/chia-network/go-chia-libs/pkg/rpcinterface" "github.com/itchyny/gojq" @@ -31,6 +32,20 @@ func formatHex(str string) string { return "0x" + str } +func convertAddressOrPuzzleHash(input string) (string, error) { + if isAddress(input) { + _, puzzleHashBytes, err := bech32m.DecodePuzzleHash(input) + if err != nil { + return "", fmt.Errorf("invalid address: %v", err) + } + return puzzleHashBytes.String(), nil + } else if isHex(input) { + return formatHex(input), nil + } else { + return "", fmt.Errorf("invalid input: must be either a Chia address or hex puzzle hash") + } +} + func apiHost() string { baseUrl, err := url.Parse(apiRoot()) if err != nil {