Skip to content

Commit 8e0e80d

Browse files
enable using a height in place of a header hash (#22)
1 parent b24c023 commit 8e0e80d

File tree

6 files changed

+94
-47
lines changed

6 files changed

+94
-47
lines changed
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package cmd
22

33
import (
4-
"fmt"
5-
64
"github.com/spf13/cobra"
75
)
86

@@ -11,21 +9,23 @@ func init() {
119
}
1210

1311
var getAdditionsAndRemovalsCmd = &cobra.Command{
14-
Use: "get_additions_and_removals <header_hash>",
12+
Use: "get_additions_and_removals <height_or_header_hash>",
1513
Args: func(cmd *cobra.Command, args []string) error {
1614
if err := cobra.ExactArgs(1)(cmd, args); err != nil {
1715
return err
1816
}
19-
if isHex(args[0]) {
20-
return nil
17+
_, err := convertHeightOrHeaderHash(args[0])
18+
if err != nil {
19+
return err
2120
}
22-
return fmt.Errorf("invalid hex value specified: %s", args[0])
21+
return nil
2322
},
2423
Short: "Retrieves the additions and removals for a certain block",
25-
Long: "Retrieves the additions and removals for a certain block. Returns coin records for each addition and removal. Blocks that are not transaction blocks will have empty removal and addition lists. To get the actual puzzles and solutions for spent coins, use the get_puzzle_and_solution api.",
24+
Long: "Retrieves the additions and removals for a certain block by height or header hash. Returns coin records for each addition and removal. Blocks that are not transaction blocks will have empty removal and addition lists. To get the actual puzzles and solutions for spent coins, use the get_puzzle_and_solution api.",
2625
Run: func(cmd *cobra.Command, args []string) {
26+
headerHash, _ := convertHeightOrHeaderHash(args[0])
2727
jsonData := map[string]interface{}{}
28-
jsonData["header_hash"] = formatHex(args[0])
28+
jsonData["header_hash"] = headerHash
2929
makeRequest("get_additions_and_removals", jsonData)
3030
},
3131
}

internal/cmd/coinset/get_block.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package cmd
22

33
import (
4-
"fmt"
5-
64
"github.com/spf13/cobra"
75
)
86

@@ -11,21 +9,23 @@ func init() {
119
}
1210

1311
var getBlockCmd = &cobra.Command{
14-
Use: "get_block <header_hash>",
12+
Use: "get_block <height_or_header_hash>",
1513
Args: func(cmd *cobra.Command, args []string) error {
1614
if err := cobra.ExactArgs(1)(cmd, args); err != nil {
1715
return err
1816
}
19-
if isHex(args[0]) {
20-
return nil
17+
_, err := convertHeightOrHeaderHash(args[0])
18+
if err != nil {
19+
return err
2120
}
22-
return fmt.Errorf("invalid hex value specified: %s", args[0])
21+
return nil
2322
},
24-
Short: "Retrieves an entire block as a block by header hash",
25-
Long: `Retrieves an entire block as a block by header hash`,
23+
Short: "Retrieves an entire block by height or header hash",
24+
Long: `Retrieves an entire block by height or header hash`,
2625
Run: func(cmd *cobra.Command, args []string) {
26+
headerHash, _ := convertHeightOrHeaderHash(args[0])
2727
jsonData := map[string]interface{}{}
28-
jsonData["header_hash"] = formatHex(args[0])
28+
jsonData["header_hash"] = headerHash
2929
makeRequest("get_block", jsonData)
3030
},
3131
}
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package cmd
22

33
import (
4-
"fmt"
5-
64
"github.com/spf13/cobra"
75
)
86

@@ -11,21 +9,23 @@ func init() {
119
}
1210

1311
var getBlockRecordCmd = &cobra.Command{
14-
Use: "get_block_record <header_hash>",
12+
Use: "get_block_record <height_or_header_hash>",
1513
Args: func(cmd *cobra.Command, args []string) error {
1614
if err := cobra.ExactArgs(1)(cmd, args); err != nil {
1715
return err
1816
}
19-
if isHex(args[0]) {
20-
return nil
17+
_, err := convertHeightOrHeaderHash(args[0])
18+
if err != nil {
19+
return err
2120
}
22-
return fmt.Errorf("invalid hex value specified: %s", args[0])
21+
return nil
2322
},
24-
Short: "Retrieves a block record by header hash",
25-
Long: "Retrieves a block record by header hash",
23+
Short: "Retrieves a block record by height or header hash",
24+
Long: "Retrieves a block record by height or header hash",
2625
Run: func(cmd *cobra.Command, args []string) {
26+
headerHash, _ := convertHeightOrHeaderHash(args[0])
2727
jsonData := map[string]interface{}{}
28-
jsonData["header_hash"] = formatHex(args[0])
28+
jsonData["header_hash"] = headerHash
2929
makeRequest("get_block_record", jsonData)
3030
},
3131
}
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package cmd
22

33
import (
4-
"fmt"
5-
64
"github.com/spf13/cobra"
75
)
86

@@ -11,21 +9,23 @@ func init() {
119
}
1210

1311
var getBlockSpendsCmd = &cobra.Command{
14-
Use: "get_block_spends <header_hash>",
12+
Use: "get_block_spends <height_or_header_hash>",
1513
Args: func(cmd *cobra.Command, args []string) error {
1614
if err := cobra.ExactArgs(1)(cmd, args); err != nil {
1715
return err
1816
}
19-
if isHex(args[0]) {
20-
return nil
17+
_, err := convertHeightOrHeaderHash(args[0])
18+
if err != nil {
19+
return err
2120
}
22-
return fmt.Errorf("invalid hex value specified: %s", args[0])
21+
return nil
2322
},
2423
Short: "Retrieves every coin that was spent in a block",
25-
Long: `Retrieves every coin that was spent in a block`,
24+
Long: `Retrieves every coin that was spent in a block by height or header hash`,
2625
Run: func(cmd *cobra.Command, args []string) {
26+
headerHash, _ := convertHeightOrHeaderHash(args[0])
2727
jsonData := map[string]interface{}{}
28-
jsonData["header_hash"] = formatHex(args[0])
28+
jsonData["header_hash"] = headerHash
2929
makeRequest("get_block_spends", jsonData)
3030
},
3131
}
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package cmd
22

33
import (
4-
"fmt"
5-
64
"github.com/spf13/cobra"
75
)
86

@@ -11,21 +9,23 @@ func init() {
119
}
1210

1311
var getBlockSpendsWithConditionsCmd = &cobra.Command{
14-
Use: "get_block_spends_with_conditions <header_hash>",
12+
Use: "get_block_spends_with_conditions <height_or_header_hash>",
1513
Args: func(cmd *cobra.Command, args []string) error {
1614
if err := cobra.ExactArgs(1)(cmd, args); err != nil {
1715
return err
1816
}
19-
if isHex(args[0]) {
20-
return nil
17+
_, err := convertHeightOrHeaderHash(args[0])
18+
if err != nil {
19+
return err
2120
}
22-
return fmt.Errorf("invalid hex value specified: %s", args[0])
21+
return nil
2322
},
2423
Short: "Retrieves every coin that was spent in a block with the returned conditions",
25-
Long: `Retrieves every coin that was spent in a block with the returned conditions`,
24+
Long: `Retrieves every coin that was spent in a block with the returned conditions by height or header hash`,
2625
Run: func(cmd *cobra.Command, args []string) {
26+
headerHash, _ := convertHeightOrHeaderHash(args[0])
2727
jsonData := map[string]interface{}{}
28-
jsonData["header_hash"] = formatHex(args[0])
28+
jsonData["header_hash"] = headerHash
2929
makeRequest("get_block_spends_with_conditions", jsonData)
3030
},
3131
}

internal/cmd/coinset/util.go

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"log"
77
"net/url"
88
"regexp"
9+
"strconv"
910

1011
"github.com/TylerBrock/colorjson"
1112
"github.com/chia-network/go-chia-libs/pkg/bech32m"
@@ -46,6 +47,44 @@ func convertAddressOrPuzzleHash(input string) (string, error) {
4647
}
4748
}
4849

50+
func convertHeightOrHeaderHash(input string) (string, error) {
51+
if height, err := strconv.Atoi(input); err == nil {
52+
return getHeaderHashByHeight(height)
53+
} else if isHex(input) {
54+
return formatHex(input), nil
55+
} else {
56+
return "", fmt.Errorf("invalid input: must be either a block height (number) or hex header hash")
57+
}
58+
}
59+
60+
func getHeaderHashByHeight(height int) (string, error) {
61+
jsonData := map[string]interface{}{
62+
"height": height,
63+
}
64+
65+
jsonResponse, err := doRpc("get_block_record_by_height", jsonData)
66+
if err != nil {
67+
return "", fmt.Errorf("failed to get block record by height %d: %v", height, err)
68+
}
69+
70+
var response map[string]interface{}
71+
if err := json.Unmarshal(jsonResponse, &response); err != nil {
72+
return "", fmt.Errorf("failed to parse response: %v", err)
73+
}
74+
75+
blockRecord, ok := response["block_record"].(map[string]interface{})
76+
if !ok {
77+
return "", fmt.Errorf("invalid response format from get_block_record_by_height")
78+
}
79+
80+
headerHash, ok := blockRecord["header_hash"].(string)
81+
if !ok {
82+
return "", fmt.Errorf("header_hash not found in block record")
83+
}
84+
85+
return headerHash, nil
86+
}
87+
4988
func apiHost() string {
5089
baseUrl, err := url.Parse(apiRoot())
5190
if err != nil {
@@ -64,13 +103,13 @@ func apiRoot() string {
64103
return "https://api.coinset.org"
65104
}
66105

67-
func makeRequest(path string, jsonData map[string]interface{}) {
106+
func doRpc(path string, jsonData map[string]interface{}) (json.RawMessage, error) {
68107
var client *rpc.Client
69108
var err error
70109

71110
baseUrl, err := url.Parse(apiRoot())
72111
if err != nil {
73-
log.Fatal(err.Error())
112+
return nil, fmt.Errorf("failed to parse API URL: %v", err)
74113
}
75114

76115
if local {
@@ -80,20 +119,28 @@ func makeRequest(path string, jsonData map[string]interface{}) {
80119
}
81120

82121
if err != nil {
83-
log.Fatal(err.Error())
122+
return nil, fmt.Errorf("failed to create RPC client: %v", err)
84123
}
85124

86125
req, err := client.FullNodeService.NewRequest(rpcinterface.Endpoint(path), jsonData)
87126
if err != nil {
88-
log.Fatal(err.Error())
127+
return nil, fmt.Errorf("failed to create request: %v", err)
89128
}
90129

91130
jsonResponse := json.RawMessage{}
92131
_, err = client.FullNodeService.Do(req, &jsonResponse)
93132
if err != nil {
94-
log.Fatal(err.Error())
133+
return nil, fmt.Errorf("request failed: %v", err)
95134
}
96135

136+
return jsonResponse, nil
137+
}
138+
139+
func makeRequest(path string, jsonData map[string]interface{}) {
140+
jsonResponse, err := doRpc(path, jsonData)
141+
if err != nil {
142+
log.Fatal(err.Error())
143+
}
97144
printJson(jsonResponse)
98145
}
99146

0 commit comments

Comments
 (0)