Skip to content
This repository was archived by the owner on Apr 21, 2025. It is now read-only.
This repository was archived by the owner on Apr 21, 2025. It is now read-only.

Dynamically Add Contracts and ABI #131

@mufaddal-ik

Description

@mufaddal-ik

I have a use case where I want to add contracts from the database or via any queue system. Currently, I am creating a Contract Manager class and loading that way, but it does not seem optimal. Do you have any suggestions?
Note: logger is just a logger class and TokenABIs is just Ethereum 721 and 1155 transfer function.

import { createPublicClient, http } from 'viem';
import { sepolia } from 'viem/chains';
import { ERC1155_ABI, ERC721_ABI } from '../abis/TokenABIs';
import { logger } from '../utils/logger';

interface Contract {
  address: string;
  type: 'ERC721' | 'ERC1155';
  chainId: number;
  startBlock: number;
}

export class ContractManager {
  private contracts: Map<string, Contract> = new Map();
  private client: any;

  constructor(rpcUrl: string) {
    this.client = createPublicClient({
      chain: sepolia,
      transport: http(rpcUrl)
    });
  }

  async addContract(contract: Contract) {
    const key = `${contract.chainId}-${contract.address}`;
    this.contracts.set(key, contract);
    logger.info(`Added contract: ${key} (${contract.type})`);
    
    // Log contract details for Ponder indexing
    console.log(JSON.stringify({
      type: 'CONTRACT_ADDED',
      data: {
        address: contract.address,
        chainId: contract.chainId,
        type: contract.type,
        startBlock: contract.startBlock,
        abi: contract.type === 'ERC721' ? ERC721_ABI : ERC1155_ABI
      }
    }));
  }

  async removeContract(chainId: number, address: string) {
    const key = `${chainId}-${address}`;
    this.contracts.delete(key);
    logger.info(`Removed contract: ${key}`);
    
    // Log contract removal for Ponder indexing
    console.log(JSON.stringify({
      type: 'CONTRACT_REMOVED',
      data: {
        address,
        chainId
      }
    }));
  }

  getContracts(): Contract[] {
    return Array.from(this.contracts.values());
  }

  async validateContract(address: string, type: 'ERC721' | 'ERC1155'): Promise<boolean> {
    try {
      const abi = type === 'ERC721' ? ERC721_ABI : ERC1155_ABI;
      // Try to read a basic function to validate the contract
      await this.client.readContract({
        address: address as `0x${string}`,
        abi,
        functionName: type === 'ERC721' ? 'name' : 'uri',
        args: [0n]
      });
      return true;
    } catch (error) {
      logger.error(`Contract validation failed for ${address}: ${error}`);
      return false;
    }
  }
} 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions