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

# Warehouse

# GoldRush Warehouse Recipes on Solana

## Critical Rules

1. Warehouse delivery lands decoded Solana data as unified tables into ClickHouse, BigQuery, Postgres, Kafka, or S3.
2. The `swaps` normalizer streams decoded DEX trades; the `transfers` normalizer streams decoded SPL token transfers.
3. SPL transfer history is not available on the Foundational REST API for Solana - use the warehouse `transfers` normalizer instead.

***

The `swaps` normalizer streams decoded Solana DEX trades into your warehouse as one unified table.

## Why warehouse delivery

REST is great for live lookups, but every retention cohort, churn model, token analytics dashboard, and tax export lives in your data warehouse - not in HTTP responses. GoldRush streams Solana data continuously into customer-managed destinations with no ETL on your side.

## Pipeline configuration

**Create a pipeline**

In the [GoldRush Platform](https://goldrush.dev/platform/), navigate to **Manage Pipelines** and click **Create Pipeline**. Name it `solana-swaps`.

**Pick Solana + Swaps**

Choose **Solana** as the chain and **Swaps** as the data type.

**Configure your destination**

Connect ClickHouse, BigQuery, Postgres, Kafka, S3/GCS/R2, SQS, or a Webhook. ClickHouse is recommended for high-volume analytical queries over swaps.

```yaml theme={null}
destination:
  type: "clickhouse"
  url: "https://your-cluster.clickhouse.cloud:8443"
  user: "${CH_USER}"
  password: "${CH_PASSWORD}"
  database: "solana_swaps"
  batch_size: 5000
```

**Optional: SQL transform**

Filter or reshape rows before they land. Example: keep only swaps over \$100 of volume.

```yaml theme={null}
transforms:
  swaps: >
    SELECT *
    FROM swaps
    WHERE volume_usd >= 100
```

**Deploy**

Decoded swaps begin flowing within seconds.

## Schema

Key columns of the `swaps` table include `block_slot`, `block_time`, `tx_id`, `signer`, `pool_address`, `base_mint`, `quote_mint`, `base_amount`, `quote_amount`, `price_usd`, `volume_usd`, `protocol_name`, and CPI attribution fields (`outer_program`, `inner_program`, `instruction_type`).

## Sample analytical queries

### Top tokens by 24h volume

```sql theme={null}
SELECT
  base_mint,
  SUM(volume_usd) AS volume_24h
FROM swaps
WHERE block_time >= now() - INTERVAL 1 DAY
GROUP BY base_mint
ORDER BY volume_24h DESC
LIMIT 50;
```

### Per-protocol market share by token

```sql theme={null}
SELECT
  protocol_name,
  SUM(volume_usd) AS volume_24h,
  COUNT(*) AS swap_count
FROM swaps
WHERE base_mint = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
  AND block_time >= now() - INTERVAL 1 DAY
GROUP BY protocol_name
ORDER BY volume_24h DESC;
```

### Whale activity

```sql theme={null}
SELECT
  signer,
  SUM(volume_usd) AS volume_24h,
  COUNT(*) AS swap_count
FROM swaps
WHERE block_time >= now() - INTERVAL 1 DAY
GROUP BY signer
HAVING volume_24h > 1000000
ORDER BY volume_24h DESC;
```

### Jupiter routing through Raydium and Orca

```sql theme={null}
SELECT
  tx_id,
  protocol_name,
  outer_program,
  inner_program,
  base_mint,
  quote_mint,
  volume_usd
FROM swaps
WHERE outer_program = 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4' -- Jupiter v6
  AND block_time >= now() - INTERVAL 1 HOUR
ORDER BY tx_id, instruction_index;
```

## Production tips

* **ClickHouse for high-volume analytics.** Solana swap volume is significant; analytical queries over millions of rows are much faster on ClickHouse than Postgres.
* **Partition by `block_date`.** Most analytical queries are time-bounded.
* **Materialized views for per-token metrics.** Build hourly / daily roll-ups in ClickHouse materialized views to keep dashboards snappy.

## Related

* **SPL Transfers warehouse recipe** - companion table for transfer-side analytics.

***

The `transfers` normalizer streams decoded SPL token transfers on Solana into your warehouse. Each row carries source/destination account context (owner, balance pre/post, UI amount).

## Pipeline configuration

**Create a pipeline**

In the [GoldRush Platform](https://goldrush.dev/platform/), navigate to **Manage Pipelines** and click **Create Pipeline**. Name it `solana-spl-transfers`.

**Pick Solana + Transfers**

Choose **Solana** as the chain and **Transfers** as the data type.

**Configure your destination**

Connect ClickHouse, BigQuery, Postgres, Kafka, S3/GCS/R2, SQS, or a Webhook.

```yaml theme={null}
destination:
  type: "postgres"
  url: "postgresql://your-host:5432/solana_data"
  user: "${PG_USER}"
  password: "${PG_PASSWORD}"
  batch_size: 1000
```

**Optional: SQL transform**

Filter rows before they land. Example: keep only stablecoin transfers.

```yaml theme={null}
transforms:
  transfers: >
    SELECT *
    FROM transfers
    WHERE mint IN (
      'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',  -- USDC
      'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'   -- USDT
    )
```

**Deploy**

Decoded transfers begin flowing within seconds.

## Schema

Key columns of the `transfers` table:

* `block_slot`, `slot`, `block_time`, `tx_hash` (signature).
* `mint`, `amount` (raw uint64), `token_decimals`, `is_raw_amount`.
* `source_address` (token account), `source_owner` (wallet pubkey).
* `destination_address`, `destination_owner`.
* Pre/post balances on both sides (`*_pre_balance`, `*_post_balance`) plus UI-amount variants.
* `transfer_index` for ordering within a transaction.

## Sample analytical queries

### Daily stablecoin volume by mint

```sql theme={null}
SELECT
  date_trunc('day', to_timestamp(block_time)) AS day,
  mint,
  SUM(amount::numeric / power(10, token_decimals)) AS volume_tokens
FROM transfers
WHERE mint IN (
  'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
  'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB'
)
  AND block_time >= extract(epoch from now() - interval '30 days')
GROUP BY day, mint
ORDER BY day DESC, volume_tokens DESC;
```

### Net flow per wallet for a token

```sql theme={null}
WITH inflow AS (
  SELECT destination_owner AS wallet, mint, SUM(amount::numeric) AS in_amount
  FROM transfers
  WHERE mint = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
  GROUP BY destination_owner, mint
),
outflow AS (
  SELECT source_owner AS wallet, mint, SUM(amount::numeric) AS out_amount
  FROM transfers
  WHERE mint = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
  GROUP BY source_owner, mint
)
SELECT
  COALESCE(i.wallet, o.wallet) AS wallet,
  COALESCE(i.in_amount, 0) - COALESCE(o.out_amount, 0) AS net
FROM inflow i
FULL OUTER JOIN outflow o ON i.wallet = o.wallet AND i.mint = o.mint
ORDER BY net DESC
LIMIT 100;
```

### Exchange deposit attribution

Maintain a table of known exchange wallets; join against `destination_owner` to attribute deposits.

```sql theme={null}
SELECT
  ex.exchange_name,
  t.mint,
  date_trunc('day', to_timestamp(t.block_time)) AS day,
  SUM(t.amount::numeric / power(10, t.token_decimals)) AS deposits
FROM transfers t
JOIN known_exchanges ex ON t.destination_owner = ex.wallet
WHERE t.block_time >= extract(epoch from now() - interval '7 days')
GROUP BY ex.exchange_name, t.mint, day
ORDER BY day DESC, deposits DESC;
```

## Production tips

* **`source_owner` and `destination_owner`** are the *wallet* pubkeys, not the SPL token-account pubkeys. Index on these for wallet-centric queries.
* **`amount` is raw uint64.** Always divide by `power(10, token_decimals)` (or use the `*_ui` balance columns) for human-readable amounts.
* **High-volume mints (USDC, USDT, WSOL).** Partition by date and consider materialized views per top-N mint for fast dashboarding.

## Related

* **DEX Swaps warehouse recipe** - companion table for DEX-trade analytics.
* **Wallet endpoints (REST)** - REST lookups for the same transfer history.
