package http import ( "bytes" "encoding/json" "errors" "fmt" "io/ioutil" "net/http" ) type HttpClient struct { host string port string apiKey string } func NewHttpClient(host, port, apiKey string) *HttpClient { return &HttpClient{ host: host, port: port, apiKey: apiKey, } } func (client *HttpClient) parseJson(resp *http.Response, data []byte) (map[string]interface{}, error) { // 尝试解析为 JSON 对象 var dataJson map[string]interface{} if err := json.Unmarshal(data, &dataJson); err != nil { // 如果解析为 JSON 对象失败,检查是否是布尔值 var booleanValue bool if err := json.Unmarshal(data, &booleanValue); err == nil { // 如果是布尔值,包装成一个 map 返回 return map[string]interface{}{"success": booleanValue}, nil } // 如果既不是 JSON 对象也不是布尔值,返回错误 return nil, fmt.Errorf("invalid JSON response: %s", string(data)) } // 检查 HTTP 状态码 if resp.StatusCode != http.StatusOK { errMessage, _ := dataJson["detail"].(string) // 如果没有 "detail",默认为空字符串 dataJson["statusCode"] = resp.StatusCode dataJson["error"] = errMessage return dataJson, fmt.Errorf("HTTP error: %d - %s", resp.StatusCode, errMessage) } return dataJson, nil } func (client *HttpClient) httpRequest(method, path string, headers map[string]string, requestData []byte) (map[string]interface{}, error) { var url string if client.port == "" { url = "http://" + client.host + path } else { url = fmt.Sprintf("%s://%s:%s%s", "http", client.host, client.port, path) } req, err := http.NewRequest(method, url, bytes.NewBuffer(requestData)) if err != nil { return nil, err } for key, value := range headers { req.Header.Set(key, value) } clientResponse, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer clientResponse.Body.Close() body, err := ioutil.ReadAll(clientResponse.Body) if err != nil { return nil, err } return client.parseJson(clientResponse, body) } func (client *HttpClient) Get(path string) (map[string]interface{}, error) { headers := map[string]string{ "Accept": "application/json", } if client.apiKey != "" { headers["X-API-KEY"] = client.apiKey } return client.httpRequest("GET", path, headers, nil) } func (client *HttpClient) Post(path string, data interface{}) (map[string]interface{}, error) { headers := map[string]string{ "Content-Type": "application/json", } if client.apiKey != "" { headers["X-API-KEY"] = client.apiKey } jsonData, err := json.Marshal(data) if err != nil { return nil, err } fmt.Println("POST 请求的数据:", string(jsonData)) response, err := client.httpRequest("POST", path, headers, jsonData) if err != nil { return nil, err } fmt.Println("POST 响应的数据:", response) return response, nil } func (client *HttpClient) WalletStatus(walletName string) (map[string]interface{}, error) { path := fmt.Sprintf("/wallets/%s", walletName) return client.Get(path) } func (client *HttpClient) UnlockWallet(walletName, password, mnemonicPassphrase string) (map[string]interface{}, error) { path := fmt.Sprintf("/wallets/%s/unlock", walletName) data := map[string]string{"password": password} if mnemonicPassphrase != "" { data["mnemonicPassphrase"] = mnemonicPassphrase } return client.Post(path, data) } func (client *HttpClient) BuildUnsignedTx(fromPubKey string, destinations []interface{}) (map[string]interface{}, error) { path := "/transactions/build" data := map[string]interface{}{ "fromPublicKey": fromPubKey, "destinations": destinations, } return client.Post(path, data) } func (client *HttpClient) SelfClique() (map[string]interface{}, error) { path := "/infos/self-clique" return client.Get(path) } func (client *HttpClient) GetBlockHash(fromGroup uint32, toGroup uint32, height uint32) (string, error) { // 构建请求路径 path := fmt.Sprintf("/blockflow/hashes?fromGroup=%d&toGroup=%d&height=%d", fromGroup, toGroup, height) // 调用客户端的 Get 方法 result, err := client.Get(path) if err != nil { fmt.Println("获取hash失败:", err) return "", err } // 断言 result 是 map[string]interface{} data := result // 获取 headers 字段并断言为 []interface{} headers, ok := data["headers"].([]interface{}) if !ok { fmt.Println("headers 字段格式不正确") return "", errors.New("headers 字段格式不正确") } // 转换为字符串切片 var headerStrings []string for _, header := range headers { if str, ok := header.(string); ok { headerStrings = append(headerStrings, str) } else { fmt.Println("headers 中存在非字符串类型数据") return "", errors.New("headers 中存在非字符串类型数据") } } // 如果只需要第一个字符串,返回它 if len(headerStrings) > 0 { return headerStrings[0], nil } // 如果 headers 是空的,返回空字符串 return "", nil } func (client *HttpClient) CheckBlk(hash string) bool { path := fmt.Sprintf("/blockflow/is-block-in-main-chain?blockHash=%s", hash) result, err := client.Get(path) if err != nil { fmt.Println("获取hash失败:", err) return false } // 从返回结果中提取布尔值 if success, ok := result["success"].(bool); ok { return success } // 如果结果不包含布尔值或格式不对 fmt.Println("返回的结果格式不正确:", result) return false } type Block struct { ChainFrom int `json:"chainFrom"` ChainTo int `json:"chainTo"` DepStateHash string `json:"depStateHash"` Deps []string `json:"deps"` GhostUncles interface{} `json:"ghostUncles"` Hash string `json:"hash"` Height int64 `json:"height"` Nonce string `json:"nonce"` Target string `json:"target"` Timestamp float64 `json:"timestamp"` Transactions []TxDetail `json:"transactions"` TxsHash string `json:"txsHash"` Version int `json:"version"` } type TxDetail struct { Unsigned UnsignedTx `json:"unsigned"` } type UnsignedTx struct { Inputs []Input `json:"inputs"` FixedOutputs []FixedOutput `json:"fixedOutputs"` } type Input struct { } type FixedOutput struct { Address string `json:"address"` AttoAlphAmount string `json:"attoAlphAmount"` Hint float64 `json:"hint"` Key string `json:"key"` LockTime int64 `json:"lockTime"` } func (client *HttpClient) GetBlcokInfo(hash string) Block { path := fmt.Sprintf("/blockflow/blocks/%s", hash) result, err := client.Get(path) if err != nil { fmt.Println("获取区块信息失败:", err) return Block{} } // 将 map[string]interface{} 转换为 JSON 字符串 jsonData, err := json.Marshal(result) if err != nil { fmt.Println("转换为 JSON 字符串失败:", err) return Block{} } var blockInfo Block err = json.Unmarshal(jsonData, &blockInfo) if err != nil { fmt.Println("解析失败:", err) return Block{} } return blockInfo } // func (client *HttpClient) GetBlockCount(fromGroup uint32, toGroup uint32) (int, error) { // } func (client *HttpClient) ChangeActiveAddress(walletName string, address string) (map[string]interface{}, error) { path := fmt.Sprintf("/wallets/%s/change-active-address", walletName) data := map[string]interface{}{ "address": address, } return client.Post(path, data) } func (client *HttpClient) SignTx(walletName string, txId string) (map[string]interface{}, error) { path := fmt.Sprintf("/wallets/%s/sign", walletName) data := map[string]interface{}{ "data": txId, } return client.Post(path, data) } func (client *HttpClient) GetAddressInfo(walletName string, address string) (map[string]interface{}, error) { path := fmt.Sprintf("/wallets/%s/addresses/%s", walletName, address) return client.Get(path) } func (client *HttpClient) SweepActiveAddress(walletName string, toAddress string) (map[string]interface{}, error) { path := fmt.Sprintf("/wallets/%s/sweep-active-address", walletName) data := map[string]interface{}{ "toAddress": toAddress, } return client.Post(path, data) } func (client *HttpClient) CheckAccount(coin string, account string) bool { path := "/api/pool/checkAccount" data := map[string]interface{}{ "coin": coin, "ma": account, } result, err := client.Post(path, data) if err != nil { fmt.Println("校验挖矿账号失败:", err) return false } // 检查返回值中的 "success" 字段 success, ok := result["success"].(bool) if !ok { fmt.Println("响应格式错误或 success 字段不存在:", result) return false } return success }