Skip to main content

Overview

The MarketFetcher handles market discovery, individual market lookups, and orderbook retrieval. It also automatically caches venue contract addresses needed for order signing.

Setup

import limitless "github.com/limitless-labs-group/limitless-exchange-go-sdk/limitless"

client := limitless.NewHttpClient() // loads LIMITLESS_API_KEY from env
marketFetcher := limitless.NewMarketFetcher(client)

Fetching Active Markets

Use GetActiveMarkets() to retrieve a paginated list of all active markets:
ctx := context.Background()
result, err := marketFetcher.GetActiveMarkets(ctx, &limitless.ActiveMarketsParams{
    Page:   1,
    Limit:  10,
    SortBy: limitless.SortByLiquidity,
})
if err != nil {
    log.Fatal(err)
}

for _, m := range result.Data {
    fmt.Println(m.Title, m.Slug)
}
ParameterTypeDefaultDescription
Pageint1Page number for pagination
Limitint10Number of markets per page
SortByActiveMarketsSortBy""Sort order

Sort Options

ConstantDescription
SortByLPRewardsSort by LP rewards
SortByEndingSoonSort by markets ending soonest
SortByNewestSort by newest markets
SortByHighValueSort by highest value
SortByLiquiditySort by liquidity
Use pagination parameters to avoid large responses. Start with a small Limit and increment Page as needed.

Fetching a Single Market

Use GetMarket() to retrieve full details for a specific market:
market, err := marketFetcher.GetMarket(ctx, "btc-above-100k-march-2025")
if err != nil {
    log.Fatal(err)
}

fmt.Println(market.Title)
fmt.Println("YES token:", market.Tokens.Yes)
fmt.Println("NO token:", market.Tokens.No)
fmt.Println("Exchange:", market.Venue.Exchange)
The returned Market struct has the following key fields:
FieldTypeDescription
TitlestringHuman-readable market title
SlugstringURL-friendly market identifier
Tokens.YesstringToken ID for the YES outcome
Tokens.NostringToken ID for the NO outcome
Venue.ExchangestringExchange contract address (used as EIP-712 verifyingContract)
Venue.Adapter*stringAdapter contract address (used for NegRisk token approvals)
Markets[]MarketSub-markets (for NegRisk group markets)
Token IDs are returned as strings. Pass them directly to OrderClient.CreateOrder() via FOKOrderArgs or GTCOrderArgs.

Fetching the Orderbook

Use GetOrderBook() to retrieve current bids and asks for a market:
orderbook, err := marketFetcher.GetOrderBook(ctx, "btc-above-100k-march-2025")
if err != nil {
    log.Fatal(err)
}

fmt.Println("Bids:")
for _, bid := range orderbook.Bids {
    fmt.Printf("  Price: %.3f  Size: %.2f\n", bid.Price, bid.Size)
}

fmt.Println("Asks:")
for _, ask := range orderbook.Asks {
    fmt.Printf("  Price: %.3f  Size: %.2f\n", ask.Price, ask.Size)
}

fmt.Printf("Midpoint: %.4f\n", orderbook.AdjustedMidpoint)

Fetching User Orders

Use GetUserOrders() to retrieve your open orders on a market (requires authentication):
orders, err := marketFetcher.GetUserOrders(ctx, "btc-above-100k-march-2025")
if err != nil {
    log.Fatal(err)
}

for _, order := range orders {
    fmt.Printf("Order %s: %s %.2f @ %.3f\n", order.ID, order.Side, order.Size, order.Price)
}

Venue Caching

Every call to GetMarket() automatically caches the venue contract addresses (exchange and adapter) for that market. The OrderClient reads from this cache when signing orders, so you do not need to manage venues manually.
1

Fetch the market

Calling GetMarket() retrieves and caches the venue:
market, err := marketFetcher.GetMarket(ctx, "btc-above-100k-march-2025")
// Venue is now cached for this slug
2

Check the cache

You can also access the venue cache directly:
venue, ok := marketFetcher.GetVenue("btc-above-100k-march-2025")
if ok {
    fmt.Println("Exchange:", venue.Exchange)
}
3

Place an order

The OrderClient automatically looks up the cached venue when you pass MarketSlug:
result, err := orderClient.CreateOrder(ctx, limitless.CreateOrderParams{
    OrderType:  limitless.OrderTypeGTC,
    MarketSlug: "btc-above-100k-march-2025",
    Args: limitless.GTCOrderArgs{
        TokenID: market.Tokens.Yes,
        Side:    limitless.SideBuy,
        Price:   0.65,
        Size:    10.0,
    },
})
You must call GetMarket(slug) at least once before placing orders on that market. Without a cached venue, the OrderClient cannot determine the correct verifyingContract for EIP-712 signing.

Debugging Venue Cache

Enable LogLevelDebug logging to see venue cache operations:
logger := limitless.NewConsoleLogger(limitless.LogLevelDebug)
marketFetcher := limitless.NewMarketFetcher(client, limitless.WithMarketLogger(logger))

// Output will include lines like:
// [DEBUG] Venue cached for btc-above-100k-march-2025: exchange=0xA1b2... adapter=0xD4e5...
// [DEBUG] Venue cache hit for btc-above-100k-march-2025

Complete Example

package main

import (
    "context"
    "fmt"
    "log"

    limitless "github.com/limitless-labs-group/limitless-exchange-go-sdk/limitless"
)

func main() {
    client := limitless.NewHttpClient()
    marketFetcher := limitless.NewMarketFetcher(client)
    ctx := context.Background()

    // List active markets
    active, err := marketFetcher.GetActiveMarkets(ctx, &limitless.ActiveMarketsParams{Limit: 5})
    if err != nil {
        log.Fatal(err)
    }
    for _, m := range active.Data {
        fmt.Printf("%s%s\n", m.Title, m.Slug)
    }

    // Get a specific market
    slug := active.Data[0].Slug
    market, err := marketFetcher.GetMarket(ctx, slug)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("\nMarket: %s\n", market.Title)
    fmt.Printf("YES token: %s\n", market.Tokens.Yes)
    fmt.Printf("NO token:  %s\n", market.Tokens.No)

    // Fetch the orderbook
    orderbook, err := marketFetcher.GetOrderBook(ctx, slug)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("\nOrderbook — %d bids, %d asks\n", len(orderbook.Bids), len(orderbook.Asks))
}