{"id":20049025,"url":"https://github.com/unlock-protocol/hackathon-demo","last_synced_at":"2026-05-13T14:31:28.978Z","repository":{"id":196253910,"uuid":"695255298","full_name":"unlock-protocol/hackathon-demo","owner":"unlock-protocol","description":null,"archived":false,"fork":false,"pushed_at":"2023-09-23T18:05:16.000Z","size":403,"stargazers_count":1,"open_issues_count":1,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-27T16:40:43.662Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/unlock-protocol.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}},"created_at":"2023-09-22T17:41:55.000Z","updated_at":"2024-02-23T19:43:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"b4b5c77a-c22b-4fea-8681-d18beaf422c4","html_url":"https://github.com/unlock-protocol/hackathon-demo","commit_stats":null,"previous_names":["unlock-protocol/hackathon-demo"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/unlock-protocol/hackathon-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unlock-protocol%2Fhackathon-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unlock-protocol%2Fhackathon-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unlock-protocol%2Fhackathon-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unlock-protocol%2Fhackathon-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unlock-protocol","download_url":"https://codeload.github.com/unlock-protocol/hackathon-demo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unlock-protocol%2Fhackathon-demo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32986694,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T13:14:54.681Z","status":"ssl_error","status_checked_at":"2026-05-13T13:14:51.610Z","response_time":115,"last_error":"SSL_read: 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":"2024-11-13T11:48:01.105Z","updated_at":"2026-05-13T14:31:28.962Z","avatar_url":"https://github.com/unlock-protocol.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Install deps:\n\n```bash\nyarn add wagmi@0.12.0 ethers@5 @unlock-protocol/paywall @unlock-protocol/networks @unlock-protocol/contracts\n```\n\n# Update App.js to include wagmi config\n\nThis is not Unlock specific:\n\nAdd a constant to `constants.ts` for the network we will use.\n\n```js\nexport const NETWORK = 5 // also called chain id\n```\n\n```jsx\nimport { WagmiConfig, createClient} from 'wagmi'\nimport { AppProps } from 'next/app'\nimport '../styles/index.css'\nimport { ethers } from 'ethers'\nimport { NETWORK } from '../lib/constants'\n\n// Create a WAGMI client\nconst wagmiClient = createClient({\n  // Unlock provides some RPC providers but you can use your own!\n  provider: new ethers.providers.JsonRpcProvider(`https://rpc.unlock-protocol.com/${NETWORK}`, NETWORK),\n})\n\nexport default function MyApp({ Component, pageProps }: AppProps) {\n  return \u003cWagmiConfig client={wagmiClient}\u003e\n    \u003cComponent {...pageProps} /\u003e\n  \u003c/WagmiConfig\u003e\n}\n\n```\n\n# Add a `TokenGate` component:\n\nThis component is in fact pretty simple:\n\n- It wraps any component that needs to be token-gated\n- It checks the \"status\" of the user (has a membership or not), if the user is connected\n- If the user is not connected, it renders a subcomponent to prompt the user to connect\n- If the user is connected and they do NOT have a membership NFT, it renders a `Checkout` sub-component that promps them to purchase a membership!\n- If the user is connected AND they have a membership, it renders he children!\n\n```tsx\nimport { useAccount, useConnect, useContractRead } from \"wagmi\"\nimport {InjectedConnector} from \"wagmi/connectors/injected\"\nimport { PublicLockV13 } from \"@unlock-protocol/contracts\"\nimport { LOCK, NETWORK } from \"../lib/constants\"\nimport { ethers } from \"ethers\"\nimport { Paywall } from \"@unlock-protocol/paywall\"\nimport networks from '@unlock-protocol/networks'\n\n\nexport const TokenGate = ({children}) =\u003e {\n  const {isConnected, address} = useAccount()\n\n  const {data: isMember, isError, isLoading} = useContractRead({\n    address: LOCK,\n    abi: PublicLockV13.abi,\n    functionName: 'balanceOf',\n    chainId: NETWORK,\n    enabled: !!address,\n    args: [address],\n    watch: true,\n    select: (data: ethers.BigNumber) =\u003e {\n      return data.gt(0)\n    }\n  })\n\n  if (isLoading) {\n    return \u003cdiv\u003eLoading...\u003c/div\u003e\n  }\n  \n  if (isError) {\n    return \u003cdiv\u003eThere was an error checking your membership status. Please reload the page!\u003c/div\u003e\n  }\n\n  // User not connected\n  if (!isConnected)  {\n    return \u003cConnect /\u003e\n  }\n\n  // User does not have membership\n  if (!isMember) {\n    return \u003cCheckout /\u003e\n  }\n\n  // All good: user is connected and they have a membership!\n  return children\n}\n\n/**\n * Connect subcomponent!\n * @returns \n */\nconst Connect = () =\u003e {\n  const {connect} = useConnect({\n    connector: new InjectedConnector()\n  })\n  return \u003csection\u003e\n    \u003cp className=\"mb-4\"\u003eTo view this post you need to be be a member!\u003c/p\u003e\n    \u003cbutton onClick={() =\u003e  connect()} className=\"bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded\"\u003e\n        Sign-In\n      \u003c/button\u003e\n    \u003c/section\u003e\n}\n\n/**\n * Checkout subcomponent!\n * @returns \n */\nconst Checkout = () =\u003e {\n  const {connector} = useAccount()\n  const checkout = () =\u003e {\n    const paywall = new Paywall(networks)\n    const provider = connector!.provider\n    paywall.connect(provider)\n    paywall.loadCheckoutModal({\n      locks: {\n        [LOCK]: {\n          network: NETWORK,\n        }\n      },\n      pessimistic: true,\n    })\n  }\n\n  return  (\n    \u003csection\u003e\n      \u003cp className=\"mb-4\"\u003eYou currently don't have a membership... \u003c/p\u003e\n      \u003cbutton onClick={() =\u003e  checkout()} className=\"bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded\"\u003e\n        Purchase one now!\n      \u003c/button\u003e\n    \u003c/section\u003e\n  )\n}\n\n```\n\n# Wrap the components that renders the content\n\nWe just replace `post-body.tsx` with this:\n\n```tsx\n\nimport { TokenGate } from './token-gate'\nimport markdownStyles from './markdown-styles.module.css'\n\ntype Props = {\n  content: string\n}\n\nconst PostBody = ({ content }: Props) =\u003e {\n  return (\n    \u003cdiv className=\"max-w-2xl mx-auto\"\u003e\n      \u003cTokenGate\u003e\n        \u003cdiv\n          className={markdownStyles['markdown']}\n          dangerouslySetInnerHTML={{ __html: content }}\n        /\u003e\n      \u003c/TokenGate\u003e\n    \u003c/div\u003e\n  )\n}\n\nexport default PostBody\n\n```\n\n# That's it!\n\nPlease jump in [Unlock's Discord](https://discord.unlock-protocol.com/) if you have any question!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funlock-protocol%2Fhackathon-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funlock-protocol%2Fhackathon-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funlock-protocol%2Fhackathon-demo/lists"}