subquery / subql

SubQuery is an Open, Flexible, Fast and Universal data indexing framework for web3. Our mission is to help developers create the decentralised products of the future.
https://subquery.network
GNU General Public License v3.0
19.06k stars 328 forks source link

Individually inject polkadot api and ethers api instead of single api in substrate frontier project #2556

Closed Niraj-Kamdar closed 3 days ago

Niraj-Kamdar commented 5 days ago

Prerequisites

Description

In Substrate Frontier projects, we need the ability to individually inject both the Polkadot API and the Ethers.js API instead of a single api object. This enhancement would allow developers to access both Substrate-specific and EVM-specific functionalities within the same mapping handlers, which is essential for indexing data on a Frontier-based chain that supports both Substrate modules and EVM contracts.

Details

These details can help to reproduce the environment where the issue is occurring:

Local Environment:

$ subql version
@subql/cli: 5.1.1

Query Version: 5.1.1

Indexer Version: 5.1.1

Network Details:

Steps to Reproduce

  1. Initialize a SubQuery Project: Create a new SubQuery project targeting a Frontier-based Substrate chain that supports EVM contracts.

  2. Attempt to Use Both APIs: In your mapping handlers (e.g., mappingHandlers.ts), try to use both the Polkadot.js API and the Ethers.js API:

    export async function handleBlock(block: SubstrateBlock): Promise<void> {
     // Attempt to use Substrate API
     const blockNumber = await api.rpc.chain.getHeader();
    
     // Attempt to use Ethers.js API
     const provider = api; // Assuming 'api' is an Ethers.js provider
     const balance = await provider.getBalance(someAddress);
    }
  3. Observe the Issue: You'll notice that the api object cannot be both a Polkadot.js API and an Ethers.js provider simultaneously. This limitation prevents access to both Substrate and EVM functionalities within the same handler.

Expected Behavior

We expect to have both APIs injected separately into the mapping handlers, such as:

This separation allows us to:

Example Usage:

export async function handleBlock(block: SubstrateBlock, { polkadotApi, ethersApi }): Promise<void> {
  // Use Polkadot.js API
  const blockNumber = await polkadotApi.rpc.chain.getHeader();

  // Use Ethers.js API
  const balance = await ethersApi.getBalance(someAddress);
}

Actual Behavior

Currently, only a single api object is injected into the mapping handlers, which is either:

This setup forces developers to choose between Substrate and EVM functionalities, which is not practical for Frontier-based chains that support both.

Any Other Information

References from Documentation:

Issue Summary:

In Frontier-based Substrate chains, both Substrate modules and EVM contracts are first-class citizens. Developers need access to both the Polkadot.js API and the Ethers.js API within the same mapping handlers to fully leverage the chain's capabilities.

Proposed Solution:

Benefits:

Thank you for considering this feature request. Implementing this enhancement will significantly improve the developer experience and capabilities when working with Frontier-based Substrate projects.

stwiname commented 3 days ago

Hi @Niraj-Kamdar

This is already possible. You can use the FrontierEthProvider which implements the ethers provider interface.

Example:

const provider = new FrontierEthProvider();
const erc20 = Erc20__factory.connect(contractAddress, provider);
const balance = await erc20.balanceOf(address);