{"_id":"@c-tech/c-indexer-consumer","_rev":"6-23f9c35cb1b77a9a40f084ef4f2492b3","name":"@c-tech/c-indexer-consumer","dist-tags":{"latest":"1.0.8"},"versions":{"1.0.4":{"name":"@c-tech/c-indexer-consumer","version":"1.0.4","keywords":["blockchain","ethereum","kafka","events","web3","indexer","etl","consumer","smart-contract"],"author":{"name":"c-tech"},"license":"MIT","_id":"@c-tech/c-indexer-consumer@1.0.4","maintainers":[{"name":"0x0642.xyz","email":"ductrungnguyen98@gmail.com"}],"dist":{"shasum":"3f749c48731ce9a2ce8910fb2bc1ed5c5019f260","tarball":"https://registry.npmjs.org/@c-tech/c-indexer-consumer/-/c-indexer-consumer-1.0.4.tgz","fileCount":9,"integrity":"sha512-c7iG5qRnosAa0CEcRcMprocppOVXi9SmmAJeUcL792ZQATmBoRhJDdRdiDzO4jJdt8Ju4yYHTo91PuH1T+8UGQ==","signatures":[{"sig":"MEUCIB01yGNIlPpA5gECIwTS3zt8m5Pqh7u/LG7PWZTL/yhAAiEAnp8x2ZqsuEvvzk294IkwOSc8KPrIYTB7bjmh4k9P3ig=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":25272},"main":"src/index.ts","type":"module","types":"src/index.ts","module":"src/index.ts","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./src/index.ts","import":"./src/index.ts"}},"gitHead":"545277181f3e34f01b4034a18ff77936d2fa8f56","_npmUser":{"name":"0x0642.xyz","email":"ductrungnguyen98@gmail.com"},"_npmVersion":"10.9.3","description":"A TypeScript library for consuming blockchain events through Kafka","directories":{},"_nodeVersion":"22.19.0","dependencies":{"ethers":"^6.15.0","kafkajs":"^2.2.4"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest"},"peerDependencies":{"typescript":"^5"},"_npmOperationalInternal":{"tmp":"tmp/c-indexer-consumer_1.0.4_1760586817292_0.023086138205991036","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"@c-tech/c-indexer-consumer","version":"1.0.5","keywords":["blockchain","ethereum","kafka","events","web3","indexer","etl","consumer","smart-contract"],"author":{"name":"c-tech"},"license":"MIT","_id":"@c-tech/c-indexer-consumer@1.0.5","maintainers":[{"name":"0x0642.xyz","email":"ductrungnguyen98@gmail.com"}],"dist":{"shasum":"ba4c8fdc2a0f3452f26889a1b710425a8a77b455","tarball":"https://registry.npmjs.org/@c-tech/c-indexer-consumer/-/c-indexer-consumer-1.0.5.tgz","fileCount":9,"integrity":"sha512-me6ezcQAuKrKiUL3oPdjkmMqaFk2Szvw0r26oEokwVwWoGDQLl1M2sHFvjNWx+O17lEFgZCZmnj91OR6yW6ALQ==","signatures":[{"sig":"MEQCIDfQZ4Lc3qpdCCAVwKrWCiuzsBsc7CBbTkVHVmOJ5OyUAiBZj12An6kUDfMhuo02MwGbltVBpJIRq3WYrQcDXrifGQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":25272},"main":"src/index.ts","type":"module","types":"src/index.ts","module":"src/index.ts","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./src/index.ts","import":"./src/index.ts"}},"gitHead":"441d6657698dd326088e529ea562d5236056ccd9","_npmUser":{"name":"0x0642.xyz","email":"ductrungnguyen98@gmail.com"},"_npmVersion":"10.9.3","description":"A TypeScript library for consuming blockchain events through Kafka","directories":{},"_nodeVersion":"22.19.0","dependencies":{"ethers":"^6.15.0","kafkajs":"^2.2.4"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest"},"peerDependencies":{"typescript":"^5"},"_npmOperationalInternal":{"tmp":"tmp/c-indexer-consumer_1.0.5_1760587304957_0.9880640784865351","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"@c-tech/c-indexer-consumer","version":"1.0.6","keywords":["blockchain","ethereum","kafka","events","web3","indexer","etl","consumer","smart-contract"],"author":{"name":"c-tech"},"license":"MIT","_id":"@c-tech/c-indexer-consumer@1.0.6","maintainers":[{"name":"0x0642.xyz","email":"ductrungnguyen98@gmail.com"},{"name":"nguyenvanvay1999","email":"nguyenvanvy1999@gmail.com"}],"homepage":"https://gitlab.com/c-tech/c-indexer-consumer-nodepkg#readme","bugs":{"url":"https://gitlab.com/c-tech/c-indexer-consumer-nodepkg/-/issues"},"dist":{"shasum":"388b27cb6d40b7d8e39b13d66fde55f17b032fa7","tarball":"https://registry.npmjs.org/@c-tech/c-indexer-consumer/-/c-indexer-consumer-1.0.6.tgz","fileCount":28,"integrity":"sha512-2GbZh5AcqGXs5zByfESUtQCnn/uIHhkgrx0h1R/6DzT/D/BPEsIt2vS9iGGI2JREc9kc2uIwqUXNlRGomrHLTQ==","signatures":[{"sig":"MEYCIQCvpLYqM+0HkHY+j5k0r1LGS/6CBTLq5AN4ktS3pKoKHAIhAJ98gcAnYHl+OeuThnYQEaWg8j+6SvrIAT6iae7Nub3p","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":42802},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"441d6657698dd326088e529ea562d5236056ccd9","scripts":{"build":"node scripts/build.js","clean":"rm -rf dist","prebuild":"npm run clean","build:watch":"tsc -p tsconfig.build.json --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"nguyenvanvay1999","email":"nguyenvanvy1999@gmail.com"},"repository":{"url":"git+https://gitlab.com/c-tech/c-indexer-consumer-nodepkg.git","type":"git"},"_npmVersion":"10.9.2","description":"A TypeScript library for consuming blockchain events through Kafka","directories":{},"_nodeVersion":"22.14.0","dependencies":{"ethers":"^6.15.0","kafkajs":"^2.2.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsc-alias":"^1.8.8","@types/bun":"latest","typescript":"^5.0.0"},"peerDependencies":{"typescript":"^5"},"_npmOperationalInternal":{"tmp":"tmp/c-indexer-consumer_1.0.6_1761017497488_0.5348552792158168","host":"s3://npm-registry-packages-npm-production"}},"1.0.7":{"name":"@c-tech/c-indexer-consumer","version":"1.0.7","keywords":["blockchain","ethereum","kafka","events","web3","indexer","etl","consumer","smart-contract"],"author":{"name":"c-tech"},"license":"MIT","_id":"@c-tech/c-indexer-consumer@1.0.7","maintainers":[{"name":"0x0642.xyz","email":"ductrungnguyen98@gmail.com"},{"name":"nguyenvanvay1999","email":"nguyenvanvy1999@gmail.com"}],"homepage":"https://gitlab.com/c-tech/c-indexer-consumer-nodepkg#readme","bugs":{"url":"https://gitlab.com/c-tech/c-indexer-consumer-nodepkg/-/issues"},"dist":{"shasum":"3b1d953499674c142a2bb20f8570852246b68db3","tarball":"https://registry.npmjs.org/@c-tech/c-indexer-consumer/-/c-indexer-consumer-1.0.7.tgz","fileCount":27,"integrity":"sha512-G59VZ0tDjrRoJE3nunmxNXbfaMhg4CXvoSLhPmFYkoVXh2JJYzgAF3d6XSvNa5o2Idym+1/nrArI8UgLeMY2xQ==","signatures":[{"sig":"MEYCIQDuUToe5SmFp9UbEMAYbHfXLwqsTLr9K1p1Bd4vGznUoQIhAJVMQAeU+8zQQeRM9fJEGgQCR1Iaf8dQxeOcVnGG59eg","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":49024},"main":"dist/index.js","types":"dist/index.d.ts","module":"dist/index.mjs","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"441d6657698dd326088e529ea562d5236056ccd9","scripts":{"build":"node scripts/build.js","clean":"rm -rf dist","prebuild":"npm run clean","build:watch":"tsc -p tsconfig.build.json --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"nguyenvanvay1999","email":"nguyenvanvy1999@gmail.com"},"repository":{"url":"git+https://gitlab.com/c-tech/c-indexer-consumer-nodepkg.git","type":"git"},"_npmVersion":"10.9.2","description":"A TypeScript library for consuming blockchain events through Kafka","directories":{},"_nodeVersion":"22.14.0","dependencies":{"ethers":"^6.15.0","kafkajs":"^2.2.4"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"tsc-alias":"^1.8.8","typescript":"^5.0.0"},"peerDependencies":{"typescript":"^5"},"_npmOperationalInternal":{"tmp":"tmp/c-indexer-consumer_1.0.7_1761017866490_0.5013687759995251","host":"s3://npm-registry-packages-npm-production"}},"1.0.8":{"name":"@c-tech/c-indexer-consumer","version":"1.0.8","description":"A TypeScript library for consuming blockchain events through Kafka","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","exports":{".":{"import":"./dist/index.mjs","require":"./dist/index.js","types":"./dist/index.d.ts"},"./package.json":"./package.json"},"keywords":["blockchain","ethereum","kafka","events","web3","indexer","etl","consumer","smart-contract"],"author":{"name":"c-tech"},"license":"MIT","scripts":{"build":"node scripts/build.js","build:watch":"tsc -p tsconfig.build.json --watch","prepublishOnly":"npm run build","clean":"rm -rf dist","prebuild":"npm run clean"},"devDependencies":{"tsc-alias":"^1.8.8","typescript":"^5.0.0"},"peerDependencies":{"typescript":"^5"},"dependencies":{"ethers":"^6.15.0","kafkajs":"^2.2.4"},"engines":{"node":">=18.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"repository":{"type":"git","url":"git+https://gitlab.com/c-tech/c-indexer-consumer-nodepkg.git"},"bugs":{"url":"https://gitlab.com/c-tech/c-indexer-consumer-nodepkg/-/issues"},"homepage":"https://gitlab.com/c-tech/c-indexer-consumer-nodepkg#readme","_id":"@c-tech/c-indexer-consumer@1.0.8","gitHead":"2f50ea41582b6a14d531a08040e9c85dd0680c40","_nodeVersion":"22.14.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-uV2zkXgchx71GxFQuMYEqucd59/knM6yBNgCNqAGTScxqPvwa1lGRp3bDnieCFXAeJFlTqIKgpt0MELv5bgotg==","shasum":"22e40516172c7e2e9e0f851b560ec82d2697fbd8","tarball":"https://registry.npmjs.org/@c-tech/c-indexer-consumer/-/c-indexer-consumer-1.0.8.tgz","fileCount":27,"unpackedSize":48293,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQC5XiPyH9Vu8+8NuYQRcODQtLQ/2L1K4onotyitg/TacQIgN4YhZClc+49fSMbZ+st5Q610jt/TZRTqwl0fefpbIXw="}]},"_npmUser":{"name":"nguyenvanvay1999","email":"nguyenvanvy1999@gmail.com"},"directories":{},"maintainers":[{"name":"0x0642.xyz","email":"ductrungnguyen98@gmail.com"},{"name":"nguyenvanvay1999","email":"nguyenvanvy1999@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/c-indexer-consumer_1.0.8_1761031401876_0.868800747447257"},"_hasShrinkwrap":false}},"time":{"created":"2025-10-16T03:53:37.231Z","modified":"2025-10-21T07:23:22.260Z","1.0.4":"2025-10-16T03:53:37.460Z","1.0.5":"2025-10-16T04:01:45.155Z","1.0.6":"2025-10-21T03:31:37.670Z","1.0.7":"2025-10-21T03:37:46.716Z","1.0.8":"2025-10-21T07:23:22.058Z"},"bugs":{"url":"https://gitlab.com/c-tech/c-indexer-consumer-nodepkg/-/issues"},"author":{"name":"c-tech"},"license":"MIT","homepage":"https://gitlab.com/c-tech/c-indexer-consumer-nodepkg#readme","keywords":["blockchain","ethereum","kafka","events","web3","indexer","etl","consumer","smart-contract"],"repository":{"type":"git","url":"git+https://gitlab.com/c-tech/c-indexer-consumer-nodepkg.git"},"description":"A TypeScript library for consuming blockchain events through Kafka","maintainers":[{"name":"0x0642.xyz","email":"ductrungnguyen98@gmail.com"},{"name":"nguyenvanvay1999","email":"nguyenvanvy1999@gmail.com"}],"readme":"# @c-tech/c-indexer-consumer\n\nA TypeScript library for consuming blockchain events through Kafka, designed to work with blockchain ETL services. This\npackage simplifies the process of registering blockchain event listeners and consuming them via Kafka.\n\n## Features\n\n- 🔗 **Easy Event Registration**: Register blockchain contract events with minimal configuration\n- 📨 **Kafka Integration**: Built-in Kafka consumer management with kafkajs\n- 🔧 **Type-Safe**: Full TypeScript support with comprehensive type definitions\n- 🎯 **Event Parsing**: Automatic event signature parsing using ethers.js v6\n- 🔄 **Transform Scripts**: Support for custom data transformation scripts\n- ⚡ **Efficient**: Optimized for handling high-throughput blockchain events\n\n## Installation\n\n```bash\nnpm install @c-tech/c-indexer-consumer\n```\n\nor with bun:\n\n```bash\nbun add @c-tech/c-indexer-consumer\n```\n\n## Prerequisites\n\n- A blockchain ETL service endpoint\n- Kafka broker(s) configured and running\n- Contract ABI for the events you want to monitor\n\n## Usage\n\n### Basic Example\n\n```typescript\nimport {BlockWatcherRegister, withTransformScript} from \"@c-tech/c-indexer-consumer\";\nimport {Kafka} from \"kafkajs\";\n\n// Initialize Kafka\nconst kafka = new Kafka({\n    clientId: \"my-app\",\n    brokers: [\"localhost:9092\"],\n});\n\n// Create a BlockWatcherRegister instance\nconst watcher = new BlockWatcherRegister({\n    etlBaseUrl: \"https://your-etl-service.com\",\n    defaultGroupId: \"my-consumer-group\", // optional, default: \"blockwatcher-group\"\n});\n\n// Define your contract ABI\nconst contractABI = `[\n  {\n    \"anonymous\": false,\n    \"inputs\": [\n      {\"indexed\": true, \"name\": \"from\", \"type\": \"address\"},\n      {\"indexed\": true, \"name\": \"to\", \"type\": \"address\"},\n      {\"indexed\": false, \"name\": \"value\", \"type\": \"uint256\"}\n    ],\n    \"name\": \"Transfer\",\n    \"type\": \"event\"\n  }\n]`;\n\n// Register an event handler\nawait watcher.register(\n    \"0x1234567890123456789012345678901234567890\", // contract address\n    contractABI,\n    \"Transfer\", // event name\n    1, // chain ID (1 = Ethereum mainnet)\n    async (payload) => {\n        // payload is already parsed - contains the event data\n        console.log(\"Transfer event:\", payload);\n    },\n    \"my-group-id\" // optional groupId, uses defaultGroupId if not provided\n);\n\n// Start consuming Kafka messages\nawait watcher.startKafka(kafka, {\n    groupId: \"my-consumer-group\", // optional, overrides defaultGroupId\n    fromBeginning: true, // optional, default: true\n});\n```\n\n### Advanced Usage with Custom Kafka Topic\n\n```typescript\nimport {\n    BlockWatcherRegister,\n    withKafkaTopic\n} from \"@c-tech/c-indexer-consumer\";\n\nconst watcher = new BlockWatcherRegister({\n    etlBaseUrl: \"https://your-etl-service.com\",\n});\n\n// Register with custom Kafka topic\nawait watcher.register(\n    \"0x1234567890123456789012345678901234567890\",\n    contractABI,\n    \"Transfer\",\n    1,\n    async (payload, meta) => {\n        console.log(\"Transfer event:\", payload);\n        console.log(\"Block number:\", meta.block_number);\n    },\n    undefined, // groupId (optional)\n    withKafkaTopic(\"my-custom-topic-name\") // custom Kafka topic\n);\n\nawait watcher.startKafka(kafka);\n```\n\n### Advanced Usage with Transform Scripts\n\n```typescript\nimport {\n    BlockWatcherRegister,\n    withTransformScript,\n    withTestData,\n    withKafkaTopic\n} from \"@c-tech/c-indexer-consumer\";\n\nconst watcher = new BlockWatcherRegister({\n    etlBaseUrl: \"https://your-etl-service.com\",\n});\n\n// Custom transformation script\nconst transformScript = `\nexport function transform(data, meta) {\n  return {\n    ...data,\n    timestamp: Date.now(),\n    chainId: meta.chain_id,\n    blockNumber: meta.block_number\n  };\n}\n`;\n\nawait watcher.register(\n    \"0x1234567890123456789012345678901234567890\",\n    contractABI,\n    \"Transfer\",\n    1,\n    async (payload, meta) => {\n        // Payload is already transformed by the script\n        console.log(\"Transformed event:\", payload);\n        console.log(\"With metadata:\", meta);\n    },\n    undefined, // groupId (optional)\n    withTransformScript(transformScript),\n    withTestData({mockField: \"test\"}),\n    withKafkaTopic(\"custom-transfer-topic\") // custom Kafka topic (optional)\n);\n\nawait watcher.startKafka(kafka, {\n    groupId: \"my-consumer-group\",\n    fromBeginning: true,\n});\n```\n\n### Multiple Event Registration\n\n```typescript\nconst watcher = new BlockWatcherRegister({\n    etlBaseUrl: \"https://your-etl-service.com\",\n});\n\n// Handler functions\nconst handleTransfer = async (payload: any, meta: EtlMetaData) => {\n    console.log(`Transfer on chain ${meta.chain_id}:`, payload);\n};\n\nconst handleApproval = async (payload: any) => {\n    console.log(\"Approval event:\", payload);\n};\n\nconst handleSwap = async (payload: any, meta: EtlMetaData) => {\n    console.log(`Swap at block ${meta.block_number}:`, payload);\n};\n\n// Register multiple events\nawait watcher.register(\n    \"0xContractA...\",\n    contractABI_A,\n    \"Transfer\",\n    1,\n    handleTransfer\n);\n\nawait watcher.register(\n    \"0xContractB...\",\n    contractABI_B,\n    \"Approval\",\n    1,\n    handleApproval\n);\n\nawait watcher.register(\n    \"0xContractC...\",\n    contractABI_C,\n    \"Swap\",\n    1,\n    handleSwap\n);\n\n// Start consuming all registered events\nawait watcher.startKafka(kafka);\n```\n\n## API Reference\n\n### `BlockWatcherRegister`\n\nMain class for managing blockchain event registration and consumption.\n\n#### Constructor\n\n```typescript\nnew BlockWatcherRegister(args\n:\nBlockWatcherConfig\n)\n```\n\n**BlockWatcherConfig:**\n\n```typescript\ntype BlockWatcherConfig = {\n    etlBaseUrl: string;\n    defaultGroupId?: string; // optional, default: \"blockwatcher-group\"\n}\n```\n\n- `etlBaseUrl`: The base URL of your blockchain ETL service\n- `defaultGroupId`: Default Kafka consumer group ID for all registered events\n\n#### Methods\n\n##### `register()`\n\nRegister a blockchain event to monitor.\n\n```typescript\nasync\nregister(\n    contractAddress\n:\nstring,\n    contractABI\n:\nstring,\n    eventName\n:\nstring,\n    chainId\n:\nnumber,\n    handler\n:\nKafkaConsumerMessageHandlerFunc,\n    groupId ? : string,\n...\noptions: RegisterOption[]\n):\nPromise<void>\n```\n\n**Parameters:**\n\n- `contractAddress`: The smart contract address\n- `contractABI`: Contract ABI JSON string\n- `eventName`: Name of the event to monitor (e.g., \"Transfer\", \"Approval\")\n- `chainId`: Blockchain chain ID (1 for Ethereum mainnet, 137 for Polygon, etc.)\n- `handler`: Callback function to handle incoming events\n- `groupId`: Optional Kafka consumer group ID for this specific event (overrides defaultGroupId)\n- `options`: Optional configuration (transform scripts, test data)\n\n##### `startKafka()`\n\nInitialize Kafka consumer and start processing events.\n\n```typescript\nasync\nstartKafka(\n    kafka\n:\nKafka,\n    options ? : {\n        groupId? : string;\n        fromBeginning? : boolean;\n    }\n):\nPromise<void>\n```\n\n**Parameters:**\n\n- `kafka`: KafkaJS Kafka instance\n- `options`: Optional configuration object\n    - `groupId`: Consumer group ID (overrides defaultGroupId)\n    - `fromBeginning`: Whether to read from the beginning of the topic (default: true)\n\n### Types\n\n#### `KafkaConsumerMessageHandlerFunc`\n\nThe handler function can have multiple signatures:\n\n```typescript\n// Option 1: Just payload\ntype Handler = (payload: any) => Promise<void> | void;\n\n// Option 2: Payload + metadata\ntype Handler = (payload: any, meta: EtlMetaData) => Promise<void> | void;\n\n// Option 3: Payload + raw Kafka message\ntype Handler = (payload: any, raw: KafkaMessage) => Promise<void> | void;\n```\n\n**Examples:**\n\n```typescript\n// Simple handler - just the payload\nasync (payload) => {\n    console.log(\"Event data:\", payload);\n}\n\n// Handler with metadata\nasync (payload, meta) => {\n    console.log(\"Event data:\", payload);\n    console.log(\"Chain ID:\", meta.chain_id);\n    console.log(\"Block number:\", meta.block_number);\n    console.log(\"Transaction hash:\", meta.tx_hash);\n}\n\n// Handler with raw message (for advanced use cases)\nasync (payload, rawMessage) => {\n    console.log(\"Event data:\", payload);\n    console.log(\"Kafka headers:\", rawMessage.headers);\n    console.log(\"Kafka offset:\", rawMessage.offset);\n}\n```\n\n#### `EtlMetaData`\n\nMetadata extracted from blockchain events:\n\n```typescript\ntype EtlMetaData = {\n    chain_id?: number;\n    _etl_event_log_entity_id?: number;\n    address?: string;\n    block_number?: number;\n    block_hash?: string;\n    tx_hash?: string;\n    tx_index?: number;\n    index?: number;\n    topics?: string[];\n    [k: string]: any;\n};\n```\n\n#### `RegisterOption`\n\n```typescript\ntype RegisterOption = {\n    transformScript?: string;\n    testData?: Record<string, any>;\n    kafkaTopic?: string;\n};\n```\n\n### Helper Functions\n\n#### `withTransformScript(script: string)`\n\nCreate a RegisterOption with a custom transform script.\n\n```typescript\nconst option = withTransformScript(`\n  export function transform(data, meta) {\n    return { ...data, processed: true };\n  }\n`);\n```\n\n#### `withTestData(testData: Record<string, any>)`\n\nCreate a RegisterOption with test data.\n\n```typescript\nconst option = withTestData({mockField: \"value\"});\n```\n\n#### `withKafkaTopic(kafkaTopic: string)`\n\nCreate a RegisterOption with a custom Kafka topic name.\n\n```typescript\nconst option = withKafkaTopic(\"my-custom-topic\");\n```\n\n**Note:** If not specified, the default topic naming convention is:\n\n```\nblockchain.{chainId}.{eventName}.{contractAddress}.{topicHash4Bytes}\n```\n\n## How It Works\n\n1. **Event Registration**: When you register an event, the library:\n    - Parses the contract ABI using ethers.js\n    - Extracts the event signature and generates the topic hash\n    - Creates a unique Kafka topic name\n    - Sends a registration request to the ETL service\n\n2. **Kafka Topic Naming**: By default, topics are automatically generated in the format:\n   ```\n   blockchain.{chainId}.{eventName}.{contractAddress}.{topicHash4Bytes}\n   ```\n   You can override this by using `withKafkaTopic()` option.\n\n3. **Message Processing Flow**:\n   ```\n   Kafka Message\n       ↓\n   KafkaConsumerRegister (receives raw message)\n       ↓\n   KafkaConsumerHandlerSingleFunc (wrapper layer)\n       ↓\n   - Parses message.value JSON\n   - Extracts payload\n   - Extracts metadata (if needed)\n   - Converts string numbers to actual numbers\n       ↓\n   Your Handler Function (receives parsed data)\n   ```\n\n4. **Event Consumption**: The Kafka consumer subscribes to all registered topics and routes messages to the appropriate\n   handlers.\n\n5. **Automatic Parsing**: The library automatically:\n    - Parses the Kafka message JSON\n    - Extracts the `payload` field\n    - Extracts and converts `meta` data (chain_id, block_number, etc.)\n    - Calls your handler with the appropriate parameters based on function signature\n\n## Configuration\n\n### Environment Variables\n\nYou can configure Kafka brokers and other settings through environment variables or directly in code:\n\n```typescript\nconst kafka = new Kafka({\n    clientId: process.env.KAFKA_CLIENT_ID || \"blockchain-consumer\",\n    brokers: process.env.KAFKA_BROKERS?.split(\",\") || [\"localhost:9092\"],\n});\n```\n\n## Error Handling\n\nThe library throws errors for:\n\n- Invalid contract ABIs\n- Non-existent event names\n- ETL service connection failures\n- Kafka connection issues\n\nAlways wrap registration and startup calls in try-catch blocks:\n\n```typescript\ntry {\n    await watcher.register(...);\n    await watcher.startKafka(kafka);\n} catch (error) {\n    console.error(\"Error:\", error.message);\n}\n```\n\n## Dependencies\n\n- **ethers** (^6.15.0): For ABI parsing and event signature generation\n- **kafkajs** (^2.2.4): For Kafka consumer functionality\n\n## License\n\nMIT\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## Support\n\nFor issues and questions, please open an issue on the GitHub repository.\n","readmeFilename":"README.md"}