Instantiate new WL Flex during collection creation

This commit is contained in:
Serkan Reis 2023-04-27 20:19:42 +03:00
parent 0945bcf927
commit ccf1b13f5b
2 changed files with 139 additions and 19 deletions

View File

@ -4,6 +4,8 @@ import { AddressList } from 'components/forms/AddressList'
import { useAddressListState } from 'components/forms/AddressList.hooks'
import { useInputState, useNumberInputState } from 'components/forms/FormInput.hooks'
import { InputDateTime } from 'components/InputDateTime'
import type { WhitelistFlexMember } from 'components/WhitelistFlexUpload'
import { WhitelistFlexUpload } from 'components/WhitelistFlexUpload'
import React, { useEffect, useState } from 'react'
import { isValidAddress } from 'utils/isValidAddress'
@ -20,7 +22,7 @@ export interface WhitelistDetailsDataProps {
whitelistState: WhitelistState
whitelistType: WhitelistType
contractAddress?: string
members?: string[]
members?: string[] | WhitelistFlexMember[]
unitPrice?: string
startTime?: string
endTime?: string
@ -39,7 +41,8 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
const [whitelistType, setWhitelistType] = useState<WhitelistType>('standard')
const [startDate, setStartDate] = useState<Date | undefined>(undefined)
const [endDate, setEndDate] = useState<Date | undefined>(undefined)
const [whitelistArray, setWhitelistArray] = useState<string[]>([])
const [whitelistStandardArray, setWhitelistStandardArray] = useState<string[]>([])
const [whitelistFlexArray, setWhitelistFlexArray] = useState<WhitelistFlexMember[]>([])
const [adminsMutable, setAdminsMutable] = useState<boolean>(true)
const whitelistAddressState = useInputState({
@ -76,9 +79,18 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
const addressListState = useAddressListState()
const whitelistFileOnChange = (data: string[]) => {
setWhitelistArray(data)
setWhitelistStandardArray(data)
}
const whitelistFlexFileOnChange = (whitelistData: WhitelistFlexMember[]) => {
setWhitelistFlexArray(whitelistData)
}
useEffect(() => {
setWhitelistStandardArray([])
setWhitelistFlexArray([])
}, [whitelistType])
useEffect(() => {
const data: WhitelistDetailsDataProps = {
whitelistState,
@ -89,7 +101,7 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
.replace(/"/g, '')
.replace(/'/g, '')
.replace(/ /g, ''),
members: whitelistArray,
members: whitelistType === 'standard' ? whitelistStandardArray : whitelistFlexArray,
unitPrice: unitPriceState.value ? (Number(unitPriceState.value) * 1_000_000).toString() : '',
startTime: startDate ? (startDate.getTime() * 1_000_000).toString() : '',
endTime: endDate ? (endDate.getTime() * 1_000_000).toString() : '',
@ -113,7 +125,8 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
perAddressLimitState.value,
startDate,
endDate,
whitelistArray,
whitelistStandardArray,
whitelistFlexArray,
whitelistState,
addressListState.values,
adminsMutable,
@ -186,11 +199,54 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
</Conditional>
<Conditional test={whitelistState === 'new'}>
<div className="flex justify-between mb-5 ml-6 max-w-[300px] text-lg font-bold">
<div className="form-check form-check-inline">
<input
checked={whitelistType === 'standard'}
className="peer sr-only"
id="inlineRadio7"
name="inlineRadioOptions7"
onClick={() => {
setWhitelistType('standard')
}}
type="radio"
value="nft-storage"
/>
<label
className="inline-block py-1 px-2 text-gray peer-checked:text-white hover:text-white peer-checked:bg-black hover:rounded-sm peer-checked:border-b-2 hover:border-b-2 peer-checked:border-plumbus hover:border-plumbus cursor-pointer form-check-label"
htmlFor="inlineRadio7"
>
Standard Whitelist
</label>
</div>
<div className="form-check form-check-inline">
<input
checked={whitelistType === 'flex'}
className="peer sr-only"
id="inlineRadio8"
name="inlineRadioOptions8"
onClick={() => {
setWhitelistType('flex')
}}
type="radio"
value="flex"
/>
<label
className="inline-block py-1 px-2 text-gray peer-checked:text-white hover:text-white peer-checked:bg-black hover:rounded-sm peer-checked:border-b-2 hover:border-b-2 peer-checked:border-plumbus hover:border-plumbus cursor-pointer form-check-label"
htmlFor="inlineRadio8"
>
Whitelist Flex
</label>
</div>
</div>
<div className="grid grid-cols-2">
<FormGroup subtitle="Information about your minting settings" title="Whitelist Minting Details">
<NumberInput isRequired {...unitPriceState} />
<NumberInput isRequired {...memberLimitState} />
<Conditional test={whitelistType === 'standard'}>
<NumberInput isRequired {...perAddressLimitState} />
</Conditional>
<FormControl
htmlId="start-date"
isRequired
@ -231,11 +287,24 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
title="Administrator Addresses"
/>
</div>
<Conditional test={whitelistType === 'standard'}>
<FormGroup subtitle="TXT file that contains the whitelisted addresses" title="Whitelist File">
<WhitelistUpload onChange={whitelistFileOnChange} />
</FormGroup>
<Conditional test={whitelistArray.length > 0}>
<JsonPreview content={whitelistArray} initialState title="File Contents" />
<Conditional test={whitelistStandardArray.length > 0}>
<JsonPreview content={whitelistStandardArray} initialState title="File Contents" />
</Conditional>
</Conditional>
<Conditional test={whitelistType === 'flex'}>
<FormGroup
subtitle="CSV file that contains the whitelisted addresses and their corresponding mint counts"
title="Whitelist File"
>
<WhitelistFlexUpload onChange={whitelistFlexFileOnChange} />
</FormGroup>
<Conditional test={whitelistFlexArray.length > 0}>
<JsonPreview content={whitelistFlexArray} initialState={false} title="File Contents" />
</Conditional>
</Conditional>
</div>
</div>

View File

@ -49,8 +49,10 @@ import {
SG721_UPDATABLE_CODE_ID,
STARGAZE_URL,
VENDING_FACTORY_ADDRESS,
VENDING_FACTORY_FLEX_ADDRESS,
VENDING_FACTORY_UPDATABLE_ADDRESS,
WHITELIST_CODE_ID,
WHITELIST_FLEX_CODE_ID,
} from 'utils/constants'
import { withMetadata } from 'utils/layout'
import { links } from 'utils/links'
@ -93,9 +95,11 @@ const CollectionCreationPage: NextPage = () => {
const [vendingMinterCreationFee, setVendingMinterCreationFee] = useState<string | null>(null)
const [baseMinterCreationFee, setBaseMinterCreationFee] = useState<string | null>(null)
const [vendingMinterUpdatableCreationFee, setVendingMinterUpdatableCreationFee] = useState<string | null>(null)
const [vendingMinterFlexCreationFee, setVendingMinterFlexCreationFee] = useState<string | null>(null)
const [baseMinterUpdatableCreationFee, setBaseMinterUpdatableCreationFee] = useState<string | null>(null)
const [minimumMintPrice, setMinimumMintPrice] = useState<string | null>('0')
const [minimumUpdatableMintPrice, setMinimumUpdatableMintPrice] = useState<string | null>('0')
const [minimumFlexMintPrice, setMinimumFlexMintPrice] = useState<string | null>('0')
const [uploading, setUploading] = useState(false)
const [isMintingComplete, setIsMintingComplete] = useState(false)
@ -401,7 +405,7 @@ const CollectionCreationPage: NextPage = () => {
if (!wallet.initialized) throw new Error('Wallet not connected')
if (!whitelistContract) throw new Error('Contract not found')
const msg = {
const standardMsg = {
members: whitelistDetails?.members,
start_time: whitelistDetails?.startTime,
end_time: whitelistDetails?.endTime,
@ -412,9 +416,19 @@ const CollectionCreationPage: NextPage = () => {
admins_mutable: whitelistDetails?.adminsMutable,
}
const flexMsg = {
members: whitelistDetails?.members,
start_time: whitelistDetails?.startTime,
end_time: whitelistDetails?.endTime,
mint_price: coin(String(Number(whitelistDetails?.unitPrice)), 'ustars'),
member_limit: whitelistDetails?.memberLimit,
admins: whitelistDetails?.admins || [wallet.address],
admins_mutable: whitelistDetails?.adminsMutable,
}
const data = await whitelistContract.instantiate(
WHITELIST_CODE_ID,
msg,
whitelistDetails?.whitelistType === 'standard' ? WHITELIST_CODE_ID : WHITELIST_FLEX_CODE_ID,
whitelistDetails?.whitelistType === 'standard' ? standardMsg : flexMsg,
'Stargaze Whitelist Contract',
wallet.address,
)
@ -469,20 +483,40 @@ const CollectionCreationPage: NextPage = () => {
},
}
console.log('Whitelist State: ', whitelistDetails?.whitelistState)
console.log('Whitelist Type: ', whitelistDetails?.whitelistType)
console.log(
'Factory Address: ',
whitelistDetails?.whitelistState === 'new' && whitelistDetails.whitelistType === 'flex'
? VENDING_FACTORY_FLEX_ADDRESS
: collectionDetails?.updatable
? VENDING_FACTORY_UPDATABLE_ADDRESS
: VENDING_FACTORY_ADDRESS,
)
console.log('Whitelist: ', whitelist)
const payload: VendingFactoryDispatchExecuteArgs = {
contract: collectionDetails?.updatable ? VENDING_FACTORY_UPDATABLE_ADDRESS : VENDING_FACTORY_ADDRESS,
contract:
whitelistDetails?.whitelistState === 'new' && whitelistDetails.whitelistType === 'flex'
? VENDING_FACTORY_FLEX_ADDRESS
: collectionDetails?.updatable
? VENDING_FACTORY_UPDATABLE_ADDRESS
: VENDING_FACTORY_ADDRESS,
messages: vendingFactoryMessages,
txSigner: wallet.address,
msg,
funds: [
coin(
collectionDetails?.updatable
whitelistDetails?.whitelistState === 'new' && whitelistDetails.whitelistType === 'flex'
? (vendingMinterFlexCreationFee as string)
: collectionDetails?.updatable
? (vendingMinterUpdatableCreationFee as string)
: (vendingMinterCreationFee as string),
'ustars',
),
],
updatable: collectionDetails?.updatable,
flex: whitelistDetails?.whitelistState === 'new' && whitelistDetails.whitelistType === 'flex',
}
const data = await vendingFactoryDispatchExecute(payload)
setTransactionHash(data.transactionHash)
@ -786,7 +820,10 @@ const CollectionCreationPage: NextPage = () => {
const checkMintingDetails = () => {
if (!mintingDetails) throw new Error('Please fill out the minting details')
if (mintingDetails.numTokens < 1 || mintingDetails.numTokens > 10000) throw new Error('Invalid number of tokens')
if (collectionDetails?.updatable) {
if (whitelistDetails?.whitelistState === 'new' && whitelistDetails.whitelistType === 'flex') {
if (Number(mintingDetails.unitPrice) < Number(minimumFlexMintPrice))
throw new Error(`Invalid unit price: The minimum unit price is ${Number(minimumFlexMintPrice) / 1000000} STARS`)
} else if (collectionDetails?.updatable) {
if (Number(mintingDetails.unitPrice) < Number(minimumUpdatableMintPrice))
throw new Error(
`Invalid unit price: The minimum unit price is ${Number(minimumUpdatableMintPrice) / 1000000} STARS`,
@ -859,7 +896,10 @@ const CollectionCreationPage: NextPage = () => {
throw new Error('Invalid unit price: The unit price cannot be negative')
if (whitelistDetails.startTime === '') throw new Error('Start time is required')
if (whitelistDetails.endTime === '') throw new Error('End time is required')
if (!whitelistDetails.perAddressLimit || whitelistDetails.perAddressLimit === 0)
if (
whitelistDetails.whitelistType === 'standard' &&
(!whitelistDetails.perAddressLimit || whitelistDetails.perAddressLimit === 0)
)
throw new Error('Per address limit is required')
if (!whitelistDetails.memberLimit || whitelistDetails.memberLimit === 0)
throw new Error('Member limit is required')
@ -945,6 +985,13 @@ const CollectionCreationPage: NextPage = () => {
setVendingMinterUpdatableCreationFee(vendingFactoryUpdatableParameters?.params?.creation_fee?.amount)
setMinimumUpdatableMintPrice(vendingFactoryUpdatableParameters?.params?.min_mint_price?.amount)
}
if (VENDING_FACTORY_FLEX_ADDRESS) {
const vendingFactoryFlexParameters = await client.queryContractSmart(VENDING_FACTORY_FLEX_ADDRESS, {
params: {},
})
setVendingMinterFlexCreationFee(vendingFactoryFlexParameters?.params?.creation_fee?.amount)
setMinimumFlexMintPrice(vendingFactoryFlexParameters?.params?.min_mint_price?.amount)
}
}
const checkwalletBalance = () => {
@ -952,7 +999,11 @@ const CollectionCreationPage: NextPage = () => {
if (minterType === 'vending' && whitelistDetails?.whitelistState === 'new' && whitelistDetails.memberLimit) {
const amountNeeded =
Math.ceil(Number(whitelistDetails.memberLimit) / 1000) * 100000000 +
(collectionDetails?.updatable ? Number(vendingMinterUpdatableCreationFee) : Number(vendingMinterCreationFee))
(whitelistDetails.whitelistType === 'flex'
? Number(vendingMinterFlexCreationFee)
: collectionDetails?.updatable
? Number(vendingMinterUpdatableCreationFee)
: Number(vendingMinterCreationFee))
if (amountNeeded >= Number(wallet.balance[0].amount))
throw new Error(
`Insufficient wallet balance to instantiate the required contracts. Needed amount: ${(