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

<AgentInstructions>

## Submitting Feedback

If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback:

POST https://docs.sqd.dev/feedback

```json
{
  "path": "/en/sdk/pipes-sdk/solana/quickstart",
  "feedback": "Description of the issue"
}
```

Only submit feedback when you have something specific and actionable to report.

</AgentInstructions>

# Quickstart

> Bootstrap a Pipes SDK project

# Using with AI

The fastest way to get an AI coding agent productive on a Pipes SDK project is to install the official [Pipes SDK Agent Skill](/en/ai/agent-skills#pipes-sdk-skill):

```bash theme={"system"}
npx skills add subsquid-labs/skills/pipes-sdk
```

The skill activates automatically on tasks like *"create an indexer for Uniswap V3 swaps"* or *"my indexer is syncing slowly, help me optimize it"*. It covers scaffolding, runtime error diagnosis, sync tuning, and data-quality checks.

Pair the skill with one or both MCP servers so the agent can read live data and look things up:

* [Portal MCP server](/en/ai/mcp-server) — 29 tools for querying blocks, transactions, logs, instructions, and analytics across 225+ datasets. No API key.
* [Documentation MCP server](/en/ai/mcp-server-docs) — search and retrieve these docs from inside the agent.

If you'd rather feed docs into a model directly, the static [`llms.txt`](/llms.txt) (index) and [`llms-full.txt`](/llms-full.txt) (full content) files are kept in sync with the site. See the [AI Development overview](/en/ai/ai-development) for the full menu.

# Scaffolding with Pipes CLI

<Note>
  `pipes-cli` is a work in progress.
</Note>

In a few minutes, you'll have a running pipe that indexes Orca Whirlpool swap instructions on Solana mainnet into a local PostgreSQL database.

## Prerequisites

* Node.js 22.15+
* `pnpm`
* Docker (for the bundled PostgreSQL container)

## Initialize the project

Run the CLI in the directory where you want the project folder to land:

```bash theme={"system"}
pnpx @subsquid/pipes-cli@1.0.0-alpha.4 init
```

The CLI prompts for the project folder name, package manager (please stick to `pnpm` for now), sink (please use `ClickHouse` or `Postgres`), network type, network, and template; then installs dependencies and writes a runnable project.

You can supply a JSON config instead of filling the prompts manually. Here's the configuration for Orca Whirlpool swap instructions mentioned above:

```bash theme={"system"}
pnpx @subsquid/pipes-cli@1.0.0-alpha.4 init --config '{
  "projectFolder": "orca-example",
  "packageManager": "pnpm",
  "sink": "postgresql",
  "networkType": "svm",
  "network": "solana-mainnet",
  "templates": [
    {
      "templateId": "custom",
      "params": {
        "contracts": [
          {
            "contractAddress": "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc",
            "contractName": "OrcaWhirlpool",
            "contractEvents": [
              {
                "name": "swap",
                "type": "instruction",
                "inputs": [
                  { "name": "amount", "type": "u64" },
                  { "name": "sqrtPriceLimit", "type": "u128" }
                ]
              }
            ],
            "range": { "from": "latest" }
          }
        ]
      }
    }
  ]
}'
```

`--config` also accepts a path to a JSON file.

To inspect the full config schema run

```
pnpx @subsquid/pipes-cli@1.0.0-alpha.4 init --schema
```

## Run the pipeline

The generated project ships with a `docker-compose.yml` that brings up the sink database and the pipeline together:

```bash theme={"system"}
cd orca-example
docker compose --profile with-pipeline up
```

For an iterative dev loop, run the database in Docker and the pipeline locally:

```bash theme={"system"}
docker compose up -d         # Postgres on :5432
pnpm run db:migrate          # apply the generated migration
pnpm run dev                 # tsx src/index.ts
```

Either way, rows start landing in the `orca_whirlpool_swap` table within a minute.

## What was generated

The project layout:

```
orca-example/
├── src/
│   ├── index.ts        # the pipe — source, decoder, target
│   ├── schemas.ts      # Drizzle table definitions
│   ├── contracts/      # generated ABI bindings (per program ID)
│   └── utils/
├── migrations/         # SQL migrations generated by drizzle-kit
├── docker-compose.yml  # Postgres + optional pipeline service
├── Dockerfile
├── drizzle.config.ts
├── package.json
├── .env                # DB_CONNECTION_STR — points at local Postgres
└── README.md
```

The pipe lives in `src/index.ts`. The decoder block defines what to extract + a light transform:

```ts theme={"system"}
const custom = solanaInstructionDecoder({
  range: { from: 'latest' },
  programId: ['whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc'],
  instructions: {
    swap: orcaWhirlpoolInstructions.swap,
  },
}).pipe(enrichEvents)
```

The decoder asks the Portal for `swap` instructions on the Orca Whirlpool program. `enrichEvents` (from `src/utils/`) reshapes each decoded instruction into a row matching the Drizzle table. See the [Pipe anatomy](./guides/basic-development/anatomy) and [Handling contract events](./guides/basic-development/handling-events) guides for more info on `evmDecoder()`.

The `main()` function wires the decoder to a [drizzleTarget](./reference/basic-components/target/postgres-drizzle):

```ts theme={"system"}
export async function main() {
  await solanaPortalSource({
    id: 'solana-orca-pipe',
    portal: 'https://portal.sqd.dev/datasets/solana-mainnet',
    outputs: { custom },
  }).pipeTo(
    drizzleTarget({
      db: drizzle(env.DB_CONNECTION_STR),
      tables: [orcaWhirlpoolSwapTable],
      onData: async ({ tx, data }) => {
        for (const values of chunk(data.custom.swap)) {
          await tx.insert(orcaWhirlpoolSwapTable).values(values)
        }
      },
    }),
  )
}
```

The `id` is a per-pipeline identifier — keep it stable so the [target's cursor](./guides/architecture-deep-dives/cursor-management) survives restarts. See [solanaPortalSource](./reference/basic-components/source) for the full source API and [Pipe anatomy](./guides/basic-development/anatomy) for how the pieces fit together.

## Other examples

<AccordionGroup>
  <Accordion title="Token balances">
    The `tokenBalances` template indexes pre/post token balances directly from blocks — no program ID needed. The generated pipe uses [solanaQuery()](./reference/basic-components/query-builder) instead of an instruction decoder.

    ```json theme={"system"}
    pnpx @subsquid/pipes-cli@1.0.0-alpha.4 init --config '{
      "projectFolder": "solana-tokens",
      "packageManager": "pnpm",
      "sink": "postgresql",
      "networkType": "svm",
      "network": "solana-mainnet",
      "templates": [
        {
          "templateId": "tokenBalances"
        }
      ]
    }'
    ```
  </Accordion>
</AccordionGroup>

The CLI ships one built-in SVM template — `tokenBalances` — plus the open-ended `custom` template shown at the top of the page.
