{"id":15456824,"url":"https://github.com/ipaulpro/smart-polls","last_synced_at":"2026-02-28T08:07:44.509Z","repository":{"id":222387379,"uuid":"757118105","full_name":"iPaulPro/smart-polls","owner":"iPaulPro","description":"An Open Action Module for Lens Protocol that transforms a publication into a poll, using Ethereum Attestation Service for on-chain voting.","archived":false,"fork":false,"pushed_at":"2024-03-21T17:14:21.000Z","size":724,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-28T08:23:29.525Z","etag":null,"topics":["decentralized-social","eas","ethereum-attestation-service","lens-protocol","web3"],"latest_commit_sha":null,"homepage":"","language":"Solidity","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/iPaulPro.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}},"created_at":"2024-02-13T20:56:26.000Z","updated_at":"2024-05-20T13:45:44.000Z","dependencies_parsed_at":"2024-10-05T05:40:44.355Z","dependency_job_id":"a62a204d-bfc6-4292-a4b7-019fb2e9a9ed","html_url":"https://github.com/iPaulPro/smart-polls","commit_stats":null,"previous_names":["ipaulpro/easpollactionmodule","ipaulpro/smartpolls"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/iPaulPro/smart-polls","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iPaulPro%2Fsmart-polls","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iPaulPro%2Fsmart-polls/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iPaulPro%2Fsmart-polls/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iPaulPro%2Fsmart-polls/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iPaulPro","download_url":"https://codeload.github.com/iPaulPro/smart-polls/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iPaulPro%2Fsmart-polls/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29928061,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T19:37:42.220Z","status":"online","status_checked_at":"2026-02-28T02:00:07.010Z","response_time":90,"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":["decentralized-social","eas","ethereum-attestation-service","lens-protocol","web3"],"created_at":"2024-10-01T22:40:00.903Z","updated_at":"2026-02-28T08:07:44.489Z","avatar_url":"https://github.com/iPaulPro.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Smart Polls\n\nSmart Polls transform Lens posts into polls using the Ethereum Attestation Service (EAS) for on-chain voting.\n\n`EasPollActionModule.sol` is an Open Action Module (Publication Module) for Lens Protocol that can be added to any publication to create a poll. The poll options and votes are stored on-chain and can be queried using the EAS GraphQL API or by running a subgraph.\n\n## Packages\n\n- `EasPollActionModule`: The Open Action module contract for creating and querying polls and votes. \n- `eas-poll-action-module`: A helper library for interacting with `EasPollActionModule`, available for [installation](#install-eas-poll-action-module-helper-library) via npm.\n\n## Benefits over using Snapshot\n\nThe `EasPollActionModule` contract provides a number of benefits over using Snapshot for polls:\n\n1. **100% on-chain**: The poll and votes are stored on-chain, providing a high level of trust and transparency.\n2. **Protocol-wide**: Unlike Snapshot, the `EasPollActionModule` can be used on any Lens Protocol publication, and polls can be voted on from any Lens app. No DAO hack necessary!\n3. **EAS Integration**: Ethereum Attestation Service (EAS) allows for easy and permissionless querying of votes using their GraphQL API or your own subgraph.\n4. **Token gating**: Easily restrict voting to followers of the publication author or to any arbitrary ERC20/ERC721 token holders.\n5. **Require Signature**: Optionally require a signature for voting, creating a [delegated attestation](https://docs.attest.sh/docs/core--concepts/delegated-attestations).\n\n## Using the EasPollActionModule Contract\n\nTo use the live `EasPollActionModule` you can use the address and metadata below:\n\n| Network | Chain ID | Deployed Contract                                                                                                               | Metadata                                                                     | EAS Schema UID                                                                                                                                                                          |\n|---------|----------|---------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Polygon | 137      | [0x3d06AA6ca4FC7eE0D5581B85CB52CA7714175e43](https://polygonscan.com/address/0x3d06AA6ca4FC7eE0D5581B85CB52CA7714175e43)        | [link](https://gateway.irys.xyz/mksPnRse1o2esLEHu_GxSgakfPagWmkELoOHlS_6XyQ) | [0xd91d9a230a4f60495ff79cd81fa5d7f27ee75b28e71f1ce144c7affae8cc8c52](https://polygon-mumbai.easscan.org/schema/view/0xd91d9a230a4f60495ff79cd81fa5d7f27ee75b28e71f1ce144c7affae8cc8c52) |\n| Mumbai  | 80001    | [0xc91C3d3eD7089a9b52945c8967CF0854f08E9e7a](https://mumbai.polygonscan.com/address/0xc91C3d3eD7089a9b52945c8967CF0854f08E9e7a) | [link](https://gateway.irys.xyz/NTOWrzOZxJH_RJHEha1MC_m9s6-kAY7igCyhSDE6seU) | [0x44c235a2465c4d70bd980bdcf968d1997b237e2c7d30a2de1b59b98fee4a1f37](https://polygon-mumbai.easscan.org/schema/view/0x44c235a2465c4d70bd980bdcf968d1997b237e2c7d30a2de1b59b98fee4a1f37) |\n\nThe `EasPollActionModule` contract can be used as an Open Action Module on Lens Protocol publications. Here are examples of successful transactions on Mumbai using the poll module:\n\n[`Post (init)` transaction](https://mumbai.polygonscan.com/tx/0xc20b03ff16c67a5e04d461b5535426137a6afc186fab3f33517d45bee8f18eeb)\n\n[`Act (process)` transaction](https://mumbai.polygonscan.com/tx/0x17519fee2af6cec2b5fe508646a135aecf6beac7bc4478cbca6e247e38718b02)\n\n[Example Attestation](https://polygon-mumbai.easscan.org/attestation/view/0x8787529ab2627b903970b971dfe52576ae7ef62570f42bfb9ff28a4a0ee395fc)\n\n### Install `eas-poll-action-module` Helper Library\n\nThe helper library provides functions for creating the Lens SDK `OpenActionModuleInput` and `ActOnOpenActionRequest` which can be used to attach and act on the Open Action Module. To use the `eas-poll-action-module` helper library, you can install it from npm:\n\n```bash\nnpm i -D eas-poll-action-module\n```\n```bash\nyarn add -D eas-poll-action-module\n```\n```bash\npnpm add -D eas-poll-action-module\n```\n\n### Create a Poll\n\nTo create a poll, the initialize calldata ABI is:\n\n| Name                | Type         | Description                                                                           | Required |\n|---------------------|:-------------|---------------------------------------------------------------------------------------|----------|\n| `options`           | `bytes32[4]` | An array of 2 to 4 voting choice strings that have been encoded into `bytes32` format | true     |\n| `followersOnly`     | `bool`       | Restrict voting to followers of the publication author                                | false    |\n| `endTimestamp`      | `uint40`     | The timestamp (in seconds) when the poll ends or zero for open-ended                  | false    |\n| `signatureRequired` | `bool`       | Whether a signature is required for voting                                            | false    |\n| `gateParams`        | `tuple`      | Token gating parameters                                                               | false    |\n\nThe optional `gateParams` tuple is used to restrict voting to holders of a specific ERC20 or ERC721 token:\n\n| Name           | Type      | Description                          | Required |\n|----------------|-----------|--------------------------------------|----------|\n| `tokenAddress` | `address` | The address of the token contract    | true     |\n| `minBalance`   | `uint256` | The minimum balance required to vote | true     |\n\nHere's an example of creating the poll action with the `eas-poll-action-module` helper library:\n\n```typescript\nimport { OpenActionModuleInput, OnchainPostRequest } from \"@lens-protocol/client\";\nimport { type EasPoll, createPollActionModuleInput } from \"eas-poll-action-module\";\n\nconst poll: EasPoll = {\n  options: [\"Option A\", \"Option B\", \"Option C\", \"Option D\"],\n  followersOnly: true, // Optional\n  endTimestamp: Math.floor(Date.now() / 1000) + 60 * 60 * 24, // Optional\n  signatureRequired: false, // Optional\n  gateParams: { // Optional\n    tokenAddress: \"0x9B8cc6320F22325759B7D2CA5CD27347bB4eCD86\",\n    minBalance: 1000000000000000000n,\n  }\n};\n\nconst pollAction: OpenActionModuleInput = createPollActionModuleInput(poll);\n\nconst postRequest: OnchainPostRequest = { contentURI };\npostRequest.openActionModules= [{ unknownOpenAction: pollAction }];\nawait lensClient.publication.postOnchain(postRequest);\n````\n### Vote on a Poll\n\nTo vote on a poll, you create a `vote` tuple:\n\n| Parameter              | Description                                         | Type      |\n|------------------------|-----------------------------------------------------|-----------|\n| `publicationProfileId` | The profile id of the publication author            | `uint256` |\n| `publicationId`        | The publication id                                  | `uint256` |\n| `actorProfileId`       | The profile id of the voter                         | `uint256` |\n| `actorProfileOwner`    | The address of the voter                            | `address` |\n| `transactionExecutor`  | The address of the transaction executor             | `address` |\n| `optionIndex`          | The index of the option the voter selected (0 to 3) | `uint8`   |\n| `timestamp`            | The timestamp (in seconds) when the vote was cast   | `uint40`  |\n\nHere's how you can use the `eas-poll-action-module` helper library to create the `vote` \"act on\" request to be used with the Lens SDK:\n\n```typescript\nimport { ActOnOpenActionRequest } from \"@lens-protocol/client\";\nimport { type EasVote, createVoteActionRequest } from \"eas-poll-action-module\";\n\nconst vote: EasVote = {\n  publicationId: \"0xd8-0x01\",\n  optionIndex: 1,\n};\n\nconst voteAction: ActOnOpenActionRequest = createVoteActionRequest(vote);\nawait lensClient.publication.actions.actOn(voteAction);\n```\n\n#### ⚠️ Note:\nWhen `signatureRequired` is `true` on the `Poll` you must sign the `vote` using the `transactionExecutor` address. You can provide an `ethers.Signer` to the `createVoteActionRequest` function to sign the vote.\n\n### EAS GraphQL API\n\nThe `scemaUid` can also be used to query the [EAS GraphQL API](https://docs.attest.sh/docs/developer-tools/api) for votes. The `eas-poll-action-module` helper library provides functions for encoding the `pollId` and `optionIndex` to be used in the GraphQL query.\n\nHere's how you can get an attestation (vote) count from EAS:\n\n```typescript\nimport { createVoteCountQueryVariables, getVoteCount } from \"eas-poll-action-module\";\n\nconst variables = createVoteCountQueryVariables(publicationId);\nconst count = await getVoteCount(variables);\n```\n\nHere's how you can get an attestation (vote) count for a specific option from EAS.\n\n```typescript\nimport { createVoteCountForOptionQueryVariables, getVoteCountForOption } from \"eas-poll-action-module\";\n\nconst optionIndex = 1;\nconst variables = createVoteCountForOptionQueryVariables(publicationId, optionIndex);\nconst count = await getVoteCountForOption(variables);\n```\n\n### Get Poll Results\n\nThe contract also provides many ways to get poll results.\n\n```solidity\n/**\n * @dev Get the number of votes/attestations for a publication.\n * @param profileId The profile id of the publication author\n * @param pubId The publication id\n * @return The number of attestations\n */\nfunction getAttestationCount(\n    uint256 profileId,\n    uint256 pubId\n) external view returns (uint256);\n\n/**\n * @dev Get the attestation for a vote at a specific index.\n * @param profileId The profile id of the publication author\n * @param pubId The publication id\n * @param index The index of the vote\n * @return The vote\n */\nfunction getAttestationByIndex(\n    uint256 profileId,\n    uint256 pubId,\n    uint256 index\n) external view returns (bytes32);\n\n/**\n * @dev Get the attested vote for an actor.\n * @param profileId The profile id of the publication author\n * @param pubId The publication id\n * @param actor The actor address\n * @return The vote\n */\nfunction getVote(\n    uint256 profileId,\n    uint256 pubId,\n    address actor\n) external view returns (Vote memory);\n\n/**\n * @dev Get the attestation for a vote at a specific index.\n * @param profileId The profile id of the publication author\n * @param pubId The publication id\n * @param index The index of the vote\n * @return The vote\n */\nfunction getVoteByIndex(\n    uint256 profileId,\n    uint256 pubId,\n    uint256 index\n) external view returns (Vote memory);\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fipaulpro%2Fsmart-polls","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fipaulpro%2Fsmart-polls","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fipaulpro%2Fsmart-polls/lists"}