Merge branch 'ibc-minter-creation' into export-import-collection-config
This commit is contained in:
@@ -4,6 +4,9 @@ import { FormControl } from 'components/FormControl'
|
||||
import { FormGroup } from 'components/FormGroup'
|
||||
import { useInputState, useNumberInputState } from 'components/forms/FormInput.hooks'
|
||||
import { InputDateTime } from 'components/InputDateTime'
|
||||
import { vendingMinterList } from 'config/minter'
|
||||
import type { TokenInfo } from 'config/token'
|
||||
import { stars, tokensList } from 'config/token'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { resolveAddress } from 'utils/resolveAddress'
|
||||
|
||||
@@ -16,6 +19,7 @@ interface MintingDetailsProps {
|
||||
numberOfTokens: number | undefined
|
||||
uploadMethod: UploadMethod
|
||||
minimumMintPrice: number
|
||||
mintingTokenFromFactory?: TokenInfo
|
||||
importedMintingDetails?: MintingDetailsDataProps
|
||||
}
|
||||
|
||||
@@ -25,6 +29,7 @@ export interface MintingDetailsDataProps {
|
||||
perAddressLimit: number
|
||||
startTime: string
|
||||
paymentAddress?: string
|
||||
selectedMintToken?: TokenInfo
|
||||
}
|
||||
|
||||
export const MintingDetails = ({
|
||||
@@ -32,11 +37,13 @@ export const MintingDetails = ({
|
||||
numberOfTokens,
|
||||
uploadMethod,
|
||||
minimumMintPrice,
|
||||
mintingTokenFromFactory,
|
||||
importedMintingDetails,
|
||||
}: MintingDetailsProps) => {
|
||||
const wallet = useWallet()
|
||||
|
||||
const [timestamp, setTimestamp] = useState<Date | undefined>()
|
||||
const [selectedMintToken, setSelectedMintToken] = useState<TokenInfo | undefined>(stars)
|
||||
|
||||
const numberOfTokensState = useNumberInputState({
|
||||
id: 'numberoftokens',
|
||||
@@ -50,7 +57,9 @@ export const MintingDetails = ({
|
||||
id: 'unitPrice',
|
||||
name: 'unitPrice',
|
||||
title: 'Unit Price',
|
||||
subtitle: `Price of each token (min. ${minimumMintPrice} STARS)`,
|
||||
subtitle: `Price of each token (min. ${minimumMintPrice} ${
|
||||
mintingTokenFromFactory ? mintingTokenFromFactory.displayName : 'STARS'
|
||||
})`,
|
||||
placeholder: '50',
|
||||
})
|
||||
|
||||
@@ -92,6 +101,7 @@ export const MintingDetails = ({
|
||||
perAddressLimit: perAddressLimitState.value,
|
||||
startTime: timestamp ? (timestamp.getTime() * 1_000_000).toString() : '',
|
||||
paymentAddress: paymentAddressState.value.trim(),
|
||||
selectedMintToken,
|
||||
}
|
||||
onChange(data)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@@ -102,6 +112,7 @@ export const MintingDetails = ({
|
||||
perAddressLimitState.value,
|
||||
timestamp,
|
||||
paymentAddressState.value,
|
||||
selectedMintToken,
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
@@ -124,7 +135,22 @@ export const MintingDetails = ({
|
||||
isRequired
|
||||
value={uploadMethod === 'new' ? numberOfTokens : numberOfTokensState.value}
|
||||
/>
|
||||
<NumberInput {...unitPriceState} isRequired />
|
||||
<div className="flex flex-row items-center">
|
||||
<NumberInput {...unitPriceState} isRequired />
|
||||
<select
|
||||
className="py-[9px] px-4 mt-14 ml-2 placeholder:text-white/50 bg-white/10 rounded border-2 border-white/20 focus:ring focus:ring-plumbus-20"
|
||||
onChange={(e) => setSelectedMintToken(tokensList.find((t) => t.displayName === e.target.value))}
|
||||
>
|
||||
{vendingMinterList
|
||||
.filter((minter) => minter.factoryAddress !== undefined && minter.updatable === false)
|
||||
.map((minter) => (
|
||||
<option key={minter.id} className="bg-black" value={minter.supportedToken.displayName}>
|
||||
{minter.supportedToken.displayName}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<NumberInput {...perAddressLimitState} isRequired />
|
||||
<FormControl htmlId="timestamp" isRequired subtitle="Minting start time (local)" title="Start Time">
|
||||
<InputDateTime minDate={new Date()} onChange={(date) => setTimestamp(date)} value={timestamp} />
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useInputState, useNumberInputState } from 'components/forms/FormInput.h
|
||||
import { InputDateTime } from 'components/InputDateTime'
|
||||
import type { WhitelistFlexMember } from 'components/WhitelistFlexUpload'
|
||||
import { WhitelistFlexUpload } from 'components/WhitelistFlexUpload'
|
||||
import type { TokenInfo } from 'config/token'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { isValidAddress } from 'utils/isValidAddress'
|
||||
|
||||
@@ -18,6 +19,7 @@ import { WhitelistUpload } from '../../WhitelistUpload'
|
||||
|
||||
interface WhitelistDetailsProps {
|
||||
onChange: (data: WhitelistDetailsDataProps) => void
|
||||
mintingTokenFromFactory?: TokenInfo
|
||||
importedWhitelistDetails?: WhitelistDetailsDataProps
|
||||
}
|
||||
|
||||
@@ -39,7 +41,11 @@ type WhitelistState = 'none' | 'existing' | 'new'
|
||||
|
||||
type WhitelistType = 'standard' | 'flex'
|
||||
|
||||
export const WhitelistDetails = ({ onChange, importedWhitelistDetails }: WhitelistDetailsProps) => {
|
||||
export const WhitelistDetails = ({
|
||||
onChange,
|
||||
mintingTokenFromFactory,
|
||||
importedWhitelistDetails,
|
||||
}: WhitelistDetailsProps) => {
|
||||
const [whitelistState, setWhitelistState] = useState<WhitelistState>('none')
|
||||
const [whitelistType, setWhitelistType] = useState<WhitelistType>('standard')
|
||||
const [startDate, setStartDate] = useState<Date | undefined>(undefined)
|
||||
@@ -59,7 +65,9 @@ export const WhitelistDetails = ({ onChange, importedWhitelistDetails }: Whiteli
|
||||
id: 'unit-price',
|
||||
name: 'unitPrice',
|
||||
title: 'Unit Price',
|
||||
subtitle: 'Token price for whitelisted addresses \n (min. 0 STARS)',
|
||||
subtitle: `Token price for whitelisted addresses \n (min. 0 ${
|
||||
mintingTokenFromFactory ? mintingTokenFromFactory.displayName : 'STARS'
|
||||
})`,
|
||||
placeholder: '25',
|
||||
})
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@ import { FormControl } from 'components/FormControl'
|
||||
import { FormGroup } from 'components/FormGroup'
|
||||
import { useInputState, useNumberInputState } from 'components/forms/FormInput.hooks'
|
||||
import { InputDateTime } from 'components/InputDateTime'
|
||||
import { openEditionMinterList } from 'config/minter'
|
||||
import type { TokenInfo } from 'config/token'
|
||||
import { stars, tokensList } from 'config/token'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { resolveAddress } from 'utils/resolveAddress'
|
||||
|
||||
@@ -15,6 +18,7 @@ interface MintingDetailsProps {
|
||||
onChange: (data: MintingDetailsDataProps) => void
|
||||
uploadMethod: UploadMethod
|
||||
minimumMintPrice: number
|
||||
mintTokenFromFactory?: TokenInfo | undefined
|
||||
importedMintingDetails?: MintingDetailsDataProps
|
||||
}
|
||||
|
||||
@@ -24,24 +28,29 @@ export interface MintingDetailsDataProps {
|
||||
startTime: string
|
||||
endTime: string
|
||||
paymentAddress?: string
|
||||
selectedMintToken?: TokenInfo
|
||||
}
|
||||
|
||||
export const MintingDetails = ({
|
||||
onChange,
|
||||
uploadMethod,
|
||||
minimumMintPrice,
|
||||
mintTokenFromFactory,
|
||||
importedMintingDetails,
|
||||
}: MintingDetailsProps) => {
|
||||
const wallet = useWallet()
|
||||
|
||||
const [timestamp, setTimestamp] = useState<Date | undefined>()
|
||||
const [endTimestamp, setEndTimestamp] = useState<Date | undefined>()
|
||||
const [selectedMintToken, setSelectedMintToken] = useState<TokenInfo | undefined>(stars)
|
||||
|
||||
const unitPriceState = useNumberInputState({
|
||||
id: 'unitPrice',
|
||||
name: 'unitPrice',
|
||||
title: 'Unit Price',
|
||||
subtitle: `Price of each token (min. ${minimumMintPrice} STARS)`,
|
||||
title: 'Mint Price',
|
||||
subtitle: `Price of each token (min. ${minimumMintPrice} ${
|
||||
mintTokenFromFactory ? mintTokenFromFactory.displayName : 'STARS'
|
||||
})`,
|
||||
placeholder: '50',
|
||||
})
|
||||
|
||||
@@ -82,10 +91,18 @@ export const MintingDetails = ({
|
||||
startTime: timestamp ? (timestamp.getTime() * 1_000_000).toString() : '',
|
||||
endTime: endTimestamp ? (endTimestamp.getTime() * 1_000_000).toString() : '',
|
||||
paymentAddress: paymentAddressState.value.trim(),
|
||||
selectedMintToken,
|
||||
}
|
||||
onChange(data)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [unitPriceState.value, perAddressLimitState.value, timestamp, endTimestamp, paymentAddressState.value])
|
||||
}, [
|
||||
unitPriceState.value,
|
||||
perAddressLimitState.value,
|
||||
timestamp,
|
||||
endTimestamp,
|
||||
paymentAddressState.value,
|
||||
selectedMintToken,
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
if (importedMintingDetails) {
|
||||
@@ -101,7 +118,22 @@ export const MintingDetails = ({
|
||||
return (
|
||||
<div className="border-l-[1px] border-gray-500 border-opacity-20">
|
||||
<FormGroup subtitle="Information about your minting settings" title="Minting Details">
|
||||
<NumberInput {...unitPriceState} isRequired />
|
||||
<div className="flex flex-row items-center">
|
||||
<NumberInput {...unitPriceState} isRequired />
|
||||
<select
|
||||
className="py-[9px] px-4 mt-14 ml-4 placeholder:text-white/50 bg-white/10 rounded border-2 border-white/20 focus:ring focus:ring-plumbus-20"
|
||||
onChange={(e) => setSelectedMintToken(tokensList.find((t) => t.displayName === e.target.value))}
|
||||
>
|
||||
{openEditionMinterList
|
||||
.filter((minter) => minter.factoryAddress !== undefined && minter.updatable === false)
|
||||
.map((minter) => (
|
||||
<option key={minter.id} className="bg-black" value={minter.supportedToken.displayName}>
|
||||
{minter.supportedToken.displayName}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<NumberInput {...perAddressLimitState} isRequired />
|
||||
<FormControl htmlId="timestamp" isRequired subtitle="Minting start time (local)" title="Start Time">
|
||||
<InputDateTime minDate={new Date()} onChange={(date) => setTimestamp(date)} value={timestamp} />
|
||||
|
||||
@@ -12,6 +12,8 @@ import type { MinterType } from 'components/collections/actions/Combobox'
|
||||
import { Conditional } from 'components/Conditional'
|
||||
import { ConfirmationModal } from 'components/ConfirmationModal'
|
||||
import { LoadingModal } from 'components/LoadingModal'
|
||||
import { openEditionMinterList } from 'config/minter'
|
||||
import type { TokenInfo } from 'config/token'
|
||||
import { useContracts } from 'contexts/contracts'
|
||||
import { addLogItem } from 'contexts/log'
|
||||
import { useWallet } from 'contexts/wallet'
|
||||
@@ -65,6 +67,7 @@ interface OpenEditionMinterCreatorProps {
|
||||
minimumMintPrice?: string
|
||||
minimumUpdatableMintPrice?: string
|
||||
minterType?: MinterType
|
||||
mintTokenFromFactory?: TokenInfo | undefined
|
||||
importedOpenEditionMinterDetails?: OpenEditionMinterDetailsDataProps
|
||||
}
|
||||
|
||||
@@ -83,16 +86,13 @@ export const OpenEditionMinterCreator = ({
|
||||
minimumMintPrice,
|
||||
minimumUpdatableMintPrice,
|
||||
minterType,
|
||||
mintTokenFromFactory,
|
||||
importedOpenEditionMinterDetails,
|
||||
}: OpenEditionMinterCreatorProps) => {
|
||||
const wallet = useWallet()
|
||||
const { openEditionMinter: openEditionMinterContract, openEditionFactory: openEditionFactoryContract } =
|
||||
useContracts()
|
||||
|
||||
const openEditionFactoryMessages = useMemo(
|
||||
() => openEditionFactoryContract?.use(OPEN_EDITION_FACTORY_ADDRESS),
|
||||
[openEditionFactoryContract, wallet.address],
|
||||
)
|
||||
const [metadataStorageMethod, setMetadataStorageMethod] = useState<MetadataStorageMethod>('off-chain')
|
||||
const [imageUploadDetails, setImageUploadDetails] = useState<ImageUploadDetailsDataProps | null>(null)
|
||||
const [collectionDetails, setCollectionDetails] = useState<CollectionDetailsDataProps | null>(null)
|
||||
@@ -113,6 +113,21 @@ export const OpenEditionMinterCreator = ({
|
||||
const [sg721ContractAddress, setSg721ContractAddress] = useState<string | null>(null)
|
||||
const [transactionHash, setTransactionHash] = useState<string | null>(null)
|
||||
|
||||
const factoryAddressForSelectedDenom =
|
||||
openEditionMinterList.find((minter) => minter.supportedToken === mintTokenFromFactory && minter.updatable === false)
|
||||
?.factoryAddress || OPEN_EDITION_FACTORY_ADDRESS
|
||||
const updatableFactoryAddressForSelectedDenom =
|
||||
openEditionMinterList.find((minter) => minter.supportedToken === mintTokenFromFactory && minter.updatable === true)
|
||||
?.factoryAddress || OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS
|
||||
|
||||
const openEditionFactoryMessages = useMemo(
|
||||
() =>
|
||||
openEditionFactoryContract?.use(
|
||||
collectionDetails?.updatable ? updatableFactoryAddressForSelectedDenom : factoryAddressForSelectedDenom,
|
||||
),
|
||||
[openEditionFactoryContract, wallet.address],
|
||||
)
|
||||
|
||||
const performOpenEditionMinterChecks = () => {
|
||||
try {
|
||||
setReadyToCreate(false)
|
||||
@@ -271,10 +286,16 @@ export const OpenEditionMinterCreator = ({
|
||||
if (collectionDetails?.updatable) {
|
||||
if (Number(mintingDetails.unitPrice) < Number(minimumUpdatableMintPrice))
|
||||
throw new Error(
|
||||
`Invalid mint price: The minimum mint price is ${Number(minimumUpdatableMintPrice) / 1000000} STARS`,
|
||||
`Invalid mint price: The minimum mint price is ${Number(minimumUpdatableMintPrice) / 1000000} ${
|
||||
mintTokenFromFactory?.displayName
|
||||
}`,
|
||||
)
|
||||
} else if (Number(mintingDetails.unitPrice) < Number(minimumMintPrice))
|
||||
throw new Error(`Invalid mint price: The minimum mint price is ${Number(minimumMintPrice) / 1000000} STARS`)
|
||||
throw new Error(
|
||||
`Invalid mint price: The minimum mint price is ${Number(minimumMintPrice) / 1000000} ${
|
||||
mintTokenFromFactory?.displayName
|
||||
}`,
|
||||
)
|
||||
if (!mintingDetails.perAddressLimit || mintingDetails.perAddressLimit < 1 || mintingDetails.perAddressLimit > 50)
|
||||
throw new Error('Invalid limit for tokens per address')
|
||||
if (mintingDetails.startTime === '') throw new Error('Start time is required')
|
||||
@@ -527,7 +548,7 @@ export const OpenEditionMinterCreator = ({
|
||||
end_time: mintingDetails?.endTime,
|
||||
mint_price: {
|
||||
amount: Number(mintingDetails?.unitPrice).toString(),
|
||||
denom: 'ustars',
|
||||
denom: (mintTokenFromFactory?.denom as string) || 'ustars',
|
||||
},
|
||||
per_address_limit: mintingDetails?.perAddressLimit,
|
||||
payment_address: mintingDetails?.paymentAddress || null,
|
||||
@@ -548,10 +569,8 @@ export const OpenEditionMinterCreator = ({
|
||||
},
|
||||
}
|
||||
|
||||
console.log('msg: ', msg)
|
||||
|
||||
const payload: OpenEditionFactoryDispatchExecuteArgs = {
|
||||
contract: collectionDetails?.updatable ? OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS : OPEN_EDITION_FACTORY_ADDRESS,
|
||||
contract: collectionDetails?.updatable ? updatableFactoryAddressForSelectedDenom : factoryAddressForSelectedDenom,
|
||||
messages: openEditionFactoryMessages,
|
||||
txSigner: wallet.address,
|
||||
msg,
|
||||
@@ -719,6 +738,7 @@ export const OpenEditionMinterCreator = ({
|
||||
? Number(minimumUpdatableMintPrice) / 1000000
|
||||
: Number(minimumMintPrice) / 1000000
|
||||
}
|
||||
mintTokenFromFactory={mintTokenFromFactory}
|
||||
onChange={setMintingDetails}
|
||||
uploadMethod={offChainMetadataUploadDetails?.uploadMethod as UploadMethod}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user