portal-query-evm-logs

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

When to Use This Skill

何时使用该Skill

Use this skill when you need to:
  • Track ERC20 token transfers (Transfer events)
  • Monitor DeFi protocol events (Swap, Deposit, Withdraw, etc.)
  • Find events emitted by specific contracts
  • Filter events by indexed parameters (addresses, token IDs, etc.)
  • Analyze historical on-chain activity
This is the most common Portal use case - most blockchain data analysis involves event logs.

当你需要以下操作时使用该Skill:
  • 追踪ERC20代币转账(Transfer事件)
  • 监控DeFi协议事件(Swap、Deposit、Withdraw等)
  • 查找特定合约发出的事件
  • 按索引参数(地址、代币ID等)过滤事件
  • 分析历史链上活动
这是Portal最常见的使用场景——大多数区块链数据分析都涉及事件日志。

Query Structure

查询结构

Portal Stream API uses POST requests with JSON payloads to
/datasets/{dataset-name}/stream
.
Basic EVM log query structure:
json
{
  "type": "evm",
  "fromBlock": 19500000,
  "toBlock": 19500100,
  "logs": [{
    "address": ["0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"],
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]
  }],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "data": true,
      "transactionHash": true
    }
  }
}
Field explanations:
  • type: "evm"
    - Required for EVM chains
  • fromBlock/toBlock
    - Block range (required)
  • logs
    - Array of log filter objects
  • address
    - Contract addresses to filter (INDEXED - fast)
  • topic0
    - Event signature hash (INDEXED - fast)
  • topic1/2/3
    - Indexed event parameters (INDEXED - fast)
  • fields
    - Which fields to include in response (optimize payload size)

Portal Stream API使用带JSON负载的POST请求访问
/datasets/{dataset-name}/stream
接口。
基础EVM日志查询结构:
json
{
  "type": "evm",
  "fromBlock": 19500000,
  "toBlock": 19500100,
  "logs": [{
    "address": ["0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"],
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]
  }],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "data": true,
      "transactionHash": true
    }
  }
}
字段说明:
  • type: "evm"
    - EVM链必填参数
  • fromBlock/toBlock
    - 区块范围(必填)
  • logs
    - 日志过滤器对象数组
  • address
    - 要过滤的合约地址(已索引 - 查询速度快)
  • topic0
    - 事件签名哈希(已索引 - 查询速度快)
  • topic1/2/3
    - 索引化的事件参数(已索引 - 查询速度快)
  • fields
    - 响应中需要包含的字段(优化负载大小)

Understanding Event Topics

理解事件主题

EVM event logs use topics for indexed parameters:
solidity
event Transfer(address indexed from, address indexed to, uint256 amount);
Maps to:
  • topic0
    = keccak256("Transfer(address,address,uint256)") =
    0xddf252ad...
  • topic1
    = indexed
    from
    address (padded to 32 bytes)
  • topic2
    = indexed
    to
    address (padded to 32 bytes)
  • data
    = non-indexed parameters (
    amount
    )
Key rules:
  1. topic0
    is ALWAYS the event signature hash
  2. topic1-3
    are indexed parameters in declaration order
  3. Non-indexed parameters go in
    data
    field
  4. Anonymous events don't have topic0 (rare)

EVM事件日志使用主题存储索引参数:
solidity
event Transfer(address indexed from, address indexed to, uint256 amount);
对应关系:
  • topic0
    = keccak256("Transfer(address,address,uint256)") =
    0xddf252ad...
  • topic1
    = 索引化的
    from
    地址(填充至32字节)
  • topic2
    = 索引化的
    to
    地址(填充至32字节)
  • data
    = 非索引参数(
    amount
关键规则:
  1. topic0
    始终是事件签名哈希
  2. topic1-3
    按声明顺序对应索引参数
  3. 非索引参数存储在
    data
    字段中
  4. 匿名事件没有topic0(罕见情况)

Examples

示例

Example 1: Track USDC Transfers on Base

示例1:追踪Base链上的USDC转账

Use case: Monitor all USDC transfer events on Base mainnet.
json
{
  "type": "evm",
  "fromBlock": 10000000,
  "toBlock": 10000100,
  "logs": [{
    "address": ["0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"],
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]
  }],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "data": true,
      "transactionHash": true,
      "blockNumber": true
    }
  }
}
Dataset:
base-mainnet
Contract: USDC on Base (0x833589fcd6edb6e08f4c7c32d4f71b54bda02913) Event: Transfer(address indexed from, address indexed to, uint256 amount)

使用场景: 监控Base主网上所有USDC转账事件。
json
{
  "type": "evm",
  "fromBlock": 10000000,
  "toBlock": 10000100,
  "logs": [{
    "address": ["0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"],
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]
  }],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "data": true,
      "transactionHash": true,
      "blockNumber": true
    }
  }
}
数据集:
base-mainnet
合约: Base链上的USDC(0x833589fcd6edb6e08f4c7c32d4f71b54bda02913) 事件: Transfer(address indexed from, address indexed to, uint256 amount)

Example 2: Find Transfers FROM Specific Address

示例2:查找从特定地址发起的转账

Use case: Track all ERC20 transfers sent by a specific wallet.
json
{
  "type": "evm",
  "fromBlock": 19500000,
  "logs": [{
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
    "topic1": ["0x000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045"]
  }],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "data": true
    }
  }
}
Notes:
  • topic1
    = sender address (vitalik.eth)
  • Address is padded to 32 bytes with leading zeros
  • Omitting
    address
    filter searches ALL contracts (slower but comprehensive)

使用场景: 追踪特定钱包地址发起的所有ERC20转账。
json
{
  "type": "evm",
  "fromBlock": 19500000,
  "logs": [{
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
    "topic1": ["0x000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045"]
  }],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "data": true
    }
  }
}
说明:
  • topic1
    = 发送方地址(vitalik.eth)
  • 地址需用前导零填充至32字节
  • 省略
    address
    过滤器会搜索所有合约(速度较慢但覆盖全面)

Example 3: Uniswap V3 Swap Events

示例3:Uniswap V3 Swap事件

Use case: Track Uniswap V3 pool swap events on Ethereum.
json
{
  "type": "evm",
  "fromBlock": 19500000,
  "toBlock": 19500100,
  "logs": [{
    "address": ["0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640"],
    "topic0": ["0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67"]
  }],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "data": true,
      "blockNumber": true,
      "transactionHash": true
    }
  }
}
Dataset:
ethereum-mainnet
Contract: USDC/WETH 0.05% pool Event: Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick)

使用场景: 追踪以太坊链上Uniswap V3资金池的Swap事件。
json
{
  "type": "evm",
  "fromBlock": 19500000,
  "toBlock": 19500100,
  "logs": [{
    "address": ["0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640"],
    "topic0": ["0xc42079f94a6350d7e6235f29174924f928cc2ac818eb64fed8004e115fbcca67"]
  }],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "data": true,
      "blockNumber": true,
      "transactionHash": true
    }
  }
}
数据集:
ethereum-mainnet
合约: USDC/WETH 0.05%资金池 事件: Swap(address indexed sender, address indexed recipient, int256 amount0, int256 amount1, uint160 sqrtPriceX96, uint128 liquidity, int24 tick)

Example 4: Multiple Event Types from Same Contract

示例4:同一合约的多种事件类型

Use case: Track both Deposit and Withdraw events from Aave lending pool.
json
{
  "type": "evm",
  "fromBlock": 19500000,
  "logs": [
    {
      "address": ["0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2"],
      "topic0": ["0xde6857219544bb5b7746f48ed30be6386fefc61b2f864cacf559893bf50fd951"]
    },
    {
      "address": ["0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2"],
      "topic0": ["0x3115d1449a7b732c986cba18244e897a450f61e1bb8d589cd2e69e6c8924f9f7"]
    }
  ],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "data": true
    }
  }
}
Notes:
  • Multiple filter objects in
    logs
    array = OR logic
  • Both Deposit and Withdraw events will be returned
  • Same contract address for both filters

使用场景: 追踪Aave借贷池的Deposit和Withdraw事件。
json
{
  "type": "evm",
  "fromBlock": 19500000,
  "logs": [
    {
      "address": ["0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2"],
      "topic0": ["0xde6857219544bb5b7746f48ed30be6386fefc61b2f864cacf559893bf50fd951"]
    },
    {
      "address": ["0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2"],
      "topic0": ["0x3115d1449a7b732c986cba18244e897a450f61e1bb8d589cd2e69e6c8924f9f7"]
    }
  ],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "data": true
    }
  }
}
说明:
  • logs
    数组中的多个过滤器对象表示OR逻辑
  • 会同时返回Deposit和Withdraw事件
  • 两个过滤器使用同一合约地址

Example 5: NFT Transfers to Specific Address

示例5:转至特定地址的NFT转账

Use case: Track NFT transfers to a specific wallet address.
json
{
  "type": "evm",
  "fromBlock": 17000000,
  "toBlock": 17001000,
  "logs": [{
    "address": ["0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D"],
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
    "topic2": ["0x000000000000000000000000742d35cc6634c0532925a3b844bc454e4438f44e"]
  }],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "data": true,
      "transactionHash": true,
      "blockNumber": true
    }
  }
}
Dataset:
ethereum-mainnet
Contract: Bored Ape Yacht Club Event: Transfer(address indexed from, address indexed to, uint256 indexed tokenId) Filter: NFTs transferred TO a specific address (topic2) Notes:
  • ERC721 Transfer events have 3 indexed parameters:
    from
    ,
    to
    ,
    tokenId
  • topic1
    = from address,
    topic2
    = to address,
    topic3
    = token ID
  • Compare with ERC20: only 2 indexed parameters (
    from
    ,
    to
    ), amount is in
    data

使用场景: 追踪转至特定钱包地址的NFT转账。
json
{
  "type": "evm",
  "fromBlock": 17000000,
  "toBlock": 17001000,
  "logs": [{
    "address": ["0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D"],
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
    "topic2": ["0x000000000000000000000000742d35cc6634c0532925a3b844bc454e4438f44e"]
  }],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "data": true,
      "transactionHash": true,
      "blockNumber": true
    }
  }
}
数据集:
ethereum-mainnet
合约: Bored Ape Yacht Club 事件: Transfer(address indexed from, address indexed to, uint256 indexed tokenId) 过滤条件: 转至特定地址的NFT(topic2) 说明:
  • ERC721的Transfer事件包含3个索引参数:
    from
    to
    tokenId
  • topic1
    = 转出地址,
    topic2
    = 转入地址,
    topic3
    = 代币ID
  • 与ERC20对比:仅包含2个索引参数(
    from
    to
    ),金额存储在
    data

Example 6: Query Multiple ERC-20 Tokens Simultaneously

示例6:同时查询多种ERC-20代币

Use case: Track transfers across multiple stablecoins (USDC, USDT, DAI) in one query.
json
{
  "type": "evm",
  "fromBlock": 18000000,
  "toBlock": 18010000,
  "logs": [{
    "address": [
      "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
      "0xdAC17F958D2ee523a2206206994597C13D831ec7",
      "0x6B175474E89094C44Da98b954EedeAC495271d0F"
    ],
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]
  }],
  "fields": {
    "block": {
      "number": true,
      "timestamp": true
    },
    "log": {
      "address": true,
      "topics": true,
      "data": true,
      "transactionHash": true
    }
  }
}
Dataset:
ethereum-mainnet
Contracts: USDC, USDT, DAI Notes:
  • Multiple addresses in array = OR logic (matches any of the addresses)
  • Including block fields allows timestamping events
  • Efficient way to track multiple tokens without separate queries

使用场景: 一次查询中追踪多种稳定币(USDC、USDT、DAI)的转账。
json
{
  "type": "evm",
  "fromBlock": 18000000,
  "toBlock": 18010000,
  "logs": [{
    "address": [
      "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
      "0xdAC17F958D2ee523a2206206994597C13D831ec7",
      "0x6B175474E89094C44Da98b954EedeAC495271d0F"
    ],
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]
  }],
  "fields": {
    "block": {
      "number": true,
      "timestamp": true
    },
    "log": {
      "address": true,
      "topics": true,
      "data": true,
      "transactionHash": true
    }
  }
}
数据集:
ethereum-mainnet
合约: USDC、USDT、DAI 说明:
  • 数组中的多个地址表示OR逻辑(匹配任意地址)
  • 包含区块字段可实现事件时间戳标记
  • 无需单独查询即可高效追踪多种代币

Example 7: Monitor NFT Minting Events

示例7:监控NFT铸造事件

Use case: Capture NFT creation events (transfers from zero address).
json
{
  "type": "evm",
  "fromBlock": 18000000,
  "toBlock": 18010000,
  "logs": [{
    "address": ["0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D"],
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
    "topic1": ["0x0000000000000000000000000000000000000000000000000000000000000000"]
  }],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "transactionHash": true,
      "blockNumber": true
    }
  }
}
Dataset:
ethereum-mainnet
Contract: Bored Ape Yacht Club Notes:
  • Minting is represented as a transfer from the zero address
  • topic1
    = zero address (0x000...000 padded to 32 bytes)
  • topic2
    = recipient address (minter)
  • topic3
    = token ID

使用场景: 捕获NFT创建事件(从零地址转账)。
json
{
  "type": "evm",
  "fromBlock": 18000000,
  "toBlock": 18010000,
  "logs": [{
    "address": ["0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D"],
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],
    "topic1": ["0x0000000000000000000000000000000000000000000000000000000000000000"]
  }],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "transactionHash": true,
      "blockNumber": true
    }
  }
}
数据集:
ethereum-mainnet
合约: Bored Ape Yacht Club 说明:
  • 铸造行为表示为从无地址(零地址)发起的转账
  • topic1
    = 零地址(0x000...000填充至32字节)
  • topic2
    = 接收地址(铸造者)
  • topic3
    = 代币ID

Example 8: Track ERC-1155 Multi-Token Transfers

示例8:追踪ERC-1155多代币转账

Use case: Monitor ERC-1155 TransferSingle and TransferBatch events.
json
{
  "type": "evm",
  "fromBlock": 18000000,
  "toBlock": 18010000,
  "logs": [{
    "address": ["0x495f947276749Ce646f68AC8c248420045cb7b5e"],
    "topic0": [
      "0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62",
      "0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb"
    ]
  }],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "data": true
    }
  }
}
Dataset:
ethereum-mainnet
Contract: OpenSea Shared Storefront (ERC-1155) Event Signatures:
  • TransferSingle:
    0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62
  • TransferBatch:
    0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb
Notes:
  • ERC-1155 uses separate signatures for single vs batch transfers
  • Both signatures must be queried to capture complete transfer activity
  • data
    field contains encoded quantity information

使用场景: 监控ERC-1155的TransferSingle和TransferBatch事件。
json
{
  "type": "evm",
  "fromBlock": 18000000,
  "toBlock": 18010000,
  "logs": [{
    "address": ["0x495f947276749Ce646f68AC8c248420045cb7b5e"],
    "topic0": [
      "0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62",
      "0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb"
    ]
  }],
  "fields": {
    "log": {
      "address": true,
      "topics": true,
      "data": true
    }
  }
}
数据集:
ethereum-mainnet
合约: OpenSea Shared Storefront(ERC-1155) 事件签名:
  • TransferSingle:
    0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62
  • TransferBatch:
    0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb
说明:
  • ERC-1155为单笔和批量转账使用不同的签名
  • 必须同时查询两个签名才能捕获完整的转账活动
  • data
    字段包含编码后的数量信息

Example 9: Monitor Multiple NFT Collections

示例9:监控多个NFT系列

Use case: Track transfers across popular NFT collections (BAYC, MAYC, CryptoPunks).
json
{
  "type": "evm",
  "fromBlock": 18000000,
  "toBlock": 18010000,
  "logs": [{
    "address": [
      "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
      "0x60E4d786628Fea6478F785A6d7e704777c86a7c6",
      "0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB"
    ],
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]
  }],
  "fields": {
    "block": {
      "number": true,
      "timestamp": true
    },
    "log": {
      "address": true,
      "topics": true,
      "transactionHash": true
    }
  }
}
Dataset:
ethereum-mainnet
Contracts: BAYC, MAYC, CryptoPunks Notes:
  • Multi-collection filtering with single query
  • Transfer event signature uniform across ERC-721 contracts
  • Indexed parameters contain from, to, and tokenID

使用场景: 追踪热门NFT系列(BAYC、MAYC、CryptoPunks)的转账。
json
{
  "type": "evm",
  "fromBlock": 18000000,
  "toBlock": 18010000,
  "logs": [{
    "address": [
      "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
      "0x60E4d786628Fea6478F785A6d7e704777c86a7c6",
      "0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB"
    ],
    "topic0": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]
  }],
  "fields": {
    "block": {
      "number": true,
      "timestamp": true
    },
    "log": {
      "address": true,
      "topics": true,
      "transactionHash": true
    }
  }
}
数据集:
ethereum-mainnet
合约: BAYC、MAYC、CryptoPunks 说明:
  • 单查询实现多系列过滤
  • 所有ERC-721合约的Transfer事件签名统一
  • 索引参数包含转出地址、转入地址和代币ID

Key Concepts

核心概念

1. Indexed vs Non-Indexed Parameters

1. 索引参数与非索引参数

Indexed parameters (up to 3):
  • Stored in
    topic1
    ,
    topic2
    ,
    topic3
  • Filterable via Portal API
  • Padded to 32 bytes
  • Fast to query
Non-indexed parameters:
  • Stored in
    data
    field (ABI-encoded)
  • NOT filterable via Portal API
  • Must decode client-side
  • Smaller storage footprint
Rule: Use indexed parameters for fields you need to filter by.

索引参数(最多3个):
  • 存储在
    topic1
    topic2
    topic3
  • 可通过Portal API过滤
  • 填充至32字节
  • 查询速度快
非索引参数:
  • 存储在
    data
    字段中(ABI编码)
  • 无法通过Portal API过滤
  • 必须在客户端解码
  • 存储空间占用更小
规则: 对需要过滤的字段使用索引参数。

2. Filter Performance Optimization

2. 过滤性能优化

Field index status:
  • address
    - INDEXED (fast)
  • topic0
    - INDEXED (fast)
  • topic1/2/3
    - INDEXED (fast)
  • data
    - NOT INDEXED (can't filter)
  • blockNumber
    - INDEXED (fast)
  • transactionIndex
    - INDEXED (fast)
Best practices:
  1. Always filter by
    address
    if you know the contract (10-100x faster)
  2. Add
    topic0
    filter for specific events (another 10x faster)
  3. Add topic1-3 filters for further narrowing
  4. Use narrow block ranges when possible
Performance comparison:
No filters: 1M+ logs/sec → Timeout risk
address only: ~100K logs/sec → Usually safe
address + topic0: ~10K logs/sec → Fast
address + topic0 + topic1: <1K logs/sec → Very fast

字段索引状态:
  • address
    - 已索引(速度快)
  • topic0
    - 已索引(速度快)
  • topic1/2/3
    - 已索引(速度快)
  • data
    - 未索引(无法过滤)
  • blockNumber
    - 已索引(速度快)
  • transactionIndex
    - 已索引(速度快)
最佳实践:
  1. 若已知合约地址,始终按
    address
    过滤(速度提升10-100倍)
  2. 添加
    topic0
    过滤特定事件(再提升10倍速度)
  3. 添加topic1-3过滤进一步缩小范围
  4. 尽可能使用窄区块范围
性能对比:
无过滤器:100万+日志/秒 → 存在超时风险
仅address过滤:约10万日志/秒 → 通常安全
address + topic0过滤:约1万日志/秒 → 快速
address + topic0 + topic1过滤:<1000日志/秒 → 极快

3. Field Selection Strategy

3. 字段选择策略

Minimize payload size by requesting only needed fields:
json
{
  "fields": {
    "log": {
      "address": true,        // Contract address
      "topics": true,         // All topics array
      "data": true,           // Event data
      "transactionHash": true,// Tx hash
      "blockNumber": true,    // Block number
      "logIndex": true,       // Position in block
      "removed": true         // Chain reorg flag
    }
  }
}
Common minimal field sets:
  • Event tracking:
    address
    ,
    topics
    ,
    data
    ,
    transactionHash
  • Volume analysis:
    address
    ,
    topics
    ,
    blockNumber
  • Full context: all fields
Note: Requesting fewer fields = smaller response = faster transfer.

仅请求所需字段以最小化负载大小:
json
{
  "fields": {
    "log": {
      "address": true,        // 合约地址
      "topics": true,         // 所有主题数组
      "data": true,           // 事件数据
      "transactionHash": true,// 交易哈希
      "blockNumber": true,    // 区块号
      "logIndex": true,       // 在区块中的位置
      "removed": true         // 链重组标记
    }
  }
}
常见最小字段集:
  • 事件追踪:
    address
    topics
    data
    transactionHash
  • 交易量分析:
    address
    topics
    blockNumber
  • 完整上下文:所有字段
注意: 请求的字段越少 → 响应体积越小 → 传输速度越快。

4. Topic Padding Rules

4. 主题填充规则

Addresses in topics must be padded to 32 bytes:
Original: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
Padded:   0x000000000000000000000000d8dA6BF26964aF9D7eEd9e03E53415D37aA96045
Padding rules:
  • Addresses: left-pad with zeros (24 zeros + 20-byte address)
  • uint256: already 32 bytes (no padding needed)
  • uint8/16/32/etc: left-pad with zeros
  • bytes32: no padding needed
Tool: Use ethers.js
zeroPadValue()
or manually pad.

主题中的地址必须填充至32字节:
原始地址:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
填充后:   0x000000000000000000000000d8dA6BF26964aF9D7eEd9e03E53415D37aA96045
填充规则:
  • 地址:左侧补零(24个零 + 20字节地址)
  • uint256:已为32字节(无需填充)
  • uint8/16/32等:左侧补零
  • bytes32:无需填充
工具: 使用ethers.js的
zeroPadValue()
或手动填充。

Common Mistakes

常见错误

❌ Mistake 1: Filtering by Non-Indexed Parameter

❌ 错误1:按非索引参数过滤

json
{
  "logs": [{
    "address": ["0x..."],
    "topic0": ["0x..."],
    "data": ["0x1234..."]  // ❌ Can't filter by data
  }]
}
Fix: Only topic0-3 are filterable. To filter by non-indexed params, fetch all events and filter client-side.

json
{
  "logs": [{
    "address": ["0x..."],
    "topic0": ["0x..."],
    "data": ["0x1234..."]  // ❌ 无法按data过滤
  }]
}
修复: 仅topic0-3可用于过滤。若需按非索引参数过滤,需先获取所有事件再在客户端过滤。

❌ Mistake 2: Forgetting Topic Padding

❌ 错误2:忘记主题填充

json
{
  "topic1": ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"]  // ❌ Not padded
}
Fix: Always pad addresses to 32 bytes:
json
{
  "topic1": ["0x000000000000000000000000d8dA6BF26964aF9D7eEd9e03E53415D37aA96045"]
}

json
{
  "topic1": ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"]  // ❌ 未填充
}
修复: 始终将地址填充至32字节:
json
{
  "topic1": ["0x000000000000000000000000d8dA6BF26964aF9D7eEd9e03E53415D37aA96045"]
}

❌ Mistake 3: Using Wrong Event Signature

❌ 错误3:使用错误的事件签名

json
{
  "topic0": ["0x123..."]  // ❌ Incorrect hash
}
Fix: Compute correct keccak256 hash:
  • Function:
    Transfer(address,address,uint256)
  • No spaces, exact types
  • Use ethers.js:
    ethers.id("Transfer(address,address,uint256)")

json
{
  "topic0": ["0x123..."]  // ❌ 哈希错误
}
修复: 计算正确的keccak256哈希:
  • 函数:
    Transfer(address,address,uint256)
  • 无空格,类型精确
  • 使用ethers.js:
    ethers.id("Transfer(address,address,uint256)")

❌ Mistake 4: Too Broad Query (No Filters)

❌ 错误4:查询范围过宽(无过滤器)

json
{
  "type": "evm",
  "fromBlock": 0,
  "logs": [{}]  // ❌ No filters = millions of logs
}
Fix: Always filter by at least
address
or
topic0
, and use reasonable block ranges.

json
{
  "type": "evm",
  "fromBlock": 0,
  "logs": [{}]  // ❌ 无过滤器 = 数百万条日志
}
修复: 始终至少按
address
topic0
过滤,并使用合理的区块范围。

❌ Mistake 5: Wrong Dataset Name

❌ 错误5:数据集名称错误

json
// POST /datasets/arbitrum/stream  ❌ Wrong name
Fix: Use correct Portal dataset names:
  • ethereum-mainnet
    (not "ethereum")
  • arbitrum-one
    (not "arbitrum")
  • base-mainnet
    (not "base")
See portal-dataset-discovery skill for full mapping.

json
// POST /datasets/arbitrum/stream  ❌ 名称错误
修复: 使用正确的Portal数据集名称:
  • ethereum-mainnet
    (而非"ethereum")
  • arbitrum-one
    (而非"arbitrum")
  • base-mainnet
    (而非"base")
查看portal-dataset-discovery skill获取完整映射。

Response Format

响应格式

Portal returns JSON Lines (one JSON object per line):
json
{"header":{"blockNumber":19500000,"hash":"0x...","parentHash":"0x...","timestamp":1234567890}}
{"logs":[{"address":"0x833589fcd6edb6e08f4c7c32d4f71b54bda02913","topics":["0xddf252ad...","0x000...123","0x000...456"],"data":"0x000...789","transactionHash":"0xabc...","logIndex":42}]}
{"logs":[{"address":"0x833589fcd6edb6e08f4c7c32d4f71b54bda02913","topics":["0xddf252ad...","0x000...111","0x000...222"],"data":"0x000...333","transactionHash":"0xdef...","logIndex":18}]}
Parsing:
  1. Split response by newlines
  2. Parse each line as JSON
  3. First line is block header
  4. Subsequent lines contain logs array

Portal返回JSON Lines格式(每行一个JSON对象):
json
{"header":{"blockNumber":19500000,"hash":"0x...","parentHash":"0x...","timestamp":1234567890}}
{"logs":[{"address":"0x833589fcd6edb6e08f4c7c32d4f71b54bda02913","topics":["0xddf252ad...","0x000...123","0x000...456"],"data":"0x000...789","transactionHash":"0xabc...","logIndex":42}]}
{"logs":[{"address":"0x833589fcd6edb6e08f4c7c32d4f71b54bda02913","topics":["0xddf252ad...","0x000...111","0x000...222"],"data":"0x000...333","transactionHash":"0xdef...","logIndex":18}]}
解析方法:
  1. 按换行符拆分响应
  2. 将每行解析为JSON
  3. 第一行是区块头
  4. 后续行包含日志数组

Related Skills

相关Skills

  • portal-query-evm-transactions - Query transactions that emitted these logs
  • portal-query-evm-traces - Track internal calls related to events
  • portal-dataset-discovery - Find correct dataset name for your chain
  • pipes-abi - Get ABI and event signatures for contracts

  • portal-query-evm-transactions - 查询触发这些日志的交易
  • portal-query-evm-traces - 追踪与事件相关的内部调用
  • portal-dataset-discovery - 查找对应链的正确数据集名称
  • pipes-abi - 获取合约的ABI和事件签名

Additional Resources

额外资源

Official Subsquid Documentation

官方Subsquid文档

Core Documentation

核心文档

  • llms.txt - Quick reference for Portal API logs querying
  • llms-full.txt - Complete Portal documentation
  • skill.md - Comprehensive Portal API guide

API Resources

API资源