@somnia-chain/markets-sdk


@somnia-chain/markets-sdk / index / snapRawToGrid

Function: snapRawToGrid()

snapRawToGrid(raw, step, direction): bigint

Defined in: packages/sdk/src/units.ts:680

Snap a raw on-chain value onto a raw-units grid — a venue's tickSize for a price, or its lotSize for a quantity. Both come from the pool's getOrderBookParameters. Returns the aligned raw value.

When to use

Reach for this on the engine path, where a caller holds bigint price and quantity and calls Trader.placeOrder directly. The unified facade snaps for you — exchange.createOrder aligns price and quantity before it signs — so a facade caller does not need this.

The pool rejects anything off the grid: an off-tick price reverts InvalidPrice, an off-lot quantity reverts InvalidQuantity.

Details

direction belongs to the VALUE, not to the order side. Rounding the wrong way is a real loss rather than a formatting choice, and the side does not determine it: a RESTING buy limit rounds down to stay at or below the price the caller accepted, while a CROSSING buy limit rounds up so it still sweeps every level it was computed to reach. Both ship today, so a side parameter would silently invert one of them. Pass the direction you mean.

Gotchas

Rounding DOWN can return 0, and for a PRICE that is the one value the pool always rejects (InvalidPrice). This helper does not hide that: a shared kernel that floored a price to one tick and a quantity to zero would be keying its behaviour on which of the two it was handed, which is exactly the guess this signature exists to avoid. Use roundPriceToTick for a price, which refuses to produce 0. For a quantity, 0 is the honest answer — the caller has no size left and must branch rather than submit dust.

This aligns to the grid and nothing else. It does not check minQuantity, which the pool tests BEFORE lot alignment and reverts as QuantityBelowMinimum. On every venue this repository deploys tickSize == lotSize == minQuantity, so alignment satisfies the minimum there; on an external spot or perp book the two can differ, and a caller sizing against a minimum wants ceilRawAmount.

Parameters

raw

bigint

step

bigint

direction

RawGridDirection

Returns

bigint

Example

Align a computed price and quantity before placing an order

ts
const trader = client.createTrader({ privateKey });
// `tickSize` and `lotSize` are the pool's own increments.
const { tickSize, lotSize } = await client.getBinaryBookParams(pool);

// A crossing buy rounds the limit UP so it still sweeps every level.
const price = snapRawToGrid(rawPrice, tickSize, "up");
// Size rounds DOWN so it never exceeds what the caller has.
const quantity = snapRawToGrid(rawQuantity, lotSize, "down");

// A quantity that floors to nothing is a real answer — branch, don't submit.
if (quantity > 0n) {
  await trader.placeOrder({ pool, side: "BUY_YES", price, quantity });
}

Throws

when step is not positive.