{"id":41145771,"url":"https://github.com/func25/gother","last_synced_at":"2026-01-22T18:55:44.741Z","repository":{"id":41053038,"uuid":"507049117","full_name":"func25/gother","owner":"func25","description":null,"archived":false,"fork":false,"pushed_at":"2023-08-18T09:59:17.000Z","size":71,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-06-21T01:44:41.560Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/func25.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-24T14:56:22.000Z","updated_at":"2022-06-25T08:59:20.000Z","dependencies_parsed_at":"2024-06-21T00:26:17.114Z","dependency_job_id":"495eca08-89e2-4e43-a2e8-f50929f2df88","html_url":"https://github.com/func25/gother","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/func25/gother","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/func25%2Fgother","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/func25%2Fgother/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/func25%2Fgother/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/func25%2Fgother/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/func25","download_url":"https://codeload.github.com/func25/gother/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/func25%2Fgother/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28668643,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T17:07:18.858Z","status":"ssl_error","status_checked_at":"2026-01-22T17:05:02.040Z","response_time":144,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2026-01-22T18:55:44.659Z","updated_at":"2026-01-22T18:55:44.714Z","avatar_url":"https://github.com/func25.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gother\n\ngother is the library supporting interaction with smart contract, fetch contract's logs from blocks,...\n\n## Content:\n\n- [Installation](#installation)\n- [Get started](#get-started)\n  - [Dial to node](#dial-to-node)\n  - [Worker workflow](#worker-workflow)\n    - [Scanner: collect the logs](#scanner-scan-blocks-to-get-the-logs)\n    - [Agent \u0026 Lazier: collect the logs, but in loop](#agent--lazier-scan-but-in-the-loop)\n\n## Installation\n\n1. You first need Go installed (version 1.18+ is required):\n\n```sh\n$ go get -u github.com/func25/gother\n```\n\n2. Import it in your code:\n\n```go\nimport \"github.com/func25/gother\"\n```\n\n## Get started\n\n### Dial to node\n\nYou need to dial the RPC node first:\n\n```go\ngother.DialCtx(context.Background(), \"https://data-seed-prebsc-1-s3.binance.org:8545/\")\n\n// or gother.Dial(\"https://data-seed-prebsc-1-s3.binance.org:8545/\")\n```\n\n### Worker workflow\n\nIn some cases, we need to crawl contract logs from the block; you can collect with the support of a scanner and lazier.\n\n#### Scanner: scan blocks to get the logs\n\n```go\n// scan 100 blocks from block 2160030\nscan := gother.NewScanner(100, 21600030)\n\nlogs, scannedBlock, err := scan.Scan(ctx)\nif err != nil {\n  return err\n}\n\n// print the transaction hash of logs\nfor _, l := range logs {\n  fmt.Println(l.TxHash)\n}\n\nfmt.Printf(\"I have scanned to block %d\\n\", scannedBlock)\n```\n\nBut how can you scan logs emitted from a specific smart contract?\n```go\n// scan 100 blocks from block 2160030 and get the logs \n// which emitted from contract: 0xbA01E92eA9B940745f89785fC9cED4DDc17Da450\nscan := gother.NewScanner(100, 21600030, common.HexToAddress(\"0xbA01E92eA9B940745f89785fC9cED4DDc17Da450\"))\n```\n\n#### Agent \u0026 Lazier: scan but in the loop\n\nThis lib supports you define an agent to do the loop: scan -\u003e wait -\u003e scan -\u003e wait -\u003e scan..., and the agent must meet the interface IAgent\n```go\n// the target interface \ntype IAgent interface {\n\tFromBlock(ctx context.Context) (uint64, error)       // get the next block which want to scan from\n\tProcessLog(ctx context.Context, log types.Log) error // process the logs that agent collects\n\tUpdateBlock(ctx context.Context, block uint64) error // update the scanned block after scanning\n}\n\n// create an agent\ntype Agent struct {\n  Block uint64\n}\n\n// Scanner will scan from this block\nfunc (s *Agent) FromBlock(ctx context.Context) (uint64, error) {\n\treturn s.Block + 1, nil\n}\n\n// Process the crawled log\nfunc (s *Agent) ProcessLog(ctx context.Context, log types.Log) error {\n\tif log.Removed {\n\t\treturn nil\n\t}\n\n\tfmt.Println(log.TxHash.Hex())\n\n\treturn nil\n}\n\n// Save the scanned block after scanning\nfunc (s *Agent) UpdateBlock(ctx context.Context, block uint64) error {\n\ts.Block = block\n\treturn nil\n}\n```\n\nAfter creating the agent, wrap it with the lazier and do scanning\n```go\n// create an agent\nagent := Agent{Block: 21600130}\n\n// wrap the agent with lazier and wait duration of lazier is 3 seconds\nlazier := gother.Lazier[*Agent]{Agent: \u0026agent, Duration: time.Second * 3}\n\n// scan 100 blocks each time, the `from` of scanner will be replaced with FromBlock(ctx) of agent\nlazier.Scan(*gother.NewScanner(100, 0))\n\nfor {} // block the thread\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffunc25%2Fgother","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffunc25%2Fgother","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffunc25%2Fgother/lists"}