For the complete documentation index, see llms.txt. This page is also available as Markdown.

Go Example for Calling API

Golang Example for Calling the CatFee.IO Rest API

Prerequisites

You need a valid API Key and API Secret.

Make sure your Go environment has access to standard libraries such as net/http and crypto/hmac.

Sample Code

package main

import (
	"crypto/hmac"
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
	"time"
)

const (
	APIKey    = "your_api_key"       // Replace with your actual API Key
	APISecret = "your_api_secret"    // Replace with your actual API Secret
	BaseURL   = "https://api.catfee.io"
	Timeout   = 15 * time.Second
)

type apiResponse struct {
	Code   int           `json:"code"`
	Msg    string        `json:"msg"`
	SubMsg string        `json:"sub_msg"`
	Data   *orderPayload `json:"data"`
}

type orderPayload struct {
	ID string `json:"id"`
}

// Generate the current timestamp in ISO 8601 format
func generateTimestamp() string {
	return time.Now().UTC().Format("2006-01-02T15:04:05.000Z")
}

// Build request path including query parameters
func buildRequestPath(path string, queryParams url.Values) string {
	if len(queryParams) == 0 {
		return path
	}

	return path + "?" + queryParams.Encode()
}

// Generate HMAC-SHA256 signature
func generateSignature(timestamp, method, requestPath string) string {
	signString := timestamp + strings.ToUpper(method) + requestPath
	mac := hmac.New(sha256.New, []byte(APISecret))
	mac.Write([]byte(signString))
	signature := mac.Sum(nil)
	return base64.StdEncoding.EncodeToString(signature)
}

// Generate a 32-character idempotency key.
func generateClientOrderID() (string, error) {
	value := make([]byte, 16)
	if _, err := rand.Read(value); err != nil {
		return "", err
	}
	return hex.EncodeToString(value), nil
}

// Create and send HTTP request
func createRequest(url, method, timestamp, signature string) (*http.Response, error) {
	client := &http.Client{Timeout: Timeout}
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return nil, err
	}

	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("CF-ACCESS-KEY", APIKey)
	req.Header.Add("CF-ACCESS-SIGN", signature)
	req.Header.Add("CF-ACCESS-TIMESTAMP", timestamp)

	return client.Do(req)
}

func main() {
	method := "POST" // Can be "GET", "PUT", or "DELETE"
	path := "/v1/order"
	clientOrderID, err := generateClientOrderID()
	if err != nil {
		fmt.Println("Failed to generate Client Order ID:", err)
		return
	}

	// Example: Create order
	queryParams := url.Values{}
	queryParams.Set("quantity", "65000")
	queryParams.Set("receiver", "TRON_ADDRESS")
	queryParams.Set("duration", "1h")
	queryParams.Set("client_order_id", clientOrderID)
	queryParams.Set("activate", "true")

	timestamp := generateTimestamp()
	requestPath := buildRequestPath(path, queryParams)
	signature := generateSignature(timestamp, method, requestPath)

	url := BaseURL + requestPath

	fmt.Println("Client Order ID:", clientOrderID)
	resp, err := createRequest(url, method, timestamp, signature)
	if err != nil {
		fmt.Println("Request failed:", err)
		fmt.Println("Retry with the same Client Order ID:", clientOrderID)
		return
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Failed to read response:", err)
		return
	}

	fmt.Println("HTTP Status:", resp.StatusCode)
	fmt.Println("Response Body:", string(body))

	if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
		fmt.Printf("HTTP request failed with status %d\n", resp.StatusCode)
		return
	}

	var result apiResponse
	if err := json.Unmarshal(body, &result); err != nil {
		fmt.Println("Response is not valid JSON:", err)
		return
	}
	if result.Code != 0 {
		message := result.Msg
		if message == "" {
			message = result.SubMsg
		}
		fmt.Printf("API request failed: code=%d, message=%s\n", result.Code, message)
		return
	}
	if result.Data != nil {
		fmt.Println("Order ID:", result.Data.ID)
	}
}

Code Explanation

generateTimestamp()

Generates the current UTC time formatted as an ISO 8601 timestamp using Go’s time package.

buildRequestPath()

Uses url.Values.Encode() to URL-encode and sort query parameters. The resulting path is used for both signing and the actual request.

generateSignature()

Creates a signature string by concatenating timestamp + method + requestPath, and then signs it using HMAC-SHA256 with the API Secret. The result is Base64 encoded.

createRequest()

Builds the HTTP request with appropriate headers (CF-ACCESS-KEY, CF-ACCESS-SIGN, CF-ACCESS-TIMESTAMP) and sends it using the standard http package.

main()

Defines request method and query parameters, generates timestamp, request path, and signature, builds the final URL, and sends the request. Finally, the response is read and printed.


Notes

API Key and Secret

Make sure to replace APIKey and APISecret with your actual credentials from CatFee.IO.

Idempotent retries

Use a unique client_order_id of no more than 64 characters for each new order, and reuse it after a timeout or connection failure.

Response Handling

HTTP 200 does not necessarily mean business success. Always verify that the response body's code is 0.

HTTP Methods

This example supports POST, but you can change it to GET, PUT, or DELETE depending on your needs.


Summary

This example demonstrates how to securely call the CatFee.IO Rest API using Go, including HMAC-SHA256 signature generation for authentication. You can adjust the code to use different HTTP methods and handle various API responses accordingly.

Last updated

Was this helpful?