{"id":20640506,"url":"https://github.com/kovart/forta-helpers","last_synced_at":"2025-08-15T22:44:31.493Z","repository":{"id":154157147,"uuid":"630837566","full_name":"kovart/forta-helpers","owner":"kovart","description":"A set of ready-made solutions to common problems encountered during Forta bot development.","archived":false,"fork":false,"pushed_at":"2024-03-05T21:52:54.000Z","size":112,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-29T02:21:44.550Z","etag":null,"topics":["bot","forta","helpers","library","utils"],"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/kovart.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}},"created_at":"2023-04-21T09:07:27.000Z","updated_at":"2024-10-29T10:51:36.000Z","dependencies_parsed_at":"2024-03-05T22:52:43.570Z","dependency_job_id":null,"html_url":"https://github.com/kovart/forta-helpers","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kovart%2Fforta-helpers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kovart%2Fforta-helpers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kovart%2Fforta-helpers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kovart%2Fforta-helpers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kovart","download_url":"https://codeload.github.com/kovart/forta-helpers/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249167446,"owners_count":21223506,"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":["bot","forta","helpers","library","utils"],"created_at":"2024-11-16T15:29:43.600Z","updated_at":"2025-04-15T23:01:20.864Z","avatar_url":"https://github.com/kovart.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Forta Helpers\n\nA set of ready-made recipes to common problems encountered during Forta bot development.\n\n## Installation\n\n```bash\n$ npm install forta-helpers\n```\n\n## Solutions\n\nHere is a list of example solutions to various problems using this library.\n\n## Extract created contracts\n\nThe tool detects all contracts created within the passed transaction event.\nIt should be noted that contracts created by other contracts can be detected only\nif [Trace API](https://github.com/NethermindEth/docs/blob/master/nethermind-utilities/cli/trace.md) is supported.\n\n```ts\nimport { getCreatedContracts } from 'forta-helpers';\n\nasync function handleTransaction(txEvent: TransactionEvent) {\n  const createdContracts = getCreatedContracts(txEvent);\n\n  for (const contract of createdContracts) {\n    // {\n    //     address: string;\n    //     deployer: string;\n    //     timestamp: number;\n    //     blockNumber: number;\n    // }\n    console.log(contract);\n  }\n\n  return [];\n}\n```\n\n## Identify token contract\n\n```ts\nimport { getCreatedContracts, identifyTokenInterface } from 'forta-helpers';\n\nasync function handleTransaction(txEvent: TransactionEvent) {\n  const createdContracts = getCreatedContracts(txEvent);\n\n  for (const contract of createdContracts) {\n    const type = await identifyTokenInterface(contract.address, data.provider);\n    if (type) Logger.debug(`Found token contract (ERC${type}): ${contract.address}`);\n  }\n\n  return [];\n}\n```\n\n## Extract addresses from a contract code\n\n```ts\nimport { getOpcodeAddresses, getOpcodeContractAddresses } from 'forta-helpers';\n\nconst provider = new ethers.providers.JsonRpcProvider('https://rpc.ankr.com/eth');\nconst code = await provider.getCode('0xdAC17F958D2ee523a2206206994597C13D831ec7');\nconst allAddresses = getOpcodeAddresses(code);\nconst contractAddresses = await getOpcodeContractAddresses(code, provider);\n```\n\n## Get accessible IPFS URI\n\nSupported formats:\n\n- QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o\n- /ipfs/QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o\n- ://QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o\n- ipfs://QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o/0.json\n- https://ipfs.io/ipfs/QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o\n- http://bafybeie5gq4jxvzmsym6hjlwxej4rwdoxt7wadqvmmwbqi7r27fclha2va.dweb.link\n- https://site.com/test.json#234?a=3\n\n```ts\nimport { containsLink, normalizeMetadataUri } from 'forta-helpers';\n\nconst uri = '://QmYjtig7VJQ6XsnUjqqJvj7QaMcCAwtrgNdahSiFofrE7o/0.json';\nconst isLink = containsLink(uri);\nif (!isLink) {\n  const url = normalizeMetadataUri(uri);\n  const data = await axios.get(url);\n}\n```\n\n## Parallel execution by multiple providers\n\nThis queue allows tasks to be performed concurrently by multiple providers.\nEach task is assigned a unique provider.\n\n```ts\nimport { providersQueue } from 'forta-helpers';\n\ntype Task = {\n  account: string;\n  blockNumber: number;\n};\n\nconst provider1 = new ethers.providers.JsonRpcProvider('https://rpc.ankr.com/eth');\nconst provider2 = new ethers.providers.JsonRpcProvider('https://ethereum.publicnode.com');\nconst provider3 = new ethers.providers.JsonRpcProvider('https://1rpc.io/eth');\n\nconst q = providersQueue\u003cTask, ethers.providers.JsonRpcProvider\u003e(\n  async (task, provider) =\u003e {\n    const balance = await provider.getBalance(task.account, task.blockNumber);\n    // do some work here\n  },\n  [provider1, provider2, provider3],\n);\n\n// add your tasks\n\nq.push({\n  account: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',\n  blockNumber: 17387564,\n});\nq.push({\n  account: '0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5',\n  blockNumber: 17387564,\n});\n// ... add as much as you need\n\n// and wait for them all to be fulfilled\n\nawait q.finish();\n```\n\n## Get addresses from contract storage\n\n```ts\nimport { getStorageAddresses, getStorageContractAddresses } from 'forta-helpers';\n\n// Check up to 20 contract variables and extract all the addresses from there\nconst allAddresses = await getStorageAddresses(\n  '0xdAC17F958D2ee523a2206206994597C13D831ec7',\n  provider,\n  20,\n);\n\n// Check up to 20 internal contract variables, extract all the addresses from there and check if they are contracts\nconst contractAddresses = await getStorageContractAddresses(\n  '0xdAC17F958D2ee523a2206206994597C13D831ec7',\n  provider,\n  20,\n);\n```\n\n## File Storage\n\n### JsonStorage\n\n```ts\nimport { JsonStorage } from 'forta-helpers';\n\ntype BotState = {\n  transactionCount: number;\n  lastTransactionHash: string;\n};\n\nconst stateStorage = new JsonStorage\u003cBotState\u003e('./data', 'state.json');\n\nawait stateStorage.write({\n  transactionCount: 20,\n  lastTransactionHash: '0xHASH',\n});\n\nconst state = await stateStorage.read();\n```\n\n### CsvStorage\n\n```ts\nimport { CsvStorage } from 'forta-helpers';\n\ntype Transaction = {\n  hash: string;\n  blockNumber: number;\n};\n\nconst transactionStorage = new CsvStorage\u003cTransaction\u003e(\n  './data',\n  'transactions.csv',\n  // preparing data for reading\n  (v) =\u003e ({ ...v, blockNumber: Number(v.blockNumber) }),\n  // preparing data for writing\n  (v) =\u003e v,\n);\n\nawait transactionStorage.write([\n  { hash: '0xHASH1', blockNumber: 1 },\n  { hash: '0xHASH2', blockNumber: 2 },\n]);\n\nconst transactions = await transactionStorage.read();\n```\n\n### InMemoryStorage\n\nThis storage type is handy for not having to create a file during the development or testing of the bot.\n\n```ts\nimport { InMemoryStorage, JsonStorage } from 'forta-helpers';\n\ntype BotState = {\n  transactionCount: number;\n  lastTransactionHash: string;\n};\n\nconst storage = isDevelopment\n  ? new InMemoryStorage\u003cBotState\u003e()\n  : new JsonStorage\u003cBotState\u003e('./data', 'state.json');\n  \nawait storage.write({\n  transactionCount: 20,\n  lastTransactionHash: '0xHASH',\n});\n\nconst state = await storage.read();\n\n```\n\n## Filter burn-address\n\nChecks for the presence in the list of known burn-addresses, as well as the frequent repetition of \"0\" in the address.\n\n```ts\nimport { isBurnAddress } from 'forta-helpers';\n\nif (\n  isBurnAddress('0xdead000000000000000042069420694206942069') ||\n  isBurnAddress('0x0123456789012345678901234567890123456789') ||\n  isBurnAddress('0x000000000000000000000000000000000000dEaD')\n) {\n  // do some work\n}\n```\n\n## Retry\n\n```ts\nimport { retry } from 'forta-helpers';\n\nconst provider = new ethers.providers.JsonRpcProvider('https://rpc.ankr.com/eth');\nconst balance = await retry(() =\u003e provider.getBalance('0xdAC17F958D2ee523a2206206994597C13D831ec7'), {\n  // wait 15s between attempts\n  wait: 15 * 1000,\n  // try to call 3 times\n  attempts: 3,\n});\n```\n\n## Do some work at a given interval\n\n```ts\nimport { createTicker } from 'forta-helpers';\n\nconst isTimeToSync = createTicker(5 * 60 * 1000);\n\nasync function handleTransaction(txEvent: TransactionEvent) {\n  // by default, always true on the first call\n  if(isTimeToSync(txEvent.timestamp)) {\n    // sync\n  }\n\n  return [];\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkovart%2Fforta-helpers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkovart%2Fforta-helpers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkovart%2Fforta-helpers/lists"}