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

# Introduction

> Spot and perps trading infrastructure for traders, builders, or AI agents.

export const MONACO_TICKER_SCREENER_CACHE_KEY = "screener-active-100";
export const MONACO_TICKER_SCREENER_URL = "https://staging.apimonaco.xyz/api/v1/market/screener?page=1&pageSize=100&isActive=true";
export const MONACO_MARKET_DATA_CACHE_TTL_MS = 60000;
export const MONACO_MARKET_DATA_STALE_MS = 5 * 60000;
export const MONACO_MARKET_DATA_CACHE_PREFIX = "monaco-docs-market-data:";
export const MONACO_INTRO_AUDIENCES = ["traders", "builders", "market makers", "institutions", "wallets", "custodians", "AI agents", "everyone"];
export const MONACO_INTRO_TYPE_MS = 55;
export const MONACO_INTRO_DELETE_MS = 28;
export const MONACO_INTRO_HOLD_MS = 1150;

export function monacoMarketCacheStore() {
  const root = globalThis;
  if (!root.__monacoMarketDataCache) {
    root.__monacoMarketDataCache = {
      values: {},
      inflight: {}
    };
  }
  return root.__monacoMarketDataCache;
}

export function monacoMarketCacheStorageKey(key) {
  return `${MONACO_MARKET_DATA_CACHE_PREFIX}${key}`;
}

export function readMonacoMarketLocalStorageCache(key) {
  try {
    const storage = globalThis.localStorage;
    const value = storage ? storage.getItem(monacoMarketCacheStorageKey(key)) : null;
    if (!value) return null;
    return JSON.parse(value);
  } catch (error) {
    return null;
  }
}

export function writeMonacoMarketLocalStorageCache(key, entry) {
  try {
    const storage = globalThis.localStorage;
    if (storage) storage.setItem(monacoMarketCacheStorageKey(key), JSON.stringify(entry));
  } catch (error) {}
}

export function readMonacoMarketCache(key, options = {}) {
  const ttlMs = options.ttlMs == null ? MONACO_MARKET_DATA_CACHE_TTL_MS : options.ttlMs;
  const staleMs = options.staleMs == null ? MONACO_MARKET_DATA_STALE_MS : options.staleMs;
  const now = Date.now();
  const store = monacoMarketCacheStore();
  const memoryEntry = store.values[key];
  const localEntry = memoryEntry || readMonacoMarketLocalStorageCache(key);
  const age = localEntry ? now - Number(localEntry.timestamp || 0) : Infinity;
  if (!localEntry || age > staleMs) return null;
  store.values[key] = localEntry;
  return {
    data: localEntry.data,
    timestamp: localEntry.timestamp,
    isFresh: age <= ttlMs
  };
}

export async function fetchMonacoMarketData(key, url) {
  const store = monacoMarketCacheStore();
  if (store.inflight[key]) return store.inflight[key];
  store.inflight[key] = fetch(url).then(async response => {
    if (!response.ok) throw new Error("Unable to load Monaco market data.");
    const entry = {
      data: await response.json(),
      timestamp: Date.now()
    };
    store.values[key] = entry;
    writeMonacoMarketLocalStorageCache(key, entry);
    return entry;
  }).finally(() => {
    delete store.inflight[key];
  });
  return store.inflight[key];
}

export const monacoMarketTickerStyles = `
@keyframes monacoIntroCaretBlink {
	0%,
	49% {
		opacity: 1;
	}
	50%,
	100% {
		opacity: 0;
	}
}

@keyframes monacoIntroGlowPulse {
	0%,
	100% {
		text-shadow: 0 0 1.75rem rgba(84, 224, 166, 0.35);
	}
	50% {
		text-shadow: 0 0 2.85rem rgba(84, 224, 166, 0.6);
	}
}

.monaco-market-ticker-shell {
	--ticker-surface: rgba(35, 51, 41, 0.035);
	--ticker-border: rgba(35, 51, 41, 0.12);
	--ticker-label-surface: rgba(35, 51, 41, 0.075);
	--ticker-text: #18231d;
	--ticker-muted: #526258;
	--ticker-positive: #1f7a4d;
	--ticker-negative: #b42318;
	display: flex;
	overflow: hidden;
	margin: 0 0 3rem;
	border: 1px solid var(--ticker-border);
	border-radius: 8px;
	background: var(--ticker-surface);
	color: var(--ticker-text);
}

.monaco-market-ticker-shell a {
	color: inherit;
}

.monaco-market-ticker-shell .monaco-market-status,
.monaco-market-ticker-shell .monaco-market-symbol,
.monaco-market-ticker-shell .monaco-market-link {
	color: var(--ticker-text) !important;
}

.monaco-market-ticker-shell .monaco-market-price {
	color: var(--ticker-muted) !important;
}

.monaco-market-ticker-shell .monaco-market-positive {
	color: var(--ticker-positive) !important;
}

.monaco-market-ticker-shell .monaco-market-negative {
	color: var(--ticker-negative) !important;
}

:where(.dark, [data-theme='dark']) .monaco-market-ticker-shell {
	--ticker-surface: rgba(26, 38, 32, 0.34);
	--ticker-border: rgba(166, 190, 174, 0.18);
	--ticker-label-surface: rgba(166, 190, 174, 0.08);
	--ticker-text: #f4faf5;
	--ticker-muted: #b6c4ba;
	--ticker-positive: #74d99f;
	--ticker-negative: #ff8d80;
}

.monaco-market-ticker-label {
	display: flex;
	flex: 0 0 auto;
	align-items: center;
	border-right: 1px solid var(--ticker-border);
	padding: 0.42rem 0.9rem;
	background: var(--ticker-label-surface);
	color: var(--ticker-text);
	font-size: 0.78rem;
	font-weight: 850;
	white-space: nowrap;
}

.monaco-market-ticker {
	flex: 1 1 auto;
	overflow: hidden;
	min-width: 0;
	min-height: 2.25rem;
	color: var(--ticker-text);
}

.monaco-market-ticker-shell .monaco-market-ticker {
	margin: 0;
	border: 0;
	border-radius: 0;
	background: transparent;
}

.monaco-market-ticker-track {
	display: flex;
	width: max-content;
	min-width: 100%;
	animation: monacoTickerScroll 42s linear infinite;
}

.monaco-market-ticker:hover .monaco-market-ticker-track {
	animation-play-state: paused;
}

.monaco-market-item {
	position: relative;
	isolation: isolate;
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	column-gap: 0.5rem;
	width: 9.25rem;
	min-height: 2.25rem;
	align-content: center;
	align-items: center;
	border-right: 1px solid var(--ticker-border);
	padding: 0.34rem 0.62rem;
	color: inherit;
	text-decoration: none;
	white-space: nowrap;
}

.monaco-market-item::after {
	position: absolute;
	inset: 0;
	z-index: -1;
	background: linear-gradient(90deg, var(--ticker-surface) 0%, rgba(255, 255, 255, 0.72) 50%, var(--ticker-surface) 100%);
	content: "";
	transition: background-color 160ms ease;
}

:where(.dark, [data-theme='dark']) .monaco-market-item::after {
	background: linear-gradient(90deg, rgba(9, 13, 11, 0.68) 0%, rgba(9, 13, 11, 0.42) 48%, rgba(9, 13, 11, 0.68) 100%);
}

.monaco-market-item-link:hover::after {
	background:
		linear-gradient(rgba(35, 51, 41, 0.075), rgba(35, 51, 41, 0.075)),
		linear-gradient(90deg, var(--ticker-surface) 0%, rgba(255, 255, 255, 0.76) 50%, var(--ticker-surface) 100%);
}

:where(.dark, [data-theme='dark']) .monaco-market-item-link:hover::after {
	background:
		linear-gradient(rgba(244, 250, 245, 0.09), rgba(244, 250, 245, 0.09)),
		linear-gradient(90deg, rgba(9, 13, 11, 0.68) 0%, rgba(9, 13, 11, 0.42) 48%, rgba(9, 13, 11, 0.68) 100%);
}

.monaco-market-item-link:hover .monaco-market-symbol {
	text-decoration: none;
}

.monaco-market-item-link:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: -4px;
}

.monaco-market-status {
	font-size: 0.72rem;
	font-weight: 800;
	letter-spacing: 0;
	text-transform: uppercase;
	color: var(--ticker-muted);
}

.monaco-market-main {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	grid-template-rows: auto auto;
	column-gap: 0.38rem;
	align-items: center;
	min-width: 0;
}

.monaco-market-icon {
	grid-row: 1 / 3;
	box-sizing: border-box;
	width: 1.22rem;
	height: 1.22rem;
	border-radius: 50%;
	border: 1px solid rgba(35, 51, 41, 0.08);
	background: rgba(244, 250, 245, 0.92);
	object-fit: contain;
	padding: 0.12rem;
	box-shadow: 0 1px 3px rgba(10, 15, 12, 0.08);
}

:where(.dark, [data-theme='dark']) .monaco-market-icon {
	border-color: rgba(244, 250, 245, 0.1);
	background: rgba(244, 250, 245, 0.94);
}

.monaco-market-icon-fallback {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: var(--ticker-text);
	font-size: 0.52rem;
	font-weight: 850;
	line-height: 1;
}

.monaco-market-symbol {
	position: relative;
	z-index: 1;
	overflow: hidden;
	min-width: 0;
	text-overflow: ellipsis;
	font-size: 0.76rem;
	line-height: 0.92rem;
	font-weight: 800;
}

.monaco-market-price {
	position: relative;
	z-index: 1;
	overflow: hidden;
	min-width: 0;
	text-overflow: ellipsis;
	font-variant-numeric: tabular-nums;
	font-size: 0.68rem;
	font-weight: 760;
	line-height: 0.8rem;
	color: var(--ticker-muted);
}

.monaco-market-change {
	position: relative;
	z-index: 1;
	font-variant-numeric: tabular-nums;
	font-size: 0.66rem;
	line-height: 0.86rem;
	font-weight: 800;
	text-align: right;
}

.monaco-market-positive {
	color: var(--ticker-positive);
}

.monaco-market-negative {
	color: var(--ticker-negative);
}

.monaco-market-sparkline {
	position: absolute;
	inset: 0.35rem 0.45rem;
	z-index: -2;
	width: calc(100% - 0.9rem);
	height: calc(100% - 0.7rem);
	overflow: visible;
	opacity: 0.38;
	transform: scaleX(1.04);
	transform-origin: center;
	pointer-events: none;
}

.monaco-intro-hero .monaco-market-ticker-shell {
	position: absolute;
	right: 1.75rem;
	bottom: 1.25rem;
	left: 1.75rem;
	z-index: 2;
	margin: 0;
	--ticker-surface: rgba(7, 13, 11, 0.58);
	--ticker-border: rgba(140, 200, 172, 0.13);
	--ticker-label-surface: rgba(244, 250, 245, 0.06);
	--ticker-text: #eef4f0;
	--ticker-muted: rgba(190, 208, 200, 0.62);
	--ticker-positive: #54e0a6;
	--ticker-negative: #ff8d80;
	border-radius: 10px;
	box-shadow: 0 18px 48px rgba(0, 0, 0, 0.22);
	backdrop-filter: blur(18px);
}

.monaco-intro-hero .monaco-market-item::after {
	background: linear-gradient(90deg, rgba(9, 13, 11, 0.68) 0%, rgba(9, 13, 11, 0.42) 48%, rgba(9, 13, 11, 0.68) 100%);
}

.monaco-intro-hero .monaco-market-item-link:hover::after {
	background:
		linear-gradient(rgba(244, 250, 245, 0.09), rgba(244, 250, 245, 0.09)),
		linear-gradient(90deg, rgba(9, 13, 11, 0.68) 0%, rgba(9, 13, 11, 0.42) 48%, rgba(9, 13, 11, 0.68) 100%);
}

:where(.dark, [data-theme='dark']) .monaco-intro-hero .monaco-market-ticker-shell {
	--ticker-surface: rgba(7, 13, 11, 0.62);
	--ticker-border: rgba(140, 200, 172, 0.15);
	--ticker-label-surface: rgba(244, 250, 245, 0.08);
	box-shadow: 0 14px 40px rgba(0, 0, 0, 0.26);
}

.monaco-intro-hero {
	--intro-hero-accent: #54e0a6;
	--intro-hero-text: #eef4f0;
	--intro-hero-muted: rgba(206, 222, 214, 0.66);
	--intro-hero-kicker: rgba(160, 210, 186, 0.62);
	--intro-hero-line: rgba(150, 220, 190, 0.052);
	--intro-hero-mark-opacity: 0.92;
	position: relative;
	isolation: isolate;
	display: flex;
	width: 100%;
	max-width: none;
	box-sizing: border-box;
	aspect-ratio: 16 / 7.35;
	min-height: 22rem;
	align-items: center;
	justify-content: flex-start;
	overflow: hidden;
	margin: 0 0 0.5rem;
	padding: 2.8rem 3rem 5.85rem;
	border: 1px solid rgba(120, 200, 170, 0.14);
	border-radius: 20px;
	background:
		radial-gradient(120% 88% at 50% 22%, rgba(40, 98, 76, 0.42), rgba(8, 16, 13, 0) 60%),
		linear-gradient(180deg, #0a1512 0%, #060c0a 100%);
	box-shadow: 0 18px 46px rgba(3, 8, 6, 0.16);
	color: var(--intro-hero-text);
	font-family: "Inter Tight", Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}

.monaco-intro-hero:not(:has(.monaco-market-ticker-shell)) {
	padding-bottom: 2.8rem;
}

:where(.dark, [data-theme='dark']) .monaco-intro-hero {
	--intro-hero-text: #f5faf6;
	--intro-hero-muted: rgba(245, 250, 246, 0.66);
	--intro-hero-line: rgba(210, 229, 215, 0.064);
	border-color: rgba(120, 200, 170, 0.16);
	background:
		radial-gradient(130% 95% at 50% 22%, rgba(40, 98, 76, 0.55), rgba(8, 16, 13, 0) 62%),
		linear-gradient(180deg, #0a1512 0%, #060c0a 100%);
	box-shadow: 0 22px 70px rgba(0, 0, 0, 0.36);
}

.monaco-intro-hero::before {
	position: absolute;
	inset: 0;
	z-index: -2;
	opacity: 0.72;
	background-image:
		linear-gradient(var(--intro-hero-line) 1px, transparent 1px),
		linear-gradient(90deg, var(--intro-hero-line) 1px, transparent 1px);
	background-size: 2.875rem 2.875rem;
	mask-image: radial-gradient(75% 70% at 50% 35%, black 40%, transparent 100%);
	content: "";
}

.monaco-intro-hero::after {
	position: absolute;
	inset: auto 10% 4.5rem 10%;
	z-index: -1;
	height: 8rem;
	border-radius: 999px;
	background:
		radial-gradient(ellipse at 50% 30%, rgba(84, 224, 166, 0.06), transparent 58%),
		radial-gradient(ellipse at 50% 80%, rgba(84, 224, 166, 0.09), transparent 66%);
	filter: blur(26px);
	content: "";
}

:where(.dark, [data-theme='dark']) .monaco-intro-hero::after {
	background:
		radial-gradient(ellipse at 50% 30%, rgba(84, 224, 166, 0.1), transparent 58%),
		radial-gradient(ellipse at 50% 80%, rgba(84, 224, 166, 0.16), transparent 66%);
}

.monaco-intro-hero-mark {
	position: absolute;
	top: 2.05rem;
	right: 2.05rem;
	z-index: 2;
	width: 2.35rem;
	height: auto;
	margin: 0;
	opacity: var(--intro-hero-mark-opacity);
	filter: drop-shadow(0 0 1.5rem rgba(84, 224, 166, 0.16));
}

:where(.dark, [data-theme='dark']) .monaco-intro-hero-mark {
	filter: drop-shadow(0 0 1.5rem rgba(84, 224, 166, 0.18));
}

.monaco-intro-hero-content {
	display: flex;
	position: relative;
	z-index: 1;
	width: 100%;
	max-width: none;
	padding-bottom: 0;
	flex-direction: column;
	align-items: flex-start;
	justify-content: center;
	gap: 0;
	text-align: left;
}

.monaco-intro-hero-kicker {
	margin-bottom: 1.85rem;
	padding-left: 0.12rem;
	color: var(--intro-hero-kicker);
	font-size: 1rem;
	font-weight: 820;
	letter-spacing: 0.42em;
	text-transform: uppercase;
}

.monaco-intro-hero-title {
	max-width: 40rem;
	margin: 0;
	color: var(--intro-hero-text);
	font-family: "Space Grotesk", Inter, ui-sans-serif, system-ui, sans-serif;
	font-size: clamp(2rem, 4.05vw, 3.05rem);
	font-weight: 760;
	letter-spacing: 0;
	line-height: 1.12;
}

img[src="/logo.png"],
img[src="/logo-white.png"],
img[src$="/logo.png"],
img[src$="/logo-white.png"] {
	max-height: 2rem;
	width: auto;
}

.monaco-intro-audience-wrap {
	position: relative;
	display: inline-block;
	vertical-align: baseline;
	line-height: inherit;
}

.monaco-intro-audience-reserve {
	display: inline-block;
	visibility: hidden;
	line-height: inherit;
	white-space: nowrap;
}

.monaco-intro-audience-word {
	position: absolute;
	top: 0;
	left: 0;
	display: block;
	color: #e9f1ec;
	line-height: inherit;
	white-space: nowrap;
}

.monaco-intro-audience-word-final {
	color: var(--intro-hero-accent);
	animation: monacoIntroGlowPulse 2.6s ease-in-out infinite;
}

.monaco-intro-audience-caret {
	display: inline-block;
	width: 0.07em;
	height: 0.98em;
	margin-left: 0.07em;
	border-radius: 2px;
	background: var(--intro-hero-accent);
	box-shadow: 0 0 10px var(--intro-hero-accent);
	vertical-align: -0.12em;
	animation: monacoIntroCaretBlink 1s steps(1, end) infinite;
}

.monaco-intro-audience-caret-done {
	visibility: hidden;
	animation: none;
}

.monaco-intro-hero-subtitle {
	max-width: 41rem;
	margin-top: 1.35rem;
	color: var(--intro-hero-muted);
	font-size: clamp(0.95rem, 1.45vw, 1.08rem);
	font-weight: 430;
	line-height: 1.55;
}

@media (max-width: 520px) {
	.monaco-intro-hero {
		border-radius: 14px;
		aspect-ratio: auto;
		min-height: 28rem;
		padding: 2rem 1.1rem 5rem;
	}

	.monaco-intro-hero:not(:has(.monaco-market-ticker-shell)) {
		padding-bottom: 2rem;
	}

	.monaco-intro-hero .monaco-market-ticker-shell {
		right: 0.75rem;
		bottom: 0.75rem;
		left: 0.75rem;
	}

	.monaco-intro-hero-content {
		justify-content: center;
	}

	.monaco-intro-hero-mark {
		top: 1.15rem;
		right: 1rem;
		width: 2.2rem;
	}

	.monaco-intro-hero-kicker {
		margin-bottom: 1.85rem;
		font-size: 0.95rem;
	}

	.monaco-intro-hero-title {
		max-width: 20rem;
		font-size: 2.3rem;
	}

	.monaco-intro-hero-subtitle {
		margin-top: 1.35rem;
		font-size: 0.98rem;
	}
}

.monaco-intro-stats {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 0.75rem;
	margin: 0 0 0.5rem;
}

.monaco-intro-stat {
	min-width: 0;
	border: 1px solid rgba(35, 51, 41, 0.12);
	border-radius: 10px;
	padding: 1rem;
	background: rgba(35, 51, 41, 0.025);
}

:where(.dark, [data-theme='dark']) .monaco-intro-stat {
	border-color: rgba(166, 190, 174, 0.16);
	background: rgba(26, 38, 32, 0.28);
}

.monaco-intro-stat-label {
	margin-bottom: 0.2rem;
	color: #526258;
	font-size: 0.75rem;
	font-weight: 800;
	letter-spacing: 0;
}

:where(.dark, [data-theme='dark']) .monaco-intro-stat-label {
	color: #b6c4ba;
}

.monaco-intro-stat-value {
	color: #142119;
	font-variant-numeric: tabular-nums;
	font-size: 1.6rem;
	font-weight: 840;
	letter-spacing: 0;
	line-height: 1.05;
}

:where(.dark, [data-theme='dark']) .monaco-intro-stat-value {
	color: #f5faf6;
}

.monaco-intro-stat-note {
	margin-top: 0.25rem;
	color: #6a766f;
	font-size: 0.76rem;
	font-weight: 650;
	line-height: 1.35;
}

:where(.dark, [data-theme='dark']) .monaco-intro-stat-note {
	color: #9eaea4;
}

@media (max-width: 640px) {
	.monaco-intro-stats {
		grid-template-columns: 1fr;
	}
}

.monaco-ai-cta {
	--ai-cta-text: #17231c;
	--ai-cta-accent: #0f9d6b;
	--ai-cta-glow: 7%;
	--ai-cta-glow-mid: 3%;
	display: flex;
	align-items: center;
	gap: 1rem;
	margin: 3.25rem 0 3.75rem;
	min-height: 7rem;
	padding: 1.9rem 1.85rem;
	border-radius: 18px;
	background: radial-gradient(
		80% 230% at 50% 50%,
		color-mix(in srgb, var(--ai-cta-accent) var(--ai-cta-glow), transparent),
		color-mix(in srgb, var(--ai-cta-accent) var(--ai-cta-glow-mid), transparent) 34%,
		transparent 68%
	);
	color: var(--ai-cta-text) !important;
	text-decoration: none !important;
	transition: background 220ms ease;
}

:where(.dark, [data-theme='dark']) .monaco-ai-cta {
	--ai-cta-text: #f4faf6;
	--ai-cta-accent: #2fe0a3;
	--ai-cta-glow: 8%;
	--ai-cta-glow-mid: 4%;
}

.monaco-ai-cta:hover {
	--ai-cta-glow: 11%;
	--ai-cta-glow-mid: 5%;
}

.monaco-ai-cta:focus-visible {
	outline: 2px solid var(--ai-cta-accent);
	outline-offset: 4px;
}

.monaco-ai-cta-icon {
	display: inline-flex;
	flex: 0 0 auto;
	align-items: center;
	justify-content: center;
	width: 2.25rem;
	height: 2.25rem;
	border-radius: 10px;
	background: color-mix(in srgb, var(--ai-cta-accent) 8%, transparent);
	color: var(--ai-cta-accent);
}

.monaco-ai-cta-text {
	flex: 1 1 auto;
	min-width: 0;
	color: var(--ai-cta-text);
	font-size: 1rem;
	font-weight: 560;
	line-height: 1.4;
}

.monaco-ai-cta-cue {
	display: inline-flex;
	flex: 0 0 auto;
	align-items: center;
	gap: 0.35rem;
	color: var(--ai-cta-accent);
	font-size: 0.92rem;
	font-weight: 720;
	white-space: nowrap;
}

.monaco-ai-cta-arrow {
	transition: transform 150ms ease;
}

.monaco-ai-cta:hover .monaco-ai-cta-arrow {
	transform: translateX(2px);
}

@media (max-width: 600px) {
	.monaco-ai-cta-cue-label {
		display: none;
	}
}

.monaco-earn-cta {
	--earn-cta-text: #17231c;
	--earn-cta-muted: #5b6a61;
	--earn-cta-accent: #0f9d6b;
	--earn-cta-border: rgba(35, 51, 41, 0.12);
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 18rem;
	margin: 3.25rem 0 3.75rem;
	padding: 4.75rem 1rem;
	border-top: 1px solid var(--earn-cta-border);
	border-bottom: 1px solid var(--earn-cta-border);
	color: var(--earn-cta-text) !important;
	text-align: center;
	text-decoration: none !important;
	transition: border-color 150ms ease;
}

:where(.dark, [data-theme='dark']) .monaco-earn-cta {
	--earn-cta-text: #f4faf6;
	--earn-cta-muted: #a7b6ad;
	--earn-cta-accent: #2fe0a3;
	--earn-cta-border: rgba(166, 190, 174, 0.16);
}

.monaco-earn-cta:hover {
	border-color: color-mix(in srgb, var(--earn-cta-accent) 38%, var(--earn-cta-border));
}

.monaco-earn-cta:focus-visible {
	outline: 2px solid var(--earn-cta-accent);
	outline-offset: 4px;
}

.monaco-earn-cta-main {
	display: grid;
	justify-items: center;
	gap: 0.9rem;
	max-width: 43rem;
	min-width: 0;
}

.monaco-earn-cta-copy {
	min-width: 0;
}

.monaco-earn-cta-title {
	color: var(--earn-cta-text);
	font-size: clamp(1.55rem, 3vw, 2.15rem);
	font-weight: 760;
	letter-spacing: 0;
	line-height: 1.12;
}

.monaco-earn-cta-cue {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.4rem;
	margin-top: 0.35rem;
	color: var(--earn-cta-accent);
	font-size: 0.9rem;
	font-weight: 760;
	white-space: nowrap;
}

.monaco-earn-cta-arrow {
	transition: transform 150ms ease;
}

.monaco-earn-cta:hover .monaco-earn-cta-arrow {
	transform: translateX(2px);
}

@media (max-width: 600px) {
	.monaco-earn-cta {
		min-height: 15rem;
		padding: 3.75rem 0.4rem;
	}
}

.monaco-market-link {
	color: inherit;
	font-size: 0.78rem;
	font-weight: 800;
	text-decoration: none;
}

.monaco-market-link:hover {
	text-decoration: underline;
}

.monaco-market-link:focus-visible {
	border-radius: 4px;
	outline: 2px solid currentColor;
	outline-offset: 3px;
}

@keyframes monacoTickerScroll {
	from {
		transform: translate3d(0, 0, 0);
	}
	to {
		transform: translate3d(-50%, 0, 0);
	}
}

@media (prefers-reduced-motion: reduce) {
	.monaco-market-ticker-track {
		animation: none;
	}
}
`;

export function formatTickerPrice(value) {
  const number = Number(value);
  if (!Number.isFinite(number)) return "n/a";
  if (number >= 1000) return `$${number.toLocaleString(undefined, {
    maximumFractionDigits: 0
  })}`;
  if (number >= 1) return `$${number.toLocaleString(undefined, {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  })}`;
  return `$${number.toLocaleString(undefined, {
    maximumSignificantDigits: 4
  })}`;
}

export function formatTickerChange(value) {
  const number = Number(value);
  if (!Number.isFinite(number)) return "0.00%";
  const sign = number > 0 ? "+" : "";
  return `${sign}${number.toFixed(2)}%`;
}

export function formatIntroStatVolume(value) {
  const number = Number(value);
  if (!Number.isFinite(number)) return "Loading";
  if (number >= 1_000_000_000) return `$${(number / 1_000_000_000).toFixed(2)}B`;
  if (number >= 1_000_000) return `$${(number / 1_000_000).toFixed(2)}M`;
  if (number >= 1_000) return `$${(number / 1_000).toFixed(1)}K`;
  return `$${number.toLocaleString(undefined, {
    maximumFractionDigits: 0
  })}`;
}

export function formatTickerSymbol(symbol) {
  return String(symbol || "").replace(new RegExp("[/-]USDC$", "i"), "");
}

export function marketTickerSymbolToSlug(symbol) {
  return String(symbol || "").trim().toLowerCase().replace(new RegExp("[^a-z0-9]+", "g"), "-").replace(new RegExp("^-+|-+$", "g"), "");
}

export function marketTickerHref(symbol) {
  return `/markets/market?symbol=${encodeURIComponent(marketTickerSymbolToSlug(symbol))}`;
}

export function tickerSparklinePoints(points) {
  const values = (points || []).map(point => Number(point?.priceChangePercent)).filter(value => Number.isFinite(value));
  const data = values.length > 1 ? values : [0, 0];
  const min = Math.min(...data);
  const max = Math.max(...data);
  const span = max - min || 1;
  return data.map((value, index) => {
    const x = data.length === 1 ? 0 : index / (data.length - 1) * 64;
    const y = 18 - (value - min) / span * 16;
    return `${x.toFixed(1)},${y.toFixed(1)}`;
  }).join(" ");
}

export const MonacoIntroAudience = () => {
  const finalIndex = MONACO_INTRO_AUDIENCES.length - 1;
  const [index, setIndex] = useState(0);
  const [text, setText] = useState("");
  const [phase, setPhase] = useState("typing");
  useEffect(() => {
    const word = MONACO_INTRO_AUDIENCES[index];
    const isFinal = index === finalIndex;
    let timer;
    if (phase === "typing") {
      if (text.length < word.length) {
        timer = window.setTimeout(() => setText(word.slice(0, text.length + 1)), MONACO_INTRO_TYPE_MS);
      } else if (isFinal) {
        setPhase("done");
      } else {
        timer = window.setTimeout(() => setPhase("deleting"), MONACO_INTRO_HOLD_MS);
      }
    } else if (phase === "deleting") {
      if (text.length > 0) {
        timer = window.setTimeout(() => setText(word.slice(0, text.length - 1)), MONACO_INTRO_DELETE_MS);
      } else {
        setIndex(current => current >= finalIndex ? finalIndex : current + 1);
        setPhase("typing");
      }
    }
    return () => {
      window.clearTimeout(timer);
    };
  }, [text, phase, index, finalIndex]);
  const isDone = phase === "done";
  const restart = () => {
    if (isDone) {
      setIndex(0);
      setText("");
      setPhase("typing");
    }
  };
  return <span className="monaco-intro-audience-wrap" onClick={restart} onMouseEnter={restart}>
			<span className="monaco-intro-audience-reserve">market makers</span>
			<span className={`monaco-intro-audience-word${isDone ? " monaco-intro-audience-word-final" : ""}`}>
				{text}
				<span className={`monaco-intro-audience-caret${isDone ? " monaco-intro-audience-caret-done" : ""}`} aria-hidden="true" />
			</span>
		</span>;
};

export const MonacoMarketTicker = () => {
  const [markets, setMarkets] = useState([]);
  useEffect(() => {
    let active = true;
    const applyMarkets = items => {
      const seen = new Set();
      const uniqueItems = (items || []).filter(item => {
        if (!item?.symbol || seen.has(item.symbol)) return false;
        seen.add(item.symbol);
        return true;
      });
      if (active) {
        setMarkets(uniqueItems.slice(0, 10));
      }
    };
    const loadMarkets = async () => {
      let renderedCache = false;
      const cachedScreener = readMonacoMarketCache(MONACO_TICKER_SCREENER_CACHE_KEY);
      if (cachedScreener) {
        applyMarkets(cachedScreener.data.items || []);
        renderedCache = true;
        if (cachedScreener.isFresh) return;
      }
      try {
        const screenerEntry = await fetchMonacoMarketData(MONACO_TICKER_SCREENER_CACHE_KEY, MONACO_TICKER_SCREENER_URL);
        applyMarkets(screenerEntry.data.items || []);
      } catch (error) {
        if (active && !renderedCache) setMarkets([]);
      }
    };
    loadMarkets();
    const timer = window.setInterval(loadMarkets, 60000);
    return () => {
      active = false;
      window.clearInterval(timer);
    };
  }, []);
  const marketItems = markets.map(market => ({
    type: "market",
    key: market.tradingPairId || market.symbol,
    symbol: market.symbol,
    displaySymbol: formatTickerSymbol(market.symbol),
    iconUrl: market.baseIconUrl || "",
    price: formatTickerPrice(market.lastPrice),
    change: formatTickerChange(market.priceChangePercent24h),
    changeValue: Number(market.priceChangePercent24h || 0),
    points: tickerSparklinePoints(market.snapshot7d)
  }));
  if (!marketItems.length) {
    return <style>{monacoMarketTickerStyles}</style>;
  }
  const renderItems = [...marketItems, ...marketItems];
  return <>
			<style>{monacoMarketTickerStyles}</style>
			<div className="not-prose monaco-market-ticker-shell" aria-label="Live Monaco market ticker">
				<div className="monaco-market-ticker">
					<div className="monaco-market-ticker-track">
						{renderItems.map((item, index) => {
    const directionClass = item.changeValue >= 0 ? "monaco-market-positive" : "monaco-market-negative";
    return <a className="monaco-market-item monaco-market-item-link" href={marketTickerHref(item.symbol)} key={`${item.key}-${index}`}>
									<span className="monaco-market-main">
										{item.iconUrl ? <img alt="" className="monaco-market-icon" src={item.iconUrl} /> : <span className="monaco-market-icon monaco-market-icon-fallback">{String(item.displaySymbol || item.symbol).slice(0, 2)}</span>}
										<span className="monaco-market-symbol">{item.displaySymbol || item.symbol}</span>
										<span className="monaco-market-price">{item.price}</span>
									</span>
									<span className={`monaco-market-change ${directionClass}`}>{item.change}</span>
									<svg className="monaco-market-sparkline" viewBox="0 0 64 20" aria-hidden="true">
										<polyline points={item.points} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={directionClass} />
									</svg>
								</a>;
  })}
					</div>
				</div>
			</div>
		</>;
};

export const MonacoIntroStats = () => {
  const [stats, setStats] = useState({
    markets: null,
    volume24h: null
  });
  useEffect(() => {
    let active = true;
    const applyStats = items => {
      const seen = new Set();
      let volume24h = 0;
      (items || []).forEach(item => {
        if (item?.symbol) seen.add(item.symbol);
        const volume = Number(item?.quoteVolume24h);
        if (Number.isFinite(volume)) volume24h += volume;
      });
      if (active) {
        setStats({
          markets: seen.size || null,
          volume24h
        });
      }
    };
    const loadStats = async () => {
      const cachedScreener = readMonacoMarketCache(MONACO_TICKER_SCREENER_CACHE_KEY);
      if (cachedScreener) {
        applyStats(cachedScreener.data.items || []);
        if (cachedScreener.isFresh) return;
      }
      try {
        const screenerEntry = await fetchMonacoMarketData(MONACO_TICKER_SCREENER_CACHE_KEY, MONACO_TICKER_SCREENER_URL);
        applyStats(screenerEntry.data.items || []);
      } catch (error) {}
    };
    loadStats();
    const timer = window.setInterval(loadStats, 60000);
    return () => {
      active = false;
      window.clearInterval(timer);
    };
  }, []);
  return <div className="not-prose monaco-intro-stats" aria-label="Monaco market stats">
			<div className="monaco-intro-stat">
				<div className="monaco-intro-stat-label">Markets</div>
				<div className="monaco-intro-stat-value">{stats.markets || "Loading"}</div>
				<div className="monaco-intro-stat-note">Supported testnet markets</div>
			</div>
			<div className="monaco-intro-stat">
				<div className="monaco-intro-stat-label">24h volume</div>
				<div className="monaco-intro-stat-value">{formatIntroStatVolume(stats.volume24h)}</div>
				<div className="monaco-intro-stat-note">Across active market rows</div>
			</div>
			<div className="monaco-intro-stat">
				<div className="monaco-intro-stat-label">Order latency</div>
				<div className="monaco-intro-stat-value">&lt;1ms</div>
				<div className="monaco-intro-stat-note">Matching-engine target</div>
			</div>
		</div>;
};

<div className="not-prose monaco-intro-hero" aria-label="The world's trading floor">
  <img className="monaco-intro-hero-mark" src="https://mintcdn.com/monaco/Puhxf4Whf6wQMalZ/logoMark.png?fit=max&auto=format&n=Puhxf4Whf6wQMalZ&q=85&s=7cfd00a92f26b8cb3855b908c31629b8" alt="" width="38" height="26" data-path="logoMark.png" />

  <div className="monaco-intro-hero-content">
    <div className="monaco-intro-hero-kicker">Monaco</div>

    <div className="monaco-intro-hero-title">
      <span>Spot and perps markets for <MonacoIntroAudience /></span>
    </div>

    <div className="monaco-intro-hero-subtitle">APIs and SDKs for high-performance access to financial markets.</div>
  </div>

  <MonacoMarketTicker />
</div>

## What is Monaco?

Monaco is a high-performance trading platform for [spot](/trading-mechanics/spot) and [perpetual](/trading-mechanics/perps) markets, with prediction markets incoming, built using a simple and robust API stack. Trading is powered by Monaco's low-latency institutional-grade order book, where SDKs and APIs provide everything needed for anyone to access trading infrastructure: builders, traders, and agents.

<a className="not-prose monaco-ai-cta" href="/build-with-ai">
  <span className="monaco-ai-cta-icon" aria-hidden="true">
    <svg width="19" height="19" viewBox="0 0 24 24" fill="none">
      <path d="M21 11.5a8.38 8.38 0 0 1-8.5 8.5 8.5 8.5 0 0 1-3.9-.9L3 21l1.9-5.6A8.5 8.5 0 0 1 12.5 3 8.38 8.38 0 0 1 21 11.5Z" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  </span>

  <span className="monaco-ai-cta-text">Prefer to chat with an agent instead of searching the docs?</span>

  <span className="monaco-ai-cta-cue">
    <span className="monaco-ai-cta-cue-label">AI & Agents</span>
    <span className="monaco-ai-cta-arrow" aria-hidden="true">→</span>
  </span>
</a>

## Why Monaco?

For builders looking to bootstrap liquidity without the overhead of designing, maintaining, and improving a sophisticated risk and matching engine, Monaco is a full-stack solution. For traders looking to access global markets with highly competitive fees, rebates, and capital efficiency, Monaco offers a sophisticated trading experience.

* **Real Revenue to Users:** maker rebates for both retail and institutional participants at all volume levels, with BuilderCodes for any integrated frontend, and TraderCodes for multi-layer referrals.
* **Mature Market Design:** price-time priority alongside prioritized cancels, low-latency matching, and simplified funding rates in a shared liquidity layer.
* **Robust Risk Management:** margin accounts can start with cross-margin, but will support correlation and scenario-based portfolio margin to allow netting benefits for offsetting correlated positions.
* **Open Integration:** REST, WebSocket, gRPC, TypeScript, React, Rust, generated clients, and MCP tooling allow traders, application builders, market makers, and AI agents to use unified market infrastructure.

<a className="not-prose monaco-earn-cta" href="/earn">
  <span className="monaco-earn-cta-main">
    <span className="monaco-earn-cta-copy">
      <span className="monaco-earn-cta-title">Revenue-sharing for maker liquidity, building, and referrals</span>
    </span>

    <span className="monaco-earn-cta-cue">
      <span>Learn how to earn with Monaco</span>
      <span className="monaco-earn-cta-arrow" aria-hidden="true">→</span>
    </span>
  </span>
</a>

## Trade on Monaco

For traders who prefer a terminal, you can access Monaco through your preferred platform, or access it programmatically using the existing SDKs and API stack.

* [**Mach 1**](https://app.m1.markets/en)
* [**Monte Carlo**](https://www.montecarlo.trade/)

Want to build a Monaco-powered app and have it listed here? Reach out to [team@0xmonaco.com](mailto:team@0xmonaco.com) for an introduction.

## Building on Monaco

Anyone can build tailored trading experiences, analytics dashboards, market-maker systems, internal tooling, or AI agent workflows leveraging Monaco's unified order book. Monaco provides the core infrastructure, so builders can focus on the product experience.

BuilderCodes allow applications to earn protocol revenue on the volume they route directly to the order book. Visit the [builder quickstart](/quickstart) to get started.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.