> ## 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.

# Source

> API reference for EVM Portal source

The source component connects to SQD Portal and streams blockchain data to your pipeline. It's the starting point for all Pipes SDK data flows.

## evmPortalSource

Create a Portal source for EVM chains.

```ts theme={"system"}
evmPortalSource(config: EvmPortalSourceConfig): Source
```

**Parameters:**

* `id`: (required) Pipeline ID. Must be unique within any infra shared with other pipelines (DB, logging sinks etc).

* `portal`: (required) Portal API URL or config object.
  * String: `"https://portal.sqd.dev/datasets/ethereum-mainnet"`
  * Object: `{ url: string, finalized?: boolean }`. When `finalized: true` is set the stream will consist of finalized blocks only and none of the [fork handling machinery](../../guides/architecture-deep-dives/fork-handling) will be required.

* `outputs`: (required) A single query-transformers chain combo or record of named outputs.

* `cache`: (optional) Portal cache instance. If supplied, saves portal responses locally and reuses them when the pipeline re-runs.

* `logger`: (optional) A pino-compatible `Logger` instance or a log level string. Accepted level values: `'fatal'`, `'error'`, `'warn'`, `'info'`, `'debug'`, `'trace'`, `'silent'`, `false`, `null`. Passing `false` or `null` silences all log output. When omitted, a default console logger is used.

* `metrics`: (optional) `metricsServer()` instance for exposing Prometheus metrics.

* `progress`: (optional) Options for progress tracking.

* `profiler`: (optional) Enable the built-in per-batch profiler. See [Profiling](../../guides/advanced-topics/profiling).

**Example:**

```ts theme={"system"}
import { evmPortalSource } from "@subsquid/pipes/evm";
import { portalSqliteCache } from "@subsquid/pipes/portal-cache/node";

const source = evmPortalSource({
  id: "ethereum-transfers",
  portal: "https://portal.sqd.dev/datasets/ethereum-mainnet",
  outputs: evmDecoder({ 
    range: { from: 20000000 },
    events: { transfers: commonAbis.erc20.events.Transfer },
  }),
  cache: portalSqliteCache({ path: "./cache.sqlite" }),
});

```

### Finalized Blocks

You can configure the source to only receive finalized blocks:

```ts theme={"system"}
const source = evmPortalSource({
  portal: {
    finalized: true,
    url: 'https://portal.sqd.dev/datasets/ethereum-mainnet'
  }
});
```

Using finalized blocks eliminates the need for rollback handlers in your targets, simplifying the logic of your pipeline.

## Pipe methods

### pipe()

Chain a single [whole-pipe transformer](./transformer) to the source.

```ts theme={"system"}
source.pipe(transformer)
```

The returned value behaves exactly as the source.

See also: [Stateful transformers](../../guides/advanced-topics/stateful-transforms).

### pipeTo()

Connect the pipeline to a [target](./target).

```ts theme={"system"}
source.pipeTo(target)
```

This is a terminal operation: you cannot continue piping after calling this method.

If you want your stream to resume on restarts and properly handle unfinalized data, make sure that the target [manages cursors](../../guides/architecture-deep-dives/cursor-management) and [handles forks](../../guides/architecture-deep-dives/fork-handling) correctly.

### \*[Symbol.asyncIterator]()

Use the pipeline as an async iterator:

```ts theme={"system"}
for await (const { data } of stream) {
  // ... do something with data ...
}
```

On blockchain forks this will throw `ForkException`s - see [Fork handling](../../guides/architecture-deep-dives/fork-handling).
