Skip to main content
Glama

create_aptos_indexer

Create a new Aptos blockchain indexer project using example processors to process transactions or events.

Instructions

Creates a new Aptos indexer project based on the example processor.

Args:
    project_name: Name of the indexer project
    processor_type: Type of processor (transaction, event)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
project_nameYes
processor_typeNotransaction

Implementation Reference

  • The @mcp.tool()-decorated handler function that implements the core logic for creating a new Aptos indexer project. It clones a GitHub template, customizes package.json, generates processor TypeScript code based on transaction or event type, creates README and .env files, and sets up the project structure.
    @mcp.tool()
    async def create_aptos_indexer(project_name: str, processor_type: str = "transaction") -> str:
        """
        Creates a new Aptos indexer project based on the example processor.
        
        Args:
            project_name: Name of the indexer project
            processor_type: Type of processor (transaction, event)
        """
        project_name = project_name.strip().replace(" ", "-").lower()
        
        supported_types = ["transaction", "event"]
        if processor_type not in supported_types:
            return f"Unsupported processor type. Choose from: {', '.join(supported_types)}"
        
        try:
            # Create project directory
            project_dir = os.path.join(os.getcwd(), project_name)
            if os.path.exists(project_dir):
                return f"Directory {project_dir} already exists. Please choose a different name."
            
            os.makedirs(project_dir)
            
            # Clone the example repo to get the template
            temp_dir = os.path.join(tempfile.gettempdir(), "aptos-indexer-example")
            if os.path.exists(temp_dir):
                shutil.rmtree(temp_dir)
            
            clone_cmd = [
                "git", "clone", "https://github.com/aptos-labs/aptos-indexer-processor-example.git", 
                temp_dir, "--depth", "1"
            ]
            subprocess.run(clone_cmd, check=True, capture_output=True)
            
            # Copy relevant files from template
            shutil.copytree(os.path.join(temp_dir, "typescript"), project_dir, dirs_exist_ok=True)
            
            # Remove the git directory
            git_dir = os.path.join(project_dir, ".git")
            if os.path.exists(git_dir):
                shutil.rmtree(git_dir)
            
            # Customize the package.json
            package_json_path = os.path.join(project_dir, "package.json")
            with open(package_json_path, "r") as f:
                package_json = json.load(f)
            
            package_json["name"] = project_name
            package_json["description"] = f"Aptos indexer for {project_name}"
            
            with open(package_json_path, "w") as f:
                json.dump(package_json, f, indent=2)
            
            # Customize processor based on type
            processor_dir = os.path.join(project_dir, "src", "processors")
            os.makedirs(processor_dir, exist_ok=True)
            
            processor_code = ""
            if processor_type == "transaction":
                processor_code = generate_transaction_processor(project_name)
            elif processor_type == "event":
                processor_code = generate_event_processor(project_name)
            
            processor_file = os.path.join(processor_dir, f"{project_name}_processor.ts")
            with open(processor_file, "w") as f:
                f.write(processor_code)
            
            # Create README
            readme_content = f"""# {project_name} Aptos Indexer
    
    An Aptos indexer for processing {processor_type}s.
    
    ## Setup
    
    1. Install dependencies:
       ```
       npm install
       ```
    
    2. Configure connection:
       Edit the `.env` file to set your database and Aptos node URLs.
    
    3. Run the indexer:
       ```
       npm run start
       ```
    
    ## Architecture
    
    This indexer uses the Aptos Indexer Framework to process {processor_type}s from the Aptos blockchain.
    
    ## Development
    
    - `src/processors/{project_name}_processor.ts`: Contains the main processor logic
    - `src/models/`: Database models for storing indexed data
    """
    
            with open(os.path.join(project_dir, "README.md"), "w") as f:
                f.write(readme_content)
            
            # Create .env file
            env_content = """# Aptos Node URL
    APTOS_NODE_URL=https://fullnode.devnet.aptoslabs.com/v1
    
    # Database Configuration
    DB_HOST=localhost
    DB_PORT=5432
    DB_NAME=postgres
    DB_USER=postgres
    DB_PASS=postgres
    
    # Indexer Configuration
    STARTING_VERSION=0
    BATCH_SIZE=500
    """
            
            with open(os.path.join(project_dir, ".env"), "w") as f:
                f.write(env_content)
            
            return f"""
    Successfully created Aptos indexer project at {project_dir}!
    
    The project includes:
    - TypeScript boilerplate for an Aptos indexer
    - {processor_type.capitalize()} processor template
    - Database models and configurations
    - Environment setup
    
    Next steps:
    1. Navigate to the project directory: `cd {project_name}`
    2. Install dependencies: `npm install`
    3. Configure your database in .env
    4. Start developing your indexer!
    
    See the README.md file for more information.
    """
        
        except Exception as e:
            return f"Error creating indexer project: {str(e)}"
  • Helper function that generates TypeScript code for a transaction processor class used in the indexer project.
    def generate_transaction_processor(project_name: str) -> str:
        """Generate code for a transaction processor"""
        return f"""import {{
      InputModels,
      Models,
      OutputModels,
      ProcessingResult,
      Transaction,
      TransactionModel,
      TransactionProcessor,
      UserTransactionInput,
      parseTransaction,
    }} from "@aptos-labs/indexer-sdk";
    
    /**
     * {project_name.capitalize()} Transaction Processor
     * 
     * This processor handles transactions and extracts relevant information.
     */
    export class {project_name.capitalize()}TransactionProcessor extends TransactionProcessor {{
      constructor() {{
        super();
      }}
    
      /**
       * Process a batch of transactions
       */
      async process(
        transactionInputs: UserTransactionInput[],
      ): Promise<ProcessingResult> {{
        const processingResult = new ProcessingResult();
        console.log(`Processing ${{transactionInputs.length}} transactions`);
    
        for (const transactionInput of transactionInputs) {{
          const transaction = parseTransaction(transactionInput);
          
          // Process each transaction
          try {{
            await this.processTransaction(transaction, processingResult);
          }} catch (e) {{
            console.error(
              `Error processing transaction ${{transaction.version}}: ${{e}}`,
            );
          }}
        }}
    
        return processingResult;
      }}
    
      /**
       * Process a single transaction
       */
      async processTransaction(
        transaction: Transaction,
        processingResult: ProcessingResult,
      ): Promise<void> {{
        // Check if transaction is successful
        if (!transaction.success) {{
          return;
        }}
    
        // Extract basic transaction data
        const txModel = new TransactionModel();
        txModel.version = transaction.version;
        txModel.hash = transaction.hash;
        txModel.sender = transaction.sender;
        txModel.success = transaction.success;
        txModel.timestamp = new Date(Number(transaction.timestamp) / 1000);
        txModel.blockHeight = transaction.blockHeight;
        
        // Add to processing result
        processingResult.transactionModel = txModel;
    
        // Process specific entry functions
        if (transaction.payload?.type === "entry_function_payload") {{
          const entryFunctionFullStr = transaction.payload.function;
          
          // Example: Process a specific entry function
          if (entryFunctionFullStr === "0x1::coin::transfer") {{
            // Handle coin transfer function
            this.processCoinTransfer(transaction, processingResult);
          }}
          
          // TODO: Add more function handlers
        }}
      }}
    
      /**
       * Process a coin transfer transaction
       */
      private processCoinTransfer(
        transaction: Transaction,
        processingResult: ProcessingResult,
      ): void {{
        if (
          transaction.payload?.type !== "entry_function_payload" ||
          !transaction.payload.arguments
        ) {{
          return;
        }}
    
        try {{
          // Extract function arguments
          const [recipient, amount] = transaction.payload.arguments;
          
          // Create custom transaction model
          const transferModel = new Models.{project_name.capitalize()}TransferModel();
          transferModel.version = transaction.version;
          transferModel.sender = transaction.sender;
          transferModel.recipient = recipient as string;
          transferModel.amount = BigInt(amount as string);
          transferModel.timestamp = new Date(Number(transaction.timestamp) / 1000);
          
          // Add to processing result
          processingResult.models.push(transferModel);
          
          console.log(
            `Processed transfer: ${{transaction.sender}} -> ${{recipient}} (${{amount}})`,
          );
        }} catch (e) {{
          console.error(`Error processing coin transfer: ${{e}}`);
        }}
      }}
    }}
    
    // Register processor
    new {project_name.capitalize()}TransactionProcessor().start();
    """
  • Helper function that generates TypeScript code for an event processor class used in the indexer project.
    def generate_event_processor(project_name: str) -> str:
        """Generate code for an event processor"""
        return f"""import {{
      InputModels,
      Models,
      OutputModels,
      ProcessingResult,
      Event,
      EventProcessor,
      UserTransactionInput,
      parseEvent,
    }} from "@aptos-labs/indexer-sdk";
    
    /**
     * {project_name.capitalize()} Event Processor
     * 
     * This processor handles events and extracts relevant information.
     */
    export class {project_name.capitalize()}EventProcessor extends EventProcessor {{
      constructor() {{
        super();
      }}
    
      /**
       * Process a batch of events
       */
      async process(
        eventInputs: InputModels.Event[],
      ): Promise<ProcessingResult> {{
        const processingResult = new ProcessingResult();
        console.log(`Processing ${{eventInputs.length}} events`);
    
        for (const eventInput of eventInputs) {{
          const event = parseEvent(eventInput);
          
          // Process each event
          try {{
            await this.processEvent(event, processingResult);
          }} catch (e) {{
            console.error(
              `Error processing event ${{event.type}} (version: ${{event.version}}): ${{e}}`,
            );
          }}
        }}
    
        return processingResult;
      }}
    
      /**
       * Process a single event
       */
      async processEvent(
        event: Event,
        processingResult: ProcessingResult,
      ): Promise<void> {{
        // Create base event model
        const eventModel = new Models.{project_name.capitalize()}EventModel();
        eventModel.transactionVersion = event.version;
        eventModel.eventType = event.type;
        eventModel.data = event.data ? JSON.stringify(event.data) : null;
        eventModel.timestamp = new Date(Number(event.timestamp) / 1000);
        
        // Process specific event types
        if (event.type.includes("0x1::coin::DepositEvent")) {{
          await this.processDepositEvent(event, processingResult);
        }} else if (event.type.includes("0x1::coin::WithdrawEvent")) {{
          await this.processWithdrawEvent(event, processingResult);
        }}
        
        // Add base event to processing result 
        processingResult.models.push(eventModel);
      }}
    
      /**
       * Process a deposit event
       */
      private async processDepositEvent(
        event: Event,
        processingResult: ProcessingResult,
      ): Promise<void> {{
        if (!event.data) {{
          return;
        }}
    
        try {{
          // Extract event data
          const {{ amount }} = event.data;
          
          // Create deposit model
          const depositModel = new Models.{project_name.capitalize()}DepositModel();
          depositModel.transactionVersion = event.version;
          depositModel.address = event.accountAddress;
          depositModel.amount = BigInt(amount);
          depositModel.timestamp = new Date(Number(event.timestamp) / 1000);
          
          // Add to processing result
          processingResult.models.push(depositModel);
          
          console.log(
            `Processed deposit: ${{event.accountAddress}} (+${{amount}})`,
          );
        }} catch (e) {{
          console.error(`Error processing deposit event: ${{e}}`);
        }}
      }}
    
      /**
       * Process a withdraw event
       */
      private async processWithdrawEvent(
        event: Event,
        processingResult: ProcessingResult,
      ): Promise<void> {{
        if (!event.data) {{
          return;
        }}
    
        try {{
          // Extract event data
          const {{ amount }} = event.data;
          
          // Create withdraw model
          const withdrawModel = new Models.{project_name.capitalize()}WithdrawModel();
          withdrawModel.transactionVersion = event.version;
          withdrawModel.address = event.accountAddress;
          withdrawModel.amount = BigInt(amount);
          withdrawModel.timestamp = new Date(Number(event.timestamp) / 1000);
          
          // Add to processing result
          processingResult.models.push(withdrawModel);
          
          console.log(
            `Processed withdraw: ${{event.accountAddress}} (-${{amount}})`,
          );
        }} catch (e) {{
          console.error(`Error processing withdraw event: ${{e}}`);
        }}
      }}
    }}
    
    // Register processor
    new {project_name.capitalize()}EventProcessor().start();
    """
  • The @mcp.tool() decorator registers the create_aptos_indexer function as an MCP tool.
    @mcp.tool()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Tlazypanda/aptos-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server