/* eslint-disable eslint-comments/disable-enable-pair */ /* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ //import { coin } from '@cosmjs/proto-signing' import clsx from 'clsx' import { Alert } from 'components/Alert' import { Anchor } from 'components/Anchor' import type { BadgeDetailsDataProps } from 'components/badges/creation/BadgeDetails' import { BadgeDetails } from 'components/badges/creation/BadgeDetails' import type { ImageUploadDetailsDataProps, MintRule } from 'components/badges/creation/ImageUploadDetails' import { ImageUploadDetails } from 'components/badges/creation/ImageUploadDetails' import { Button } from 'components/Button' import { Conditional } from 'components/Conditional' import { useInputState } from 'components/forms/FormInput.hooks' import { LoadingModal } from 'components/LoadingModal' import { useContracts } from 'contexts/contracts' import { useWallet } from 'contexts/wallet' import type { DispatchExecuteArgs as BadgeHubDispatchExecuteArgs } from 'contracts/badgeHub/messages/execute' import { dispatchExecute as badgeHubDispatchExecute } from 'contracts/badgeHub/messages/execute' import * as crypto from 'crypto' import type { NextPage } from 'next' import { NextSeo } from 'next-seo' import { QRCodeSVG } from 'qrcode.react' import { useEffect, useMemo, useRef, useState } from 'react' import { toast } from 'react-hot-toast' import * as secp256k1 from 'secp256k1' import { upload } from 'services/upload' import { BADGE_HUB_ADDRESS, BLOCK_EXPLORER_URL, NETWORK } from 'utils/constants' import { withMetadata } from 'utils/layout' import { links } from 'utils/links' import { TextInput } from '../../components/forms/FormInput' // import { ConfirmationModal } from '../../components/ConfirmationModal' // import { badgeHub } from '../../contracts/badgeHub/contract' // import { isValidAddress } from '../../utils/isValidAddress' const BadgeCreationPage: NextPage = () => { const wallet = useWallet() const { badgeHub: badgeHubContract } = useContracts() const scrollRef = useRef(null) const badgeHubMessages = useMemo(() => badgeHubContract?.use(BADGE_HUB_ADDRESS), [badgeHubContract, wallet.address]) const [imageUploadDetails, setImageUploadDetails] = useState(null) const [badgeDetails, setBadgeDetails] = useState(null) // const [baseMinterDetails, setBaseMinterDetails] = useState(null) const [uploading, setUploading] = useState(false) const [creatingBadge, setCreatingBadge] = useState(false) const [readyToCreateBadge, setReadyToCreateBadge] = useState(false) const [mintRule, setMintRule] = useState('by_key') const [badgeId, setBadgeId] = useState(null) const [imageUrl, setImageUrl] = useState(null) const [createdBadgeKey, setCreatedBadgeKey] = useState(undefined) const [transactionHash, setTransactionHash] = useState(null) const keyState = useInputState({ id: 'key', name: 'key', title: 'Key', subtitle: 'The key generated for the badge', }) const performBadgeCreationChecks = () => { try { setReadyToCreateBadge(false) checkImageUploadDetails() // checkMetadataDetails() setReadyToCreateBadge(true) } catch (error: any) { toast.error(error.message, { style: { maxWidth: 'none' } }) setUploading(false) setReadyToCreateBadge(false) } } const handleImageUrl = async () => { try { setImageUrl(null) setBadgeId(null) setTransactionHash(null) if (imageUploadDetails?.uploadMethod === 'new') { setUploading(true) const coverUrl = await upload( [imageUploadDetails.assetFile] as File[], imageUploadDetails.uploadService, 'cover', imageUploadDetails.nftStorageApiKey as string, imageUploadDetails.pinataApiKey as string, imageUploadDetails.pinataSecretKey as string, ).then((imageBaseUrl) => { setUploading(false) return `ipfs://${imageBaseUrl}/${imageUploadDetails.assetFile?.name as string}` }) setImageUrl(coverUrl) return coverUrl } setImageUrl(imageUploadDetails?.imageUrl as string) return imageUploadDetails?.imageUrl as string } catch (error: any) { toast.error(error.message, { style: { maxWidth: 'none' } }) setCreatingBadge(false) setUploading(false) throw new Error("Couldn't upload the image.") } } const createNewBadge = async () => { try { if (!wallet.initialized) throw new Error('Wallet not connected') if (!badgeHubContract) throw new Error('Contract not found') setCreatingBadge(true) const coverUrl = await handleImageUrl() const badge = { manager: badgeDetails?.manager as string, metadata: { name: badgeDetails?.name || undefined, description: badgeDetails?.description || undefined, image: coverUrl || undefined, image_data: badgeDetails?.image_data || undefined, external_url: badgeDetails?.external_url || undefined, attributes: badgeDetails?.attributes || undefined, background_color: badgeDetails?.background_color || undefined, animation_url: badgeDetails?.animation_url || undefined, youtube_url: badgeDetails?.youtube_url || undefined, }, transferrable: badgeDetails?.transferrable as boolean, rule: { by_key: keyState.value, }, expiry: badgeDetails?.expiry || undefined, max_supply: badgeDetails?.max_supply || undefined, } const payload: BadgeHubDispatchExecuteArgs = { contract: BADGE_HUB_ADDRESS, messages: badgeHubMessages, txSigner: wallet.address, badge, type: 'create_badge', } const data = await badgeHubDispatchExecute(payload) console.log(data) setTransactionHash(data.split(':')[0]) setBadgeId(data.split(':')[1]) } catch (error: any) { toast.error(error.message, { style: { maxWidth: 'none' } }) setCreatingBadge(false) setUploading(false) } } const checkImageUploadDetails = () => { if (!wallet.initialized) throw new Error('Wallet not connected.') if (!imageUploadDetails) { throw new Error('Please specify the image related details.') } if (imageUploadDetails.uploadMethod === 'new' && imageUploadDetails.assetFile === undefined) { throw new Error('Please select the image file') } if (imageUploadDetails.uploadMethod === 'new') { if (imageUploadDetails.uploadService === 'nft-storage') { if (imageUploadDetails.nftStorageApiKey === '') { throw new Error('Please enter a valid NFT.Storage API key') } } else if (imageUploadDetails.pinataApiKey === '' || imageUploadDetails.pinataSecretKey === '') { throw new Error('Please enter Pinata API and secret keys') } } if (imageUploadDetails.uploadMethod === 'existing' && !imageUploadDetails.imageUrl?.includes('ipfs://')) { throw new Error('Please specify a valid image URL') } } // const checkBadgeDetails = () => { // if (!metadataDetails) throw new Error('Please fill out the collection details') // if (collectionDetails.name === '') throw new Error('Collection name is required') // if (collectionDetails.description === '') throw new Error('Collection description is required') // if (collectionDetails.description.length > 512) // throw new Error('Collection description cannot exceed 512 characters') // if (uploadDetails?.uploadMethod === 'new' && collectionDetails.imageFile.length === 0) // throw new Error('Collection cover image is required') // if ( // collectionDetails.startTradingTime && // Number(collectionDetails.startTradingTime) < new Date().getTime() * 1000000 // ) // throw new Error('Invalid trading start time') // if ( // collectionDetails.startTradingTime && // Number(collectionDetails.startTradingTime) < Number(mintingDetails?.startTime) // ) // throw new Error('Trading start time must be after minting start time') // if (collectionDetails.externalLink) { // try { // const url = new URL(collectionDetails.externalLink) // } catch (e: any) { // throw new Error(`Invalid external link: Make sure to include the protocol (e.g. https://)`) // } // } // } const handleGenerateKey = () => { let privKey: Buffer do { privKey = crypto.randomBytes(32) } while (!secp256k1.privateKeyVerify(privKey)) const privateKey = privKey.toString('hex') setCreatedBadgeKey(privateKey) console.log('Private Key: ', privateKey) const publicKey = Buffer.from(secp256k1.publicKeyCreate(privKey)).toString('hex') keyState.onChange(publicKey) } const checkwalletBalance = () => { if (!wallet.initialized) throw new Error('Wallet not connected.') // TODO: estimate creation cost and check wallet balance } useEffect(() => { if (badgeId !== null) scrollRef.current?.scrollIntoView({ behavior: 'smooth' }) }, [badgeId]) useEffect(() => { setImageUrl(imageUploadDetails?.imageUrl as string) }, [imageUploadDetails?.imageUrl]) useEffect(() => { setBadgeId(null) setReadyToCreateBadge(false) }, [imageUploadDetails?.uploadMethod]) return (

Create Badge

Make sure you check our{' '} documentation {' '} on how to create a new badge.


Badge ID:{` ${badgeId as string}`}
Transaction Hash: {' '} {transactionHash} {transactionHash}
{/* */}
) } export default withMetadata(BadgeCreationPage, { center: false })