Viewing Offers
Learn how to query and view offers from the Vif order book using vifdk.
Overview
The SDK provides functions to read offer data from the order book:
packedOfferList()- Get a list of offers from a marketpackedBook()- Get aggregated price levels (book depth)rawOffer()- Get a single offer by ID
These functions return contract call parameters that you use with viem's readContract.
Reading Offer Lists
Setup
import {
Token,
Market,
packedOfferList,
OfferList,
packedBook,
Book,
rawOffer,
Offer,
offerOwner,
} from "vifdk";
import { createPublicClient, http } from "viem";
import { mainnet } from "viem/chains";
const WETH = Token.from(WETH_ADDRESS, 18, "WETH", 1n);
const USDC = Token.from(USDC_ADDRESS, 6, "USDC", 1n);
const market = Market.create({
base: WETH,
quote: USDC,
tickSpacing: 1n,
});
const client = createPublicClient({
chain: mainnet,
transport: http(),
});Query Offers
Use packedOfferList() to get detailed offer data:
// Query offers from the asks market
const result = await client.readContract({
address: VIF_READER_ADDRESS,
...packedOfferList(market.asks, 0, 100),
});
const [nextOfferId, offerIds, packedOffers, owners] = result;
// Create an OfferList from the results
const offerList = OfferList.fromPacked(
market.asks,
offerIds,
packedOffers,
owners
);
// Access individual offers
for (const offer of offerList.offers) {
console.log("Offer ID:", offer.id);
console.log(
"Gives:",
offer.data.gives.amountString,
offer.data.gives.token.symbol
);
console.log("Tick:", offer.data.tick.value);
console.log("Owner:", offer.owner);
}Pagination
The fromId parameter allows pagination through large offer lists:
let fromId = 0;
const allOffers = [];
while (true) {
const [nextOfferId, offerIds, packedOffers, owners] =
await client.readContract({
address: VIF_READER_ADDRESS,
...packedOfferList(market.asks, fromId, 100),
});
if (offerIds.length === 0) break;
const offerList = OfferList.fromPacked(
market.asks,
offerIds,
packedOffers,
owners
);
allOffers.push(...offerList.offers);
if (nextOfferId === 0) break;
fromId = nextOfferId;
}Reading a Single Offer
Use rawOffer() to get a specific offer by ID:
const offerId = 42;
// Query the offer
const packedOffer = await client.readContract({
address: VIF_CORE_ADDRESS,
...rawOffer(market.asks, offerId),
});
// Get the owner
const ownerBigInt = await client.readContract({
address: VIF_CORE_ADDRESS,
...offerOwner(market.asks, offerId),
});
// Cast to address
const owner = `0x${ownerBigInt.toString(16).padStart(40, "0")}` as Address;
// Create Offer instance
const offer = Offer.fromPacked(market.asks, packedOffer, offerId, owner);
console.log("Gives:", offer.data.gives.amountString);
console.log("Received:", offer.data.received.amountString);
console.log("Tick:", offer.data.tick.value);Reading Book Depth
Use packedBook() to get aggregated price levels:
// Query book depth
const [nextPricePoint, packedElements] = await client.readContract({
address: VIF_READER_ADDRESS,
...packedBook(market.asks, 0, 100),
});
// Create Book instance
const book = Book.fromPacked(market.asks, packedElements);
// View price levels
for (const element of book.elements) {
const price = Number(element.tick.price) / 2 ** 128;
console.log("Price (raw):", price);
console.log("Total available:", element.totalGives.amountString);
console.log("Number of offers:", element.offerCount);
}Simulating Orders
Once you have an offer list, you can simulate what an order would do:
// Get offers
const [, offerIds2, packedOffers2, owners2] = await client.readContract({
address: VIF_READER_ADDRESS,
...packedOfferList(market.asks, 0, 100),
});
const offerList2 = OfferList.fromPacked(
market.asks,
offerIds2,
packedOffers2,
owners2
);
// Simulate buying 1 WETH
const result2 = offerList2.simulateOrder({
amount: WETH.amount("1"),
maxTick: market.asks.price(3600), // Don't pay more than 3600
});
console.log("Would receive:", result2.got.amountString, WETH.symbol);
console.log("Would spend:", result2.gave.amountString, USDC.symbol);
console.log("Fee:", result2.fee.amountString);Filtering Offers
Filter offers by owner or other criteria:
import { createWalletClient } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const walletClient = createWalletClient({
chain: mainnet,
transport: http(),
account: privateKeyToAccount(privateKey),
});
const [, offerIds3, packedOffers3, owners3] = await client.readContract({
address: VIF_READER_ADDRESS,
...packedOfferList(market.asks, 0, 1000),
});
const offerList3 = OfferList.fromPacked(
market.asks,
offerIds3,
packedOffers3,
owners3
);
// Get your offers
const myOffers = offerList3.offers.filter(
(offer) => offer.owner === walletClient.account.address
);
// Get offers at specific price
const targetTick = market.asks.price(3500);
const offersAtPrice = offerList3.offers.filter(
(offer) => offer.data.tick.value === targetTick.value
);
// Get offers with specific size
const largeOffers = offerList3.offers.filter(
(offer) => offer.data.gives.amount >= WETH.amount("10").amount
);Best Practices
- Use appropriate page sizes - 100 offers is usually sufficient
- Cache results - Order book data doesn't change every block
- Use Book for price quotes - Faster than loading all offers
- Use OfferList for simulations - More accurate than Book
- Handle pagination - Large markets may have thousands of offers
Next Steps
- Create Limit Orders - Place your own offers
- Market Orders - Take from the book
- Core Classes - Learn about Offer, Book, and OfferList
- Reading State - Direct contract reading