Merge pull request #195 from public-awesome/ibc-minter-creation

IBC minter support
This commit is contained in:
Serkan Reis 2023-08-17 16:30:28 +03:00 committed by GitHub
commit 958671a030
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 655 additions and 103 deletions

View File

@ -1,4 +1,4 @@
APP_VERSION=0.7.2 APP_VERSION=0.7.3
NEXT_PUBLIC_PINATA_ENDPOINT_URL=https://api.pinata.cloud/pinning/pinFileToIPFS NEXT_PUBLIC_PINATA_ENDPOINT_URL=https://api.pinata.cloud/pinning/pinFileToIPFS
NEXT_PUBLIC_SG721_CODE_ID=2595 NEXT_PUBLIC_SG721_CODE_ID=2595
@ -8,14 +8,35 @@ NEXT_PUBLIC_OPEN_EDITION_SG721_UPDATABLE_CODE_ID=2596
NEXT_PUBLIC_VENDING_MINTER_CODE_ID=2600 NEXT_PUBLIC_VENDING_MINTER_CODE_ID=2600
NEXT_PUBLIC_VENDING_MINTER_FLEX_CODE_ID=2601 NEXT_PUBLIC_VENDING_MINTER_FLEX_CODE_ID=2601
NEXT_PUBLIC_BASE_MINTER_CODE_ID=2598 NEXT_PUBLIC_BASE_MINTER_CODE_ID=2598
NEXT_PUBLIC_OPEN_EDITION_MINTER_CODE_ID=2579
NEXT_PUBLIC_VENDING_FACTORY_ADDRESS="stars18h7ugh8eaug7wr0w4yjw0ls5s937z35pnkg935ucsek2y9xl3gaqqk4jtx" NEXT_PUBLIC_VENDING_FACTORY_ADDRESS="stars18h7ugh8eaug7wr0w4yjw0ls5s937z35pnkg935ucsek2y9xl3gaqqk4jtx"
NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_ADDRESS="stars1h65nms9gwg4vdktyqj84tu50gwlm34e0eczl5w2ezllxuzfxy9esa9qlt0" NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_ADDRESS="stars1h65nms9gwg4vdktyqj84tu50gwlm34e0eczl5w2ezllxuzfxy9esa9qlt0"
NEXT_PUBLIC_VENDING_FACTORY_FLEX_ADDRESS="stars1hvu2ghqkcnvhtj2fc6wuazxt4dqcftslp2rwkkkcxy269a35a9pq60ug2q" NEXT_PUBLIC_VENDING_FACTORY_FLEX_ADDRESS="stars1hvu2ghqkcnvhtj2fc6wuazxt4dqcftslp2rwkkkcxy269a35a9pq60ug2q"
NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS=
# NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_ADDRESS=
# NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS=
# NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_FLEX_ADDRESS=
# NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_FLEX_ADDRESS=
# NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_ADDRESS=
# NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS=
# NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS=
# NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS=
NEXT_PUBLIC_BASE_FACTORY_ADDRESS="stars1a45hcxty3spnmm2f0papl8v4dk5ew29s4syhn4efte8u5haex99qlkrtnx" NEXT_PUBLIC_BASE_FACTORY_ADDRESS="stars1a45hcxty3spnmm2f0papl8v4dk5ew29s4syhn4efte8u5haex99qlkrtnx"
NEXT_PUBLIC_BASE_FACTORY_UPDATABLE_ADDRESS="stars100xegx2syry4tclkmejjwxk4nfqahvcqhm9qxut5wxuzhj5d9qfsh5nmym" NEXT_PUBLIC_BASE_FACTORY_UPDATABLE_ADDRESS="stars100xegx2syry4tclkmejjwxk4nfqahvcqhm9qxut5wxuzhj5d9qfsh5nmym"
NEXT_PUBLIC_OPEN_EDITION_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e" NEXT_PUBLIC_OPEN_EDITION_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS="stars1fk5dkzcylam8mcpqrn8y9spauvc3d4navtaqurcc49dc3p9f8d3qdkvymx" NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS="stars1fk5dkzcylam8mcpqrn8y9spauvc3d4navtaqurcc49dc3p9f8d3qdkvymx"
NEXT_PUBLIC_OPEN_EDITION_MINTER_CODE_ID=2579
# NEXT_PUBLIC_OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS=
# NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS=
# NEXT_PUBLIC_OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS=
# NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS=
NEXT_PUBLIC_OPEN_EDITION_IBC_FRNZ_FACTORY_ADDRESS="stars1vzffawsjhvspstu5lvtzz2x5n7zh07hnw09c9dfxcj78un05rcms5n3q3e"
NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_FRNZ_FACTORY_ADDRESS="stars1tc09vlgdg8rqyapcxwm9qdq8naj4gym9px4ntue9cs0kse5rvess0nee3a"
NEXT_PUBLIC_SG721_NAME_ADDRESS="stars1fx74nkqkw2748av8j7ew7r3xt9cgjqduwn8m0ur5lhe49uhlsasszc5fhr" NEXT_PUBLIC_SG721_NAME_ADDRESS="stars1fx74nkqkw2748av8j7ew7r3xt9cgjqduwn8m0ur5lhe49uhlsasszc5fhr"
NEXT_PUBLIC_WHITELIST_CODE_ID=2602 NEXT_PUBLIC_WHITELIST_CODE_ID=2602

View File

@ -4,6 +4,9 @@ import { FormControl } from 'components/FormControl'
import { FormGroup } from 'components/FormGroup' import { FormGroup } from 'components/FormGroup'
import { useInputState, 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 { vendingMinterList } from 'config/minter'
import type { TokenInfo } from 'config/token'
import { stars, tokensList } from 'config/token'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { resolveAddress } from 'utils/resolveAddress' import { resolveAddress } from 'utils/resolveAddress'
@ -16,6 +19,7 @@ interface MintingDetailsProps {
numberOfTokens: number | undefined numberOfTokens: number | undefined
uploadMethod: UploadMethod uploadMethod: UploadMethod
minimumMintPrice: number minimumMintPrice: number
mintingTokenFromFactory?: TokenInfo
} }
export interface MintingDetailsDataProps { export interface MintingDetailsDataProps {
@ -24,12 +28,20 @@ export interface MintingDetailsDataProps {
perAddressLimit: number perAddressLimit: number
startTime: string startTime: string
paymentAddress?: string paymentAddress?: string
selectedMintToken?: TokenInfo
} }
export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod, minimumMintPrice }: MintingDetailsProps) => { export const MintingDetails = ({
onChange,
numberOfTokens,
uploadMethod,
minimumMintPrice,
mintingTokenFromFactory,
}: MintingDetailsProps) => {
const wallet = useWallet() const wallet = useWallet()
const [timestamp, setTimestamp] = useState<Date | undefined>() const [timestamp, setTimestamp] = useState<Date | undefined>()
const [selectedMintToken, setSelectedMintToken] = useState<TokenInfo | undefined>(stars)
const numberOfTokensState = useNumberInputState({ const numberOfTokensState = useNumberInputState({
id: 'numberoftokens', id: 'numberoftokens',
@ -43,7 +55,9 @@ export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod, minimum
id: 'unitPrice', id: 'unitPrice',
name: 'unitPrice', name: 'unitPrice',
title: 'Unit Price', title: 'Unit Price',
subtitle: `Price of each token (min. ${minimumMintPrice} STARS)`, subtitle: `Price of each token (min. ${minimumMintPrice} ${
mintingTokenFromFactory ? mintingTokenFromFactory.displayName : 'STARS'
})`,
placeholder: '50', placeholder: '50',
}) })
@ -85,6 +99,7 @@ export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod, minimum
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.trim(), paymentAddress: paymentAddressState.value.trim(),
selectedMintToken,
} }
onChange(data) onChange(data)
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
@ -95,6 +110,7 @@ export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod, minimum
perAddressLimitState.value, perAddressLimitState.value,
timestamp, timestamp,
paymentAddressState.value, paymentAddressState.value,
selectedMintToken,
]) ])
return ( return (
@ -106,7 +122,22 @@ export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod, minimum
isRequired isRequired
value={uploadMethod === 'new' ? numberOfTokens : numberOfTokensState.value} value={uploadMethod === 'new' ? numberOfTokens : numberOfTokensState.value}
/> />
<div className="flex flex-row items-center">
<NumberInput {...unitPriceState} isRequired /> <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 /> <NumberInput {...perAddressLimitState} isRequired />
<FormControl htmlId="timestamp" isRequired subtitle="Minting start time (local)" title="Start Time"> <FormControl htmlId="timestamp" isRequired subtitle="Minting start time (local)" title="Start Time">
<InputDateTime minDate={new Date()} onChange={(date) => setTimestamp(date)} value={timestamp} /> <InputDateTime minDate={new Date()} onChange={(date) => setTimestamp(date)} value={timestamp} />

View File

@ -8,6 +8,7 @@ import { useInputState, useNumberInputState } from 'components/forms/FormInput.h
import { InputDateTime } from 'components/InputDateTime' import { InputDateTime } from 'components/InputDateTime'
import type { WhitelistFlexMember } from 'components/WhitelistFlexUpload' import type { WhitelistFlexMember } from 'components/WhitelistFlexUpload'
import { WhitelistFlexUpload } from 'components/WhitelistFlexUpload' import { WhitelistFlexUpload } from 'components/WhitelistFlexUpload'
import type { TokenInfo } from 'config/token'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { isValidAddress } from 'utils/isValidAddress' import { isValidAddress } from 'utils/isValidAddress'
@ -18,6 +19,7 @@ import { WhitelistUpload } from '../../WhitelistUpload'
interface WhitelistDetailsProps { interface WhitelistDetailsProps {
onChange: (data: WhitelistDetailsDataProps) => void onChange: (data: WhitelistDetailsDataProps) => void
mintingTokenFromFactory?: TokenInfo
} }
export interface WhitelistDetailsDataProps { export interface WhitelistDetailsDataProps {
@ -38,7 +40,7 @@ type WhitelistState = 'none' | 'existing' | 'new'
type WhitelistType = 'standard' | 'flex' type WhitelistType = 'standard' | 'flex'
export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => { export const WhitelistDetails = ({ onChange, mintingTokenFromFactory }: WhitelistDetailsProps) => {
const [whitelistState, setWhitelistState] = useState<WhitelistState>('none') const [whitelistState, setWhitelistState] = useState<WhitelistState>('none')
const [whitelistType, setWhitelistType] = useState<WhitelistType>('standard') const [whitelistType, setWhitelistType] = useState<WhitelistType>('standard')
const [startDate, setStartDate] = useState<Date | undefined>(undefined) const [startDate, setStartDate] = useState<Date | undefined>(undefined)
@ -58,7 +60,9 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
id: 'unit-price', id: 'unit-price',
name: 'unitPrice', name: 'unitPrice',
title: 'Unit Price', 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', placeholder: '25',
}) })

View File

@ -4,6 +4,9 @@ import { FormControl } from 'components/FormControl'
import { FormGroup } from 'components/FormGroup' import { FormGroup } from 'components/FormGroup'
import { useInputState, 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 { openEditionMinterList } from 'config/minter'
import type { TokenInfo } from 'config/token'
import { stars, tokensList } from 'config/token'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { resolveAddress } from 'utils/resolveAddress' import { resolveAddress } from 'utils/resolveAddress'
@ -15,6 +18,7 @@ interface MintingDetailsProps {
onChange: (data: MintingDetailsDataProps) => void onChange: (data: MintingDetailsDataProps) => void
uploadMethod: UploadMethod uploadMethod: UploadMethod
minimumMintPrice: number minimumMintPrice: number
mintTokenFromFactory?: TokenInfo | undefined
} }
export interface MintingDetailsDataProps { export interface MintingDetailsDataProps {
@ -23,19 +27,28 @@ export interface MintingDetailsDataProps {
startTime: string startTime: string
endTime: string endTime: string
paymentAddress?: string paymentAddress?: string
selectedMintToken?: TokenInfo
} }
export const MintingDetails = ({ onChange, uploadMethod, minimumMintPrice }: MintingDetailsProps) => { export const MintingDetails = ({
onChange,
uploadMethod,
minimumMintPrice,
mintTokenFromFactory,
}: MintingDetailsProps) => {
const wallet = useWallet() const wallet = useWallet()
const [timestamp, setTimestamp] = useState<Date | undefined>() const [timestamp, setTimestamp] = useState<Date | undefined>()
const [endTimestamp, setEndTimestamp] = useState<Date | undefined>() const [endTimestamp, setEndTimestamp] = useState<Date | undefined>()
const [selectedMintToken, setSelectedMintToken] = useState<TokenInfo | undefined>(stars)
const unitPriceState = useNumberInputState({ const unitPriceState = useNumberInputState({
id: 'unitPrice', id: 'unitPrice',
name: 'unitPrice', name: 'unitPrice',
title: 'Unit Price', title: 'Mint Price',
subtitle: `Price of each token (min. ${minimumMintPrice} STARS)`, subtitle: `Price of each token (min. ${minimumMintPrice} ${
mintTokenFromFactory ? mintTokenFromFactory.displayName : 'STARS'
})`,
placeholder: '50', placeholder: '50',
}) })
@ -76,15 +89,38 @@ export const MintingDetails = ({ onChange, uploadMethod, minimumMintPrice }: Min
startTime: timestamp ? (timestamp.getTime() * 1_000_000).toString() : '', startTime: timestamp ? (timestamp.getTime() * 1_000_000).toString() : '',
endTime: endTimestamp ? (endTimestamp.getTime() * 1_000_000).toString() : '', endTime: endTimestamp ? (endTimestamp.getTime() * 1_000_000).toString() : '',
paymentAddress: paymentAddressState.value.trim(), paymentAddress: paymentAddressState.value.trim(),
selectedMintToken,
} }
onChange(data) onChange(data)
// eslint-disable-next-line react-hooks/exhaustive-deps // 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,
])
return ( return (
<div className="border-l-[1px] border-gray-500 border-opacity-20"> <div className="border-l-[1px] border-gray-500 border-opacity-20">
<FormGroup subtitle="Information about your minting settings" title="Minting Details"> <FormGroup subtitle="Information about your minting settings" title="Minting Details">
<div className="flex flex-row items-center">
<NumberInput {...unitPriceState} isRequired /> <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 /> <NumberInput {...perAddressLimitState} isRequired />
<FormControl htmlId="timestamp" isRequired subtitle="Minting start time (local)" title="Start Time"> <FormControl htmlId="timestamp" isRequired subtitle="Minting start time (local)" title="Start Time">
<InputDateTime minDate={new Date()} onChange={(date) => setTimestamp(date)} value={timestamp} /> <InputDateTime minDate={new Date()} onChange={(date) => setTimestamp(date)} value={timestamp} />

View File

@ -12,6 +12,8 @@ import type { MinterType } from 'components/collections/actions/Combobox'
import { Conditional } from 'components/Conditional' import { Conditional } from 'components/Conditional'
import { ConfirmationModal } from 'components/ConfirmationModal' import { ConfirmationModal } from 'components/ConfirmationModal'
import { LoadingModal } from 'components/LoadingModal' import { LoadingModal } from 'components/LoadingModal'
import { openEditionMinterList } from 'config/minter'
import type { TokenInfo } from 'config/token'
import { useContracts } from 'contexts/contracts' import { useContracts } from 'contexts/contracts'
import { addLogItem } from 'contexts/log' import { addLogItem } from 'contexts/log'
import { useWallet } from 'contexts/wallet' import { useWallet } from 'contexts/wallet'
@ -47,13 +49,25 @@ import { type RoyaltyDetailsDataProps, RoyaltyDetails } from './RoyaltyDetails'
export type MetadataStorageMethod = 'off-chain' | 'on-chain' export type MetadataStorageMethod = 'off-chain' | 'on-chain'
export interface OpenEditionMinterDetailsDataProps {
imageUploadDetails?: ImageUploadDetailsDataProps
collectionDetails?: CollectionDetailsDataProps
royaltyDetails?: RoyaltyDetailsDataProps
onChainMetadataInputDetails?: OnChainMetadataInputDetailsDataProps
offChainMetadataUploadDetails?: OffChainMetadataUploadDetailsDataProps
mintingDetails?: MintingDetailsDataProps
metadataStorageMethod?: MetadataStorageMethod
}
interface OpenEditionMinterCreatorProps { interface OpenEditionMinterCreatorProps {
onChange: (data: OpenEditionMinterCreatorDataProps) => void onChange: (data: OpenEditionMinterCreatorDataProps) => void
onDetailsChange: (data: OpenEditionMinterDetailsDataProps) => void
openEditionMinterUpdatableCreationFee?: string openEditionMinterUpdatableCreationFee?: string
openEditionMinterCreationFee?: string openEditionMinterCreationFee?: string
minimumMintPrice?: string minimumMintPrice?: string
minimumUpdatableMintPrice?: string minimumUpdatableMintPrice?: string
minterType?: MinterType minterType?: MinterType
mintTokenFromFactory?: TokenInfo | undefined
} }
export interface OpenEditionMinterCreatorDataProps { export interface OpenEditionMinterCreatorDataProps {
@ -65,20 +79,18 @@ export interface OpenEditionMinterCreatorDataProps {
export const OpenEditionMinterCreator = ({ export const OpenEditionMinterCreator = ({
onChange, onChange,
onDetailsChange,
openEditionMinterCreationFee, openEditionMinterCreationFee,
openEditionMinterUpdatableCreationFee, openEditionMinterUpdatableCreationFee,
minimumMintPrice, minimumMintPrice,
minimumUpdatableMintPrice, minimumUpdatableMintPrice,
minterType, minterType,
mintTokenFromFactory,
}: OpenEditionMinterCreatorProps) => { }: OpenEditionMinterCreatorProps) => {
const wallet = useWallet() const wallet = useWallet()
const { openEditionMinter: openEditionMinterContract, openEditionFactory: openEditionFactoryContract } = const { openEditionMinter: openEditionMinterContract, openEditionFactory: openEditionFactoryContract } =
useContracts() useContracts()
const openEditionFactoryMessages = useMemo(
() => openEditionFactoryContract?.use(OPEN_EDITION_FACTORY_ADDRESS),
[openEditionFactoryContract, wallet.address],
)
const [metadataStorageMethod, setMetadataStorageMethod] = useState<MetadataStorageMethod>('off-chain') const [metadataStorageMethod, setMetadataStorageMethod] = useState<MetadataStorageMethod>('off-chain')
const [imageUploadDetails, setImageUploadDetails] = useState<ImageUploadDetailsDataProps | null>(null) const [imageUploadDetails, setImageUploadDetails] = useState<ImageUploadDetailsDataProps | null>(null)
const [collectionDetails, setCollectionDetails] = useState<CollectionDetailsDataProps | null>(null) const [collectionDetails, setCollectionDetails] = useState<CollectionDetailsDataProps | null>(null)
@ -99,6 +111,21 @@ export const OpenEditionMinterCreator = ({
const [sg721ContractAddress, setSg721ContractAddress] = useState<string | null>(null) const [sg721ContractAddress, setSg721ContractAddress] = useState<string | null>(null)
const [transactionHash, setTransactionHash] = 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 = () => { const performOpenEditionMinterChecks = () => {
try { try {
setReadyToCreate(false) setReadyToCreate(false)
@ -257,10 +284,16 @@ export const OpenEditionMinterCreator = ({
if (collectionDetails?.updatable) { if (collectionDetails?.updatable) {
if (Number(mintingDetails.unitPrice) < Number(minimumUpdatableMintPrice)) if (Number(mintingDetails.unitPrice) < Number(minimumUpdatableMintPrice))
throw new Error( 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)) } 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) if (!mintingDetails.perAddressLimit || mintingDetails.perAddressLimit < 1 || mintingDetails.perAddressLimit > 50)
throw new Error('Invalid limit for tokens per address') throw new Error('Invalid limit for tokens per address')
if (mintingDetails.startTime === '') throw new Error('Start time is required') if (mintingDetails.startTime === '') throw new Error('Start time is required')
@ -515,7 +548,7 @@ export const OpenEditionMinterCreator = ({
end_time: mintingDetails?.endTime, end_time: mintingDetails?.endTime,
mint_price: { mint_price: {
amount: Number(mintingDetails?.unitPrice).toString(), amount: Number(mintingDetails?.unitPrice).toString(),
denom: 'ustars', denom: (mintTokenFromFactory?.denom as string) || 'ustars',
}, },
per_address_limit: mintingDetails?.perAddressLimit, per_address_limit: mintingDetails?.perAddressLimit,
payment_address: mintingDetails?.paymentAddress || null, payment_address: mintingDetails?.paymentAddress || null,
@ -537,9 +570,9 @@ export const OpenEditionMinterCreator = ({
} }
console.log('msg: ', msg) console.log('msg: ', msg)
console.log('Using factory address: ', factoryAddressForSelectedDenom)
const payload: OpenEditionFactoryDispatchExecuteArgs = { const payload: OpenEditionFactoryDispatchExecuteArgs = {
contract: collectionDetails?.updatable ? OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS : OPEN_EDITION_FACTORY_ADDRESS, contract: collectionDetails?.updatable ? updatableFactoryAddressForSelectedDenom : factoryAddressForSelectedDenom,
messages: openEditionFactoryMessages, messages: openEditionFactoryMessages,
txSigner: wallet.address, txSigner: wallet.address,
msg, msg,
@ -587,6 +620,27 @@ export const OpenEditionMinterCreator = ({
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [metadataStorageMethod, openEditionMinterContractAddress, sg721ContractAddress, transactionHash]) }, [metadataStorageMethod, openEditionMinterContractAddress, sg721ContractAddress, transactionHash])
useEffect(() => {
const data: OpenEditionMinterDetailsDataProps = {
imageUploadDetails: imageUploadDetails ? imageUploadDetails : undefined,
collectionDetails: collectionDetails ? collectionDetails : undefined,
royaltyDetails: royaltyDetails ? royaltyDetails : undefined,
onChainMetadataInputDetails: onChainMetadataInputDetails ? onChainMetadataInputDetails : undefined,
offChainMetadataUploadDetails: offChainMetadataUploadDetails ? offChainMetadataUploadDetails : undefined,
mintingDetails: mintingDetails ? mintingDetails : undefined,
metadataStorageMethod,
}
onDetailsChange(data)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
imageUploadDetails,
collectionDetails,
royaltyDetails,
onChainMetadataInputDetails,
offChainMetadataUploadDetails,
mintingDetails,
])
return ( return (
<div> <div>
{/* TODO: Cancel once we're able to index on-chain metadata */} {/* TODO: Cancel once we're able to index on-chain metadata */}
@ -671,6 +725,7 @@ export const OpenEditionMinterCreator = ({
? Number(minimumUpdatableMintPrice) / 1000000 ? Number(minimumUpdatableMintPrice) / 1000000
: Number(minimumMintPrice) / 1000000 : Number(minimumMintPrice) / 1000000
} }
mintTokenFromFactory={mintTokenFromFactory}
onChange={setMintingDetails} onChange={setMintingDetails}
uploadMethod={offChainMetadataUploadDetails?.uploadMethod as UploadMethod} uploadMethod={offChainMetadataUploadDetails?.uploadMethod as UploadMethod}
/> />

214
config/minter.ts Normal file
View File

@ -0,0 +1,214 @@
import {
OPEN_EDITION_FACTORY_ADDRESS,
OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS,
OPEN_EDITION_IBC_FRNZ_FACTORY_ADDRESS,
OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS,
OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS,
OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS,
OPEN_EDITION_UPDATABLE_IBC_FRNZ_FACTORY_ADDRESS,
OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS,
VENDING_FACTORY_ADDRESS,
VENDING_FACTORY_FLEX_ADDRESS,
VENDING_FACTORY_UPDATABLE_ADDRESS,
VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS,
VENDING_IBC_ATOM_FACTORY_ADDRESS,
VENDING_IBC_ATOM_FACTORY_FLEX_ADDRESS,
VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS,
VENDING_IBC_ATOM_UPDATABLE_FACTORY_FLEX_ADDRESS,
VENDING_IBC_USDC_FACTORY_ADDRESS,
VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS,
VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS,
VENDING_IBC_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS,
} from 'utils/constants'
import type { TokenInfo } from './token'
import { ibcAtom, ibcFrnz, ibcUsdc, stars } from './token'
export interface MinterInfo {
id: string
factoryAddress: string
supportedToken: TokenInfo
updatable?: boolean
flexible?: boolean
}
export const openEditionStarsMinter: MinterInfo = {
id: 'open-edition-stars-minter',
factoryAddress: OPEN_EDITION_FACTORY_ADDRESS,
supportedToken: stars,
updatable: false,
}
export const openEditionUpdatableStarsMinter: MinterInfo = {
id: 'open-edition-updatable-stars-minter',
factoryAddress: OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS,
supportedToken: stars,
updatable: true,
}
export const openEditionIbcAtomMinter: MinterInfo = {
id: 'open-edition-ibc-atom-minter',
factoryAddress: OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS,
supportedToken: ibcAtom,
updatable: false,
}
export const openEditionUpdatableIbcAtomMinter: MinterInfo = {
id: 'open-edition-updatable-ibc-atom-minter',
factoryAddress: OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS,
supportedToken: ibcAtom,
updatable: true,
}
export const openEditionIbcUsdcMinter: MinterInfo = {
id: 'open-edition-ibc-usdc-minter',
factoryAddress: OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS,
supportedToken: ibcUsdc,
updatable: false,
}
export const openEditionUpdatableIbcUsdcMinter: MinterInfo = {
id: 'open-edition-updatable-ibc-usdc-minter',
factoryAddress: OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS,
supportedToken: ibcUsdc,
updatable: true,
}
export const openEditionIbcFrnzMinter: MinterInfo = {
id: 'open-edition-ibc-frnz-minter',
factoryAddress: OPEN_EDITION_IBC_FRNZ_FACTORY_ADDRESS,
supportedToken: ibcFrnz,
updatable: false,
}
export const openEditionUpdatableIbcFrnzMinter: MinterInfo = {
id: 'open-edition-updatable-ibc-frnz-minter',
factoryAddress: OPEN_EDITION_UPDATABLE_IBC_FRNZ_FACTORY_ADDRESS,
supportedToken: ibcFrnz,
updatable: true,
}
export const openEditionMinterList = [
openEditionStarsMinter,
openEditionUpdatableStarsMinter,
openEditionUpdatableIbcAtomMinter,
openEditionIbcAtomMinter,
openEditionIbcFrnzMinter,
openEditionUpdatableIbcFrnzMinter,
openEditionIbcUsdcMinter,
openEditionUpdatableIbcUsdcMinter,
]
export const vendingStarsMinter: MinterInfo = {
id: 'vending-stars-minter',
factoryAddress: VENDING_FACTORY_ADDRESS,
supportedToken: stars,
updatable: false,
flexible: false,
}
export const vendingUpdatableStarsMinter: MinterInfo = {
id: 'vending-updatable-stars-minter',
factoryAddress: VENDING_FACTORY_UPDATABLE_ADDRESS,
supportedToken: stars,
updatable: true,
flexible: false,
}
export const vendingIbcAtomMinter: MinterInfo = {
id: 'vending-ibc-atom-minter',
factoryAddress: VENDING_IBC_ATOM_FACTORY_ADDRESS,
supportedToken: ibcAtom,
updatable: false,
flexible: false,
}
export const vendingUpdatableIbcAtomMinter: MinterInfo = {
id: 'vending-updatable-ibc-atom-minter',
factoryAddress: VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS,
supportedToken: ibcAtom,
updatable: true,
flexible: false,
}
export const vendingIbcUsdcMinter: MinterInfo = {
id: 'vending-ibc-usdc-minter',
factoryAddress: VENDING_IBC_USDC_FACTORY_ADDRESS,
supportedToken: ibcUsdc,
updatable: false,
flexible: false,
}
export const vendingUpdatableIbcUsdcMinter: MinterInfo = {
id: 'vending-updatable-ibc-usdc-minter',
factoryAddress: VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS,
supportedToken: ibcUsdc,
updatable: true,
flexible: false,
}
export const vendingMinterList = [
vendingStarsMinter,
vendingUpdatableStarsMinter,
vendingIbcAtomMinter,
vendingUpdatableIbcAtomMinter,
vendingIbcUsdcMinter,
vendingUpdatableIbcUsdcMinter,
]
export const flexibleVendingStarsMinter: MinterInfo = {
id: 'flexible-vending-stars-minter',
factoryAddress: VENDING_FACTORY_FLEX_ADDRESS,
supportedToken: stars,
updatable: false,
flexible: true,
}
export const flexibleVendingUpdatableStarsMinter: MinterInfo = {
id: 'flexible-vending-updatable-stars-minter',
factoryAddress: VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS,
supportedToken: stars,
updatable: true,
flexible: true,
}
export const flexibleVendingIbcAtomMinter: MinterInfo = {
id: 'flexible-vending-ibc-atom-minter',
factoryAddress: VENDING_IBC_ATOM_FACTORY_FLEX_ADDRESS,
supportedToken: ibcAtom,
updatable: false,
flexible: true,
}
export const flexibleVendingUpdatableIbcAtomMinter: MinterInfo = {
id: 'flexible-vending-updatable-ibc-atom-minter',
factoryAddress: VENDING_IBC_ATOM_UPDATABLE_FACTORY_FLEX_ADDRESS,
supportedToken: ibcAtom,
updatable: true,
flexible: true,
}
export const flexibleVendingIbcUsdcMinter: MinterInfo = {
id: 'flexible-vending-ibc-usdc-minter',
factoryAddress: VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS,
supportedToken: ibcUsdc,
updatable: false,
flexible: true,
}
export const flexibleVendingUpdatableIbcUsdcMinter: MinterInfo = {
id: 'flexible-vending-updatable-ibc-usdc-minter',
factoryAddress: VENDING_IBC_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS,
supportedToken: ibcUsdc,
updatable: true,
flexible: true,
}
export const flexibleVendingMinterList = [
flexibleVendingStarsMinter,
flexibleVendingUpdatableStarsMinter,
flexibleVendingIbcAtomMinter,
flexibleVendingUpdatableIbcAtomMinter,
flexibleVendingIbcUsdcMinter,
flexibleVendingUpdatableIbcUsdcMinter,
]

43
config/token.ts Normal file
View File

@ -0,0 +1,43 @@
import { NETWORK } from 'utils/constants'
export interface TokenInfo {
id: string
denom: string
displayName: string
decimalPlaces: number
imageURL?: string
symbol?: string
}
export const stars: TokenInfo = {
id: 'stars',
denom: 'ustars',
displayName: 'STARS',
decimalPlaces: 6,
}
export const ibcAtom: TokenInfo = {
id: 'ibc-atom',
denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2',
displayName: 'ATOM',
decimalPlaces: 6,
}
export const ibcUsdc: TokenInfo = {
id: 'ibc-usdc',
denom: 'ibc/D189335C6E4A68B513C10AB227BF1C1D38C746766278BA3EEB4FB14124F1D858',
displayName: 'USDC',
decimalPlaces: 6,
}
export const ibcFrnz: TokenInfo = {
id: 'ibc-frnz',
denom:
NETWORK === 'mainnet'
? 'ibc/7FA7EC64490E3BDE5A1A28CBE73CC0AD22522794957BC891C46321E3A6074DB9'
: 'factory/stars10w5eulj60qp3cfqa0hkmke78qdy2feq6x9xdmd/ufrnz',
displayName: 'FRNZ',
decimalPlaces: 6,
}
export const tokensList = [stars, ibcAtom, ibcUsdc, ibcFrnz]

View File

@ -3,7 +3,6 @@
import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate' import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
import type { Coin } from '@cosmjs/proto-signing' import type { Coin } from '@cosmjs/proto-signing'
import type { logs } from '@cosmjs/stargate' import type { logs } from '@cosmjs/stargate'
import { OPEN_EDITION_FACTORY_ADDRESS, OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS } from 'utils/constants'
export interface CreateOpenEditionMinterResponse { export interface CreateOpenEditionMinterResponse {
readonly openEditionMinterAddress: string readonly openEditionMinterAddress: string
@ -23,6 +22,7 @@ export interface OpenEditionFactoryInstance {
msg: Record<string, unknown>, msg: Record<string, unknown>,
funds: Coin[], funds: Coin[],
updatable?: boolean, updatable?: boolean,
selectedFactoryAddress?: string,
) => Promise<CreateOpenEditionMinterResponse> ) => Promise<CreateOpenEditionMinterResponse>
} }
@ -56,16 +56,9 @@ export const openEditionFactory = (client: SigningCosmWasmClient, txSigner: stri
senderAddress: string, senderAddress: string,
msg: Record<string, unknown>, msg: Record<string, unknown>,
funds: Coin[], funds: Coin[],
updatable?: boolean,
): Promise<CreateOpenEditionMinterResponse> => { ): Promise<CreateOpenEditionMinterResponse> => {
const result = await client.execute( console.log('Contract Address: ', contractAddress)
senderAddress, const result = await client.execute(senderAddress, contractAddress, msg, 'auto', '', funds)
updatable ? OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS : OPEN_EDITION_FACTORY_ADDRESS,
msg,
'auto',
'',
funds,
)
return { return {
openEditionMinterAddress: result.logs[0].events[5].attributes[0].value, openEditionMinterAddress: result.logs[0].events[5].attributes[0].value,

View File

@ -356,9 +356,10 @@ export const openEditionMinter = (client: SigningCosmWasmClient, txSigner: strin
console.log(factoryParameters?.params?.extension?.airdrop_mint_fee_bps) console.log(factoryParameters?.params?.extension?.airdrop_mint_fee_bps)
const price = factoryParameters?.params?.extension?.airdrop_mint_price.amount const price = factoryParameters?.params?.extension?.airdrop_mint_price.amount
const denom = factoryParameters?.params?.extension?.airdrop_mint_price.denom || 'ustars'
if (!price) { if (!price) {
throw new Error( throw new Error(
'Unable to retrieve a valid airdrop mint price. It may be that the given contract address does not belong to a Open Edition Factory.', 'Unable to retrieve a valid airdrop mint price. It may be that the given contract address does not belong to an Open Edition Factory.',
) )
} }
const airdropFee = Number(price) * Number(factoryParameters.params.extension?.airdrop_mint_fee_bps) const airdropFee = Number(price) * Number(factoryParameters.params.extension?.airdrop_mint_fee_bps)
@ -370,7 +371,7 @@ export const openEditionMinter = (client: SigningCosmWasmClient, txSigner: strin
}, },
'auto', 'auto',
'', '',
airdropFee > 0 ? [coin(airdropFee / 100 / 100, 'ustars')] : [], airdropFee > 0 ? [coin(airdropFee / 100 / 100, denom as string)] : [],
) )
return res.transactionHash return res.transactionHash
}) })
@ -386,6 +387,7 @@ export const openEditionMinter = (client: SigningCosmWasmClient, txSigner: strin
}) })
const price = factoryParameters?.params?.extension?.airdrop_mint_price.amount const price = factoryParameters?.params?.extension?.airdrop_mint_price.amount
const denom = factoryParameters?.params?.extension?.airdrop_mint_price.denom || 'ustars'
if (!price) { if (!price) {
throw new Error( throw new Error(
'Unable to retrieve a valid airdrop mint price. It may be that the given contract address does not belong to a Open Edition Factory.', 'Unable to retrieve a valid airdrop mint price. It may be that the given contract address does not belong to a Open Edition Factory.',
@ -403,7 +405,7 @@ export const openEditionMinter = (client: SigningCosmWasmClient, txSigner: strin
sender: senderAddress, sender: senderAddress,
contract: contractAddress, contract: contractAddress,
msg: toUtf8(JSON.stringify(msg)), msg: toUtf8(JSON.stringify(msg)),
funds: airdropFee > 0 ? [coin(airdropFee / 100 / 100, 'ustars')] : [], funds: airdropFee > 0 ? [coin(airdropFee / 100 / 100, denom as string)] : [],
}), }),
} }
@ -426,6 +428,7 @@ export const openEditionMinter = (client: SigningCosmWasmClient, txSigner: strin
}) })
const price = factoryParameters?.params?.extension?.airdrop_mint_price.amount const price = factoryParameters?.params?.extension?.airdrop_mint_price.amount
const denom = factoryParameters?.params?.extension?.airdrop_mint_price.denom || 'ustars'
if (!price) { if (!price) {
throw new Error( throw new Error(
'Unable to retrieve a valid airdrop mint price. It may be that the given contract address does not belong to a Open Edition Factory.', 'Unable to retrieve a valid airdrop mint price. It may be that the given contract address does not belong to a Open Edition Factory.',
@ -443,7 +446,7 @@ export const openEditionMinter = (client: SigningCosmWasmClient, txSigner: strin
sender: senderAddress, sender: senderAddress,
contract: contractAddress, contract: contractAddress,
msg: toUtf8(JSON.stringify(msg)), msg: toUtf8(JSON.stringify(msg)),
funds: airdropFee > 0 ? [coin(airdropFee / 100 / 100, 'ustars')] : [], funds: airdropFee > 0 ? [coin(airdropFee / 100 / 100, denom as string)] : [],
}), }),
} }

View File

@ -1,11 +1,8 @@
/* eslint-disable eslint-comments/disable-enable-pair */ /* eslint-disable eslint-comments/disable-enable-pair */
/* eslint-disable no-nested-ternary */
import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate' import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'
import type { Coin } from '@cosmjs/proto-signing' import type { Coin } from '@cosmjs/proto-signing'
import type { logs } from '@cosmjs/stargate' import type { logs } from '@cosmjs/stargate'
import { VENDING_FACTORY_ADDRESS, VENDING_FACTORY_FLEX_ADDRESS } from 'utils/constants'
import { VENDING_FACTORY_UPDATABLE_ADDRESS } from '../../utils/constants'
export interface CreateVendingMinterResponse { export interface CreateVendingMinterResponse {
readonly vendingMinterAddress: string readonly vendingMinterAddress: string
@ -63,14 +60,7 @@ export const vendingFactory = (client: SigningCosmWasmClient, txSigner: string):
updatable?: boolean, updatable?: boolean,
flex?: boolean, flex?: boolean,
): Promise<CreateVendingMinterResponse> => { ): Promise<CreateVendingMinterResponse> => {
const result = await client.execute( const result = await client.execute(senderAddress, contractAddress, msg, 'auto', '', funds)
senderAddress,
flex ? VENDING_FACTORY_FLEX_ADDRESS : updatable ? VENDING_FACTORY_UPDATABLE_ADDRESS : VENDING_FACTORY_ADDRESS,
msg,
'auto',
'',
funds,
)
return { return {
vendingMinterAddress: result.logs[0].events[5].attributes[0].value, vendingMinterAddress: result.logs[0].events[5].attributes[0].value,

21
env.d.ts vendored
View File

@ -23,11 +23,26 @@ declare namespace NodeJS {
readonly NEXT_PUBLIC_VENDING_MINTER_CODE_ID: string readonly NEXT_PUBLIC_VENDING_MINTER_CODE_ID: string
readonly NEXT_PUBLIC_VENDING_MINTER_FLEX_CODE_ID: string readonly NEXT_PUBLIC_VENDING_MINTER_FLEX_CODE_ID: string
readonly NEXT_PUBLIC_VENDING_FACTORY_ADDRESS: string readonly NEXT_PUBLIC_VENDING_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_OPEN_EDITION_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_OPEN_EDITION_MINTER_CODE_ID: string
readonly NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_ADDRESS: string readonly NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_ADDRESS: string
readonly NEXT_PUBLIC_VENDING_FACTORY_FLEX_ADDRESS: string readonly NEXT_PUBLIC_VENDING_FACTORY_FLEX_ADDRESS: string
readonly NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS: string
readonly NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_FLEX_ADDRESS: string
readonly NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_FLEX_ADDRESS: string
readonly NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS: string
readonly NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS: string
readonly NEXT_PUBLIC_OPEN_EDITION_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_OPEN_EDITION_IBC_FRNZ_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_FRNZ_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_OPEN_EDITION_MINTER_CODE_ID: string
readonly NEXT_PUBLIC_BASE_FACTORY_ADDRESS: string readonly NEXT_PUBLIC_BASE_FACTORY_ADDRESS: string
readonly NEXT_PUBLIC_BASE_FACTORY_UPDATABLE_ADDRESS: string readonly NEXT_PUBLIC_BASE_FACTORY_UPDATABLE_ADDRESS: string
readonly NEXT_PUBLIC_SG721_NAME_ADDRESS: string readonly NEXT_PUBLIC_SG721_NAME_ADDRESS: string

View File

@ -1,6 +1,6 @@
{ {
"name": "stargaze-studio", "name": "stargaze-studio",
"version": "0.7.2", "version": "0.7.3",
"workspaces": [ "workspaces": [
"packages/*" "packages/*"
], ],

View File

@ -33,6 +33,8 @@ import { Conditional } from 'components/Conditional'
import { LoadingModal } from 'components/LoadingModal' import { LoadingModal } from 'components/LoadingModal'
import type { OpenEditionMinterCreatorDataProps } from 'components/openEdition/OpenEditionMinterCreator' import type { OpenEditionMinterCreatorDataProps } from 'components/openEdition/OpenEditionMinterCreator'
import { OpenEditionMinterCreator } from 'components/openEdition/OpenEditionMinterCreator' import { OpenEditionMinterCreator } from 'components/openEdition/OpenEditionMinterCreator'
import { flexibleVendingMinterList, openEditionMinterList, vendingMinterList } from 'config/minter'
import type { TokenInfo } from 'config/token'
import { useContracts } from 'contexts/contracts' import { useContracts } from 'contexts/contracts'
import { addLogItem } from 'contexts/log' import { addLogItem } from 'contexts/log'
import { useWallet } from 'contexts/wallet' import { useWallet } from 'contexts/wallet'
@ -71,6 +73,8 @@ import { uid } from 'utils/random'
import type { MinterType } from '../../components/collections/actions/Combobox' import type { MinterType } from '../../components/collections/actions/Combobox'
import type { UploadMethod } from '../../components/collections/creation/UploadDetails' import type { UploadMethod } from '../../components/collections/creation/UploadDetails'
import { ConfirmationModal } from '../../components/ConfirmationModal' import { ConfirmationModal } from '../../components/ConfirmationModal'
import type { OpenEditionMinterDetailsDataProps } from '../../components/openEdition/OpenEditionMinterCreator'
import { stars, tokensList } from '../../config/token'
import { getAssetType } from '../../utils/getAssetType' import { getAssetType } from '../../utils/getAssetType'
import { isValidAddress } from '../../utils/isValidAddress' import { isValidAddress } from '../../utils/isValidAddress'
@ -86,20 +90,12 @@ const CollectionCreationPage: NextPage = () => {
const scrollRef = useRef<HTMLDivElement>(null) const scrollRef = useRef<HTMLDivElement>(null)
const sidetabRef = useRef<any>(null) const sidetabRef = useRef<any>(null)
const vendingFactoryMessages = useMemo(
() => vendingFactoryContract?.use(VENDING_FACTORY_ADDRESS),
[vendingFactoryContract, wallet.address],
)
const baseFactoryMessages = useMemo(
() => baseFactoryContract?.use(BASE_FACTORY_ADDRESS),
[baseFactoryContract, wallet.address],
)
const [uploadDetails, setUploadDetails] = useState<UploadDetailsDataProps | null>(null) const [uploadDetails, setUploadDetails] = useState<UploadDetailsDataProps | null>(null)
const [collectionDetails, setCollectionDetails] = useState<CollectionDetailsDataProps | null>(null) const [collectionDetails, setCollectionDetails] = useState<CollectionDetailsDataProps | null>(null)
const [baseMinterDetails, setBaseMinterDetails] = useState<BaseMinterDetailsDataProps | null>(null) const [baseMinterDetails, setBaseMinterDetails] = useState<BaseMinterDetailsDataProps | null>(null)
const [openEditionMinterDetails, setOpenEditionMinterDetails] = useState<OpenEditionMinterCreatorDataProps | null>( const [openEditionMinterCreatorData, setOpenEditionMinterCreatorData] =
useState<OpenEditionMinterCreatorDataProps | null>(null)
const [openEditionMinterDetails, setOpenEditionMinterDetails] = useState<OpenEditionMinterDetailsDataProps | null>(
null, null,
) )
const [mintingDetails, setMintingDetails] = useState<MintingDetailsDataProps | null>(null) const [mintingDetails, setMintingDetails] = useState<MintingDetailsDataProps | null>(null)
@ -122,8 +118,23 @@ const CollectionCreationPage: NextPage = () => {
const [minimumOpenEditionUpdatableMintPrice, setMinimumOpenEditionUpdatableMintPrice] = useState<string | null>('0') const [minimumOpenEditionUpdatableMintPrice, setMinimumOpenEditionUpdatableMintPrice] = useState<string | null>('0')
const [minimumFlexMintPrice, setMinimumFlexMintPrice] = useState<string | null>('0') const [minimumFlexMintPrice, setMinimumFlexMintPrice] = useState<string | null>('0')
const [mintTokenFromOpenEditionFactory, setMintTokenFromOpenEditionFactory] = useState<TokenInfo | undefined>(stars)
const [mintTokenFromVendingFactory, setMintTokenFromVendingFactory] = useState<TokenInfo | undefined>(stars)
const [vendingFactoryAddress, setVendingFactoryAddress] = useState<string | null>(VENDING_FACTORY_ADDRESS)
const vendingFactoryMessages = useMemo(
() => vendingFactoryContract?.use(vendingFactoryAddress as string),
[vendingFactoryContract, wallet.address],
)
const baseFactoryMessages = useMemo(
() => baseFactoryContract?.use(BASE_FACTORY_ADDRESS),
[baseFactoryContract, wallet.address],
)
const [uploading, setUploading] = useState(false) const [uploading, setUploading] = useState(false)
const [isMintingComplete, setIsMintingComplete] = useState(false) const [isMintingComplete, setIsMintingComplete] = useState(false)
const [initialParametersFetched, setInitialParametersFetched] = useState(false)
const [creatingCollection, setCreatingCollection] = useState(false) const [creatingCollection, setCreatingCollection] = useState(false)
const [readyToCreateVm, setReadyToCreateVm] = useState(false) const [readyToCreateVm, setReadyToCreateVm] = useState(false)
const [readyToCreateBm, setReadyToCreateBm] = useState(false) const [readyToCreateBm, setReadyToCreateBm] = useState(false)
@ -484,7 +495,10 @@ const CollectionCreationPage: NextPage = () => {
members: whitelistDetails?.members, members: whitelistDetails?.members,
start_time: whitelistDetails?.startTime, start_time: whitelistDetails?.startTime,
end_time: whitelistDetails?.endTime, end_time: whitelistDetails?.endTime,
mint_price: coin(String(Number(whitelistDetails?.unitPrice)), 'ustars'), mint_price: coin(
String(Number(whitelistDetails?.unitPrice)),
mintTokenFromVendingFactory ? mintTokenFromVendingFactory.denom : 'ustars',
),
per_address_limit: whitelistDetails?.perAddressLimit, per_address_limit: whitelistDetails?.perAddressLimit,
member_limit: whitelistDetails?.memberLimit, member_limit: whitelistDetails?.memberLimit,
admins: whitelistDetails?.admins || [wallet.address], admins: whitelistDetails?.admins || [wallet.address],
@ -495,7 +509,10 @@ const CollectionCreationPage: NextPage = () => {
members: whitelistDetails?.members, members: whitelistDetails?.members,
start_time: whitelistDetails?.startTime, start_time: whitelistDetails?.startTime,
end_time: whitelistDetails?.endTime, end_time: whitelistDetails?.endTime,
mint_price: coin(String(Number(whitelistDetails?.unitPrice)), 'ustars'), mint_price: coin(
String(Number(whitelistDetails?.unitPrice)),
mintTokenFromVendingFactory ? mintTokenFromVendingFactory.denom : 'ustars',
),
member_limit: whitelistDetails?.memberLimit, member_limit: whitelistDetails?.memberLimit,
admins: whitelistDetails?.admins || [wallet.address], admins: whitelistDetails?.admins || [wallet.address],
admins_mutable: whitelistDetails?.adminsMutable, admins_mutable: whitelistDetails?.adminsMutable,
@ -532,17 +549,13 @@ const CollectionCreationPage: NextPage = () => {
payment_address: mintingDetails?.paymentAddress ? mintingDetails.paymentAddress : undefined, payment_address: mintingDetails?.paymentAddress ? mintingDetails.paymentAddress : undefined,
mint_price: { mint_price: {
amount: mintingDetails?.unitPrice, amount: mintingDetails?.unitPrice,
denom: 'ustars', denom: (mintTokenFromVendingFactory?.denom as string) || 'ustars',
}, },
per_address_limit: mintingDetails?.perAddressLimit, per_address_limit: mintingDetails?.perAddressLimit,
whitelist, whitelist,
}, },
collection_params: { collection_params: {
code_id: collectionDetails?.updatable code_id: collectionDetails?.updatable ? SG721_UPDATABLE_CODE_ID : SG721_CODE_ID,
? whitelistDetails?.whitelistType === 'flex'
? SG721_CODE_ID
: SG721_UPDATABLE_CODE_ID
: SG721_CODE_ID,
name: collectionDetails?.name, name: collectionDetails?.name,
symbol: collectionDetails?.symbol, symbol: collectionDetails?.symbol,
info: { info: {
@ -563,12 +576,7 @@ const CollectionCreationPage: NextPage = () => {
} }
const payload: VendingFactoryDispatchExecuteArgs = { const payload: VendingFactoryDispatchExecuteArgs = {
contract: contract: vendingFactoryAddress as string,
whitelistDetails?.whitelistState !== 'none' && whitelistDetails?.whitelistType === 'flex'
? VENDING_FACTORY_FLEX_ADDRESS
: collectionDetails?.updatable
? VENDING_FACTORY_UPDATABLE_ADDRESS
: VENDING_FACTORY_ADDRESS,
messages: vendingFactoryMessages, messages: vendingFactoryMessages,
txSigner: wallet.address, txSigner: wallet.address,
msg, msg,
@ -668,8 +676,6 @@ const CollectionCreationPage: NextPage = () => {
setCreatingCollection(false) setCreatingCollection(false)
}) })
} else { } else {
console.log('Here')
console.log(data.baseMinterAddress)
await toast await toast
.promise( .promise(
baseMinterContract baseMinterContract
@ -907,14 +913,24 @@ const CollectionCreationPage: NextPage = () => {
if (mintingDetails.unitPrice === '') throw new Error('Public mint price is required') if (mintingDetails.unitPrice === '') throw new Error('Public mint price is required')
if (whitelistDetails?.whitelistState !== 'none' && whitelistDetails?.whitelistType === 'flex') { if (whitelistDetails?.whitelistState !== 'none' && whitelistDetails?.whitelistType === 'flex') {
if (Number(mintingDetails.unitPrice) < Number(minimumFlexMintPrice)) if (Number(mintingDetails.unitPrice) < Number(minimumFlexMintPrice))
throw new Error(`Invalid unit price: The minimum unit price is ${Number(minimumFlexMintPrice) / 1000000} STARS`) throw new Error(
`Invalid unit price: The minimum unit price is ${Number(minimumFlexMintPrice) / 1000000} ${
mintTokenFromVendingFactory ? mintTokenFromVendingFactory.displayName : 'STARS'
}`,
)
} else if (collectionDetails?.updatable) { } else if (collectionDetails?.updatable) {
if (Number(mintingDetails.unitPrice) < Number(minimumUpdatableMintPrice)) if (Number(mintingDetails.unitPrice) < Number(minimumUpdatableMintPrice))
throw new Error( throw new Error(
`Invalid unit price: The minimum unit price is ${Number(minimumUpdatableMintPrice) / 1000000} STARS`, `Invalid unit price: The minimum unit price is ${Number(minimumUpdatableMintPrice) / 1000000} ${
mintTokenFromVendingFactory ? mintTokenFromVendingFactory.displayName : 'STARS'
}`,
) )
} else if (Number(mintingDetails.unitPrice) < Number(minimumMintPrice)) } else if (Number(mintingDetails.unitPrice) < Number(minimumMintPrice))
throw new Error(`Invalid unit price: The minimum unit price is ${Number(minimumMintPrice) / 1000000} STARS`) throw new Error(
`Invalid unit price: The minimum unit price is ${Number(minimumMintPrice) / 1000000} ${
mintTokenFromVendingFactory ? mintTokenFromVendingFactory.displayName : 'STARS'
}`,
)
if ( if (
!mintingDetails.perAddressLimit || !mintingDetails.perAddressLimit ||
mintingDetails.perAddressLimit < 1 || mintingDetails.perAddressLimit < 1 ||
@ -1047,7 +1063,7 @@ const CollectionCreationPage: NextPage = () => {
} }
} }
const fetchFactoryParameters = async () => { const fetchInitialFactoryParameters = async () => {
const client = wallet.client const client = wallet.client
if (!client) return if (!client) return
if (BASE_FACTORY_ADDRESS) { if (BASE_FACTORY_ADDRESS) {
@ -1122,9 +1138,103 @@ const CollectionCreationPage: NextPage = () => {
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
}) })
setOpenEditionMinterUpdatableCreationFee(openEditionUpdatableFactoryParameters?.params?.creation_fee?.amount) setOpenEditionMinterUpdatableCreationFee(openEditionUpdatableFactoryParameters?.params?.creation_fee?.amount)
setMinimumOpenEditionMintPrice(openEditionUpdatableFactoryParameters?.params?.min_mint_price?.amount) setMinimumOpenEditionUpdatableMintPrice(openEditionUpdatableFactoryParameters?.params?.min_mint_price?.amount)
}
setInitialParametersFetched(true)
}
const fetchOpenEditionFactoryParameters = useCallback(async () => {
const client = wallet.client
if (!client) return
const factoryForSelectedDenom = openEditionMinterList.find(
(minter) =>
minter.supportedToken === openEditionMinterDetails?.mintingDetails?.selectedMintToken &&
minter.updatable === false,
)
const updatableFactoryForSelectedDenom = openEditionMinterList.find(
(minter) =>
minter.supportedToken === openEditionMinterDetails?.mintingDetails?.selectedMintToken &&
minter.updatable === true,
)
if (factoryForSelectedDenom?.factoryAddress) {
const openEditionFactoryParameters = await client
.queryContractSmart(factoryForSelectedDenom.factoryAddress, { params: {} })
.catch((error) => {
toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
})
setOpenEditionMinterCreationFee(openEditionFactoryParameters?.params?.creation_fee?.amount)
if (!openEditionMinterDetails?.collectionDetails?.updatable) {
setMinimumOpenEditionMintPrice(openEditionFactoryParameters?.params?.min_mint_price?.amount)
setMintTokenFromOpenEditionFactory(
tokensList.find((token) => token.denom === openEditionFactoryParameters?.params?.min_mint_price?.denom),
)
} }
} }
if (updatableFactoryForSelectedDenom?.factoryAddress) {
const openEditionUpdatableFactoryParameters = await client
.queryContractSmart(updatableFactoryForSelectedDenom.factoryAddress, { params: {} })
.catch((error) => {
toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
})
setOpenEditionMinterUpdatableCreationFee(openEditionUpdatableFactoryParameters?.params?.creation_fee?.amount)
if (openEditionMinterDetails?.collectionDetails?.updatable) {
setMinimumOpenEditionUpdatableMintPrice(openEditionUpdatableFactoryParameters?.params?.min_mint_price?.amount)
setMintTokenFromOpenEditionFactory(
tokensList.find(
(token) => token.denom === openEditionUpdatableFactoryParameters?.params?.min_mint_price?.denom,
),
)
}
}
}, [
openEditionMinterDetails?.mintingDetails?.selectedMintToken,
openEditionMinterDetails?.collectionDetails?.updatable,
wallet.client,
])
const fetchVendingFactoryParameters = useCallback(async () => {
const client = wallet.client
if (!client) return
const vendingFactoryForSelectedDenom = vendingMinterList
.concat(flexibleVendingMinterList)
.find(
(minter) =>
minter.supportedToken === mintingDetails?.selectedMintToken &&
minter.updatable === collectionDetails?.updatable &&
minter.flexible === (whitelistDetails?.whitelistType === 'flex'),
)?.factoryAddress
if (vendingFactoryForSelectedDenom) {
setVendingFactoryAddress(vendingFactoryForSelectedDenom)
const vendingFactoryParameters = await client
.queryContractSmart(vendingFactoryForSelectedDenom, { params: {} })
.catch((error) => {
toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
})
if (whitelistDetails?.whitelistState !== 'none' && whitelistDetails?.whitelistType === 'flex') {
setVendingMinterFlexCreationFee(vendingFactoryParameters?.params?.creation_fee?.amount)
setMinimumFlexMintPrice(vendingFactoryParameters?.params?.min_mint_price?.amount)
} else if (collectionDetails?.updatable) {
setVendingMinterUpdatableCreationFee(vendingFactoryParameters?.params?.creation_fee?.amount)
setMinimumUpdatableMintPrice(vendingFactoryParameters?.params?.min_mint_price?.amount)
} else {
setVendingMinterCreationFee(vendingFactoryParameters?.params?.creation_fee?.amount)
setMinimumMintPrice(vendingFactoryParameters?.params?.min_mint_price?.amount)
}
setMintTokenFromVendingFactory(
tokensList.find((token) => token.denom === vendingFactoryParameters?.params?.min_mint_price?.denom),
)
}
}, [
collectionDetails?.updatable,
mintingDetails?.selectedMintToken,
wallet.client,
whitelistDetails?.whitelistState,
whitelistDetails?.whitelistType,
])
const checkwalletBalance = async () => { const checkwalletBalance = async () => {
const walletBalance = await wallet.client?.getBalance(wallet.address, 'ustars').then((balance) => { const walletBalance = await wallet.client?.getBalance(wallet.address, 'ustars').then((balance) => {
@ -1165,25 +1275,25 @@ const CollectionCreationPage: NextPage = () => {
const syncCollections = useCallback(async () => { const syncCollections = useCallback(async () => {
const collectionAddress = const collectionAddress =
minterType === 'openEdition' ? openEditionMinterDetails?.sg721ContractAddress : sg721ContractAddress minterType === 'openEdition' ? openEditionMinterCreatorData?.sg721ContractAddress : sg721ContractAddress
if (collectionAddress && SYNC_COLLECTIONS_API_URL) { if (collectionAddress && SYNC_COLLECTIONS_API_URL) {
await axios.get(`${SYNC_COLLECTIONS_API_URL}/${collectionAddress}`).catch((error) => { await axios.get(`${SYNC_COLLECTIONS_API_URL}/${collectionAddress}`).catch((error) => {
console.error('Sync collections: ', error) console.error('Sync collections: ', error)
}) })
} }
}, [minterType, openEditionMinterDetails?.sg721ContractAddress, sg721ContractAddress]) }, [minterType, openEditionMinterCreatorData?.sg721ContractAddress, sg721ContractAddress])
useEffect(() => { useEffect(() => {
if ( if (
vendingMinterContractAddress !== null || vendingMinterContractAddress !== null ||
openEditionMinterDetails?.openEditionMinterContractAddress || openEditionMinterCreatorData?.openEditionMinterContractAddress ||
isMintingComplete isMintingComplete
) { ) {
scrollRef.current?.scrollIntoView({ behavior: 'smooth' }) scrollRef.current?.scrollIntoView({ behavior: 'smooth' })
} }
if ( if (
(minterType === 'vending' && vendingMinterContractAddress !== null) || (minterType === 'vending' && vendingMinterContractAddress !== null) ||
(minterType === 'openEdition' && openEditionMinterDetails?.openEditionMinterContractAddress) || (minterType === 'openEdition' && openEditionMinterCreatorData?.openEditionMinterContractAddress) ||
(minterType === 'base' && vendingMinterContractAddress !== null && isMintingComplete) (minterType === 'base' && vendingMinterContractAddress !== null && isMintingComplete)
) { ) {
void syncCollections() void syncCollections()
@ -1196,7 +1306,7 @@ const CollectionCreationPage: NextPage = () => {
} }
}, [ }, [
vendingMinterContractAddress, vendingMinterContractAddress,
openEditionMinterDetails?.openEditionMinterContractAddress, openEditionMinterCreatorData?.openEditionMinterContractAddress,
isMintingComplete, isMintingComplete,
minterType, minterType,
syncCollections, syncCollections,
@ -1214,9 +1324,19 @@ const CollectionCreationPage: NextPage = () => {
}, [minterType, baseMinterDetails?.baseMinterAcquisitionMethod, uploadDetails?.uploadMethod]) }, [minterType, baseMinterDetails?.baseMinterAcquisitionMethod, uploadDetails?.uploadMethod])
useEffect(() => { useEffect(() => {
void fetchFactoryParameters() if (!initialParametersFetched) {
void fetchInitialFactoryParameters()
}
}, [wallet.client]) }, [wallet.client])
useEffect(() => {
void fetchOpenEditionFactoryParameters()
}, [fetchOpenEditionFactoryParameters])
useEffect(() => {
void fetchVendingFactoryParameters()
}, [fetchVendingFactoryParameters])
return ( return (
<div> <div>
<NextSeo <NextSeo
@ -1248,7 +1368,7 @@ const CollectionCreationPage: NextPage = () => {
</div> </div>
<div className="mx-10" ref={scrollRef}> <div className="mx-10" ref={scrollRef}>
<Conditional <Conditional
test={minterType === 'openEdition' && openEditionMinterDetails?.openEditionMinterContractAddress !== null} test={minterType === 'openEdition' && openEditionMinterCreatorData?.openEditionMinterContractAddress !== null}
> >
<Alert className="mt-5" type="info"> <Alert className="mt-5" type="info">
<div> <div>
@ -1257,10 +1377,10 @@ const CollectionCreationPage: NextPage = () => {
className="text-stargaze hover:underline" className="text-stargaze hover:underline"
external external
href={`/contracts/openEditionMinter/query/?contractAddress=${ href={`/contracts/openEditionMinter/query/?contractAddress=${
openEditionMinterDetails?.openEditionMinterContractAddress as string openEditionMinterCreatorData?.openEditionMinterContractAddress as string
}`} }`}
> >
{openEditionMinterDetails?.openEditionMinterContractAddress as string} {openEditionMinterCreatorData?.openEditionMinterContractAddress as string}
</Anchor> </Anchor>
<br /> <br />
SG721 Contract Address:{' '} SG721 Contract Address:{' '}
@ -1268,10 +1388,10 @@ const CollectionCreationPage: NextPage = () => {
className="text-stargaze hover:underline" className="text-stargaze hover:underline"
external external
href={`/contracts/sg721/query/?contractAddress=${ href={`/contracts/sg721/query/?contractAddress=${
openEditionMinterDetails?.sg721ContractAddress as string openEditionMinterCreatorData?.sg721ContractAddress as string
}`} }`}
> >
{openEditionMinterDetails?.sg721ContractAddress as string} {openEditionMinterCreatorData?.sg721ContractAddress as string}
</Anchor> </Anchor>
<br /> <br />
Transaction Hash: {' '} Transaction Hash: {' '}
@ -1279,18 +1399,18 @@ const CollectionCreationPage: NextPage = () => {
<Anchor <Anchor
className="text-stargaze hover:underline" className="text-stargaze hover:underline"
external external
href={`${BLOCK_EXPLORER_URL}/tx/${openEditionMinterDetails?.transactionHash as string}`} href={`${BLOCK_EXPLORER_URL}/tx/${openEditionMinterCreatorData?.transactionHash as string}`}
> >
{openEditionMinterDetails?.transactionHash} {openEditionMinterCreatorData?.transactionHash}
</Anchor> </Anchor>
</Conditional> </Conditional>
<Conditional test={NETWORK === 'mainnet'}> <Conditional test={NETWORK === 'mainnet'}>
<Anchor <Anchor
className="text-stargaze hover:underline" className="text-stargaze hover:underline"
external external
href={`${BLOCK_EXPLORER_URL}/txs/${openEditionMinterDetails?.transactionHash as string}`} href={`${BLOCK_EXPLORER_URL}/txs/${openEditionMinterCreatorData?.transactionHash as string}`}
> >
{openEditionMinterDetails?.transactionHash} {openEditionMinterCreatorData?.transactionHash}
</Anchor> </Anchor>
</Conditional> </Conditional>
<br /> <br />
@ -1299,7 +1419,7 @@ const CollectionCreationPage: NextPage = () => {
className="text-white" className="text-white"
external external
href={`${STARGAZE_URL}/launchpad/${ href={`${STARGAZE_URL}/launchpad/${
openEditionMinterDetails?.openEditionMinterContractAddress as string openEditionMinterCreatorData?.openEditionMinterContractAddress as string
}`} }`}
> >
View on Launchpad View on Launchpad
@ -1567,8 +1687,10 @@ const CollectionCreationPage: NextPage = () => {
<OpenEditionMinterCreator <OpenEditionMinterCreator
minimumMintPrice={minimumOpenEditionMintPrice as string} minimumMintPrice={minimumOpenEditionMintPrice as string}
minimumUpdatableMintPrice={minimumOpenEditionUpdatableMintPrice as string} minimumUpdatableMintPrice={minimumOpenEditionUpdatableMintPrice as string}
mintTokenFromFactory={mintTokenFromOpenEditionFactory}
minterType={minterType} minterType={minterType}
onChange={setOpenEditionMinterDetails} onChange={setOpenEditionMinterCreatorData}
onDetailsChange={setOpenEditionMinterDetails}
openEditionMinterCreationFee={openEditionMinterCreationFee as string} openEditionMinterCreationFee={openEditionMinterCreationFee as string}
openEditionMinterUpdatableCreationFee={openEditionMinterUpdatableCreationFee as string} openEditionMinterUpdatableCreationFee={openEditionMinterUpdatableCreationFee as string}
/> />
@ -1605,10 +1727,13 @@ const CollectionCreationPage: NextPage = () => {
<Conditional test={minterType === 'vending'}> <Conditional test={minterType === 'vending'}>
<MintingDetails <MintingDetails
minimumMintPrice={ minimumMintPrice={
collectionDetails?.updatable whitelistDetails?.whitelistState !== 'none' && whitelistDetails?.whitelistType === 'flex'
? Number(minimumFlexMintPrice) / 1000000
: collectionDetails?.updatable
? Number(minimumUpdatableMintPrice) / 1000000 ? Number(minimumUpdatableMintPrice) / 1000000
: Number(minimumMintPrice) / 1000000 : Number(minimumMintPrice) / 1000000
} }
mintingTokenFromFactory={mintTokenFromVendingFactory}
numberOfTokens={uploadDetails?.assetFiles.length} numberOfTokens={uploadDetails?.assetFiles.length}
onChange={setMintingDetails} onChange={setMintingDetails}
uploadMethod={uploadDetails?.uploadMethod as UploadMethod} uploadMethod={uploadDetails?.uploadMethod as UploadMethod}
@ -1637,7 +1762,7 @@ const CollectionCreationPage: NextPage = () => {
> >
<div className="my-6"> <div className="my-6">
<Conditional test={minterType === 'vending'}> <Conditional test={minterType === 'vending'}>
<WhitelistDetails onChange={setWhitelistDetails} /> <WhitelistDetails mintingTokenFromFactory={mintTokenFromVendingFactory} onChange={setWhitelistDetails} />
<div className="my-6" /> <div className="my-6" />
</Conditional> </Conditional>
<RoyaltyDetails onChange={setRoyaltyDetails} /> <RoyaltyDetails onChange={setRoyaltyDetails} />

View File

@ -12,10 +12,32 @@ export const VENDING_MINTER_FLEX_CODE_ID = parseInt(process.env.NEXT_PUBLIC_VEND
export const VENDING_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_VENDING_FACTORY_ADDRESS export const VENDING_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_VENDING_FACTORY_ADDRESS
export const VENDING_FACTORY_UPDATABLE_ADDRESS = process.env.NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_ADDRESS export const VENDING_FACTORY_UPDATABLE_ADDRESS = process.env.NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_ADDRESS
export const VENDING_FACTORY_FLEX_ADDRESS = process.env.NEXT_PUBLIC_VENDING_FACTORY_FLEX_ADDRESS export const VENDING_FACTORY_FLEX_ADDRESS = process.env.NEXT_PUBLIC_VENDING_FACTORY_FLEX_ADDRESS
export const VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS = process.env.NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_FLEX_ADDRESS
export const VENDING_IBC_ATOM_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_ADDRESS
export const VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS =
process.env.NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS
export const VENDING_IBC_USDC_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_ADDRESS
export const VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS =
process.env.NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS
export const VENDING_IBC_ATOM_FACTORY_FLEX_ADDRESS = process.env.NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_FLEX_ADDRESS
export const VENDING_IBC_ATOM_UPDATABLE_FACTORY_FLEX_ADDRESS =
process.env.NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_FLEX_ADDRESS
export const VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS = process.env.NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS
export const VENDING_IBC_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS =
process.env.NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS
export const BASE_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_BASE_FACTORY_ADDRESS export const BASE_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_BASE_FACTORY_ADDRESS
export const BASE_FACTORY_UPDATABLE_ADDRESS = process.env.NEXT_PUBLIC_BASE_FACTORY_UPDATABLE_ADDRESS export const BASE_FACTORY_UPDATABLE_ADDRESS = process.env.NEXT_PUBLIC_BASE_FACTORY_UPDATABLE_ADDRESS
export const OPEN_EDITION_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_FACTORY_ADDRESS export const OPEN_EDITION_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_FACTORY_ADDRESS
export const OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS export const OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS
export const OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS
export const OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS =
process.env.NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS
export const OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS
export const OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS =
process.env.NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS
export const OPEN_EDITION_IBC_FRNZ_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_FRNZ_FACTORY_ADDRESS
export const OPEN_EDITION_UPDATABLE_IBC_FRNZ_FACTORY_ADDRESS =
process.env.NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_FRNZ_FACTORY_ADDRESS
export const OPEN_EDITION_MINTER_CODE_ID = parseInt(process.env.NEXT_PUBLIC_OPEN_EDITION_MINTER_CODE_ID, 10) export const OPEN_EDITION_MINTER_CODE_ID = parseInt(process.env.NEXT_PUBLIC_OPEN_EDITION_MINTER_CODE_ID, 10)
export const SG721_NAME_ADDRESS = process.env.NEXT_PUBLIC_SG721_NAME_ADDRESS export const SG721_NAME_ADDRESS = process.env.NEXT_PUBLIC_SG721_NAME_ADDRESS
export const BASE_MINTER_CODE_ID = parseInt(process.env.NEXT_PUBLIC_VENDING_MINTER_CODE_ID, 10) export const BASE_MINTER_CODE_ID = parseInt(process.env.NEXT_PUBLIC_VENDING_MINTER_CODE_ID, 10)