mirror of
https://github.com/luxfi/dex.git
synced 2026-09-24 00:26:31 +00:00
The gateway spoke 8=FIX.4.4 and reported a fill as ExecType 1/2 — the pair FIX Latest retired precisely because it duplicated order state into the event field. Both fields carried the same thing, so nothing on the wire distinguished "a trade happened" from "the order is done", and a client could read either. Session layer is now FIXT.1.1; the application layer is FIX.5.0SP2 + EP307, named on the Logon by DefaultApplVerID(1137) and ApplExtID(1156). Every fill is ExecType=F (Trade) and OrdStatus alone moves Partial -> Filled. Nothing depended on the old BeginString, so the wire moved with the semantics instead of straddling both. This is the wire pkg/dexprotocol already documents (150=F, 39=1|2). A partially-filled IOC also never reached a terminal state: the last report said Partial and nothing followed, leaving a client waiting for an end that never came. It now closes with Canceled. Vocabulary, one word per concept: execReport -> execution, gateway OrderFill -> Fill, multisig ExecutionResult -> Result (it holds an error string, never an execution). Deletes the SDK's hand-rolled FIX encoder — it pinned a second protocol version, omitted BodyLength entirely so the acceptor would have rejected every frame, and sendFIXMessage returned nil without sending. Co-authored-by: Hanzo Dev <[email protected]>
131 lines
3.4 KiB
Go
131 lines
3.4 KiB
Go
//go:build !grpc
|
|
|
|
// Package lxsdk is the gRPC-backed Go SDK for the LX trading platform.
|
|
//
|
|
// In the default build (no `grpc` build tag), gRPC support is excluded
|
|
// so consumers compile zero gRPC code. NewClient and NewHighFrequencyClient
|
|
// return an explanatory error. Rebuild with `-tags=grpc` to get the
|
|
// real client.
|
|
//
|
|
// External trading clients that do not need the binary gRPC transport
|
|
// should use the JSON-RPC + WebSocket SDK at
|
|
// github.com/luxfi/dex/sdk/go/client instead.
|
|
package lxsdk
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
// ErrGRPCNotBuilt is returned when the SDK is used without the `grpc`
|
|
// build tag. Rebuild with `go build -tags=grpc` to enable.
|
|
var ErrGRPCNotBuilt = errors.New("lxsdk: gRPC client requires the `grpc` build tag (rebuild with -tags=grpc)")
|
|
|
|
// Side represents order side.
|
|
type Side int
|
|
|
|
const (
|
|
Buy Side = iota
|
|
Sell
|
|
)
|
|
|
|
// OrderType represents order type.
|
|
type OrderType int
|
|
|
|
const (
|
|
Market OrderType = iota
|
|
Limit
|
|
Stop
|
|
StopLimit
|
|
)
|
|
|
|
// Order represents a trading order.
|
|
type Order struct {
|
|
ID string
|
|
Symbol string
|
|
Price float64
|
|
Quantity float64
|
|
Side Side
|
|
Type OrderType
|
|
Timestamp time.Time
|
|
}
|
|
|
|
// Trade represents an executed trade.
|
|
type Trade struct {
|
|
ID string
|
|
OrderID string
|
|
Symbol string
|
|
Price float64
|
|
Quantity float64
|
|
Side Side
|
|
Timestamp time.Time
|
|
}
|
|
|
|
// Client is the no-op placeholder for the gRPC client. All operations
|
|
// return ErrGRPCNotBuilt.
|
|
type Client struct {
|
|
address string
|
|
|
|
// Match the gRPC build's exported observability surface so consumers
|
|
// compile against both builds.
|
|
ordersSent atomic.Int64
|
|
tradesRecv atomic.Int64
|
|
latencyNanos atomic.Int64
|
|
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
// NewClient returns an error in the default build. Rebuild with `-tags=grpc`.
|
|
func NewClient(address string) (*Client, error) {
|
|
return nil, ErrGRPCNotBuilt
|
|
}
|
|
|
|
// SendOrder returns ErrGRPCNotBuilt.
|
|
func (c *Client) SendOrder(symbol string, price, quantity float64, side Side) (*Order, error) {
|
|
return nil, ErrGRPCNotBuilt
|
|
}
|
|
|
|
// SendBulkOrders returns ErrGRPCNotBuilt.
|
|
func (c *Client) SendBulkOrders(orders []*Order) error { return ErrGRPCNotBuilt }
|
|
|
|
// CancelOrder returns ErrGRPCNotBuilt.
|
|
func (c *Client) CancelOrder(orderID string) error { return ErrGRPCNotBuilt }
|
|
|
|
// Subscribe returns ErrGRPCNotBuilt.
|
|
func (c *Client) Subscribe(symbols []string, callback func(*Trade)) error { return ErrGRPCNotBuilt }
|
|
|
|
// GetOrderBook returns ErrGRPCNotBuilt.
|
|
func (c *Client) GetOrderBook(symbol string) (bids, asks []Order, err error) {
|
|
return nil, nil, ErrGRPCNotBuilt
|
|
}
|
|
|
|
// GetMetrics returns zeroed metrics.
|
|
func (c *Client) GetMetrics() map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"orders_sent": c.ordersSent.Load(),
|
|
"trades_received": c.tradesRecv.Load(),
|
|
"latency_ns": c.latencyNanos.Load(),
|
|
"latency_ms": float64(c.latencyNanos.Load()) / 1e6,
|
|
}
|
|
}
|
|
|
|
// GetThroughput returns 0.
|
|
func (c *Client) GetThroughput() float64 { return 0 }
|
|
|
|
// Close is a no-op.
|
|
func (c *Client) Close() error { return nil }
|
|
|
|
// HighFrequencyClient placeholder.
|
|
type HighFrequencyClient struct{ *Client }
|
|
|
|
// NewHighFrequencyClient returns ErrGRPCNotBuilt.
|
|
func NewHighFrequencyClient(address string) (*HighFrequencyClient, error) {
|
|
return nil, ErrGRPCNotBuilt
|
|
}
|
|
|
|
// SendOrderAsync is a no-op.
|
|
func (hft *HighFrequencyClient) SendOrderAsync(symbol string, price, quantity float64, side Side) {
|
|
}
|