From d5b1acc16e2e3b2ebb9904e67ccef8e1db7e0707 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 23 Jul 2023 21:54:14 +0300
Subject: [PATCH 01/51] Create OpenEditionMinterDetailsDataProps

---
 .../openEdition/OpenEditionMinterCreator.tsx  | 32 +++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/components/openEdition/OpenEditionMinterCreator.tsx b/components/openEdition/OpenEditionMinterCreator.tsx
index 3f0fce3..6fe8763 100644
--- a/components/openEdition/OpenEditionMinterCreator.tsx
+++ b/components/openEdition/OpenEditionMinterCreator.tsx
@@ -47,13 +47,24 @@ 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
+}
+
 interface OpenEditionMinterCreatorProps {
   onChange: (data: OpenEditionMinterCreatorDataProps) => void
+  onDetailsChange: (data: OpenEditionMinterDetailsDataProps) => void
   openEditionMinterUpdatableCreationFee?: string
   openEditionMinterCreationFee?: string
   minimumMintPrice?: string
   minimumUpdatableMintPrice?: string
   minterType?: MinterType
+  importedOpenEditionMinterDetails?: OpenEditionMinterCreatorDataProps
 }
 
 export interface OpenEditionMinterCreatorDataProps {
@@ -65,6 +76,7 @@ export interface OpenEditionMinterCreatorDataProps {
 
 export const OpenEditionMinterCreator = ({
   onChange,
+  onDetailsChange,
   openEditionMinterCreationFee,
   openEditionMinterUpdatableCreationFee,
   minimumMintPrice,
@@ -585,6 +597,26 @@ 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,
+    }
+    onDetailsChange(data)
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [
+    imageUploadDetails,
+    collectionDetails,
+    royaltyDetails,
+    onChainMetadataInputDetails,
+    offChainMetadataUploadDetails,
+    mintingDetails,
+  ])
+
   return (
     <div>
       {/* TODO: Cancel once we're able to index on-chain metadata */}

From e074413a9ebacfb260a40ff540838c927bd96c6c Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 24 Jul 2023 21:57:53 +0300
Subject: [PATCH 02/51] Update AddressList

---
 components/forms/AddressList.tsx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/components/forms/AddressList.tsx b/components/forms/AddressList.tsx
index 59dad9d..b95db84 100644
--- a/components/forms/AddressList.tsx
+++ b/components/forms/AddressList.tsx
@@ -31,6 +31,7 @@ export function AddressList(props: AddressListProps) {
       {entries.map(([id], i) => (
         <Address
           key={`ib-${id}`}
+          defaultValue={entries[i][1]}
           id={id}
           isLast={i === entries.length - 1}
           onAdd={onAdd}
@@ -48,9 +49,10 @@ export interface AddressProps {
   onAdd: AddressListProps['onAdd']
   onChange: AddressListProps['onChange']
   onRemove: AddressListProps['onRemove']
+  defaultValue?: Address
 }
 
-export function Address({ id, isLast, onAdd, onChange, onRemove }: AddressProps) {
+export function Address({ id, isLast, onAdd, onChange, onRemove, defaultValue }: AddressProps) {
   const wallet = useWallet()
   const Icon = useMemo(() => (isLast ? FaPlus : FaMinus), [isLast])
 
@@ -60,6 +62,7 @@ export function Address({ id, isLast, onAdd, onChange, onRemove }: AddressProps)
     id: `ib-address-${htmlId}`,
     name: `ib-address-${htmlId}`,
     title: ``,
+    defaultValue: defaultValue?.address,
   })
 
   const resolveAddress = async (name: string) => {

From 8921938c6c3f73b6a6fd9f44a6b323031b5d274a Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Tue, 25 Jul 2023 22:24:40 +0300
Subject: [PATCH 03/51] Initial export/import logic

---
 pages/collections/create.tsx | 103 ++++++++++++++++++++++++++++-------
 1 file changed, 83 insertions(+), 20 deletions(-)

diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 6a99323..2399ce2 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -42,6 +42,7 @@ import type { DispatchExecuteArgs as VendingFactoryDispatchExecuteArgs } from 'c
 import { dispatchExecute as vendingFactoryDispatchExecute } from 'contracts/vendingFactory/messages/execute'
 import type { NextPage } from 'next'
 import { NextSeo } from 'next-seo'
+import type { ChangeEvent } from 'react'
 import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
 import { toast } from 'react-hot-toast'
 import { upload } from 'services/upload'
@@ -71,6 +72,7 @@ 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 { getAssetType } from '../../utils/getAssetType'
 import { isValidAddress } from '../../utils/isValidAddress'
 
@@ -96,10 +98,23 @@ const CollectionCreationPage: NextPage = () => {
     [baseFactoryContract, wallet.address],
   )
 
+  const [importedDetails, setImportedDetails] = useState<{
+    minterType: MinterType
+    collectionDetails: CollectionDetailsDataProps
+    uploadDetails: UploadDetailsDataProps
+    mintingDetails: MintingDetailsDataProps
+    whitelistDetails: WhitelistDetailsDataProps
+    royaltyDetails: RoyaltyDetailsDataProps
+    baseMinterDetails: BaseMinterDetailsDataProps
+    openEditionMinterDetails: OpenEditionMinterDetailsDataProps
+  }>()
+
   const [uploadDetails, setUploadDetails] = useState<UploadDetailsDataProps | null>(null)
   const [collectionDetails, setCollectionDetails] = useState<CollectionDetailsDataProps | 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,
   )
   const [mintingDetails, setMintingDetails] = useState<MintingDetailsDataProps | null>(null)
@@ -1159,27 +1174,60 @@ const CollectionCreationPage: NextPage = () => {
     })
   }
 
+  // function to export all details as a .json file
+  const exportDetails = () => {
+    const details = {
+      minterType,
+      collectionDetails,
+      uploadDetails,
+      mintingDetails,
+      whitelistDetails,
+      royaltyDetails,
+      baseMinterDetails,
+      openEditionMinterDetails,
+    }
+    const element = document.createElement('a')
+    const file = new Blob([JSON.stringify(details)], { type: 'text/plain' })
+    element.href = URL.createObjectURL(file)
+    element.download = 'details.json'
+    document.body.appendChild(element) // Required for this to work in FireFox
+    element.click()
+  }
+  // function to import all details from a .json file
+  const importDetails = (event: ChangeEvent<HTMLInputElement>) => {
+    if (event.target.files === null) return toast.error('No files selected.')
+    const file = event.target.files[0]
+    const reader = new FileReader()
+    reader.onload = (e) => {
+      const contents = e.target?.result
+      const details = JSON.parse(contents as string)
+      setMinterType(details.minterType)
+      setImportedDetails(details)
+    }
+    reader.readAsText(file)
+  }
+
   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()
@@ -1192,7 +1240,7 @@ const CollectionCreationPage: NextPage = () => {
     }
   }, [
     vendingMinterContractAddress,
-    openEditionMinterDetails?.openEditionMinterContractAddress,
+    openEditionMinterCreatorData?.openEditionMinterContractAddress,
     isMintingComplete,
     minterType,
     syncCollections,
@@ -1222,7 +1270,15 @@ const CollectionCreationPage: NextPage = () => {
             : 'Create Collection'
         }
       />
-
+      <Button className="absolute top-5 right-5" onClick={() => exportDetails()}>
+        Export Details
+      </Button>
+      <input
+        accept="application/json"
+        className="absolute top-5 right-20"
+        onChange={(e) => importDetails(e)}
+        type="file"
+      />
       <div className="mt-5 space-y-5 text-center">
         <h1 className="font-heading text-4xl font-bold">
           {minterType === 'base' && baseMinterDetails?.baseMinterAcquisitionMethod === 'existing'
@@ -1244,7 +1300,7 @@ const CollectionCreationPage: NextPage = () => {
       </div>
       <div className="mx-10" ref={scrollRef}>
         <Conditional
-          test={minterType === 'openEdition' && openEditionMinterDetails?.openEditionMinterContractAddress !== null}
+          test={minterType === 'openEdition' && openEditionMinterCreatorData?.openEditionMinterContractAddress !== null}
         >
           <Alert className="mt-5" type="info">
             <div>
@@ -1253,10 +1309,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}
               </Anchor>
               <br />
               SG721 Contract Address:{'  '}
@@ -1264,10 +1320,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}
               </Anchor>
               <br />
               Transaction Hash: {'  '}
@@ -1275,18 +1331,18 @@ const CollectionCreationPage: NextPage = () => {
                 <Anchor
                   className="text-stargaze hover:underline"
                   external
-                  href={`${BLOCK_EXPLORER_URL}/tx/${openEditionMinterDetails?.transactionHash as string}`}
+                  href={`${BLOCK_EXPLORER_URL}/tx/${openEditionMinterCreatorData?.transactionHash as string}`}
                 >
-                  {openEditionMinterDetails?.transactionHash}
+                  {openEditionMinterCreatorData?.transactionHash}
                 </Anchor>
               </Conditional>
               <Conditional test={NETWORK === 'mainnet'}>
                 <Anchor
                   className="text-stargaze hover:underline"
                   external
-                  href={`${BLOCK_EXPLORER_URL}/txs/${openEditionMinterDetails?.transactionHash as string}`}
+                  href={`${BLOCK_EXPLORER_URL}/txs/${openEditionMinterCreatorData?.transactionHash as string}`}
                 >
-                  {openEditionMinterDetails?.transactionHash}
+                  {openEditionMinterCreatorData?.transactionHash}
                 </Anchor>
               </Conditional>
               <br />
@@ -1295,7 +1351,7 @@ const CollectionCreationPage: NextPage = () => {
                   className="text-white"
                   external
                   href={`${STARGAZE_URL}/launchpad/${
-                    openEditionMinterDetails?.openEditionMinterContractAddress as string
+                    openEditionMinterCreatorData?.openEditionMinterContractAddress as string
                   }`}
                 >
                   View on Launchpad
@@ -1564,7 +1620,8 @@ const CollectionCreationPage: NextPage = () => {
           minimumMintPrice={minimumOpenEditionMintPrice as string}
           minimumUpdatableMintPrice={minimumOpenEditionUpdatableMintPrice as string}
           minterType={minterType}
-          onChange={setOpenEditionMinterDetails}
+          onChange={setOpenEditionMinterCreatorData}
+          onDetailsChange={setOpenEditionMinterDetails}
           openEditionMinterCreationFee={openEditionMinterCreationFee as string}
           openEditionMinterUpdatableCreationFee={openEditionMinterUpdatableCreationFee as string}
         />
@@ -1573,6 +1630,7 @@ const CollectionCreationPage: NextPage = () => {
         <Conditional test={minterType === 'vending' || minterType === 'base'}>
           <UploadDetails
             baseMinterAcquisitionMethod={baseMinterDetails?.baseMinterAcquisitionMethod}
+            importedUploadDetails={importedDetails?.uploadDetails}
             minterType={minterType}
             onChange={setUploadDetails}
           />
@@ -1593,6 +1651,7 @@ const CollectionCreationPage: NextPage = () => {
             >
               <CollectionDetails
                 coverImageUrl={coverImageUrl as string}
+                importedCollectionDetails={importedDetails?.collectionDetails}
                 minterType={minterType}
                 onChange={setCollectionDetails}
                 uploadMethod={uploadDetails?.uploadMethod as UploadMethod}
@@ -1600,6 +1659,7 @@ const CollectionCreationPage: NextPage = () => {
             </Conditional>
             <Conditional test={minterType === 'vending'}>
               <MintingDetails
+                importedMintingDetails={importedDetails?.mintingDetails}
                 minimumMintPrice={
                   collectionDetails?.updatable
                     ? Number(minimumUpdatableMintPrice) / 1000000
@@ -1633,10 +1693,13 @@ const CollectionCreationPage: NextPage = () => {
         >
           <div className="my-6">
             <Conditional test={minterType === 'vending'}>
-              <WhitelistDetails onChange={setWhitelistDetails} />
+              <WhitelistDetails
+                importedWhitelistDetails={importedDetails?.whitelistDetails}
+                onChange={setWhitelistDetails}
+              />
               <div className="my-6" />
             </Conditional>
-            <RoyaltyDetails onChange={setRoyaltyDetails} />
+            <RoyaltyDetails importedRoyaltyDetails={importedDetails?.royaltyDetails} onChange={setRoyaltyDetails} />
           </div>
         </Conditional>
         <Conditional test={readyToCreateVm && minterType === 'vending'}>

From 2a38e791913fcb628d7f00d92800a2f6641e8436 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Tue, 25 Jul 2023 22:26:29 +0300
Subject: [PATCH 04/51] Surface open edition collection configuration

---
 components/openEdition/CollectionDetails.tsx  | 19 ++++++++++++
 components/openEdition/ImageUploadDetails.tsx | 15 +++++++++-
 components/openEdition/MintingDetails.tsx     | 19 +++++++++++-
 .../OffChainMetadataUploadDetails.tsx         | 15 ++++++++++
 .../OnChainMetadataInputDetails.tsx           | 27 ++++++++++++++++-
 .../openEdition/OpenEditionMinterCreator.tsx  | 29 ++++++++++++++++---
 components/openEdition/RoyaltyDetails.tsx     | 12 +++++++-
 7 files changed, 128 insertions(+), 8 deletions(-)

diff --git a/components/openEdition/CollectionDetails.tsx b/components/openEdition/CollectionDetails.tsx
index c919b73..4c46fff 100644
--- a/components/openEdition/CollectionDetails.tsx
+++ b/components/openEdition/CollectionDetails.tsx
@@ -28,6 +28,7 @@ interface CollectionDetailsProps {
   uploadMethod: UploadMethod
   coverImageUrl: string
   metadataStorageMethod: MetadataStorageMethod
+  importedCollectionDetails?: CollectionDetailsDataProps
 }
 
 export interface CollectionDetailsDataProps {
@@ -46,6 +47,7 @@ export const CollectionDetails = ({
   uploadMethod,
   metadataStorageMethod,
   coverImageUrl,
+  importedCollectionDetails,
 }: CollectionDetailsProps) => {
   const [coverImage, setCoverImage] = useState<File | null>(null)
   const [timestamp, setTimestamp] = useState<Date | undefined>()
@@ -152,6 +154,23 @@ export const CollectionDetails = ({
     }
   }, [updatable])
 
+  useEffect(() => {
+    if (importedCollectionDetails) {
+      nameState.onChange(importedCollectionDetails.name)
+      descriptionState.onChange(importedCollectionDetails.description)
+      symbolState.onChange(importedCollectionDetails.symbol)
+      setCoverImage(importedCollectionDetails.imageFile[0] || null)
+      externalLinkState.onChange(importedCollectionDetails.externalLink || '')
+      setTimestamp(
+        importedCollectionDetails.startTradingTime
+          ? new Date(parseInt(importedCollectionDetails.startTradingTime) / 1_000_000)
+          : undefined,
+      )
+      setExplicit(importedCollectionDetails.explicit)
+      setUpdatable(importedCollectionDetails.updatable)
+    }
+  }, [importedCollectionDetails])
+
   const videoPreview = useMemo(() => {
     if (uploadMethod === 'new' && coverImage) {
       return (
diff --git a/components/openEdition/ImageUploadDetails.tsx b/components/openEdition/ImageUploadDetails.tsx
index ad84b0e..f8748f2 100644
--- a/components/openEdition/ImageUploadDetails.tsx
+++ b/components/openEdition/ImageUploadDetails.tsx
@@ -20,6 +20,7 @@ export type UploadMethod = 'new' | 'existing'
 
 interface ImageUploadDetailsProps {
   onChange: (value: ImageUploadDetailsDataProps) => void
+  importedImageUploadDetails?: ImageUploadDetailsDataProps
 }
 
 export interface ImageUploadDetailsDataProps {
@@ -33,7 +34,7 @@ export interface ImageUploadDetailsDataProps {
   coverImageUrl?: string
 }
 
-export const ImageUploadDetails = ({ onChange }: ImageUploadDetailsProps) => {
+export const ImageUploadDetails = ({ onChange, importedImageUploadDetails }: ImageUploadDetailsProps) => {
   const [assetFile, setAssetFile] = useState<File>()
   const [uploadMethod, setUploadMethod] = useState<UploadMethod>('new')
   const [uploadService, setUploadService] = useState<UploadServiceType>('nft-storage')
@@ -140,6 +141,18 @@ export const ImageUploadDetails = ({ onChange }: ImageUploadDetailsProps) => {
     imageUrlState.onChange('')
   }, [uploadMethod])
 
+  useEffect(() => {
+    if (importedImageUploadDetails) {
+      setUploadMethod(importedImageUploadDetails.uploadMethod)
+      setUploadService(importedImageUploadDetails.uploadService)
+      nftStorageApiKeyState.onChange(importedImageUploadDetails.nftStorageApiKey || '')
+      pinataApiKeyState.onChange(importedImageUploadDetails.pinataApiKey || '')
+      pinataSecretKeyState.onChange(importedImageUploadDetails.pinataSecretKey || '')
+      imageUrlState.onChange(importedImageUploadDetails.imageUrl || '')
+      coverImageUrlState.onChange(importedImageUploadDetails.coverImageUrl || '')
+    }
+  }, [importedImageUploadDetails])
+
   const previewUrl = imageUrlState.value.toLowerCase().trim().startsWith('ipfs://')
     ? `https://ipfs-gw.stargaze-apis.com/ipfs/${imageUrlState.value.substring(7)}`
     : imageUrlState.value
diff --git a/components/openEdition/MintingDetails.tsx b/components/openEdition/MintingDetails.tsx
index 8b6acd5..0938a7d 100644
--- a/components/openEdition/MintingDetails.tsx
+++ b/components/openEdition/MintingDetails.tsx
@@ -15,6 +15,7 @@ interface MintingDetailsProps {
   onChange: (data: MintingDetailsDataProps) => void
   uploadMethod: UploadMethod
   minimumMintPrice: number
+  importedMintingDetails?: MintingDetailsDataProps
 }
 
 export interface MintingDetailsDataProps {
@@ -25,7 +26,12 @@ export interface MintingDetailsDataProps {
   paymentAddress?: string
 }
 
-export const MintingDetails = ({ onChange, uploadMethod, minimumMintPrice }: MintingDetailsProps) => {
+export const MintingDetails = ({
+  onChange,
+  uploadMethod,
+  minimumMintPrice,
+  importedMintingDetails,
+}: MintingDetailsProps) => {
   const wallet = useWallet()
 
   const [timestamp, setTimestamp] = useState<Date | undefined>()
@@ -81,6 +87,17 @@ export const MintingDetails = ({ onChange, uploadMethod, minimumMintPrice }: Min
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [unitPriceState.value, perAddressLimitState.value, timestamp, endTimestamp, paymentAddressState.value])
 
+  useEffect(() => {
+    if (importedMintingDetails) {
+      unitPriceState.onChange(Number(importedMintingDetails.unitPrice))
+      perAddressLimitState.onChange(importedMintingDetails.perAddressLimit)
+      setTimestamp(new Date(Number(importedMintingDetails.startTime) / 1_000_000))
+      setEndTimestamp(new Date(Number(importedMintingDetails.endTime) / 1_000_000))
+      paymentAddressState.onChange(importedMintingDetails.paymentAddress ? importedMintingDetails.paymentAddress : '')
+    }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [importedMintingDetails])
+
   return (
     <div className="border-l-[1px] border-gray-500 border-opacity-20">
       <FormGroup subtitle="Information about your minting settings" title="Minting Details">
diff --git a/components/openEdition/OffChainMetadataUploadDetails.tsx b/components/openEdition/OffChainMetadataUploadDetails.tsx
index 02c4ce3..02e8703 100644
--- a/components/openEdition/OffChainMetadataUploadDetails.tsx
+++ b/components/openEdition/OffChainMetadataUploadDetails.tsx
@@ -28,6 +28,7 @@ export type UploadMethod = 'new' | 'existing'
 interface OffChainMetadataUploadDetailsProps {
   onChange: (value: OffChainMetadataUploadDetailsDataProps) => void
   metadataStorageMethod?: MetadataStorageMethod
+  importedOffChainMetadataUploadDetails?: OffChainMetadataUploadDetailsDataProps
 }
 
 export interface OffChainMetadataUploadDetailsDataProps {
@@ -46,6 +47,7 @@ export interface OffChainMetadataUploadDetailsDataProps {
 export const OffChainMetadataUploadDetails = ({
   onChange,
   metadataStorageMethod,
+  importedOffChainMetadataUploadDetails,
 }: OffChainMetadataUploadDetailsProps) => {
   const [assetFilesArray, setAssetFilesArray] = useState<File[]>([])
   const [metadataFilesArray, setMetadataFilesArray] = useState<File[]>([])
@@ -233,6 +235,19 @@ export const OffChainMetadataUploadDetails = ({
     coverImageUrlState.onChange('')
   }, [uploadMethod, metadataStorageMethod])
 
+  useEffect(() => {
+    if (importedOffChainMetadataUploadDetails) {
+      setUploadService(importedOffChainMetadataUploadDetails.uploadService)
+      nftStorageApiKeyState.onChange(importedOffChainMetadataUploadDetails.nftStorageApiKey || '')
+      pinataApiKeyState.onChange(importedOffChainMetadataUploadDetails.pinataApiKey || '')
+      pinataSecretKeyState.onChange(importedOffChainMetadataUploadDetails.pinataSecretKey || '')
+      setUploadMethod('existing')
+      tokenUriState.onChange(importedOffChainMetadataUploadDetails.tokenURI || '')
+      coverImageUrlState.onChange(importedOffChainMetadataUploadDetails.imageUrl || '')
+      setOpenEditionMinterMetadataFile(importedOffChainMetadataUploadDetails.openEditionMinterMetadataFile)
+    }
+  }, [importedOffChainMetadataUploadDetails])
+
   return (
     <div className="justify-items-start mb-3 rounded border-2 border-white/20 flex-column">
       <div className="flex justify-center">
diff --git a/components/openEdition/OnChainMetadataInputDetails.tsx b/components/openEdition/OnChainMetadataInputDetails.tsx
index 2fb0eed..f71fa23 100644
--- a/components/openEdition/OnChainMetadataInputDetails.tsx
+++ b/components/openEdition/OnChainMetadataInputDetails.tsx
@@ -21,6 +21,7 @@ import type { UploadMethod } from './ImageUploadDetails'
 interface OnChainMetadataInputDetailsProps {
   onChange: (data: OnChainMetadataInputDetailsDataProps) => void
   uploadMethod: UploadMethod | undefined
+  importedOnChainMetadataInputDetails?: OnChainMetadataInputDetailsDataProps
 }
 
 export interface OnChainMetadataInputDetailsDataProps {
@@ -34,7 +35,11 @@ export interface OnChainMetadataInputDetailsDataProps {
   youtube_url?: string
 }
 
-export const OnChainMetadataInputDetails = ({ onChange, uploadMethod }: OnChainMetadataInputDetailsProps) => {
+export const OnChainMetadataInputDetails = ({
+  onChange,
+  uploadMethod,
+  importedOnChainMetadataInputDetails,
+}: OnChainMetadataInputDetailsProps) => {
   const wallet = useWallet()
   const [timestamp, setTimestamp] = useState<Date | undefined>(undefined)
   const [metadataFile, setMetadataFile] = useState<File>()
@@ -196,6 +201,26 @@ export const OnChainMetadataInputDetails = ({ onChange, uploadMethod }: OnChainM
     youtubeUrlState.value,
   ])
 
+  useEffect(() => {
+    if (importedOnChainMetadataInputDetails) {
+      nameState.onChange(importedOnChainMetadataInputDetails.name || '')
+      descriptionState.onChange(importedOnChainMetadataInputDetails.description || '')
+      externalUrlState.onChange(importedOnChainMetadataInputDetails.external_url || '')
+      youtubeUrlState.onChange(importedOnChainMetadataInputDetails.youtube_url || '')
+      animationUrlState.onChange(importedOnChainMetadataInputDetails.animation_url || '')
+      imageDataState.onChange(importedOnChainMetadataInputDetails.image_data || '')
+      if (importedOnChainMetadataInputDetails.attributes) {
+        attributesState.reset()
+        importedOnChainMetadataInputDetails.attributes.forEach((attr) => {
+          attributesState.add({
+            trait_type: attr.trait_type,
+            value: attr.value,
+          })
+        })
+      }
+    }
+  }, [importedOnChainMetadataInputDetails])
+
   return (
     <div className="py-3 px-8 rounded border-2 border-white/20">
       <span className="ml-4 text-xl font-bold underline underline-offset-4">NFT Metadata</span>
diff --git a/components/openEdition/OpenEditionMinterCreator.tsx b/components/openEdition/OpenEditionMinterCreator.tsx
index 6fe8763..bfd893a 100644
--- a/components/openEdition/OpenEditionMinterCreator.tsx
+++ b/components/openEdition/OpenEditionMinterCreator.tsx
@@ -54,6 +54,7 @@ export interface OpenEditionMinterDetailsDataProps {
   onChainMetadataInputDetails?: OnChainMetadataInputDetailsDataProps
   offChainMetadataUploadDetails?: OffChainMetadataUploadDetailsDataProps
   mintingDetails?: MintingDetailsDataProps
+  metadataStorageMethod?: MetadataStorageMethod
 }
 
 interface OpenEditionMinterCreatorProps {
@@ -64,7 +65,7 @@ interface OpenEditionMinterCreatorProps {
   minimumMintPrice?: string
   minimumUpdatableMintPrice?: string
   minterType?: MinterType
-  importedOpenEditionMinterDetails?: OpenEditionMinterCreatorDataProps
+  importedOpenEditionMinterDetails?: OpenEditionMinterDetailsDataProps
 }
 
 export interface OpenEditionMinterCreatorDataProps {
@@ -82,6 +83,7 @@ export const OpenEditionMinterCreator = ({
   minimumMintPrice,
   minimumUpdatableMintPrice,
   minterType,
+  importedOpenEditionMinterDetails,
 }: OpenEditionMinterCreatorProps) => {
   const wallet = useWallet()
   const { openEditionMinter: openEditionMinterContract, openEditionFactory: openEditionFactoryContract } =
@@ -605,6 +607,7 @@ export const OpenEditionMinterCreator = ({
       onChainMetadataInputDetails: onChainMetadataInputDetails ? onChainMetadataInputDetails : undefined,
       offChainMetadataUploadDetails: offChainMetadataUploadDetails ? offChainMetadataUploadDetails : undefined,
       mintingDetails: mintingDetails ? mintingDetails : undefined,
+      metadataStorageMethod,
     }
     onDetailsChange(data)
     // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -617,6 +620,12 @@ export const OpenEditionMinterCreator = ({
     mintingDetails,
   ])
 
+  useEffect(() => {
+    if (importedOpenEditionMinterDetails) {
+      setMetadataStorageMethod(importedOpenEditionMinterDetails.metadataStorageMethod as MetadataStorageMethod)
+    }
+  }, [importedOpenEditionMinterDetails])
+
   return (
     <div>
       {/* TODO: Cancel once we're able to index on-chain metadata */}
@@ -667,13 +676,20 @@ export const OpenEditionMinterCreator = ({
       <div className={clsx('my-4 mx-10')}>
         <Conditional test={metadataStorageMethod === 'off-chain'}>
           <div>
-            <OffChainMetadataUploadDetails onChange={setOffChainMetadataUploadDetails} />
+            <OffChainMetadataUploadDetails
+              importedOffChainMetadataUploadDetails={importedOpenEditionMinterDetails?.offChainMetadataUploadDetails}
+              onChange={setOffChainMetadataUploadDetails}
+            />
           </div>
         </Conditional>
         <Conditional test={metadataStorageMethod === 'on-chain'}>
           <div>
-            <ImageUploadDetails onChange={setImageUploadDetails} />
+            <ImageUploadDetails
+              importedImageUploadDetails={importedOpenEditionMinterDetails?.imageUploadDetails}
+              onChange={setImageUploadDetails}
+            />
             <OnChainMetadataInputDetails
+              importedOnChainMetadataInputDetails={importedOpenEditionMinterDetails?.onChainMetadataInputDetails}
               onChange={setOnChainMetadataInputDetails}
               uploadMethod={imageUploadDetails?.uploadMethod}
             />
@@ -687,6 +703,7 @@ export const OpenEditionMinterCreator = ({
               ? (offChainMetadataUploadDetails?.imageUrl as string)
               : (imageUploadDetails?.coverImageUrl as string)
           }
+          importedCollectionDetails={importedOpenEditionMinterDetails?.collectionDetails}
           metadataStorageMethod={metadataStorageMethod}
           onChange={setCollectionDetails}
           uploadMethod={
@@ -696,6 +713,7 @@ export const OpenEditionMinterCreator = ({
           }
         />
         <MintingDetails
+          importedMintingDetails={importedOpenEditionMinterDetails?.mintingDetails}
           minimumMintPrice={
             collectionDetails?.updatable
               ? Number(minimumUpdatableMintPrice) / 1000000
@@ -706,7 +724,10 @@ export const OpenEditionMinterCreator = ({
         />
       </div>
       <div className="my-6">
-        <RoyaltyDetails onChange={setRoyaltyDetails} />
+        <RoyaltyDetails
+          importedRoyaltyDetails={importedOpenEditionMinterDetails?.royaltyDetails}
+          onChange={setRoyaltyDetails}
+        />
       </div>
       <div className="flex justify-end w-full">
         <Button
diff --git a/components/openEdition/RoyaltyDetails.tsx b/components/openEdition/RoyaltyDetails.tsx
index 518458a..17f32d3 100644
--- a/components/openEdition/RoyaltyDetails.tsx
+++ b/components/openEdition/RoyaltyDetails.tsx
@@ -9,6 +9,7 @@ import { NumberInput, TextInput } from '../forms/FormInput'
 
 interface RoyaltyDetailsProps {
   onChange: (data: RoyaltyDetailsDataProps) => void
+  importedRoyaltyDetails?: RoyaltyDetailsDataProps
 }
 
 export interface RoyaltyDetailsDataProps {
@@ -19,7 +20,7 @@ export interface RoyaltyDetailsDataProps {
 
 type RoyaltyState = 'none' | 'new'
 
-export const RoyaltyDetails = ({ onChange }: RoyaltyDetailsProps) => {
+export const RoyaltyDetails = ({ onChange, importedRoyaltyDetails }: RoyaltyDetailsProps) => {
   const wallet = useWallet()
   const [royaltyState, setRoyaltyState] = useState<RoyaltyState>('none')
 
@@ -60,6 +61,15 @@ export const RoyaltyDetails = ({ onChange }: RoyaltyDetailsProps) => {
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [royaltyState, royaltyPaymentAddressState.value, royaltyShareState.value])
 
+  useEffect(() => {
+    if (importedRoyaltyDetails) {
+      setRoyaltyState(importedRoyaltyDetails.royaltyType)
+      royaltyPaymentAddressState.onChange(importedRoyaltyDetails.paymentAddress)
+      royaltyShareState.onChange(importedRoyaltyDetails.share.toString())
+    }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [importedRoyaltyDetails])
+
   return (
     <div className="py-3 px-8 mx-10 rounded border-2 border-white/20">
       <div className="flex justify-center">

From 0481032a1f53ecda1bc951802b773c21be69b068 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Tue, 25 Jul 2023 22:27:42 +0300
Subject: [PATCH 05/51] Surface standard & 1/1 collection configuration

---
 .../creation/BaseMinterDetails.tsx            | 12 +++-
 .../creation/CollectionDetails.tsx            | 26 ++++++++-
 .../collections/creation/MintingDetails.tsx   | 20 ++++++-
 .../collections/creation/RoyaltyDetails.tsx   | 12 +++-
 .../collections/creation/UploadDetails.tsx    | 33 ++++++++++-
 .../collections/creation/WhitelistDetails.tsx | 56 ++++++++++++++++++-
 6 files changed, 149 insertions(+), 10 deletions(-)

diff --git a/components/collections/creation/BaseMinterDetails.tsx b/components/collections/creation/BaseMinterDetails.tsx
index e40d842..f87ec07 100644
--- a/components/collections/creation/BaseMinterDetails.tsx
+++ b/components/collections/creation/BaseMinterDetails.tsx
@@ -28,6 +28,7 @@ export interface MinterInfo {
 interface BaseMinterDetailsProps {
   onChange: (data: BaseMinterDetailsDataProps) => void
   minterType: MinterType
+  importedBaseMinterDetails?: BaseMinterDetailsDataProps
 }
 
 export interface BaseMinterDetailsDataProps {
@@ -37,7 +38,7 @@ export interface BaseMinterDetailsDataProps {
   collectionTokenCount: number | undefined
 }
 
-export const BaseMinterDetails = ({ onChange, minterType }: BaseMinterDetailsProps) => {
+export const BaseMinterDetails = ({ onChange, minterType, importedBaseMinterDetails }: BaseMinterDetailsProps) => {
   const wallet = useWallet()
 
   const [myBaseMinterContracts, setMyBaseMinterContracts] = useState<MinterInfo[]>([])
@@ -198,6 +199,15 @@ export const BaseMinterDetails = ({ onChange, minterType }: BaseMinterDetailsPro
     collectionTokenCount,
   ])
 
+  useEffect(() => {
+    if (importedBaseMinterDetails) {
+      setBaseMinterAcquisitionMethod(importedBaseMinterDetails.baseMinterAcquisitionMethod)
+      existingBaseMinterState.onChange(
+        importedBaseMinterDetails.existingBaseMinter ? importedBaseMinterDetails.existingBaseMinter : '',
+      )
+    }
+  }, [importedBaseMinterDetails])
+
   return (
     <div className="mx-10 mb-4 rounded border-2 border-white/20">
       <div className="flex justify-center mb-2">
diff --git a/components/collections/creation/CollectionDetails.tsx b/components/collections/creation/CollectionDetails.tsx
index 629cbff..b2c2256 100644
--- a/components/collections/creation/CollectionDetails.tsx
+++ b/components/collections/creation/CollectionDetails.tsx
@@ -26,6 +26,7 @@ interface CollectionDetailsProps {
   uploadMethod: UploadMethod
   coverImageUrl: string
   minterType: MinterType
+  importedCollectionDetails?: CollectionDetailsDataProps
 }
 
 export interface CollectionDetailsDataProps {
@@ -39,7 +40,13 @@ export interface CollectionDetailsDataProps {
   updatable: boolean
 }
 
-export const CollectionDetails = ({ onChange, uploadMethod, coverImageUrl, minterType }: CollectionDetailsProps) => {
+export const CollectionDetails = ({
+  onChange,
+  uploadMethod,
+  coverImageUrl,
+  minterType,
+  importedCollectionDetails,
+}: CollectionDetailsProps) => {
   const [coverImage, setCoverImage] = useState<File | null>(null)
   const [timestamp, setTimestamp] = useState<Date | undefined>()
   const [explicit, setExplicit] = useState<boolean>(false)
@@ -105,6 +112,23 @@ export const CollectionDetails = ({ onChange, uploadMethod, coverImageUrl, minte
     updatable,
   ])
 
+  useEffect(() => {
+    if (importedCollectionDetails) {
+      nameState.onChange(importedCollectionDetails.name)
+      descriptionState.onChange(importedCollectionDetails.description)
+      symbolState.onChange(importedCollectionDetails.symbol)
+      externalLinkState.onChange(importedCollectionDetails.externalLink || '')
+      setTimestamp(
+        importedCollectionDetails.startTradingTime
+          ? new Date(parseInt(importedCollectionDetails.startTradingTime) / 1_000_000)
+          : undefined,
+      )
+      setExplicit(importedCollectionDetails.explicit)
+      setUpdatable(importedCollectionDetails.updatable)
+    }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [importedCollectionDetails])
+
   const selectCoverImage = (event: ChangeEvent<HTMLInputElement>) => {
     if (event.target.files === null) return toast.error('Error selecting cover image')
     if (event.target.files.length === 0) {
diff --git a/components/collections/creation/MintingDetails.tsx b/components/collections/creation/MintingDetails.tsx
index 6ca136e..7185ceb 100644
--- a/components/collections/creation/MintingDetails.tsx
+++ b/components/collections/creation/MintingDetails.tsx
@@ -16,6 +16,7 @@ interface MintingDetailsProps {
   numberOfTokens: number | undefined
   uploadMethod: UploadMethod
   minimumMintPrice: number
+  importedMintingDetails?: MintingDetailsDataProps
 }
 
 export interface MintingDetailsDataProps {
@@ -26,7 +27,13 @@ export interface MintingDetailsDataProps {
   paymentAddress?: string
 }
 
-export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod, minimumMintPrice }: MintingDetailsProps) => {
+export const MintingDetails = ({
+  onChange,
+  numberOfTokens,
+  uploadMethod,
+  minimumMintPrice,
+  importedMintingDetails,
+}: MintingDetailsProps) => {
   const wallet = useWallet()
 
   const [timestamp, setTimestamp] = useState<Date | undefined>()
@@ -97,6 +104,17 @@ export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod, minimum
     paymentAddressState.value,
   ])
 
+  useEffect(() => {
+    if (importedMintingDetails) {
+      numberOfTokensState.onChange(importedMintingDetails.numTokens)
+      unitPriceState.onChange(Number(importedMintingDetails.unitPrice) / 1_000_000)
+      perAddressLimitState.onChange(importedMintingDetails.perAddressLimit)
+      setTimestamp(new Date(Number(importedMintingDetails.startTime) / 1_000_000))
+      paymentAddressState.onChange(importedMintingDetails.paymentAddress ? importedMintingDetails.paymentAddress : '')
+    }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [importedMintingDetails])
+
   return (
     <div>
       <FormGroup subtitle="Information about your minting settings" title="Minting Details">
diff --git a/components/collections/creation/RoyaltyDetails.tsx b/components/collections/creation/RoyaltyDetails.tsx
index 0d873e2..f8ccd35 100644
--- a/components/collections/creation/RoyaltyDetails.tsx
+++ b/components/collections/creation/RoyaltyDetails.tsx
@@ -9,6 +9,7 @@ import { NumberInput, TextInput } from '../../forms/FormInput'
 
 interface RoyaltyDetailsProps {
   onChange: (data: RoyaltyDetailsDataProps) => void
+  importedRoyaltyDetails?: RoyaltyDetailsDataProps
 }
 
 export interface RoyaltyDetailsDataProps {
@@ -19,7 +20,7 @@ export interface RoyaltyDetailsDataProps {
 
 type RoyaltyState = 'none' | 'new'
 
-export const RoyaltyDetails = ({ onChange }: RoyaltyDetailsProps) => {
+export const RoyaltyDetails = ({ onChange, importedRoyaltyDetails }: RoyaltyDetailsProps) => {
   const wallet = useWallet()
   const [royaltyState, setRoyaltyState] = useState<RoyaltyState>('none')
 
@@ -60,6 +61,15 @@ export const RoyaltyDetails = ({ onChange }: RoyaltyDetailsProps) => {
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [royaltyState, royaltyPaymentAddressState.value, royaltyShareState.value])
 
+  useEffect(() => {
+    if (importedRoyaltyDetails) {
+      setRoyaltyState(importedRoyaltyDetails.royaltyType)
+      royaltyPaymentAddressState.onChange(importedRoyaltyDetails.paymentAddress)
+      royaltyShareState.onChange(importedRoyaltyDetails.share.toString())
+    }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [importedRoyaltyDetails])
+
   return (
     <div className="py-3 px-8 rounded border-2 border-white/20">
       <div className="flex justify-center">
diff --git a/components/collections/creation/UploadDetails.tsx b/components/collections/creation/UploadDetails.tsx
index 02567a9..0b8aa61 100644
--- a/components/collections/creation/UploadDetails.tsx
+++ b/components/collections/creation/UploadDetails.tsx
@@ -31,6 +31,7 @@ interface UploadDetailsProps {
   onChange: (value: UploadDetailsDataProps) => void
   minterType: MinterType
   baseMinterAcquisitionMethod?: BaseMinterAcquisitionMethod
+  importedUploadDetails?: UploadDetailsDataProps
 }
 
 export interface UploadDetailsDataProps {
@@ -46,7 +47,12 @@ export interface UploadDetailsDataProps {
   baseMinterMetadataFile?: File
 }
 
-export const UploadDetails = ({ onChange, minterType, baseMinterAcquisitionMethod }: UploadDetailsProps) => {
+export const UploadDetails = ({
+  onChange,
+  minterType,
+  baseMinterAcquisitionMethod,
+  importedUploadDetails,
+}: UploadDetailsProps) => {
   const [assetFilesArray, setAssetFilesArray] = useState<File[]>([])
   const [metadataFilesArray, setMetadataFilesArray] = useState<File[]>([])
   const [uploadMethod, setUploadMethod] = useState<UploadMethod>('new')
@@ -274,10 +280,31 @@ export const UploadDetails = ({ onChange, minterType, baseMinterAcquisitionMetho
     setMetadataFilesArray([])
     if (assetFilesRef.current) assetFilesRef.current.value = ''
     setAssetFilesArray([])
-    baseTokenUriState.onChange('')
-    coverImageUrlState.onChange('')
+    if (!importedUploadDetails) {
+      baseTokenUriState.onChange('')
+      coverImageUrlState.onChange('')
+    }
   }, [uploadMethod, minterType, baseMinterAcquisitionMethod])
 
+  useEffect(() => {
+    if (importedUploadDetails) {
+      if (importedUploadDetails.uploadMethod === 'new') {
+        setUploadMethod('existing')
+        setUploadService(importedUploadDetails.uploadService)
+        nftStorageApiKeyState.onChange(importedUploadDetails.nftStorageApiKey || '')
+        pinataApiKeyState.onChange(importedUploadDetails.pinataApiKey || '')
+        pinataSecretKeyState.onChange(importedUploadDetails.pinataSecretKey || '')
+        baseTokenUriState.onChange(importedUploadDetails.baseTokenURI || '')
+        coverImageUrlState.onChange(importedUploadDetails.imageUrl || '')
+      } else if (importedUploadDetails.uploadMethod === 'existing') {
+        setUploadMethod('existing')
+        baseTokenUriState.onChange(importedUploadDetails.baseTokenURI || '')
+        coverImageUrlState.onChange(importedUploadDetails.imageUrl || '')
+      }
+    }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [importedUploadDetails])
+
   return (
     <div className="justify-items-start mb-3 rounded border-2 border-white/20 flex-column">
       <div className="flex justify-center">
diff --git a/components/collections/creation/WhitelistDetails.tsx b/components/collections/creation/WhitelistDetails.tsx
index 3f9daa7..fd3beb3 100644
--- a/components/collections/creation/WhitelistDetails.tsx
+++ b/components/collections/creation/WhitelistDetails.tsx
@@ -18,6 +18,7 @@ import { WhitelistUpload } from '../../WhitelistUpload'
 
 interface WhitelistDetailsProps {
   onChange: (data: WhitelistDetailsDataProps) => void
+  importedWhitelistDetails?: WhitelistDetailsDataProps
 }
 
 export interface WhitelistDetailsDataProps {
@@ -38,7 +39,7 @@ type WhitelistState = 'none' | 'existing' | 'new'
 
 type WhitelistType = 'standard' | 'flex'
 
-export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
+export const WhitelistDetails = ({ onChange, importedWhitelistDetails }: WhitelistDetailsProps) => {
   const [whitelistState, setWhitelistState] = useState<WhitelistState>('none')
   const [whitelistType, setWhitelistType] = useState<WhitelistType>('standard')
   const [startDate, setStartDate] = useState<Date | undefined>(undefined)
@@ -89,8 +90,10 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
   }
 
   useEffect(() => {
-    setWhitelistStandardArray([])
-    setWhitelistFlexArray([])
+    if (!importedWhitelistDetails) {
+      setWhitelistStandardArray([])
+      setWhitelistFlexArray([])
+    }
   }, [whitelistType])
 
   useEffect(() => {
@@ -138,6 +141,53 @@ export const WhitelistDetails = ({ onChange }: WhitelistDetailsProps) => {
     adminsMutable,
   ])
 
+  // make the necessary changes with respect to imported whitelist details
+  useEffect(() => {
+    if (importedWhitelistDetails) {
+      setWhitelistState(importedWhitelistDetails.whitelistState)
+      setWhitelistType(importedWhitelistDetails.whitelistType)
+      whitelistAddressState.onChange(
+        importedWhitelistDetails.contractAddress ? importedWhitelistDetails.contractAddress : '',
+      )
+      unitPriceState.onChange(importedWhitelistDetails.unitPrice ? Number(importedWhitelistDetails.unitPrice) : 0)
+      memberLimitState.onChange(importedWhitelistDetails.memberLimit ? importedWhitelistDetails.memberLimit : 0)
+      perAddressLimitState.onChange(
+        importedWhitelistDetails.perAddressLimit ? importedWhitelistDetails.perAddressLimit : 0,
+      )
+      setStartDate(
+        importedWhitelistDetails.startTime
+          ? new Date(Number(importedWhitelistDetails.startTime) / 1_000_000)
+          : undefined,
+      )
+      setEndDate(
+        importedWhitelistDetails.endTime ? new Date(Number(importedWhitelistDetails.endTime) / 1_000_000) : undefined,
+      )
+      setAdminsMutable(importedWhitelistDetails.adminsMutable ? importedWhitelistDetails.adminsMutable : true)
+      importedWhitelistDetails.admins?.forEach((admin) => {
+        addressListState.reset()
+        addressListState.add({ address: admin })
+      })
+      if (importedWhitelistDetails.whitelistType === 'standard') {
+        setWhitelistStandardArray([])
+        importedWhitelistDetails.members?.forEach((member) => {
+          setWhitelistStandardArray((standardArray) => [...standardArray, member as string])
+        })
+      } else {
+        setWhitelistFlexArray([])
+        importedWhitelistDetails.members?.forEach((member) => {
+          setWhitelistFlexArray((flexArray) => [
+            ...flexArray,
+            {
+              address: (member as WhitelistFlexMember).address,
+              mint_count: (member as WhitelistFlexMember).mint_count,
+            },
+          ])
+        })
+      }
+    }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [importedWhitelistDetails])
+
   return (
     <div className="py-3 px-8 rounded border-2 border-white/20">
       <div className="flex justify-center">

From 75fe1d33876d96a50622bee6e4cc09d17b8fa613 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Wed, 26 Jul 2023 22:26:27 +0300
Subject: [PATCH 06/51] Init TokenInfo

---
 config/token.ts | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
 create mode 100644 config/token.ts

diff --git a/config/token.ts b/config/token.ts
new file mode 100644
index 0000000..10d815f
--- /dev/null
+++ b/config/token.ts
@@ -0,0 +1,22 @@
+export interface TokenInfo {
+  id: string
+  denom: string
+  displayName: string
+  decimalPlaces: number
+  imageURL?: string
+  symbol?: string
+}
+
+export const ibcAtom: TokenInfo = {
+  id: 'ibc-atom',
+  denom: 'ibc/',
+  displayName: 'ATOM',
+  decimalPlaces: 6,
+}
+
+export const stars: TokenInfo = {
+  id: 'stars',
+  denom: 'ustars',
+  displayName: 'STARS',
+  decimalPlaces: 6,
+}

From 3ff3d094b405a908ee676f71f4333f9bc9e4ddb5 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Thu, 27 Jul 2023 17:26:51 +0300
Subject: [PATCH 07/51] Init minter list

---
 .env.example       |  2 ++
 config/minter.ts   | 34 ++++++++++++++++++++++++++++++++++
 config/token.ts    | 23 ++++++++++++++++-------
 env.d.ts           |  2 ++
 utils/constants.ts |  2 ++
 5 files changed, 56 insertions(+), 7 deletions(-)
 create mode 100644 config/minter.ts

diff --git a/.env.example b/.env.example
index 46be8b3..7ec8697 100644
--- a/.env.example
+++ b/.env.example
@@ -14,6 +14,8 @@ NEXT_PUBLIC_VENDING_FACTORY_FLEX_ADDRESS="stars1hvu2ghqkcnvhtj2fc6wuazxt4dqcftsl
 NEXT_PUBLIC_BASE_FACTORY_ADDRESS="stars1a45hcxty3spnmm2f0papl8v4dk5ew29s4syhn4efte8u5haex99qlkrtnx"
 NEXT_PUBLIC_BASE_FACTORY_UPDATABLE_ADDRESS="stars100xegx2syry4tclkmejjwxk4nfqahvcqhm9qxut5wxuzhj5d9qfsh5nmym"
 NEXT_PUBLIC_OPEN_EDITION_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+NEXT_PUBLIC_OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+NEXT_PUBLIC_OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
 NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS="stars1fk5dkzcylam8mcpqrn8y9spauvc3d4navtaqurcc49dc3p9f8d3qdkvymx"
 NEXT_PUBLIC_OPEN_EDITION_MINTER_CODE_ID=2579
 
diff --git a/config/minter.ts b/config/minter.ts
new file mode 100644
index 0000000..4fa2a14
--- /dev/null
+++ b/config/minter.ts
@@ -0,0 +1,34 @@
+import {
+  OPEN_EDITION_FACTORY_ADDRESS,
+  OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS,
+  OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS,
+} from 'utils/constants'
+
+import type { TokenInfo } from './token'
+import { ibcAtom, ibcFrenz, stars } from './token'
+
+export interface MinterInfo {
+  id: string
+  factoryAddress: string
+  supportedToken: TokenInfo
+}
+
+export const openEditionStarsMinter: MinterInfo = {
+  id: 'open-edition-stars-minter',
+  factoryAddress: OPEN_EDITION_FACTORY_ADDRESS,
+  supportedToken: stars,
+}
+
+export const openEditionIbcAtomMinter: MinterInfo = {
+  id: 'open-edition-ibc-atom-minter',
+  factoryAddress: OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS,
+  supportedToken: ibcAtom,
+}
+
+export const openEditionIbcFrenzMinter: MinterInfo = {
+  id: 'open-edition-ibc-frenz-minter',
+  factoryAddress: OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS,
+  supportedToken: ibcFrenz,
+}
+
+export const minterList = [openEditionStarsMinter, openEditionIbcAtomMinter, openEditionIbcFrenzMinter]
diff --git a/config/token.ts b/config/token.ts
index 10d815f..8f64d82 100644
--- a/config/token.ts
+++ b/config/token.ts
@@ -7,16 +7,25 @@ export interface TokenInfo {
   symbol?: string
 }
 
-export const ibcAtom: TokenInfo = {
-  id: 'ibc-atom',
-  denom: 'ibc/',
-  displayName: 'ATOM',
-  decimalPlaces: 6,
-}
-
 export const stars: TokenInfo = {
   id: 'stars',
   denom: 'ustars',
   displayName: 'STARS',
   decimalPlaces: 6,
 }
+
+export const ibcAtom: TokenInfo = {
+  id: 'ibc-atom',
+  denom: 'ibc/atom',
+  displayName: 'ATOM',
+  decimalPlaces: 6,
+}
+
+export const ibcFrenz: TokenInfo = {
+  id: 'ibc-frenz',
+  denom: 'ibc/frenz',
+  displayName: 'FRENZ',
+  decimalPlaces: 6,
+}
+
+export const tokensList = [stars, ibcAtom, ibcFrenz]
diff --git a/env.d.ts b/env.d.ts
index 955e661..77abe04 100644
--- a/env.d.ts
+++ b/env.d.ts
@@ -24,6 +24,8 @@ declare namespace NodeJS {
     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_IBC_ATOM_FACTORY_ADDRESS: string
+    readonly NEXT_PUBLIC_OPEN_EDITION_IBC_FRENZ_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
diff --git a/utils/constants.ts b/utils/constants.ts
index 097aefa..81955ff 100644
--- a/utils/constants.ts
+++ b/utils/constants.ts
@@ -15,6 +15,8 @@ export const VENDING_FACTORY_FLEX_ADDRESS = process.env.NEXT_PUBLIC_VENDING_FACT
 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_IBC_ATOM_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS
+export const OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS
 export const OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_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

From 701369f2462e53ff1bd60b3ee37c2454c4a4c4bf Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Fri, 28 Jul 2023 23:38:45 +0300
Subject: [PATCH 08/51] Surface Open Edition Minter details

---
 .../openEdition/OpenEditionMinterCreator.tsx  | 37 +++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/components/openEdition/OpenEditionMinterCreator.tsx b/components/openEdition/OpenEditionMinterCreator.tsx
index 3f0fce3..eab0869 100644
--- a/components/openEdition/OpenEditionMinterCreator.tsx
+++ b/components/openEdition/OpenEditionMinterCreator.tsx
@@ -12,6 +12,7 @@ import type { MinterType } from 'components/collections/actions/Combobox'
 import { Conditional } from 'components/Conditional'
 import { ConfirmationModal } from 'components/ConfirmationModal'
 import { LoadingModal } from 'components/LoadingModal'
+import type { TokenInfo } from 'config/token'
 import { useContracts } from 'contexts/contracts'
 import { addLogItem } from 'contexts/log'
 import { useWallet } from 'contexts/wallet'
@@ -47,13 +48,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,11 +78,13 @@ export interface OpenEditionMinterCreatorDataProps {
 
 export const OpenEditionMinterCreator = ({
   onChange,
+  onDetailsChange,
   openEditionMinterCreationFee,
   openEditionMinterUpdatableCreationFee,
   minimumMintPrice,
   minimumUpdatableMintPrice,
   minterType,
+  mintTokenFromFactory,
 }: OpenEditionMinterCreatorProps) => {
   const wallet = useWallet()
   const { openEditionMinter: openEditionMinterContract, openEditionFactory: openEditionFactoryContract } =
@@ -585,6 +600,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 (
     <div>
       {/* TODO: Cancel once we're able to index on-chain metadata */}
@@ -669,6 +705,7 @@ export const OpenEditionMinterCreator = ({
               ? Number(minimumUpdatableMintPrice) / 1000000
               : Number(minimumMintPrice) / 1000000
           }
+          mintTokenFromFactory={mintTokenFromFactory}
           onChange={setMintingDetails}
           uploadMethod={offChainMetadataUploadDetails?.uploadMethod as UploadMethod}
         />

From 000a67a2f6c517f351e584d6e3e2cce759079917 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 30 Jul 2023 21:11:10 +0300
Subject: [PATCH 09/51] Update env variables

---
 .env.example       |  8 ++++++--
 env.d.ts           |  8 ++++++--
 utils/constants.ts | 11 +++++++++--
 3 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/.env.example b/.env.example
index 7ec8697..29d3ca6 100644
--- a/.env.example
+++ b/.env.example
@@ -14,9 +14,13 @@ NEXT_PUBLIC_VENDING_FACTORY_FLEX_ADDRESS="stars1hvu2ghqkcnvhtj2fc6wuazxt4dqcftsl
 NEXT_PUBLIC_BASE_FACTORY_ADDRESS="stars1a45hcxty3spnmm2f0papl8v4dk5ew29s4syhn4efte8u5haex99qlkrtnx"
 NEXT_PUBLIC_BASE_FACTORY_UPDATABLE_ADDRESS="stars100xegx2syry4tclkmejjwxk4nfqahvcqhm9qxut5wxuzhj5d9qfsh5nmym"
 NEXT_PUBLIC_OPEN_EDITION_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-NEXT_PUBLIC_OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-NEXT_PUBLIC_OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
 NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS="stars1fk5dkzcylam8mcpqrn8y9spauvc3d4navtaqurcc49dc3p9f8d3qdkvymx"
+NEXT_PUBLIC_OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+NEXT_PUBLIC_OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+NEXT_PUBLIC_OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_FRENZ_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
 NEXT_PUBLIC_OPEN_EDITION_MINTER_CODE_ID=2579
 
 NEXT_PUBLIC_SG721_NAME_ADDRESS="stars1fx74nkqkw2748av8j7ew7r3xt9cgjqduwn8m0ur5lhe49uhlsasszc5fhr"
diff --git a/env.d.ts b/env.d.ts
index 77abe04..72e2935 100644
--- a/env.d.ts
+++ b/env.d.ts
@@ -24,9 +24,13 @@ declare namespace NodeJS {
     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_IBC_ATOM_FACTORY_ADDRESS: string
-    readonly NEXT_PUBLIC_OPEN_EDITION_IBC_FRENZ_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_FRENZ_FACTORY_ADDRESS: string
+    readonly NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_FRENZ_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
diff --git a/utils/constants.ts b/utils/constants.ts
index 81955ff..2f0e607 100644
--- a/utils/constants.ts
+++ b/utils/constants.ts
@@ -15,9 +15,16 @@ export const VENDING_FACTORY_FLEX_ADDRESS = process.env.NEXT_PUBLIC_VENDING_FACT
 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_IBC_ATOM_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS
-export const OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_FRENZ_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_FRENZ_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS
+export const OPEN_EDITION_UPDATABLE_IBC_FRENZ_FACTORY_ADDRESS =
+  process.env.NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_FRENZ_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)

From 717fd88e74506d56dba9493cb175d05a20293149 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 30 Jul 2023 21:11:37 +0300
Subject: [PATCH 10/51] Update minter and token list

---
 config/minter.ts | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
 config/token.ts  |  9 ++++++++-
 2 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/config/minter.ts b/config/minter.ts
index 4fa2a14..6260da1 100644
--- a/config/minter.ts
+++ b/config/minter.ts
@@ -2,33 +2,77 @@ import {
   OPEN_EDITION_FACTORY_ADDRESS,
   OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS,
   OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS,
+  OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS,
+  OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS,
+  OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS,
+  OPEN_EDITION_UPDATABLE_IBC_FRENZ_FACTORY_ADDRESS,
+  OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS,
 } from 'utils/constants'
 
 import type { TokenInfo } from './token'
-import { ibcAtom, ibcFrenz, stars } from './token'
+import { ibcAtom, ibcFrenz, ibcUsdc, stars } from './token'
 
 export interface MinterInfo {
   id: string
   factoryAddress: string
   supportedToken: TokenInfo
+  updatable?: 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-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-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-ibc-usdc-minter',
+  factoryAddress: OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS,
+  supportedToken: ibcUsdc,
+  updatable: false,
 }
 
 export const openEditionIbcFrenzMinter: MinterInfo = {
   id: 'open-edition-ibc-frenz-minter',
   factoryAddress: OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS,
   supportedToken: ibcFrenz,
+  updatable: false,
 }
 
-export const minterList = [openEditionStarsMinter, openEditionIbcAtomMinter, openEditionIbcFrenzMinter]
+export const openEditionUpdatableIbcFrenzMinter: MinterInfo = {
+  id: 'open-edition-ibc-frenz-minter',
+  factoryAddress: OPEN_EDITION_UPDATABLE_IBC_FRENZ_FACTORY_ADDRESS,
+  supportedToken: ibcFrenz,
+  updatable: true,
+}
+
+export const openEditionMinterList = [openEditionStarsMinter, openEditionIbcAtomMinter, openEditionIbcFrenzMinter]
diff --git a/config/token.ts b/config/token.ts
index 8f64d82..3119c6d 100644
--- a/config/token.ts
+++ b/config/token.ts
@@ -21,6 +21,13 @@ export const ibcAtom: TokenInfo = {
   decimalPlaces: 6,
 }
 
+export const ibcUsdc: TokenInfo = {
+  id: 'ibc-usdc',
+  denom: 'ibc/usdc',
+  displayName: 'USDC',
+  decimalPlaces: 6,
+}
+
 export const ibcFrenz: TokenInfo = {
   id: 'ibc-frenz',
   denom: 'ibc/frenz',
@@ -28,4 +35,4 @@ export const ibcFrenz: TokenInfo = {
   decimalPlaces: 6,
 }
 
-export const tokensList = [stars, ibcAtom, ibcFrenz]
+export const tokensList = [stars, ibcAtom, ibcUsdc, ibcFrenz]

From d2d06dffae0899eb6a050123e841132e87d47e76 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 31 Jul 2023 12:25:57 +0300
Subject: [PATCH 11/51] Match selected denom and fetch open edition factory
 parameters

---
 components/openEdition/MintingDetails.tsx |  46 ++++++++-
 config/minter.ts                          |  19 +++-
 pages/collections/create.tsx              | 108 ++++++++++++++++++----
 3 files changed, 144 insertions(+), 29 deletions(-)

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<Date | undefined>()
   const [endTimestamp, setEndTimestamp] = useState<Date | undefined>()
+  const [selectedMintToken, setSelectedMintToken] = useState<TokenInfo | undefined>(stars)
 
   const unitPriceState = useNumberInputState({
     id: 'unitPrice',
     name: 'unitPrice',
-    title: 'Unit Price',
-    subtitle: `Price of each token (min. ${minimumMintPrice} STARS)`,
+    title: 'Mint Price',
+    subtitle: `Price of each token (min. ${minimumMintPrice} ${
+      mintTokenFromFactory ? mintTokenFromFactory.displayName : 'STARS'
+    })`,
     placeholder: '50',
   })
 
@@ -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 (
     <div className="border-l-[1px] border-gray-500 border-opacity-20">
       <FormGroup subtitle="Information about your minting settings" title="Minting Details">
-        <NumberInput {...unitPriceState} isRequired />
+        <div className="flex flex-row items-center">
+          <NumberInput {...unitPriceState} isRequired />
+          <select
+            className="py-[9px] px-4 mt-14 ml-4 placeholder:text-white/50 bg-white/10 rounded border-2 border-white/20 focus:ring focus:ring-plumbus-20"
+            onChange={(e) => setSelectedMintToken(tokensList.find((t) => t.displayName === e.target.value))}
+          >
+            {openEditionMinterList
+              .filter((minter) => minter.factoryAddress !== undefined && minter.updatable === false)
+              .map((minter) => (
+                <option key={minter.id} className="bg-black" value={minter.supportedToken.displayName}>
+                  {minter.supportedToken.displayName}
+                </option>
+              ))}
+          </select>
+        </div>
+
         <NumberInput {...perAddressLimitState} isRequired />
         <FormControl htmlId="timestamp" isRequired subtitle="Minting start time (local)" title="Start Time">
           <InputDateTime minDate={new Date()} onChange={(date) => setTimestamp(date)} value={timestamp} />
diff --git a/config/minter.ts b/config/minter.ts
index 6260da1..413614d 100644
--- a/config/minter.ts
+++ b/config/minter.ts
@@ -27,7 +27,7 @@ export const openEditionStarsMinter: MinterInfo = {
 }
 
 export const openEditionUpdatableStarsMinter: MinterInfo = {
-  id: 'open-edition-stars-minter',
+  id: 'open-edition-updatable-stars-minter',
   factoryAddress: OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS,
   supportedToken: stars,
   updatable: true,
@@ -41,7 +41,7 @@ export const openEditionIbcAtomMinter: MinterInfo = {
 }
 
 export const openEditionUpdatableIbcAtomMinter: MinterInfo = {
-  id: 'open-edition-ibc-atom-minter',
+  id: 'open-edition-updatable-ibc-atom-minter',
   factoryAddress: OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS,
   supportedToken: ibcAtom,
   updatable: true,
@@ -55,7 +55,7 @@ export const openEditionIbcUsdcMinter: MinterInfo = {
 }
 
 export const openEditionUpdatableIbcUsdcMinter: MinterInfo = {
-  id: 'open-edition-ibc-usdc-minter',
+  id: 'open-edition-updatable-ibc-usdc-minter',
   factoryAddress: OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS,
   supportedToken: ibcUsdc,
   updatable: false,
@@ -69,10 +69,19 @@ export const openEditionIbcFrenzMinter: MinterInfo = {
 }
 
 export const openEditionUpdatableIbcFrenzMinter: MinterInfo = {
-  id: 'open-edition-ibc-frenz-minter',
+  id: 'open-edition-updatable-ibc-frenz-minter',
   factoryAddress: OPEN_EDITION_UPDATABLE_IBC_FRENZ_FACTORY_ADDRESS,
   supportedToken: ibcFrenz,
   updatable: true,
 }
 
-export const openEditionMinterList = [openEditionStarsMinter, openEditionIbcAtomMinter, openEditionIbcFrenzMinter]
+export const openEditionMinterList = [
+  openEditionStarsMinter,
+  openEditionUpdatableStarsMinter,
+  openEditionUpdatableIbcAtomMinter,
+  openEditionIbcAtomMinter,
+  openEditionIbcFrenzMinter,
+  openEditionUpdatableIbcFrenzMinter,
+  openEditionIbcUsdcMinter,
+  openEditionUpdatableIbcUsdcMinter,
+]
diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 6a99323..9493fba 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 { 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'
@@ -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 { tokensList } from '../../config/token'
 import { getAssetType } from '../../utils/getAssetType'
 import { isValidAddress } from '../../utils/isValidAddress'
 
@@ -99,7 +103,9 @@ const CollectionCreationPage: NextPage = () => {
   const [uploadDetails, setUploadDetails] = useState<UploadDetailsDataProps | null>(null)
   const [collectionDetails, setCollectionDetails] = useState<CollectionDetailsDataProps | 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,
   )
   const [mintingDetails, setMintingDetails] = useState<MintingDetailsDataProps | null>(null)
@@ -122,6 +128,10 @@ const CollectionCreationPage: NextPage = () => {
   const [minimumOpenEditionUpdatableMintPrice, setMinimumOpenEditionUpdatableMintPrice] = useState<string | null>('0')
   const [minimumFlexMintPrice, setMinimumFlexMintPrice] = useState<string | null>('0')
 
+  const [mintTokenFromOpenEditionFactory, setMintTokenFromOpenEditionFactory] = useState<TokenInfo | undefined>(
+    undefined,
+  )
+
   const [uploading, setUploading] = useState(false)
   const [isMintingComplete, setIsMintingComplete] = useState(false)
   const [creatingCollection, setCreatingCollection] = useState(false)
@@ -1043,7 +1053,7 @@ const CollectionCreationPage: NextPage = () => {
     }
   }
 
-  const fetchFactoryParameters = async () => {
+  const fetchInitialFactoryParameters = async () => {
     const client = wallet.client
     if (!client) return
     if (BASE_FACTORY_ADDRESS) {
@@ -1100,6 +1110,7 @@ const CollectionCreationPage: NextPage = () => {
       setVendingMinterFlexCreationFee(vendingFactoryFlexParameters?.params?.creation_fee?.amount)
       setMinimumFlexMintPrice(vendingFactoryFlexParameters?.params?.min_mint_price?.amount)
     }
+
     if (OPEN_EDITION_FACTORY_ADDRESS) {
       const openEditionFactoryParameters = await client
         .queryContractSmart(OPEN_EDITION_FACTORY_ADDRESS, { params: {} })
@@ -1122,6 +1133,59 @@ const CollectionCreationPage: NextPage = () => {
     }
   }
 
+  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),
+        )
+      }
+      console.log('Selected OE Factory: ', factoryForSelectedDenom)
+      console.log('Selected Updatable OE Factory: ', updatableFactoryForSelectedDenom)
+    }
+    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) {
+        setMinimumOpenEditionMintPrice(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 checkwalletBalance = async () => {
     const walletBalance = await wallet.client?.getBalance(wallet.address, 'ustars').then((balance) => {
       if (minterType === 'vending' && whitelistDetails?.whitelistState === 'new' && whitelistDetails.memberLimit) {
@@ -1161,25 +1225,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()
@@ -1192,7 +1256,7 @@ const CollectionCreationPage: NextPage = () => {
     }
   }, [
     vendingMinterContractAddress,
-    openEditionMinterDetails?.openEditionMinterContractAddress,
+    openEditionMinterCreatorData?.openEditionMinterContractAddress,
     isMintingComplete,
     minterType,
     syncCollections,
@@ -1210,9 +1274,13 @@ const CollectionCreationPage: NextPage = () => {
   }, [minterType, baseMinterDetails?.baseMinterAcquisitionMethod, uploadDetails?.uploadMethod])
 
   useEffect(() => {
-    void fetchFactoryParameters()
+    void fetchInitialFactoryParameters()
   }, [wallet.client])
 
+  useEffect(() => {
+    void fetchOpenEditionFactoryParameters()
+  }, [fetchOpenEditionFactoryParameters])
+
   return (
     <div>
       <NextSeo
@@ -1244,7 +1312,7 @@ const CollectionCreationPage: NextPage = () => {
       </div>
       <div className="mx-10" ref={scrollRef}>
         <Conditional
-          test={minterType === 'openEdition' && openEditionMinterDetails?.openEditionMinterContractAddress !== null}
+          test={minterType === 'openEdition' && openEditionMinterCreatorData?.openEditionMinterContractAddress !== null}
         >
           <Alert className="mt-5" type="info">
             <div>
@@ -1253,10 +1321,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}
               </Anchor>
               <br />
               SG721 Contract Address:{'  '}
@@ -1264,10 +1332,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}
               </Anchor>
               <br />
               Transaction Hash: {'  '}
@@ -1275,18 +1343,18 @@ const CollectionCreationPage: NextPage = () => {
                 <Anchor
                   className="text-stargaze hover:underline"
                   external
-                  href={`${BLOCK_EXPLORER_URL}/tx/${openEditionMinterDetails?.transactionHash as string}`}
+                  href={`${BLOCK_EXPLORER_URL}/tx/${openEditionMinterCreatorData?.transactionHash as string}`}
                 >
-                  {openEditionMinterDetails?.transactionHash}
+                  {openEditionMinterCreatorData?.transactionHash}
                 </Anchor>
               </Conditional>
               <Conditional test={NETWORK === 'mainnet'}>
                 <Anchor
                   className="text-stargaze hover:underline"
                   external
-                  href={`${BLOCK_EXPLORER_URL}/txs/${openEditionMinterDetails?.transactionHash as string}`}
+                  href={`${BLOCK_EXPLORER_URL}/txs/${openEditionMinterCreatorData?.transactionHash as string}`}
                 >
-                  {openEditionMinterDetails?.transactionHash}
+                  {openEditionMinterCreatorData?.transactionHash}
                 </Anchor>
               </Conditional>
               <br />
@@ -1295,7 +1363,7 @@ const CollectionCreationPage: NextPage = () => {
                   className="text-white"
                   external
                   href={`${STARGAZE_URL}/launchpad/${
-                    openEditionMinterDetails?.openEditionMinterContractAddress as string
+                    openEditionMinterCreatorData?.openEditionMinterContractAddress as string
                   }`}
                 >
                   View on Launchpad
@@ -1563,8 +1631,10 @@ const CollectionCreationPage: NextPage = () => {
         <OpenEditionMinterCreator
           minimumMintPrice={minimumOpenEditionMintPrice as string}
           minimumUpdatableMintPrice={minimumOpenEditionUpdatableMintPrice as string}
+          mintTokenFromFactory={mintTokenFromOpenEditionFactory}
           minterType={minterType}
-          onChange={setOpenEditionMinterDetails}
+          onChange={setOpenEditionMinterCreatorData}
+          onDetailsChange={setOpenEditionMinterDetails}
           openEditionMinterCreationFee={openEditionMinterCreationFee as string}
           openEditionMinterUpdatableCreationFee={openEditionMinterUpdatableCreationFee as string}
         />

From 1bfd1113bbeadb584193c0913133a217f8d4573f Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 31 Jul 2023 16:49:35 +0300
Subject: [PATCH 12/51] Open edition IBC minter creation success

---
 .../openEdition/OpenEditionMinterCreator.tsx  | 26 ++++++++++++++-----
 config/minter.ts                              |  2 +-
 contracts/openEditionFactory/contract.ts      | 13 +++-------
 pages/collections/create.tsx                  |  7 +++--
 4 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/components/openEdition/OpenEditionMinterCreator.tsx b/components/openEdition/OpenEditionMinterCreator.tsx
index eab0869..15af184 100644
--- a/components/openEdition/OpenEditionMinterCreator.tsx
+++ b/components/openEdition/OpenEditionMinterCreator.tsx
@@ -12,6 +12,7 @@ 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'
@@ -90,10 +91,6 @@ export const OpenEditionMinterCreator = ({
   const { openEditionMinter: openEditionMinterContract, openEditionFactory: openEditionFactoryContract } =
     useContracts()
 
-  const openEditionFactoryMessages = useMemo(
-    () => openEditionFactoryContract?.use(OPEN_EDITION_FACTORY_ADDRESS),
-    [openEditionFactoryContract, wallet.address],
-  )
   const [metadataStorageMethod, setMetadataStorageMethod] = useState<MetadataStorageMethod>('off-chain')
   const [imageUploadDetails, setImageUploadDetails] = useState<ImageUploadDetailsDataProps | null>(null)
   const [collectionDetails, setCollectionDetails] = useState<CollectionDetailsDataProps | null>(null)
@@ -114,6 +111,21 @@ export const OpenEditionMinterCreator = ({
   const [sg721ContractAddress, setSg721ContractAddress] = useState<string | null>(null)
   const [transactionHash, setTransactionHash] = useState<string | null>(null)
 
+  const factoryAddressForSelectedDenom =
+    openEditionMinterList.find((minter) => minter.supportedToken === mintTokenFromFactory && minter.updatable === false)
+      ?.factoryAddress || OPEN_EDITION_FACTORY_ADDRESS
+  const updatableFactoryAddressForSelectedDenom =
+    openEditionMinterList.find((minter) => minter.supportedToken === mintTokenFromFactory && minter.updatable === true)
+      ?.factoryAddress || OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS
+
+  const openEditionFactoryMessages = useMemo(
+    () =>
+      openEditionFactoryContract?.use(
+        collectionDetails?.updatable ? updatableFactoryAddressForSelectedDenom : factoryAddressForSelectedDenom,
+      ),
+    [openEditionFactoryContract, wallet.address],
+  )
+
   const performOpenEditionMinterChecks = () => {
     try {
       setReadyToCreate(false)
@@ -528,7 +540,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,
@@ -550,9 +562,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,
diff --git a/config/minter.ts b/config/minter.ts
index 413614d..d191f14 100644
--- a/config/minter.ts
+++ b/config/minter.ts
@@ -58,7 +58,7 @@ export const openEditionUpdatableIbcUsdcMinter: MinterInfo = {
   id: 'open-edition-updatable-ibc-usdc-minter',
   factoryAddress: OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS,
   supportedToken: ibcUsdc,
-  updatable: false,
+  updatable: true,
 }
 
 export const openEditionIbcFrenzMinter: MinterInfo = {
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<string, unknown>,
     funds: Coin[],
     updatable?: boolean,
+    selectedFactoryAddress?: string,
   ) => Promise<CreateOpenEditionMinterResponse>
 }
 
@@ -56,16 +56,9 @@ export const openEditionFactory = (client: SigningCosmWasmClient, txSigner: stri
       senderAddress: string,
       msg: Record<string, unknown>,
       funds: Coin[],
-      updatable?: boolean,
     ): Promise<CreateOpenEditionMinterResponse> => {
-      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/pages/collections/create.tsx b/pages/collections/create.tsx
index 9493fba..42573f7 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -74,7 +74,7 @@ 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 { tokensList } from '../../config/token'
+import { stars, tokensList } from '../../config/token'
 import { getAssetType } from '../../utils/getAssetType'
 import { isValidAddress } from '../../utils/isValidAddress'
 
@@ -128,9 +128,7 @@ const CollectionCreationPage: NextPage = () => {
   const [minimumOpenEditionUpdatableMintPrice, setMinimumOpenEditionUpdatableMintPrice] = useState<string | null>('0')
   const [minimumFlexMintPrice, setMinimumFlexMintPrice] = useState<string | null>('0')
 
-  const [mintTokenFromOpenEditionFactory, setMintTokenFromOpenEditionFactory] = useState<TokenInfo | undefined>(
-    undefined,
-  )
+  const [mintTokenFromOpenEditionFactory, setMintTokenFromOpenEditionFactory] = useState<TokenInfo | undefined>(stars)
 
   const [uploading, setUploading] = useState(false)
   const [isMintingComplete, setIsMintingComplete] = useState(false)
@@ -1153,6 +1151,7 @@ const CollectionCreationPage: NextPage = () => {
           toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
           addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
         })
+      console.log('Open Edition Factory Parameters: ', openEditionFactoryParameters)
       setOpenEditionMinterCreationFee(openEditionFactoryParameters?.params?.creation_fee?.amount)
       if (!openEditionMinterDetails?.collectionDetails?.updatable) {
         setMinimumOpenEditionMintPrice(openEditionFactoryParameters?.params?.min_mint_price?.amount)

From 4f473b6bf818809d9a4986b2240010c10c9927c7 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 31 Jul 2023 17:24:04 +0300
Subject: [PATCH 13/51] Display the right denom in minimum mint price not met
 error

---
 components/openEdition/OpenEditionMinterCreator.tsx | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/components/openEdition/OpenEditionMinterCreator.tsx b/components/openEdition/OpenEditionMinterCreator.tsx
index 15af184..0db516e 100644
--- a/components/openEdition/OpenEditionMinterCreator.tsx
+++ b/components/openEdition/OpenEditionMinterCreator.tsx
@@ -284,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')

From ce477c8b768702dc21b56dc1551e695331ededb6 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Tue, 1 Aug 2023 11:14:22 +0300
Subject: [PATCH 14/51] Include vending minters in the minter list

---
 .env.example       |  4 ++++
 config/minter.ts   | 57 ++++++++++++++++++++++++++++++++++++++++++++++
 env.d.ts           |  4 ++++
 utils/constants.ts |  6 +++++
 4 files changed, 71 insertions(+)

diff --git a/.env.example b/.env.example
index 29d3ca6..538335d 100644
--- a/.env.example
+++ b/.env.example
@@ -11,6 +11,10 @@ NEXT_PUBLIC_BASE_MINTER_CODE_ID=2598
 NEXT_PUBLIC_VENDING_FACTORY_ADDRESS="stars18h7ugh8eaug7wr0w4yjw0ls5s937z35pnkg935ucsek2y9xl3gaqqk4jtx"
 NEXT_PUBLIC_VENDING_FACTORY_UPDATABLE_ADDRESS="stars1h65nms9gwg4vdktyqj84tu50gwlm34e0eczl5w2ezllxuzfxy9esa9qlt0"
 NEXT_PUBLIC_VENDING_FACTORY_FLEX_ADDRESS="stars1hvu2ghqkcnvhtj2fc6wuazxt4dqcftslp2rwkkkcxy269a35a9pq60ug2q"
+NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
 NEXT_PUBLIC_BASE_FACTORY_ADDRESS="stars1a45hcxty3spnmm2f0papl8v4dk5ew29s4syhn4efte8u5haex99qlkrtnx"
 NEXT_PUBLIC_BASE_FACTORY_UPDATABLE_ADDRESS="stars100xegx2syry4tclkmejjwxk4nfqahvcqhm9qxut5wxuzhj5d9qfsh5nmym"
 NEXT_PUBLIC_OPEN_EDITION_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
diff --git a/config/minter.ts b/config/minter.ts
index d191f14..b7d359f 100644
--- a/config/minter.ts
+++ b/config/minter.ts
@@ -7,6 +7,12 @@ import {
   OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS,
   OPEN_EDITION_UPDATABLE_IBC_FRENZ_FACTORY_ADDRESS,
   OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS,
+  VENDING_FACTORY_ADDRESS,
+  VENDING_FACTORY_UPDATABLE_ADDRESS,
+  VENDING_IBC_ATOM_FACTORY_ADDRESS,
+  VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS,
+  VENDING_IBC_USDC_FACTORY_ADDRESS,
+  VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS,
 } from 'utils/constants'
 
 import type { TokenInfo } from './token'
@@ -85,3 +91,54 @@ export const openEditionMinterList = [
   openEditionIbcUsdcMinter,
   openEditionUpdatableIbcUsdcMinter,
 ]
+
+export const vendingStarsMinter: MinterInfo = {
+  id: 'vending-stars-minter',
+  factoryAddress: VENDING_FACTORY_ADDRESS,
+  supportedToken: stars,
+  updatable: false,
+}
+
+export const vendingUpdatableStarsMinter: MinterInfo = {
+  id: 'vending-updatable-stars-minter',
+  factoryAddress: VENDING_FACTORY_UPDATABLE_ADDRESS,
+  supportedToken: stars,
+  updatable: true,
+}
+
+export const vendingIbcAtomMinter: MinterInfo = {
+  id: 'vending-ibc-atom-minter',
+  factoryAddress: VENDING_IBC_ATOM_FACTORY_ADDRESS,
+  supportedToken: ibcAtom,
+  updatable: false,
+}
+
+export const vendingUpdatableIbcAtomMinter: MinterInfo = {
+  id: 'vending-updatable-ibc-atom-minter',
+  factoryAddress: VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS,
+  supportedToken: ibcAtom,
+  updatable: true,
+}
+
+export const vendingIbcUsdcMinter: MinterInfo = {
+  id: 'vending-ibc-usdc-minter',
+  factoryAddress: VENDING_IBC_USDC_FACTORY_ADDRESS,
+  supportedToken: ibcUsdc,
+  updatable: false,
+}
+
+export const vendingUpdatableIbcUsdcMinter: MinterInfo = {
+  id: 'vending-updatable-ibc-usdc-minter',
+  factoryAddress: VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS,
+  supportedToken: ibcUsdc,
+  updatable: true,
+}
+
+export const vendingMinterList = [
+  vendingStarsMinter,
+  vendingUpdatableStarsMinter,
+  vendingIbcAtomMinter,
+  vendingUpdatableIbcAtomMinter,
+  vendingIbcUsdcMinter,
+  vendingUpdatableIbcUsdcMinter,
+]
diff --git a/env.d.ts b/env.d.ts
index 72e2935..1325002 100644
--- a/env.d.ts
+++ b/env.d.ts
@@ -23,6 +23,10 @@ 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_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_OPEN_EDITION_FACTORY_ADDRESS: string
     readonly NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS: string
     readonly NEXT_PUBLIC_OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS: string
diff --git a/utils/constants.ts b/utils/constants.ts
index 2f0e607..01b8a8a 100644
--- a/utils/constants.ts
+++ b/utils/constants.ts
@@ -12,6 +12,12 @@ 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_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 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

From 3621a7363e3f2ea4bb95d1c26856a8b01077f3cd Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Tue, 1 Aug 2023 11:26:24 +0300
Subject: [PATCH 15/51] Add mint denom selection for standard collections

---
 .../collections/creation/MintingDetails.tsx   | 24 ++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/components/collections/creation/MintingDetails.tsx b/components/collections/creation/MintingDetails.tsx
index 6ca136e..e6555f1 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'
 
@@ -24,12 +27,14 @@ export interface MintingDetailsDataProps {
   perAddressLimit: number
   startTime: string
   paymentAddress?: string
+  selectedMintToken?: TokenInfo
 }
 
 export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod, minimumMintPrice }: MintingDetailsProps) => {
   const wallet = useWallet()
 
   const [timestamp, setTimestamp] = useState<Date | undefined>()
+  const [selectedMintToken, setSelectedMintToken] = useState<TokenInfo | undefined>(stars)
 
   const numberOfTokensState = useNumberInputState({
     id: 'numberoftokens',
@@ -85,6 +90,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 +101,7 @@ export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod, minimum
     perAddressLimitState.value,
     timestamp,
     paymentAddressState.value,
+    selectedMintToken,
   ])
 
   return (
@@ -106,7 +113,22 @@ export const MintingDetails = ({ onChange, numberOfTokens, uploadMethod, minimum
           isRequired
           value={uploadMethod === 'new' ? numberOfTokens : numberOfTokensState.value}
         />
-        <NumberInput {...unitPriceState} isRequired />
+        <div className="flex flex-row items-center">
+          <NumberInput {...unitPriceState} isRequired />
+          <select
+            className="py-[9px] px-4 mt-14 ml-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))}
+          >
+            {vendingMinterList
+              .filter((minter) => minter.factoryAddress !== undefined && minter.updatable === false)
+              .map((minter) => (
+                <option key={minter.id} className="bg-black" value={minter.supportedToken.displayName}>
+                  {minter.supportedToken.displayName}
+                </option>
+              ))}
+          </select>
+        </div>
+
         <NumberInput {...perAddressLimitState} isRequired />
         <FormControl htmlId="timestamp" isRequired subtitle="Minting start time (local)" title="Start Time">
           <InputDateTime minDate={new Date()} onChange={(date) => setTimestamp(date)} value={timestamp} />

From 180eb914b3025a904d521bd9ef73a9cae3109b5b Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Wed, 2 Aug 2023 22:56:41 +0300
Subject: [PATCH 16/51] Fetch vending factory parameters wrt selected mint
 denom

---
 pages/collections/create.tsx | 33 +++++++++++++++++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 42573f7..d03115e 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -33,7 +33,7 @@ import { Conditional } from 'components/Conditional'
 import { LoadingModal } from 'components/LoadingModal'
 import type { OpenEditionMinterCreatorDataProps } from 'components/openEdition/OpenEditionMinterCreator'
 import { OpenEditionMinterCreator } from 'components/openEdition/OpenEditionMinterCreator'
-import { openEditionMinterList } from 'config/minter'
+import { flexibleVendingMinterList, openEditionMinterList, vendingMinterList } from 'config/minter'
 import type { TokenInfo } from 'config/token'
 import { useContracts } from 'contexts/contracts'
 import { addLogItem } from 'contexts/log'
@@ -129,6 +129,7 @@ const CollectionCreationPage: NextPage = () => {
   const [minimumFlexMintPrice, setMinimumFlexMintPrice] = useState<string | null>('0')
 
   const [mintTokenFromOpenEditionFactory, setMintTokenFromOpenEditionFactory] = useState<TokenInfo | undefined>(stars)
+  const [mintTokenFromVendingFactory, setMintTokenFromVendingFactory] = useState<TokenInfo | undefined>(stars)
 
   const [uploading, setUploading] = useState(false)
   const [isMintingComplete, setIsMintingComplete] = useState(false)
@@ -540,7 +541,7 @@ 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,
@@ -1185,6 +1186,34 @@ const CollectionCreationPage: NextPage = () => {
     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) {
+      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() })
+        })
+      setVendingMinterCreationFee(vendingFactoryParameters?.params?.creation_fee?.amount)
+      if (!collectionDetails?.updatable) {
+        setMinimumMintPrice(vendingFactoryParameters?.params?.min_mint_price?.amount)
+        setMintTokenFromVendingFactory(
+          tokensList.find((token) => token.denom === vendingFactoryParameters?.params?.min_mint_price?.denom),
+        )
+      }
+    }
+  }, [collectionDetails?.updatable, mintingDetails?.selectedMintToken, tokensList, whitelistDetails?.whitelistType])
+
   const checkwalletBalance = async () => {
     const walletBalance = await wallet.client?.getBalance(wallet.address, 'ustars').then((balance) => {
       if (minterType === 'vending' && whitelistDetails?.whitelistState === 'new' && whitelistDetails.memberLimit) {

From 15427072e4acfa7e83716aa06c431637540b08bf Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 6 Aug 2023 16:53:02 +0300
Subject: [PATCH 17/51] Add flexible factories to the minter list

---
 .env.example       |  4 +++
 config/minter.ts   | 70 ++++++++++++++++++++++++++++++++++++++++++++++
 env.d.ts           |  9 ++++--
 utils/constants.ts |  7 +++++
 4 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/.env.example b/.env.example
index 538335d..45ed4b3 100644
--- a/.env.example
+++ b/.env.example
@@ -15,6 +15,10 @@ NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q
 NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
 NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
 NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_FLEX_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_FLEX_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
 NEXT_PUBLIC_BASE_FACTORY_ADDRESS="stars1a45hcxty3spnmm2f0papl8v4dk5ew29s4syhn4efte8u5haex99qlkrtnx"
 NEXT_PUBLIC_BASE_FACTORY_UPDATABLE_ADDRESS="stars100xegx2syry4tclkmejjwxk4nfqahvcqhm9qxut5wxuzhj5d9qfsh5nmym"
 NEXT_PUBLIC_OPEN_EDITION_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
diff --git a/config/minter.ts b/config/minter.ts
index b7d359f..02ebc5b 100644
--- a/config/minter.ts
+++ b/config/minter.ts
@@ -8,11 +8,17 @@ import {
   OPEN_EDITION_UPDATABLE_IBC_FRENZ_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'
@@ -23,6 +29,7 @@ export interface MinterInfo {
   factoryAddress: string
   supportedToken: TokenInfo
   updatable?: boolean
+  flexible?: boolean
 }
 
 export const openEditionStarsMinter: MinterInfo = {
@@ -97,6 +104,7 @@ export const vendingStarsMinter: MinterInfo = {
   factoryAddress: VENDING_FACTORY_ADDRESS,
   supportedToken: stars,
   updatable: false,
+  flexible: false,
 }
 
 export const vendingUpdatableStarsMinter: MinterInfo = {
@@ -104,6 +112,7 @@ export const vendingUpdatableStarsMinter: MinterInfo = {
   factoryAddress: VENDING_FACTORY_UPDATABLE_ADDRESS,
   supportedToken: stars,
   updatable: true,
+  flexible: false,
 }
 
 export const vendingIbcAtomMinter: MinterInfo = {
@@ -111,6 +120,7 @@ export const vendingIbcAtomMinter: MinterInfo = {
   factoryAddress: VENDING_IBC_ATOM_FACTORY_ADDRESS,
   supportedToken: ibcAtom,
   updatable: false,
+  flexible: false,
 }
 
 export const vendingUpdatableIbcAtomMinter: MinterInfo = {
@@ -118,6 +128,7 @@ export const vendingUpdatableIbcAtomMinter: MinterInfo = {
   factoryAddress: VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS,
   supportedToken: ibcAtom,
   updatable: true,
+  flexible: false,
 }
 
 export const vendingIbcUsdcMinter: MinterInfo = {
@@ -125,6 +136,7 @@ export const vendingIbcUsdcMinter: MinterInfo = {
   factoryAddress: VENDING_IBC_USDC_FACTORY_ADDRESS,
   supportedToken: ibcUsdc,
   updatable: false,
+  flexible: false,
 }
 
 export const vendingUpdatableIbcUsdcMinter: MinterInfo = {
@@ -132,6 +144,7 @@ export const vendingUpdatableIbcUsdcMinter: MinterInfo = {
   factoryAddress: VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS,
   supportedToken: ibcUsdc,
   updatable: true,
+  flexible: false,
 }
 
 export const vendingMinterList = [
@@ -142,3 +155,60 @@ export const vendingMinterList = [
   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/env.d.ts b/env.d.ts
index 1325002..d41c8e5 100644
--- a/env.d.ts
+++ b/env.d.ts
@@ -23,10 +23,17 @@ 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_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
@@ -36,8 +43,6 @@ declare namespace NodeJS {
     readonly NEXT_PUBLIC_OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS: string
     readonly NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_FRENZ_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_BASE_FACTORY_ADDRESS: string
     readonly NEXT_PUBLIC_BASE_FACTORY_UPDATABLE_ADDRESS: string
     readonly NEXT_PUBLIC_SG721_NAME_ADDRESS: string
diff --git a/utils/constants.ts b/utils/constants.ts
index 01b8a8a..8b919ed 100644
--- a/utils/constants.ts
+++ b/utils/constants.ts
@@ -12,12 +12,19 @@ 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

From ade9410a91764ec618c85d5ba934bdf1abdef3ab Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 6 Aug 2023 17:24:51 +0300
Subject: [PATCH 18/51] Fetch and display factory denom for minimum mint price

---
 components/collections/creation/MintingDetails.tsx | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/components/collections/creation/MintingDetails.tsx b/components/collections/creation/MintingDetails.tsx
index e6555f1..22f802f 100644
--- a/components/collections/creation/MintingDetails.tsx
+++ b/components/collections/creation/MintingDetails.tsx
@@ -19,6 +19,7 @@ interface MintingDetailsProps {
   numberOfTokens: number | undefined
   uploadMethod: UploadMethod
   minimumMintPrice: number
+  mintingTokenFromFactory?: TokenInfo
 }
 
 export interface MintingDetailsDataProps {
@@ -30,7 +31,13 @@ export interface MintingDetailsDataProps {
   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<Date | undefined>()
@@ -48,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',
   })
 

From 8aaff3823877825f18ffc1c99e021abf5597e4ca Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 6 Aug 2023 18:44:22 +0300
Subject: [PATCH 19/51] Instantiate vending minter wrt selected denom

---
 contracts/vendingFactory/contract.ts | 14 +----
 pages/collections/create.tsx         | 90 ++++++++++++++++++----------
 2 files changed, 60 insertions(+), 44 deletions(-)

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<CreateVendingMinterResponse> => {
-      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/pages/collections/create.tsx b/pages/collections/create.tsx
index d03115e..c29bd28 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -90,16 +90,6 @@ const CollectionCreationPage: NextPage = () => {
   const scrollRef = useRef<HTMLDivElement>(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 [collectionDetails, setCollectionDetails] = useState<CollectionDetailsDataProps | null>(null)
   const [baseMinterDetails, setBaseMinterDetails] = useState<BaseMinterDetailsDataProps | null>(null)
@@ -130,6 +120,17 @@ const CollectionCreationPage: NextPage = () => {
 
   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 [isMintingComplete, setIsMintingComplete] = useState(false)
@@ -547,11 +548,7 @@ const CollectionCreationPage: NextPage = () => {
           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_CODE_ID : SG721_UPDATABLE_CODE_ID,
           name: collectionDetails?.name,
           symbol: collectionDetails?.symbol,
           info: {
@@ -572,12 +569,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,
@@ -912,14 +904,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 ||
@@ -1128,7 +1130,7 @@ 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)
     }
   }
 
@@ -1187,8 +1189,10 @@ const CollectionCreationPage: NextPage = () => {
   ])
 
   const fetchVendingFactoryParameters = useCallback(async () => {
+    console.log('Here')
     const client = wallet.client
     if (!client) return
+    console.log('Selected Token: ', mintingDetails?.selectedMintToken)
     const vendingFactoryForSelectedDenom = vendingMinterList
       .concat(flexibleVendingMinterList)
       .find(
@@ -1197,22 +1201,38 @@ const CollectionCreationPage: NextPage = () => {
           minter.updatable === collectionDetails?.updatable &&
           minter.flexible === (whitelistDetails?.whitelistType === 'flex'),
       )?.factoryAddress
+    console.log(vendingFactoryForSelectedDenom)
     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() })
         })
-      setVendingMinterCreationFee(vendingFactoryParameters?.params?.creation_fee?.amount)
-      if (!collectionDetails?.updatable) {
+
+      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),
-        )
       }
+
+      setMintTokenFromVendingFactory(
+        tokensList.find((token) => token.denom === vendingFactoryParameters?.params?.min_mint_price?.denom),
+      )
     }
-  }, [collectionDetails?.updatable, mintingDetails?.selectedMintToken, tokensList, whitelistDetails?.whitelistType])
+  }, [
+    collectionDetails?.updatable,
+    mintingDetails?.selectedMintToken,
+    wallet.client,
+    whitelistDetails?.whitelistState,
+    whitelistDetails?.whitelistType,
+  ])
 
   const checkwalletBalance = async () => {
     const walletBalance = await wallet.client?.getBalance(wallet.address, 'ustars').then((balance) => {
@@ -1309,6 +1329,10 @@ const CollectionCreationPage: NextPage = () => {
     void fetchOpenEditionFactoryParameters()
   }, [fetchOpenEditionFactoryParameters])
 
+  useEffect(() => {
+    void fetchVendingFactoryParameters()
+  }, [fetchVendingFactoryParameters])
+
   return (
     <div>
       <NextSeo
@@ -1699,7 +1723,9 @@ const CollectionCreationPage: NextPage = () => {
             <Conditional test={minterType === 'vending'}>
               <MintingDetails
                 minimumMintPrice={
-                  collectionDetails?.updatable
+                  whitelistDetails?.whitelistState !== 'none' && whitelistDetails?.whitelistType === 'flex'
+                    ? Number(minimumFlexMintPrice) / 1000000
+                    : collectionDetails?.updatable
                     ? Number(minimumUpdatableMintPrice) / 1000000
                     : Number(minimumMintPrice) / 1000000
                 }

From c77e583d53655328f1bfecc89485314bcda3f914 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 6 Aug 2023 21:09:43 +0300
Subject: [PATCH 20/51] Update whitelist mint price denom wrt selected denom

---
 .../collections/creation/MintingDetails.tsx       |  2 +-
 .../collections/creation/WhitelistDetails.tsx     |  8 ++++++--
 pages/collections/create.tsx                      | 15 +++++++++++----
 3 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/components/collections/creation/MintingDetails.tsx b/components/collections/creation/MintingDetails.tsx
index 22f802f..8246327 100644
--- a/components/collections/creation/MintingDetails.tsx
+++ b/components/collections/creation/MintingDetails.tsx
@@ -125,7 +125,7 @@ export const MintingDetails = ({
         <div className="flex flex-row items-center">
           <NumberInput {...unitPriceState} isRequired />
           <select
-            className="py-[9px] px-4 mt-14 ml-4 placeholder:text-white/50 bg-white/10 rounded border-2 border-white/20 focus:ring focus:ring-plumbus-20"
+            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
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<WhitelistState>('none')
   const [whitelistType, setWhitelistType] = useState<WhitelistType>('standard')
   const [startDate, setStartDate] = useState<Date | undefined>(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/pages/collections/create.tsx b/pages/collections/create.tsx
index c29bd28..f23d75d 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -494,7 +494,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],
@@ -505,7 +508,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,
@@ -1221,7 +1227,7 @@ const CollectionCreationPage: NextPage = () => {
         setVendingMinterCreationFee(vendingFactoryParameters?.params?.creation_fee?.amount)
         setMinimumMintPrice(vendingFactoryParameters?.params?.min_mint_price?.amount)
       }
-
+      console.log('Vending Factory Parameters: ', vendingFactoryParameters)
       setMintTokenFromVendingFactory(
         tokensList.find((token) => token.denom === vendingFactoryParameters?.params?.min_mint_price?.denom),
       )
@@ -1729,6 +1735,7 @@ const CollectionCreationPage: NextPage = () => {
                     ? Number(minimumUpdatableMintPrice) / 1000000
                     : Number(minimumMintPrice) / 1000000
                 }
+                mintingTokenFromFactory={mintTokenFromVendingFactory}
                 numberOfTokens={uploadDetails?.assetFiles.length}
                 onChange={setMintingDetails}
                 uploadMethod={uploadDetails?.uploadMethod as UploadMethod}
@@ -1757,7 +1764,7 @@ const CollectionCreationPage: NextPage = () => {
         >
           <div className="my-6">
             <Conditional test={minterType === 'vending'}>
-              <WhitelistDetails onChange={setWhitelistDetails} />
+              <WhitelistDetails mintingTokenFromFactory={mintTokenFromVendingFactory} onChange={setWhitelistDetails} />
               <div className="my-6" />
             </Conditional>
             <RoyaltyDetails onChange={setRoyaltyDetails} />

From a985e97c2eb5e32d8c36a6aabe1c9c7f2946b5fe Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 6 Aug 2023 21:27:58 +0300
Subject: [PATCH 21/51] Use factoryParameters/mint_price/denom for open edition
 airdrops

---
 contracts/openEditionMinter/contract.ts | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

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)] : [],
             }),
           }
 

From fe1cfe884c3ece1ab32b35c8e007c6f8c3363266 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 6 Aug 2023 21:57:03 +0300
Subject: [PATCH 22/51] Fix updatable code id mix up

---
 pages/collections/create.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index f23d75d..9adca27 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -554,7 +554,7 @@ const CollectionCreationPage: NextPage = () => {
           whitelist,
         },
         collection_params: {
-          code_id: collectionDetails?.updatable ? SG721_CODE_ID : SG721_UPDATABLE_CODE_ID,
+          code_id: collectionDetails?.updatable ? SG721_UPDATABLE_CODE_ID : SG721_CODE_ID,
           name: collectionDetails?.name,
           symbol: collectionDetails?.symbol,
           info: {

From 6d0b21ec594a805086dc54f632f29c78ca3deb47 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 7 Aug 2023 12:59:23 +0300
Subject: [PATCH 23/51] Update IBC denoms

---
 config/minter.ts   | 26 +++++++++++++-------------
 config/token.ts    | 14 +++++++-------
 env.d.ts           |  4 ++--
 utils/constants.ts |  6 +++---
 4 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/config/minter.ts b/config/minter.ts
index 02ebc5b..528f60b 100644
--- a/config/minter.ts
+++ b/config/minter.ts
@@ -1,11 +1,11 @@
 import {
   OPEN_EDITION_FACTORY_ADDRESS,
   OPEN_EDITION_IBC_ATOM_FACTORY_ADDRESS,
-  OPEN_EDITION_IBC_FRENZ_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_FRENZ_FACTORY_ADDRESS,
+  OPEN_EDITION_UPDATABLE_IBC_FRNZ_FACTORY_ADDRESS,
   OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS,
   VENDING_FACTORY_ADDRESS,
   VENDING_FACTORY_FLEX_ADDRESS,
@@ -22,7 +22,7 @@ import {
 } from 'utils/constants'
 
 import type { TokenInfo } from './token'
-import { ibcAtom, ibcFrenz, ibcUsdc, stars } from './token'
+import { ibcAtom, ibcFrnz, ibcUsdc, stars } from './token'
 
 export interface MinterInfo {
   id: string
@@ -74,17 +74,17 @@ export const openEditionUpdatableIbcUsdcMinter: MinterInfo = {
   updatable: true,
 }
 
-export const openEditionIbcFrenzMinter: MinterInfo = {
-  id: 'open-edition-ibc-frenz-minter',
-  factoryAddress: OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS,
-  supportedToken: ibcFrenz,
+export const openEditionIbcFrnzMinter: MinterInfo = {
+  id: 'open-edition-ibc-frnz-minter',
+  factoryAddress: OPEN_EDITION_IBC_FRNZ_FACTORY_ADDRESS,
+  supportedToken: ibcFrnz,
   updatable: false,
 }
 
-export const openEditionUpdatableIbcFrenzMinter: MinterInfo = {
-  id: 'open-edition-updatable-ibc-frenz-minter',
-  factoryAddress: OPEN_EDITION_UPDATABLE_IBC_FRENZ_FACTORY_ADDRESS,
-  supportedToken: ibcFrenz,
+export const openEditionUpdatableIbcFrnzMinter: MinterInfo = {
+  id: 'open-edition-updatable-ibc-frnz-minter',
+  factoryAddress: OPEN_EDITION_UPDATABLE_IBC_FRNZ_FACTORY_ADDRESS,
+  supportedToken: ibcFrnz,
   updatable: true,
 }
 
@@ -93,8 +93,8 @@ export const openEditionMinterList = [
   openEditionUpdatableStarsMinter,
   openEditionUpdatableIbcAtomMinter,
   openEditionIbcAtomMinter,
-  openEditionIbcFrenzMinter,
-  openEditionUpdatableIbcFrenzMinter,
+  openEditionIbcFrnzMinter,
+  openEditionUpdatableIbcFrnzMinter,
   openEditionIbcUsdcMinter,
   openEditionUpdatableIbcUsdcMinter,
 ]
diff --git a/config/token.ts b/config/token.ts
index 3119c6d..af49d99 100644
--- a/config/token.ts
+++ b/config/token.ts
@@ -16,23 +16,23 @@ export const stars: TokenInfo = {
 
 export const ibcAtom: TokenInfo = {
   id: 'ibc-atom',
-  denom: 'ibc/atom',
+  denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2',
   displayName: 'ATOM',
   decimalPlaces: 6,
 }
 
 export const ibcUsdc: TokenInfo = {
   id: 'ibc-usdc',
-  denom: 'ibc/usdc',
+  denom: 'ibc/D189335C6E4A68B513C10AB227BF1C1D38C746766278BA3EEB4FB14124F1D858',
   displayName: 'USDC',
   decimalPlaces: 6,
 }
 
-export const ibcFrenz: TokenInfo = {
-  id: 'ibc-frenz',
-  denom: 'ibc/frenz',
-  displayName: 'FRENZ',
+export const ibcFrnz: TokenInfo = {
+  id: 'ibc-frnz',
+  denom: 'ibc/7FA7EC64490E3BDE5A1A28CBE73CC0AD22522794957BC891C46321E3A6074DB9',
+  displayName: 'FRNZ',
   decimalPlaces: 6,
 }
 
-export const tokensList = [stars, ibcAtom, ibcUsdc, ibcFrenz]
+export const tokensList = [stars, ibcAtom, ibcUsdc, ibcFrnz]
diff --git a/env.d.ts b/env.d.ts
index d41c8e5..3d4984a 100644
--- a/env.d.ts
+++ b/env.d.ts
@@ -40,8 +40,8 @@ declare namespace NodeJS {
     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_FRENZ_FACTORY_ADDRESS: string
-    readonly NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_FRENZ_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
diff --git a/utils/constants.ts b/utils/constants.ts
index 8b919ed..4911df1 100644
--- a/utils/constants.ts
+++ b/utils/constants.ts
@@ -35,9 +35,9 @@ export const 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_FRENZ_FACTORY_ADDRESS = process.env.NEXT_PUBLIC_OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS
-export const OPEN_EDITION_UPDATABLE_IBC_FRENZ_FACTORY_ADDRESS =
-  process.env.NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_FRENZ_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)

From 7207e26520422f17473ba6c1cde22b18ac4699a8 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 7 Aug 2023 13:53:17 +0300
Subject: [PATCH 24/51] Update .env.example

---
 .env.example | 39 +++++++++++++++++++++++----------------
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/.env.example b/.env.example
index 45ed4b3..12863f6 100644
--- a/.env.example
+++ b/.env.example
@@ -8,28 +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_IBC_ATOM_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-NEXT_PUBLIC_VENDING_IBC_ATOM_FACTORY_FLEX_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-NEXT_PUBLIC_VENDING_IBC_ATOM_UPDATABLE_FACTORY_FLEX_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-NEXT_PUBLIC_VENDING_IBC_USDC_FACTORY_FLEX_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-NEXT_PUBLIC_VENDING_IBC_USDC_UPDATABLE_FACTORY_FLEX_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
+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_IBC_ATOM_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_ATOM_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-NEXT_PUBLIC_OPEN_EDITION_IBC_USDC_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_USDC_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-NEXT_PUBLIC_OPEN_EDITION_IBC_FRENZ_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_FRENZ_FACTORY_ADDRESS="stars1sqweqcxlf2f7qhf27gn5naqusk5q52fkzewmy63c4sglvle3s7ls6k828e"
-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=
+# NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_FRNZ_FACTORY_ADDRESS=
 
 NEXT_PUBLIC_SG721_NAME_ADDRESS="stars1fx74nkqkw2748av8j7ew7r3xt9cgjqduwn8m0ur5lhe49uhlsasszc5fhr"
 NEXT_PUBLIC_WHITELIST_CODE_ID=2602
@@ -47,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://..."

From 784446a676e4b317fbab3214068678a809c4d15e Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 7 Aug 2023 13:55:31 +0300
Subject: [PATCH 25/51] Bump Studio version

---
 .env.example | 2 +-
 package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.env.example b/.env.example
index 12863f6..e460d2a 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
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/*"
   ],

From 85efecd40c3b61b7736934f9e4820a04ea29ca27 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 7 Aug 2023 14:01:46 +0300
Subject: [PATCH 26/51] Clean up

---
 pages/collections/create.tsx | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 9adca27..7642a42 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -675,8 +675,6 @@ const CollectionCreationPage: NextPage = () => {
               setCreatingCollection(false)
             })
         } else {
-          console.log('Here')
-          console.log(data.baseMinterAddress)
           await toast
             .promise(
               baseMinterContract
@@ -1160,7 +1158,6 @@ const CollectionCreationPage: NextPage = () => {
           toast.error(`${error.message}`, { style: { maxWidth: 'none' } })
           addLogItem({ id: uid(), message: error.message, type: 'Error', timestamp: new Date() })
         })
-      console.log('Open Edition Factory Parameters: ', openEditionFactoryParameters)
       setOpenEditionMinterCreationFee(openEditionFactoryParameters?.params?.creation_fee?.amount)
       if (!openEditionMinterDetails?.collectionDetails?.updatable) {
         setMinimumOpenEditionMintPrice(openEditionFactoryParameters?.params?.min_mint_price?.amount)
@@ -1168,8 +1165,6 @@ const CollectionCreationPage: NextPage = () => {
           tokensList.find((token) => token.denom === openEditionFactoryParameters?.params?.min_mint_price?.denom),
         )
       }
-      console.log('Selected OE Factory: ', factoryForSelectedDenom)
-      console.log('Selected Updatable OE Factory: ', updatableFactoryForSelectedDenom)
     }
     if (updatableFactoryForSelectedDenom?.factoryAddress) {
       const openEditionUpdatableFactoryParameters = await client
@@ -1195,10 +1190,8 @@ const CollectionCreationPage: NextPage = () => {
   ])
 
   const fetchVendingFactoryParameters = useCallback(async () => {
-    console.log('Here')
     const client = wallet.client
     if (!client) return
-    console.log('Selected Token: ', mintingDetails?.selectedMintToken)
     const vendingFactoryForSelectedDenom = vendingMinterList
       .concat(flexibleVendingMinterList)
       .find(
@@ -1207,7 +1200,6 @@ const CollectionCreationPage: NextPage = () => {
           minter.updatable === collectionDetails?.updatable &&
           minter.flexible === (whitelistDetails?.whitelistType === 'flex'),
       )?.factoryAddress
-    console.log(vendingFactoryForSelectedDenom)
     if (vendingFactoryForSelectedDenom) {
       setVendingFactoryAddress(vendingFactoryForSelectedDenom)
       const vendingFactoryParameters = await client
@@ -1227,7 +1219,6 @@ const CollectionCreationPage: NextPage = () => {
         setVendingMinterCreationFee(vendingFactoryParameters?.params?.creation_fee?.amount)
         setMinimumMintPrice(vendingFactoryParameters?.params?.min_mint_price?.amount)
       }
-      console.log('Vending Factory Parameters: ', vendingFactoryParameters)
       setMintTokenFromVendingFactory(
         tokensList.find((token) => token.denom === vendingFactoryParameters?.params?.min_mint_price?.denom),
       )

From 51843cade00b33f09585c1c8609e84569c92bf08 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Thu, 10 Aug 2023 22:38:03 +0300
Subject: [PATCH 27/51] Surface open edition collection summary details

---
 components/openEdition/OpenEditionMinterCreator.tsx | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/components/openEdition/OpenEditionMinterCreator.tsx b/components/openEdition/OpenEditionMinterCreator.tsx
index 6b845b9..90c7c21 100644
--- a/components/openEdition/OpenEditionMinterCreator.tsx
+++ b/components/openEdition/OpenEditionMinterCreator.tsx
@@ -57,6 +57,9 @@ export interface OpenEditionMinterDetailsDataProps {
   offChainMetadataUploadDetails?: OffChainMetadataUploadDetailsDataProps
   mintingDetails?: MintingDetailsDataProps
   metadataStorageMethod?: MetadataStorageMethod
+  openEditionMinterContractAddress?: string | null
+  coverImageUrl?: string | null
+  tokenUri?: string | null
 }
 
 interface OpenEditionMinterCreatorProps {
@@ -627,6 +630,9 @@ export const OpenEditionMinterCreator = ({
       offChainMetadataUploadDetails: offChainMetadataUploadDetails ? offChainMetadataUploadDetails : undefined,
       mintingDetails: mintingDetails ? mintingDetails : undefined,
       metadataStorageMethod,
+      openEditionMinterContractAddress,
+      coverImageUrl,
+      tokenUri,
     }
     onDetailsChange(data)
     // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -637,6 +643,10 @@ export const OpenEditionMinterCreator = ({
     onChainMetadataInputDetails,
     offChainMetadataUploadDetails,
     mintingDetails,
+    metadataStorageMethod,
+    openEditionMinterContractAddress,
+    coverImageUrl,
+    tokenUri,
   ])
 
   useEffect(() => {

From f324cb6f50626ef8e6615783fda2b3eda16207aa Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sat, 12 Aug 2023 22:47:53 +0300
Subject: [PATCH 28/51] Add token image URI to open edition minter details

---
 components/openEdition/OpenEditionMinterCreator.tsx | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/components/openEdition/OpenEditionMinterCreator.tsx b/components/openEdition/OpenEditionMinterCreator.tsx
index 90c7c21..d21cf60 100644
--- a/components/openEdition/OpenEditionMinterCreator.tsx
+++ b/components/openEdition/OpenEditionMinterCreator.tsx
@@ -60,6 +60,7 @@ export interface OpenEditionMinterDetailsDataProps {
   openEditionMinterContractAddress?: string | null
   coverImageUrl?: string | null
   tokenUri?: string | null
+  tokenImageUri?: string | null
 }
 
 interface OpenEditionMinterCreatorProps {
@@ -633,6 +634,7 @@ export const OpenEditionMinterCreator = ({
       openEditionMinterContractAddress,
       coverImageUrl,
       tokenUri,
+      tokenImageUri,
     }
     onDetailsChange(data)
     // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -647,6 +649,7 @@ export const OpenEditionMinterCreator = ({
     openEditionMinterContractAddress,
     coverImageUrl,
     tokenUri,
+    tokenImageUri,
   ])
 
   useEffect(() => {

From 6fc4022c8d3be90155045663a2ad3343664d65e3 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Tue, 15 Aug 2023 18:24:27 +0300
Subject: [PATCH 29/51] Update export logic for standard collection summary

---
 pages/collections/create.tsx | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 9ad3c76..4bf62e5 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -1280,7 +1280,6 @@ const CollectionCreationPage: NextPage = () => {
     })
   }
 
-  // function to export all details as a .json file
   const exportDetails = () => {
     const details = {
       minterType,
@@ -1291,6 +1290,12 @@ const CollectionCreationPage: NextPage = () => {
       royaltyDetails,
       baseMinterDetails,
       openEditionMinterDetails,
+      vendingMinterContractAddress,
+      baseTokenUri: `ipfs://${baseTokenUri}`,
+      coverImageUrl:
+        uploadDetails?.uploadMethod === 'new'
+          ? `ipfs://${coverImageUrl}/${collectionDetails?.imageFile[0].name as string}`
+          : `${coverImageUrl}`,
     }
     const element = document.createElement('a')
     const file = new Blob([JSON.stringify(details)], { type: 'text/plain' })
@@ -1299,7 +1304,6 @@ const CollectionCreationPage: NextPage = () => {
     document.body.appendChild(element) // Required for this to work in FireFox
     element.click()
   }
-  // function to import all details from a .json file
   const importDetails = (event: ChangeEvent<HTMLInputElement>) => {
     if (event.target.files === null) return toast.error('No files selected.')
     const file = event.target.files[0]
@@ -1308,6 +1312,11 @@ const CollectionCreationPage: NextPage = () => {
       const contents = e.target?.result
       const details = JSON.parse(contents as string)
       setMinterType(details.minterType)
+      if (details.vendingMinterContractAddress) {
+        details.uploadDetails.uploadMethod = 'existing'
+        details.uploadDetails.baseTokenURI = details.baseTokenUri
+        details.uploadDetails.imageUrl = details.coverImageUrl
+      }
       setImportedDetails(details)
     }
     reader.readAsText(file)

From 702e47e9e6500d61d3ec8415db05642bcf199aff Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Tue, 15 Aug 2023 20:06:53 +0300
Subject: [PATCH 30/51] Update FRNZ denom for testnet

---
 config/token.ts | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/config/token.ts b/config/token.ts
index af49d99..7cb99b6 100644
--- a/config/token.ts
+++ b/config/token.ts
@@ -1,3 +1,5 @@
+import { NETWORK } from 'utils/constants'
+
 export interface TokenInfo {
   id: string
   denom: string
@@ -30,7 +32,10 @@ export const ibcUsdc: TokenInfo = {
 
 export const ibcFrnz: TokenInfo = {
   id: 'ibc-frnz',
-  denom: 'ibc/7FA7EC64490E3BDE5A1A28CBE73CC0AD22522794957BC891C46321E3A6074DB9',
+  denom:
+    NETWORK === 'mainnet'
+      ? 'ibc/7FA7EC64490E3BDE5A1A28CBE73CC0AD22522794957BC891C46321E3A6074DB9'
+      : 'factory/stars10w5eulj60qp3cfqa0hkmke78qdy2feq6x9xdmd/ufrnz',
   displayName: 'FRNZ',
   decimalPlaces: 6,
 }

From 3c392381b246974733ca6a07eed1ad3d098cf70b Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Tue, 15 Aug 2023 20:07:51 +0300
Subject: [PATCH 31/51] Address invalid creation fee problem following minting
 denom change

---
 pages/collections/create.tsx | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 7642a42..70868ff 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -134,6 +134,7 @@ const CollectionCreationPage: NextPage = () => {
 
   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)
@@ -1115,7 +1116,6 @@ const CollectionCreationPage: NextPage = () => {
       setVendingMinterFlexCreationFee(vendingFactoryFlexParameters?.params?.creation_fee?.amount)
       setMinimumFlexMintPrice(vendingFactoryFlexParameters?.params?.min_mint_price?.amount)
     }
-
     if (OPEN_EDITION_FACTORY_ADDRESS) {
       const openEditionFactoryParameters = await client
         .queryContractSmart(OPEN_EDITION_FACTORY_ADDRESS, { params: {} })
@@ -1136,6 +1136,7 @@ const CollectionCreationPage: NextPage = () => {
       setOpenEditionMinterUpdatableCreationFee(openEditionUpdatableFactoryParameters?.params?.creation_fee?.amount)
       setMinimumOpenEditionUpdatableMintPrice(openEditionUpdatableFactoryParameters?.params?.min_mint_price?.amount)
     }
+    setInitialParametersFetched(true)
   }
 
   const fetchOpenEditionFactoryParameters = useCallback(async () => {
@@ -1175,7 +1176,7 @@ const CollectionCreationPage: NextPage = () => {
         })
       setOpenEditionMinterUpdatableCreationFee(openEditionUpdatableFactoryParameters?.params?.creation_fee?.amount)
       if (openEditionMinterDetails?.collectionDetails?.updatable) {
-        setMinimumOpenEditionMintPrice(openEditionUpdatableFactoryParameters?.params?.min_mint_price?.amount)
+        setMinimumOpenEditionUpdatableMintPrice(openEditionUpdatableFactoryParameters?.params?.min_mint_price?.amount)
         setMintTokenFromOpenEditionFactory(
           tokensList.find(
             (token) => token.denom === openEditionUpdatableFactoryParameters?.params?.min_mint_price?.denom,
@@ -1319,7 +1320,9 @@ const CollectionCreationPage: NextPage = () => {
   }, [minterType, baseMinterDetails?.baseMinterAcquisitionMethod, uploadDetails?.uploadMethod])
 
   useEffect(() => {
-    void fetchInitialFactoryParameters()
+    if (!initialParametersFetched) {
+      void fetchInitialFactoryParameters()
+    }
   }, [wallet.client])
 
   useEffect(() => {

From ea5caff1aa2ef599a8d0bdbcde9aae81efc06e83 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Tue, 15 Aug 2023 20:09:35 +0300
Subject: [PATCH 32/51] Update .env.example

---
 .env.example | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.env.example b/.env.example
index e460d2a..ffe2835 100644
--- a/.env.example
+++ b/.env.example
@@ -35,8 +35,8 @@ NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_FACTORY_ADDRESS="stars1fk5dkzcylam8mcpqrn8y9s
 # 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=
-# NEXT_PUBLIC_OPEN_EDITION_UPDATABLE_IBC_FRNZ_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

From 27e1727fa84b65a987881fc1ca2acd236a46f99e Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Wed, 16 Aug 2023 17:48:33 +0300
Subject: [PATCH 33/51] Update export logic for open edition collection summary

---
 components/openEdition/CollectionDetails.tsx          |  2 +-
 .../openEdition/OffChainMetadataUploadDetails.tsx     |  8 +++++---
 pages/collections/create.tsx                          | 11 ++++++++++-
 3 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/components/openEdition/CollectionDetails.tsx b/components/openEdition/CollectionDetails.tsx
index 4c46fff..0118cea 100644
--- a/components/openEdition/CollectionDetails.tsx
+++ b/components/openEdition/CollectionDetails.tsx
@@ -159,7 +159,7 @@ export const CollectionDetails = ({
       nameState.onChange(importedCollectionDetails.name)
       descriptionState.onChange(importedCollectionDetails.description)
       symbolState.onChange(importedCollectionDetails.symbol)
-      setCoverImage(importedCollectionDetails.imageFile[0] || null)
+      //setCoverImage(importedCollectionDetails.imageFile[0] || null)
       externalLinkState.onChange(importedCollectionDetails.externalLink || '')
       setTimestamp(
         importedCollectionDetails.startTradingTime
diff --git a/components/openEdition/OffChainMetadataUploadDetails.tsx b/components/openEdition/OffChainMetadataUploadDetails.tsx
index 02e8703..4328495 100644
--- a/components/openEdition/OffChainMetadataUploadDetails.tsx
+++ b/components/openEdition/OffChainMetadataUploadDetails.tsx
@@ -231,8 +231,10 @@ export const OffChainMetadataUploadDetails = ({
     setMetadataFilesArray([])
     if (assetFilesRef.current) assetFilesRef.current.value = ''
     setAssetFilesArray([])
-    tokenUriState.onChange('')
-    coverImageUrlState.onChange('')
+    if (!importedOffChainMetadataUploadDetails) {
+      tokenUriState.onChange('')
+      coverImageUrlState.onChange('')
+    }
   }, [uploadMethod, metadataStorageMethod])
 
   useEffect(() => {
@@ -241,7 +243,7 @@ export const OffChainMetadataUploadDetails = ({
       nftStorageApiKeyState.onChange(importedOffChainMetadataUploadDetails.nftStorageApiKey || '')
       pinataApiKeyState.onChange(importedOffChainMetadataUploadDetails.pinataApiKey || '')
       pinataSecretKeyState.onChange(importedOffChainMetadataUploadDetails.pinataSecretKey || '')
-      setUploadMethod('existing')
+      setUploadMethod(importedOffChainMetadataUploadDetails.uploadMethod)
       tokenUriState.onChange(importedOffChainMetadataUploadDetails.tokenURI || '')
       coverImageUrlState.onChange(importedOffChainMetadataUploadDetails.imageUrl || '')
       setOpenEditionMinterMetadataFile(importedOffChainMetadataUploadDetails.openEditionMinterMetadataFile)
diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 4bf62e5..423cd19 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -1294,7 +1294,7 @@ const CollectionCreationPage: NextPage = () => {
       baseTokenUri: `ipfs://${baseTokenUri}`,
       coverImageUrl:
         uploadDetails?.uploadMethod === 'new'
-          ? `ipfs://${coverImageUrl}/${collectionDetails?.imageFile[0].name as string}`
+          ? `ipfs://${coverImageUrl}/${collectionDetails?.imageFile[0]?.name as string}`
           : `${coverImageUrl}`,
     }
     const element = document.createElement('a')
@@ -1317,6 +1317,14 @@ const CollectionCreationPage: NextPage = () => {
         details.uploadDetails.baseTokenURI = details.baseTokenUri
         details.uploadDetails.imageUrl = details.coverImageUrl
       }
+      if (details.openEditionMinterDetails.openEditionMinterContractAddress) {
+        details.openEditionMinterDetails.offChainMetadataUploadDetails.uploadMethod = 'existing'
+        details.openEditionMinterDetails.offChainMetadataUploadDetails.tokenURI =
+          details.openEditionMinterDetails.tokenUri
+        details.openEditionMinterDetails.offChainMetadataUploadDetails.imageUrl =
+          details.openEditionMinterDetails.coverImageUrl
+      }
+
       setImportedDetails(details)
     }
     reader.readAsText(file)
@@ -1740,6 +1748,7 @@ const CollectionCreationPage: NextPage = () => {
       )}
       <Conditional test={minterType === 'openEdition'}>
         <OpenEditionMinterCreator
+          importedOpenEditionMinterDetails={importedDetails?.openEditionMinterDetails}
           minimumMintPrice={minimumOpenEditionMintPrice as string}
           minimumUpdatableMintPrice={minimumOpenEditionUpdatableMintPrice as string}
           mintTokenFromFactory={mintTokenFromOpenEditionFactory}

From 3fbebbe03d264ca825132956d0ace32c3b7fd247 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Wed, 16 Aug 2023 17:57:07 +0300
Subject: [PATCH 34/51] Auto-add wallet address as whitelist admin

---
 components/collections/creation/WhitelistDetails.tsx | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/components/collections/creation/WhitelistDetails.tsx b/components/collections/creation/WhitelistDetails.tsx
index a0de6c9..aa0d908 100644
--- a/components/collections/creation/WhitelistDetails.tsx
+++ b/components/collections/creation/WhitelistDetails.tsx
@@ -9,6 +9,7 @@ import { InputDateTime } from 'components/InputDateTime'
 import type { WhitelistFlexMember } from 'components/WhitelistFlexUpload'
 import { WhitelistFlexUpload } from 'components/WhitelistFlexUpload'
 import type { TokenInfo } from 'config/token'
+import { useWallet } from 'contexts/wallet'
 import React, { useEffect, useState } from 'react'
 import { isValidAddress } from 'utils/isValidAddress'
 
@@ -46,6 +47,8 @@ export const WhitelistDetails = ({
   mintingTokenFromFactory,
   importedWhitelistDetails,
 }: WhitelistDetailsProps) => {
+  const wallet = useWallet()
+
   const [whitelistState, setWhitelistState] = useState<WhitelistState>('none')
   const [whitelistType, setWhitelistType] = useState<WhitelistType>('standard')
   const [startDate, setStartDate] = useState<Date | undefined>(undefined)
@@ -196,6 +199,14 @@ export const WhitelistDetails = ({
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [importedWhitelistDetails])
 
+  useEffect(() => {
+    if (whitelistState === 'new' && wallet.address) {
+      addressListState.reset()
+      addressListState.add({ address: wallet.address })
+    }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [whitelistState, wallet.address])
+
   return (
     <div className="py-3 px-8 rounded border-2 border-white/20">
       <div className="flex justify-center">
@@ -344,7 +355,6 @@ export const WhitelistDetails = ({
             <div className="my-4 ml-4">
               <AddressList
                 entries={addressListState.entries}
-                isRequired
                 onAdd={addressListState.add}
                 onChange={addressListState.update}
                 onRemove={addressListState.remove}

From 71e539a0b4ac5ff057aa9e8ee81369faaeec6a18 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Thu, 17 Aug 2023 14:20:37 +0300
Subject: [PATCH 35/51] Export/Import open edition token metadata

---
 components/MetadataInput.tsx                  | 39 +++++++++++++++++--
 .../OffChainMetadataUploadDetails.tsx         |  8 +++-
 2 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/components/MetadataInput.tsx b/components/MetadataInput.tsx
index 652c480..2340d3f 100644
--- a/components/MetadataInput.tsx
+++ b/components/MetadataInput.tsx
@@ -13,6 +13,8 @@ export interface MetadataInputProps {
   selectedAssetFile: File
   selectedMetadataFile: File
   updateMetadataToUpload: (metadataFile: File) => void
+  onChange?: (metadata: any) => void
+  importedMetadata?: any
 }
 
 export const MetadataInput = (props: MetadataInputProps) => {
@@ -151,8 +153,11 @@ export const MetadataInput = (props: MetadataInputProps) => {
 
   useEffect(() => {
     console.log(props.selectedMetadataFile?.name)
-    if (props.selectedMetadataFile) void parseMetadata(props.selectedMetadataFile)
-    else void parseMetadata(emptyMetadataFile)
+    if (props.selectedMetadataFile) {
+      void parseMetadata(props.selectedMetadataFile)
+    } else if (!props.importedMetadata) {
+      void parseMetadata(emptyMetadataFile)
+    }
   }, [props.selectedMetadataFile?.name])
 
   const nameStateMemo = useMemo(() => nameState, [nameState.value])
@@ -163,7 +168,10 @@ export const MetadataInput = (props: MetadataInputProps) => {
 
   useEffect(() => {
     console.log('Update metadata')
-    if (metadata) generateUpdatedMetadata()
+    if (metadata) {
+      generateUpdatedMetadata()
+      if (props.onChange) props.onChange(metadata)
+    }
     console.log(metadata)
   }, [
     nameStateMemo.value,
@@ -173,6 +181,31 @@ export const MetadataInput = (props: MetadataInputProps) => {
     attributesStateMemo.entries,
   ])
 
+  useEffect(() => {
+    if (props.importedMetadata) {
+      console.log('Imported metadata: ', props.importedMetadata)
+      nameState.onChange(props.importedMetadata.name || '')
+      descriptionState.onChange(props.importedMetadata.description || '')
+      externalUrlState.onChange(props.importedMetadata.external_url || '')
+      youtubeUrlState.onChange(props.importedMetadata.youtube_url || '')
+      if (props.importedMetadata?.attributes && props.importedMetadata?.attributes?.length > 0) {
+        attributesState.reset()
+        props.importedMetadata?.attributes?.forEach((attribute: { trait_type: string; value: string }) => {
+          attributesState.add({
+            trait_type: attribute.trait_type,
+            value: attribute.value,
+          })
+        })
+      } else {
+        attributesState.reset()
+        attributesState.add({
+          trait_type: '',
+          value: '',
+        })
+      }
+    }
+  }, [props.importedMetadata])
+
   return (
     <div>
       <div className="grid grid-cols-2 mt-4 mr-4 ml-8 w-full max-w-6xl max-h-full no-scrollbar">
diff --git a/components/openEdition/OffChainMetadataUploadDetails.tsx b/components/openEdition/OffChainMetadataUploadDetails.tsx
index 4328495..abe06f6 100644
--- a/components/openEdition/OffChainMetadataUploadDetails.tsx
+++ b/components/openEdition/OffChainMetadataUploadDetails.tsx
@@ -42,6 +42,7 @@ export interface OffChainMetadataUploadDetailsDataProps {
   tokenURI?: string
   imageUrl?: string
   openEditionMinterMetadataFile?: File
+  exportedMetadata?: any
 }
 
 export const OffChainMetadataUploadDetails = ({
@@ -55,6 +56,7 @@ export const OffChainMetadataUploadDetails = ({
   const [uploadService, setUploadService] = useState<UploadServiceType>('nft-storage')
   const [metadataFileArrayIndex, setMetadataFileArrayIndex] = useState(0)
   const [refreshMetadata, setRefreshMetadata] = useState(false)
+  const [exportedMetadata, setExportedMetadata] = useState(undefined)
 
   const [openEditionMinterMetadataFile, setOpenEditionMinterMetadataFile] = useState<File | undefined>()
 
@@ -206,6 +208,7 @@ export const OffChainMetadataUploadDetails = ({
           .replace(regex, '')
           .trim(),
         openEditionMinterMetadataFile,
+        exportedMetadata,
       }
       onChange(data)
     } catch (error: any) {
@@ -224,6 +227,7 @@ export const OffChainMetadataUploadDetails = ({
     coverImageUrlState.value,
     refreshMetadata,
     openEditionMinterMetadataFile,
+    exportedMetadata,
   ])
 
   useEffect(() => {
@@ -246,7 +250,7 @@ export const OffChainMetadataUploadDetails = ({
       setUploadMethod(importedOffChainMetadataUploadDetails.uploadMethod)
       tokenUriState.onChange(importedOffChainMetadataUploadDetails.tokenURI || '')
       coverImageUrlState.onChange(importedOffChainMetadataUploadDetails.imageUrl || '')
-      setOpenEditionMinterMetadataFile(importedOffChainMetadataUploadDetails.openEditionMinterMetadataFile)
+      //setOpenEditionMinterMetadataFile(importedOffChainMetadataUploadDetails.openEditionMinterMetadataFile)
     }
   }, [importedOffChainMetadataUploadDetails])
 
@@ -464,6 +468,8 @@ export const OffChainMetadataUploadDetails = ({
                 />
               </div>
               <MetadataInput
+                importedMetadata={importedOffChainMetadataUploadDetails?.exportedMetadata}
+                onChange={setExportedMetadata}
                 selectedAssetFile={assetFilesArray[0]}
                 selectedMetadataFile={metadataFilesArray[0]}
                 updateMetadataToUpload={updateOpenEditionMinterMetadataFile}

From 58d2a4abd772a4e1a83c80ab972eb4d28de9f836 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Thu, 17 Aug 2023 14:21:30 +0300
Subject: [PATCH 36/51] Export/Import selected mint token

---
 components/collections/creation/MintingDetails.tsx |  2 ++
 components/openEdition/MintingDetails.tsx          | 11 +++++++++--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/components/collections/creation/MintingDetails.tsx b/components/collections/creation/MintingDetails.tsx
index ca6187b..1e17ce9 100644
--- a/components/collections/creation/MintingDetails.tsx
+++ b/components/collections/creation/MintingDetails.tsx
@@ -122,6 +122,7 @@ export const MintingDetails = ({
       perAddressLimitState.onChange(importedMintingDetails.perAddressLimit)
       setTimestamp(new Date(Number(importedMintingDetails.startTime) / 1_000_000))
       paymentAddressState.onChange(importedMintingDetails.paymentAddress ? importedMintingDetails.paymentAddress : '')
+      setSelectedMintToken(tokensList.find((token) => token.id === importedMintingDetails.selectedMintToken?.id))
     }
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [importedMintingDetails])
@@ -140,6 +141,7 @@ export const MintingDetails = ({
           <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))}
+            value={selectedMintToken?.displayName}
           >
             {vendingMinterList
               .filter((minter) => minter.factoryAddress !== undefined && minter.updatable === false)
diff --git a/components/openEdition/MintingDetails.tsx b/components/openEdition/MintingDetails.tsx
index 6bb9338..3da1036 100644
--- a/components/openEdition/MintingDetails.tsx
+++ b/components/openEdition/MintingDetails.tsx
@@ -43,6 +43,7 @@ export const MintingDetails = ({
   const [timestamp, setTimestamp] = useState<Date | undefined>()
   const [endTimestamp, setEndTimestamp] = useState<Date | undefined>()
   const [selectedMintToken, setSelectedMintToken] = useState<TokenInfo | undefined>(stars)
+  const [mintingDetailsImported, setMintingDetailsImported] = useState(false)
 
   const unitPriceState = useNumberInputState({
     id: 'unitPrice',
@@ -77,7 +78,9 @@ export const MintingDetails = ({
   }
 
   useEffect(() => {
-    void resolvePaymentAddress()
+    if (!importedMintingDetails || (importedMintingDetails && mintingDetailsImported)) {
+      void resolvePaymentAddress()
+    }
   }, [paymentAddressState.value])
 
   useEffect(() => {
@@ -106,11 +109,14 @@ export const MintingDetails = ({
 
   useEffect(() => {
     if (importedMintingDetails) {
-      unitPriceState.onChange(Number(importedMintingDetails.unitPrice))
+      console.log('Selected Token ID: ', importedMintingDetails.selectedMintToken?.id)
+      unitPriceState.onChange(Number(importedMintingDetails.unitPrice) / 1000000)
       perAddressLimitState.onChange(importedMintingDetails.perAddressLimit)
       setTimestamp(new Date(Number(importedMintingDetails.startTime) / 1_000_000))
       setEndTimestamp(new Date(Number(importedMintingDetails.endTime) / 1_000_000))
       paymentAddressState.onChange(importedMintingDetails.paymentAddress ? importedMintingDetails.paymentAddress : '')
+      setSelectedMintToken(tokensList.find((token) => token.id === importedMintingDetails.selectedMintToken?.id))
+      setMintingDetailsImported(true)
     }
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [importedMintingDetails])
@@ -123,6 +129,7 @@ export const MintingDetails = ({
           <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))}
+            value={selectedMintToken?.displayName}
           >
             {openEditionMinterList
               .filter((minter) => minter.factoryAddress !== undefined && minter.updatable === false)

From 8b902a1078e72ed6b2bebceef8116250cdd33840 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Thu, 17 Aug 2023 14:22:05 +0300
Subject: [PATCH 37/51] Address royalty address import issue for open edition

---
 components/openEdition/RoyaltyDetails.tsx | 40 +++++++++++++----------
 1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/components/openEdition/RoyaltyDetails.tsx b/components/openEdition/RoyaltyDetails.tsx
index 17f32d3..039e9b6 100644
--- a/components/openEdition/RoyaltyDetails.tsx
+++ b/components/openEdition/RoyaltyDetails.tsx
@@ -23,6 +23,7 @@ type RoyaltyState = 'none' | 'new'
 export const RoyaltyDetails = ({ onChange, importedRoyaltyDetails }: RoyaltyDetailsProps) => {
   const wallet = useWallet()
   const [royaltyState, setRoyaltyState] = useState<RoyaltyState>('none')
+  const [royaltyDetailsImported, setRoyaltyDetailsImported] = useState(false)
 
   const royaltyPaymentAddressState = useInputState({
     id: 'royalty-payment-address',
@@ -41,31 +42,34 @@ export const RoyaltyDetails = ({ onChange, importedRoyaltyDetails }: RoyaltyDeta
   })
 
   useEffect(() => {
-    void resolveAddress(
-      royaltyPaymentAddressState.value
-        .toLowerCase()
-        .replace(/,/g, '')
-        .replace(/"/g, '')
-        .replace(/'/g, '')
-        .replace(/ /g, ''),
-      wallet,
-    ).then((royaltyPaymentAddress) => {
-      royaltyPaymentAddressState.onChange(royaltyPaymentAddress)
-      const data: RoyaltyDetailsDataProps = {
-        royaltyType: royaltyState,
-        paymentAddress: royaltyPaymentAddressState.value,
-        share: Number(royaltyShareState.value),
-      }
-      onChange(data)
-    })
+    if (!importedRoyaltyDetails || (importedRoyaltyDetails && royaltyDetailsImported)) {
+      void resolveAddress(
+        royaltyPaymentAddressState.value
+          .toLowerCase()
+          .replace(/,/g, '')
+          .replace(/"/g, '')
+          .replace(/'/g, '')
+          .replace(/ /g, ''),
+        wallet,
+      ).then((royaltyPaymentAddress) => {
+        royaltyPaymentAddressState.onChange(royaltyPaymentAddress)
+        const data: RoyaltyDetailsDataProps = {
+          royaltyType: royaltyState,
+          paymentAddress: royaltyPaymentAddressState.value,
+          share: Number(royaltyShareState.value),
+        }
+        onChange(data)
+      })
+    }
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [royaltyState, royaltyPaymentAddressState.value, royaltyShareState.value])
 
   useEffect(() => {
     if (importedRoyaltyDetails) {
       setRoyaltyState(importedRoyaltyDetails.royaltyType)
-      royaltyPaymentAddressState.onChange(importedRoyaltyDetails.paymentAddress)
+      royaltyPaymentAddressState.onChange(importedRoyaltyDetails.paymentAddress.toString())
       royaltyShareState.onChange(importedRoyaltyDetails.share.toString())
+      setRoyaltyDetailsImported(true)
     }
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [importedRoyaltyDetails])

From e26253fec5027757b457afc9d440ad0a06c37b5b Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Fri, 18 Aug 2023 13:10:22 +0300
Subject: [PATCH 38/51] Badge creation video asset support

---
 components/badges/creation/BadgeDetails.tsx   |  7 +++-
 .../badges/creation/ImageUploadDetails.tsx    | 40 ++++++++++++++-----
 pages/badges/create.tsx                       |  8 +++-
 3 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/components/badges/creation/BadgeDetails.tsx b/components/badges/creation/BadgeDetails.tsx
index 652143b..58fef4c 100644
--- a/components/badges/creation/BadgeDetails.tsx
+++ b/components/badges/creation/BadgeDetails.tsx
@@ -44,7 +44,7 @@ export interface BadgeDetailsDataProps {
   youtube_url?: string
 }
 
-export const BadgeDetails = ({ metadataSize, onChange }: BadgeDetailsProps) => {
+export const BadgeDetails = ({ metadataSize, onChange, uploadMethod }: BadgeDetailsProps) => {
   const wallet = useWallet()
   const [timestamp, setTimestamp] = useState<Date | undefined>(undefined)
   const [transferrable, setTransferrable] = useState<boolean>(false)
@@ -192,6 +192,10 @@ export const BadgeDetails = ({ metadataSize, onChange }: BadgeDetailsProps) => {
       })
   }, [metadataFile])
 
+  useEffect(() => {
+    animationUrlState.onChange('')
+  }, [uploadMethod])
+
   useEffect(() => {
     try {
       const data: BadgeDetailsDataProps = {
@@ -266,6 +270,7 @@ export const BadgeDetails = ({ metadataSize, onChange }: BadgeDetailsProps) => {
           <TextInput className="mt-2" {...nameState} />
           <TextInput className="mt-2" {...descriptionState} />
           <NumberInput className="mt-2" {...maxSupplyState} />
+          {uploadMethod === 'existing' ? <TextInput className="mt-2" {...animationUrlState} /> : null}
           <TextInput className="mt-2" {...externalUrlState} />
 
           <FormControl className="mt-2" htmlId="expiry-date" subtitle="Badge minting expiry date" title="Expiry Date">
diff --git a/components/badges/creation/ImageUploadDetails.tsx b/components/badges/creation/ImageUploadDetails.tsx
index 180aa06..a6b1851 100644
--- a/components/badges/creation/ImageUploadDetails.tsx
+++ b/components/badges/creation/ImageUploadDetails.tsx
@@ -1,5 +1,5 @@
 /* eslint-disable eslint-comments/disable-enable-pair */
-
+/* eslint-disable jsx-a11y/media-has-caption */
 /* eslint-disable no-misleading-character-class */
 /* eslint-disable no-control-regex */
 
@@ -10,9 +10,10 @@ import { TextInput } from 'components/forms/FormInput'
 import { useInputState } from 'components/forms/FormInput.hooks'
 import { SingleAssetPreview } from 'components/SingleAssetPreview'
 import type { ChangeEvent } from 'react'
-import { useEffect, useRef, useState } from 'react'
+import { useEffect, useMemo, useRef, useState } from 'react'
 import { toast } from 'react-hot-toast'
 import type { UploadServiceType } from 'services/upload'
+import { getAssetType } from 'utils/getAssetType'
 
 export type UploadMethod = 'new' | 'existing'
 export type MintRule = 'by_key' | 'by_minter' | 'by_keys' | 'not_resolved'
@@ -129,6 +130,22 @@ export const ImageUploadDetails = ({ onChange, mintRule }: ImageUploadDetailsPro
     imageUrlState.onChange('')
   }, [uploadMethod, mintRule])
 
+  const videoPreview = useMemo(
+    () => (
+      <video
+        className="ml-4"
+        controls
+        id="video"
+        onMouseEnter={(e) => e.currentTarget.play()}
+        onMouseLeave={(e) => e.currentTarget.pause()}
+        src={
+          imageUrlState.value ? imageUrlState.value.replace('ipfs://', 'https://ipfs-gw.stargaze-apis.com/ipfs/') : ''
+        }
+      />
+    ),
+    [imageUrlState.value],
+  )
+
   return (
     <div className="justify-items-start mb-3 rounded border-2 border-white/20 flex-column">
       <div className="flex justify-center">
@@ -190,13 +207,16 @@ export const ImageUploadDetails = ({ onChange, mintRule }: ImageUploadDetailsPro
             <div className="flex flex-row w-full">
               <TextInput {...imageUrlState} className="mt-2 ml-6 w-full max-w-2xl" />
               <Conditional test={imageUrlState.value !== ''}>
-                <div className="mt-2 ml-4 w-1/4 border-2 border-dashed">
-                  <img
-                    alt="badge-preview"
-                    className="w-full"
-                    src={imageUrlState.value.replace('IPFS://', 'ipfs://').replace(/,/g, '').replace(/"/g, '').trim()}
-                  />
-                </div>
+                {getAssetType(imageUrlState.value) === 'image' && (
+                  <div className="mt-2 ml-4 w-1/4 border-2 border-dashed">
+                    <img
+                      alt="badge-preview"
+                      className="w-full"
+                      src={imageUrlState.value.replace('IPFS://', 'ipfs://').replace(/,/g, '').replace(/"/g, '').trim()}
+                    />
+                  </div>
+                )}
+                {getAssetType(imageUrlState.value) === 'video' && videoPreview}
               </Conditional>
             </div>
           </div>
@@ -277,7 +297,7 @@ export const ImageUploadDetails = ({ onChange, mintRule }: ImageUploadDetailsPro
                         )}
                       >
                         <input
-                          accept="image/*"
+                          accept="image/*, video/*"
                           className={clsx(
                             'file:py-2 file:px-4 file:mr-4 file:bg-plumbus-light file:rounded file:border-0 cursor-pointer',
                             'before:absolute before:inset-0 before:hover:bg-white/5 before:transition',
diff --git a/pages/badges/create.tsx b/pages/badges/create.tsx
index 61f39ad..85aecd0 100644
--- a/pages/badges/create.tsx
+++ b/pages/badges/create.tsx
@@ -41,6 +41,7 @@ import * as secp256k1 from 'secp256k1'
 import { upload } from 'services/upload'
 import { copy } from 'utils/clipboard'
 import { BADGE_HUB_ADDRESS, BLOCK_EXPLORER_URL, NETWORK } from 'utils/constants'
+import { getAssetType } from 'utils/getAssetType'
 import { withMetadata } from 'utils/layout'
 import { links } from 'utils/links'
 import { uid } from 'utils/random'
@@ -184,7 +185,6 @@ const BadgeCreationPage: NextPage = () => {
       if (!badgeHubContract) throw new Error('Contract not found')
       setCreatingBadge(true)
       const coverUrl = await handleImageUrl()
-
       const badge = {
         manager: badgeDetails?.manager as string,
         metadata: {
@@ -195,7 +195,11 @@ const BadgeCreationPage: NextPage = () => {
           external_url: badgeDetails?.external_url || undefined,
           attributes: badgeDetails?.attributes || undefined,
           background_color: badgeDetails?.background_color || undefined,
-          animation_url: badgeDetails?.animation_url || undefined,
+          animation_url: badgeDetails?.animation_url
+            ? badgeDetails.animation_url
+            : imageUploadDetails?.assetFile && getAssetType(imageUploadDetails.assetFile.name) === 'video'
+            ? coverUrl
+            : undefined,
           youtube_url: badgeDetails?.youtube_url || undefined,
         },
         transferrable: badgeDetails?.transferrable as boolean,

From 0ed370aa67fae56bb696c129e0830625889fcc88 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 21 Aug 2023 10:59:10 +0300
Subject: [PATCH 39/51] Check end time during open edition creation

---
 components/openEdition/OpenEditionMinterCreator.tsx | 1 +
 1 file changed, 1 insertion(+)

diff --git a/components/openEdition/OpenEditionMinterCreator.tsx b/components/openEdition/OpenEditionMinterCreator.tsx
index 4253c56..d7acb34 100644
--- a/components/openEdition/OpenEditionMinterCreator.tsx
+++ b/components/openEdition/OpenEditionMinterCreator.tsx
@@ -303,6 +303,7 @@ export const OpenEditionMinterCreator = ({
     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')
+    if (mintingDetails.endTime === '') throw new Error('End time is required')
     if (Number(mintingDetails.startTime) < new Date().getTime() * 1000000) throw new Error('Invalid start time')
     if (
       mintingDetails.paymentAddress &&

From 8990175b03cc07c496611d39c54eec579b725500 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 21 Aug 2023 11:37:19 +0300
Subject: [PATCH 40/51] Check end time during open edition creation - 2

---
 components/openEdition/OpenEditionMinterCreator.tsx | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/components/openEdition/OpenEditionMinterCreator.tsx b/components/openEdition/OpenEditionMinterCreator.tsx
index d7acb34..46e4363 100644
--- a/components/openEdition/OpenEditionMinterCreator.tsx
+++ b/components/openEdition/OpenEditionMinterCreator.tsx
@@ -305,6 +305,11 @@ export const OpenEditionMinterCreator = ({
     if (mintingDetails.startTime === '') throw new Error('Start time is required')
     if (mintingDetails.endTime === '') throw new Error('End time is required')
     if (Number(mintingDetails.startTime) < new Date().getTime() * 1000000) throw new Error('Invalid start time')
+    if (Number(mintingDetails.endTime) < Number(mintingDetails.startTime))
+      throw new Error('End time cannot be earlier than start time')
+    if (Number(mintingDetails.endTime) === Number(mintingDetails.startTime))
+      throw new Error('End time cannot be equal to the start time')
+
     if (
       mintingDetails.paymentAddress &&
       (!isValidAddress(mintingDetails.paymentAddress) || !mintingDetails.paymentAddress.startsWith('stars1'))

From 96dda936ae6d95fc3b154d5d24c6b6ba76192de2 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 21 Aug 2023 12:07:11 +0300
Subject: [PATCH 41/51] Address OE collection empty metadata file issue

---
 components/MetadataInput.tsx                  | 42 ++++++++++---------
 .../OffChainMetadataUploadDetails.tsx         |  2 +-
 2 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/components/MetadataInput.tsx b/components/MetadataInput.tsx
index 2340d3f..0e870be 100644
--- a/components/MetadataInput.tsx
+++ b/components/MetadataInput.tsx
@@ -158,7 +158,7 @@ export const MetadataInput = (props: MetadataInputProps) => {
     } else if (!props.importedMetadata) {
       void parseMetadata(emptyMetadataFile)
     }
-  }, [props.selectedMetadataFile?.name])
+  }, [props.selectedMetadataFile?.name, props.importedMetadata])
 
   const nameStateMemo = useMemo(() => nameState, [nameState.value])
   const descriptionStateMemo = useMemo(() => descriptionState, [descriptionState.value])
@@ -183,26 +183,28 @@ export const MetadataInput = (props: MetadataInputProps) => {
 
   useEffect(() => {
     if (props.importedMetadata) {
-      console.log('Imported metadata: ', props.importedMetadata)
-      nameState.onChange(props.importedMetadata.name || '')
-      descriptionState.onChange(props.importedMetadata.description || '')
-      externalUrlState.onChange(props.importedMetadata.external_url || '')
-      youtubeUrlState.onChange(props.importedMetadata.youtube_url || '')
-      if (props.importedMetadata?.attributes && props.importedMetadata?.attributes?.length > 0) {
-        attributesState.reset()
-        props.importedMetadata?.attributes?.forEach((attribute: { trait_type: string; value: string }) => {
-          attributesState.add({
-            trait_type: attribute.trait_type,
-            value: attribute.value,
+      void parseMetadata(emptyMetadataFile).then(() => {
+        console.log('Imported metadata: ', props.importedMetadata)
+        nameState.onChange(props.importedMetadata.name || '')
+        descriptionState.onChange(props.importedMetadata.description || '')
+        externalUrlState.onChange(props.importedMetadata.external_url || '')
+        youtubeUrlState.onChange(props.importedMetadata.youtube_url || '')
+        if (props.importedMetadata?.attributes && props.importedMetadata?.attributes?.length > 0) {
+          attributesState.reset()
+          props.importedMetadata?.attributes?.forEach((attribute: { trait_type: string; value: string }) => {
+            attributesState.add({
+              trait_type: attribute.trait_type,
+              value: attribute.value,
+            })
           })
-        })
-      } else {
-        attributesState.reset()
-        attributesState.add({
-          trait_type: '',
-          value: '',
-        })
-      }
+        } else {
+          attributesState.reset()
+          attributesState.add({
+            trait_type: '',
+            value: '',
+          })
+        }
+      })
     }
   }, [props.importedMetadata])
 
diff --git a/components/openEdition/OffChainMetadataUploadDetails.tsx b/components/openEdition/OffChainMetadataUploadDetails.tsx
index abe06f6..e317a8e 100644
--- a/components/openEdition/OffChainMetadataUploadDetails.tsx
+++ b/components/openEdition/OffChainMetadataUploadDetails.tsx
@@ -250,7 +250,7 @@ export const OffChainMetadataUploadDetails = ({
       setUploadMethod(importedOffChainMetadataUploadDetails.uploadMethod)
       tokenUriState.onChange(importedOffChainMetadataUploadDetails.tokenURI || '')
       coverImageUrlState.onChange(importedOffChainMetadataUploadDetails.imageUrl || '')
-      //setOpenEditionMinterMetadataFile(importedOffChainMetadataUploadDetails.openEditionMinterMetadataFile)
+      // setOpenEditionMinterMetadataFile(importedOffChainMetadataUploadDetails.openEditionMinterMetadataFile)
     }
   }, [importedOffChainMetadataUploadDetails])
 

From ae9aec3bd891f83397512919b68f71f363b39466 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 21 Aug 2023 12:40:54 +0300
Subject: [PATCH 42/51] Disable default upload method when importing

---
 components/collections/creation/UploadDetails.tsx | 2 +-
 pages/collections/create.tsx                      | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/components/collections/creation/UploadDetails.tsx b/components/collections/creation/UploadDetails.tsx
index 0b8aa61..519f879 100644
--- a/components/collections/creation/UploadDetails.tsx
+++ b/components/collections/creation/UploadDetails.tsx
@@ -289,7 +289,7 @@ export const UploadDetails = ({
   useEffect(() => {
     if (importedUploadDetails) {
       if (importedUploadDetails.uploadMethod === 'new') {
-        setUploadMethod('existing')
+        setUploadMethod('new')
         setUploadService(importedUploadDetails.uploadService)
         nftStorageApiKeyState.onChange(importedUploadDetails.nftStorageApiKey || '')
         pinataApiKeyState.onChange(importedUploadDetails.pinataApiKey || '')
diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 0053acd..bc83c42 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -1322,7 +1322,7 @@ const CollectionCreationPage: NextPage = () => {
         details.uploadDetails.baseTokenURI = details.baseTokenUri
         details.uploadDetails.imageUrl = details.coverImageUrl
       }
-      if (details.openEditionMinterDetails.openEditionMinterContractAddress) {
+      if (details.openEditionMinterDetails?.openEditionMinterContractAddress) {
         details.openEditionMinterDetails.offChainMetadataUploadDetails.uploadMethod = 'existing'
         details.openEditionMinterDetails.offChainMetadataUploadDetails.tokenURI =
           details.openEditionMinterDetails.tokenUri

From 4cc6fdc0700245c9568fb9ba9a32d1736006beb8 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 21 Aug 2023 14:59:12 +0300
Subject: [PATCH 43/51] Update import/export component placement

---
 .../openEdition/OpenEditionMinterCreator.tsx  |  2 +-
 pages/collections/create.tsx                  | 43 +++++++++++++------
 2 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/components/openEdition/OpenEditionMinterCreator.tsx b/components/openEdition/OpenEditionMinterCreator.tsx
index 46e4363..bf2ab74 100644
--- a/components/openEdition/OpenEditionMinterCreator.tsx
+++ b/components/openEdition/OpenEditionMinterCreator.tsx
@@ -713,7 +713,7 @@ export const OpenEditionMinterCreator = ({
           </div>
         </div>
       </Conditional>
-      <div className={clsx('my-4 mx-10')}>
+      <div className={clsx('my-0 mx-10')}>
         <Conditional test={metadataStorageMethod === 'off-chain'}>
           <div>
             <OffChainMetadataUploadDetails
diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index bc83c42..5311fba 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -30,6 +30,7 @@ import type { RoyaltyDetailsDataProps } from 'components/collections/creation/Ro
 import type { UploadDetailsDataProps } from 'components/collections/creation/UploadDetails'
 import type { WhitelistDetailsDataProps } from 'components/collections/creation/WhitelistDetails'
 import { Conditional } from 'components/Conditional'
+import { FormControl } from 'components/FormControl'
 import { LoadingModal } from 'components/LoadingModal'
 import type { OpenEditionMinterCreatorDataProps } from 'components/openEdition/OpenEditionMinterCreator'
 import { OpenEditionMinterCreator } from 'components/openEdition/OpenEditionMinterCreator'
@@ -1305,12 +1306,20 @@ const CollectionCreationPage: NextPage = () => {
     const element = document.createElement('a')
     const file = new Blob([JSON.stringify(details)], { type: 'text/plain' })
     element.href = URL.createObjectURL(file)
-    element.download = 'details.json'
+    element.download = `${
+      minterType === 'vending'
+        ? collectionDetails?.name
+          ? `${collectionDetails.name}-`
+          : ''
+        : openEditionMinterDetails?.collectionDetails
+        ? `${openEditionMinterDetails.collectionDetails.name}-`
+        : ''
+    }configuration-${new Date().toLocaleString().replaceAll(',', '_')}.json`
     document.body.appendChild(element) // Required for this to work in FireFox
     element.click()
   }
   const importDetails = (event: ChangeEvent<HTMLInputElement>) => {
-    if (event.target.files === null) return toast.error('No files selected.')
+    if (event.target.files === null || event.target.files.length === 0) return toast.error('No files selected.')
     const file = event.target.files[0]
     const reader = new FileReader()
     reader.onload = (e) => {
@@ -1408,15 +1417,7 @@ const CollectionCreationPage: NextPage = () => {
             : 'Create Collection'
         }
       />
-      <Button className="absolute top-5 right-5" onClick={() => exportDetails()}>
-        Export Details
-      </Button>
-      <input
-        accept="application/json"
-        className="absolute top-5 right-20"
-        onChange={(e) => importDetails(e)}
-        type="file"
-      />
+
       <div className="mt-5 space-y-5 text-center">
         <h1 className="font-heading text-4xl font-bold">
           {minterType === 'base' && baseMinterDetails?.baseMinterAcquisitionMethod === 'existing'
@@ -1436,6 +1437,7 @@ const CollectionCreationPage: NextPage = () => {
           on how to create your collection
         </p>
       </div>
+
       <div className="mx-10" ref={scrollRef}>
         <Conditional
           test={minterType === 'openEdition' && openEditionMinterCreatorData?.openEditionMinterContractAddress !== null}
@@ -1674,7 +1676,8 @@ const CollectionCreationPage: NextPage = () => {
           className={clsx(
             'mx-10 mt-5',
             'grid before:absolute relative grid-cols-3 grid-flow-col items-stretch rounded',
-            'before:inset-x-0 before:bottom-0 before:border-white/25',
+            'before:inset-x-0 before:bottom-0  before:border-white/25',
+            minterType !== 'base' ? 'rounded-none border-b-2 border-white/25' : 'border-0',
           )}
         >
           <div
@@ -1748,6 +1751,22 @@ const CollectionCreationPage: NextPage = () => {
         </div>
       </div>
 
+      <Conditional test={minterType !== 'base'}>
+        <FormControl className={clsx('py-4 px-10 w-full')} title="Import Creation Configuration">
+          <div className="flex flex-row justify-between mt-5 space-x-2">
+            <input
+              accept="application/json"
+              className="py-4 px-4 w-1/3 rounded-sm border-[1px] border-zinc-500 border-dashed"
+              onChange={(e) => importDetails(e)}
+              type="file"
+            />
+            <Button className="mt-3 h-1/2 w-1/8" onClick={() => exportDetails()}>
+              Export Creation Configuration
+            </Button>
+          </div>
+        </FormControl>
+      </Conditional>
+
       {minterType === 'base' && (
         <div>
           <BaseMinterDetails minterType={minterType} onChange={setBaseMinterDetails} />

From 5578c408a51a666b864690f39cd16322ab7422e1 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 21 Aug 2023 15:00:06 +0300
Subject: [PATCH 44/51] Bump Studio version

---
 .env.example | 2 +-
 package.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.env.example b/.env.example
index ffe2835..170dd6e 100644
--- a/.env.example
+++ b/.env.example
@@ -1,4 +1,4 @@
-APP_VERSION=0.7.3
+APP_VERSION=0.7.4
 
 NEXT_PUBLIC_PINATA_ENDPOINT_URL=https://api.pinata.cloud/pinning/pinFileToIPFS
 NEXT_PUBLIC_SG721_CODE_ID=2595
diff --git a/package.json b/package.json
index ff54c94..acc68fe 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "stargaze-studio",
-  "version": "0.7.3",
+  "version": "0.7.4",
   "workspaces": [
     "packages/*"
   ],

From f25807f35579cbb1e2df4892ae2d7d19242f56b7 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 21 Aug 2023 16:29:52 +0300
Subject: [PATCH 45/51] Unmicro whitelist unit price

---
 components/collections/creation/WhitelistDetails.tsx | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/components/collections/creation/WhitelistDetails.tsx b/components/collections/creation/WhitelistDetails.tsx
index aa0d908..880bf7b 100644
--- a/components/collections/creation/WhitelistDetails.tsx
+++ b/components/collections/creation/WhitelistDetails.tsx
@@ -160,7 +160,9 @@ export const WhitelistDetails = ({
       whitelistAddressState.onChange(
         importedWhitelistDetails.contractAddress ? importedWhitelistDetails.contractAddress : '',
       )
-      unitPriceState.onChange(importedWhitelistDetails.unitPrice ? Number(importedWhitelistDetails.unitPrice) : 0)
+      unitPriceState.onChange(
+        importedWhitelistDetails.unitPrice ? Number(importedWhitelistDetails.unitPrice) / 1000000 : 0,
+      )
       memberLimitState.onChange(importedWhitelistDetails.memberLimit ? importedWhitelistDetails.memberLimit : 0)
       perAddressLimitState.onChange(
         importedWhitelistDetails.perAddressLimit ? importedWhitelistDetails.perAddressLimit : 0,

From 1ca1d08b2ac7991d67b265286ee822cb63106f22 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 21 Aug 2023 16:43:05 +0300
Subject: [PATCH 46/51] Reset upload details on import for 1/1 collections

---
 components/collections/creation/UploadDetails.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/components/collections/creation/UploadDetails.tsx b/components/collections/creation/UploadDetails.tsx
index 519f879..bb99e3b 100644
--- a/components/collections/creation/UploadDetails.tsx
+++ b/components/collections/creation/UploadDetails.tsx
@@ -280,7 +280,7 @@ export const UploadDetails = ({
     setMetadataFilesArray([])
     if (assetFilesRef.current) assetFilesRef.current.value = ''
     setAssetFilesArray([])
-    if (!importedUploadDetails) {
+    if (!importedUploadDetails || minterType === 'base') {
       baseTokenUriState.onChange('')
       coverImageUrlState.onChange('')
     }

From 391b712bde688dcb01b923ec7cf151122b2e957f Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 21 Aug 2023 19:45:23 +0300
Subject: [PATCH 47/51] Prevent duplicate protocol in the base token uri

---
 pages/collections/create.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 5311fba..4ba9555 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -1297,7 +1297,7 @@ const CollectionCreationPage: NextPage = () => {
       baseMinterDetails,
       openEditionMinterDetails,
       vendingMinterContractAddress,
-      baseTokenUri: `ipfs://${baseTokenUri}`,
+      baseTokenUri: `${baseTokenUri?.startsWith('ipfs://') ? baseTokenUri : `ipfs://${baseTokenUri}`}`,
       coverImageUrl:
         uploadDetails?.uploadMethod === 'new'
           ? `ipfs://${coverImageUrl}/${collectionDetails?.imageFile[0]?.name as string}`

From 26a54235999486631dd56547cf41f3ece4b6dc42 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Tue, 22 Aug 2023 21:52:31 +0300
Subject: [PATCH 48/51] Address upload issue when token metadata lacks a
 description

---
 components/openEdition/OpenEditionMinterCreator.tsx |  6 ++++--
 pages/collections/create.tsx                        | 12 ++++++++----
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/components/openEdition/OpenEditionMinterCreator.tsx b/components/openEdition/OpenEditionMinterCreator.tsx
index 1c62c29..190c279 100644
--- a/components/openEdition/OpenEditionMinterCreator.tsx
+++ b/components/openEdition/OpenEditionMinterCreator.tsx
@@ -468,8 +468,10 @@ export const OpenEditionMinterCreator = ({
             if (getAssetType(offChainMetadataUploadDetails.assetFiles[0].name) !== 'html')
               data.image = `ipfs://${assetUri}/${offChainMetadataUploadDetails.assetFiles[0].name}`
 
-            // eslint-disable-next-line @typescript-eslint/no-unsafe-call
-            data.description = data.description.replaceAll('\\n', '\n')
+            if (data.description) {
+              // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+              data.description = data.description.replaceAll('\\n', '\n')
+            }
             const metadataFileBlob = new Blob([JSON.stringify(data)], {
               type: 'application/json',
             })
diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 008830f..2137308 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -741,8 +741,10 @@ const CollectionCreationPage: NextPage = () => {
                 if (getAssetType(uploadDetails.assetFiles[i].name) !== 'html')
                   data.image = `ipfs://${assetUri}/${uploadDetails.assetFiles[i].name}`
 
-                // eslint-disable-next-line @typescript-eslint/no-unsafe-call
-                data.description = data.description.replaceAll('\\n', '\n')
+                if (data.description) {
+                  // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+                  data.description = data.description.replaceAll('\\n', '\n')
+                }
                 const metadataFileBlob = new Blob([JSON.stringify(data)], {
                   type: 'application/json',
                 })
@@ -797,8 +799,10 @@ const CollectionCreationPage: NextPage = () => {
                 type: 'application/json',
               })
 
-              // eslint-disable-next-line @typescript-eslint/no-unsafe-call
-              data.description = data.description.replaceAll('\\n', '\n')
+              if (data.description) {
+                // eslint-disable-next-line @typescript-eslint/no-unsafe-call
+                data.description = data.description.replaceAll('\\n', '\n')
+              }
               console.log('Name: ', (uploadDetails.baseMinterMetadataFile as File).name)
               const updatedMetadataFile = new File(
                 [metadataFileBlob],

From f62348df0c1e51457e654997469861e3e90026d2 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Fri, 25 Aug 2023 18:24:18 +0300
Subject: [PATCH 49/51] Update USDC denom for testnet

---
 config/token.ts | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/config/token.ts b/config/token.ts
index 7cb99b6..6513b8d 100644
--- a/config/token.ts
+++ b/config/token.ts
@@ -25,7 +25,10 @@ export const ibcAtom: TokenInfo = {
 
 export const ibcUsdc: TokenInfo = {
   id: 'ibc-usdc',
-  denom: 'ibc/D189335C6E4A68B513C10AB227BF1C1D38C746766278BA3EEB4FB14124F1D858',
+  denom:
+    NETWORK === 'mainnet'
+      ? 'ibc/D189335C6E4A68B513C10AB227BF1C1D38C746766278BA3EEB4FB14124F1D858'
+      : 'factory/stars1s8qx0zvz8yd6e4x0mqmqf7fr9vvfn622wtp3g3/uusdc',
   displayName: 'USDC',
   decimalPlaces: 6,
 }

From 1c689cbb19394cf8007cd337b46370b13aabbedb Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sat, 26 Aug 2023 18:28:05 +0300
Subject: [PATCH 50/51] Update enable updatable fee

---
 contracts/sg721/contract.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/contracts/sg721/contract.ts b/contracts/sg721/contract.ts
index 91a7b38..6963d13 100644
--- a/contracts/sg721/contract.ts
+++ b/contracts/sg721/contract.ts
@@ -719,7 +719,7 @@ export const SG721 = (client: SigningCosmWasmClient, txSigner: string): SG721Con
         },
         'auto',
         '',
-        [coin('500000000', 'ustars')],
+        [coin('2000000000', 'ustars')],
       )
       return res.transactionHash
     }
@@ -1018,7 +1018,7 @@ export const SG721 = (client: SigningCosmWasmClient, txSigner: string): SG721Con
         msg: {
           enable_updatable: {},
         },
-        funds: [coin('500000000', 'ustars')],
+        funds: [coin('2000000000', 'ustars')],
       }
     }
 

From bf697745d53273e3e6ed8c3f73969c516841fc0a Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Tue, 29 Aug 2023 14:13:57 +0300
Subject: [PATCH 51/51] Fix factory switching related issues

---
 components/openEdition/OpenEditionMinterCreator.tsx | 8 +++++++-
 pages/collections/create.tsx                        | 2 +-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/components/openEdition/OpenEditionMinterCreator.tsx b/components/openEdition/OpenEditionMinterCreator.tsx
index 190c279..c722c8f 100644
--- a/components/openEdition/OpenEditionMinterCreator.tsx
+++ b/components/openEdition/OpenEditionMinterCreator.tsx
@@ -123,7 +123,13 @@ export const OpenEditionMinterCreator = ({
       openEditionFactoryContract?.use(
         collectionDetails?.updatable ? updatableFactoryAddressForSelectedDenom : factoryAddressForSelectedDenom,
       ),
-    [openEditionFactoryContract, wallet.address],
+    [
+      openEditionFactoryContract,
+      wallet.address,
+      collectionDetails?.updatable,
+      factoryAddressForSelectedDenom,
+      updatableFactoryAddressForSelectedDenom,
+    ],
   )
 
   const performOpenEditionMinterChecks = () => {
diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 2137308..13896d7 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -124,7 +124,7 @@ const CollectionCreationPage: NextPage = () => {
 
   const vendingFactoryMessages = useMemo(
     () => vendingFactoryContract?.use(vendingFactoryAddress as string),
-    [vendingFactoryContract, wallet.address],
+    [vendingFactoryContract, wallet.address, vendingFactoryAddress],
   )
 
   const baseFactoryMessages = useMemo(