> For the complete documentation index, see [llms.txt](https://bubblegum-reality.gitbook.io/bubblegum-reality-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bubblegum-reality.gitbook.io/bubblegum-reality-docs/reference/server-functions.md).

# Server Functions

All server logic is typed RPC via `createServerFn` from `@tanstack/react-start`. Same-origin, so there is no CORS surface. Five modules expose them: market, swap, portfolio, AI, and account.

Every function returns either a value or a discriminated result:

```ts
type Result<T> =
  | { ok: true;  data: T }
  | { ok: false; error: { code: string; message: string } };
```

Errors are sanitized by `sanitizeError()` before they leave the server. Upstream bodies, URLs, and API keys are never relayed.

## `src/lib/market.functions.ts`

### `getChainStatus()`

`GET` · no input · returns [`ChainStatus`](/bubblegum-reality-docs/reference/data-types.md#chainstatus).

Block height, RPC latency, and which RPC source answered (`configured` | `public`). Powers the landing status strip.

### `getAssets()`

`GET` · no input · returns `Result<AssetsPayload>`.

The canonical registry, filtered to chain `4663`. See [Asset Discovery](/bubblegum-reality-docs/architecture/asset-discovery.md).

### `getPrice({ symbol, multiplier })`

`GET` · returns `Result<ReferencePrice>`.

| Input        | Validation                                                |
| ------------ | --------------------------------------------------------- |
| `symbol`     | 1–12 chars, `/^[A-Za-z0-9.-]+$/`, upper-cased server-side |
| `multiplier` | `/^\d+(\.\d+)?$/`, defaults to `"1"`                      |

Returns raw underlying bid/ask **and** multiplier-adjusted bid/ask, plus halt state, volume, `generatedAt`, and `fetchedAt`. Cached 15s.

```ts
import { getPrice } from "@/lib/market.functions";

const res = await getPrice({ data: { symbol: "AAPL", multiplier: "10" } });
if (res.ok) console.log(res.data.adjustedAsk);
```

### `getPrices({ symbols })`

`POST` · returns reference prices for many symbols in one round trip. Powers the `/markets` table, which refreshes every 20s instead of firing one request per row.

### `getCorporateActions()`

`GET` · no input · returns `Result<CorporateAction[]>` — pending multiplier changes and effective times.

### `checkEligibility(claim)`

`POST` · returns `{ eligible: boolean; reason: string | null }`.

Server-side evaluation of the [eligibility gate](/bubblegum-reality-docs/compliance/eligibility.md). Fails closed. **No eligibility detail is logged.**

## `src/lib/swap.functions.ts`

### `routingConfigured()`

`GET` · returns `{ configured: boolean }` — whether `ZEROX_API_KEY` is present. Only the boolean crosses the boundary.

### `fetchIndicativePrice(request)`

`POST` · `Result<ZeroExPriceResult>` · rate limit **30 / 60s per IP**.

Debounced indicative pricing for the terminal. No eligibility required — this is a read.

### `fetchFirmQuote({ ...request, eligibility })`

`POST` · `Result<ZeroExQuoteResult>` · rate limit **12 / 60s per IP**.

Requires a full eligibility claim. If ineligible, returns `{ ok: false, error: { code: "NOT_ELIGIBLE", message } }` and never calls 0x. On success, includes the `transaction` object (`to`, `data`, `value`, `gas`, `gasPrice`).

## `src/lib/portfolio.functions.ts`

### `getPortfolio({ address })`

`GET` · `Result<PortfolioSummary>`. Validates a `0x`-prefixed 40-hex address, then batches `balanceOf` across the registry via Multicall3 and values it against multiplier-adjusted references. See [Portfolio & Concentration](/bubblegum-reality-docs/architecture/portfolio.md).

## `src/lib/ai.functions.ts`

### `getRealityCheck(snapshot)`

`POST` · `AiResult<RealityCheckPayload>`. Zod-validates an identity-free execution snapshot, looks up a SHA-256 digest of it in `ai_insights` (10-minute TTL), and otherwise calls the AI gateway. Returns `verdict`, `headline`, `summary`, `factors`, `cautions`, `model`, `cached`, `generatedAt`, and the disclaimer. See [Reality Check (AI)](/bubblegum-reality-docs/architecture/reality-check-ai.md).

## `src/lib/account.functions.ts`

Every function here uses `requireSupabaseAuth`, so RLS applies as the signed-in user and the client bearer token is attached by the middleware in `src/start.ts`.

| Group      | Functions                                                                                                                |
| ---------- | ------------------------------------------------------------------------------------------------------------------------ |
| Profile    | `getMyProfile`, `updateMyProfile`, `recordEligibilityAcknowledgement`                                                    |
| Wallets    | `listLinkedWallets`, `linkWallet`, `unlinkWallet`                                                                        |
| Watchlists | `listWatchlists`, `createWatchlist`, `deleteWatchlist`, `addWatchlistItem`, `removeWatchlistItem`                        |
| Alerts     | `listAlertRules`, `createAlertRule`, `setAlertRuleActive`, `deleteAlertRule`, `listAlertEvents`, `acknowledgeAlertEvent` |
| History    | `listTransactions`, `recordTransaction`                                                                                  |

None of these may be called from a public route loader — SSR and prerender have no session.

## Swap request validation

`swapRequestSchema` in `zerox.server.ts` enforces:

| Rule                                      | Rejects                    |
| ----------------------------------------- | -------------------------- |
| `chainId` is exactly `4663`               | Cross-chain quote requests |
| Token addresses are canonical/allowlisted | Arbitrary address proxying |
| `taker` is a valid address                | Malformed takers           |
| Amount is a positive base-unit integer    | Floats, zero, negatives    |
| Slippage within a safe bounded range      | Sandwich-friendly slippage |

The allowlist is the point: without it, the endpoint is an open, key-funded proxy to any token pair on the chain.

## Authoring rules

* Read `process.env` **inside** `.handler()`, never at module scope.
* `*.functions.ts` files stay thin — imports, erased types, and exported declarations only.
* Never call an auth-protected function from a public route loader; SSR and prerender have no session.
* Import `createServerFn` from `@tanstack/react-start`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://bubblegum-reality.gitbook.io/bubblegum-reality-docs/reference/server-functions.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
