ListingMarket
One market in the permissionless-listing catalog — a row of the pools list.
import type { ListingMarket } from "@symmio/trading-core";Money and rate fields are bigint at LISTING_VALUE_DECIMALS (18), independent of the token’s own decimals. null means the backend reported no value for that field, which is distinct from zero.
Fields
contractAddressstringThe listed token’s contract address on chainId. Typed string, not viem’s Address: Solana listings
(chainId === ListingDepositChainId.SOLANA) carry a base58 address that is not 0x-prefixed. This is also the id
used to address a single market in the rest of the listing API.
chainIdListingDepositChainIdChain the token lives on and its listing deposit was made on — not the chain the market trades on. See
ListingDepositChainId.
symbolIdnumber | nullThe solver market id this listing trades under, or null when it has none yet. Assigned when the market reaches
ListingMarketStatus.LISTED; everything downstream — prices, notional caps, quotes, subgraph rows — keys off it, so
null here means the market is not tradable.
tokenTickerstringToken ticker, e.g. "SYMM".
tokenNamestringToken display name, e.g. "Symmio".
maxLeveragenumberMaximum leverage the market allows, as a whole multiplier (20 = 20x). A plain number — not 18-decimal scaled.
marketCapbigint | nullToken market capitalization, in USD.
vol24hbigint | nullTrailing 24-hour trading volume, in USD.
tvlbigint | nullTotal value locked in the market’s pool, in USD.
liquiditybigint | nullNotional the solver will still take on this market, in USD.
openInterestbigint | nullNotional currently open on this market, in USD.
reward24hbigint | nullLP rewards accrued over the trailing 24 hours, in USD.
aprbigint | nullHeadline APR. A percentage already (1e18 = 1%), not a fraction — render it without multiplying by 100.
aprByWindowListingTrailingWindowsAPR broken out per trailing window, same units as apr. There is no lifetime APR — use apr for the headline.
tvlDrivenApyListingApyWindowsAPY attributed to TVL growth, per window. A percentage already (1e18 = 1%), not a fraction — render it
without multiplying by 100.
priceDrivenApyListingApyWindowsAPY attributed to token price movement, per window. A percentage already (1e18 = 1%), not a fraction —
render it without multiplying by 100.
listingTimenumber | nullWhen the market went live, as a Unix timestamp in seconds. null before it is listed.
marketStatusListingMarketStatusWhere the market sits in the listing lifecycle. See ListingMarketStatus.
isLockedbooleanWhether the inventory service currently has this market’s pool locked against new deposits. Only deposits are
blocked — trading, withdrawals and every other flow stay available. Independent of marketStatus — a LISTED
market can be locked. The row carries only the flag; the reasons are on
getListingMarketDetail as lockReasons. See MarketLockReason.
Rate fields are signed. The backend’s own schema types its values as unsigned decimal strings, but live responses carry negative APY figures, so a formatter that assumes a non-negative number will render them wrong.
ListingMarketPage
One page of rows, with the totals needed to paginate.
totalnumberTotal rows matching the query across all pages.
limitnumberPage size the backend applied.
offsetnumberRow offset of this page.
itemsListingMarket[]The rows themselves.
ListingTrailingWindows
The same metric measured over each trailing window the backend reports. Every entry is a bigint at
LISTING_VALUE_DECIMALS, or null when there is no value for that window — a young market has no 30-day figure, and
null means absent, never zero.
h1bigint | nullTrailing 1 hour.
h6bigint | nullTrailing 6 hours.
h24bigint | nullTrailing 24 hours.
d30bigint | nullTrailing 30 days.
ListingApyWindows
A metric the backend reports over the trailing windows and since listing. Extends
ListingTrailingWindows with one field. Only the two APY series carry a lifetime column;
APR does not, which is why lifetime lives here rather than on ListingTrailingWindows.
lifetimebigint | nullSince the market was listed.
ListingMarketStatus
Lifecycle status of a market in the permissionless-listing service. The backend — not the chain — owns this state
machine. A market becomes tradable only at LISTED; before that it has no symbolId and no solver market behind it.
WAITING_FOR_DEPOSIT"waiting_for_deposit"Application accepted, the listing deposit has not landed at the custodial address yet.
UNDER_REVIEW"under_review"Deposit received, awaiting the operator’s decision.
REJECTED"rejected"The operator declined the listing; the deposit is refundable.
LISTED"listed"Live and tradable; symbolId is assigned.
DELISTED"delisted"Was live, has since been withdrawn from trading.
It is a string enum, so compare against the member rather than the literal:
import { ListingMarketStatus } from "@symmio/trading-core";
const tradable = market.marketStatus === ListingMarketStatus.LISTED;MarketLockReason
Why the inventory service has locked a market’s pool against new deposits. A lock blocks deposits only — trading,
withdrawals, claims and every other flow stay available. It is also orthogonal to
ListingMarketStatus: a LISTED market can be locked, and the lock lifts without the lifecycle
status moving. The catalogue row exposes only the boolean isLocked; the reasons come back on
getListingMarketDetail as lockReasons.
LIQUIDITY_EXPOSURE"LIQUIDITY_EXPOSURE"Locked on the service’s liquidity-exposure limit.
LOW_TVL"LOW_TVL"The pool’s TVL is below the service’s threshold.
PRICE_UNAVAILABLE"PRICE_UNAVAILABLE"The service has no price for the token.
SHORT_CIRCUIT"SHORT_CIRCUIT"The service’s short-circuit guard tripped.
MANUAL"MANUAL"An operator locked the market by hand.
UNKNOWN"UNKNOWN"A reason this SDK release does not recognize. The mapper folds every unrecognized wire value here rather than throwing, so a reason added by a newer backend never breaks the read.
import { MarketLockReason } from "@symmio/trading-core";
const lockedForTvl = detail.isLocked && detail.lockReasons.includes(MarketLockReason.LOW_TVL);Gate the deposit action on isLocked, not on the reasons: UNKNOWN is still a lock. Leave trading, withdrawals
and claims enabled — a lock does not touch them. Use lockReasons to explain the lock to the user, and treat
UNKNOWN as “locked for a reason this version cannot name”.
ListingDepositChainId
Chains the listing service accepts a listing deposit on. This is the chain the token lives on and where its listing collateral was deposited — it is not the chain the resulting market trades on. A market whose token is on Solana or BSC still trades on the SYMMIO deployment the listing service is configured for.
SOLANA0Sentinel for Solana — not an EVM chain id. Addresses are base58.
BSC56BNB Smart Chain.
BASE8453Base.
SONIC146Sonic.
ARBITRUM_ONE42161Arbitrum One.
HYPER_EVM999HyperEVM.
SOLANA = 0 is a sentinel, not a real chain id. A row on it carries a base58 contractAddress, so never feed one to
an EVM address helper without checking chainId first.
LISTING_VALUE_DECIMALS
The fixed-point scale of every money and rate field the listing service returns, exported as a constant:
import { LISTING_VALUE_DECIMALS } from "@symmio/trading-core";
LISTING_VALUE_DECIMALS; // 18The service reports these as decimal strings at 18 decimals, regardless of the token’s own decimals or the
collateral’s ("1000000000000000000" is 1). The SDK keeps them as bigint at that scale so nothing is lost; format
at the display edge, and give the null case its own rendering:
import { LISTING_VALUE_DECIMALS } from "@symmio/trading-core";
import { formatUnits } from "@symmio/utils/decimal";
function formatListingValue(raw: bigint | null): string {
if (raw === null) return "—";
return formatUnits(raw, LISTING_VALUE_DECIMALS).toFixed(2);
}Related
getListingMarkets— the read that produces these rows.- Pools — the slice overview and the value contract in full.
useListingMarkets— the React hook.