Skip to main content
Index USDC token transfers on Ethereum.

Prerequisites

  • Node.js 22.15+ installed
  • pnpm (recommended): npm install -g pnpm, or if pnpm is under ~/node/bin, run export PATH=${PATH}:${HOME}/node/bin before the init command

Initialize the project

Run the following in an empty directory, then follow the instructions.
pnpx @iankressin/pipes-cli@latest init --config '{
  "projectFolder": "usdc-example",
  "packageManager": "pnpm",
  "sink": "postgresql",
  "networkType": "evm",
  "network": "ethereum-mainnet",
  "templates": [
    {
      "templateId": "erc20Transfers",
      "params": {
        "contractAddresses": ["0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"]
      }
    }
  ]
}'

What it’s doing

Find the following code at src/index.ts:
export async function main() {
  await evmPortalSource({
    portal: 'https://portal.sqd.dev/datasets/ethereum-mainnet',
  })
    .pipeComposite({
      erc20Transfers,
    })
    .pipeTo(
      drizzleTarget({
        db: drizzle(env.DB_CONNECTION_STR),
        tables: [erc20TransfersTable],
        onData: async ({ tx, data }) => {
          for (const values of chunk(data.erc20Transfers)) {
            await tx.insert(erc20TransfersTable).values(values)
          }
        },
      }),
    )
}
Explanations TBA.

Other examples

pnpx @iankressin/pipes-cli@latest init --config '{
  "projectFolder": "uniswapv3-swaps-example",
  "packageManager": "pnpm",
  "sink": "postgresql",
  "networkType": "evm",
  "network": "ethereum-mainnet",
  "templates": [
    {
      "templateId": "uniswapV3Swaps",
      "params": {
        "factoryAddress": "0x1f98431c8ad98523631ae4a59f267346ea31f984"
      }
    }
  ]
}'
pnpx @iankressin/pipes-cli@latest init --config '{
  "projectFolder": "aave-deposits-withdrawals-example",
  "packageManager": "pnpm",
  "sink": "postgresql",
  "networkType": "evm",
  "network": "ethereum-mainnet",
  "templates": [
    {
      "templateId": "custom",
      "params": {
        "contracts": [
          {
            "contractAddress": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
            "contractName": "AaveV3Pool",
            "contractEvents": [
              {
                "anonymous": false,
                "inputs": [
                  { "indexed": true, "name": "reserve", "type": "address" },
                  { "indexed": false, "name": "user", "type": "address" },
                  { "indexed": true, "name": "onBehalfOf", "type": "address" },
                  { "indexed": false, "name": "amount", "type": "uint256" },
                  { "indexed": true, "name": "referralCode", "type": "uint16" }
                ],
                "name": "Supply",
                "type": "event"
              },
              {
                "anonymous": false,
                "inputs": [
                  { "indexed": true, "name": "reserve", "type": "address" },
                  { "indexed": true, "name": "user", "type": "address" },
                  { "indexed": true, "name": "to", "type": "address" },
                  { "indexed": false, "name": "amount", "type": "uint256" }
                ],
                "name": "Withdraw",
                "type": "event"
              }
            ]
          }
        ]
      }
    }
  ]
}'
Many more TBA, eventually covering all major protocols.

Using with AI

Instructions on setting up AI workflows in common environments TBA. Tentatively skills-based.