Listing mappers
The three functions that turn the listing backend’s wire JSON into the SDK’s shapes. getListingMarkets runs all of them for you, so you only reach for these when you hold a raw response yourself — a server route that proxies the backend, a fixture in a test, a cached payload you rehydrate.
import { toListingMarket, toListingMarketPage, toListingValue } from "@symmio/trading-core";They are pure and synchronous. None of them takes a Config, touches the network, or raises a SymmError.
toListingValue
Parse one of the backend’s 18-decimal value strings into a bigint.
toListingValue("1000000000000000000"); // 1000000000000000000n — 1.0 at LISTING_VALUE_DECIMALS
toListingValue("-25000000000000000"); // -25000000000000000n — a negative APY
toListingValue(null); // nullParameters
rawstring | null | undefinedrequiredThe value as the backend reported it.
Returns
bigint | nullThe value at LISTING_VALUE_DECIMALS, or null when
there is nothing to parse.
The return contract in full — three ways to get null, one to get a number:
| Input | Result |
|---|---|
null or undefined | null |
"", or any string that is only whitespace | null |
| A string that is not an optionally-signed decimal | null |
| A decimal string | its integer part as a bigint, sign preserved |
null is not 0. An absent figure and a figure of zero are different facts about a market — a listing an hour
old has no 30-day window, which is not the same as having earned nothing over thirty days. Collapsing the two makes
them indistinguishable in the UI.
Why the parse is lenient
The backend’s own schema types these fields as unsigned decimal strings. Live responses do not honor that on either count, so the parse handles both deviations rather than trusting the schema:
- Signs are preserved. The APY series carries negative values in practice, so a leading
-survives into thebigint. - Fractional tails are truncated toward zero. A fractional string would make
BigInt()throw outright, so the digits after the decimal point are dropped rather than rounded:"1234.9"is1234nand"-1234.9"is-1234n.
A string with no integer digits at all — ".5" — has nothing to truncate to and returns null, as does anything the pattern rejects ("n/a", "1e18").
toListingMarket
Map one raw row of the backend’s /v2/market/search response into a ListingMarket.
const market = toListingMarket(rawRow);Parameters
rawMarketSearchItemrequiredOne row of the backend’s response, in its generated wire shape. That type belongs to the generated client and is not
re-exported from the package root; name it as Parameters<typeof toListingMarket>[0] if you need it in a signature.
Returns
ListingMarketThe normalized row. See ListingMarket for every field.
What the mapping does:
- Renames the wire’s snake_case to the SDK’s camelCase (
contract_address→contractAddress,open_interest→openInterest). - Runs every money and rate string through
toListingValue, so absent figures staynull. - Folds the flat windowed columns into objects —
apr_1h…apr_30dbecomeaprByWindow.h1…aprByWindow.d30, and the two APY series add thelifetimecolumn they carry. - Normalizes
symbol_idandlisting_timetonullwhen the backend omits them.
chain_id and market_status are carried across as ListingDepositChainId and ListingMarketStatus. Both enums mirror the backend’s own values, so this is a naming of what arrived, not a validation of it — an unrecognized value from a newer backend passes through unchanged.
toListingMarketPage
Map the backend’s paginated envelope into a ListingMarketPage, mapping each row through toListingMarket on the way.
const page = toListingMarketPage(rawResponseBody);Parameters
rawPaginationResponseMarketSearchItemrequiredThe backend’s /v2/market/search response body.
Returns
ListingMarketPagetotalnumberTotal rows matching the query across all pages. 0 when the backend omits it.
limitnumberPage size the backend applied. 0 when omitted.
offsetnumberRow offset of this page. 0 when omitted.
itemsListingMarket[]The mapped rows. An empty array when the backend omits them.
Every envelope field is defaulted rather than required because the generated schema marks them all optional — the backend declares defaults for them instead of demanding them.
Related
getListingMarkets— the read that applies all three.ListingMarket— the shape they produce.- Pools — the slice overview and the 18-decimal value contract.