mirror of
https://github.com/luxfi/maker.git
synced 2026-10-30 16:20:04 +00:00
The wire method names are dex_* (zapwire MethodPlace="dex_place", etc.); the clob_* strings were stale pre-rename references in comments and operator-facing error strings only — no wire change. An error logging "clob_deposit" when the method is dex_deposit is misleading on-call. config.go:140 (the named drift) plus every sibling clob_* in dex.go/ dexhttp.go/seeder.go. Method constants + frozen frames unchanged; the 26 tests pass.
172 lines
6.3 KiB
Go
172 lines
6.3 KiB
Go
package maker
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Canonical DEVNET asset ids for the native D-Chain CLOB ledger. An asset id is
|
|
// the FULL 32-byte injective id the venue keys balance:/locked: by and binds a
|
|
// market's (base,quote) to (zapwire.AssetIDSize); it is NEVER derived from a
|
|
// symbol (that would let two assets collide). The id must be PINNED and identical
|
|
// across restarts, and the SAME id the settlement/precompile rail uses.
|
|
//
|
|
// Convention (the rail's INJECTIVE map, per zapwire's custody block):
|
|
// - native LUX = the reserved all-zero id (ids.Empty);
|
|
// - ERC-20 = the 20-byte C-Chain token address left-padded into 32 bytes.
|
|
//
|
|
// DEVNET ONLY: there is no devnet ERC-20 token registry (the addresses in
|
|
// dex/pkg/price and dex/pkg/gateway/lux are the MAINNET C-Chain set verified
|
|
// 2026-03-05 — using them for a devnet id would be wrong and could pollute prod).
|
|
// So on devnet LUSD/LETH are pinned by the documented label convention a32(label)
|
|
// — the ASCII ticker packed big-endian into the low bytes — exactly what the live
|
|
// consensus-fill proof tool cmd/fourpath-live and pkg/dchain conservation_test
|
|
// seed on devnet. These are therefore the canonical devnet ids the native
|
|
// settlement rail already settles against. When a devnet ERC-20 LUSD/LETH is
|
|
// deployed, repin these to its left-padded C-Chain address (and bridge custody in
|
|
// over dex_deposit from a real ImportTx) — the id is the ONLY thing that changes.
|
|
var (
|
|
// AssetLUX is native LUX: the reserved all-zero 32-byte id.
|
|
AssetLUX = [32]byte{}
|
|
|
|
// AssetLUSD is devnet LUSD: ASCII "LUSD" packed into the low bytes
|
|
// (a32(0x4c555344_000001)). Matches cmd/fourpath-live assetLUSD.
|
|
AssetLUSD = assetLabel(0x4c555344_000001)
|
|
|
|
// AssetLETH is devnet LETH: ASCII "LETH" packed into the low bytes
|
|
// (a32(0x4c455448_000001)). Matches the fourpath/conservation label form.
|
|
AssetLETH = assetLabel(0x4c455448_000001)
|
|
)
|
|
|
|
// assetLabel packs a uint64 ticker label big-endian into the low 8 bytes of a
|
|
// 32-byte asset id, byte-identical to pkg/dchain.a32 / cmd/fourpath-live.assetID.
|
|
// It is the DEVNET label convention for a pinned, derive-from-nothing asset id.
|
|
func assetLabel(label uint64) [32]byte {
|
|
var a [32]byte
|
|
a[24] = byte(label >> 56)
|
|
a[25] = byte(label >> 48)
|
|
a[26] = byte(label >> 40)
|
|
a[27] = byte(label >> 32)
|
|
a[28] = byte(label >> 24)
|
|
a[29] = byte(label >> 16)
|
|
a[30] = byte(label >> 8)
|
|
a[31] = byte(label)
|
|
return a
|
|
}
|
|
|
|
// AssetAddress left-pads a 20-byte EVM C-Chain token address into the 32-byte
|
|
// asset id — the rail's ERC-20 convention (see the file header). hexAddr is a
|
|
// token address with or without the 0x prefix. A malformed address yields the
|
|
// zero id (which the venue/precompile reject), so a bad config fails closed
|
|
// instead of seeding a phantom market. The asset id is the ONLY thing that
|
|
// differs between a devnet label id and a real mainnet/testnet ERC-20 id.
|
|
func AssetAddress(hexAddr string) [32]byte {
|
|
var a [32]byte
|
|
s := strings.TrimPrefix(strings.TrimPrefix(hexAddr, "0x"), "0X")
|
|
b, err := hex.DecodeString(s)
|
|
if err != nil || len(b) != 20 {
|
|
return a // fail closed: not a 20-byte address
|
|
}
|
|
copy(a[12:], b) // address in the low 20 bytes
|
|
return a
|
|
}
|
|
|
|
// Config controls market maker behavior.
|
|
type Config struct {
|
|
// BrokerURL is the broker API base URL.
|
|
BrokerURL string
|
|
|
|
// Symbols to make markets on.
|
|
Symbols []string
|
|
|
|
// SpreadBps is the half-spread in basis points (10 = 10bps each side).
|
|
SpreadBps float64
|
|
|
|
// Levels is how many price levels to quote on each side.
|
|
Levels int
|
|
|
|
// LevelSpacingBps is spacing between levels in basis points.
|
|
LevelSpacingBps float64
|
|
|
|
// BaseQty is the quantity at the best level.
|
|
BaseQty float64
|
|
|
|
// QtyMultiplier increases qty at deeper levels (1.5 = 50% more per level).
|
|
QtyMultiplier float64
|
|
|
|
// RefreshInterval is how often to requote.
|
|
RefreshInterval time.Duration
|
|
|
|
// Providers to aggregate depth from (empty = all registered).
|
|
Providers []string
|
|
|
|
// PhantomDepth includes external venue depth in unified book view.
|
|
PhantomDepth bool
|
|
|
|
// MaxPositionQty caps net position before stopping one-sided quoting.
|
|
MaxPositionQty float64
|
|
|
|
// SkewBps adjusts spread based on inventory.
|
|
SkewBps float64
|
|
|
|
// DEXEndpoint is the lux/dex ZAP server address (host:port) the maker
|
|
// seeds liquidity into. Empty means quote-only (no submission).
|
|
DEXEndpoint string
|
|
|
|
// MakerUser is the maker identity written into each order (<=16 bytes).
|
|
MakerUser string
|
|
|
|
// Pairs are the markets to create and seed on the DEX. When set, the
|
|
// seeder creates each market and maintains a 2-sided book.
|
|
Pairs []Pair
|
|
}
|
|
|
|
// Pair is a market the maker seeds on the DEX. Mid is the initial reference
|
|
// mid used to bootstrap quotes before any external venue price is available
|
|
// (e.g. a freshly created market with an empty book).
|
|
type Pair struct {
|
|
Symbol string // e.g. "LUX/LUSD"
|
|
Mid float64 // initial reference mid price
|
|
|
|
// PoolID optionally pins the venue's 32-byte market id for this pair,
|
|
// overriding the SymbolPoolID(Symbol) venue-convention default. Set it to a
|
|
// deployed EVM V4 PoolKey hash (key.ID()) so the maker seeds the exact
|
|
// on-chain book the precompile routes swaps to. A zero PoolID means "derive
|
|
// from Symbol by the venue convention".
|
|
PoolID [32]byte
|
|
|
|
// Base and Quote are the market's FULL 32-byte asset ids (e.g. AssetLUX /
|
|
// AssetLUSD). When Custody is true the seeder binds them via dex_open_market
|
|
// and funds the maker via dex_deposit before placing, so the seeded book is
|
|
// custody-backed (orders lock real balances and fills settle in the ledger).
|
|
Base [32]byte
|
|
Quote [32]byte
|
|
|
|
// Custody makes the seeder open the market with (Base, Quote) and deposit the
|
|
// maker's funding before placing. The canonical devnet books (LUX/LUSD,
|
|
// LUX/LETH) are custody-backed. Left false, the pair seeds the asset-LESS
|
|
// path (ensure_market + place only) — useful for a no-custody display book.
|
|
Custody bool
|
|
}
|
|
|
|
// hasPoolID reports whether the pair pins an explicit (non-zero) poolId.
|
|
func (p Pair) hasPoolID() bool {
|
|
return p.PoolID != [32]byte{}
|
|
}
|
|
|
|
// DefaultConfig returns production-ready defaults.
|
|
func DefaultConfig() Config {
|
|
return Config{
|
|
SpreadBps: 10,
|
|
Levels: 5,
|
|
LevelSpacingBps: 5,
|
|
BaseQty: 1.0,
|
|
QtyMultiplier: 1.5,
|
|
RefreshInterval: 5 * time.Second,
|
|
PhantomDepth: true,
|
|
MaxPositionQty: 100,
|
|
SkewBps: 2,
|
|
}
|
|
}
|