Standard collection creation now includes optional payment address input

This commit is contained in:
Serkan Reis 2023-03-18 16:11:40 +03:00
parent 8255c8dd92
commit 6da52258b2
3 changed files with 45 additions and 7 deletions

View File

@ -142,9 +142,9 @@ export const CollectionDetails = ({ onChange, uploadMethod, coverImageUrl, minte
<TextInput className="mt-2" {...symbolState} isRequired /> <TextInput className="mt-2" {...symbolState} isRequired />
</div> </div>
<div className={clsx(minterType === 'base' ? 'ml-10' : '')}> <div className={clsx(minterType === 'base' ? 'ml-10' : '')}>
<TextInput {...externalLinkState} /> <TextInput className="mt-2" {...externalLinkState} />
<FormControl <FormControl
className={clsx(minterType === 'base' ? 'mt-12' : '')} className={clsx(minterType === 'base' ? 'mt-12' : 'mt-2')}
htmlId="timestamp" htmlId="timestamp"
subtitle="Trading start time offset will be set as 2 weeks by default." subtitle="Trading start time offset will be set as 2 weeks by default."
title="Trading Start Time (optional)" title="Trading Start Time (optional)"
@ -163,6 +163,8 @@ export const CollectionDetails = ({ onChange, uploadMethod, coverImageUrl, minte
<input <input
accept="image/*" accept="image/*"
className={clsx( className={clsx(
minterType === 'base' ? 'w-1/2' : 'w-full',
'p-[13px] rounded border-2 border-white/20 border-dashed cursor-pointer h-18',
'file:py-2 file:px-4 file:mr-4 file:bg-plumbus-light file:rounded file:border-0 cursor-pointer', 'file:py-2 file:px-4 file:mr-4 file:bg-plumbus-light file:rounded file:border-0 cursor-pointer',
'before:hover:bg-white/5 before:transition', 'before:hover:bg-white/5 before:transition',
)} )}
@ -196,7 +198,7 @@ export const CollectionDetails = ({ onChange, uploadMethod, coverImageUrl, minte
</FormControl> </FormControl>
<div className={clsx(minterType === 'base' ? 'flex flex-col -ml-16 space-y-2' : 'flex flex-col space-y-2')}> <div className={clsx(minterType === 'base' ? 'flex flex-col -ml-16 space-y-2' : 'flex flex-col space-y-2')}>
<div> <div>
<div className="flex"> <div className="flex mt-4">
<span className="mt-1 ml-[2px] text-sm first-letter:capitalize"> <span className="mt-1 ml-[2px] text-sm first-letter:capitalize">
Does the collection contain explicit content? Does the collection contain explicit content?
</span> </span>
@ -240,11 +242,12 @@ export const CollectionDetails = ({ onChange, uploadMethod, coverImageUrl, minte
</div> </div>
</div> </div>
<Tooltip <Tooltip
backgroundColor="bg-blue-500"
label={ label={
<div className="grid grid-flow-row"> <div className="grid grid-flow-row">
<span> <span>
When enabled, the metadata for tokens can be updated after the collection is created until the When enabled, the metadata for tokens can be updated after the collection is created until the
metadata is frozen by the creator. collection is frozen by the creator.
</span> </span>
</div> </div>
} }

View File

@ -1,10 +1,12 @@
import { FormControl } from 'components/FormControl' import { FormControl } from 'components/FormControl'
import { FormGroup } from 'components/FormGroup' import { FormGroup } from 'components/FormGroup'
import { useNumberInputState } from 'components/forms/FormInput.hooks' import { useInputState, useNumberInputState } from 'components/forms/FormInput.hooks'
import { InputDateTime } from 'components/InputDateTime' import { InputDateTime } from 'components/InputDateTime'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { resolveAddress } from 'utils/resolveAddress'
import { NumberInput } from '../../forms/FormInput' import { useWallet } from '../../../contexts/wallet'
import { NumberInput, TextInput } from '../../forms/FormInput'
import type { UploadMethod } from './UploadDetails' import type { UploadMethod } from './UploadDetails'
interface MintingDetailsProps { interface MintingDetailsProps {
@ -18,9 +20,12 @@ export interface MintingDetailsDataProps {
unitPrice: string unitPrice: string
perAddressLimit: number perAddressLimit: number
startTime: string startTime: string
paymentAddress?: string
} }
export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod }: MintingDetailsProps) => { export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod }: MintingDetailsProps) => {
const wallet = useWallet()
const [timestamp, setTimestamp] = useState<Date | undefined>() const [timestamp, setTimestamp] = useState<Date | undefined>()
const numberOfTokensState = useNumberInputState({ const numberOfTokensState = useNumberInputState({
@ -47,6 +52,24 @@ export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod }: Minti
placeholder: '1', placeholder: '1',
}) })
const paymentAddressState = useInputState({
id: 'payment-address',
name: 'paymentAddress',
title: 'Payment Address (optional)',
subtitle: 'Address to receive minting revenues (defaults to current wallet address)',
placeholder: 'stars1234567890abcdefghijklmnopqrstuvwxyz...',
})
const resolvePaymentAddress = async () => {
await resolveAddress(paymentAddressState.value.trim(), wallet).then((resolvedAddress) => {
paymentAddressState.onChange(resolvedAddress)
})
}
useEffect(() => {
void resolvePaymentAddress()
}, [paymentAddressState.value])
useEffect(() => { useEffect(() => {
if (numberOfTokens) numberOfTokensState.onChange(numberOfTokens) if (numberOfTokens) numberOfTokensState.onChange(numberOfTokens)
const data: MintingDetailsDataProps = { const data: MintingDetailsDataProps = {
@ -54,10 +77,18 @@ export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod }: Minti
unitPrice: unitPriceState.value ? (Number(unitPriceState.value) * 1_000_000).toString() : '', unitPrice: unitPriceState.value ? (Number(unitPriceState.value) * 1_000_000).toString() : '',
perAddressLimit: perAddressLimitState.value, perAddressLimit: perAddressLimitState.value,
startTime: timestamp ? (timestamp.getTime() * 1_000_000).toString() : '', startTime: timestamp ? (timestamp.getTime() * 1_000_000).toString() : '',
paymentAddress: paymentAddressState.value,
} }
onChange(data) onChange(data)
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [numberOfTokens, numberOfTokensState.value, unitPriceState.value, perAddressLimitState.value, timestamp]) }, [
numberOfTokens,
numberOfTokensState.value,
unitPriceState.value,
perAddressLimitState.value,
timestamp,
paymentAddressState.value,
])
return ( return (
<div> <div>
@ -74,6 +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} />
</div> </div>
) )
} }

View File

@ -414,6 +414,7 @@ const CollectionCreationPage: NextPage = () => {
base_token_uri: `${uploadDetails?.uploadMethod === 'new' ? `ipfs://${baseUri}` : `${baseUri}`}`, base_token_uri: `${uploadDetails?.uploadMethod === 'new' ? `ipfs://${baseUri}` : `${baseUri}`}`,
start_time: mintingDetails?.startTime, start_time: mintingDetails?.startTime,
num_tokens: mintingDetails?.numTokens, num_tokens: mintingDetails?.numTokens,
payment_address: mintingDetails?.paymentAddress ? mintingDetails.paymentAddress : undefined,
mint_price: { mint_price: {
amount: mintingDetails?.unitPrice, amount: mintingDetails?.unitPrice,
denom: 'ustars', denom: 'ustars',
@ -769,6 +770,8 @@ const CollectionCreationPage: NextPage = () => {
) )
if (mintingDetails.startTime === '') throw new Error('Start time is required') if (mintingDetails.startTime === '') throw new Error('Start time is required')
if (Number(mintingDetails.startTime) < new Date().getTime() * 1000000) throw new Error('Invalid start time') if (Number(mintingDetails.startTime) < new Date().getTime() * 1000000) throw new Error('Invalid start time')
if (mintingDetails.paymentAddress && !isValidAddress(mintingDetails.paymentAddress))
throw new Error('Invalid payment address')
} }
const checkWhitelistDetails = async () => { const checkWhitelistDetails = async () => {