Skip to content

IvanTurko/mexc-sdk-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Go SDK for MEXC Exchange

A production-ready Go SDK for interacting with the MEXC REST and WebSocket APIs, built specifically for low-latency applications, 24/7 bots, and high-load systems.


⚠️ Project Status (Beta)

The library is under active development. We welcome contributions and Pull Requests.

API Coverage Status
WebSocket API Full Coverage (100%): Spot (spot_v3) and Futures (contract_v1). ✅ Ready
REST API Partial coverage of public and private methods (e.g., Futures trading and specific private account history are pending). 🟡 In Development

Key Features

Feature User Benefit
Unified Transport Abstraction (DI) Full control over the network stack for REST and WebSocket. Simplifies testing, allows injecting mocks, custom proxies, and HFT/low-latency optimized clients.
Financial Precision (decimal) decimal.Decimal is used for all price and quantity data throughout the SDK. This eliminates rounding errors and ensures the safety of trading strategies.
Typed Error Model The use of typed errors allows for writing clean retry/backoff logic using Go's standard errors.Is/errors.As mechanism, reacting precisely to the error type (e.g., Auth, Validation, Rate Limit).
WS: Promises & Handles The asynchronous request/response matching logic is abstracted using a Promise pattern. Subscribe() is synchronous from the user's perspective, and the subscription is managed as an object (SubscriptionHandle).
WS: Low-Latency Monitoring Built-in PING/PONG RTT monitoring allows the bot to react to network degradation.
Thread-Safety All operations and internal data structures are protected, ensuring correct concurrent execution across multiple goroutines.

Installation

go get github.com/IvanTurko/mexc-sdk-go

Quick Start

Important: All examples use context with a timeout to follow Go best practices. Example #2 shows the robust, production-ready error handling required for reliable applications, while Example #1 is focused purely on quick setup.

Example #1: Authenticated REST (Simple Order Placement)

Demonstrating API Key usage and the Fluent Interface (Quick Start).

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/IvanTurko/mexc-sdk-go/spot/rest"
	"github.com/shopspring/decimal"
)

func main() {
	const timeout = 5 * time.Second

	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	// 1. Create order service with API keys
	svc := rest.NewCreateOrderService("YOUR_API_KEY_HERE", "YOUR_SECRET_KEY_HERE").
		Symbol("BTCUSDT").
		Side(rest.OrderSideBuy).
		Type(rest.OrderTypeLimit).
		Quantity(decimal.NewFromFloat(0.001)). // e.g., 0.001 BTC
		Price(decimal.NewFromFloat(60000.0))   // limit price

	// 2. Send order (omitting error handling for brevity)
	// NOTE: In production, always check the error returned here!
	order, _ := svc.Do(ctx)

	// 3. Print result
	fmt.Printf("Order placed! ID: %s, Type: %s, Qty: %s\n",
		order.OrderID, order.Type, order.OrigQty.String())
}

Example #2: REST API (Get Order Book)

Demonstrating DI, Transport Tuning, and Production Error Handling.

package main

import (
	"context"
	"errors"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/IvanTurko/mexc-sdk-go/sdkerr"
	"github.com/IvanTurko/mexc-sdk-go/spot/rest"
	"github.com/IvanTurko/mexc-sdk-go/transport"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 1. Configure and create custom HTTP transport.
	baseHTTP := &http.Client{
		Timeout: 5 * time.Second,
		Transport: &http.Transport{
			MaxIdleConns: 50,
			MaxConnsPerHost: 50,
		},
	}

	// 2. Wrap the custom client for SDK compatibility.
	customClient := transport.NewHTTPClient(baseHTTP)

	// 3. Build service with dependency injection.
	svc := rest.NewOrderBookService().
		WithClient(customClient).
		Symbol("BTCUSDT").
		Limit(5)

	// 4. Validate parameters before executing the request.
	if err := svc.Validate(); err != nil {
		log.Fatalf("Validation failed: %v", err)
	}

	// 5. Perform the request.
	book, err := svc.Do(ctx)
	if err != nil {
		handleSDKError(err)
		return
	}

	fmt.Println("Best Ask:", book.Asks[0].Price)
}

// handleSDKError processes and logs typed SDK errors (used for production code).
func handleSDKError(err error) {
	var sdkErr *sdkerr.SDKError
	if !errors.As(err, &sdkErr) {
		log.Fatalf("System error: %v", err)
	}

	switch {
	case errors.Is(sdkErr.Kind(), sdkerr.ErrValidation):
		log.Fatalf("Validation error: %s", sdkErr.Message())

	case errors.Is(sdkErr.Kind(), sdkerr.ErrAPIError):
		log.Printf("API error: %s", sdkErr.Message())

	case errors.Is(sdkErr.Kind(), sdkerr.ErrRequestFailed),
		errors.Is(sdkErr.Kind(), sdkerr.ErrDecodeError):
		log.Printf("Transport/Decode error: %s", sdkErr.Cause())

	default:
		log.Printf("Unknown SDK error: %s", err)
	}
}

Example #3: WebSocket API (Depth Subscription)

Demonstrating SubscriptionHandle, Asynchronous Handlers, and RTT monitoring.

package main

import (
	"context"
	"fmt"
	"os"
	"os/signal"
	"time"

	"github.com/IvanTurko/mexc-sdk-go/spot/wsmarket"
)

func handleDepthSnapshot(snapshot *wsmarket.DepthSnapshot) {
	bestAskPrice := "N/A"
	bestBidPrice := "N/A"

	if len(snapshot.Asks) > 0 {
		bestAskPrice = snapshot.Asks[0].Price.String()
	}
	if len(snapshot.Bids) > 0 {
		bestBidPrice = snapshot.Bids[0].Price.String()
	}

	fmt.Printf(">>> [%s v%d] | ASK: %s | BID: %s\n",
		snapshot.Symbol,
		snapshot.Version,
		bestAskPrice,
		bestBidPrice,
	)
}

func main() {
	// Set up context to handle interrupt signals (Ctrl+C)
	ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
	defer cancel()

	// 1. Create WebSocket client with latency monitoring
	client := wsmarket.NewWSMarket(
		wsmarket.WithPingLatencyHandler(func(latency time.Duration) {
			fmt.Printf("Current RTT latency: %v\n", latency)
		}),
	)

	// Connect to the exchange
	if err := client.Connect(ctx); err != nil {
		panic(err)
	}
	// Ensure client is safely closed when main exits
	defer func() {
		fmt.Println("Closing WS client...")
		client.Close()
	}()

	// 2. Prepare subscription
	sub := wsmarket.NewBookDepthSub(
		"BTCUSDT",
		wsmarket.DepthLevel5,
		handleDepthSnapshot,
	)

	// 3. Subscribe and obtain handle
	handle, err := client.Subscribe(ctx, sub)
	if err != nil {
		panic(err)
	}
	// Ensure we unsubscribe safely when main exits
	defer func() {
		fmt.Println("Unsubscribing from WS...")
		handle.Unsubscribe(context.Background())
	}()

	fmt.Println("Successfully subscribed to BTCUSDT DepthLevel5!")
	<-ctx.Done() // Wait until context is canceled (Ctrl+C)
	fmt.Println("Shutdown signal received, exiting...")
}

Architectural Philosophy

The entire SDK follows unified design principles, ensuring the maturity, accuracy, and flexibility required for a production environment.

1. Transport Abstraction (Dependency Injection)

The transport layer is abstracted through interfaces (transport.HTTPClient, WSConnFactory). This enables:

  • Testability: Mock injection for unit testing without network dependence.
  • Flexibility: Swapping implementations for custom stacks (mTLS, proxies, low-level optimizations).

2. Financial Precision (Zero-Loss Precision)

Using the decimal.Decimal type for all price and quantity data eliminates precision drift and is a mandatory requirement for any financial application.

3. Unified Domain Error Model (sdkerr)

The SDK provides a strictly typed error model. Every API error is mapped to an ErrorCode, which allows for:

  • Programmatic Reaction: Filtering errors by category (Auth, Trading, Validation).
  • Clear Code: Eliminating "magic numbers" and string parsing.

Design Decisions

This section explains key architectural choices that differentiate the SDK from most standard Go client implementations and demonstrate the focus on reliability and low-latency.

Decision Engineering Goal
Idempotent Closing with sync.Once Guarantees correct, exactly-once resource cleanup during concurrent or repeated Close() calls.
Synchronous API over WS (Promises) Simplifies developer logic by abstracting the asynchronous request/response matching using a Promise pattern (Future/Promise).
Buffered Channel for Outgoing WS Messages Prevents the user's goroutine from blocking, mitigating backpressure and increasing stability during temporary network slowdowns.
Built-in RTT Monitoring Embeds PING/PONG handlers for constant control over the actual latency to the exchange. Critical for HFT bots.
Clear Separation of Client / Conn Separates high-level client logic from low-level connection logic, maximizing modularity and testability.
Functional Options Pattern Ensures configurability and API extensibility without breaking existing compatibility (e.g., WithLogger, WithWriteTimeout).

Roadmap

Item Description
Full REST API Coverage Key Priority: Finalizing the implementation of all public and private REST API methods for Spot and Futures markets.

Contributing

We welcome community contributions! Please feel free to open an issue or submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

Production-ready Go SDK for MEXC REST & WebSocket APIs (Spot & Futures), optimized for low-latency and high-load systems.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages