Indexer API Documentation

Complete REST API reference for querying QELT blockchain data. Access blocks, transactions, tokens, NFTs, and smart contracts with simple HTTP requests.

Production Ready
v1.0.0
https://mnindexer.qelt.ai
Base URL
770
Chain ID
120
Req/min
5s
Block Interval

Overview

The QELT Mainnet Indexer is a high-performance blockchain indexing service that provides fast, reliable access to QELT blockchain data through a RESTful API. It continuously syncs with the blockchain, indexes transactions, blocks, tokens, NFTs, and smart contracts, making them instantly queryable.

Real-time Indexing

5-second block sync for up-to-date data

Comprehensive API

Blocks, txs, tokens, NFTs, contracts

Contract Verification

Multi-file contract verification

High Availability

Multiple RPC failover support

CORS Enabled

Browser-based dApp support

Prometheus Metrics

Real-time monitoring

Getting Started

Start querying blockchain data in seconds with simple HTTP requests. No authentication required.

Quick Start Example

// Fetch latest block
const response = await fetch('https://mnindexer.qelt.ai/v1/blocks/latest');
const block = await response.json();
console.log('Latest block:', block.number);

// Get transaction by hash
const tx = await fetch('https://mnindexer.qelt.ai/v1/transactions/0xABC...');
const transaction = await tx.json();
console.log('Transaction:', transaction);

API Versioning

The API supports multiple versioning schemes for backward compatibility:

/v1/blocks/latest (recommended)
/blocks/latest (legacy)
/api/v2/contracts/verify (enhanced)

Blocks API

GET/v1/blocks/latest

Get the most recent block with all transactions.

{
  "number": 1234567,
  "hash": "0x...",
  "parentHash": "0x...",
  "timestamp": 1705223340,
  "miner": "0x...",
  "gasUsed": "21000",
  "gasLimit": "50000000",
  "transactions": [...]
}
GET/v1/blocks/:blockId

Get block by number or hash.

Parameters:blockId- Block number or block hash (0x...)
GET /v1/blocks/1234567
GET /v1/blocks/0x74b6359f58b54d1ce166406bdd831a39727762217fae2ac742a1698f1bcb0684
GET/v1/blocks

Get list of latest blocks with pagination.

Query:limit(optional, default: 10)
Query:offset(optional, default: 0)
GET /v1/blocks?limit=20&offset=0

Transactions API

GET/v1/transactions/:hash

Get transaction by hash.

{
  "hash": "0x...",
  "blockNumber": 1234567,
  "from": "0x...",
  "to": "0x...",
  "value": "1000000000000000000",
  "gasPrice": "0",
  "gasUsed": "21000",
  "status": 1,
  "timestamp": 1705223340
}
GET/v1/transactions/:hash/receipt

Get transaction receipt with logs and status.

{
  "transactionHash": "0x...",
  "blockNumber": 1234567,
  "status": 1,
  "gasUsed": "65000",
  "logs": [...]
}
GET/v1/transactions/count

Get total transactions count on chain.

{
  "totalTransactions": 1234567,
  "latestBlock": 1234567,
  "timestamp": "2026-01-16T13:00:00.000Z"
}

Address API

GET/v1/address/:address/transactions

Get all transactions for an address.

Query:limit(optional, default: 10)
Query:offset(optional, default: 0)
GET /v1/address/0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb/transactions?limit=50
GET/v1/address/:address/tokens

Get ERC20 token balances for address.

[
  {
    "contractAddress": "0x...",
    "symbol": "USDT",
    "name": "Tether USD",
    "balance": "1000500000",
    "balanceFormatted": "1000.5",
    "decimals": 6,
    "type": "ERC20"
  }
]
GET/v1/account/:address/balances

Get all balances (native + tokens) for address.

{
  "native": "1234.56",
  "tokens": [
    {
      "contractAddress": "0x...",
      "symbol": "USDT",
      "name": "Tether USD",
      "balance": "1000.5",
      "decimals": 6,
      "type": "ERC20"
    }
  ],
  "dataSource": "database_optimized"
}

Contract Verification

QELT provides production-ready smart contract verification that enables source code transparency, ABI access, and trust for deployed contracts. Achieve 95% Etherscan parity with our CLI tool and Hardhat plugin.

Latest Versions: v1.0.12 (Hardhat) • v1.1.0 (CLI) ✅

Enterprise-grade contract verification with automatic viaIR detection, 10-minute timeout for large compilations, multi-file support (75+ source files), immutable variable normalization, comprehensive debug logging, and enhanced error reporting with proper exit codes.

Supports 500+ Solidity compiler versions, constructor arguments, library linking, and automatic EVM version detection. Production-ready and battle-tested.

Install: npm install --save-dev @qelt/hardhat-verify@latest

Timeout Configuration (10-Minute Safe Buffer)

Both verification tools now have 10-minute (600s) timeout to safely handle large contracts, viaIR compilation (slower but optimizes through IR), and multi-file projects up to 28+ source files.

CLI Tool (qelt-verify)
600s

HTTP timeout (10 minutes)

v1.1.0 (was 300s)
Hardhat Plugin
600s

HTTP timeout (10 minutes)

v1.0.12 (was 120s)
Plugin Timeout600 secondsPer verification request (v1.0.12)
Nginx Timeout300 secondsServer allows 5min compilation
Poll Interval3 secondsStatus check frequency

EVM Version Compatibility Guide

The plugin automatically detects the correct EVM version based on your Solidity compiler. You can also manually override using the --evm-version flag.

londonSolidity 0.8.6 - 0.8.17
parisSolidity 0.8.18 - 0.8.19
shanghaiSolidity 0.8.20 - 0.8.23
cancunSolidity 0.8.24+
berlinSolidity 0.8.5 - 0.8.6
istanbulSolidity 0.5.14 - 0.8.4

CLI Tool

Standalone verification for any workflow

npm install -g qelt-verify@latest
✅ v1.1.0 • Debug logging • Proper exit codes

Hardhat Plugin

Drop-in Hardhat integration

@qelt/hardhat-verify
v1.0.12 • 10min timeout • All bugs fixed

Async Queue

No timeouts, 300-500 verifications/hour

Real-time status tracking

Key Features

Multi-file contract support (75+ files)
500+ Solidity compiler versions
Constructor argument handling
Library linking support
Auto-detection from artifacts
viaIR compilation support
SHA256 compiler validation
Build-info scanning with fallback
Immutable variable normalization
Full commit hash version support

CLI Tool - qelt-verify

Standalone command-line tool for verifying smart contracts on QELT blockchain. Works with any project setup including Hardhat, Foundry, Truffle, and Remix.

Installation

npm install -g qelt-verify

Initialize Configuration

# Initialize with network settings
qelt-verify init

# Creates ~/.qelt-verify/config.json with:
# - Mainnet: https://mnindexer.qelt.ai (Chain ID: 770)
# - Testnet: https://tnindexer.qelt.ai (Chain ID: 771)

Verify a Contract

qelt-verify verify \
  0x1234567890123456789012345678901234567890 \
  ./MyContract.sol \
  --contract-name MyContract \
  --compiler-version 0.8.20 \
  --optimize \
  --optimizer-runs 200 \
  --network mainnet \
  --watch

With Constructor Arguments

# Example: Token(string name, string symbol, uint256 supply)
qelt-verify verify 0x123... ./Token.sol \
  --contract-name Token \
  --compiler-version 0.8.20 \
  --constructor-args 0x000000000000000000000000000000000000000000...
CommandDescription
initInitialize configuration
verifyVerify a contract
statusCheck verification status
queueView queue statistics
historyView verification history
configManage network configurations

Hardhat Plugin

Drop-in Hardhat plugin for seamless contract verification. Compatible with existing Hardhat workflows and auto-detects settings from your project artifacts.

Installation

npm install --save-dev @qelt/hardhat-verify@latest
v1.0.12 recommended: Enterprise-grade verification with 10-minute timeout, automatic viaIR detection, and comprehensive debug logging for production deployments.

Configuration (hardhat.config.ts)

import "@qelt/hardhat-verify";

const config: HardhatUserConfig = {
  solidity: {
    version: "0.8.17",
    settings: {
      optimizer: {
        enabled: true,
        runs: 200
      },
      viaIR: true  // ← Fully supported in v1.0.3+
    }
  },
  networks: {
    qelt: {
      url: "https://mainnet.qelt.ai",
      chainId: 770,
      accounts: [process.env.PRIVATE_KEY!]
    }
  },
  qeltVerify: {
    networks: {
      qelt: {
        apiUrl: "https://mnindexer.qelt.ai",
        chainId: 770,
        explorerUrl: "https://qeltscan.ai"
      }
    }
  }
};
✅ viaIR Auto-Detection: Automatically extracts viaIR setting from Hardhat build artifacts. No manual configuration needed!

Usage Examples

# Simple verification (auto-detects viaIR and all settings)
npx hardhat qelt:verify --network qelt-mainnet 0x123...

# With constructor arguments
npx hardhat qelt:verify --network qelt-mainnet 0x123... "My Token" "MTK" 1000000

# Specify contract (recommended for clarity)
npx hardhat qelt:verify --network qelt-mainnet \
  --contract contracts/Token.sol:Token \
  0x123...

# With libraries
npx hardhat qelt:verify --network qelt-mainnet \
  --libraries "SafeMath:0xABC...,Utils:0xDEF..." \
  0x123...

# Real example: QXMPDynamicRegistryV2 (28 files + viaIR + constructor args)
npx hardhat qelt:verify --network qelt \
  --contract contracts/QXMPDynamicRegistryV2.sol:QXMPDynamicRegistryV2 \
  0xd00cD3a986746cf134756464Cb9Eaf024DF110fB
✅ Production Ready: Fully supports multi-file contracts, viaIR compilation, constructor arguments, library linking, and automatic EVM version detection.
⚠️ Breaking Change (v1.0.1+): Command changed from verify to qelt:verify to prevent conflicts with other plugins

Verification API Endpoints

RESTful API for programmatic contract verification. All endpoints use /api/v1 prefix (v1.0.2+).

POST/api/v1/verification/submit

Submit contract for async verification (recommended for large contracts)

{
  "address": "0x123...",
  "sourceCode": "pragma solidity ^0.8.0; ...",
  "compilerVersion": "0.8.20",  // or "v0.8.20+commit.8a97fa7a"
  "contractName": "MyContract",
  "optimizationUsed": true,
  "runs": 200,
  "evmVersion": "cancun",
  "constructorArguments": "0x000...",
  "libraries": {
    "SafeMath": "0xABC..."
  }
}
Response:
{
  "success": true,
  "jobId": "550e8400-e29b-41d4-a716-446655440000",
  "statusUrl": "/api/v1/verification/status/550e8400-..."
}
GET/api/v1/verification/status/:jobId

Get verification job status and results

{
  "jobId": "550e8400-...",
  "address": "0x123...",
  "status": "completed",  // pending | processing | completed | failed
  "progress": 100,
  "message": "Contract verified successfully",
  "createdAt": "2026-01-20T09:00:00.000Z",
  "completedAt": "2026-01-20T09:00:15.000Z",
  "result": {
    "success": true,
    "verified": true,  // ← CHECK THIS! (v1.0.5 fix)
    "abi": [...],
    "bytecode": "0x...",
    "compilationTimeMs": 1234
  }
}
💡 Important: Always check result.verified === true to confirm successful verification. A job can complete (status === 'completed') without verification if there's a bytecode mismatch.
POST/api/v1/verification/submit-multi

Submit multi-file contract for verification (for contracts with imports like OpenZeppelin)

{
  "address": "0x123...",
  "compilerVersion": "v0.8.17+commit.8df45f5f",  // Full format supported
  "contractName": "MyContract",
  "optimizationUsed": true,
  "runs": 200,
  "viaIR": true,
  "evmVersion": "london",
  "mainFile": "contracts/MyContract.sol",
  "sourceFiles": {
    "contracts/MyContract.sol": "pragma solidity...",
    "@openzeppelin/contracts/access/Ownable.sol": "// SPDX...",
    "@openzeppelin/contracts/utils/Context.sol": "// SPDX..."
  }
}
✅ Auto-Routing: v1.0.5 Hardhat plugin automatically routes to /submit-multi when multiple source files detected. Supports 75+ files. EVM version correctly detected (london for 0.8.17).
GET/api/v2/contracts/:address/verification

Get verification details for a verified contract

{
  "address": "0x123...",
  "verified": true,
  "contractName": "MyContract",
  "compilerVersion": "0.8.20",
  "sourceCode": "pragma solidity...",
  "abi": [...],
  "optimizationUsed": true,
  "runs": 200,
  "evmVersion": "cancun",
  "verifiedAt": "2026-01-20T09:00:00.000Z"
}
GET/api/v2/verification/compiler-versions

List all available Solidity compiler versions (500+ versions from 0.4.11 to latest)

GET/api/v2/verification/evm-versions

List supported EVM versions (cancun, shanghai, paris, london, berlin, etc.)

Network Configuration

NetworkIndexer APIChain IDRPC URL
Mainnethttps://mnindexer.qelt.ai770https://mainnet.qelt.ai
Testnethttps://tnindexer.qelt.ai771https://testnet.qelt.ai

Quick Start: Verify Your First Contract

1
Install CLI or Hardhat Plugin
npm install -g qelt-verify
2
Initialize (CLI only)
qelt-verify init
3
Verify your contract
qelt-verify verify 0x... ./Contract.sol --compiler-version 0.8.20 --optimize
4
View on Explorer
Your verified contract appears on QELT Explorer with source code and ABI

Contract Verification Rate Limits

Verification endpoints are rate limited to prevent abuse and ensure fair resource distribution.

10
Requests per hour
Per IP address
1 hour
Auto-unblock time
Rolling 60-minute window
Rate Limited Endpoints:
POST /api/v1/verification/submit
POST /api/v1/verification/submit-multi
NOT Rate Limited:
GET /api/v1/verification/status/:jobId(unlimited polling)
GET /api/v1/contracts/:address/verified
All other read endpoints
Rate Limit Headers:
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1737373200
Retry-After: 3600  (on 429 error)
HTTP 429 - Rate Limit Exceeded:
{
  "success": false,
  "error": "Too many requests",
  "message": "Rate limit exceeded.
             Max 10 requests per hour.",
  "retryAfter": 3600
}
HTTP 403 - IP Blocked:
{
  "success": false,
  "error": "IP address blocked",
  "message": "Rate limit exceeded",
  "blockedUntil":
    "2026-01-20T14:51:00.000Z"
}
Best Practices:
  • Check if verified first: Use GET /contracts/:address/verified before submitting
  • Use multi-submit for batches: Submit multiple contracts in one request to save rate limit quota
  • Poll status wisely: Status polling is unlimited, but use 3-5 second intervals
  • Handle 429 errors: Implement retry logic with exponential backoff using Retry-After header
  • Use the Hardhat plugin: Automatically handles rate limits and retries
Retry Logic Example:
async function verifyWithRetry(data, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(
      'https://mnindexer.qelt.ai/api/v1/verification/submit',
      {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
      }
    );
    
    if (response.status === 429) {
      const retryAfter = response.headers.get('Retry-After') || 60;
      console.log(`Rate limit hit. Waiting ${retryAfter}s...`);
      await new Promise(r => setTimeout(r, retryAfter * 1000));
      continue;
    }
    
    return await response.json();
  }
}

Rate Limiting

The indexer implements multi-tier rate limiting to ensure fair usage and service availability.

TierEndpointsRate LimitBurst
Health/health*120 req/min20
Standard API/v1/*120 req/min20
Heavy QueriesSee docs60 req/min10
GeneralOther paths30 req/min5

Rate Limit Response

When rate limit is exceeded, the API returns HTTP 503 with the following response:

HTTP/1.1 503 Service Unavailable

{
  "error": "Rate limit exceeded"
}

Security & CORS

HTTPS/SSL

  • SSL certificate from Let's Encrypt
  • TLS 1.2 and 1.3 only
  • HSTS enabled (1 year)

CORS Configuration

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods:
GET, POST, OPTIONS
Access-Control-Max-Age: 1728000

Example CORS Request

fetch('https://mnindexer.qelt.ai/v1/blocks/latest', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
  }
})
.then(response => response.json())
.then(data => console.log(data));

Code Examples

TypeScript API Client

class QELTIndexerClient {
  private baseURL = 'https://mnindexer.qelt.ai';

  async getLatestBlock() {
    const response = await fetch(`${this.baseURL}/v1/blocks/latest`);
    return await response.json();
  }

  async getTransaction(hash: string) {
    const response = await fetch(`${this.baseURL}/v1/transactions/${hash}`);
    return await response.json();
  }

  async getAddressTransactions(address: string, limit = 10) {
    const response = await fetch(
      `${this.baseURL}/v1/address/${address}/transactions?limit=${limit}`
    );
    return await response.json();
  }
}

// Usage
const client = new QELTIndexerClient();
const latestBlock = await client.getLatestBlock();
console.log('Latest block:', latestBlock.number);

Python Example

import requests

class QELTIndexer:
    def __init__(self):
        self.base_url = 'https://mnindexer.qelt.ai'
    
    def get_latest_block(self):
        response = requests.get(f'{self.base_url}/v1/blocks/latest')
        return response.json()
    
    def get_transaction(self, tx_hash):
        response = requests.get(f'{self.base_url}/v1/transactions/{tx_hash}')
        return response.json()

# Usage
indexer = QELTIndexer()
block = indexer.get_latest_block()
print(f"Latest block: {block['number']}")

Best Practices

Use Pagination

Always use limit and offset parameters for list endpoints to avoid overwhelming responses.

// Good
GET /v1/blocks?limit=20&offset=0

Implement Caching

Cache responses that don't change frequently (e.g., historical blocks, token info).

const cache = new Map();
const ttl = 300000; // 5 minutes

async function getCachedData(key, fetchFn) {
  const cached = cache.get(key);
  if (cached && Date.now() - cached.timestamp < ttl) {
    return cached.data;
  }
  const data = await fetchFn();
  cache.set(key, { data, timestamp: Date.now() });
  return data;
}

Handle Rate Limits

Implement exponential backoff when rate limits are hit.

async function fetchWithRetry(url, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(url);
      if (response.ok) return await response.json();
      
      if (response.status === 503 && i < maxRetries - 1) {
        await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));
        continue;
      }
      throw new Error(`HTTP ${response.status}`);
    } catch (error) {
      if (i === maxRetries - 1) throw error;
    }
  }
}

Monitor Health

Regularly check indexer health to ensure data is up-to-date.

const health = await fetch('https://mnindexer.qelt.ai/v1/health/ready');
const status = await health.json();

if (status.lag > 1000) {
  console.warn('Indexer is behind:', status.lag, 'blocks');
}

Next Steps

Explore the blockchain documentation and whitepaper for complete technical specifications.