diff --git a/.env.example b/.env.example index 46be8b3..ffe2835 100644 --- a/.env.example +++ b/.env.example @@ -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_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_FLEX_CODE_ID=2601 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_UPDATABLE_ADDRESS="stars1h65nms9gwg4vdktyqj84tu50gwlm34e0eczl5w2ezllxuzfxy9esa9qlt0" 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_UPDATABLE_ADDRESS="stars100xegx2syry4tclkmejjwxk4nfqahvcqhm9qxut5wxuzhj5d9qfsh5nmym" + NEXT_PUBLIC_OPEN_EDITION_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e" 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_WHITELIST_CODE_ID=2602 @@ -33,4 +54,4 @@ NEXT_PUBLIC_NETWORK=testnet NEXT_PUBLIC_STARGAZE_WEBSITE_URL=https://testnet.publicawesome.dev NEXT_PUBLIC_BADGES_URL=https://badges.publicawesome.dev NEXT_PUBLIC_WEBSITE_URL=https:// -NEXT_PUBLIC_SYNC_COLLECTIONS_API_URL="https://..." \ No newline at end of file +NEXT_PUBLIC_SYNC_COLLECTIONS_API_URL="https://..." diff --git a/components/collections/creation/MintingDetails.tsx b/components/collections/creation/MintingDetails.tsx index 6ca136e..8246327 100644 --- a/components/collections/creation/MintingDetails.tsx +++ b/components/collections/creation/MintingDetails.tsx @@ -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 } export interface MintingDetailsDataProps { @@ -24,12 +28,20 @@ export interface MintingDetailsDataProps { perAddressLimit: number startTime: 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 [timestamp, setTimestamp] = useState() + const [selectedMintToken, setSelectedMintToken] = useState(stars) const numberOfTokensState = useNumberInputState({ id: 'numberoftokens', @@ -43,7 +55,9 @@ export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod, minimum 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', }) @@ -85,6 +99,7 @@ export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod, minimum 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 @@ -95,6 +110,7 @@ export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod, minimum perAddressLimitState.value, timestamp, paymentAddressState.value, + selectedMintToken, ]) return ( @@ -106,7 +122,22 @@ export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod, minimum isRequired value={uploadMethod === 'new' ? numberOfTokens : numberOfTokensState.value} /> - +
+ + +
+ setTimestamp(date)} value={timestamp} /> diff --git a/components/collections/creation/WhitelistDetails.tsx b/components/collections/creation/WhitelistDetails.tsx index 3f9daa7..e047e0d 100644 --- a/components/collections/creation/WhitelistDetails.tsx +++ b/components/collections/creation/WhitelistDetails.tsx @@ -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 } export interface WhitelistDetailsDataProps { @@ -38,7 +40,7 @@ type WhitelistState = 'none' | 'existing' | 'new' type WhitelistType = 'standard' | 'flex' -export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => { +export const WhitelistDetails = ({ onChange, mintingTokenFromFactory }: WhitelistDetailsProps) => { const [whitelistState, setWhitelistState] = useState('none') const [whitelistType, setWhitelistType] = useState('standard') const [startDate, setStartDate] = useState(undefined) @@ -58,7 +60,9 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => { 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', }) diff --git a/components/openEdition/MintingDetails.tsx b/components/openEdition/MintingDetails.tsx index 8b6acd5..5562c43 100644 --- a/components/openEdition/MintingDetails.tsx +++ b/components/openEdition/MintingDetails.tsx @@ -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 } export interface MintingDetailsDataProps { @@ -23,19 +27,28 @@ export interface MintingDetailsDataProps { startTime: string endTime: string paymentAddress?: string + selectedMintToken?: TokenInfo } -export const MintingDetails = ({ onChange, uploadMethod, minimumMintPrice }: MintingDetailsProps) => { +export const MintingDetails = ({ + onChange, + uploadMethod, + minimumMintPrice, + mintTokenFromFactory, +}: MintingDetailsProps) => { const wallet = useWallet() const [timestamp, setTimestamp] = useState() const [endTimestamp, setEndTimestamp] = useState() + const [selectedMintToken, setSelectedMintToken] = useState(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', }) @@ -76,15 +89,38 @@ export const MintingDetails = ({ onChange, uploadMethod, minimumMintPrice }: Min 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, + ]) return (
- +
+ + +
+ setTimestamp(date)} value={timestamp} /> diff --git a/components/openEdition/OpenEditionMinterCreator.tsx b/components/openEdition/OpenEditionMinterCreator.tsx index 3260caa..1c62c29 100644 --- a/components/openEdition/OpenEditionMinterCreator.tsx +++ b/components/openEdition/OpenEditionMinterCreator.tsx @@ -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' @@ -47,13 +49,25 @@ import { type RoyaltyDetailsDataProps, RoyaltyDetails } from './RoyaltyDetails' 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 { onChange: (data: OpenEditionMinterCreatorDataProps) => void + onDetailsChange: (data: OpenEditionMinterDetailsDataProps) => void openEditionMinterUpdatableCreationFee?: string openEditionMinterCreationFee?: string minimumMintPrice?: string minimumUpdatableMintPrice?: string minterType?: MinterType + mintTokenFromFactory?: TokenInfo | undefined } export interface OpenEditionMinterCreatorDataProps { @@ -65,20 +79,18 @@ export interface OpenEditionMinterCreatorDataProps { export const OpenEditionMinterCreator = ({ onChange, + onDetailsChange, openEditionMinterCreationFee, openEditionMinterUpdatableCreationFee, minimumMintPrice, minimumUpdatableMintPrice, minterType, + mintTokenFromFactory, }: 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('off-chain') const [imageUploadDetails, setImageUploadDetails] = useState(null) const [collectionDetails, setCollectionDetails] = useState(null) @@ -99,6 +111,21 @@ export const OpenEditionMinterCreator = ({ const [sg721ContractAddress, setSg721ContractAddress] = useState(null) const [transactionHash, setTransactionHash] = useState(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) @@ -257,10 +284,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') @@ -515,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, @@ -537,9 +570,9 @@ export const OpenEditionMinterCreator = ({ } console.log('msg: ', msg) - + console.log('Using factory address: ', factoryAddressForSelectedDenom) 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, @@ -587,6 +620,27 @@ export const OpenEditionMinterCreator = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [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 (
{/* TODO: Cancel once we're able to index on-chain metadata */} @@ -671,6 +725,7 @@ export const OpenEditionMinterCreator = ({ ? Number(minimumUpdatableMintPrice) / 1000000 : Number(minimumMintPrice) / 1000000 } + mintTokenFromFactory={mintTokenFromFactory} onChange={setMintingDetails} uploadMethod={offChainMetadataUploadDetails?.uploadMethod as UploadMethod} /> diff --git a/config/minter.ts b/config/minter.ts new file mode 100644 index 0000000..528f60b --- /dev/null +++ b/config/minter.ts @@ -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, +] diff --git a/config/token.ts b/config/token.ts new file mode 100644 index 0000000..7cb99b6 --- /dev/null +++ b/config/token.ts @@ -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] diff --git a/contracts/openEditionFactory/contract.ts b/contracts/openEditionFactory/contract.ts index d512b8a..7f20216 100644 --- a/contracts/openEditionFactory/contract.ts +++ b/contracts/openEditionFactory/contract.ts @@ -3,7 +3,6 @@ import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate' import type { Coin } from '@cosmjs/proto-signing' import type { logs } from '@cosmjs/stargate' -import { OPEN_EDITION_FACTORY_ADDRESS, OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS } from 'utils/constants' export interface CreateOpenEditionMinterResponse { readonly openEditionMinterAddress: string @@ -23,6 +22,7 @@ export interface OpenEditionFactoryInstance { msg: Record, funds: Coin[], updatable?: boolean, + selectedFactoryAddress?: string, ) => Promise } @@ -56,16 +56,9 @@ export const openEditionFactory = (client: SigningCosmWasmClient, txSigner: stri senderAddress: string, msg: Record, funds: Coin[], - updatable?: boolean, ): Promise => { - const result = await client.execute( - senderAddress, - updatable ? OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS : OPEN_EDITION_FACTORY_ADDRESS, - msg, - 'auto', - '', - funds, - ) + console.log('Contract Address: ', contractAddress) + const result = await client.execute(senderAddress, contractAddress, msg, 'auto', '', funds) return { openEditionMinterAddress: result.logs[0].events[5].attributes[0].value, diff --git a/contracts/openEditionMinter/contract.ts b/contracts/openEditionMinter/contract.ts index df99013..bb66310 100644 --- a/contracts/openEditionMinter/contract.ts +++ b/contracts/openEditionMinter/contract.ts @@ -356,9 +356,10 @@ export const openEditionMinter = (client: SigningCosmWasmClient, txSigner: strin console.log(factoryParameters?.params?.extension?.airdrop_mint_fee_bps) const price = factoryParameters?.params?.extension?.airdrop_mint_price.amount + const denom = factoryParameters?.params?.extension?.airdrop_mint_price.denom || 'ustars' if (!price) { 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) @@ -370,7 +371,7 @@ export const openEditionMinter = (client: SigningCosmWasmClient, txSigner: strin }, 'auto', '', - airdropFee > 0 ? [coin(airdropFee / 100 / 100, 'ustars')] : [], + airdropFee > 0 ? [coin(airdropFee / 100 / 100, denom as string)] : [], ) return res.transactionHash }) @@ -386,6 +387,7 @@ export const openEditionMinter = (client: SigningCosmWasmClient, txSigner: strin }) const price = factoryParameters?.params?.extension?.airdrop_mint_price.amount + const denom = factoryParameters?.params?.extension?.airdrop_mint_price.denom || 'ustars' if (!price) { 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.', @@ -403,7 +405,7 @@ export const openEditionMinter = (client: SigningCosmWasmClient, txSigner: strin sender: senderAddress, contract: contractAddress, 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 denom = factoryParameters?.params?.extension?.airdrop_mint_price.denom || 'ustars' if (!price) { 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.', @@ -443,7 +446,7 @@ export const openEditionMinter = (client: SigningCosmWasmClient, txSigner: strin sender: senderAddress, contract: contractAddress, msg: toUtf8(JSON.stringify(msg)), - funds: airdropFee > 0 ? [coin(airdropFee / 100 / 100, 'ustars')] : [], + funds: airdropFee > 0 ? [coin(airdropFee / 100 / 100, denom as string)] : [], }), } diff --git a/contracts/vendingFactory/contract.ts b/contracts/vendingFactory/contract.ts index 30f59d0..af41418 100644 --- a/contracts/vendingFactory/contract.ts +++ b/contracts/vendingFactory/contract.ts @@ -1,11 +1,8 @@ /* eslint-disable eslint-comments/disable-enable-pair */ -/* eslint-disable no-nested-ternary */ + import type { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate' import type { Coin } from '@cosmjs/proto-signing' 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 { readonly vendingMinterAddress: string @@ -63,14 +60,7 @@ export const vendingFactory = (client: SigningCosmWasmClient, txSigner: string): updatable?: boolean, flex?: boolean, ): Promise => { - const result = await client.execute( - senderAddress, - flex ? VENDING_FACTORY_FLEX_ADDRESS : updatable ? VENDING_FACTORY_UPDATABLE_ADDRESS : VENDING_FACTORY_ADDRESS, - msg, - 'auto', - '', - funds, - ) + const result = await client.execute(senderAddress, contractAddress, msg, 'auto', '', funds) return { vendingMinterAddress: result.logs[0].events[5].attributes[0].value, diff --git a/env.d.ts b/env.d.ts index 955e661..3d4984a 100644 --- a/env.d.ts +++ b/env.d.ts @@ -23,11 +23,26 @@ declare namespace NodeJS { readonly NEXT_PUBLIC_VENDING_MINTER_CODE_ID: string readonly NEXT_PUBLIC_VENDING_MINTER_FLEX_CODE_ID: 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_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_UPDATABLE_ADDRESS: string readonly NEXT_PUBLIC_SG721_NAME_ADDRESS: string diff --git a/package.json b/package.json index e053b14..ff54c94 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stargaze-studio", - "version": "0.7.2", + "version": "0.7.3", "workspaces": [ "packages/*" ], diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx index e4c1636..008830f 100644 --- a/pages/collections/create.tsx +++ b/pages/collections/create.tsx @@ -33,6 +33,8 @@ import { Conditional } from 'components/Conditional' import { LoadingModal } from 'components/LoadingModal' import type { OpenEditionMinterCreatorDataProps } 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 { addLogItem } from 'contexts/log' import { useWallet } from 'contexts/wallet' @@ -71,6 +73,8 @@ import { uid } from 'utils/random' import type { MinterType } from '../../components/collections/actions/Combobox' import type { UploadMethod } from '../../components/collections/creation/UploadDetails' import { ConfirmationModal } from '../../components/ConfirmationModal' +import type { OpenEditionMinterDetailsDataProps } from '../../components/openEdition/OpenEditionMinterCreator' +import { stars, tokensList } from '../../config/token' import { getAssetType } from '../../utils/getAssetType' import { isValidAddress } from '../../utils/isValidAddress' @@ -86,20 +90,12 @@ const CollectionCreationPage: NextPage = () => { const scrollRef = useRef(null) const sidetabRef = useRef(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(null) const [collectionDetails, setCollectionDetails] = useState(null) const [baseMinterDetails, setBaseMinterDetails] = useState(null) - const [openEditionMinterDetails, setOpenEditionMinterDetails] = useState( + const [openEditionMinterCreatorData, setOpenEditionMinterCreatorData] = + useState(null) + const [openEditionMinterDetails, setOpenEditionMinterDetails] = useState( null, ) const [mintingDetails, setMintingDetails] = useState(null) @@ -122,8 +118,23 @@ const CollectionCreationPage: NextPage = () => { const [minimumOpenEditionUpdatableMintPrice, setMinimumOpenEditionUpdatableMintPrice] = useState('0') const [minimumFlexMintPrice, setMinimumFlexMintPrice] = useState('0') + const [mintTokenFromOpenEditionFactory, setMintTokenFromOpenEditionFactory] = useState(stars) + const [mintTokenFromVendingFactory, setMintTokenFromVendingFactory] = useState(stars) + const [vendingFactoryAddress, setVendingFactoryAddress] = useState(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 [isMintingComplete, setIsMintingComplete] = useState(false) + const [initialParametersFetched, setInitialParametersFetched] = useState(false) const [creatingCollection, setCreatingCollection] = useState(false) const [readyToCreateVm, setReadyToCreateVm] = useState(false) const [readyToCreateBm, setReadyToCreateBm] = useState(false) @@ -484,7 +495,10 @@ const CollectionCreationPage: NextPage = () => { members: whitelistDetails?.members, start_time: whitelistDetails?.startTime, 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, member_limit: whitelistDetails?.memberLimit, admins: whitelistDetails?.admins || [wallet.address], @@ -495,7 +509,10 @@ const CollectionCreationPage: NextPage = () => { members: whitelistDetails?.members, start_time: whitelistDetails?.startTime, 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, admins: whitelistDetails?.admins || [wallet.address], admins_mutable: whitelistDetails?.adminsMutable, @@ -532,17 +549,13 @@ const CollectionCreationPage: NextPage = () => { payment_address: mintingDetails?.paymentAddress ? mintingDetails.paymentAddress : undefined, mint_price: { amount: mintingDetails?.unitPrice, - denom: 'ustars', + denom: (mintTokenFromVendingFactory?.denom as string) || 'ustars', }, per_address_limit: mintingDetails?.perAddressLimit, whitelist, }, collection_params: { - code_id: collectionDetails?.updatable - ? whitelistDetails?.whitelistType === 'flex' - ? SG721_CODE_ID - : SG721_UPDATABLE_CODE_ID - : SG721_CODE_ID, + code_id: collectionDetails?.updatable ? SG721_UPDATABLE_CODE_ID : SG721_CODE_ID, name: collectionDetails?.name, symbol: collectionDetails?.symbol, info: { @@ -563,12 +576,7 @@ const CollectionCreationPage: NextPage = () => { } const payload: VendingFactoryDispatchExecuteArgs = { - contract: - whitelistDetails?.whitelistState !== 'none' && whitelistDetails?.whitelistType === 'flex' - ? VENDING_FACTORY_FLEX_ADDRESS - : collectionDetails?.updatable - ? VENDING_FACTORY_UPDATABLE_ADDRESS - : VENDING_FACTORY_ADDRESS, + contract: vendingFactoryAddress as string, messages: vendingFactoryMessages, txSigner: wallet.address, msg, @@ -668,8 +676,6 @@ const CollectionCreationPage: NextPage = () => { setCreatingCollection(false) }) } else { - console.log('Here') - console.log(data.baseMinterAddress) await toast .promise( baseMinterContract @@ -907,14 +913,24 @@ const CollectionCreationPage: NextPage = () => { if (mintingDetails.unitPrice === '') throw new Error('Public mint price is required') if (whitelistDetails?.whitelistState !== 'none' && whitelistDetails?.whitelistType === 'flex') { 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) { if (Number(mintingDetails.unitPrice) < Number(minimumUpdatableMintPrice)) 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)) - 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 ( !mintingDetails.perAddressLimit || mintingDetails.perAddressLimit < 1 || @@ -1047,7 +1063,7 @@ const CollectionCreationPage: NextPage = () => { } } - const fetchFactoryParameters = async () => { + const fetchInitialFactoryParameters = async () => { const client = wallet.client if (!client) return if (BASE_FACTORY_ADDRESS) { @@ -1122,10 +1138,104 @@ const CollectionCreationPage: NextPage = () => { addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() }) }) 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 walletBalance = await wallet.client?.getBalance(wallet.address, 'ustars').then((balance) => { if (minterType === 'vending' && whitelistDetails?.whitelistState === 'new' && whitelistDetails.memberLimit) { @@ -1165,25 +1275,25 @@ const CollectionCreationPage: NextPage = () => { const syncCollections = useCallback(async () => { const collectionAddress = - minterType === 'openEdition' ? openEditionMinterDetails?.sg721ContractAddress : sg721ContractAddress + minterType === 'openEdition' ? openEditionMinterCreatorData?.sg721ContractAddress : sg721ContractAddress if (collectionAddress && SYNC_COLLECTIONS_API_URL) { await axios.get(`${SYNC_COLLECTIONS_API_URL}/${collectionAddress}`).catch((error) => { console.error('Sync collections: ', error) }) } - }, [minterType, openEditionMinterDetails?.sg721ContractAddress, sg721ContractAddress]) + }, [minterType, openEditionMinterCreatorData?.sg721ContractAddress, sg721ContractAddress]) useEffect(() => { if ( vendingMinterContractAddress !== null || - openEditionMinterDetails?.openEditionMinterContractAddress || + openEditionMinterCreatorData?.openEditionMinterContractAddress || isMintingComplete ) { scrollRef.current?.scrollIntoView({ behavior: 'smooth' }) } if ( (minterType === 'vending' && vendingMinterContractAddress !== null) || - (minterType === 'openEdition' && openEditionMinterDetails?.openEditionMinterContractAddress) || + (minterType === 'openEdition' && openEditionMinterCreatorData?.openEditionMinterContractAddress) || (minterType === 'base' && vendingMinterContractAddress !== null && isMintingComplete) ) { void syncCollections() @@ -1196,7 +1306,7 @@ const CollectionCreationPage: NextPage = () => { } }, [ vendingMinterContractAddress, - openEditionMinterDetails?.openEditionMinterContractAddress, + openEditionMinterCreatorData?.openEditionMinterContractAddress, isMintingComplete, minterType, syncCollections, @@ -1214,9 +1324,19 @@ const CollectionCreationPage: NextPage = () => { }, [minterType, baseMinterDetails?.baseMinterAcquisitionMethod, uploadDetails?.uploadMethod]) useEffect(() => { - void fetchFactoryParameters() + if (!initialParametersFetched) { + void fetchInitialFactoryParameters() + } }, [wallet.client]) + useEffect(() => { + void fetchOpenEditionFactoryParameters() + }, [fetchOpenEditionFactoryParameters]) + + useEffect(() => { + void fetchVendingFactoryParameters() + }, [fetchVendingFactoryParameters]) + return (
{
@@ -1257,10 +1377,10 @@ const CollectionCreationPage: NextPage = () => { className="text-stargaze hover:underline" external href={`/contracts/openEditionMinter/query/?contractAddress=${ - openEditionMinterDetails?.openEditionMinterContractAddress as string + openEditionMinterCreatorData?.openEditionMinterContractAddress as string }`} > - {openEditionMinterDetails?.openEditionMinterContractAddress as string} + {openEditionMinterCreatorData?.openEditionMinterContractAddress as string}
SG721 Contract Address:{' '} @@ -1268,10 +1388,10 @@ const CollectionCreationPage: NextPage = () => { className="text-stargaze hover:underline" external href={`/contracts/sg721/query/?contractAddress=${ - openEditionMinterDetails?.sg721ContractAddress as string + openEditionMinterCreatorData?.sg721ContractAddress as string }`} > - {openEditionMinterDetails?.sg721ContractAddress as string} + {openEditionMinterCreatorData?.sg721ContractAddress as string}
Transaction Hash: {' '} @@ -1279,18 +1399,18 @@ const CollectionCreationPage: NextPage = () => { - {openEditionMinterDetails?.transactionHash} + {openEditionMinterCreatorData?.transactionHash} - {openEditionMinterDetails?.transactionHash} + {openEditionMinterCreatorData?.transactionHash}
@@ -1299,7 +1419,7 @@ const CollectionCreationPage: NextPage = () => { className="text-white" external href={`${STARGAZE_URL}/launchpad/${ - openEditionMinterDetails?.openEditionMinterContractAddress as string + openEditionMinterCreatorData?.openEditionMinterContractAddress as string }`} > View on Launchpad @@ -1567,8 +1687,10 @@ const CollectionCreationPage: NextPage = () => { @@ -1605,10 +1727,13 @@ const CollectionCreationPage: NextPage = () => { { >
- +
diff --git a/utils/constants.ts b/utils/constants.ts index 097aefa..4911df1 100644 --- a/utils/constants.ts +++ b/utils/constants.ts @@ -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_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_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_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_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 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)