diff --git a/package-lock.json b/package-lock.json index 321f5f6..96eaa04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@testing-library/user-event": "^13.5.0", "bulma": "^0.9.4", "ethers": "^5.7.2", + "noty": "^3.2.0-beta-deprecated", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", @@ -15754,6 +15755,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/noty": { + "version": "3.2.0-beta-deprecated", + "resolved": "https://registry.npmjs.org/noty/-/noty-3.2.0-beta-deprecated.tgz", + "integrity": "sha512-ntRbHuQ9SnnnVFZm/oq5L1DBCaHQUvsU24AwZH3PGjAWx2YqR/IhOadMk11vmJovYiQo00oqTj6Hp+D6PGtmLA==", + "deprecated": "no longer supported" + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -33061,6 +33068,11 @@ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" }, + "noty": { + "version": "3.2.0-beta-deprecated", + "resolved": "https://registry.npmjs.org/noty/-/noty-3.2.0-beta-deprecated.tgz", + "integrity": "sha512-ntRbHuQ9SnnnVFZm/oq5L1DBCaHQUvsU24AwZH3PGjAWx2YqR/IhOadMk11vmJovYiQo00oqTj6Hp+D6PGtmLA==" + }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", diff --git a/package.json b/package.json index 773dbf1..0df21ed 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "@testing-library/user-event": "^13.5.0", "bulma": "^0.9.4", "ethers": "^5.7.2", + "noty": "^3.2.0-beta-deprecated", "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", diff --git a/src/721a.json b/src/721a.json new file mode 100644 index 0000000..d41276b --- /dev/null +++ b/src/721a.json @@ -0,0 +1,441 @@ +[ + { + "inputs": [], + "name": "ApprovalCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "ApprovalQueryForNonexistentToken", + "type": "error" + }, + { + "inputs": [], + "name": "BalanceQueryForZeroAddress", + "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": "balance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "operator", + "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": "owner", + "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": [], + "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" + } +] diff --git a/src/App.js b/src/App.js index 7201046..3e1ef06 100644 --- a/src/App.js +++ b/src/App.js @@ -9,8 +9,13 @@ import { localhost, goerli } from 'wagmi/chains'; import { publicProvider } from 'wagmi/providers/public'; import { InjectedConnector } from 'wagmi/connectors/injected'; 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'; const contractAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3"; @@ -42,7 +47,8 @@ function Contract() { mintAmount: 1, balance: 0, hash: '', - txPending: false + txPending: false, + tokensSet: '' }); function handleStateChange(obj) { setOptions(preState => ({...preState , ...obj})); @@ -57,6 +63,7 @@ function Contract() { {..._contract, functionName: 'phraseSet'}, {..._contract, functionName: 'balanceOf', args: [address]}, {..._contract, functionName: 'winningPhraseHash'}, + {..._contract, functionName: 'tokensSet'} ], watch: true, cacheTime: 8000, @@ -69,7 +76,8 @@ function Contract() { winningAmount: Number(data[4]), phraseSet: data[5], balance: Number(data[6]), - hash: data[7].toString() + hash: data[7], + tokensSet: data[8] }); } }); @@ -85,24 +93,62 @@ function Contract() { } }); const mintWrite = useContractWrite({ - ...mintPrepare.config, - onError(data) { - // if (data.message.startsWith('user rejected transaction')) NotificationManager.info(`tx cancelled`, 'ok', 4000); - mintWrite.reset(); - } + ...mintPrepare.config, + onError(data) { + new Noty({ + type: 'error', + text: `Tx rejected`, + theme: 'relax', + timeout: 3000 + }).show(); + mintWrite.reset(); + handleStateChange({txPending: false}); + }, + onSuccess(data) { + new Noty({ + type: 'info', + text: `Tx ${data.hash} sent...pending confirmation`, + theme: 'relax', + timeout: 3000 + }).show(); + } }); useWaitForTransaction({ hash: mintWrite.data?.hash, enabled: mintWrite.status === 'success', - onSuccess() { - handleStateChange({txPending: false}); - mintWrite.reset(); + onSuccess(data) { + handleStateChange({txPending: false}); + new Noty({ + type: 'success', + text: `Tx ${data.transactionHash} confirmed`, + theme: 'relax', + timeout: 3000 + }).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); + } + } if (isConnected && options.phraseSet) return ( <> + {options.totalSupply === options.max && options.tokensSet === true && ( + + )} + {options.totalSupply === options.max && options.tokensSet === false && ( + + )} + + {options.totalSupply < options.max && (

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

@@ -112,24 +158,32 @@ function Contract() { }>
- { +
-

You'll have a ~{(options.balance + options.mintAmount) / options.max * 100}% chance to win 1 ETH

+

You'll have a ~{((options.balance + options.mintAmount) / options.max * 100).toFixed(2)}% chance to win 1 ETH

+ )}
-

Connected to {address.slice(0,6) + '...' + address.slice(-4)} :: You own {options.balance} tokens

-

Minted {options.totalSupply} / {options.max}

+

Connected to {address.slice(0,6) + '...' + address.slice(-4)} :: You own {options.balance} tokens

+

Minted {options.totalSupply} / {options.max} {options.max - options.totalSupply > 0 && ( + <> + ({options.max - options.totalSupply} remaining) + + )}

The secret phrase containing the pre-determined winners is: {options.hash}
+
+ ETH claims will be made available to winners approximately 48 hours after mint out. +
) if (isConnected && !options.phraseSet) diff --git a/src/abi.json b/src/abi.json index dceeb59..f7d55e7 100644 --- a/src/abi.json +++ b/src/abi.json @@ -543,6 +543,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "tokensSet", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "totalSupply",