├── .eslintrc.json ├── public ├── favicon.ico ├── images │ ├── bg_tile.png │ └── logo_commsaur.png └── fonts │ ├── SF-Pro-Rounded-Black.otf │ ├── SF-Pro-Rounded-Bold.otf │ ├── SF-Pro-Rounded-Heavy.otf │ ├── SF-Pro-Rounded-Light.otf │ ├── SF-Pro-Rounded-Thin.otf │ ├── SF-Pro-Rounded-Medium.otf │ ├── SF-Pro-Rounded-Regular.otf │ ├── SF-Pro-Rounded-Semibold.otf │ └── SF-Pro-Rounded-Ultralight.otf ├── postcss.config.js ├── next-env.d.ts ├── next.config.js ├── abis ├── commsaur.ts ├── commsaur_pfp_abi.json └── commsaur_abi.json ├── tailwind.config.js ├── pages ├── api │ └── hello.ts ├── _document.tsx ├── _app.tsx └── index.tsx ├── .gitignore ├── tsconfig.json ├── hooks ├── useCommsaurData.ts └── useContractBigNumber.ts ├── package.json ├── components ├── icons │ └── DownloadIcon.tsx ├── LoadingSpinner.tsx ├── CommsaurRow.tsx ├── ToolContainer.tsx ├── UnwrapButton.tsx ├── CommsaurProvider.tsx ├── WrapButton.tsx └── CommsaurComponent.tsx ├── styles └── globals.css └── README.md /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exception/commsaur-tooling/master/public/favicon.ico -------------------------------------------------------------------------------- /public/images/bg_tile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exception/commsaur-tooling/master/public/images/bg_tile.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /public/images/logo_commsaur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exception/commsaur-tooling/master/public/images/logo_commsaur.png -------------------------------------------------------------------------------- /public/fonts/SF-Pro-Rounded-Black.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exception/commsaur-tooling/master/public/fonts/SF-Pro-Rounded-Black.otf -------------------------------------------------------------------------------- /public/fonts/SF-Pro-Rounded-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exception/commsaur-tooling/master/public/fonts/SF-Pro-Rounded-Bold.otf -------------------------------------------------------------------------------- /public/fonts/SF-Pro-Rounded-Heavy.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exception/commsaur-tooling/master/public/fonts/SF-Pro-Rounded-Heavy.otf -------------------------------------------------------------------------------- /public/fonts/SF-Pro-Rounded-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exception/commsaur-tooling/master/public/fonts/SF-Pro-Rounded-Light.otf -------------------------------------------------------------------------------- /public/fonts/SF-Pro-Rounded-Thin.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exception/commsaur-tooling/master/public/fonts/SF-Pro-Rounded-Thin.otf -------------------------------------------------------------------------------- /public/fonts/SF-Pro-Rounded-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exception/commsaur-tooling/master/public/fonts/SF-Pro-Rounded-Medium.otf -------------------------------------------------------------------------------- /public/fonts/SF-Pro-Rounded-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exception/commsaur-tooling/master/public/fonts/SF-Pro-Rounded-Regular.otf -------------------------------------------------------------------------------- /public/fonts/SF-Pro-Rounded-Semibold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exception/commsaur-tooling/master/public/fonts/SF-Pro-Rounded-Semibold.otf -------------------------------------------------------------------------------- /public/fonts/SF-Pro-Rounded-Ultralight.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exception/commsaur-tooling/master/public/fonts/SF-Pro-Rounded-Ultralight.otf -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | reactStrictMode: true, 4 | images: { 5 | domains: ['commsaur.mypinata.cloud', 'd124myd65w4vuo.cloudfront.net'], 6 | }, 7 | }; 8 | 9 | module.exports = nextConfig; 10 | -------------------------------------------------------------------------------- /abis/commsaur.ts: -------------------------------------------------------------------------------- 1 | export const commsaurAddress: string = process.env.NODE_ENV === 'production' ? '0xbacb34bcf94442dba033e9cf7216888b8170f0ce' : '0x5FbDB2315678afecb367f032d93F642f64180aa3'; 2 | export const pfpAddress: string = process.env.NODE_ENV === 'production' ? '0x664dc1247848F1AddD2065009eBF9974b3BE7a81' : '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512'; -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: [ 3 | './pages/**/*.{js,ts,jsx,tsx}', 4 | './components/**/*.{js,ts,jsx,tsx}', 5 | ], 6 | theme: { 7 | extend: { 8 | fontFamily: { 9 | 'sf-rounded': '"SFRounded"', 10 | }, 11 | }, 12 | }, 13 | plugins: [], 14 | }; 15 | -------------------------------------------------------------------------------- /pages/api/hello.ts: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | import type { NextApiRequest, NextApiResponse } from 'next' 3 | 4 | type Data = { 5 | name: string 6 | } 7 | 8 | export default function handler( 9 | req: NextApiRequest, 10 | res: NextApiResponse 11 | ) { 12 | res.status(200).json({ name: 'John Doe' }) 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true 17 | }, 18 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 19 | "exclude": ["node_modules"] 20 | } 21 | -------------------------------------------------------------------------------- /hooks/useCommsaurData.ts: -------------------------------------------------------------------------------- 1 | import { Commsaur } from "../components/CommsaurProvider"; 2 | const rarities: RarityData[] = require('../rarity.json'); 3 | 4 | interface RarityData { 5 | id: number; 6 | rank: number; 7 | rarity_score: number; 8 | traits: Trait[]; 9 | } 10 | 11 | type Trait = { 12 | trait_type: string; 13 | trait_value: string; 14 | percent: number; 15 | count: number; 16 | } 17 | 18 | function useCommsaurData(dino: Commsaur): RarityData { 19 | const rarity = rarities.filter(saur => saur.id == dino.id)[0]; 20 | return rarity; 21 | } 22 | 23 | export default useCommsaurData; -------------------------------------------------------------------------------- /pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import Document, { 2 | Html, 3 | Main, 4 | NextScript, 5 | DocumentContext, 6 | Head, 7 | } from 'next/document'; 8 | 9 | class MyDocument extends Document { 10 | static async getInitialProps(ctx: DocumentContext) { 11 | const initialProps = await Document.getInitialProps(ctx); 12 | return { ...initialProps }; 13 | } 14 | 15 | render() { 16 | return ( 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | ); 25 | } 26 | } 27 | 28 | export default MyDocument; 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "commsaur-utility", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@headlessui/react": "^1.6.1", 13 | "@rainbow-me/rainbowkit": "^0.1.0", 14 | "ethers": "^5.6.5", 15 | "next": "12.1.6", 16 | "react": "18.1.0", 17 | "react-dom": "18.1.0", 18 | "wagmi": "^0.3.5" 19 | }, 20 | "devDependencies": { 21 | "@types/node": "17.0.31", 22 | "@types/react": "18.0.9", 23 | "@types/react-dom": "18.0.3", 24 | "autoprefixer": "^10.4.7", 25 | "eslint": "8.15.0", 26 | "eslint-config-next": "12.1.6", 27 | "postcss": "^8.4.13", 28 | "tailwindcss": "^3.0.24", 29 | "typescript": "4.6.4" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /components/icons/DownloadIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | type Props = { 4 | onClick: () => void; 5 | }; 6 | 7 | function DownloadIcon({ onClick }: Props) { 8 | return ( 9 | 18 | 23 | 24 | ); 25 | } 26 | 27 | export default React.memo(DownloadIcon); 28 | -------------------------------------------------------------------------------- /components/LoadingSpinner.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | function LoadingSpinner() { 4 | return ( 5 | 11 | 19 | 24 | 25 | ); 26 | } 27 | 28 | export default React.memo(LoadingSpinner); 29 | -------------------------------------------------------------------------------- /hooks/useContractBigNumber.ts: -------------------------------------------------------------------------------- 1 | import { ReadContractConfig } from "@wagmi/core"; 2 | import { BigNumber, ContractInterface } from "ethers"; 3 | import { useState } from "react"; 4 | import { useContractRead } from "wagmi"; 5 | 6 | type CallData = { 7 | address: string; 8 | abi: ContractInterface; 9 | } 10 | 11 | type ContractNumberRead = { 12 | value: number; 13 | isLoading: boolean; 14 | error: Error | null; 15 | refetch: () => void; 16 | } 17 | 18 | function useContractBigNumber({ address, abi }: CallData, methodName: string, args: ReadContractConfig, enabled: boolean): ContractNumberRead { 19 | const [out, setOut] = useState(-1); 20 | const { isLoading, error, refetch } = useContractRead( 21 | { 22 | addressOrName: address, 23 | contractInterface: abi, 24 | }, 25 | methodName, 26 | { 27 | ...args, 28 | enabled, 29 | watch: true, 30 | onSuccess (data) { 31 | if ('_hex' in data) { 32 | const num = data as unknown as BigNumber; 33 | const id = num.toNumber(); 34 | 35 | setOut(id) 36 | } 37 | } 38 | }, 39 | ); 40 | 41 | return { value: out, isLoading, error, refetch }; 42 | } 43 | 44 | export default useContractBigNumber; -------------------------------------------------------------------------------- /components/CommsaurRow.tsx: -------------------------------------------------------------------------------- 1 | import Image from 'next/image'; 2 | import React from 'react'; 3 | import useCommsaurData from '../hooks/useCommsaurData'; 4 | import { Commsaur, getDinoImage } from './CommsaurProvider'; 5 | 6 | type Props = { 7 | dino: Commsaur; 8 | choose: (dino: number) => void; 9 | selected: boolean; 10 | }; 11 | 12 | function CommsaurRow({ dino, choose, selected }: Props) { 13 | const rarity = useCommsaurData(dino); 14 | 15 | return ( 16 |
choose(dino.id)} 18 | className={`flex flex-row space-x-2 px-2 py-2 mb-1 items-center cursor-pointer hover:scale-[.98] transition-all duration-100 ease-in-out ${ 19 | selected && 'bg-slate-900/60' 20 | } rounded-xl`} 21 | > 22 | {`Commsaur 29 |
30 |

31 | {`Commsaur #${dino.id}`} 32 |

33 |

34 | Rank #{rarity.rank} {dino.wrapped && ' (wrapped)'} 35 |

36 |
37 |
38 | ); 39 | } 40 | 41 | export default CommsaurRow; 42 | -------------------------------------------------------------------------------- /pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import '../styles/globals.css'; 2 | import type { AppProps } from 'next/app'; 3 | import '@rainbow-me/rainbowkit/styles.css'; 4 | import { 5 | apiProvider, 6 | configureChains, 7 | connectorsForWallets, 8 | darkTheme, 9 | getDefaultWallets, 10 | RainbowKitProvider, 11 | wallet, 12 | } from '@rainbow-me/rainbowkit'; 13 | import { chain, createClient, WagmiProvider } from 'wagmi'; 14 | 15 | const { chains, provider } = configureChains( 16 | [process.env.NODE_ENV === 'production' ? chain.mainnet : chain.hardhat], 17 | [ 18 | apiProvider.alchemy('nzLJjKrtgPGbidugKn5S6G8o9RFnsxnv'), 19 | apiProvider.jsonRpc((chain) => ({ 20 | rpcUrl: chain.rpcUrls.default, 21 | })), 22 | ], 23 | ); 24 | 25 | const { wallets } = getDefaultWallets({ 26 | appName: 'Commsaur', 27 | chains, 28 | }); 29 | 30 | const connectors = connectorsForWallets([ 31 | ...wallets, 32 | { 33 | groupName: 'More', 34 | wallets: [wallet.ledger({ chains }), wallet.argent({ chains })], 35 | }, 36 | ]); 37 | 38 | const wagmiClient = createClient({ 39 | autoConnect: true, 40 | connectors, 41 | provider, 42 | }); 43 | 44 | function MyApp({ Component, pageProps }: AppProps) { 45 | return ( 46 | 47 | 48 | 49 | 50 | 51 | ); 52 | } 53 | 54 | export default MyApp; 55 | -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer base { 6 | @font-face { 7 | font-family: 'SFRounded'; 8 | src: url('/fonts/SF-Pro-Rounded-Regular.otf') format("opentype"); 9 | font-weight: 400; 10 | } 11 | 12 | @font-face { 13 | font-family: 'SFRounded'; 14 | src: url('/fonts/SF-Pro-Rounded-Thin.otf') format("opentype"); 15 | font-weight: 100; 16 | } 17 | 18 | @font-face { 19 | font-family: 'SFRounded'; 20 | src: url('/fonts/SF-Pro-Rounded-Ultralight.otf') format("opentype"); 21 | font-weight: 200; 22 | } 23 | 24 | @font-face { 25 | font-family: 'SFRounded'; 26 | src: url('/fonts/SF-Pro-Rounded-Light.otf') format("opentype"); 27 | font-weight: 300; 28 | } 29 | 30 | @font-face { 31 | font-family: 'SFRounded'; 32 | src: url('/fonts/SF-Pro-Rounded-Medium.otf') format("opentype"); 33 | font-weight: 500; 34 | } 35 | 36 | @font-face { 37 | font-family: 'SFRounded'; 38 | src: url('/fonts/SF-Pro-Rounded-Semibold.otf') format("opentype"); 39 | font-weight: 600; 40 | } 41 | 42 | @font-face { 43 | font-family: 'SFRounded'; 44 | src: url('/fonts/SF-Pro-Rounded-Bold.otf') format("opentype"); 45 | font-weight: 700; 46 | } 47 | 48 | @font-face { 49 | font-family: 'SFRounded'; 50 | src: url('/fonts/SF-Pro-Rounded-Heavy.otf') format("opentype"); 51 | font-weight: 800; 52 | } 53 | 54 | @font-face { 55 | font-family: 'SFRounded'; 56 | src: url('/fonts/SF-Pro-Rounded-Black.otf') format("opentype"); 57 | font-weight: 900; 58 | } 59 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | ``` 12 | 13 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 14 | 15 | You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. 16 | 17 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. 18 | 19 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. 20 | 21 | ## Learn More 22 | 23 | To learn more about Next.js, take a look at the following resources: 24 | 25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 27 | 28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 29 | 30 | ## Deploy on Vercel 31 | 32 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 33 | 34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 35 | -------------------------------------------------------------------------------- /components/ToolContainer.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { useAccount } from 'wagmi'; 3 | import CommsaurComponent from './CommsaurComponent'; 4 | import { useCommsaurContext } from './CommsaurProvider'; 5 | import CommsaurRow from './CommsaurRow'; 6 | 7 | function ToolContainer() { 8 | const { data: account } = useAccount(); 9 | const { originalSize: commsaurAmount, herd, reset } = useCommsaurContext(); 10 | useEffect(() => { 11 | if (!account && herd.length > 0) { 12 | reset(); 13 | } 14 | }, [account, herd, reset]); 15 | useEffect(() => { 16 | console.log(herd); 17 | }, [herd]); 18 | const [commsaur, setCommsaur] = useState(-1); 19 | 20 | return ( 21 |
22 |
23 |

24 | Your Commsaurs{' '} 25 | ({commsaurAmount}) 26 |

27 | {herd.length != commsaurAmount && ( 28 |

29 | Herding {herd.length}/{commsaurAmount}... 30 |

31 | )} 32 |
33 | {herd.map((dino) => ( 34 | 40 | ))} 41 |
42 |
43 |
44 | {commsaur == -1 && ( 45 |
46 |

47 | Select one of your Commsaurs to access it's 48 | tools! 49 |

50 |
51 | )} 52 | {commsaur >= 0 && ( 53 |
54 | saur.id == commsaur)!} 56 | /> 57 |
58 | )} 59 |
60 |
61 | ); 62 | } 63 | 64 | export default ToolContainer; 65 | -------------------------------------------------------------------------------- /pages/index.tsx: -------------------------------------------------------------------------------- 1 | import { ConnectButton } from '@rainbow-me/rainbowkit'; 2 | import type { NextPage } from 'next'; 3 | import Head from 'next/head'; 4 | import { useAccount } from 'wagmi'; 5 | import { useEffect, useState } from 'react'; 6 | import CommsaurProvider from '../components/CommsaurProvider'; 7 | import ToolContainer from '../components/ToolContainer'; 8 | 9 | const Home: NextPage = () => { 10 | const { data: account } = useAccount(); 11 | const [hasAccount, setHasAccount] = useState(false); 12 | useEffect(() => { 13 | setHasAccount(!!account); 14 | }, [account]); 15 | 16 | return ( 17 | <> 18 | 19 | Commsaur Tools 20 | 21 |
22 | {!hasAccount && ( 23 |
24 |

25 | Commsaur Tools 26 |

27 |

28 | Connect your wallet to access the Commsaur tools, 29 | wrap your Commsaur into it's PFP version, 30 | download high-res JPEGs, and more! 31 |

32 | 33 | 34 | {({ 35 | mounted, 36 | account, 37 | chain, 38 | openConnectModal, 39 | openChainModal, 40 | openAccountModal, 41 | }) => { 42 | if (!mounted || !account || !chain) { 43 | return ( 44 | 52 | ); 53 | } 54 | 55 | if (chain.unsupported) { 56 | return ( 57 | 65 | ); 66 | } 67 | 68 | return ( 69 | 77 | ); 78 | }} 79 | 80 |
81 | )} 82 | {hasAccount && ( 83 | 84 | 85 | 86 | )} 87 |
88 | 89 | ); 90 | }; 91 | 92 | export default Home; 93 | -------------------------------------------------------------------------------- /components/UnwrapButton.tsx: -------------------------------------------------------------------------------- 1 | import React, { useCallback, useState } from 'react'; 2 | import { 3 | useAccount, 4 | useContractRead, 5 | useContractWrite, 6 | useWaitForTransaction, 7 | } from 'wagmi'; 8 | import { pfpAddress } from '../abis/commsaur'; 9 | import { Commsaur, useCommsaurContext } from './CommsaurProvider'; 10 | import pfpAbi from '../abis/commsaur_pfp_abi.json'; 11 | import { useAddRecentTransaction } from '@rainbow-me/rainbowkit'; 12 | import LoadingSpinner from './LoadingSpinner'; 13 | 14 | type Props = { 15 | dino: Commsaur; 16 | setError: (error: string) => void; 17 | }; 18 | 19 | function UnwrapButton({ dino, setError }: Props) { 20 | const { data: account } = useAccount(); 21 | const [isApproved, setIsApproved] = useState(false); 22 | const addRecent = useAddRecentTransaction(); 23 | const [transactionHash, setTransactionHash] = useState(); 24 | const [wasUnwrapped, setWasUnwrapped] = useState(false); 25 | const [approveHash, setApproveHash] = useState(); 26 | const { toggleWrapped } = useCommsaurContext(); 27 | 28 | const { isLoading: useTransactionSending } = useWaitForTransaction({ 29 | hash: transactionHash, 30 | enabled: !!transactionHash, 31 | onSuccess() { 32 | toggleWrapped(dino.id, false); 33 | setWasUnwrapped(true); 34 | }, 35 | }); 36 | 37 | const { isLoading: isApproving } = useWaitForTransaction({ 38 | hash: approveHash, 39 | enabled: !!approveHash, 40 | onSuccess() { 41 | setIsApproved(true); 42 | }, 43 | }); 44 | 45 | const { isLoading: isApprovedLoading } = useContractRead( 46 | { 47 | addressOrName: pfpAddress, 48 | contractInterface: pfpAbi, 49 | }, 50 | 'isApprovedForAll', 51 | { 52 | args: [account?.address, pfpAddress], 53 | enabled: !!account, 54 | onSuccess(data) { 55 | if (typeof data === 'boolean') { 56 | setIsApproved(data); 57 | } 58 | }, 59 | onError(error) { 60 | setError(error.message); 61 | }, 62 | }, 63 | ); 64 | 65 | const { isLoading: approvedWriting, write: approveContract } = 66 | useContractWrite( 67 | { 68 | addressOrName: pfpAddress, 69 | contractInterface: pfpAbi, 70 | }, 71 | 'setApprovalForAll', 72 | { 73 | args: [pfpAddress, true], 74 | onSuccess(tx) { 75 | addRecent({ 76 | hash: tx.hash, 77 | description: 'Approve Wrapped Commsaurs contract', 78 | }); 79 | 80 | setApproveHash(tx.hash); 81 | }, 82 | onError(error) { 83 | setError(error.message); 84 | }, 85 | }, 86 | ); 87 | 88 | const { isLoading: unwrapping, write: unwrap } = useContractWrite( 89 | { 90 | addressOrName: pfpAddress, 91 | contractInterface: pfpAbi, 92 | }, 93 | 'safeTransferFrom(address,address,uint256)', 94 | { 95 | args: [account?.address, pfpAddress, dino.id], 96 | onSuccess(tx) { 97 | addRecent({ 98 | hash: tx.hash, 99 | description: `Wrap Commsaur ${dino.id}`, 100 | }); 101 | 102 | setTransactionHash(tx.hash); 103 | }, 104 | onError(error) { 105 | setError(error.message); 106 | }, 107 | }, 108 | ); 109 | 110 | const doClick = useCallback(() => { 111 | if (!isApproved && !approvedWriting) { 112 | approveContract(); 113 | } 114 | 115 | if (!useTransactionSending && isApproved) { 116 | unwrap(); 117 | } 118 | }, [ 119 | isApproved, 120 | approvedWriting, 121 | approveContract, 122 | useTransactionSending, 123 | unwrap, 124 | ]); 125 | 126 | return ( 127 | 152 | ); 153 | } 154 | 155 | export default UnwrapButton; 156 | -------------------------------------------------------------------------------- /components/CommsaurProvider.tsx: -------------------------------------------------------------------------------- 1 | import { BigNumber } from 'ethers'; 2 | import React, { ReactNode, useCallback, useContext, useState } from 'react'; 3 | import { useAccount, useContractRead } from 'wagmi'; 4 | import { commsaurAddress, pfpAddress } from '../abis/commsaur'; 5 | import abi from '../abis/commsaur_abi.json'; 6 | import pfpAbi from '../abis/commsaur_pfp_abi.json'; 7 | 8 | export type Commsaur = { 9 | id: number; 10 | wrapped?: boolean; 11 | }; 12 | 13 | type CommsaurContext = { 14 | herd: Commsaur[]; 15 | originalSize: number; 16 | reset: () => void; 17 | error: Error | null; 18 | toggleWrapped: (id: number, state: boolean) => void; 19 | }; 20 | 21 | export const getDinoImage = (saur: Commsaur): string => { 22 | if (saur.wrapped) { 23 | return `https://d124myd65w4vuo.cloudfront.net/pfps/${saur.id}.png`; 24 | } 25 | 26 | return `https://d124myd65w4vuo.cloudfront.net/fullBody/${saur.id}.jpeg`; 27 | }; 28 | 29 | const CommsaurCtx = React.createContext(null); 30 | 31 | type Props = { 32 | children: ReactNode; 33 | }; 34 | 35 | function CommsaurProvider({ children }: Props) { 36 | const { data: account } = useAccount(); 37 | const [wrappedAmount, setWrappedAmount] = useState(0); 38 | const [saurAmount, setSaurAmount] = useState(0); 39 | const [error, setError] = useState(null); 40 | const [idx, setIdx] = useState(0); 41 | const [pfpIdx, setPfpIdx] = useState(0); 42 | const [herd, setHerd] = useState([]); 43 | 44 | useContractRead( 45 | { 46 | addressOrName: commsaurAddress, 47 | contractInterface: abi, 48 | }, 49 | 'balanceOf', 50 | { 51 | args: account?.address, 52 | enabled: !!account, 53 | onSuccess(data) { 54 | const bId = data as unknown as BigNumber; 55 | const id = bId.toNumber(); 56 | setSaurAmount(id); 57 | }, 58 | onError(error) { 59 | setError(error); 60 | }, 61 | }, 62 | ); 63 | 64 | useContractRead( 65 | { 66 | addressOrName: pfpAddress, 67 | contractInterface: pfpAbi, 68 | }, 69 | 'balanceOf', 70 | { 71 | args: account?.address, 72 | enabled: !!account, 73 | onSuccess(data) { 74 | const bId = data as unknown as BigNumber; 75 | const id = bId.toNumber(); 76 | setWrappedAmount(id); 77 | }, 78 | onError(error) { 79 | setError(error); 80 | }, 81 | }, 82 | ); 83 | 84 | const { refetch: refetchWrapped } = useContractRead( 85 | { 86 | addressOrName: pfpAddress, 87 | contractInterface: pfpAbi, 88 | }, 89 | 'tokenOfOwnerByIndex', 90 | { 91 | args: [account?.address, pfpIdx], 92 | enabled: !!account && wrappedAmount > 0 && pfpIdx < wrappedAmount, 93 | onSuccess(data) { 94 | const bId = data as unknown as BigNumber; 95 | const id = bId.toNumber(); 96 | setHerd((old) => [ 97 | ...old, 98 | { 99 | id, 100 | wrapped: true, 101 | }, 102 | ]); 103 | setPfpIdx((old) => old + 1); 104 | }, 105 | onError(error) { 106 | setError(error); 107 | }, 108 | }, 109 | ); 110 | 111 | const { refetch } = useContractRead( 112 | { 113 | addressOrName: commsaurAddress, 114 | contractInterface: abi, 115 | }, 116 | 'tokenOfOwnerByIndex', 117 | { 118 | args: [account?.address, idx], 119 | enabled: !!account && saurAmount > 0 && idx < saurAmount, 120 | onSuccess(data) { 121 | const bId = data as unknown as BigNumber; 122 | const id = bId.toNumber(); 123 | setHerd((old) => [ 124 | ...old, 125 | { 126 | id: id, 127 | wrapped: false, 128 | }, 129 | ]); 130 | setIdx((old) => old + 1); 131 | }, 132 | onError(error) { 133 | setError(error); 134 | }, 135 | }, 136 | ); 137 | 138 | const toggleWrapped = useCallback( 139 | (id: number, state: boolean) => { 140 | const idx = herd.findIndex((dino) => dino.id === id); 141 | const updated = { ...herd[idx], wrapped: state }; 142 | const youngHerd = [ 143 | ...herd.slice(0, idx), 144 | updated, 145 | ...herd.slice(idx + 1), 146 | ]; 147 | setHerd(youngHerd); 148 | }, 149 | [herd], 150 | ); 151 | 152 | const reset = useCallback(() => { 153 | setError(null); 154 | refetch(); 155 | refetchWrapped(); 156 | setIdx(0); 157 | setPfpIdx(0); 158 | setHerd([]); 159 | }, [refetch, refetchWrapped]); 160 | 161 | const ctx: CommsaurContext = { 162 | herd: herd.sort((a, b) => a.id - b.id), 163 | originalSize: saurAmount + wrappedAmount, 164 | reset, 165 | error, 166 | toggleWrapped, 167 | }; 168 | 169 | return {children}; 170 | } 171 | 172 | export function useCommsaurContext() { 173 | const ctx = useContext(CommsaurCtx); 174 | if (ctx == null) { 175 | throw new Error( 176 | 'useCommsaurContext must be called within a CommsaurProvider', 177 | ); 178 | } 179 | 180 | return ctx; 181 | } 182 | 183 | export default CommsaurProvider; 184 | -------------------------------------------------------------------------------- /components/WrapButton.tsx: -------------------------------------------------------------------------------- 1 | import { useAddRecentTransaction } from '@rainbow-me/rainbowkit'; 2 | import React, { useCallback, useState } from 'react'; 3 | import { 4 | useAccount, 5 | useContractRead, 6 | useContractWrite, 7 | useWaitForTransaction, 8 | } from 'wagmi'; 9 | import { commsaurAddress, pfpAddress } from '../abis/commsaur'; 10 | import { Commsaur, useCommsaurContext } from './CommsaurProvider'; 11 | import LoadingSpinner from './LoadingSpinner'; 12 | import abi from '../abis/commsaur_abi.json'; 13 | import pfpAbi from '../abis/commsaur_pfp_abi.json'; 14 | 15 | type Props = { 16 | dino: Commsaur; 17 | acknowledged: boolean; 18 | setShowWarning: (shown: boolean) => void; 19 | setError: (error: string) => void; 20 | }; 21 | 22 | function WrapButton({ acknowledged, dino, setShowWarning, setError }: Props) { 23 | const { data: account } = useAccount(); 24 | const [isApproved, setIsApproved] = useState(false); 25 | const addRecent = useAddRecentTransaction(); 26 | const [transactionHash, setTransactionHash] = useState(); 27 | const [wasWrapped, setWasWrapped] = useState(false); 28 | const { toggleWrapped } = useCommsaurContext(); 29 | const [approveHash, setApproveHash] = useState(); 30 | 31 | const { isLoading: useTransactionSending } = useWaitForTransaction({ 32 | hash: transactionHash, 33 | enabled: !!transactionHash, 34 | onSuccess() { 35 | setWasWrapped(true); 36 | toggleWrapped(dino.id, true); 37 | }, 38 | }); 39 | 40 | const { isLoading: isApproving } = useWaitForTransaction({ 41 | hash: approveHash, 42 | enabled: !!approveHash, 43 | onSuccess() { 44 | setIsApproved(true); 45 | }, 46 | }); 47 | 48 | const { isLoading: isApprovedLoading } = useContractRead( 49 | { 50 | addressOrName: commsaurAddress, 51 | contractInterface: abi, 52 | }, 53 | 'isApprovedForAll', 54 | { 55 | args: [account?.address, commsaurAddress], 56 | enabled: acknowledged, 57 | onSuccess(data) { 58 | if (typeof data === 'boolean') { 59 | setIsApproved(data); 60 | } 61 | }, 62 | onError(error) { 63 | setError(error.message); 64 | }, 65 | }, 66 | ); 67 | 68 | const { isLoading: approveWriting, write } = useContractWrite( 69 | { 70 | addressOrName: commsaurAddress, 71 | contractInterface: abi, 72 | }, 73 | 'setApprovalForAll', 74 | { 75 | args: [commsaurAddress, true], 76 | onSuccess(tx) { 77 | addRecent({ 78 | hash: tx.hash, 79 | description: 'Approve Wrapped Commsaurs contract', 80 | }); 81 | 82 | setApproveHash(tx.hash); 83 | }, 84 | onError(error) { 85 | setError(error.message); 86 | }, 87 | }, 88 | ); 89 | 90 | const { isLoading: wrapLoading, write: wrapDinoCall } = useContractWrite( 91 | { 92 | addressOrName: commsaurAddress, 93 | contractInterface: pfpAbi, 94 | }, 95 | 'safeTransferFrom(address,address,uint256)', 96 | { 97 | args: [account?.address, pfpAddress, dino.id], 98 | onSuccess(tx) { 99 | console.log('added', tx); 100 | addRecent({ 101 | hash: tx.hash, 102 | description: `Wrap Commsaur ${dino.id}`, 103 | }); 104 | 105 | setTransactionHash(tx.hash); 106 | }, 107 | onError(error) { 108 | setError(error.message); 109 | }, 110 | }, 111 | ); 112 | 113 | const doClick = useCallback(() => { 114 | if (!acknowledged) { 115 | setShowWarning(true); 116 | return; 117 | } 118 | 119 | setError(''); 120 | 121 | if (!isApproved && !isApprovedLoading) { 122 | write(); 123 | } else if (isApproved && !wrapLoading) { 124 | wrapDinoCall(); 125 | } 126 | }, [ 127 | acknowledged, 128 | isApproved, 129 | isApprovedLoading, 130 | write, 131 | wrapLoading, 132 | wrapDinoCall, 133 | setShowWarning, 134 | setError, 135 | ]); 136 | 137 | return ( 138 | 177 | ); 178 | } 179 | 180 | export default WrapButton; 181 | -------------------------------------------------------------------------------- /components/CommsaurComponent.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @next/next/no-img-element */ 2 | import { Dialog, Transition } from '@headlessui/react'; 3 | import Link from 'next/link'; 4 | import React, { Fragment, useCallback, useEffect, useState } from 'react'; 5 | import { commsaurAddress, pfpAddress } from '../abis/commsaur'; 6 | import useCommsaurData from '../hooks/useCommsaurData'; 7 | import { Commsaur, getDinoImage } from './CommsaurProvider'; 8 | import DownloadIcon from './icons/DownloadIcon'; 9 | import UnwrapButton from './UnwrapButton'; 10 | import WrapButton from './WrapButton'; 11 | 12 | type Props = { 13 | dino: Commsaur; 14 | }; 15 | 16 | function CommsaurComponent({ dino }: Props) { 17 | const rarity = useCommsaurData(dino); 18 | const [showWarning, setShowWarning] = useState(false); 19 | const [acknowledged, setAcknowledged] = useState(false); 20 | const [error, setError] = useState(''); 21 | 22 | useEffect(() => { 23 | setShowWarning(false); 24 | setError(''); 25 | setAcknowledged(false); 26 | }, [dino]); 27 | 28 | const download = useCallback(() => { 29 | window.open( 30 | dino.wrapped 31 | ? `https://d124myd65w4vuo.cloudfront.net/pfps/${dino.id}.png` 32 | : `https://d124myd65w4vuo.cloudfront.net/fullRes/${dino.id}.png`, 33 | '_blank', 34 | ); 35 | }, [dino]); 36 | 37 | return ( 38 | <> 39 |
40 |

41 | {dino.wrapped && 'Wrapped '}Commsaur #{dino.id} 42 |

43 | 44 |
45 |
46 |
47 | {`Commsaur 52 | {error && ( 53 |

54 | {error} 55 |

56 | )} 57 | {!dino.wrapped && ( 58 | 64 | )} 65 | {dino.wrapped && ( 66 | 67 | )} 68 | 98 |
99 |
100 | {rarity.traits.map((trait) => { 101 | if (trait.trait_value === 'None') return; 102 | return ( 103 |
107 |

108 | {trait.trait_type} / {trait.trait_value} 109 | 110 | {' '} 111 | ({trait.percent}%) 112 | 113 |

114 |
115 |
119 |
120 |
121 | ); 122 | })} 123 |

124 | This Commsaur is ranked #{rarity.rank} with a rarity 125 | score of {rarity.rarity_score}. Data provided by 126 | RaritySniper. 127 |

128 |
129 |
130 | 131 | 135 | 143 | 144 | 145 | 153 |
154 |

155 | Warning 156 |

157 |

158 | Wrapping your Commsaur NFT transfers the ERC721 159 | token to our wrapping contract, which removes it 160 | from circulation from any marketplaces. Selling 161 | your wrapped NFT means that you no longer have 162 | access to the unwrapped version, and the new 163 | owner can unwrap it to access the original 164 | version. 165 |

166 |

167 | Wrapping/unwrapping Commsaurs cost gas every 168 | time you wish to do this, however, approving 169 | Contracts is a one-time transaction (once for 170 | wrapping, and another for unwrapping). 171 |

172 | 173 | 184 |
185 |
186 |
187 |
188 | 189 | ); 190 | } 191 | 192 | export default CommsaurComponent; 193 | -------------------------------------------------------------------------------- /abis/commsaur_pfp_abi.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_commsaurAddress", 7 | "type": "address" 8 | } 9 | ], 10 | "stateMutability": "nonpayable", 11 | "type": "constructor" 12 | }, 13 | { 14 | "anonymous": false, 15 | "inputs": [ 16 | { 17 | "indexed": true, 18 | "internalType": "address", 19 | "name": "owner", 20 | "type": "address" 21 | }, 22 | { 23 | "indexed": true, 24 | "internalType": "address", 25 | "name": "approved", 26 | "type": "address" 27 | }, 28 | { 29 | "indexed": true, 30 | "internalType": "uint256", 31 | "name": "tokenId", 32 | "type": "uint256" 33 | } 34 | ], 35 | "name": "Approval", 36 | "type": "event" 37 | }, 38 | { 39 | "anonymous": false, 40 | "inputs": [ 41 | { 42 | "indexed": true, 43 | "internalType": "address", 44 | "name": "owner", 45 | "type": "address" 46 | }, 47 | { 48 | "indexed": true, 49 | "internalType": "address", 50 | "name": "operator", 51 | "type": "address" 52 | }, 53 | { 54 | "indexed": false, 55 | "internalType": "bool", 56 | "name": "approved", 57 | "type": "bool" 58 | } 59 | ], 60 | "name": "ApprovalForAll", 61 | "type": "event" 62 | }, 63 | { 64 | "anonymous": false, 65 | "inputs": [ 66 | { 67 | "indexed": true, 68 | "internalType": "address", 69 | "name": "previousOwner", 70 | "type": "address" 71 | }, 72 | { 73 | "indexed": true, 74 | "internalType": "address", 75 | "name": "newOwner", 76 | "type": "address" 77 | } 78 | ], 79 | "name": "OwnershipTransferred", 80 | "type": "event" 81 | }, 82 | { 83 | "anonymous": false, 84 | "inputs": [ 85 | { 86 | "indexed": true, 87 | "internalType": "address", 88 | "name": "from", 89 | "type": "address" 90 | }, 91 | { 92 | "indexed": true, 93 | "internalType": "address", 94 | "name": "to", 95 | "type": "address" 96 | }, 97 | { 98 | "indexed": true, 99 | "internalType": "uint256", 100 | "name": "tokenId", 101 | "type": "uint256" 102 | } 103 | ], 104 | "name": "Transfer", 105 | "type": "event" 106 | }, 107 | { 108 | "inputs": [ 109 | { 110 | "internalType": "address", 111 | "name": "to", 112 | "type": "address" 113 | }, 114 | { 115 | "internalType": "uint256", 116 | "name": "tokenId", 117 | "type": "uint256" 118 | } 119 | ], 120 | "name": "approve", 121 | "outputs": [], 122 | "stateMutability": "nonpayable", 123 | "type": "function" 124 | }, 125 | { 126 | "inputs": [ 127 | { 128 | "internalType": "address", 129 | "name": "owner", 130 | "type": "address" 131 | } 132 | ], 133 | "name": "balanceOf", 134 | "outputs": [ 135 | { 136 | "internalType": "uint256", 137 | "name": "", 138 | "type": "uint256" 139 | } 140 | ], 141 | "stateMutability": "view", 142 | "type": "function" 143 | }, 144 | { 145 | "inputs": [], 146 | "name": "commsaurContract", 147 | "outputs": [ 148 | { 149 | "internalType": "contract IERC721", 150 | "name": "", 151 | "type": "address" 152 | } 153 | ], 154 | "stateMutability": "view", 155 | "type": "function" 156 | }, 157 | { 158 | "inputs": [ 159 | { 160 | "internalType": "uint256", 161 | "name": "tokenId", 162 | "type": "uint256" 163 | } 164 | ], 165 | "name": "getApproved", 166 | "outputs": [ 167 | { 168 | "internalType": "address", 169 | "name": "", 170 | "type": "address" 171 | } 172 | ], 173 | "stateMutability": "view", 174 | "type": "function" 175 | }, 176 | { 177 | "inputs": [ 178 | { 179 | "internalType": "address", 180 | "name": "owner", 181 | "type": "address" 182 | }, 183 | { 184 | "internalType": "address", 185 | "name": "operator", 186 | "type": "address" 187 | } 188 | ], 189 | "name": "isApprovedForAll", 190 | "outputs": [ 191 | { 192 | "internalType": "bool", 193 | "name": "", 194 | "type": "bool" 195 | } 196 | ], 197 | "stateMutability": "view", 198 | "type": "function" 199 | }, 200 | { 201 | "inputs": [], 202 | "name": "name", 203 | "outputs": [ 204 | { 205 | "internalType": "string", 206 | "name": "", 207 | "type": "string" 208 | } 209 | ], 210 | "stateMutability": "view", 211 | "type": "function" 212 | }, 213 | { 214 | "inputs": [ 215 | { 216 | "internalType": "address", 217 | "name": "", 218 | "type": "address" 219 | }, 220 | { 221 | "internalType": "address", 222 | "name": "from", 223 | "type": "address" 224 | }, 225 | { 226 | "internalType": "uint256", 227 | "name": "tokenId", 228 | "type": "uint256" 229 | }, 230 | { 231 | "internalType": "bytes", 232 | "name": "", 233 | "type": "bytes" 234 | } 235 | ], 236 | "name": "onERC721Received", 237 | "outputs": [ 238 | { 239 | "internalType": "bytes4", 240 | "name": "", 241 | "type": "bytes4" 242 | } 243 | ], 244 | "stateMutability": "nonpayable", 245 | "type": "function" 246 | }, 247 | { 248 | "inputs": [], 249 | "name": "owner", 250 | "outputs": [ 251 | { 252 | "internalType": "address", 253 | "name": "", 254 | "type": "address" 255 | } 256 | ], 257 | "stateMutability": "view", 258 | "type": "function" 259 | }, 260 | { 261 | "inputs": [ 262 | { 263 | "internalType": "uint256", 264 | "name": "tokenId", 265 | "type": "uint256" 266 | } 267 | ], 268 | "name": "ownerOf", 269 | "outputs": [ 270 | { 271 | "internalType": "address", 272 | "name": "", 273 | "type": "address" 274 | } 275 | ], 276 | "stateMutability": "view", 277 | "type": "function" 278 | }, 279 | { 280 | "inputs": [], 281 | "name": "renounceOwnership", 282 | "outputs": [], 283 | "stateMutability": "nonpayable", 284 | "type": "function" 285 | }, 286 | { 287 | "inputs": [ 288 | { 289 | "internalType": "address", 290 | "name": "to", 291 | "type": "address" 292 | }, 293 | { 294 | "internalType": "uint256", 295 | "name": "tokenId", 296 | "type": "uint256" 297 | } 298 | ], 299 | "name": "rescue", 300 | "outputs": [], 301 | "stateMutability": "nonpayable", 302 | "type": "function" 303 | }, 304 | { 305 | "inputs": [ 306 | { 307 | "internalType": "address", 308 | "name": "from", 309 | "type": "address" 310 | }, 311 | { 312 | "internalType": "address", 313 | "name": "to", 314 | "type": "address" 315 | }, 316 | { 317 | "internalType": "uint256", 318 | "name": "tokenId", 319 | "type": "uint256" 320 | } 321 | ], 322 | "name": "safeTransferFrom", 323 | "outputs": [], 324 | "stateMutability": "nonpayable", 325 | "type": "function" 326 | }, 327 | { 328 | "inputs": [ 329 | { 330 | "internalType": "address", 331 | "name": "from", 332 | "type": "address" 333 | }, 334 | { 335 | "internalType": "address", 336 | "name": "to", 337 | "type": "address" 338 | }, 339 | { 340 | "internalType": "uint256", 341 | "name": "tokenId", 342 | "type": "uint256" 343 | }, 344 | { 345 | "internalType": "bytes", 346 | "name": "_data", 347 | "type": "bytes" 348 | } 349 | ], 350 | "name": "safeTransferFrom", 351 | "outputs": [], 352 | "stateMutability": "nonpayable", 353 | "type": "function" 354 | }, 355 | { 356 | "inputs": [ 357 | { 358 | "internalType": "address", 359 | "name": "operator", 360 | "type": "address" 361 | }, 362 | { 363 | "internalType": "bool", 364 | "name": "approved", 365 | "type": "bool" 366 | } 367 | ], 368 | "name": "setApprovalForAll", 369 | "outputs": [], 370 | "stateMutability": "nonpayable", 371 | "type": "function" 372 | }, 373 | { 374 | "inputs": [ 375 | { 376 | "internalType": "string", 377 | "name": "uri", 378 | "type": "string" 379 | } 380 | ], 381 | "name": "setBaseURI", 382 | "outputs": [], 383 | "stateMutability": "nonpayable", 384 | "type": "function" 385 | }, 386 | { 387 | "inputs": [ 388 | { 389 | "internalType": "bool", 390 | "name": "_enabled", 391 | "type": "bool" 392 | } 393 | ], 394 | "name": "setUnwrappingEnabled", 395 | "outputs": [], 396 | "stateMutability": "nonpayable", 397 | "type": "function" 398 | }, 399 | { 400 | "inputs": [ 401 | { 402 | "internalType": "bool", 403 | "name": "_enabled", 404 | "type": "bool" 405 | } 406 | ], 407 | "name": "setWrappingEnabled", 408 | "outputs": [], 409 | "stateMutability": "nonpayable", 410 | "type": "function" 411 | }, 412 | { 413 | "inputs": [ 414 | { 415 | "internalType": "bytes4", 416 | "name": "interfaceId", 417 | "type": "bytes4" 418 | } 419 | ], 420 | "name": "supportsInterface", 421 | "outputs": [ 422 | { 423 | "internalType": "bool", 424 | "name": "", 425 | "type": "bool" 426 | } 427 | ], 428 | "stateMutability": "view", 429 | "type": "function" 430 | }, 431 | { 432 | "inputs": [], 433 | "name": "symbol", 434 | "outputs": [ 435 | { 436 | "internalType": "string", 437 | "name": "", 438 | "type": "string" 439 | } 440 | ], 441 | "stateMutability": "view", 442 | "type": "function" 443 | }, 444 | { 445 | "inputs": [ 446 | { 447 | "internalType": "uint256", 448 | "name": "index", 449 | "type": "uint256" 450 | } 451 | ], 452 | "name": "tokenByIndex", 453 | "outputs": [ 454 | { 455 | "internalType": "uint256", 456 | "name": "", 457 | "type": "uint256" 458 | } 459 | ], 460 | "stateMutability": "view", 461 | "type": "function" 462 | }, 463 | { 464 | "inputs": [ 465 | { 466 | "internalType": "address", 467 | "name": "owner", 468 | "type": "address" 469 | }, 470 | { 471 | "internalType": "uint256", 472 | "name": "index", 473 | "type": "uint256" 474 | } 475 | ], 476 | "name": "tokenOfOwnerByIndex", 477 | "outputs": [ 478 | { 479 | "internalType": "uint256", 480 | "name": "", 481 | "type": "uint256" 482 | } 483 | ], 484 | "stateMutability": "view", 485 | "type": "function" 486 | }, 487 | { 488 | "inputs": [ 489 | { 490 | "internalType": "uint256", 491 | "name": "tokenId", 492 | "type": "uint256" 493 | } 494 | ], 495 | "name": "tokenURI", 496 | "outputs": [ 497 | { 498 | "internalType": "string", 499 | "name": "", 500 | "type": "string" 501 | } 502 | ], 503 | "stateMutability": "view", 504 | "type": "function" 505 | }, 506 | { 507 | "inputs": [], 508 | "name": "totalSupply", 509 | "outputs": [ 510 | { 511 | "internalType": "uint256", 512 | "name": "", 513 | "type": "uint256" 514 | } 515 | ], 516 | "stateMutability": "view", 517 | "type": "function" 518 | }, 519 | { 520 | "inputs": [ 521 | { 522 | "internalType": "address", 523 | "name": "from", 524 | "type": "address" 525 | }, 526 | { 527 | "internalType": "address", 528 | "name": "to", 529 | "type": "address" 530 | }, 531 | { 532 | "internalType": "uint256", 533 | "name": "tokenId", 534 | "type": "uint256" 535 | } 536 | ], 537 | "name": "transferFrom", 538 | "outputs": [], 539 | "stateMutability": "nonpayable", 540 | "type": "function" 541 | }, 542 | { 543 | "inputs": [ 544 | { 545 | "internalType": "address", 546 | "name": "newOwner", 547 | "type": "address" 548 | } 549 | ], 550 | "name": "transferOwnership", 551 | "outputs": [], 552 | "stateMutability": "nonpayable", 553 | "type": "function" 554 | }, 555 | { 556 | "inputs": [ 557 | { 558 | "internalType": "uint256[]", 559 | "name": "tokenIds", 560 | "type": "uint256[]" 561 | } 562 | ], 563 | "name": "unwrapHerd", 564 | "outputs": [], 565 | "stateMutability": "nonpayable", 566 | "type": "function" 567 | }, 568 | { 569 | "inputs": [ 570 | { 571 | "internalType": "uint256[]", 572 | "name": "tokenIds", 573 | "type": "uint256[]" 574 | } 575 | ], 576 | "name": "wrapHerd", 577 | "outputs": [], 578 | "stateMutability": "nonpayable", 579 | "type": "function" 580 | }, 581 | { 582 | "inputs": [], 583 | "name": "wrappingState", 584 | "outputs": [ 585 | { 586 | "internalType": "bool", 587 | "name": "wrappingEnabled", 588 | "type": "bool" 589 | }, 590 | { 591 | "internalType": "bool", 592 | "name": "unwrappingEnabled", 593 | "type": "bool" 594 | } 595 | ], 596 | "stateMutability": "view", 597 | "type": "function" 598 | } 599 | ] -------------------------------------------------------------------------------- /abis/commsaur_abi.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [], 4 | "stateMutability": "nonpayable", 5 | "type": "constructor" 6 | }, 7 | { 8 | "inputs": [], 9 | "name": "ApprovalCallerNotOwnerNorApproved", 10 | "type": "error" 11 | }, 12 | { 13 | "inputs": [], 14 | "name": "ApprovalQueryForNonexistentToken", 15 | "type": "error" 16 | }, 17 | { 18 | "inputs": [], 19 | "name": "ApprovalToCurrentOwner", 20 | "type": "error" 21 | }, 22 | { 23 | "inputs": [], 24 | "name": "ApproveToCaller", 25 | "type": "error" 26 | }, 27 | { 28 | "inputs": [], 29 | "name": "BalanceQueryForZeroAddress", 30 | "type": "error" 31 | }, 32 | { 33 | "inputs": [], 34 | "name": "MintToZeroAddress", 35 | "type": "error" 36 | }, 37 | { 38 | "inputs": [], 39 | "name": "MintZeroQuantity", 40 | "type": "error" 41 | }, 42 | { 43 | "inputs": [], 44 | "name": "OwnerIndexOutOfBounds", 45 | "type": "error" 46 | }, 47 | { 48 | "inputs": [], 49 | "name": "OwnerQueryForNonexistentToken", 50 | "type": "error" 51 | }, 52 | { 53 | "inputs": [], 54 | "name": "TokenIndexOutOfBounds", 55 | "type": "error" 56 | }, 57 | { 58 | "inputs": [], 59 | "name": "TransferCallerNotOwnerNorApproved", 60 | "type": "error" 61 | }, 62 | { 63 | "inputs": [], 64 | "name": "TransferFromIncorrectOwner", 65 | "type": "error" 66 | }, 67 | { 68 | "inputs": [], 69 | "name": "TransferToNonERC721ReceiverImplementer", 70 | "type": "error" 71 | }, 72 | { 73 | "inputs": [], 74 | "name": "TransferToZeroAddress", 75 | "type": "error" 76 | }, 77 | { 78 | "inputs": [], 79 | "name": "URIQueryForNonexistentToken", 80 | "type": "error" 81 | }, 82 | { 83 | "anonymous": false, 84 | "inputs": [ 85 | { 86 | "indexed": true, 87 | "internalType": "address", 88 | "name": "owner", 89 | "type": "address" 90 | }, 91 | { 92 | "indexed": true, 93 | "internalType": "address", 94 | "name": "approved", 95 | "type": "address" 96 | }, 97 | { 98 | "indexed": true, 99 | "internalType": "uint256", 100 | "name": "tokenId", 101 | "type": "uint256" 102 | } 103 | ], 104 | "name": "Approval", 105 | "type": "event" 106 | }, 107 | { 108 | "anonymous": false, 109 | "inputs": [ 110 | { 111 | "indexed": true, 112 | "internalType": "address", 113 | "name": "owner", 114 | "type": "address" 115 | }, 116 | { 117 | "indexed": true, 118 | "internalType": "address", 119 | "name": "operator", 120 | "type": "address" 121 | }, 122 | { 123 | "indexed": false, 124 | "internalType": "bool", 125 | "name": "approved", 126 | "type": "bool" 127 | } 128 | ], 129 | "name": "ApprovalForAll", 130 | "type": "event" 131 | }, 132 | { 133 | "anonymous": false, 134 | "inputs": [ 135 | { 136 | "indexed": true, 137 | "internalType": "address", 138 | "name": "previousOwner", 139 | "type": "address" 140 | }, 141 | { 142 | "indexed": true, 143 | "internalType": "address", 144 | "name": "newOwner", 145 | "type": "address" 146 | } 147 | ], 148 | "name": "OwnershipTransferred", 149 | "type": "event" 150 | }, 151 | { 152 | "anonymous": false, 153 | "inputs": [ 154 | { 155 | "indexed": true, 156 | "internalType": "address", 157 | "name": "from", 158 | "type": "address" 159 | }, 160 | { 161 | "indexed": true, 162 | "internalType": "address", 163 | "name": "to", 164 | "type": "address" 165 | }, 166 | { 167 | "indexed": true, 168 | "internalType": "uint256", 169 | "name": "tokenId", 170 | "type": "uint256" 171 | } 172 | ], 173 | "name": "Transfer", 174 | "type": "event" 175 | }, 176 | { 177 | "inputs": [], 178 | "name": "MAX_SUPPLY", 179 | "outputs": [ 180 | { 181 | "internalType": "uint16", 182 | "name": "", 183 | "type": "uint16" 184 | } 185 | ], 186 | "stateMutability": "view", 187 | "type": "function", 188 | "constant": true 189 | }, 190 | { 191 | "inputs": [], 192 | "name": "MINT_PRICE", 193 | "outputs": [ 194 | { 195 | "internalType": "uint256", 196 | "name": "", 197 | "type": "uint256" 198 | } 199 | ], 200 | "stateMutability": "view", 201 | "type": "function", 202 | "constant": true 203 | }, 204 | { 205 | "inputs": [ 206 | { 207 | "internalType": "address", 208 | "name": "to", 209 | "type": "address" 210 | }, 211 | { 212 | "internalType": "uint256", 213 | "name": "tokenId", 214 | "type": "uint256" 215 | } 216 | ], 217 | "name": "approve", 218 | "outputs": [], 219 | "stateMutability": "nonpayable", 220 | "type": "function" 221 | }, 222 | { 223 | "inputs": [ 224 | { 225 | "internalType": "address", 226 | "name": "owner", 227 | "type": "address" 228 | } 229 | ], 230 | "name": "balanceOf", 231 | "outputs": [ 232 | { 233 | "internalType": "uint256", 234 | "name": "", 235 | "type": "uint256" 236 | } 237 | ], 238 | "stateMutability": "view", 239 | "type": "function", 240 | "constant": true 241 | }, 242 | { 243 | "inputs": [ 244 | { 245 | "internalType": "uint256", 246 | "name": "tokenId", 247 | "type": "uint256" 248 | } 249 | ], 250 | "name": "getApproved", 251 | "outputs": [ 252 | { 253 | "internalType": "address", 254 | "name": "", 255 | "type": "address" 256 | } 257 | ], 258 | "stateMutability": "view", 259 | "type": "function", 260 | "constant": true 261 | }, 262 | { 263 | "inputs": [ 264 | { 265 | "internalType": "address", 266 | "name": "owner", 267 | "type": "address" 268 | }, 269 | { 270 | "internalType": "address", 271 | "name": "operator", 272 | "type": "address" 273 | } 274 | ], 275 | "name": "isApprovedForAll", 276 | "outputs": [ 277 | { 278 | "internalType": "bool", 279 | "name": "", 280 | "type": "bool" 281 | } 282 | ], 283 | "stateMutability": "view", 284 | "type": "function", 285 | "constant": true 286 | }, 287 | { 288 | "inputs": [], 289 | "name": "mintReserved", 290 | "outputs": [ 291 | { 292 | "internalType": "bool", 293 | "name": "", 294 | "type": "bool" 295 | } 296 | ], 297 | "stateMutability": "view", 298 | "type": "function", 299 | "constant": true 300 | }, 301 | { 302 | "inputs": [], 303 | "name": "mintStatus", 304 | "outputs": [ 305 | { 306 | "internalType": "enum Commsaur.MintStatus", 307 | "name": "", 308 | "type": "uint8" 309 | } 310 | ], 311 | "stateMutability": "view", 312 | "type": "function", 313 | "constant": true 314 | }, 315 | { 316 | "inputs": [], 317 | "name": "name", 318 | "outputs": [ 319 | { 320 | "internalType": "string", 321 | "name": "", 322 | "type": "string" 323 | } 324 | ], 325 | "stateMutability": "view", 326 | "type": "function", 327 | "constant": true 328 | }, 329 | { 330 | "inputs": [], 331 | "name": "owner", 332 | "outputs": [ 333 | { 334 | "internalType": "address", 335 | "name": "", 336 | "type": "address" 337 | } 338 | ], 339 | "stateMutability": "view", 340 | "type": "function", 341 | "constant": true 342 | }, 343 | { 344 | "inputs": [ 345 | { 346 | "internalType": "uint256", 347 | "name": "tokenId", 348 | "type": "uint256" 349 | } 350 | ], 351 | "name": "ownerOf", 352 | "outputs": [ 353 | { 354 | "internalType": "address", 355 | "name": "", 356 | "type": "address" 357 | } 358 | ], 359 | "stateMutability": "view", 360 | "type": "function", 361 | "constant": true 362 | }, 363 | { 364 | "inputs": [], 365 | "name": "renounceOwnership", 366 | "outputs": [], 367 | "stateMutability": "nonpayable", 368 | "type": "function" 369 | }, 370 | { 371 | "inputs": [ 372 | { 373 | "internalType": "address", 374 | "name": "from", 375 | "type": "address" 376 | }, 377 | { 378 | "internalType": "address", 379 | "name": "to", 380 | "type": "address" 381 | }, 382 | { 383 | "internalType": "uint256", 384 | "name": "tokenId", 385 | "type": "uint256" 386 | } 387 | ], 388 | "name": "safeTransferFrom", 389 | "outputs": [], 390 | "stateMutability": "nonpayable", 391 | "type": "function" 392 | }, 393 | { 394 | "inputs": [ 395 | { 396 | "internalType": "address", 397 | "name": "from", 398 | "type": "address" 399 | }, 400 | { 401 | "internalType": "address", 402 | "name": "to", 403 | "type": "address" 404 | }, 405 | { 406 | "internalType": "uint256", 407 | "name": "tokenId", 408 | "type": "uint256" 409 | }, 410 | { 411 | "internalType": "bytes", 412 | "name": "_data", 413 | "type": "bytes" 414 | } 415 | ], 416 | "name": "safeTransferFrom", 417 | "outputs": [], 418 | "stateMutability": "nonpayable", 419 | "type": "function" 420 | }, 421 | { 422 | "inputs": [ 423 | { 424 | "internalType": "address", 425 | "name": "operator", 426 | "type": "address" 427 | }, 428 | { 429 | "internalType": "bool", 430 | "name": "approved", 431 | "type": "bool" 432 | } 433 | ], 434 | "name": "setApprovalForAll", 435 | "outputs": [], 436 | "stateMutability": "nonpayable", 437 | "type": "function" 438 | }, 439 | { 440 | "inputs": [ 441 | { 442 | "internalType": "bytes4", 443 | "name": "interfaceId", 444 | "type": "bytes4" 445 | } 446 | ], 447 | "name": "supportsInterface", 448 | "outputs": [ 449 | { 450 | "internalType": "bool", 451 | "name": "", 452 | "type": "bool" 453 | } 454 | ], 455 | "stateMutability": "view", 456 | "type": "function", 457 | "constant": true 458 | }, 459 | { 460 | "inputs": [], 461 | "name": "symbol", 462 | "outputs": [ 463 | { 464 | "internalType": "string", 465 | "name": "", 466 | "type": "string" 467 | } 468 | ], 469 | "stateMutability": "view", 470 | "type": "function", 471 | "constant": true 472 | }, 473 | { 474 | "inputs": [ 475 | { 476 | "internalType": "uint256", 477 | "name": "index", 478 | "type": "uint256" 479 | } 480 | ], 481 | "name": "tokenByIndex", 482 | "outputs": [ 483 | { 484 | "internalType": "uint256", 485 | "name": "", 486 | "type": "uint256" 487 | } 488 | ], 489 | "stateMutability": "view", 490 | "type": "function", 491 | "constant": true 492 | }, 493 | { 494 | "inputs": [ 495 | { 496 | "internalType": "address", 497 | "name": "owner", 498 | "type": "address" 499 | }, 500 | { 501 | "internalType": "uint256", 502 | "name": "index", 503 | "type": "uint256" 504 | } 505 | ], 506 | "name": "tokenOfOwnerByIndex", 507 | "outputs": [ 508 | { 509 | "internalType": "uint256", 510 | "name": "", 511 | "type": "uint256" 512 | } 513 | ], 514 | "stateMutability": "view", 515 | "type": "function", 516 | "constant": true 517 | }, 518 | { 519 | "inputs": [ 520 | { 521 | "internalType": "uint256", 522 | "name": "tokenId", 523 | "type": "uint256" 524 | } 525 | ], 526 | "name": "tokenURI", 527 | "outputs": [ 528 | { 529 | "internalType": "string", 530 | "name": "", 531 | "type": "string" 532 | } 533 | ], 534 | "stateMutability": "view", 535 | "type": "function", 536 | "constant": true 537 | }, 538 | { 539 | "inputs": [], 540 | "name": "totalSupply", 541 | "outputs": [ 542 | { 543 | "internalType": "uint256", 544 | "name": "", 545 | "type": "uint256" 546 | } 547 | ], 548 | "stateMutability": "view", 549 | "type": "function", 550 | "constant": true 551 | }, 552 | { 553 | "inputs": [ 554 | { 555 | "internalType": "address", 556 | "name": "from", 557 | "type": "address" 558 | }, 559 | { 560 | "internalType": "address", 561 | "name": "to", 562 | "type": "address" 563 | }, 564 | { 565 | "internalType": "uint256", 566 | "name": "tokenId", 567 | "type": "uint256" 568 | } 569 | ], 570 | "name": "transferFrom", 571 | "outputs": [], 572 | "stateMutability": "nonpayable", 573 | "type": "function" 574 | }, 575 | { 576 | "inputs": [ 577 | { 578 | "internalType": "address", 579 | "name": "newOwner", 580 | "type": "address" 581 | } 582 | ], 583 | "name": "transferOwnership", 584 | "outputs": [], 585 | "stateMutability": "nonpayable", 586 | "type": "function" 587 | }, 588 | { 589 | "inputs": [], 590 | "name": "withdrawalAddress", 591 | "outputs": [ 592 | { 593 | "internalType": "address", 594 | "name": "", 595 | "type": "address" 596 | } 597 | ], 598 | "stateMutability": "view", 599 | "type": "function", 600 | "constant": true 601 | }, 602 | { 603 | "inputs": [ 604 | { 605 | "internalType": "uint256", 606 | "name": "commsaursToMint", 607 | "type": "uint256" 608 | } 609 | ], 610 | "name": "mintCommsaurs", 611 | "outputs": [], 612 | "stateMutability": "payable", 613 | "type": "function", 614 | "payable": true 615 | }, 616 | { 617 | "inputs": [], 618 | "name": "mintAllowList", 619 | "outputs": [], 620 | "stateMutability": "payable", 621 | "type": "function", 622 | "payable": true 623 | }, 624 | { 625 | "inputs": [ 626 | { 627 | "internalType": "uint256", 628 | "name": "status", 629 | "type": "uint256" 630 | } 631 | ], 632 | "name": "setMintStatus", 633 | "outputs": [], 634 | "stateMutability": "nonpayable", 635 | "type": "function" 636 | }, 637 | { 638 | "inputs": [ 639 | { 640 | "internalType": "string", 641 | "name": "uri", 642 | "type": "string" 643 | } 644 | ], 645 | "name": "setBaseURI", 646 | "outputs": [], 647 | "stateMutability": "nonpayable", 648 | "type": "function" 649 | }, 650 | { 651 | "inputs": [ 652 | { 653 | "internalType": "address", 654 | "name": "_addr", 655 | "type": "address" 656 | } 657 | ], 658 | "name": "setWithdrawalAddress", 659 | "outputs": [], 660 | "stateMutability": "nonpayable", 661 | "type": "function" 662 | }, 663 | { 664 | "inputs": [ 665 | { 666 | "internalType": "address[]", 667 | "name": "addresses", 668 | "type": "address[]" 669 | } 670 | ], 671 | "name": "setAllowList", 672 | "outputs": [], 673 | "stateMutability": "nonpayable", 674 | "type": "function" 675 | }, 676 | { 677 | "inputs": [], 678 | "name": "reserveTokens", 679 | "outputs": [], 680 | "stateMutability": "nonpayable", 681 | "type": "function" 682 | }, 683 | { 684 | "inputs": [], 685 | "name": "withdraw", 686 | "outputs": [], 687 | "stateMutability": "nonpayable", 688 | "type": "function" 689 | }, 690 | { 691 | "inputs": [ 692 | { 693 | "internalType": "uint256", 694 | "name": "tokenId", 695 | "type": "uint256" 696 | } 697 | ], 698 | "name": "getOwnershipData", 699 | "outputs": [ 700 | { 701 | "components": [ 702 | { 703 | "internalType": "address", 704 | "name": "addr", 705 | "type": "address" 706 | }, 707 | { 708 | "internalType": "uint64", 709 | "name": "startTimestamp", 710 | "type": "uint64" 711 | }, 712 | { 713 | "internalType": "bool", 714 | "name": "burned", 715 | "type": "bool" 716 | } 717 | ], 718 | "internalType": "struct ERC721A.TokenOwnership", 719 | "name": "", 720 | "type": "tuple" 721 | } 722 | ], 723 | "stateMutability": "view", 724 | "type": "function", 725 | "constant": true 726 | } 727 | ] --------------------------------------------------------------------------------