{"version":3,"sources":["App.jsx","index.js"],"names":["sdk","ThirdwebSDK","bundleDropModule","getBundleDropModule","tokenModule","getTokenModule","voteModule","getVoteModule","App","useWeb3","connectWallet","address","error","provider","console","log","signer","getSigner","undefined","useState","hasClaimedNFT","setHasClaimedNFT","isClaiming","setIsClaiming","memberTokenAmounts","setMemberTokenAmounts","memberAddresses","setMemberAddresses","proposals","setProposals","isVoting","setIsVoting","hasVoted","setHasVoted","useEffect","getAll","then","catch","err","length","proposalId","getAllClaimerAddresses","addresses","getAllHolderBalances","amounts","memberList","useMemo","map","tokenAmount","ethers","utils","formatUnits","setProviderOrSigner","balanceOf","balance","gt","UnsupportedChainIdError","className","onClick","member","str","substring","onSubmit","e","a","preventDefault","stopPropagation","votes","proposal","voteResult","vote","forEach","document","getElementById","type","checked","getDelegationOf","constants","AddressZero","delegateTo","Promise","all","get","state","execute","index","description","id","name","value","defaultChecked","htmlFor","label","disabled","claim","finally","ReactDOM","render","StrictMode","connectors","injected","supportedChainIds"],"mappings":"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","file":"static/js/main.9b4f54a5.chunk.js","sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\n\n// import thirdweb\nimport { useWeb3 } from \"@3rdweb/hooks\";\n\nimport { ethers } from \"ethers\";\n\nimport { UnsupportedChainIdError } from \"@web3-react/core\";\n\n// import SDK\nimport { ThirdwebSDK } from \"@3rdweb/sdk\";\n// We instantiate the sdk on Rinkeby.\nconst sdk = new ThirdwebSDK(\"rinkeby\");\n\n// We can grab a reference to our ERC-1155 contract.\nconst bundleDropModule = sdk.getBundleDropModule(\n \"0x5B6F611017301Cf56E1A32A05c19B4c703592D68\",\n);\n\nconst tokenModule = sdk.getTokenModule(\n \"0x2f62C99C4ae403F0A389f714a727cCcB98ab43b8\"\n);\n\nconst voteModule = sdk.getVoteModule(\n \"0x888A470e2927d557c91eb2F9Df075Fa1cf21e80C\",\n);\n\nconst App = () => {\n // Use the connectWallet hook thirdweb gives us.\n const { connectWallet, address, error, provider } = useWeb3();\n console.log(\"👋 Address:\", address)\n\n // The signer is required to sign transactions on the blockchain.\n // Without it we can only read data, not write.\n const signer = provider ? provider.getSigner() : undefined;\n \n // State variable for us to know if user has our NFT.\n const [hasClaimedNFT, setHasClaimedNFT] = useState(false);\n\n // isClaiming lets us easily keep a loading state while the NFT is minting.\n const [isClaiming, setIsClaiming] = useState(false);\n\n // Holds the amount of token each member has in state.\n const [memberTokenAmounts, setMemberTokenAmounts] = useState({});\n // The array holding all of our members addresses.\n const [memberAddresses, setMemberAddresses] = useState([]);\n\n\n const [proposals, setProposals] = useState([]);\n const [isVoting, setIsVoting] = useState(false);\n const [hasVoted, setHasVoted] = useState(false);\n\n\n // Retrieve all our existing proposals from the contract.\n useEffect(() => {\n if (!hasClaimedNFT) {\n return;\n }\n // A simple call to voteModule.getAll() to grab the proposals.\n voteModule\n .getAll()\n .then((proposals) => {\n // Set state!\n setProposals(proposals);\n console.log(\"🌈 Proposals:\", proposals)\n })\n .catch((err) => {\n console.error(\"failed to get proposals\", err);\n });\n }, [hasClaimedNFT]);\n\n // We also need to check if the user already voted.\n useEffect(() => {\n if (!hasClaimedNFT) {\n return;\n }\n\n // If we haven't finished retrieving the proposals from the useEffect above\n // then we can't check if the user voted yet!\n if (!proposals.length) {\n return;\n }\n\n // Check if the user has already voted on the first proposal.\n voteModule\n .hasVoted(proposals[0].proposalId, address)\n .then((hasVoted) => {\n setHasVoted(hasVoted);\n if (hasVoted) {\n console.log(\"🥵 User has already voted\");\n } else {\n console.log(\"🙂 User has not voted yet\");\n }\n })\n .catch((err) => {\n console.error(\"failed to check if wallet has voted\", err);\n });\n }, [hasClaimedNFT, proposals, address]);\n\n // A fancy function to shorten someones wallet address, no need to show the whole thing. \n const shortenAddress = (str) => {\n return str.substring(0, 6) + \"...\" + str.substring(str.length - 4);\n };\n\n // This useEffect grabs all the addresses of our members holding our NFT.\n useEffect(() => {\n if (!hasClaimedNFT) {\n return;\n }\n \n // Just like we did in the 7-airdrop-token.js file! Grab the users who hold our NFT\n // with tokenId 0.\n bundleDropModule\n .getAllClaimerAddresses(\"0\")\n .then((addresses) => {\n console.log(\"🚀 Members addresses\", addresses)\n setMemberAddresses(addresses);\n })\n .catch((err) => {\n console.error(\"failed to get member list\", err);\n });\n }, [hasClaimedNFT]);\n\n // This useEffect grabs the # of token each member holds.\n useEffect(() => {\n if (!hasClaimedNFT) {\n return;\n }\n\n // Grab all the balances.\n tokenModule\n .getAllHolderBalances()\n .then((amounts) => {\n console.log(\"👜 Amounts\", amounts)\n setMemberTokenAmounts(amounts);\n })\n .catch((err) => {\n console.error(\"failed to get token amounts\", err);\n });\n }, [hasClaimedNFT]);\n\n // Now, we combine the memberAddresses and memberTokenAmounts into a single array\n const memberList = useMemo(() => {\n return memberAddresses.map((address) => {\n return {\n address,\n tokenAmount: ethers.utils.formatUnits(\n // If the address isn't in memberTokenAmounts, it means they don't\n // hold any of our token.\n memberTokenAmounts[address] || 0,\n 18,\n ),\n };\n });\n }, [memberAddresses, memberTokenAmounts]);\n // Another useEffect!\n useEffect(() => {\n // We pass the signer to the sdk, which enables us to interact with\n // our deployed contract!\n sdk.setProviderOrSigner(signer);\n }, [signer]);\n\n useEffect(() => {\n // If they don't have an connected wallet, exit!\n if (!address) {\n return;\n }\n \n // Check if the user has the NFT by using bundleDropModule.balanceOf\n return bundleDropModule\n .balanceOf(address, \"0\")\n .then((balance) => {\n // If balance is greater than 0, they have our NFT!\n if (balance.gt(0)) {\n setHasClaimedNFT(true);\n console.log(\"🌟 this user has a membership NFT!\")\n } else {\n setHasClaimedNFT(false);\n console.log(\"😭 this user doesn't have a membership NFT.\")\n }\n })\n .catch((error) => {\n setHasClaimedNFT(false);\n console.error(\"failed to nft balance\", error);\n });\n }, [address]);\n\n\n if (error instanceof UnsupportedChainIdError ) {\n return (\n
\n

Please connect to Rinkeby

\n

\n This dapp only works on the Rinkeby network, please switch networks\n in your connected wallet.\n

\n
\n );\n }\n \n // This is the case where the user hasn't connected their wallet\n // to your web app. Let them call connectWallet.\n if (!address) {\n return (\n
\n

Welcome to QuitSmokingDAO

\n \n
\n );\n }\n // This is the case where we have the user's address\n // which means they've connected their wallet to our site!\n\n\n const mintNft = () => {\n setIsClaiming(true);\n // Call bundleDropModule.claim(\"0\", 1) to mint nft to user's wallet.\n bundleDropModule\n .claim(\"0\", 1)\n .then(() => {\n // Set claim state.\n setHasClaimedNFT(true);\n // Show user their fancy new NFT!\n console.log(\n `🌊 Successfully Minted! Check it our on OpenSea: https://testnets.opensea.io/assets/${bundleDropModule.address}/0`\n );\n })\n .catch((err) => {\n console.error(\"failed to claim\", err);\n })\n .finally(() => {\n // Stop loading state.\n setIsClaiming(false);\n });\n }\n\n\n \n\n // Add this little piece!\n // If the user has already claimed their NFT we want to display the interal DAO page to them\n // only DAO members will see this. Render all the members + token amounts.\n // If the user has already claimed their NFT we want to display the interal DAO page to them\n // only DAO members will see this. Render all the members + token amounts.\n if (hasClaimedNFT) {\n return (\n
\n

QuitSmokingDAO Member Page

\n

Congratulations on being a member

\n
\n
\n

Member List

\n \n \n \n \n \n \n \n \n {memberList.map((member) => {\n return (\n \n \n \n \n );\n })}\n \n
AddressToken Amount
{shortenAddress(member.address)}{member.tokenAmount}
\n
\n
\n

Active Proposals

\n {\n e.preventDefault();\n e.stopPropagation();\n\n //before we do async things, we want to disable the button to prevent double clicks\n setIsVoting(true);\n\n // lets get the votes from the form for the values\n const votes = proposals.map((proposal) => {\n let voteResult = {\n proposalId: proposal.proposalId,\n //abstain by default\n vote: 2,\n };\n proposal.votes.forEach((vote) => {\n const elem = document.getElementById(\n proposal.proposalId + \"-\" + vote.type\n );\n\n if (elem.checked) {\n voteResult.vote = vote.type;\n return;\n }\n });\n return voteResult;\n });\n\n // first we need to make sure the user delegates their token to vote\n try {\n //we'll check if the wallet still needs to delegate their tokens before they can vote\n const delegation = await tokenModule.getDelegationOf(address);\n // if the delegation is the 0x0 address that means they have not delegated their governance tokens yet\n if (delegation === ethers.constants.AddressZero) {\n //if they haven't delegated their tokens yet, we'll have them delegate them before voting\n await tokenModule.delegateTo(address);\n }\n // then we need to vote on the proposals\n try {\n await Promise.all(\n votes.map(async (vote) => {\n // before voting we first need to check whether the proposal is open for voting\n // we first need to get the latest state of the proposal\n const proposal = await voteModule.get(vote.proposalId);\n // then we check if the proposal is open for voting (state === 1 means it is open)\n if (proposal.state === 1) {\n // if it is open for voting, we'll vote on it\n return voteModule.vote(vote.proposalId, vote.vote);\n }\n // if the proposal is not open for voting we just return nothing, letting us continue\n return;\n })\n );\n try {\n // if any of the propsals are ready to be executed we'll need to execute them\n // a proposal is ready to be executed if it is in state 4\n await Promise.all(\n votes.map(async (vote) => {\n // we'll first get the latest state of the proposal again, since we may have just voted before\n const proposal = await voteModule.get(\n vote.proposalId\n );\n\n //if the state is in state 4 (meaning that it is ready to be executed), we'll execute the proposal\n if (proposal.state === 4) {\n return voteModule.execute(vote.proposalId);\n }\n })\n );\n // if we get here that means we successfully voted, so let's set the \"hasVoted\" state to true\n setHasVoted(true);\n // and log out a success message\n console.log(\"successfully voted\");\n } catch (err) {\n console.error(\"failed to execute votes\", err);\n }\n } catch (err) {\n console.error(\"failed to vote\", err);\n }\n } catch (err) {\n console.error(\"failed to delegate tokens\");\n } finally {\n // in *either* case we need to set the isVoting state to false to enable the button again\n setIsVoting(false);\n }\n }}\n >\n {proposals.map((proposal, index) => (\n
\n
{proposal.description}
\n
\n {proposal.votes.map((vote) => (\n
\n \n \n
\n ))}\n
\n
\n ))}\n \n \n This will trigger multiple transactions that you will need to\n sign.\n \n \n
\n
\n
\n );\n };\n\n // Render mint nft screen.\n return (\n
\n

Welcome to QuitSmokingDAO !

\n

Mint your free QuitSmokingDAO Membership NFT

\n mintNft()}\n >\n {isClaiming ? \"Minting...\" : \"Mint your nft (FREE)\"}\n \n
\n );\n\n};\n\nexport default App;\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport \"./index.css\";\nimport App from \"./App.jsx\";\n\n// Import ThirdWeb\nimport { ThirdwebWeb3Provider } from '@3rdweb/hooks';\n\n// Include what chains you wanna support.\n// 4 = Rinkeby.\nconst supportedChainIds = [4];\n\n// Include what type of wallet you want to support.\n// In this case, we support Metamask which is an \"injected wallet\".\nconst connectors = {\n injected: {},\n};\n\n// Render the App component to the DOM\n// Finally, wrap App with ThirdwebWeb3Provider.\nReactDOM.render(\n \n \n \n \n ,\n document.getElementById(\"root\")\n);\n"],"sourceRoot":""}