使用golang 使用okex 的dex钱包功能去兑换代币
如果你想接入okex,去okex的dex上交易代币,使用程序实现,参考如下,golang实现 首先安装依赖插件
go mod init test
#复制下面代码放入 test.go 然后执行:
go mod tidy
下面是一段golang代码展示调用okex去兑换代币交易
package main
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"github.com/yellomoon/web3tool"
"github.com/yellomoon/web3tool/jsonrpc"
"github.com/yellomoon/web3tool/wallet"
"io/ioutil"
"math"
"math/big"
"net/http"
"net/url"
"strconv"
"time"
)
// Config 存储 API 配置
type Config struct {
APIKey string `json:"api_key"`
Passphrase string `json:"passphrase"`
Project string `json:"project"`
SecretKey string `json:"secret_key"`
}
// PreHash 生成预签名字符串
func PreHash(timestamp, method, requestPath string, params map[string]string) string {
queryString := ""
if method == "GET" && len(params) > 0 {
tempParms := make(map[string][]string)
for k, v := range params {
tempParms[k] = []string{v}
}
queryString = "?" + url.Values(tempParms).Encode()
}
if method == "POST" && len(params) > 0 {
jsonData, _ := json.Marshal(params)
queryString = string(jsonData)
}
return timestamp + method + requestPath + queryString
}
// Sign 使用 HMAC-SHA256 对消息进行签名
func Sign(message, secretKey string) string {
key := []byte(secretKey)
h := hmac.New(sha256.New, key)
h.Write([]byte(message))
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
// CreateSignature 生成签名和时间戳
func CreateSignature(method, requestPath string, params map[string]string, config Config) map[string]string {
timestamp := time.Now().UTC().Format("2006-01-02T15:04:05Z")
message := PreHash(timestamp, method, requestPath, params)
signature := Sign(message, config.SecretKey)
return map[string]string{
"signature": signature,
"timestamp": timestamp,
}
}
// SendGetRequest 发送 GET 请求
func SendGetRequest(requestPath string, params map[string]string, config Config) (string, error) {
// 生成签名
signatureData := CreateSignature("GET", requestPath, params, config)
// 构建请求 URL
requestURL := fmt.Sprintf("https://www.okx.com%s", requestPath)
tempParms := make(map[string][]string)
for k, v := range params {
tempParms[k] = []string{v}
}
if len(params) > 0 {
requestURL += "?" + url.Values(tempParms).Encode()
}
proxyURL, _ := url.Parse("http://127.0.0.1:7890")
// 创建 HTTP 客户端
client := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(proxyURL),
},
}
// 创建请求
req, err := http.NewRequest("GET", requestURL, nil)
if err != nil {
return "", fmt.Errorf("failed to create request: %v", err)
}
// 设置请求头
req.Header.Set("OK-ACCESS-KEY", config.APIKey)
req.Header.Set("OK-ACCESS-SIGN", signatureData["signature"])
req.Header.Set("OK-ACCESS-TIMESTAMP", signatureData["timestamp"])
req.Header.Set("OK-ACCESS-PASSPHRASE", config.Passphrase)
req.Header.Set("OK-ACCESS-PROJECT", config.Project)
// 发送请求
resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("failed to send request: %v", err)
}
defer resp.Body.Close()
// 读取响应
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("failed to read response body: %v", err)
}
return string(body), nil
}
func SendPostRequest(requestPath string, params map[string]string, config Config) (string, error) {
// 生成签名
signatureData := CreateSignature("POST", requestPath, params, config)
// 构建请求 URL
requestURL := fmt.Sprintf("https://www.okx.com%s", requestPath)
// 将参数转换为 JSON
jsonData, err := json.Marshal(params)
if err != nil {
return "", fmt.Errorf("failed to marshal params: %v", err)
}
// 创建 HTTP 客户端
proxyURL, _ := url.Parse("http://127.0.0.1:7890")
// 创建 HTTP 客户端
client := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(proxyURL),
},
}
// 创建请求
req, err := http.NewRequest("POST", requestURL, bytes.NewBuffer(jsonData))
if err != nil {
return "", fmt.Errorf("failed to create request: %v", err)
}
// 设置请求头
req.Header.Set("OK-ACCESS-KEY", config.APIKey)
req.Header.Set("OK-ACCESS-SIGN", signatureData["signature"])
req.Header.Set("OK-ACCESS-TIMESTAMP", signatureData["timestamp"])
req.Header.Set("OK-ACCESS-PASSPHRASE", config.Passphrase)
req.Header.Set("OK-ACCESS-PROJECT", config.Project)
req.Header.Set("Content-Type", "application/json")
// 发送请求
resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("failed to send request: %v", err)
}
defer resp.Body.Close()
// 读取响应
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("failed to read response body: %v", err)
}
return string(body), nil
}
func get_nonce(address, chainIndex string, config Config) (error, string) {
type Response struct {
Code string `json:"code"`
Msg string `json:"msg"`
Data []struct {
Nonce string `json:"nonce"`
PendingNonce string `json:"pendingNonce"`
} `json:"data"`
}
// 定义请求路径和参数
requestPath := "/api/v5/wallet/pre-transaction/nonce"
params := map[string]string{
"chainIndex": chainIndex,
"address": address,
}
// 发送 GET 请求
responseString, err := SendGetRequest(requestPath, params, config)
if err != nil {
fmt.Printf("Error: %v\n", err)
return err, ""
}
var response Response
err = json.Unmarshal([]byte(responseString), &response)
if err != nil {
fmt.Println("JSON 解析失败:", err)
return err, response.Msg
}
for _, item := range response.Data {
return nil, item.Nonce
}
return errors.New("其他错误"), ""
}
func post_transaction(input_data, chainIndex, myAddress string, config Config) (string, error) {
requestPath := "/api/v5/wallet/pre-transaction/broadcast-transaction"
params := map[string]string{
"chainIndex": chainIndex,
"signedTx": "0x" + input_data,
"address": myAddress,
}
res, err := SendPostRequest(requestPath, params, config)
return res, err
}
func main() {
var rpcUrl = "https://polygon-mainnet.infura.io/v3/{XXX}" // RPC URL 如果地址不能使用了 请去 https://infura.io 注册账号获取免费的
var privateKey = "ea9c312161c541758038e374a53147b933d39f504649b82f823285eb0b2ffd6e"
var myAddress = "0xbf8B5bc7Ea580ca7cEDa5F79F6ef3362134fC695"
var chainIndex = 56 //56 bsc 网络,137 polygon网络 , 1 eth 主网
config := Config{
APIKey: "",
Passphrase: "",
Project: "",
SecretKey: "",
}
USDT_DECIMAL := 18
USDT_AMOUNT := 1
USDT_ADDRESS := "0x55d398326f99059fF775485246999027B3197955"
USDC_ADDRESS := "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d"
var WalletAddress = web3tool.HexToAddress(myAddress).String()
swap_api := "/api/v5/dex/aggregator/swap"
var chainIndexStr = strconv.Itoa(chainIndex)
WalletAddressObj := web3tool.HexToAddress(WalletAddress)
params := map[string]string{
"chainId": chainIndexStr,
"amount": strconv.Itoa(USDT_AMOUNT * int(math.Pow10(USDT_DECIMAL))),
"fromTokenAddress": USDT_ADDRESS,
"toTokenAddress": USDC_ADDRESS,
"slippage": "0.005",
"userWalletAddress": WalletAddress,
}
// 发送 GET 请求
swap_response, err := SendGetRequest(swap_api, params, config)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
//// 配置 API 凭证
time.Sleep(1 * time.Second)
err, nonce := get_nonce(WalletAddress, chainIndexStr, config)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Println("Nonce:", nonce)
type SwapResponse struct {
Code string `json:"code"`
Msg string `json:"msg"`
Data []struct {
RouterResult map[string]interface{} `json:"routerResult"`
Tx map[string]interface{} `json:"tx"`
} `json:"data"`
}
var response SwapResponse
err = json.Unmarshal([]byte(swap_response), &response)
if err != nil {
fmt.Println("JSON 解析失败:", err)
return
}
for _, item := range response.Data {
to, ok := item.Tx["to"].(string)
if !ok {
fmt.Println("error:", err)
return
}
data, ok := item.Tx["data"].(string)
if !ok {
fmt.Println("error:", err)
return
}
gasPrice, ok := item.Tx["gasPrice"].(string)
if !ok {
fmt.Println("error:", err)
return
}
price, _ := strconv.Atoi(gasPrice)
gastemp, ok := item.Tx["gas"].(string)
if !ok {
fmt.Println("error:", err)
return
}
gas, _ := strconv.Atoi(gastemp)
toAddress := web3tool.HexToAddress(to)
hex_data, err := hex.DecodeString(data[2:])
if err != nil {
fmt.Println("error:", err)
return
}
rnonce, _ := strconv.Atoi(nonce)
txn := &web3tool.Transaction{
To: &toAddress,
Value: big.NewInt(0),
GasPrice: uint64(price),
Nonce: uint64(rnonce),
Input: hex_data,
Gas: uint64(gas),
ChainID: big.NewInt(int64(chainIndex)),
From: WalletAddressObj,
}
msg := &web3tool.CallMsg{
From: WalletAddressObj,
To: &toAddress,
Data: hex_data,
Value: big.NewInt(0),
GasPrice: uint64(price),
}
RpcClient, _ := jsonrpc.NewClient(rpcUrl)
GasLimit, err := RpcClient.Eth().EstimateGas(msg)
if err != nil {
fmt.Println("post_transaction err:", err)
return
}
txn.Gas = GasLimit
privateByte, _ := hex.DecodeString(privateKey)
key, _ := wallet.NewWalletFromPrivKey(privateByte)
//signer := wallet.NewEIP155Signer(1) //主网 chainID是1
signer := wallet.NewEIP155Signer(uint64(chainIndex))
txn, _ = signer.SignTx(txn, key)
senddata, _ := txn.MarshalRLPTo(nil)
time.Sleep(1 * time.Second)
res, err := post_transaction(hex.EncodeToString(senddata), chainIndexStr, WalletAddress, config)
if err != nil {
fmt.Println("post_transaction err:", err)
}
hash, _ := txn.GetHash()
fmt.Printf("%v, hash : %s", res, hash.String())
break
}
}
每天学习一点点,遨游在区块链知识海洋里
本文由博客一文多发平台 OpenWrite 发布!