> ## Documentation Index
> Fetch the complete documentation index at: https://docs.livepeer.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Exchanges with LPT Listed

> A list of exchanges where the Livepeer Token (LPT) is listed. Note: this information is fetched from Coingecko weekly

export const exchangesMetadata = {
  lastUpdated: '2026-05-25T13:20:55.759Z',
  source: 'CoinGecko API',
  coinId: 'livepeer',
  totalExchanges: 77,
  cex: 74,
  dex: 3
};

export const exchangesData = [{
  Exchange: 'Azbit',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://azbit.com/exchange/LPT_USDT?referralCode=OH5QDS1',
  Volume24h: '$223,961'
}, {
  Exchange: 'Biconomy.com',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.biconomy.com/exchange/LPT_USDT',
  Volume24h: '$1,416,989'
}, {
  Exchange: 'Binance',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.binance.com/en/trade/LPT_USDT?ref=37754157',
  Volume24h: '$5,650,647'
}, {
  Exchange: 'Binance US',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.binance.us/trade/pro/LPT_USDT',
  Volume24h: '$987'
}, {
  Exchange: 'BingX',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://bingx.com/en/spot/LPTUSDT',
  Volume24h: '$206,246'
}, {
  Exchange: 'Bit2Me',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/EUR',
  URL: 'https://pro.bit2me.com/exchange/LPT-EUR',
  Volume24h: '$55,471'
}, {
  Exchange: 'Bitbaby',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.bitbaby.com/en-us/spot/LPT_USDT',
  Volume24h: '$262,437'
}, {
  Exchange: 'Bitbank',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/JPY',
  URL: 'https://app.bitbank.cc/trade/lpt_jpy',
  Volume24h: '$24,829'
}, {
  Exchange: 'BitDelta',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://bitdelta.com/en/trade/LPT_USDT',
  Volume24h: '$203,770'
}, {
  Exchange: 'Bitget',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.bitget.com/spot/LPTUSDT',
  Volume24h: '$297,326'
}, {
  Exchange: 'Bithumb',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/KRW',
  URL: 'https://www.bithumb.com/trade/order/LPT_KRW',
  Volume24h: '$359,327'
}, {
  Exchange: 'BitKan',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://bitkan.com/trade/LPT-USDT',
  Volume24h: '$85,220'
}, {
  Exchange: 'Bitkub',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/THB',
  URL: 'https://www.bitkub.com/th/market/LPT_THB',
  Volume24h: '$150'
}, {
  Exchange: 'Bitlo',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/TRY',
  URL: 'https://www.bitlo.com/kolay-alis-satis/LPT-TRY',
  Volume24h: '$1,372'
}, {
  Exchange: 'BitMart',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.bitmart.com/trade/en?symbol=LPT_USDT',
  Volume24h: '$253,203'
}, {
  Exchange: 'Bitrue',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.bitrue.com/trade/lpt_usdt',
  Volume24h: '$24,434'
}, {
  Exchange: 'Bitunix',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.bitunix.com/spot-trade/LPTUSDT',
  Volume24h: '$154,050'
}, {
  Exchange: 'Bitvavo',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/EUR',
  URL: 'https://account.bitvavo.com/markets/LPT-EUR',
  Volume24h: '$1,384,972'
}, {
  Exchange: 'BloFin',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://blofin.com/spot/LPT-USDT',
  Volume24h: '$1,221,515'
}, {
  Exchange: 'BTCC',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.btcc.com/en-US/spot/LPTUSDT',
  Volume24h: '$2,715,526'
}, {
  Exchange: 'BtcTurk | Kripto',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/TRY',
  URL: 'https://pro.btcturk.com/pro/al-sat/LPT_TRY',
  Volume24h: '$1,143,350'
}, {
  Exchange: 'BTSE',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.btse.com/en/trading/LPT-USDT',
  Volume24h: '$18,195'
}, {
  Exchange: 'BVOX',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.bitvenus.me/exchange/LPT/USDT',
  Volume24h: '$314,733'
}, {
  Exchange: 'BYDFi',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.bydfi.com/en/spot/lpt_usdt',
  Volume24h: '$611,269'
}, {
  Exchange: 'CEX.IO',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USD',
  URL: 'https://trade.cex.io/spot/LPT-USD',
  Volume24h: '$19'
}, {
  Exchange: 'Coinbase Exchange',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USD',
  URL: 'https://www.coinbase.com/advanced-trade/spot/LPT-USD',
  Volume24h: '$287,055'
}, {
  Exchange: 'CoinDCX',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/INR',
  URL: 'https://coindcx.com/trade/LPTINR',
  Volume24h: '$578'
}, {
  Exchange: 'CoinEx',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.coinex.com/en/exchange/lpt-usdt?',
  Volume24h: '$27,547'
}, {
  Exchange: 'Coinstore',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.coinstore.com/#/spot/LPTUSDT',
  Volume24h: '$560,559'
}, {
  Exchange: 'CoinTR',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/TRY',
  URL: 'https://www.cointr.com/en/spot/LPTTRY?type=spot',
  Volume24h: '$116,872'
}, {
  Exchange: 'CoinUp.io',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.coinup.io/en_US/trade/LPT_USDT',
  Volume24h: '$57,720'
}, {
  Exchange: 'CoinW',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.coinw.com/spot/lptusdt',
  Volume24h: '$1,792,521'
}, {
  Exchange: 'Crypto.com Exchange',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USD',
  URL: 'https://crypto.com/exchange/trade/spot/LPT_USD',
  Volume24h: '$57,386'
}, {
  Exchange: 'Deepcoin',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.deepcoin.com/en/Spot?currentId=LPT',
  Volume24h: '$361,222'
}, {
  Exchange: 'DigiFinex',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.digifinex.com/en-ww/trade/USDT/LPT',
  Volume24h: '$153,104'
}, {
  Exchange: 'Foxbit',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/BRL',
  URL: 'https://foxbit.com.br/grafico-bitcoin/',
  Volume24h: '$12'
}, {
  Exchange: 'Gate',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.gate.com/trade/LPT_USDT',
  Volume24h: '$435,515'
}, {
  Exchange: 'Gemini',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USD',
  URL: 'https://exchange.gemini.com/trade/LPTUSD',
  Volume24h: '$1,125'
}, {
  Exchange: 'Giottus',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/INR',
  URL: 'https://www.giottus.com/tradeview/LPT-INR',
  Volume24h: '$2'
}, {
  Exchange: 'GroveX',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.grovex.io/en_US/trade/LPT_USDT',
  Volume24h: '$1,425'
}, {
  Exchange: 'Hibt',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://hibt.com/trade/LPT-USDT',
  Volume24h: '$121,997'
}, {
  Exchange: 'Hotcoin',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.hotcoin.com/en_US/trade/exchange/?tradeCode=lpt_usdt',
  Volume24h: '$270,802'
}, {
  Exchange: 'HTX',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.huobi.com/en-us/exchange/lpt_usdt',
  Volume24h: '$1,997,685'
}, {
  Exchange: 'Icrypex',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.icrypex.com/en/trade/spot/LPTUSDT',
  Volume24h: '$5,134'
}, {
  Exchange: 'Indodax',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/IDR',
  URL: 'https://indodax.com/market/LPTIDR',
  Volume24h: '$465'
}, {
  Exchange: 'Kanga',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://trade.kanga.exchange/market/LPT-USDT',
  Volume24h: '$2,836'
}, {
  Exchange: 'KCEX',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.kcex.com/exchange/LPT_USDT',
  Volume24h: '$123,151'
}, {
  Exchange: 'Korbit',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/KRW',
  URL: 'https://lightning.korbit.co.kr/trade/?market=lpt-krw',
  Volume24h: '$146'
}, {
  Exchange: 'Kraken',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USD',
  URL: 'https://pro.kraken.com/app/trade/LPT-USD',
  Volume24h: '$132,585'
}, {
  Exchange: 'KuCoin',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.kucoin.com/trade/LPT-USDT',
  Volume24h: '$1,113,911'
}, {
  Exchange: 'LATOKEN',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://latoken.com/exchange/USDT-LPT',
  Volume24h: '$19,121'
}, {
  Exchange: 'LBank',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.lbank.com/trade/lpt_usdt',
  Volume24h: '$1,198,764'
}, {
  Exchange: 'Mercado Bitcoin',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/BRL',
  URL: 'https://www.mercadobitcoin.com.br/criptomoedas/LPT-BRL',
  Volume24h: '$1'
}, {
  Exchange: 'MEXC',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.mexc.com/exchange/LPT_USDT',
  Volume24h: '$141,635'
}, {
  Exchange: 'Mudrex',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://mudrex.com/trading-volume-mudrex',
  Volume24h: '$632'
}, {
  Exchange: 'Nami Exchange',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://nami.exchange/trade/LPT-USDT',
  Volume24h: '$2,200'
}, {
  Exchange: 'Niza.io',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://niza.io/en/trade/lpt-usdt',
  Volume24h: '$35,440'
}, {
  Exchange: 'OKX',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.okx.com/trade-spot/lpt-usdt',
  Volume24h: '$1,130,159'
}, {
  Exchange: 'OrangeX',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.orangex.com/spot/LPT-USDT-SPOT',
  Volume24h: '$1,806,705'
}, {
  Exchange: 'Ourbit',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.ourbit.com/exchange/LPT_USDT',
  Volume24h: '$576,125'
}, {
  Exchange: 'Paribu',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/TRY',
  URL: 'https://www.paribu.com/markets/lpt_tl?view=classic',
  Volume24h: '$446,840'
}, {
  Exchange: 'Pionex',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.pionex.com/en/trade/LPT_USDT/Bot',
  Volume24h: '$3,865,642'
}, {
  Exchange: 'Poloniex',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://poloniex.com/trade/LPT_USDT/?type=spot',
  Volume24h: '$58'
}, {
  Exchange: 'Tapbit',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.tapbit.com/spot/exchange/LPT_USDT',
  Volume24h: '$323,270'
}, {
  Exchange: 'TokoCrypto',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.tokocrypto.com/trade/LPTUSDT',
  Volume24h: '$4,263'
}, {
  Exchange: 'Toobit',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.toobit.com/en-US/spot/LPT_USDT',
  Volume24h: '$1,462,959'
}, {
  Exchange: 'Tothemoon',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://tothemoon.com/trading/LPT_USDT',
  Volume24h: '$17,043'
}, {
  Exchange: 'Uniswap V2 (Ethereum)',
  Type: 'DEX',
  TrustScore: '⚪',
  'Trading Pair': '0X58B6A8A3302369DAEC383334672404EE733AB239/0XC02AAA39B223FE8D0A0E5C4F27EAD9083C756CC2',
  URL: 'https://app.uniswap.org/explore/tokens/ethereum/0x58b6a8a3302369daec383334672404ee733ab239',
  Volume24h: '$2,361'
}, {
  Exchange: 'Uniswap V3 (Arbitrum One)',
  Type: 'DEX',
  TrustScore: '⚪',
  'Trading Pair': '0X289BA1701C2F088CF0FAF8B3705246331CB8A839/0X82AF49447D8A07E3BD95BD0D56F35241523FBAB1',
  URL: 'https://app.uniswap.org/explore/tokens/arbitrum/0x289ba1701c2f088cf0faf8b3705246331cb8a839',
  Volume24h: '$60,964'
}, {
  Exchange: 'Uniswap V3 (Ethereum)',
  Type: 'DEX',
  TrustScore: '⚪',
  'Trading Pair': '0X58B6A8A3302369DAEC383334672404EE733AB239/0XC02AAA39B223FE8D0A0E5C4F27EAD9083C756CC2',
  URL: 'https://app.uniswap.org/explore/tokens/ethereum/0x58b6a8a3302369daec383334672404ee733ab239',
  Volume24h: '$2,736'
}, {
  Exchange: 'Upbit',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/KRW',
  URL: 'https://upbit.com/exchange?code=CRIX.UPBIT.KRW-LPT',
  Volume24h: '$1,576,371'
}, {
  Exchange: 'Upbit Indonesia ',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/BTC',
  URL: 'https://id.upbit.com/exchange?code=CRIX.UPBIT.BTC-LPT',
  Volume24h: '$4,481'
}, {
  Exchange: 'Websea',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.websea.com/en/trade/LPT-USDT',
  Volume24h: '$1,904,197'
}, {
  Exchange: 'WEEX',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.weex.com/spot/LPT-USDT',
  Volume24h: '$49,181'
}, {
  Exchange: 'WhiteBIT',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://whitebit.com/trade/LPT_USDT',
  Volume24h: '$1,071,117'
}, {
  Exchange: 'XBO.com',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.xbo.com/platform/spot/LPT-USDT',
  Volume24h: '$2,822'
}, {
  Exchange: 'XT.COM',
  Type: 'CEX',
  TrustScore: '⚪',
  'Trading Pair': 'LPT/USDT',
  URL: 'https://www.xt.com/en/trade/lpt_usdt',
  Volume24h: '$651,839'
}];

export const CopyText = ({text, label, className = '', style = {}, ...rest}) => {
  const handleCopy = () => {
    navigator.clipboard.writeText(text);
  };
  return <span className={className} style={{
    display: 'flex',
    alignItems: 'center',
    padding: '0.2rem 0.4rem',
    borderRadius: "4px",
    fontSize: '0.85rem',
    fontFamily: 'monospace',
    backgroundColor: 'var(--lp-color-bg-card)',
    border: '1px solid var(--lp-color-border-default)',
    minWidth: 0,
    overflow: 'hidden',
    ...style
  }} {...rest}>
      {label && <strong style={{
    flexShrink: 0,
    marginRight: "var(--lp-spacing-2)"
  }}>{label}</strong>}
      <span style={{
    overflow: 'hidden',
    textOverflow: 'ellipsis',
    whiteSpace: 'nowrap',
    flex: 1,
    minWidth: 0
  }}>
        {text}
      </span>
      <button onClick={handleCopy} style={{
    background: 'none',
    border: 'none',
    cursor: 'pointer',
    padding: '0 0 0 0.4rem',
    display: 'inline-flex',
    alignItems: 'center',
    color: 'var(--lp-color-text-secondary)',
    flexShrink: 0
  }} title="Copy to clipboard">
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
          <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
          <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
        </svg>
      </button>
    </span>;
};

export const LinkIcon = ({href, target = '_blank', rel = 'noopener noreferrer', style = {}, className = '', icon = 'arrow-up-right-from-square', size = 12, ...iconProps}) => {
  return <a href={href} target={target} rel={rel} className={className} style={{
    borderBottom: 'none',
    textDecoration: 'none',
    ...style
  }}>
      <Icon icon={icon} size={size} {...iconProps} />
    </a>;
};

export const DynamicTable = ({tableTitle = null, headerList = [], itemsList = [], monospaceColumns = [], columnWidths = {}, contentFitColumns = [], showSeparators = false, margin, className = "", style = {}, ...rest}) => {
  if (!headerList.length) {
    return <div>No headers provided</div>;
  }
  const safeContentFitColumns = Array.isArray(contentFitColumns) ? contentFitColumns : [];
  const usesContentFitColumns = safeContentFitColumns.length > 0;
  const isContentFitColumn = header => safeContentFitColumns.includes(header);
  const getColumnStyle = header => {
    const widthStyle = columnWidths[header] ? {
      width: columnWidths[header],
      minWidth: columnWidths[header],
      maxWidth: columnWidths[header]
    } : {};
    const contentFitStyle = !columnWidths[header] && isContentFitColumn(header) ? {
      width: "1%",
      whiteSpace: "nowrap"
    } : {};
    return {
      ...contentFitStyle,
      ...widthStyle
    };
  };
  return <div className={className} style={style} {...rest}>
      {tableTitle && <div style={{
    fontStyle: "italic",
    margin: 0
  }}>
          <strong>{tableTitle}</strong>
        </div>}
      <div style={{
    overflowX: "auto",
    ...margin != null && ({
      margin
    })
  }} role="region" tabIndex={0} aria-label={tableTitle ? `Scrollable table: ${tableTitle}` : "Scrollable table"}>
        <table data-docs-dynamic-table style={{
    width: "100%",
    tableLayout: usesContentFitColumns ? "auto" : "fixed",
    borderCollapse: "collapse",
    fontSize: "0.9rem",
    marginTop: 0
  }}>
          <thead>
            <tr style={{
    backgroundColor: "var(--lp-color-accent)",
    color: "var(--lp-color-on-accent)",
    borderBottom: "1px solid var(--lp-color-border-default)"
  }}>
              {headerList.map((header, index) => <th key={index} style={{
    padding: "10px 8px",
    textAlign: "left",
    fontWeight: "600",
    color: "var(--lp-color-on-accent)",
    ...getColumnStyle(header)
  }}>
                  {header}
                </th>)}
            </tr>
          </thead>
          <tbody>
            {itemsList.filter(item => showSeparators || !item?.__separator).map((item, rowIndex) => item?.__separator ? <tr key={rowIndex} style={{
    backgroundColor: "var(--lp-color-accent)",
    color: "var(--lp-color-on-accent)",
    borderBottom: "1px solid var(--lp-color-accent)"
  }}>
                  <td colSpan={headerList.length} style={{
    padding: "6px 8px",
    fontWeight: "700",
    color: "var(--lp-color-on-accent)",
    letterSpacing: "0.01em"
  }}>
                    {(item[headerList[0]] ?? item.Category) ?? "Category"}
                  </td>
                </tr> : <tr key={rowIndex} style={{
    borderBottom: "1px solid var(--lp-color-border-default)"
  }}>
                  {headerList.map((header, colIndex) => {
    const value = (item[header] ?? item[header.toLowerCase()]) ?? "-";
    const isMonospace = monospaceColumns.includes(colIndex);
    return <td key={colIndex} style={{
      padding: "8px 8px",
      fontFamily: isMonospace ? "monospace" : "inherit",
      wordWrap: "break-word",
      overflowWrap: "break-word",
      ...getColumnStyle(header)
    }}>
                        {isMonospace ? <code>{value}</code> : value}
                      </td>;
  })}
                </tr>)}
          </tbody>
        </table>
      </div>
    </div>;
};

export const SearchTable = ({TableComponent = null, tableTitle = null, headerList = [], itemsList = [], monospaceColumns = [], margin, searchPlaceholder = 'Search...', searchColumns = [], categoryColumn = 'Category', filterColumns = [], columnWidths = {}, contentFitColumns = [], columnVariant = {}, categoryBadges = [], textIcons = [], showSeparators = false, separatorColumn = null, boldFirstColumn = true, className = '', style = {}}) => {
  const allFilterCols = [categoryColumn, ...filterColumns];
  const [query, setQuery] = useState('');
  const [selections, setSelections] = useState(() => {
    const init = {};
    allFilterCols.forEach(col => {
      init[col] = 'All';
    });
    return init;
  });
  const safeHeaderList = Array.isArray(headerList) ? headerList : [];
  const safeItemsList = Array.isArray(itemsList) ? itemsList : [];
  const safeMonospaceColumns = Array.isArray(monospaceColumns) ? monospaceColumns : [];
  const safeSearchColumns = Array.isArray(searchColumns) ? searchColumns : [];
  const activeColumns = safeSearchColumns.length ? safeSearchColumns : safeHeaderList;
  const normalizedQuery = query.trim().toLowerCase();
  const badgeColorMap = {};
  categoryBadges.forEach(b => {
    badgeColorMap[b.label.toLowerCase()] = b.color;
  });
  const textIconMap = {};
  textIcons.forEach(t => {
    textIconMap[t.label.toLowerCase()] = t.icon;
  });
  const getOptionsForColumn = (colName, colIndex) => {
    let scoped = safeItemsList;
    for (let i = 0; i < colIndex; i++) {
      const prevCol = allFilterCols[i];
      const prevSel = selections[prevCol];
      if (prevSel !== 'All') {
        scoped = scoped.filter(item => String(item?.[prevCol] || '') === prevSel);
      }
    }
    return [...new Set(scoped.map(item => String(item?.[colName] || '')).filter(Boolean))].sort((a, b) => a.localeCompare(b, 'en', {
      sensitivity: 'base'
    }));
  };
  const filteredItems = safeItemsList.filter(item => allFilterCols.every(col => {
    const sel = selections[col];
    return sel === 'All' || String(item?.[col] || '') === sel;
  }));
  const searchedItems = !normalizedQuery ? filteredItems : filteredItems.filter(item => activeColumns.some(column => {
    const value = (item?.[column] ?? item?.[String(column).toLowerCase()]) ?? '';
    return String(value).toLowerCase().includes(normalizedQuery);
  }));
  const sortedItems = [...searchedItems].sort((a, b) => {
    for (const col of allFilterCols) {
      const cmp = String(a[col] || '').localeCompare(String(b[col] || ''), 'en', {
        sensitivity: 'base'
      });
      if (cmp !== 0) return cmp;
    }
    return 0;
  });
  const firstColumnName = safeHeaderList[0];
  const renderVariant = (value, variant, item, header) => {
    if (variant === 'bold' && typeof value === 'string') {
      return <strong>{value}</strong>;
    }
    if (variant === 'badge' && typeof value === 'string') {
      const colorName = badgeColorMap[value.toLowerCase()];
      if (colorName) {
        return <Badge color={colorName}>{value}</Badge>;
      }
    }
    if (variant === 'textIcon' && typeof value === 'string') {
      const icon = textIconMap[value.toLowerCase()];
      if (icon) {
        return <span style={{
          display: 'inline-flex',
          alignItems: 'center',
          gap: '0.35rem'
        }}>
            {icon} {value}
          </span>;
      }
    }
    if (variant === 'addressWrapper' && typeof value === 'string') {
      const href = item?.[`_${header}Href`] ?? item?._addressHref;
      return <div style={{
        display: 'flex',
        alignItems: 'center',
        gap: '0.35rem',
        width: '100%',
        minWidth: 0
      }}>
          <CopyText text={value} style={{
        flex: 1
      }} />
          {href && <LinkIcon href={href} color="var(--lp-color-accent)" />}
        </div>;
    }
    return value;
  };
  const displayItems = sortedItems.map(item => {
    const out = {
      ...item,
      _sepKey: String(item[separatorColumn || categoryColumn] || '')
    };
    for (const header of safeHeaderList) {
      if (columnVariant[header] && out[header] !== undefined) {
        out[header] = renderVariant(out[header], columnVariant[header], item, header);
      }
    }
    if (boldFirstColumn && firstColumnName && !columnVariant[firstColumnName] && typeof out[firstColumnName] === 'string') {
      out[firstColumnName] = <strong>{out[firstColumnName]}</strong>;
    }
    return out;
  });
  const withSeparators = [];
  let lastSep = '';
  displayItems.forEach(item => {
    const sepKey = item._sepKey || '';
    if (showSeparators && sepKey && sepKey !== lastSep) {
      withSeparators.push({
        __separator: true,
        [safeHeaderList[0]]: sepKey.toUpperCase()
      });
      lastSep = sepKey;
    }
    withSeparators.push(item);
  });
  const selectStyle = {
    minWidth: '150px',
    padding: '8px 12px',
    borderRadius: '8px',
    border: '1px solid var(--lp-color-border-default)',
    background: 'var(--lp-color-bg-page)',
    color: 'var(--lp-color-text-secondary)'
  };
  const updateSelection = (col, colIndex, value) => {
    const next = {
      ...selections,
      [col]: value
    };
    for (let i = colIndex + 1; i < allFilterCols.length; i++) {
      next[allFilterCols[i]] = 'All';
    }
    setSelections(next);
  };
  return <div className={className} style={style}>
      <div style={{
    marginBottom: "var(--lp-spacing-2)",
    display: 'flex',
    flexWrap: 'wrap',
    gap: "var(--lp-spacing-2)",
    alignItems: 'center'
  }}>
        <input type="text" value={query} placeholder={searchPlaceholder} onChange={e => setQuery(e.target.value)} aria-label="Filter table rows" style={{
    width: '100%',
    maxWidth: '420px',
    padding: '8px 12px',
    borderRadius: '8px',
    border: '1px solid var(--lp-color-border-default)',
    background: 'var(--lp-color-bg-page)',
    color: 'var(--lp-color-text-secondary)'
  }} />
        {allFilterCols.map((col, colIndex) => {
    const options = getOptionsForColumn(col, colIndex);
    if (options.length === 0) return null;
    const parentLabel = colIndex > 0 && selections[allFilterCols[colIndex - 1]] !== 'All' ? selections[allFilterCols[colIndex - 1]] : col.toLowerCase() + 's';
    return <select key={col} value={selections[col]} onChange={e => updateSelection(col, colIndex, e.target.value)} aria-label={`Filter by ${col}`} style={selectStyle}>
              <option value="All">All {parentLabel}</option>
              {options.map(o => <option key={o} value={o}>
                  {o}
                </option>)}
            </select>;
  })}
      </div>

      {typeof TableComponent === 'function' ? <TableComponent tableTitle={tableTitle} headerList={safeHeaderList} itemsList={withSeparators} monospaceColumns={safeMonospaceColumns} columnWidths={columnWidths} contentFitColumns={contentFitColumns} showSeparators={showSeparators} margin={margin} /> : <Warning>SearchTable requires a `TableComponent` prop.</Warning>}
    </div>;
};

<Info>
  **Last Updated:** {exchangesMetadata.lastUpdated} | Data sourced from [CoinGecko](https://www.coingecko.com/en/coins/livepeer)
</Info>

<Note>
  **Trust Score Legend:** 🟢 High | 🟡 Medium | 🔴 Low | ⚪ Unknown
</Note>

## LPT Exchanges

<Tip>
  {exchangesMetadata.totalExchanges} exchanges listed ({exchangesMetadata.cex} centralised, {exchangesMetadata.dex} decentralised). Use the search and category filters to find specific exchanges.
</Tip>

<SearchTable TableComponent={DynamicTable} tableTitle="Exchanges with LPT Listed" headerList={['Exchange', 'Type', 'TrustScore', 'Trading Pair', 'Volume24h']} itemsList={exchangesData} searchPlaceholder="Search exchanges..." searchColumns={['Exchange', 'Type', 'Trading Pair']} categoryColumn="Type" />

## About This Data

Exchange data is fetched weekly from the [CoinGecko API](https://www.coingecko.com/en/api/documentation) via GitHub Actions (`update-exchanges-data.yml`). The data file lives at `snippets/automations/exchanges/exchangesData.jsx`.

Trust scores are assigned by CoinGecko based on exchange liquidity, web traffic, API quality, and regulatory compliance.
