### Hono App Setup with GET Endpoint Source: https://ponder.sh/docs/api-reference/ponder/api-endpoints Basic setup for a Hono application, exporting a default Hono app instance. This example registers a simple GET endpoint '/hello' that returns 'Hello, world!'. ```typescript import { Hono } from "hono"; const app = new Hono(); app.get("/hello", (c) => { return c.text("Hello, world!"); }); export default app; ``` -------------------------------- ### Start Ponder Development Server with pnpm Source: https://ponder.sh/docs/get-started Starts the Ponder local development server using the `pnpm dev` command. This action connects to the database, launches the HTTP server, and begins the data indexing process. ```bash pnpm dev ``` -------------------------------- ### Create Ponder Project using 'feature-factory' Example Source: https://ponder.sh/docs/api-reference/create-ponder Initializes a Ponder project specifically using the 'feature-factory' example template. This template is designed for projects involving factory contracts and provides a starting point for developing applications that interact with them. ```bash pnpm create ponder --template feature-factory ``` ```bash yarn create ponder --template feature-factory ``` ```bash npm create ponder --template feature-factory ``` -------------------------------- ### Create Ponder Project with pnpm Source: https://ponder.sh/docs/get-started Initiates a new Ponder project using the `create-ponder` command with the pnpm package manager. This command prompts the user for project name and template selection, then sets up the project structure and initializes a Git repository. ```bash pnpm create ponder ``` -------------------------------- ### GET /hello Source: https://ponder.sh/docs/api-reference/ponder/api-endpoints A basic example of registering a handler for GET requests to the '/hello' endpoint, returning a simple text response. ```APIDOC ## GET /hello ### Description Registers a handler for GET requests to the '/hello' endpoint. ### Method GET ### Endpoint /hello ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **text** (string) - "Hello, world!" #### Response Example ``` Hello, world! ``` ``` -------------------------------- ### Create Ponder CLI Source: https://ponder.sh/docs/api-reference/create-ponder The `create-ponder` CLI tool is the easiest way to get started with Ponder. It asks a few questions, then creates a new Ponder project in the specified directory including all required files (`package.json`, `ponder.config.ts`, ABIs, etc). ```APIDOC ## POST /create-ponder ### Description Initializes a new Ponder project in the specified directory with essential configuration files. ### Method POST ### Endpoint `/create-ponder ` ### Parameters #### Path Parameters - **directory** (string) - Required - The directory where the new Ponder project will be created. #### Query Parameters - **-t, --template [id]** (string) - Optional - Use a template to bootstrap the project. Available templates include 'feature-factory', 'feature-filter', 'feature-multichain', 'feature-proxy', 'feature-read-contract', 'project-friendtech', 'project-uniswap-v3-flash', 'reference-erc20', 'reference-erc721'. - **--etherscan [url]** (string) - Optional - Use the Etherscan template with the specified contract URL to fetch contract details. - **--etherscan-api-key [key]** (string) - Optional - Etherscan API key required for the Etherscan template. - **--subgraph [id]** (string) - Optional - Use the subgraph template with the specified subgraph ID to fetch event source details. - **--subgraph-provider [provider]** (string) - Optional - Specify the subgraph provider for the subgraph template. - **--npm** (boolean) - Optional - Use npm as the package manager. - **--pnpm** (boolean) - Optional - Use pnpm as the package manager. - **--yarn** (boolean) - Optional - Use yarn as the package manager. - **--skip-git** (boolean) - Optional - Skip initializing a git repository. - **--skip-install** (boolean) - Optional - Skip installing project dependencies. - **-h, --help** (boolean) - Optional - Display the help message. - **-v, --version** (boolean) - Optional - Display the version number. ### Request Body This endpoint does not require a request body. ### Response #### Success Response (200) - **message** (string) - Confirmation message indicating the project was created successfully. #### Response Example ```json { "message": "Ponder project created successfully in ''" } ``` ``` -------------------------------- ### Migrate Account Creation: ORM to Query Builder (TypeScript) Source: https://ponder.sh/docs/migration-guide This example demonstrates the migration of creating an account record from the older ORM pattern (`context.db.Account.create`) to the new query builder pattern (`context.db.insert`). It highlights the change in syntax for inserting data into the database. ```typescript // create -> insert await context.db.Account.create({ id: event.args.from, data: { balance: 0n }, }); await context.db.insert(account).values({ id: event.args.from, balance: 0n }); ``` -------------------------------- ### Starting Ponder with Explicit Database Schema (Shell) Source: https://ponder.sh/docs/migration-guide This command shows how to start a Ponder application with an explicitly defined database schema using the `--schema` flag, a change introduced in Ponder version 0.8. ```shell ponder start --schema my_schema ``` -------------------------------- ### Install Ponder Core v0.7 with pnpm Source: https://ponder.sh/docs/migration-guide Provides the command to install the specified version of the Ponder core library using the pnpm package manager. This is a prerequisite for using the new features and schema migration. ```shell pnpm add @ponder/core@0.7 ``` -------------------------------- ### Start Ponder with Automated View Creation Source: https://ponder.sh/docs/production/self-hosting This command shows how to start a Ponder deployment while automatically creating database views for the latest data. The `ponder start` command, when used with the `--views-schema` flag, will execute the `ponder db create-views` command once the deployment is ready and the backfill is complete. This ensures that views are consistently updated. ```bash pnpm start --schema=deployment-123 --views-schema=project-name ``` -------------------------------- ### Create Ponder Project from Example Template Source: https://ponder.sh/docs/api-reference/create-ponder Initializes a Ponder project using one of the pre-defined example templates. This is useful for quickly setting up projects with specific functionalities, such as factory contracts, proxy contracts, or integrations with protocols like Uniswap V3. ```bash pnpm create ponder --template ``` ```bash yarn create ponder --template ``` ```bash npm create ponder --template ``` -------------------------------- ### Install Hono Dependency Source: https://ponder.sh/docs/migration-guide This command installs the latest version of Hono, which is now a peer dependency for the project. Ensure you have pnpm, yarn, or npm installed. ```bash pnpm add hono@latest ``` -------------------------------- ### ponder start Source: https://ponder.sh/docs/api-reference/ponder/cli Starts the Ponder application in production mode. Project files are built once on startup, and file changes are ignored. The terminal UI is disabled. ```APIDOC ## ponder start ### Description Starts the application in production mode. Project files are built once on startup, and file changes are ignored. The terminal UI is disabled. ### Method N/A (CLI Command) ### Endpoint N/A (CLI Command) ### Parameters #### Path Parameters None #### Query Parameters None #### Command Options - **--schema** (SCHEMA) - Optional - Database schema - **-p, --port** (PORT) - Optional - Port for the web server (default: 42069) - **-H, --hostname** (HOSTNAME) - Optional - Hostname for the web server (default: "0.0.0.0" or "::") - **-h, --help** - Optional - Display help for this command ``` -------------------------------- ### Migrate FindMany to Raw SQL Select (TypeScript) Source: https://ponder.sh/docs/migration-guide This example demonstrates the migration of fetching multiple records using `findMany` to using raw SQL `select` queries. It shows how to construct a select statement using `context.db.sql.select()` and apply filtering with `where` and conditions like `eq`. ```typescript // findMany -> raw SQL select, see below await context.db.Account.findMany({ where: { balance: { gt: 100n } } }); await context.db.sql.select().from(account).where(eq(account.balance, 100n)); ``` -------------------------------- ### Define Setup Function for Contract Indexing Source: https://ponder.sh/docs/api-reference/ponder/indexing-functions This snippet demonstrates how to define a 'setup' function that runs once before indexing begins. It ensures singleton records are created efficiently, avoiding repetitive upserts in other indexing functions. This approach improves performance and simplifies code. ```typescript import { ponder } from "ponder:registry"; import { world } from "ponder:schema"; ponder.on("FunGame:setup", async ({ context }) => { await context.db.insert(world).values({ id: 1, playerCount: 0, }); }); ponder.on("FunGame:NewPlayer", async ({ context }) => { await context.db .update(world, { id: 1 }) .set((row) => ({ playerCount: row.playerCount + 1, })); }); ``` -------------------------------- ### Querying Balances and Account Data with publicClients and db (TypeScript) Source: https://ponder.sh/docs/migration-guide This example shows how to use the new `publicClients` and `db` objects from the `ponder:api` virtual module within a Hono application. It retrieves an account's balance using a Viem Public Client and fetches account data from the database. ```typescript import { publicClients, db } from "ponder:api"; import schema from "ponder:schema"; import { Hono } from "hono"; const app = new Hono(); app.get("/account/:chainId/:address", async (c) => { const chainId = c.req.param("chainId"); const address = c.req.param("address"); const balance = await publicClients[chainId].getBalance({ address }); const account = await db.query.accounts.findFirst({ where: eq(schema.accounts.address, address), }); return c.json({ balance, account }); }); export default app; ``` -------------------------------- ### Account Configuration Example Source: https://ponder.sh/docs/config/accounts Example configuration in `ponder.config.ts` to fetch transactions or native transfers from a specific account. ```APIDOC ## POST /config/accounts ### Description Configure Ponder to index transactions or native transfers sent to or from a specified account. ### Method POST ### Endpoint /config/accounts ### Parameters #### Request Body - **chain** (string) - Required - The chain to index from (e.g., "mainnet"). - **address** (string) - Required - The account address to monitor. - **startBlock** (number) - Optional - The block number to start indexing from. ### Request Example ```json { "chain": "mainnet", "address": "0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5", "startBlock": 20000000 } ``` ### Response #### Success Response (200) - **status** (string) - "success" - Indicates the configuration was processed. #### Response Example ```json { "status": "success" } ``` ``` -------------------------------- ### Update Start Command for Database Views Pattern Source: https://ponder.sh/docs/migration-guide This command enables the database views pattern, allowing platforms like Railway to create views pointing to the latest deployment's tables. The `--views-schema` flag specifies the schema name for these views. ```shell pnpm start --schema $RAILWAY_DEPLOYMENT_ID pnpm start --schema $RAILWAY_DEPLOYMENT_ID --views-schema my_project ``` -------------------------------- ### GraphQL API Setup Source: https://ponder.sh/docs/query/graphql How to enable and configure the GraphQL API using Hono middleware. ```APIDOC ## POST /graphql ### Description Registers the `graphql` Hono middleware to enable the GraphQL API. This middleware also provides a GraphiQL interface for schema exploration and query testing. ### Method POST ### Endpoint /graphql ### Parameters #### Request Body - **db** (object) - Required - The Ponder database instance. - **schema** (object) - Required - The Ponder schema definition. ### Request Example ```typescript import { db } from "ponder:api"; import schema from "ponder:schema"; import { Hono } from "hono"; import { graphql } from "ponder"; const app = new Hono(); app.use("/graphql", graphql({ db, schema })); export default app; ``` ### Response #### Success Response (200) A GraphiQL interface is provided for GET requests, allowing interactive schema exploration and query execution. ``` -------------------------------- ### ponder db list Source: https://ponder.sh/docs/api-reference/ponder/cli Lists all Ponder instances that have been started using `ponder start` in the connected database, showing schema, active status, and table count. ```APIDOC ## ponder db list ### Description Lists all `ponder start` instances that have ever ran in the connected database. Displays schema, active status, last active time, and table count for each deployment. ### Method N/A (CLI Command) ### Endpoint N/A (CLI Command) ### Parameters #### Path Parameters None #### Query Parameters None #### Command Options - **-h, --help** - Optional - Display help for this command ### Response #### Success Response (Table Output) - **Schema** (string) - The name of the database schema. - **Active** (boolean) - Indicates if the deployment is currently active. - **Last active** (string) - The timestamp of the last activity for the deployment. - **Table count** (integer) - The number of tables managed by the deployment. #### Example Output ``` │ Schema │ Active │ Last active │ Table count │ ├───────────────┼──────────┼────────────────┼─────────────┤ │ indexer_prod │ yes │ --- │ 10 │ │ test │ no │ 26m 58s ago │ 10 │ │ demo │ no │ 1 day ago │ 5 │ ``` ``` -------------------------------- ### Arbitrary SQL Select Query in Indexing Function (TypeScript) Source: https://ponder.sh/docs/migration-guide This example demonstrates how to execute arbitrary SQL select queries directly within Ponder indexing functions using the `context.db.sql` interface. It shows how to select data from the 'account' table, order it by balance in descending order, and limit the results. ```typescript import { desc } from "@ponder/core"; import { account } from "../ponder.schema"; ponder.on("", ({ event, context }) => { const result = await context.db.sql .select() .from(account) .orderBy(desc(account.balance)) .limit(1); }); ``` -------------------------------- ### Implement Custom API Endpoints with Hono in TypeScript Source: https://ponder.sh/docs/migration-guide This TypeScript example shows how to implement custom API endpoints using Hono's routing system. It replaces the older `ponder.get()`, `post()`, and `use()` methods with Hono's built-in routing capabilities. ```typescript import { ponder } from "ponder:registry"; ponder.get("/hello", (c) => { return c.text("Hello, world!"); }); ``` -------------------------------- ### Define an onchainTable with Primary Key Source: https://ponder.sh/docs/migration-guide Demonstrates the new schema definition API using `onchainTable` from `@ponder/core`. This example shows how to define a table named 'account' with a 'hex' primary key and other columns like 'daiBalance', 'isAdmin', and 'graffiti'. It highlights the use of `.primaryKey()`, `.notNull()`, and different column types. ```typescript import { onchainTable } from "@ponder/core"; export const accounts = onchainTable("account", (t) => ({ address: t.hex().primaryKey(), daiBalance: t.bigint().notNull(), isAdmin: t.boolean().notNull(), graffiti: t.text(), })); ``` -------------------------------- ### Install @ponder/client Source: https://ponder.sh/docs/api-reference/ponder-client Install the @ponder/client package using pnpm. This package provides a typed SQL over HTTP client for querying your Ponder database. ```bash pnpm add @ponder/client ``` -------------------------------- ### Cursor Pagination Example Source: https://ponder.sh/docs/query/graphql Demonstrates how to implement cursor-based pagination by using `startCursor` and `endCursor` from the `PageInfo` object in subsequent requests. ```APIDOC ## Cursor Pagination Cursor pagination involves passing the `startCursor` or `endCursor` from a previous `PageInfo` object as the `before` or `after` argument, respectively, in subsequent queries. **Cursor Values**: Cursor values are opaque strings that should only be used as arguments. Do not decode or manipulate them. Ensure filter and sort criteria remain consistent across paginated requests to avoid errors. ### Example: Initial Query This query fetches the first two persons ordered by age, without specifying pagination arguments. ```graphql query { persons(orderBy: "age", orderDirection: "asc", limit: 2) { items { name age } pageInfo { startCursor endCursor hasPreviousPage hasNextPage } totalCount } } ``` ### Example: Paginate Forward To get the next set of results, use the `endCursor` from the previous `pageInfo` as the `after` argument. ```graphql query { persons( orderBy: "age", orderDirection: "asc", limit: 2, after: "Mxhc3NDb3JlLTA=" ) { items { name age } pageInfo { startCursor endCursor hasPreviousPage hasNextPage } totalCount } } ``` ### Example: Paginate Backward To get the previous set of results, use the `startCursor` from the previous `pageInfo` as the `before` argument. ```graphql query { persons( orderBy: "age", orderDirection: "asc", limit: 2, before: "MxhcdoP9CVBhY" ) { items { name age } pageInfo { startCursor endCursor hasPreviousPage hasNextPage } totalCount } } ``` ``` -------------------------------- ### Migrate Unique Account Find: ORM to Query Builder (TypeScript) Source: https://ponder.sh/docs/migration-guide This example shows how to migrate finding a single account record. The older `findUnique` ORM method is replaced by the more general `find` method in the query builder pattern, specifying the table and query conditions. ```typescript // findUnique -> find await context.db.Account.findUnique({ id: event.args.from }); await context.db.find(account, { address: event.args.from }); ``` -------------------------------- ### Migrate Account Upsert: ORM to Query Builder (TypeScript) Source: https://ponder.sh/docs/migration-guide This example shows the migration of the 'upsert' operation for account records. The older ORM syntax is replaced by the query builder's `insert` method combined with `onConflictDoUpdate`, providing a similar functionality for creating or updating records based on a conflict. ```typescript // upsert await context.db.Account.upsert({ id: event.args.from, create: { balance: 0n }, update: ({ current }) => ({ balance: current.balance + 100n }), }); await context.db .insert(account) .values({ address: event.args.from, balance: 0n }) .onConflictDoUpdate((row) => ({ balance: row.balance + 100n })); ``` -------------------------------- ### Install @ponder/react Source: https://ponder.sh/docs/api-reference/ponder-react Installs the @ponder/react package along with its peer dependencies, @ponder/client and @tanstack/react-query. These are necessary for Ponder's React hooks to function correctly. ```bash pnpm add @ponder/react @ponder/client @tanstack/react-query ``` -------------------------------- ### Read Contract Data - Basic Example Source: https://ponder.sh/docs/indexing/read-contracts Demonstrates how to read data from a contract using `context.client.readContract()`, specifying the contract address and ABI. ```APIDOC ## POST /readContract ### Description Reads data from a contract by calling a read-only function. ### Method POST ### Endpoint `/readContract` ### Parameters #### Request Body - **abi** (object[]) - Required - The contract's ABI. - **address** (string) - Required - The contract's address. - **method** (string) - Required - The name of the read-only function to call. - **args** (any[]) - Optional - The arguments to pass to the function. ### Request Example ```json { "abi": [ { "inputs": [ { "internalType": "uint256", "name": "tokenId", "type": "uint256" } ], "name": "tokenUri", "outputs": [ { "internalType": "string", "name": "", "type": "string" } ], "stateMutability": "view", "type": "function" } ], "address": "0x8d04...D3Ff63", "method": "tokenUri", "args": [1] } ``` ### Response #### Success Response (200) - **result** (any) - The result of the read-only function call. #### Response Example ```json { "result": "ipfs://example.token-uri" } ``` ``` -------------------------------- ### ponder dev Source: https://ponder.sh/docs/api-reference/ponder/cli Starts the Ponder development server with hot-reloading and a terminal UI. Automatically restarts when project files change. ```APIDOC ## ponder dev ### Description Starts the development server with hot-reloading. The app automatically restarts when changes are detected in any project file, and an auto-updating terminal UI displays useful information. ### Method N/A (CLI Command) ### Endpoint N/A (CLI Command) ### Parameters #### Path Parameters None #### Query Parameters None #### Command Options - **--schema** (SCHEMA) - Optional - Database schema - **-p, --port** (PORT) - Optional - Port for the web server (default: 42069) - **-H, --hostname** (HOSTNAME) - Optional - Hostname for the web server (default: "0.0.0.0" or "::") - **--disable-ui** - Optional - Disable the terminal UI - **-h, --help** - Optional - Display help for this command ``` -------------------------------- ### Example: Fetching Persons by Age Source: https://ponder.sh/docs/query/sql-over-http Demonstrates fetching `person` records older than 32 using `useInfiniteQuery` from `@tanstack/react-query` and `@ponder/client`. ```APIDOC ## useInfiniteQuery for Persons ### Description Fetches `person` records where the age is greater than 32, implementing infinite scrolling with `useInfiniteQuery`. This example uses `@ponder/client` and `@ponder/react`. ### Method POST (via `@ponder/client`) ### Endpoint `/sql` (internal) ### Parameters #### Query Parameters (used by `useInfiniteQuery`) - **pageParam** (number) - The offset for the current page of results. #### Request Body (generated by `useInfiniteQuery`) - **query** (string) - SQL query with `WHERE`, `ORDER BY`, `LIMIT`, and `OFFSET` clauses. ### Request Example (Hook Setup) ```jsx import { asc, gt } from "@ponder/client"; import { usePonderClient } from "@ponder/react"; import { useInfiniteQuery } from "@tanstack/react-query"; import * as schema from "./path/to/your/schema"; // Assuming schema is imported // Ensure schema is globally registered for usePonderQuery if used directly // declare module "@ponder/react" { // interface Register { // schema: typeof schema; // } // } function PersonList() { const client = usePonderClient(); const personQuery = useInfiniteQuery({ queryKey: ["persons"], queryFn: ({ pageParam }) => client.db .select() .from(schema.person) .where(gt(schema.person.age, 32)) .orderBy(asc(schema.person.id)) .limit(100) .offset(pageParam), initialPageParam: 0, getNextPageParam: (lastPage, pages) => lastPage.length === 100 ? undefined : pages.length * 100, }); // ... component logic to render personQuery.data ... } ``` ### Response - **data** (object) - Contains `pages` array, where each page is a result set from the query. - **isLoading** (boolean) - **error** (object) - **fetchNextPage** (function) - **hasNextPage** (boolean) ``` -------------------------------- ### Example: Fetching Pool Data with Relations Source: https://ponder.sh/docs/query/sql-over-http Demonstrates fetching `pool` records with related `token0` and `token1` data using `usePonderQuery` and the Drizzle query builder. ```APIDOC ## usePonderQuery for Pools with Relations ### Description Fetches `pool` records filtering by `chainId` and `fee`, and includes the related `token0` and `token1` data. This example utilizes `usePonderQuery` and the Drizzle query builder. ### Method POST (via `@ponder/client`) ### Endpoint `/sql` (internal) ### Parameters None directly exposed, query is defined within `queryFn`. ### Request Example (Hook Setup) ```jsx import { usePonderQuery } from "@ponder/react"; import * as schema from "./path/to/your/schema"; // Assuming schema is imported declare module "@ponder/react" { interface Register { schema: typeof schema; } } function PoolData() { const { data, isLoading, error } = usePonderQuery({ queryFn: (db) => db.query.pool.findMany({ where: (pool, { and, eq }) => and(eq(pool.chainId, 1), eq(pool.fee, 0)), orderBy: (pool, { desc }) => desc(pool.creationBlock), with: { token0: true, token1: true, }, }), }); // ... component logic to render data ... } ``` ### Response - **data** (array) - An array of pool objects, each containing nested `token0` and `token1` objects. - **isLoading** (boolean) - **error** (object) ``` -------------------------------- ### Ponder CLI Commands Source: https://ponder.sh/docs/api-reference/ponder/cli Available commands for the Ponder CLI, including `dev`, `start`, `serve`, `db`, and `codegen`. ```APIDOC ## Ponder CLI Commands ### Description This section outlines the primary commands available in the Ponder CLI for managing your project lifecycle. ### Commands - **dev [options]**: Start the development server with hot reloading. - **start [options]**: Start the production server. - **serve [options]**: Start the production HTTP server without the indexer. - **db**: Database management commands. - **codegen**: Generate the ponder-env.d.ts file, then exit. ``` -------------------------------- ### Updated viem Dependency Source: https://ponder.sh/docs/migration-guide This release updates the `viem` peer dependency requirement to `>=2`. The `context.client` action `getBytecode` was renamed to `getCode`. ```APIDOC ## Updated `viem` to `>=2` This release updates the `viem` peer dependency requirement to `>=2`. The `context.client` action `getBytecode` was renamed to `getCode`. ### Installation **pnpm** ```bash pnpm add viem@latest ``` **yarn** ```bash yarn add viem@latest ``` **npm** ```bash npm install viem@latest ``` ``` -------------------------------- ### Ponder Start Command with Schema for Railway Deployment Source: https://ponder.sh/docs/production/railway This command is used to start the Ponder application on Railway, enabling zero-downtime deployments by including the --schema option. It utilizes the RAILDAY_DEPLOYMENT_ID environment variable. ```shell pnpm start --schema $RAILWAY_DEPLOYMENT_ID ``` -------------------------------- ### ponder serve Source: https://ponder.sh/docs/api-reference/ponder/cli Starts the Ponder application in server-only mode, suitable for horizontal scaling. Indexing is disabled, and it serves data from the connected database. ```APIDOC ## ponder serve ### Description Starts the application in server-only mode. This option can be used to horizontally scale the HTTP server in production. It only works with Postgres, indexing is disabled, and the HTTP server runs as normal, serving data from the connected database. ### Method N/A (CLI Command) ### Endpoint N/A (CLI Command) ### Parameters #### Path Parameters None #### Query Parameters None #### Command Options - **--schema** (SCHEMA) - Optional - Database schema - **-p, --port** (PORT) - Optional - Port for the web server (default: 42069) - **-H, --hostname** (HOSTNAME) - Optional - Hostname for the web server (default: "0.0.0.0" or "::") - **-h, --help** - Optional - Display help for this command ``` -------------------------------- ### Arbitrary SQL within Indexing Functions Source: https://ponder.sh/docs/migration-guide This section introduces the new `context.db.sql` interface, which replaces the `findMany` method and allows for arbitrary SQL `select` queries within indexing functions. ```APIDOC ## Arbitrary SQL within Indexing Functions The new `context.db.sql` interface replaces the rigid `findMany` method and supports any valid SQL `select` query. ```typescript import { desc } from "@ponder/core"; import { account } from "../ponder.schema"; ponder.on("...", ({ event, context }) => { const result = await context.db.sql .select() .from(account) .orderBy(desc(account.balance)) .limit(1); }); ``` ``` -------------------------------- ### Direct RPC Request with Ponder Client Source: https://ponder.sh/docs/indexing/read-contracts Illustrates making a direct RPC request using `context.client.request` for advanced use cases. This example shows how to perform a `debug_traceTransaction` to get call traces. ```typescript import { ponder } from "ponder:registry"; ponder.on("ENS:NewOwner", async ({ event, context }) => { const traces = await context.client.request({ method: 'debug_traceTransaction', params: [event.transaction.hash, { tracer: "callTracer" }] }); // ... }); ``` -------------------------------- ### Initialize Ponder Project with npm Source: https://ponder.sh/docs/api-reference/create-ponder This command initializes a new Ponder project using the npm package manager. It prompts the user for project details and creates the necessary configuration files and directory structure. No external dependencies are required beyond npm itself. ```bash npm create ponder {...options} ``` -------------------------------- ### GraphQL Query for Account Data Source: https://ponder.sh/docs/get-started A GraphQL query to retrieve the top two accounts by balance and the total count of accounts. This demonstrates how to interact with the auto-generated GraphQL API provided by Ponder after data indexing. ```graphql query { accounts(orderBy: "balance", orderDirection: "desc", limit: 2) { items { address balance } totalCount } } ``` -------------------------------- ### Define Account Table Schema in TypeScript Source: https://ponder.sh/docs/get-started Defines the 'account' table schema using Ponder's TypeScript API. It includes an 'address' as the primary key, 'balance' as a bigint, and a new boolean field 'isOwner', showcasing schema customization. ```typescript import { index, onchainTable, primaryKey, relations } from "ponder"; export const account = onchainTable("account", (t) => ({ address: t.hex().primaryKey(), balance: t.bigint().notNull(), isOwner: t.boolean().notNull(), })); // ... ``` -------------------------------- ### Initialize Ponder Project with pnpm Source: https://ponder.sh/docs/api-reference/create-ponder This command initializes a new Ponder project using the pnpm package manager. It prompts the user for project details and creates the necessary configuration files and directory structure. No external dependencies are required beyond pnpm itself. ```bash pnpm create ponder {...options} ``` -------------------------------- ### Initialize Ponder Project with yarn Source: https://ponder.sh/docs/api-reference/create-ponder This command initializes a new Ponder project using the yarn package manager. It prompts the user for project details and creates the necessary configuration files and directory structure. No external dependencies are required beyond yarn itself. ```bash yarn create ponder {...options} ``` -------------------------------- ### Configuring Contract Factory Address (ponder.config.ts) Source: https://ponder.sh/docs/migration-guide This example shows the transition in configuring contract factories. The older method used a `factory` property, while the newer approach in Ponder 0.8+ uses a `factory()` function whose result is passed to the `address` property. ```typescript ponder.config.ts (0.7 and below) ``` import { createConfig } from "@ponder/core"; export default createConfig({ contracts: { uniswap: { factory: { address: "0x1F98431c8aD98523631AE4a59f267346ea31F984", event: getAbiItem({ abi: UniswapV3FactoryAbi, name: "PoolCreated" }), parameter: "pool", }, }, }, }); ``` ponder.config.ts (0.8) ``` import { createConfig } from "@ponder/core"; export default createConfig({ contracts: { uniswap: { factory: { address: "0x1F98431c8aD98523631AE4a59f267346ea31F984", event: getAbiItem({ abi: UniswapV3FactoryAbi, name: "PoolCreated" }), parameter: "pool", }, }, }, }); ``` ``` -------------------------------- ### Create Ponder Project using Etherscan Template Source: https://ponder.sh/docs/api-reference/create-ponder Initializes a Ponder project using contract details fetched from an Etherscan URL. This template requires a valid contract URL and optionally an Etherscan API key. It automatically configures the project with the contract's ABI, address, and deployment block from the specified chain. ```bash pnpm create ponder --etherscan [--etherscan-api-key ] ``` ```bash yarn create ponder --etherscan [--etherscan-api-key ] ``` ```bash npm create ponder --etherscan [--etherscan-api-key ] ``` -------------------------------- ### Handle New Player Event with Database Update Source: https://ponder.sh/docs/api-reference/ponder/indexing-functions This example shows an indexing function that handles the 'NewPlayer' event. It increments the playerCount in the 'world' record using a database update operation. This function is typically used in conjunction with a 'setup' function to initialize the record. ```typescript import { ponder } from "ponder:registry"; import { world } from "ponder:schema"; ponder.on("FunGame:NewPlayer", async ({ context }) => { await context.db .insert(world) .values({ id: 1, playerCount: 0 }) .onConflictDoUpdate((row) => ({ playerCount: row.playerCount + 1, })); }); ``` -------------------------------- ### Create Database Views for Latest Deployment Data Source: https://ponder.sh/docs/production/self-hosting This command demonstrates how to use the `ponder db create-views` CLI to create or update database views. These views provide access to the latest deployment's data in a static schema, allowing direct SQL queries without post-deployment configuration changes. The `--schema` flag specifies the target deployment's schema, and `--views-schema` indicates the schema where views should be created. ```bash pnpm db create-views --schema=deployment-123 --views-schema=project-name ``` -------------------------------- ### Define onchainTable with Indexes and Composite Primary Key Source: https://ponder.sh/docs/migration-guide Illustrates advanced usage of the `onchainTable` function, including defining indexes and composite primary keys. This example shows a `transfer_event` table with a single primary key and an index on the 'from' column, and an `allowance` table with a composite primary key on 'owner' and 'spender'. ```typescript import { onchainTable, index, primaryKey } from "@ponder/core"; export const transferEvents = onchainTable( "transfer_event", (t) => ({ id: t.text().primaryKey(), amount: t.bigint().notNull(), timestamp: t.integer().notNull(), from: t.hex().notNull(), to: t.hex().notNull(), }), (table) => ({ fromIdx: index().on(table.from), }) ); export const allowance = onchainTable( "allowance", (t) => ({ owner: t.hex().notNull(), spender: t.hex().notNull(), amount: t.bigint().notNull(), }), (table) => ({ pk: primaryKey({ columns: [table.owner, table.spender] }), }) ); export const approvalEvent = onchainTable("approval_event", (t) => ({ id: t.text().primaryKey(), amount: t.bigint().notNull(), timestamp: t.integer().notNull(), owner: t.hex().notNull(), spender: t.hex().notNull(), })); ``` -------------------------------- ### Ponder Dev Server Indexing Logs Source: https://ponder.sh/docs/get-started This log output illustrates the sequence of events during a Ponder development server hot reload and indexing process. It shows the hot reload of 'src/index.ts', database table drops and creations, and the subsequent backfill indexing progress, including block ranges and event counts. ```log 12:19:31.629 INFO Hot reload "src/index.ts" 12:19:31.889 WARN Dropped existing database tables count=4 tables=["account","transfer_event","allowance","approval_event"] (3ms) 12:19:31.901 INFO Created database tables count=4 tables=["account","transfer_event","allowance","approval_event"] (12ms) 12:19:32.168 INFO Started backfill indexing chain=mainnet block_range=[13142655,13150000] 12:19:32.169 INFO Started fetching backfill JSON-RPC data chain=mainnet cached_block=13147325 cache_rate=63.6% 12:19:32.447 INFO Indexed block range chain=mainnet event_count=6004 block_range=[13142655,13146396] (199ms) 12:19:32.551 INFO Indexed block range chain=mainnet event_count=3607 block_range=[13146397,13147325] (104ms) ``` -------------------------------- ### Scale HTTP Server Independently with Ponder Serve Source: https://ponder.sh/docs/production/self-hosting This command illustrates how to run a Ponder HTTP server in a standalone mode using `ponder serve`. This separates the HTTP serving concerns from the indexing engine, preventing resource contention and improving performance under heavy traffic. The `--schema` flag must match the schema used by the `ponder start` instance. ```bash ponder serve --schema=deployment-123 ``` -------------------------------- ### GraphQL Query: Jump to Specific Page of Persons (Ascending Age) Source: https://ponder.sh/docs/query/graphql This query shows how to jump to a specific page of persons. The `offset` is calculated as `(pageNumber - 1) * limit`. For example, to get page 2 with a limit of 2, the `offset` is `(2 - 1) * 2 = 2`. The query retrieves `name`, `age`, `pageInfo`, and `totalCount`. ```graphql query { persons( orderBy: "age", orderDirection: "asc", limit: 2, offset: 2 # Page 2: (2 - 1) * 2 = 2 ) { items { name age } pageInfo { hasPreviousPage hasNextPage } totalCount } } ``` -------------------------------- ### Update Indexing Logic with Owner Status (TypeScript) Source: https://ponder.sh/docs/get-started This snippet shows how to update the Ponder indexing logic for ERC20 transfers. It demonstrates inserting new rows into the 'account' table, including a boolean 'isOwner' field based on a predefined owner address. The code relies on the 'ponder' library and assumes a 'ponder:schema' is defined for the 'account' table. ```typescript import { ponder } from "ponder:registry"; import { account } from "ponder:schema"; const OWNER_ADDRESS = "0x3bf93770f2d4a794c3d9ebefbaebae2a8f09a5e5"; ponder.on("ERC20:Transfer", async ({ event, context }) => { await context.db .insert(account) .values({ address: event.args.from, balance: 0n, isOwner: event.args.from === OWNER_ADDRESS, }) .onConflictDoUpdate((row) => ({ // ... }) ``` -------------------------------- ### Get Context Type with Event Name (TypeScript) Source: https://ponder.sh/docs/api-reference/ponder/indexing-functions Demonstrates how to use the generic `Context` type from `ponder:registry` to optionally accept an event name and return the context object type. The example shows type inference for a 'Weth:Deposit' event, including chain, client, database models, and contract details. If no event name is provided, it returns a union of all context types. ```typescript import { ponder, type Context } from "ponder:registry"; function helper(context: Context<"Weth:Deposit">) { event; // ^? { // chain: { name: "mainnet"; id: 1; }; // client: ReadonlyClient; // db: { Account: DatabaseModel<{ id: `0x${string}`; balance: bigint; }> }; // contracts: { weth9: { abi: ...; address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" } // } } ``` -------------------------------- ### Get Indexing Function Arguments Type with Event Name (TypeScript) Source: https://ponder.sh/docs/api-reference/ponder/indexing-functions Illustrates the use of the generic `IndexingFunctionArgs` type from `ponder:registry`. This type optionally accepts an event name and returns the type for indexing function arguments. The example shows type inference for a 'Weth:Deposit' event, including event and context details. Similar to `Context`, omitting the event name results in a union of all argument types. ```typescript import { ponder, type IndexingFunctionArgs } from "ponder:registry"; function helper(args: IndexingFunctionArgs<"Weth:Deposit">) { args; // ^? { // event: { ... }; // context: { ... }; // } } ``` -------------------------------- ### List Database Schemas with ponder db list Command Source: https://ponder.sh/docs/migration-guide Illustrates the usage of the `ponder db list` command, which provides visibility into the database schemas being utilized by Ponder. The output includes schema names, active status, last active time, and table counts. ```shell $ ponder db list │ Schema │ Active │ Last active │ Table count │ ├───────────────┼──────────┼────────────────┼─────────────┤ │ indexer_prod │ yes │ --- │ 10 │ │ test │ no │ 26m 58s ago │ 10 │ │ demo │ no │ 1 day ago │ 5 │ ``` -------------------------------- ### PonderProvider Setup in React Source: https://ponder.sh/docs/api-reference/ponder-react Sets up the PonderProvider as a React Context Provider to make the SQL over HTTP client instance available to all child components. It requires a client instance from @ponder/client and integrates with TanStack Query's QueryClientProvider. ```jsx import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { PonderProvider } from "@ponder/react"; import { client } from "../lib/ponder"; // Client instance from @ponder/client const queryClient = new QueryClient(); function App() { return ( {/* Your application components */} ); } ``` -------------------------------- ### Set up PonderProvider for React (TypeScript) Source: https://ponder.sh/docs/query/sql-over-http Wraps the React application with `PonderProvider`, passing the initialized Ponder client. This makes the client available to all child components for data fetching and state management. ```typescript import { PonderProvider } from "@ponder/react"; import { client } from "../lib/ponder"; function App() { return ( {/** ... */} ); } ``` -------------------------------- ### Registering a GET Route Handler in Ponder API Source: https://ponder.sh/docs/query/api-endpoints Demonstrates how to register a simple GET route handler for '/hello' on the Hono instance. This allows serving basic text responses, such as 'Hello, world!', from a custom API endpoint. It requires the Hono library. ```typescript import { Hono } from "hono"; const app = new Hono(); app.get("/hello", (c) => { return c.text("Hello, world!"); }); export default app; ``` -------------------------------- ### Configure Ponder with Load Balanced RPC Transports Source: https://ponder.sh/docs/api-reference/ponder-utils Shows how to configure Ponder using `createConfig` with `loadBalance` to manage multiple RPC endpoints for a chain. This enhances resilience by providing fallback RPCs. ```javascript import { createConfig, loadBalance } from "ponder"; import { http, webSocket, rateLimit } from "viem"; export default createConfig({ chains: { mainnet: { id: 1, rpc: loadBalance([ http("https://cloudflare-eth.com"), http("https://eth-mainnet.public.blastapi.io"), webSocket("wss://ethereum-rpc.publicnode.com"), rateLimit(http("https://rpc.ankr.com/eth"), { requestsPerSecond: 5 }), ]), }, }, // ... }); ``` -------------------------------- ### GET /account/:address Source: https://ponder.sh/docs/api-reference/ponder/api-endpoints Retrieves a specific account by its address from the database. ```APIDOC ## GET /account/:address ### Description Retrieves a specific account by its address from the database. ### Method GET ### Endpoint /account/:address ### Parameters #### Path Parameters - **address** (string) - Required - The address of the account to retrieve. #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **account** (object) - The account object. - **address** (string) - The address of the account. #### Response Example ```json { "address": "0x123..." } ``` ```