m2pool_core/internal/gbt/alph/http/http.go

309 lines
8.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}