Skip to content

Commit

Permalink
Update flare to use eth SDK (#543)
Browse files Browse the repository at this point in the history
  • Loading branch information
stwiname authored Jul 22, 2024
1 parent c938fd3 commit ff1c5ff
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 27 deletions.
108 changes: 98 additions & 10 deletions docs/indexer/build/manifest/flare.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,95 @@ With the number of new features we are adding to SubQuery, and the slight differ
Below is a standard example of a basic `project.ts`.

```ts
import {
EthereumProject,
EthereumDatasourceKind,
EthereumHandlerKind,
} from "@subql/types-ethereum";

// Can expand the Datasource processor types via the generic param
const project: EthereumProject = {
specVersion: "1.0.0",
version: "0.0.1",
name: "flare-subql-starter",
description:
"This project can be use as a starting point for developing your new Flare SubQuery project",
runner: {
node: {
name: "@subql/node-ethereum",
version: ">=3.0.0",
},
query: {
name: "@subql/query",
version: "*",
},
},
schema: {
file: "./schema.graphql",
},
network: {
/**
* chainId is the EVM Chain ID, for Flare this is 14
* https://chainlist.org/chain/14
*/
chainId: "14",
/**
* These endpoint(s) should be non-pruned archive nodes
* Public nodes may be rate limited, which can affect indexing speed
* When developing your project we suggest getting a private API key
# We suggest providing an array of endpoints for increased speed and reliability
*/
endpoint: ["https://flare-api.flare.network/ext/C/rpc"],
},
dataSources: [
{
kind: EthereumDatasourceKind.Runtime,
// This is the block that the contract was deployed on https://arbiscan.io/tx/0x8ebe1945f039f865af8b3079df3819534340ee41a5e6b8bfefb9c36a857778c9
startBlock: 2591,
options: {
// Must be a key of assets
abi: "priceSubmitter",
// This is the contract address for wrapped BTC https://arbiscan.io/token/0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f
address: "0x1000000000000000000000000000000000000003",
},
assets: new Map([["priceSubmitter", { file: "./priceSubmitter.abi.json" }]]),
mapping: {
file: "./dist/index.js",
handlers: [
{
kind: EthereumHandlerKind.Call,
handler: "handleTransaction",
filter: {
/**
* The function can either be the function fragment or signature
* function: '0x095ea7b3'
* function: '0x7ff36ab500000000000000000000000000000000000000000000000000000000'
*/
function: "submitHash(uint256 _epochId, bytes32 _hash)",
},
},
{
kind: EthereumHandlerKind.Event,
handler: "handleLog",
filter: {
/**
* Follows standard log filters https://docs.ethers.io/v5/concepts/events/
* address: "0x60781C2586D68229fde47564546784ab3fACA982"
*/
topics: [
"HashSubmitted(address indexed submitter, uint256 indexed epochId, bytes32 hash, uint256 timestamp)",
],
},
},
],
},
},
],
repository: "https://github.com/subquery/ethereum-subql-starter",
};

// Must set default to the project instance
export default project;
```

Below is a standard example of the legacy YAML version (`project.yaml`).
Expand All @@ -22,7 +110,7 @@ name: flare-subql-starter
version: 0.0.1
runner:
node:
name: "@subql/node-flare"
name: "@subql/node-ethereum"
version: "*"
query:
name: "@subql/query"
Expand All @@ -46,7 +134,7 @@ network:
dictionary: "https://api.subquery.network/sq/subquery/flare-dictionary"

dataSources:
- kind: flare/Runtime
- kind: ethereum/Runtime
startBlock: 2300000
options:
# Must be a key of assets
Expand All @@ -59,16 +147,16 @@ dataSources:
file: "./dist/index.js"
handlers:
# - handler: handleBlock
# kind: flare/BlockHander
# kind: ethereum/BlockHander
- handler: handleTransaction
kind: flare/TransactionHandler
kind: ethereum/TransactionHandler
filter:
## The function can either be the function fragment or signature
# function: '0x095ea7b3'
# function: '0x7ff36ab500000000000000000000000000000000000000000000000000000000'
function: submitHash(uint256 _epochId, bytes32 _hash)
- handler: handleLog
kind: flare/LogHandler
kind: ethereum/LogHandler
filter:
topics:
## Follows standard log filters https://docs.ethers.io/v5/concepts/events/
Expand Down Expand Up @@ -159,7 +247,7 @@ Defines the data that will be filtered and extracted and the location of the map

| Field | Type | Description |
| -------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **kind** | string | [flare/Runtime](#data-sources-and-mapping) |
| **kind** | string | [ethereum/Runtime](#data-sources-and-mapping) |
| **startBlock** | Integer | This changes your indexing start block for this datasource, set this as high as possible to skip initial blocks with no relevant data |
| **endBlock** | Integer | This sets a end block for processing on the datasource. After this block is processed, this datasource will no longer index your data. <br><br>Useful when your contracts change at a certain block height, or when you want to insert data at genesis. For example, setting both the `startBlock` and `endBlock` to 320, will mean this datasource only operates on block 320 |
| **mapping** | Mapping Spec | |
Expand All @@ -178,7 +266,7 @@ In this section, we will talk about the default Flare runtime and its mapping. H
{
dataSources: [
{
kind: FlareDatasourceKind.Runtime, // Indicates that this is default runtime
kind: EthereumDatasourceKind.Runtime, // Indicates that this is default runtime
startBlock: 1, // This changes your indexing start block, set this higher to skip initial blocks with less data
options: {
// Must be a Record of assets
Expand Down Expand Up @@ -206,9 +294,9 @@ The following table explains filters supported by different handlers.

| Handler | Supported filter |
| ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| [flare/BlockHandler](../mapping/flare.md#block-handler) | `modulo`, `timestamp` |
| [flare/TransactionHandler](../mapping/flare.md#transaction-handler) | `function` filters (either be the function fragment or signature), `from` (address), `to` (address) |
| [flare/LogHandler](../mapping/flare.md#log-handler) | `topics` filters, and `address` |
| [ethereum/BlockHandler](../mapping/flare.md#block-handler) | `modulo`, `timestamp` |
| [ethereum/TransactionHandler](../mapping/flare.md#transaction-handler) | `function` filters (either be the function fragment or signature), `from` (address), `to` (address) |
| [ethereum/LogHandler](../mapping/flare.md#log-handler) | `topics` filters, and `address` |

Default runtime mapping filters are an extremely useful feature to decide what block, event, or extrinsic will trigger a mapping handler.

Expand Down
28 changes: 11 additions & 17 deletions docs/indexer/build/mapping/flare.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ You can use block handlers to capture information each time a new block is attac
**Using block handlers slows your project down as they can be executed with each and every block - only use if you need to.**

```ts
import { FlareBlock } from "@subql/types-flare";
import { EthereumBlock } from "@subql/types-ethereum";

export async function handleBlock(block: FlareBlock): Promise<void> {
export async function handleBlock(block: EthereumBlock): Promise<void> {
// Create a new BlockEntity with the block hash as it's ID
const record = new BlockEntity(block.blockHash);
record.height = BigInt(block.blockNumber);
Expand All @@ -30,7 +30,8 @@ export async function handleBlock(block: FlareBlock): Promise<void> {
You can use transaction handlers to capture information about each of the transactions in a block. To achieve this, a defined TransactionHandler will be called once for every transaction. You should use [Mapping Filters](../manifest/flare.md#mapping-handlers-and-filters) in your manifest to filter transactions to reduce the time it takes to index data and improve mapping performance.

```ts
import { FlareTransaction } from "@subql/types-flare";
import { SubmitHash } from "../types";
import { SubmitHashTransaction } from "../types/abi-interfaces/Erc20Abi";

// Setup types from ABI
type SubmitHashCallArgs = [BigNumber, string] & {
Expand All @@ -39,7 +40,7 @@ type SubmitHashCallArgs = [BigNumber, string] & {
};

export async function handleTransaction(
transaction: FlareTransaction<SubmitHashCallArgs>,
transaction: SubmitHashTransaction,
): Promise<void> {
const approval = SubmitHash.create({
id: transaction.hash,
Expand All @@ -57,18 +58,11 @@ export async function handleTransaction(
You can use log handlers to capture information when certain logs are included on transactions. During the processing, the log handler will receive a log as an argument with the log's typed inputs and outputs. Any type of event will trigger the mapping, allowing activity with the data source to be captured. You should use [Mapping Filters](../manifest/flare.md#mapping-handlers-and-filters) in your manifest to filter events to reduce the time it takes to index data and improve mapping performance.

```ts
import { FlareLog } from "@subql/types-flare";

// Setup types from ABI
type HashSubmittedEventArgs = [string, BigNumber, string, BigNumber] & {
submitter: string;
epochId: BigNumber;
hash: string;
timestamp: BigNumber;
};
import { HashSubmittedEvent } from "../types";
import { SubmitHashEvent } from "../types/abi-interfaces/Erc20Abi";

export async function handleLog(
log: FlareLog<HashSubmittedEventArgs>,
log: SubmitHashEvent
): Promise<void> {
const transaction = HashSubmittedEvent.create({
id: log.transactionHash,
Expand Down Expand Up @@ -108,7 +102,7 @@ SubQuery is deterministic by design, that means that each SubQuery project is gu

```yml
subquery-node:
image: onfinality/subql-node-flare:latest
image: onfinality/subql-node-ethereum:latest
...
command:
- -f=/app
Expand All @@ -120,10 +114,10 @@ subquery-node:
When run in `unsafe` mode, you can import any custom libraries into your project and make external API calls using tools like node-fetch. A simple example is given below:

```ts
import { FlareTransaction } from "@subql/types-flare";
import { EthereumTransaction } from "@subql/types-ethereum";
import fetch from "node-fetch";

export async function handleTransaction(tx: FlareTransaction): Promise<void> {
export async function handleTransaction(tx: EthereumTransaction): Promise<void> {
const httpData = await fetch("https://api.github.com/users/github");
logger.info(`httpData: ${JSON.stringify(httpData.body)}`);
// Do something with this data
Expand Down

0 comments on commit ff1c5ff

Please sign in to comment.