{"id":31924985,"url":"https://github.com/chaindexing/chaindexing-ts","last_synced_at":"2025-10-14T00:26:15.005Z","repository":{"id":186806287,"uuid":"675151398","full_name":"chaindexing/chaindexing-ts","owner":"chaindexing","description":"Index any EVM chain and query in SQL","archived":false,"fork":false,"pushed_at":"2025-07-23T20:47:10.000Z","size":197,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-07-23T23:24:56.686Z","etag":null,"topics":["blockchain","blockchain-indexer","blockchain-indexing","data-collection","developer-tools","indexing-engine","postgresql","solidity","sql","token-bridge","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chaindexing.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-08-06T00:41:58.000Z","updated_at":"2025-07-23T20:47:14.000Z","dependencies_parsed_at":"2023-08-07T20:38:42.342Z","dependency_job_id":"30bd7582-846e-4da8-b52c-d73c3a28dbe1","html_url":"https://github.com/chaindexing/chaindexing-ts","commit_stats":null,"previous_names":["jurshsmith/chaindexing-ts","chaindexing/chaindexing-ts"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/chaindexing/chaindexing-ts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaindexing%2Fchaindexing-ts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaindexing%2Fchaindexing-ts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaindexing%2Fchaindexing-ts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaindexing%2Fchaindexing-ts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chaindexing","download_url":"https://codeload.github.com/chaindexing/chaindexing-ts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chaindexing%2Fchaindexing-ts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279017364,"owners_count":26086052,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-13T02:00:06.723Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blockchain","blockchain-indexer","blockchain-indexing","data-collection","developer-tools","indexing-engine","postgresql","solidity","sql","token-bridge","typescript"],"created_at":"2025-10-14T00:26:08.272Z","updated_at":"2025-10-14T00:26:14.999Z","avatar_url":"https://github.com/chaindexing.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Chaindexing TypeScript\n\nIndex any EVM chain and query in SQL - TypeScript implementation based on the Rust version.\n\n## Features\n\n- 🌐 **Multi-chain support** - Index multiple EVM chains simultaneously\n- ⚡ **Real-time indexing** - Process events as they happen\n- 🗄️ **SQL queries** - Query indexed data using standard SQL\n- 🔄 **State management** - Track contract states, chain states, and multi-chain states\n- 🎯 **Event handlers** - Pure handlers for deterministic indexing and side-effect handlers for\n  notifications\n- 🏗️ **Type-safe** - Full TypeScript support with comprehensive type definitions\n- 🚀 **Production-ready** - Based on battle-tested Rust implementation\n- 🔧 **Configurable** - Extensive configuration options for performance tuning\n\n## Quick Start\n\n### Installation\n\n```bash\nnpm install @chaindexing/chaindexing\nnpm install @chaindexing/postgres  # For PostgreSQL support\n```\n\n### Basic Example\n\n```typescript\nimport {\n  indexStates,\n  Chain,\n  createContract,\n  PureHandler,\n  PureHandlerContext,\n  BaseContractState,\n  createFilters,\n  createUpdates,\n} from '@chaindexing/chaindexing';\nimport { Config } from '@chaindexing/config';\nimport { PostgresRepo } from '@chaindexing/postgres';\n\n// Define your state\nclass Nft extends BaseContractState {\n  constructor(\n    public tokenId: number,\n    public ownerAddress: string\n  ) {\n    super();\n  }\n\n  tableName(): string {\n    return 'nfts';\n  }\n}\n\n// Create event handler\nclass TransferHandler implements PureHandler {\n  abi(): string {\n    return 'event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)';\n  }\n\n  async handleEvent(context: PureHandlerContext): Promise\u003cvoid\u003e {\n    const eventParams = context.getEventParams();\n\n    const from = eventParams.getAddressString('from');\n    const to = eventParams.getAddressString('to');\n    const tokenId = eventParams.getU32('tokenId');\n\n    if (from === '0x0000000000000000000000000000000000000000') {\n      // Mint: create new NFT\n      const newNft = new Nft(tokenId, to);\n      await newNft.create(context);\n    } else {\n      // Transfer: update existing NFT\n      const existingNft = new Nft(tokenId, from);\n      const updates = createUpdates('owner_address', to);\n      await existingNft.update(updates, context);\n    }\n  }\n}\n\n// State migrations\nclass NftMigrations {\n  migrations(): string[] {\n    return [\n      `CREATE TABLE IF NOT EXISTS nfts (\n        token_id INTEGER NOT NULL,\n        owner_address TEXT NOT NULL\n      )`,\n    ];\n  }\n}\n\n// Setup and start\nasync function main() {\n  const repo = new PostgresRepo('postgresql://localhost:5432/chaindexing');\n\n  const config = new Config(repo)\n    .addChain(Chain.Mainnet, 'https://eth-mainnet.g.alchemy.com/v2/your-api-key')\n    .addContract(\n      createContract('ERC721Token')\n        .addAddress('0x...', Chain.Mainnet, 18000000)\n        .addEventHandler(new TransferHandler())\n        .addStateMigrations(new NftMigrations())\n        .build()\n    );\n\n  await indexStates(config);\n}\n\nmain().catch(console.error);\n```\n\n## Core Concepts\n\n### States\n\nChaindexing supports three types of states:\n\n1. **ContractState** - States derived from a single contract\n2. **ChainState** - States derived from multiple contracts within a chain\n3. **MultiChainState** - States derived from contracts across multiple chains\n\n```typescript\nimport { BaseContractState } from '@chaindexing/chaindexing';\n\nclass MyContractState extends BaseContractState {\n  constructor(\n    public id: number,\n    public value: string\n  ) {\n    super();\n  }\n\n  tableName(): string {\n    return 'my_states';\n  }\n}\n```\n\n### Event Handlers\n\n#### Pure Handlers\n\nDeterministic handlers for indexing states:\n\n```typescript\nclass MyPureHandler implements PureHandler {\n  abi(): string {\n    return 'event MyEvent(uint256 indexed id, string value)';\n  }\n\n  async handleEvent(context: PureHandlerContext): Promise\u003cvoid\u003e {\n    const params = context.getEventParams();\n    const id = params.getU32('id');\n    const value = params.getString('value');\n\n    const state = new MyContractState(id, value);\n    await state.create(context);\n  }\n}\n```\n\n#### Side Effect Handlers\n\nNon-deterministic handlers for notifications, bridging, etc:\n\n```typescript\nclass MySideEffectHandler implements SideEffectHandler\u003cAppState\u003e {\n  abi(): string {\n    return 'event MyEvent(uint256 indexed id, string value)';\n  }\n\n  async handleEvent(context: SideEffectHandlerContext\u003cAppState\u003e): Promise\u003cvoid\u003e {\n    const params = context.getEventParams();\n    const sharedState = await context.getSharedState();\n\n    // Send notification, update external system, etc.\n    await sendNotification(params.getString('value'));\n\n    // Update shared state\n    sharedState.notificationCount++;\n  }\n}\n```\n\n### Contract Builder\n\nCreate contracts with addresses, handlers, and migrations:\n\n```typescript\nconst contract = createContract\u003cSharedState\u003e('MyContract')\n  .addAddress('0x...', Chain.Mainnet, 18000000)\n  .addAddress('0x...', Chain.Polygon, 25000000)\n  .addEventHandler(new MyPureHandler())\n  .addSideEffectHandler(new MySideEffectHandler())\n  .addStateMigrations(new MyMigrations())\n  .build();\n```\n\n### Configuration\n\n```typescript\nconst config = new Config(repo)\n  .addChain(Chain.Mainnet, rpcUrl)\n  .addContract(contract)\n  .withBlocksPerBatch(450) // Blocks per ingestion batch\n  .withHandlerRateMs(4000) // Handler execution interval\n  .withIngestionRateMs(20000) // Ingestion interval\n  .withMinConfirmationCount(40) // Confirmations before processing\n  .withChainConcurrency(4) // Concurrent chain processing\n  .withInitialState(initialState) // Shared state for side effects\n  .reset(1); // Reset indexing (optional)\n```\n\n## Architecture\n\nThe TypeScript implementation mirrors the Rust version's architecture:\n\n```\n┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐\n│   Config        │    │   Contracts     │    │   Chains        │\n│                 │    │                 │    │                 │\n│ - Repo          │    │ - Handlers      │    │ - RPC URLs      │\n│ - Chains        │    │ - Migrations    │    │ - Chain IDs     │\n│ - Contracts     │    │ - Addresses     │    │                 │\n└─────────────────┘    └─────────────────┘    └─────────────────┘\n         │                       │                       │\n         └───────────────────────┼───────────────────────┘\n                                 │\n                    ┌─────────────────┐\n                    │  Orchestrator   │\n                    │                 │\n                    │ - Event Ingestion│\n                    │ - Event Handling │\n                    │ - State Management│\n                    └─────────────────┘\n                                 │\n                    ┌─────────────────┐\n                    │   Repository    │\n                    │                 │\n                    │ - PostgreSQL    │\n                    │ - Migrations    │\n                    │ - Transactions  │\n                    └─────────────────┘\n```\n\n## Database Support\n\nCurrently supports PostgreSQL with Drizzle ORM:\n\n```typescript\nimport { PostgresRepo } from '@chaindexing/postgres';\n\nconst repo = new PostgresRepo('postgresql://user:pass@localhost:5432/db');\n```\n\n## Performance Tuning\n\nAdjust these configuration parameters based on your needs:\n\n- `blocksPerBatch`: Higher values = faster historical sync, higher RPC usage\n- `handlerRateMs`: Lower values = faster processing, higher CPU usage\n- `ingestionRateMs`: Lower values = more real-time, higher RPC usage\n- `chainConcurrency`: Higher values = faster multi-chain, more resources\n\n## Error Handling\n\nThe library includes comprehensive error handling:\n\n```typescript\ntry {\n  await indexStates(config);\n} catch (error) {\n  if (error instanceof ConfigError) {\n    console.error('Configuration error:', error.message);\n  } else {\n    console.error('Indexing error:', error);\n  }\n}\n```\n\n## Contributing\n\nThis TypeScript implementation is based on the battle-tested Rust version. Contributions are\nwelcome!\n\n1. Fork the repository\n2. Create a feature branch\n3. Add tests for new functionality\n4. Submit a pull request\n\n## License\n\nMIT License - see LICENSE file for details.\n\n## Related Projects\n\n- [chaindexing-rs](https://github.com/chaindexing/chaindexing-rs) - The original Rust implementation\n- [chaindexing-examples](https://github.com/chaindexing/chaindexing-examples) - Working examples and\n  tutorials\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchaindexing%2Fchaindexing-ts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchaindexing%2Fchaindexing-ts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchaindexing%2Fchaindexing-ts/lists"}