{"id":19563272,"url":"https://github.com/kodadot/click","last_synced_at":"2025-04-27T00:32:12.471Z","repository":{"id":42374368,"uuid":"504294567","full_name":"kodadot/click","owner":"kodadot","description":"Indexer for EVM based Polkadot parachains","archived":false,"fork":false,"pushed_at":"2022-12-24T20:16:06.000Z","size":1591,"stargazers_count":3,"open_issues_count":14,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2023-03-03T19:50:01.494Z","etag":null,"topics":["evm","evm-blockchain","graphql","hacktoberfest","subsquid"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kodadot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-06-16T20:19:19.000Z","updated_at":"2023-02-27T10:06:52.000Z","dependencies_parsed_at":"2023-01-30T21:15:51.058Z","dependency_job_id":null,"html_url":"https://github.com/kodadot/click","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kodadot%2Fclick","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kodadot%2Fclick/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kodadot%2Fclick/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kodadot%2Fclick/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kodadot","download_url":"https://codeload.github.com/kodadot/click/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224050652,"owners_count":17247380,"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","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":["evm","evm-blockchain","graphql","hacktoberfest","subsquid"],"created_at":"2024-11-11T05:17:10.485Z","updated_at":"2024-11-11T05:17:11.819Z","avatar_url":"https://github.com/kodadot.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Click\n\n![](https://media.giphy.com/media/KZEniLNHKh2HRFEhdu/giphy.gif)\n\nSupport of Moonsama-based NFTs in the KodaDot\n\n## How does it work\n\nWe basically index three types of events:\n\n  * `Transfer` - events emitted by the ERC-721 contract when a token is transferred.\n  * `TransferSingle` - events emitted by the ERC-1155 contract when a single token id is transferred.\n  * `TransferBatch` - events emitted by the ERC-1155 contract when a batch of token ids are transferred.\n\n```ts\n// Snippet that shows how to handle events\nprocessor.addEvmLogHandler(Contracts.Moonsama, transferFilter, mappings.mainFrame);\nprocessor.addEvmLogHandler(Contracts.Moonx, singleTransferFilter, mappings.singleMainFrame);\nprocessor.addEvmLogHandler(Contracts.Moonx, multiTransferFilter, mappings.mutliMainFrame);\n```\n\nWhat's the `Contracts.Moonsama` ? That's an excellent question.\nIn the `processable.ts,` we have an enum that defines the contract addresses.\n\n```ts\nenum Contracts {\n  Moonsama = '0xb654611f84a8dc429ba3cb4fda9fad236c505a1a', // ERC-721\n  Moonx = '0x1974eeaf317ecf792ff307f25a3521c35eecde86', // ERC-1155\n}\n```\n**What are the `transferFilter` and `singleTransferFilter` ?**\n\nWe simply tell the indexer that we want to listen to this specific event (topic) from the particular contract.\nAs shown in the snippet below, we have a filter that listens to the `Transfer` event.\n\n```ts\nexport const transferFilter: EvmLogHandlerOptions = {\n  filter: [erc721.events[\"Transfer(address,address,uint256)\"].topic],\n}\n```\n\nThe last parameter of the `addEvmLogHandler` is a function that will be called when the event is emitted.\nThe algorithm is as follows:\n\n```ts\nexport async function mainFrame(ctx: Context): Promise\u003cvoid\u003e {\n  const transfer = decode721Transfer(ctx) // decode the event to [from, to, tokenId]\n  \n    switch (whatIsThisTransfer(transfer)) { // check what kind of transfer it is (mint, transfer, send)\n    case Interaction.MINTNFT:\n      transferDebug(Interaction.MINTNFT, transfer)\n      await handleTokenCreate(ctx)\n      break\n    case Interaction.SEND:\n      transferDebug(Interaction.SEND, transfer)\n      await handleTokenTransfer(ctx)\n      break\n    case Interaction.CONSUME:\n      transferDebug(Interaction.CONSUME, transfer)\n      await handleTokenBurn(ctx)\n      break\n    default:\n      logger.warn(`Unknown transfer: ${JSON.stringify(transfer, null, 2)}`)\n  }\n}\n```\n\nFor example, we have a function that handles the `Transfer` event.\n- First, we need to get base transaction data and data about the transferred token.\n- This is done by calling the `unwrap(context, getTransferTokenEvent)` function.\n- Then we need to check if the token exists in the database.\n- In the last step, we need to update the `currentOwner` and save the token to the database.\n- Moreover, for historical purposes, we also created an event where the NFT was transferred.\n\n```ts\nexport async function handleTokenTransfer(context: Context): Promise\u003cvoid\u003e {\n  const event = unwrap(context, getTransferTokenEvent)\n  const id = createTokenId(event.collectionId, event.sn)\n  const entity = ensure\u003cNE\u003e(await get(context.store, NE, id))\n  plsBe(real, entity)\n\n  entity.currentOwner = event.to\n  \n  await context.store.save(entity)\n  await createEvent(entity, Interaction.SEND, event, event.to || '', context.store, currentOwner)\n}\n```\n\n## Fast Forward\n\n```\njust up\njust codegen\njust build\njust reset\njust explore\n```\n\nStart processor\n```\njust process\n```\n\nRun GraphQL queries\n```\njust serve\n```\n\n## Prerequisites\n\n* NodeJS 16.x\n* npm\n* docker\n\n## Bootstrap\n\n```bash\n# 1. Install dependencies\nnpm ci\n\n# 2. Compile typescript files\nnpm run build\n\n# 3. Start target Postgres database\ndocker compose up -d\n\n# 4. Apply database migrations from db/migrations\nnpx sqd db create\nnpx sqd db migrate\n\n# 5. Now start the processor\nnode -r dotenv/config lib/processor.js\n\n# 6. The above command will block the terminal\n#    being busy with fetching the chain data, \n#    transforming and storing it in the target database.\n#\n#    To start the graphql server open the separate terminal\n#    and run\nnpx squid-graphql-server\n```\n\n### Import ABI contract and set up interfaces to decode events\n\nIn order to be able to process EVM logs, it is necessary to import the respective ABI definition. In the case of this project, this has been done via the [`src/abis/ERC721.json`](src/abis/ERC721.json) file.\n\nFurthermore, it is necessary to decode logs and this is shown in [`src/abis/erc721.ts`](src/abis/erc721.ts). The `events` dictionary define there maps the event name at the center of this project to the function used to decode it.\n\n### Project structure\n\nHydra tools expect a certain directory layout:\n\n* `src/generated` - model/server definitions created by `codegen`. Do not alter the contents of this directory manually.\n* `src/server-extension` - module with custom `type-graphql` based resolvers\n* `src/types` - data type definitions for chain events and extrinsics created by `typegen`.\n* `src/mappings` - mapping module.\n* `lib` - compiled js files. The structure of this directory must reflect `src`.\n* `.env` - hydra tools are heavily driven by environment variables defined here or supplied by a shell.\n\n\n### Viki's Randomnotes\n\n1. [Squid EVM typegen](https://docs.subsquid.io/reference/squid-evm-typegen)\n\n```sh\nnpx squid-evm-typegen --abi ./src/abi/ERC1155.json --output ./src/abi/erc1155.ts\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkodadot%2Fclick","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkodadot%2Fclick","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkodadot%2Fclick/lists"}