mirror of
https://github.com/luxfi/maker.git
synced 2026-10-30 16:20:04 +00:00
Add a Kraken public-market-data price source (provider_kraken.go), the same ProviderSource shape as provider_oma.go / provider_v3.go, exposing the live CEX mid the seeder tracks via UseFeed. NewKrakenFeed wraps it; CompositeMid (feed.go) composes the CEX feed (listed majors) with the native V3 AMM feed (LUX/*) behind the single feed the seeder consumes. Binary opt-in via MAKER_KRAKEN_PAIRS. Read-only, unauthenticated, market-data only — the maker never trades on Kraken. Tests hermetic (canned frames) + KRAKEN_LIVE gate; live-proven (real BTC/USD mid). go.sum: refresh luxfi/[email protected] checksum (origin re-tag).
53 lines
2.0 KiB
Go
53 lines
2.0 KiB
Go
package maker
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
)
|
|
|
|
// feed.go composes heterogeneous price references behind the SINGLE MidProvider the
|
|
// seeder tracks. The seeder is reference-agnostic — it tracks one feed's mid per
|
|
// symbol (seeder.go currentMid). Different markets need different references: a
|
|
// CEX-listed major (ETH/USD) is priced by Kraken; a LUX/* pair is priced by the
|
|
// native V2/V3 AMM. CompositeMid lets both coexist as ONE feed, each pricing the
|
|
// symbols it knows, so there is still exactly one "what to track" seam.
|
|
|
|
// CompositeMid composes several MidProviders into one. GetMidPrice returns the
|
|
// first sub-provider that yields a positive mid for the symbol (order = priority),
|
|
// so a CEX feed and the native-AMM feed live behind a single seeder feed: the CEX
|
|
// prices its listed majors, the AMM prices LUX/*, and a symbol no sub-provider
|
|
// knows falls through to the seeder's own DEX-book / configured-mid fallback.
|
|
type CompositeMid struct{ feeds []MidProvider }
|
|
|
|
// NewCompositeMid builds a CompositeMid from the non-nil feeds, in priority order.
|
|
// It returns nil when none are given (no feed → seeder keeps prior behavior) and
|
|
// the sole feed unwrapped when exactly one is given (no needless indirection).
|
|
func NewCompositeMid(feeds ...MidProvider) MidProvider {
|
|
live := make([]MidProvider, 0, len(feeds))
|
|
for _, f := range feeds {
|
|
if f != nil {
|
|
live = append(live, f)
|
|
}
|
|
}
|
|
switch len(live) {
|
|
case 0:
|
|
return nil
|
|
case 1:
|
|
return live[0]
|
|
default:
|
|
return &CompositeMid{feeds: live}
|
|
}
|
|
}
|
|
|
|
// GetMidPrice returns the first sub-provider's positive mid for symbol. A symbol no
|
|
// sub-provider prices yields an error, so the seeder's currentMid falls through to
|
|
// the DEX book mid then the configured reference — never a fabricated price.
|
|
func (c *CompositeMid) GetMidPrice(ctx context.Context, symbol string) (float64, error) {
|
|
for _, f := range c.feeds {
|
|
if mid, err := f.GetMidPrice(ctx, symbol); err == nil && mid > 0 {
|
|
return mid, nil
|
|
}
|
|
}
|
|
return 0, fmt.Errorf("composite: no live mid for %s across %d feeds", symbol, len(c.feeds))
|
|
}
|