Files
zeekay fdef8d2a64 maker: rename stale clob_* refs to dex_* in comments + errors
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.
2026-06-26 17:51:17 -07:00

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,
}
}