From 80bec18cc7fc826e87f99d0237634fdd23a0babd Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Fri, 6 Jan 2023 17:19:43 +0300
Subject: [PATCH 1/8] Include file selection support for WL > Add Members

---
 pages/contracts/whitelist/execute.tsx | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/pages/contracts/whitelist/execute.tsx b/pages/contracts/whitelist/execute.tsx
index 005c8db..47d463c 100644
--- a/pages/contracts/whitelist/execute.tsx
+++ b/pages/contracts/whitelist/execute.tsx
@@ -13,6 +13,7 @@ import { JsonPreview } from 'components/JsonPreview'
 import { LinkTabs } from 'components/LinkTabs'
 import { whitelistLinkTabs } from 'components/LinkTabs.data'
 import { TransactionHash } from 'components/TransactionHash'
+import { WhitelistUpload } from 'components/WhitelistUpload'
 import { useContracts } from 'contexts/contracts'
 import { useWallet } from 'contexts/wallet'
 import type { DispatchExecuteArgs } from 'contracts/whitelist/messages/execute'
@@ -25,6 +26,7 @@ import { useEffect, useMemo, useState } from 'react'
 import { toast } from 'react-hot-toast'
 import { FaArrowRight } from 'react-icons/fa'
 import { useMutation } from 'react-query'
+import { isValidAddress } from 'utils/isValidAddress'
 import { withMetadata } from 'utils/layout'
 import { links } from 'utils/links'
 
@@ -33,6 +35,7 @@ const WhitelistExecutePage: NextPage = () => {
   const wallet = useWallet()
 
   const [lastTx, setLastTx] = useState('')
+  const [memberList, setMemberList] = useState<string[]>([])
 
   const comboboxState = useExecuteComboboxState()
   const type = comboboxState.value?.id
@@ -68,7 +71,14 @@ const WhitelistExecutePage: NextPage = () => {
     type,
     limit: limitState.value,
     timestamp: timestamp ? (timestamp.getTime() * 1_000_000).toString() : '',
-    members: addressListState.values.map((a) => a.address),
+    members: [
+      ...new Set(
+        addressListState.values
+          .map((a) => a.address)
+          .filter((address) => address !== '' && isValidAddress(address) && address.startsWith('stars'))
+          .concat(memberList),
+      ),
+    ],
   }
   const { isLoading, mutate } = useMutation(
     async (event: FormEvent) => {
@@ -145,6 +155,7 @@ const WhitelistExecutePage: NextPage = () => {
               subtitle="Enter the member addresses"
               title="Addresses"
             />
+            <WhitelistUpload onChange={setMemberList} />
           </Conditional>
         </div>
         <div className="space-y-8">

From fd54468d065a4c29e50c6b3d03edc1b608da5253 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 8 Jan 2023 19:41:02 +0300
Subject: [PATCH 2/8] Add instructions for WL > Execute > Add/Remove Members

---
 pages/contracts/whitelist/execute.tsx | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/pages/contracts/whitelist/execute.tsx b/pages/contracts/whitelist/execute.tsx
index 47d463c..b4e54e6 100644
--- a/pages/contracts/whitelist/execute.tsx
+++ b/pages/contracts/whitelist/execute.tsx
@@ -1,3 +1,4 @@
+import { Alert } from 'components/Alert'
 import { Button } from 'components/Button'
 import { Conditional } from 'components/Conditional'
 import { ContractPageHeader } from 'components/ContractPageHeader'
@@ -74,8 +75,8 @@ const WhitelistExecutePage: NextPage = () => {
     members: [
       ...new Set(
         addressListState.values
-          .map((a) => a.address)
-          .filter((address) => address !== '' && isValidAddress(address) && address.startsWith('stars'))
+          .map((a) => a.address.trim())
+          .filter((address) => address !== '' && isValidAddress(address.trim()) && address.startsWith('stars'))
           .concat(memberList),
       ),
     ],
@@ -155,6 +156,9 @@ const WhitelistExecutePage: NextPage = () => {
               subtitle="Enter the member addresses"
               title="Addresses"
             />
+            <Alert className="mt-8" type="info">
+              You may optionally choose a text file of additional member addresses.
+            </Alert>
             <WhitelistUpload onChange={setMemberList} />
           </Conditional>
         </div>

From ce38980eff5970922bf5489dc6e019c86152a419 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 8 Jan 2023 19:53:58 +0300
Subject: [PATCH 3/8] Perform description length check with
 checkCollectionDetails()

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

diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 20bf22f..2e3703c 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -661,6 +661,8 @@ const CollectionCreationPage: NextPage = () => {
     if (!collectionDetails) throw new Error('Please fill out the collection details')
     if (collectionDetails.name === '') throw new Error('Collection name is required')
     if (collectionDetails.description === '') throw new Error('Collection description is required')
+    if (collectionDetails.description.length > 512)
+      throw new Error('Collection description cannot exceed 512 characters')
     if (uploadDetails?.uploadMethod === 'new' && collectionDetails.imageFile.length === 0)
       throw new Error('Collection cover image is required')
     if (

From 0066fddae8e639bd3c362fc00d2fd09fa524afc5 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 8 Jan 2023 20:09:05 +0300
Subject: [PATCH 4/8] Rename mint & append token UI elements

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

diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 2e3703c..cabc15f 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -311,7 +311,10 @@ const CollectionCreationPage: NextPage = () => {
             return result
           })
           .then((result) => {
-            toast.success(`Minted successfully! Tx Hash: ${result}`, { style: { maxWidth: 'none' }, duration: 5000 })
+            toast.success(`Minted & appended successfully! Tx Hash: ${result}`, {
+              style: { maxWidth: 'none' },
+              duration: 5000,
+            })
             setIsMintingComplete(true)
           })
           .catch((error) => {
@@ -327,7 +330,10 @@ const CollectionCreationPage: NextPage = () => {
           .use(baseMinterDetails?.existingBaseMinter as string)
           ?.mint(wallet.address, `${uploadDetails?.baseTokenURI?.trim()}`)
           .then((result) => {
-            toast.success(`Minted successfully! Tx Hash: ${result}`, { style: { maxWidth: 'none' }, duration: 5000 })
+            toast.success(`Minted & appended successfully! Tx Hash: ${result}`, {
+              style: { maxWidth: 'none' },
+              duration: 5000,
+            })
           })
           .catch((error) => {
             toast.error(error.message, { style: { maxWidth: 'none' } })
@@ -789,7 +795,7 @@ const CollectionCreationPage: NextPage = () => {
       <NextSeo
         title={
           minterType === 'base' && baseMinterDetails?.baseMinterAcquisitionMethod === 'existing'
-            ? 'Mint Token'
+            ? 'Append Token'
             : 'Create Collection'
         }
       />
@@ -797,7 +803,7 @@ const CollectionCreationPage: NextPage = () => {
       <div className="mt-5 space-y-5 text-center">
         <h1 className="font-heading text-4xl font-bold">
           {minterType === 'base' && baseMinterDetails?.baseMinterAcquisitionMethod === 'existing'
-            ? 'Mint Token'
+            ? 'Append Token'
             : 'Create Collection'}
         </h1>
 
@@ -1071,7 +1077,7 @@ const CollectionCreationPage: NextPage = () => {
               onClick={performUploadAndMintChecks}
               variant="solid"
             >
-              Upload & Mint Token
+              Mint & Append Token
             </Button>
           </Conditional>
         </div>

From 6e1f1905b3d508c57c0749d73cc86d0a9498a25f Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 8 Jan 2023 20:12:15 +0300
Subject: [PATCH 5/8] Update mint & append token success toasts

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

diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index cabc15f..48101d9 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -311,7 +311,7 @@ const CollectionCreationPage: NextPage = () => {
             return result
           })
           .then((result) => {
-            toast.success(`Minted & appended successfully! Tx Hash: ${result}`, {
+            toast.success(`Token minted & appended to the collection successfully! Tx Hash: ${result}`, {
               style: { maxWidth: 'none' },
               duration: 5000,
             })
@@ -330,7 +330,7 @@ const CollectionCreationPage: NextPage = () => {
           .use(baseMinterDetails?.existingBaseMinter as string)
           ?.mint(wallet.address, `${uploadDetails?.baseTokenURI?.trim()}`)
           .then((result) => {
-            toast.success(`Minted & appended successfully! Tx Hash: ${result}`, {
+            toast.success(`Token minted & appended to the collection successfully! Tx Hash: ${result}`, {
               style: { maxWidth: 'none' },
               duration: 5000,
             })

From 123cbea66c487c5738828ec28aae66f193b7302d Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 8 Jan 2023 20:16:56 +0300
Subject: [PATCH 6/8] 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 e2e1a0a..386ce93 100644
--- a/.env.example
+++ b/.env.example
@@ -1,4 +1,4 @@
-APP_VERSION=0.3.5
+APP_VERSION=0.3.7
 
 NEXT_PUBLIC_PINATA_ENDPOINT_URL=https://api.pinata.cloud/pinning/pinFileToIPFS
 NEXT_PUBLIC_SG721_CODE_ID=274
diff --git a/package.json b/package.json
index d2c8451..f85c38b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "stargaze-studio",
-  "version": "0.3.6",
+  "version": "0.3.7",
   "workspaces": [
     "packages/*"
   ],

From ef80449b9186f81db5b5da93a1503681fcea7643 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Sun, 8 Jan 2023 20:27:37 +0300
Subject: [PATCH 7/8] Minor UI update on UploadDetails

---
 components/collections/creation/UploadDetails.tsx | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/components/collections/creation/UploadDetails.tsx b/components/collections/creation/UploadDetails.tsx
index 872e7d3..44ce386 100644
--- a/components/collections/creation/UploadDetails.tsx
+++ b/components/collections/creation/UploadDetails.tsx
@@ -318,11 +318,11 @@ export const UploadDetails = ({ onChange, minterType, baseMinterAcquisitionMetho
               and upload your assets & metadata manually to get a base URI for your collection.
             </p>
             <div>
-              <TextInput {...baseTokenUriState} className="w-1/2" />
+              <TextInput {...baseTokenUriState} className="ml-4 w-1/2" />
             </div>
             <Conditional test={minterType !== 'base'}>
               <div>
-                <TextInput {...coverImageUrlState} className="mt-2 w-1/2" />
+                <TextInput {...coverImageUrlState} className="mt-2 ml-4 w-1/2" />
               </div>
             </Conditional>
           </div>
@@ -342,13 +342,13 @@ export const UploadDetails = ({ onChange, minterType, baseMinterAcquisitionMetho
               and upload your asset & metadata manually to get a URI for your token before minting.
             </p>
             <div>
-              <TextInput {...baseTokenUriState} className="w-1/2" />
+              <TextInput {...baseTokenUriState} className="ml-4 w-1/2" />
             </div>
             <Conditional
               test={minterType !== 'base' || (minterType === 'base' && baseMinterAcquisitionMethod === 'new')}
             >
               <div>
-                <TextInput {...coverImageUrlState} className="mt-2 w-1/2" />
+                <TextInput {...coverImageUrlState} className="mt-2 ml-4 w-1/2" />
               </div>
             </Conditional>
           </div>

From cb8eeb0dfd7d6df8ded4533421ca993ae1798f88 Mon Sep 17 00:00:00 2001
From: Serkan Reis <serkanreis@gmail.com>
Date: Mon, 9 Jan 2023 09:38:13 +0300
Subject: [PATCH 8/8] Added check for external_link protocol

---
 pages/collections/create.tsx | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx
index 48101d9..ffec279 100644
--- a/pages/collections/create.tsx
+++ b/pages/collections/create.tsx
@@ -681,6 +681,13 @@ const CollectionCreationPage: NextPage = () => {
       Number(collectionDetails.startTradingTime) < Number(mintingDetails?.startTime)
     )
       throw new Error('Trading start time must be after minting start time')
+    if (collectionDetails.externalLink) {
+      try {
+        const url = new URL(collectionDetails.externalLink)
+      } catch (e: any) {
+        throw new Error(`Invalid external link: Make sure to include the protocol (e.g. https://)`)
+      }
+    }
   }
 
   const checkMintingDetails = () => {