package monero_rpc import ( "bytes" "encoding/json" "fmt" "io" "net/http" "net/url" "time" ) // HttpClient 封装 type HttpClient struct { Client *http.Client Url string } func NewHttpClient(url string, timeout time.Duration) *HttpClient { return &HttpClient{ Client: &http.Client{ Timeout: timeout, }, Url: url, } } // GET 请求,params 可为 nil func (hc *HttpClient) Get(api string, params map[string]interface{}, headers map[string]string) ([]byte, error) { rawURL := hc.Url + "/json_rpc" + api // 处理 URL 参数 if params != nil { u, err := url.Parse(rawURL) if err != nil { return nil, err } q := u.Query() for k, v := range params { q.Set(k, fmt.Sprintf("%v", v)) } u.RawQuery = q.Encode() rawURL = u.String() } // 创建请求 req, err := http.NewRequest("GET", rawURL, nil) if err != nil { return nil, err } // 设置头 for k, v := range headers { req.Header.Set(k, v) } // 发送请求 resp, err := hc.Client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() return io.ReadAll(resp.Body) } // POST 请求,params 可为 nil func (hc *HttpClient) Post(api string, params interface{}, headers map[string]string) ([]byte, error) { rawURL := hc.Url + "/json_rpc" + api var body io.Reader if params != nil { jsonBytes, err := json.Marshal(params) if err != nil { return nil, err } body = bytes.NewBuffer(jsonBytes) } req, err := http.NewRequest("POST", rawURL, body) if err != nil { return nil, err } // 设置默认 Content-Type if _, ok := headers["Content-Type"]; !ok { req.Header.Set("Content-Type", "application/json") } // 设置额外头 for k, v := range headers { req.Header.Set(k, v) } resp, err := hc.Client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() return io.ReadAll(resp.Body) } type RPCRequest struct { JsonRPC string `json:"jsonrpc"` ID string `json:"id"` Method string `json:"method"` Params interface{} `json:"params"` } func (hc *HttpClient) GetBlockTemplate(address string, size int) ([]byte, error) { params := map[string]any{ "wallet_address": address, "reserve_size": size, } req := RPCRequest{ JsonRPC: "2.0", ID: "0", Method: "get_block_template", Params: params, } resp, err := hc.Post("", req, nil) if err != nil { fmt.Println("[gbt]: getblocktemplate error:", err) return nil, err } return resp, nil } func (hc *HttpClient) GetBlockHeader(height uint64) ([]byte, error) { params := map[string]any{ "height": height, "fill_pow_hash": true, } req := RPCRequest{ JsonRPC: "2.0", ID: "0", Method: "get_block_header_by_height", Params: params, } resp, err := hc.Post("", req, nil) if err != nil { fmt.Println("[gbt]: getblockheader error:", err) return nil, err } return resp, nil } func (hc *HttpClient) GetBlockByHash(hash string) ([]byte, error) { params := map[string]any{ "hash": hash, } req := RPCRequest{ JsonRPC: "2.0", ID: "0", Method: "get_block_header_by_hash", Params: params, } resp, err := hc.Post("", req, nil) if err != nil { fmt.Println("[gbt]: getblockheader error:", err) return nil, err } return resp, nil } func (hc *HttpClient) SubmitBlock(blob string) ([]byte, error) { params := []string{blob} req := RPCRequest{ JsonRPC: "2.0", ID: "0", Method: "submit_block", Params: params, } resp, err := hc.Post("", req, nil) if err != nil { fmt.Println("[gbt]: getblockheader error:", err) return nil, err } return resp, nil }