diff --git a/public/index.html b/public/index.html index aa069f2..e71286e 100644 --- a/public/index.html +++ b/public/index.html @@ -4,40 +4,10 @@ - - - - - - - React App + + AFOUAGMI -
- - +
diff --git a/src/App.js b/src/App.js index 3e1ef06..b069528 100644 --- a/src/App.js +++ b/src/App.js @@ -3,16 +3,16 @@ import { WagmiConfig, createClient, useAccount, useConnect, useDisconnect, useContractReads, configureChains, useContractWrite, usePrepareContractWrite, - useWaitForTransaction + useWaitForTransaction, useContractRead } from 'wagmi'; import { localhost, goerli } from 'wagmi/chains'; import { publicProvider } from 'wagmi/providers/public'; import { InjectedConnector } from 'wagmi/connectors/injected'; +import { readContract } from '@wagmi/core' import { ethers, BigNumber } from 'ethers'; import Noty from 'noty'; import ABI from './abi.json'; -import ERC721ABI from './721a.json'; import 'bulma/css/bulma.min.css'; import 'noty/lib/noty.css'; import 'noty/lib/themes/relax.css'; @@ -32,6 +32,17 @@ const client = createClient({ provider }); +function GetClaimable(contract, tokenId) { + useContractRead({ + ...contract, + functionName: 'winningTokens', + args: [tokenId], + onSuccess(data) { + console.log(data); + } + }); +} + function Contract() { const { address, isConnected } = useAccount(); const { connect } = useConnect({connector}); @@ -48,7 +59,9 @@ function Contract() { balance: 0, hash: '', txPending: false, - tokensSet: '' + tokensSet: '', + winningTokens: '', + claimableTokens: '' }); function handleStateChange(obj) { setOptions(preState => ({...preState , ...obj})); @@ -81,10 +94,22 @@ function Contract() { }); } }); + useContractRead({ + ..._contract, + enabled: options.totalSupply > 0 && options.totalSupply == options.max && options.tokensSet, + functionName: 'getWinningTokens', + watch: true, + cacheTime: 8000, + onSuccess(data) { + handleStateChange({ + winningTokens: JSON.stringify(data) + }); + } + }); const mintPrepare = usePrepareContractWrite({ address: contractAddress, abi: ABI, - enabled: isConnected && options.mintAmount > 0, + enabled: isConnected && options.mintAmount > 0 && options.totalSupply < options.max, functionName: 'mint', args: [options.mintAmount], overrides: { @@ -126,28 +151,56 @@ function Contract() { }).show(); } }); - function checkClaimable(address) { - const raffle = new ethers.Contract(contractAddress, ERC721ABI); - console.log(raffle) - let claimableTokens = []; - for (let i; i < options.balance; i++) { - let token = raffle.tokenOfOwnerByIndex(address, i); - let _i = raffle.winningTokens(token); - console.log(token); - console.log(_i); + async function checkClaimable() { + const tokens = JSON.parse(options.winningTokens); + let claimable = []; + for (let i = 0; i < tokens.length; i++) { + const tokenId = BigNumber.from(tokens[i]).toString(); + const data = await readContract({ + address: contractAddress, + abi: ABI, + functionName: 'ownerOf', + args: [tokenId] + }); + if (data === address) { + claimable.push(tokenId); + } + } + handleStateChange({claimableTokens: JSON.stringify(claimable)}); + if (claimable.length > 0) { + new Noty({ + type: 'success', + text: `Winner! Congratulations, you have ${claimable.length} tokens elligible to claim the Ether prize for.`, + theme: 'relax', + timeout: 8000 + }).show(); + } else { + new Noty({ + type: 'error', + text: `Too bad! None of your tokens are elligible to claim`, + theme: 'relax', + timeout: 8000 + }).show(); } } + if (isConnected && options.phraseSet) return ( <> {options.totalSupply === options.max && options.tokensSet === true && ( - + )} {options.totalSupply === options.max && options.tokensSet === false && ( )} +
+ {JSON.parse(options.claimableTokens).map((tokenId, idx) => ( + + ))} +
+ {options.totalSupply < options.max && (

Price: {ethers.utils.formatEther((options.price * options.mintAmount).toString())} ETH

@@ -178,8 +231,13 @@ function Contract() { )}
+ {options.tokensSet && ( +
+ Tokens have now been specified in the contract. Owners of those tokens can claim the Ether. Congrats to the winners! +
+ )}
- The secret phrase containing the pre-determined winners is: {options.hash} + The secret hash containing the pre-determined winners is: {options.hash}
ETH claims will be made available to winners approximately 48 hours after mint out. diff --git a/src/abi.json b/src/abi.json index f7d55e7..620ddef 100644 --- a/src/abi.json +++ b/src/abi.json @@ -244,6 +244,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "getWinningTokens", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -650,6 +663,25 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "winningTokensIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "withdraw", diff --git a/src/queryable.json b/src/queryable.json new file mode 100644 index 0000000..dae8106 --- /dev/null +++ b/src/queryable.json @@ -0,0 +1,576 @@ +[ + { + "inputs": [], + "name": "ApprovalCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "ApprovalQueryForNonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "BalanceQueryForZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidQueryRange", + "type": "error" + }, + { + "inputs": [], + "name": "MintERC2309QuantityExceedsLimit", + "type": "error" + }, + { + "inputs": [], + "name": "MintToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MintZeroQuantity", + "type": "error" + }, + { + "inputs": [], + "name": "OwnerQueryForNonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "OwnershipNotInitializedForExtraData", + "type": "error" + }, + { + "inputs": [], + "name": "TransferCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFromIncorrectOwner", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToNonERC721ReceiverImplementer", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "URIQueryForNonexistentToken", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "fromTokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "toTokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + } + ], + "name": "ConsecutiveTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "explicitOwnershipOf", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "startTimestamp", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "burned", + "type": "bool" + }, + { + "internalType": "uint24", + "name": "extraData", + "type": "uint24" + } + ], + "internalType": "struct IERC721A.TokenOwnership", + "name": "ownership", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256[]", + "name": "tokenIds", + "type": "uint256[]" + } + ], + "name": "explicitOwnershipsOf", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "startTimestamp", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "burned", + "type": "bool" + }, + { + "internalType": "uint24", + "name": "extraData", + "type": "uint24" + } + ], + "internalType": "struct IERC721A.TokenOwnership[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "tokensOfOwner", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stop", + "type": "uint256" + } + ], + "name": "tokensOfOwnerIn", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +]