Display summary upon adding new tokens to a 1/1 collection

This commit is contained in:
Serkan Reis 2023-04-04 15:30:05 +03:00
parent bff03ffc66
commit ac467fb750
3 changed files with 192 additions and 62 deletions

View File

@ -22,6 +22,7 @@ export type BaseMinterAcquisitionMethod = 'existing' | 'new'
export interface MinterInfo { export interface MinterInfo {
name: string name: string
minter: string minter: string
contractAddress: string
} }
interface BaseMinterDetailsProps { interface BaseMinterDetailsProps {
@ -32,6 +33,8 @@ interface BaseMinterDetailsProps {
export interface BaseMinterDetailsDataProps { export interface BaseMinterDetailsDataProps {
baseMinterAcquisitionMethod: BaseMinterAcquisitionMethod baseMinterAcquisitionMethod: BaseMinterAcquisitionMethod
existingBaseMinter: string | undefined existingBaseMinter: string | undefined
selectedCollectionAddress: string | undefined
collectionTokenCount: number | undefined
} }
export const BaseMinterDetails = ({ onChange, minterType }: BaseMinterDetailsProps) => { export const BaseMinterDetails = ({ onChange, minterType }: BaseMinterDetailsProps) => {
@ -39,6 +42,8 @@ export const BaseMinterDetails = ({ onChange, minterType }: BaseMinterDetailsPro
const [myBaseMinterContracts, setMyBaseMinterContracts] = useState<MinterInfo[]>([]) const [myBaseMinterContracts, setMyBaseMinterContracts] = useState<MinterInfo[]>([])
const [baseMinterAcquisitionMethod, setBaseMinterAcquisitionMethod] = useState<BaseMinterAcquisitionMethod>('new') const [baseMinterAcquisitionMethod, setBaseMinterAcquisitionMethod] = useState<BaseMinterAcquisitionMethod>('new')
const [selectedCollectionAddress, setSelectedCollectionAddress] = useState<string | undefined>(undefined)
const [collectionTokenCount, setCollectionTokenCount] = useState<number | undefined>(undefined)
const existingBaseMinterState = useInputState({ const existingBaseMinterState = useInputState({
id: 'existingMinter', id: 'existingMinter',
@ -54,7 +59,7 @@ export const BaseMinterDetails = ({ onChange, minterType }: BaseMinterDetailsPro
.then((response) => { .then((response) => {
const collectionData = response.data const collectionData = response.data
const minterContracts = collectionData.map((collection: any) => { const minterContracts = collectionData.map((collection: any) => {
return { name: collection.name, minter: collection.minter } return { name: collection.name, minter: collection.minter, contractAddress: collection.contractAddress }
}) })
return minterContracts return minterContracts
}) })
@ -111,6 +116,8 @@ export const BaseMinterDetails = ({ onChange, minterType }: BaseMinterDetailsPro
const debouncedWalletAddress = useDebounce(wallet.address, 300) const debouncedWalletAddress = useDebounce(wallet.address, 300)
const debouncedExistingBaseMinterContract = useDebounce(existingBaseMinterState.value, 300)
const displayToast = async () => { const displayToast = async () => {
await toast.promise(filterBaseMinterContracts(), { await toast.promise(filterBaseMinterContracts(), {
loading: 'Retrieving previous 1/1 collections...', loading: 'Retrieving previous 1/1 collections...',
@ -119,6 +126,38 @@ export const BaseMinterDetails = ({ onChange, minterType }: BaseMinterDetailsPro
}) })
} }
const fetchSg721Address = async () => {
if (debouncedExistingBaseMinterContract.length === 0) return
await wallet.client
?.queryContractSmart(debouncedExistingBaseMinterContract, {
config: {},
})
.then((response) => {
console.log(response.collection_address)
setSelectedCollectionAddress(response.collection_address)
})
.catch((err) => {
console.log(err)
console.log('Unable to retrieve collection address')
})
}
const fetchCollectionTokenCount = async () => {
if (selectedCollectionAddress === undefined) return
await wallet.client
?.queryContractSmart(selectedCollectionAddress, {
num_tokens: {},
})
.then((response) => {
console.log(response)
setCollectionTokenCount(Number(response.count))
})
.catch((err) => {
console.log(err)
console.log('Unable to retrieve collection token count')
})
}
useEffect(() => { useEffect(() => {
if (debouncedWalletAddress && baseMinterAcquisitionMethod === 'existing') { if (debouncedWalletAddress && baseMinterAcquisitionMethod === 'existing') {
setMyBaseMinterContracts([]) setMyBaseMinterContracts([])
@ -130,14 +169,34 @@ export const BaseMinterDetails = ({ onChange, minterType }: BaseMinterDetailsPro
} }
}, [debouncedWalletAddress, baseMinterAcquisitionMethod]) }, [debouncedWalletAddress, baseMinterAcquisitionMethod])
useEffect(() => {
if (baseMinterAcquisitionMethod === 'existing') {
void fetchSg721Address()
}
}, [debouncedExistingBaseMinterContract])
useEffect(() => {
if (baseMinterAcquisitionMethod === 'existing') {
void fetchCollectionTokenCount()
}
}, [selectedCollectionAddress])
useEffect(() => { useEffect(() => {
const data: BaseMinterDetailsDataProps = { const data: BaseMinterDetailsDataProps = {
baseMinterAcquisitionMethod, baseMinterAcquisitionMethod,
existingBaseMinter: existingBaseMinterState.value, existingBaseMinter: existingBaseMinterState.value,
selectedCollectionAddress,
collectionTokenCount,
} }
onChange(data) onChange(data)
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [existingBaseMinterState.value, baseMinterAcquisitionMethod, wallet.initialized]) }, [
existingBaseMinterState.value,
baseMinterAcquisitionMethod,
wallet.initialized,
selectedCollectionAddress,
collectionTokenCount,
])
return ( return (
<div className="mx-10 mb-4 rounded border-2 border-white/20"> <div className="mx-10 mb-4 rounded border-2 border-white/20">

View File

@ -105,7 +105,7 @@ export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod }: Minti
<InputDateTime minDate={new Date()} onChange={(date) => setTimestamp(date)} value={timestamp} /> <InputDateTime minDate={new Date()} onChange={(date) => setTimestamp(date)} value={timestamp} />
</FormControl> </FormControl>
</FormGroup> </FormGroup>
<TextInput className="p-4 mt-5" {...paymentAddressState} /> <TextInput className="p-4 mt-10" {...paymentAddressState} />
</div> </div>
) )
} }

View File

@ -9,6 +9,7 @@ import { coin } from '@cosmjs/proto-signing'
import clsx from 'clsx' import clsx from 'clsx'
import { Alert } from 'components/Alert' import { Alert } from 'components/Alert'
import { Anchor } from 'components/Anchor' import { Anchor } from 'components/Anchor'
import { AnchorButton } from 'components/AnchorButton'
import { Button } from 'components/Button' import { Button } from 'components/Button'
import { import {
CollectionDetails, CollectionDetails,
@ -297,12 +298,12 @@ const CollectionCreationPage: NextPage = () => {
if (!wallet.initialized) throw new Error('Wallet not connected') if (!wallet.initialized) throw new Error('Wallet not connected')
if (!baseMinterContract) throw new Error('Contract not found') if (!baseMinterContract) throw new Error('Contract not found')
setCreatingCollection(true) setCreatingCollection(true)
setIsMintingComplete(false)
setBaseTokenUri(null) setBaseTokenUri(null)
setCoverImageUrl(null) setCoverImageUrl(null)
setVendingMinterContractAddress(null) setVendingMinterContractAddress(null)
setSg721ContractAddress(null) setSg721ContractAddress(null)
setTransactionHash(null) setTransactionHash(null)
if (uploadDetails?.uploadMethod === 'new') { if (uploadDetails?.uploadMethod === 'new') {
console.log(JSON.stringify(uploadDetails.baseMinterMetadataFile?.text())) console.log(JSON.stringify(uploadDetails.baseMinterMetadataFile?.text()))
setUploading(true) setUploading(true)
@ -330,7 +331,6 @@ const CollectionCreationPage: NextPage = () => {
return result return result
} }
setBaseTokenUri(baseUri) setBaseTokenUri(baseUri)
const result = await baseMinterContract const result = await baseMinterContract
.use(baseMinterDetails?.existingBaseMinter as string) .use(baseMinterDetails?.existingBaseMinter as string)
?.batchMint(wallet.address, `ipfs://${baseUri}`, uploadDetails.assetFiles.length) ?.batchMint(wallet.address, `ipfs://${baseUri}`, uploadDetails.assetFiles.length)
@ -343,6 +343,8 @@ const CollectionCreationPage: NextPage = () => {
duration: 5000, duration: 5000,
}) })
setIsMintingComplete(true) setIsMintingComplete(true)
setSg721ContractAddress(baseMinterDetails?.selectedCollectionAddress as string)
setTransactionHash(result as string)
}) })
.catch((error) => { .catch((error) => {
toast.error(error.message, { style: { maxWidth: 'none' } }) toast.error(error.message, { style: { maxWidth: 'none' } })
@ -361,6 +363,9 @@ const CollectionCreationPage: NextPage = () => {
style: { maxWidth: 'none' }, style: { maxWidth: 'none' },
duration: 5000, duration: 5000,
}) })
setIsMintingComplete(true)
setSg721ContractAddress(baseMinterDetails?.selectedCollectionAddress as string)
setTransactionHash(result)
}) })
.catch((error) => { .catch((error) => {
toast.error(error.message, { style: { maxWidth: 'none' } }) toast.error(error.message, { style: { maxWidth: 'none' } })
@ -933,8 +938,9 @@ const CollectionCreationPage: NextPage = () => {
} }
} }
useEffect(() => { useEffect(() => {
if (vendingMinterContractAddress !== null) scrollRef.current?.scrollIntoView({ behavior: 'smooth' }) if (vendingMinterContractAddress !== null || isMintingComplete)
}, [vendingMinterContractAddress]) scrollRef.current?.scrollIntoView({ behavior: 'smooth' })
}, [vendingMinterContractAddress, isMintingComplete])
useEffect(() => { useEffect(() => {
setBaseTokenUri(uploadDetails?.baseTokenURI as string) setBaseTokenUri(uploadDetails?.baseTokenURI as string)
@ -981,7 +987,7 @@ const CollectionCreationPage: NextPage = () => {
</p> </p>
</div> </div>
<div className="mx-10" ref={scrollRef}> <div className="mx-10" ref={scrollRef}>
<Conditional test={vendingMinterContractAddress !== null}> <Conditional test={vendingMinterContractAddress !== null || isMintingComplete}>
<Alert className="mt-5" type="info"> <Alert className="mt-5" type="info">
<div> <div>
<Conditional test={minterType === 'vending' || isMintingComplete}> <Conditional test={minterType === 'vending' || isMintingComplete}>
@ -1007,80 +1013,145 @@ const CollectionCreationPage: NextPage = () => {
</Anchor> </Anchor>
)} )}
<br /> <br />
<Conditional test={vendingMinterContractAddress === null && isMintingComplete}>
Transaction Hash: {' '}
<Conditional test={NETWORK === 'testnet'}>
<Anchor
className="text-stargaze hover:underline"
external
href={`${BLOCK_EXPLORER_URL}/tx/${transactionHash as string}`}
>
{transactionHash}
</Anchor>
</Conditional>
<Conditional test={NETWORK === 'mainnet'}>
<Anchor
className="text-stargaze hover:underline"
external
href={`${BLOCK_EXPLORER_URL}/txs/${transactionHash as string}`}
>
{transactionHash}
</Anchor>
</Conditional>
<br />
Minter Contract Address:{' '}
<Anchor
className="text-stargaze hover:underline"
external
href={`/contracts/baseMinter/query/?contractAddress=${
baseMinterDetails?.existingBaseMinter as string
}`}
>
{baseMinterDetails?.existingBaseMinter as string}
</Anchor>
<br />
SG721 Contract Address:{' '}
<Anchor
className="text-stargaze hover:underline"
external
href={`/contracts/sg721/query/?contractAddress=${sg721ContractAddress as string}`}
>
{sg721ContractAddress}
</Anchor>
<br />
<div className="flex flex-row mt-2">
<AnchorButton className="text-white" external href={`${STARGAZE_URL}/profile/${wallet.address}`}>
Visit Your Profile
</AnchorButton>
<AnchorButton
className="ml-2 text-white"
external
href={`${STARGAZE_URL}/marketplace/${sg721ContractAddress as string}/${
baseMinterDetails?.collectionTokenCount
? (baseMinterDetails.collectionTokenCount + 1).toString()
: '1'
}`}
>
View the Token(s) on Marketplace
</AnchorButton>
</div>
</Conditional>
</Conditional> </Conditional>
Minter Contract Address:{' '} <Conditional test={vendingMinterContractAddress !== null}>
<Anchor Minter Contract Address:{' '}
className="text-stargaze hover:underline"
external
href={
minterType === 'vending'
? `/contracts/vendingMinter/query/?contractAddress=${vendingMinterContractAddress as string}`
: `/contracts/baseMinter/query/?contractAddress=${vendingMinterContractAddress as string}`
}
>
{vendingMinterContractAddress}
</Anchor>
<br />
SG721 Contract Address:{' '}
<Anchor
className="text-stargaze hover:underline"
external
href={`/contracts/sg721/query/?contractAddress=${sg721ContractAddress as string}`}
>
{sg721ContractAddress}
</Anchor>
<br />
<Conditional test={whitelistContractAddress !== null && whitelistContractAddress !== undefined}>
Whitelist Contract Address:{' '}
<Anchor <Anchor
className="text-stargaze hover:underline" className="text-stargaze hover:underline"
external external
href={`/contracts/whitelist/query/?contractAddress=${whitelistContractAddress as string}`} href={
minterType === 'vending'
? `/contracts/vendingMinter/query/?contractAddress=${vendingMinterContractAddress as string}`
: `/contracts/baseMinter/query/?contractAddress=${vendingMinterContractAddress as string}`
}
> >
{whitelistContractAddress} {vendingMinterContractAddress}
</Anchor> </Anchor>
<br /> <br />
</Conditional> SG721 Contract Address:{' '}
Transaction Hash: {' '}
<Conditional test={NETWORK === 'testnet'}>
<Anchor <Anchor
className="text-stargaze hover:underline" className="text-stargaze hover:underline"
external external
href={`${BLOCK_EXPLORER_URL}/tx/${transactionHash as string}`} href={`/contracts/sg721/query/?contractAddress=${sg721ContractAddress as string}`}
> >
{transactionHash} {sg721ContractAddress}
</Anchor> </Anchor>
</Conditional> <br />
<Conditional test={NETWORK === 'mainnet'}> <Conditional test={whitelistContractAddress !== null && whitelistContractAddress !== undefined}>
<Anchor Whitelist Contract Address:{' '}
className="text-stargaze hover:underline"
external
href={`${BLOCK_EXPLORER_URL}/txs/${transactionHash as string}`}
>
{transactionHash}
</Anchor>
</Conditional>
<Conditional test={minterType === 'vending'}>
<Button className="mt-2">
<Anchor <Anchor
className="text-white" className="text-stargaze hover:underline"
external external
href={`${STARGAZE_URL}/launchpad/${vendingMinterContractAddress as string}`} href={`/contracts/whitelist/query/?contractAddress=${whitelistContractAddress as string}`}
> >
View on Launchpad {whitelistContractAddress}
</Anchor> </Anchor>
</Button> <br />
</Conditional> </Conditional>
<Conditional test={minterType === 'base'}> Transaction Hash: {' '}
<Button className="mt-2"> <Conditional test={NETWORK === 'testnet'}>
<Anchor <Anchor
className="text-white" className="text-stargaze hover:underline"
external external
href={`${STARGAZE_URL}/marketplace/${sg721ContractAddress as string}?sort=price_asc`} href={`${BLOCK_EXPLORER_URL}/tx/${transactionHash as string}`}
> >
View on Marketplace {transactionHash}
</Anchor> </Anchor>
</Button> </Conditional>
<Conditional test={NETWORK === 'mainnet'}>
<Anchor
className="text-stargaze hover:underline"
external
href={`${BLOCK_EXPLORER_URL}/txs/${transactionHash as string}`}
>
{transactionHash}
</Anchor>
</Conditional>
<Conditional test={minterType === 'vending'}>
<Button className="mt-2">
<Anchor
className="text-white"
external
href={`${STARGAZE_URL}/launchpad/${vendingMinterContractAddress as string}`}
>
View on Launchpad
</Anchor>
</Button>
</Conditional>
<Conditional test={minterType === 'base'}>
<div className="flex flex-row mt-2">
<AnchorButton className="text-white" external href={`${STARGAZE_URL}/profile/${wallet.address}`}>
Visit Your Profile
</AnchorButton>
<AnchorButton
className="ml-2 text-white"
external
href={`${STARGAZE_URL}/marketplace/${sg721ContractAddress as string}${
!isMintingComplete ? `?sort=price_asc` : `/1`
}`}
>
View the Collection on Marketplace
</AnchorButton>
</div>
</Conditional>
</Conditional> </Conditional>
</div> </div>
</Alert> </Alert>