diff --git a/components/collections/creation/UploadDetails.tsx b/components/collections/creation/UploadDetails.tsx index 8d78746..694ee47 100644 --- a/components/collections/creation/UploadDetails.tsx +++ b/components/collections/creation/UploadDetails.tsx @@ -119,7 +119,7 @@ export const UploadDetails = ({ if (event.target.files === null) return const thumbnailCompatibleAssetTypes: AssetType[] = ['video', 'audio', 'html'] const thumbnailCompatibleFileNamesList: string[] = [] - if (minterType === 'vending' || (minterType === 'base' && event.target.files.length > 1)) { + if (minterType === 'vending') { //sort the files const sortedFiles = Array.from(event.target.files).sort((a, b) => naturalCompare(a.name, b.name)) //check if the sorted file names are in numerical order @@ -146,6 +146,38 @@ export const UploadDetails = ({ return } } + } else if (minterType === 'base' && event.target.files.length > 1) { + //sort the files + const sortedFiles = Array.from(event.target.files).sort((a, b) => naturalCompare(a.name, b.name)) + //check if the sorted file names are in numerical order + const sortedFileNames = sortedFiles.map((file) => file.name.split('.')[0]) + sortedFiles.map((file) => { + if (thumbnailCompatibleAssetTypes.includes(getAssetType(file.name))) { + thumbnailCompatibleFileNamesList.push(file.name.split('.')[0]) + } + }) + setThumbnailCompatibleAssetFileNames(thumbnailCompatibleFileNamesList) + console.log('Thumbnail Compatible Files: ', thumbnailCompatibleFileNamesList) + + for (let i = 0; i < sortedFileNames.length - 1; i++) { + if ( + isNaN(Number(sortedFileNames[i])) || + isNaN(Number(sortedFileNames[i + 1])) || + parseInt(sortedFileNames[i]) !== parseInt(sortedFileNames[i + 1]) - 1 + ) { + toast.error('The file names should be in numerical order.') + setThumbnailCompatibleAssetFileNames([]) + addLogItem({ + id: uid(), + message: 'The file names should be in numerical order.', + type: 'Error', + timestamp: new Date(), + }) + //clear the input + event.target.value = '' + return + } + } } else if (minterType === 'base' && event.target.files.length === 1) { if (thumbnailCompatibleAssetTypes.includes(getAssetType(event.target.files[0].name))) { thumbnailCompatibleFileNamesList.push(event.target.files[0].name.split('.')[0]) @@ -186,7 +218,23 @@ export const UploadDetails = ({ event.target.value = '' return toast.error('The number of metadata files should be equal to the number of asset files.') } - if (minterType === 'vending' || (minterType === 'base' && assetFilesArray.length > 1)) { + // compare the first file name for asset and metadata files + if ( + minterType === 'base' && + assetFilesArray.length > 1 && + event.target.files[0].name.split('.')[0] !== assetFilesArray[0].name.split('.')[0] + ) { + event.target.value = '' + toast.error('The metadata file names should match the asset file names.') + addLogItem({ + id: uid(), + message: 'The metadata file names should match the asset file names.', + type: 'Error', + timestamp: new Date(), + }) + return + } + if (minterType === 'vending') { //sort the files const sortedFiles = Array.from(event.target.files).sort((a, b) => naturalCompare(a.name, b.name)) //check if the sorted file names are in numerical order @@ -204,6 +252,28 @@ export const UploadDetails = ({ return } } + } else if (minterType === 'base' && assetFilesArray.length > 1) { + //sort the files + const sortedFiles = Array.from(event.target.files).sort((a, b) => naturalCompare(a.name, b.name)) + //check if the sorted file names are in numerical order + const sortedFileNames = sortedFiles.map((file) => file.name.split('.')[0]) + for (let i = 0; i < sortedFileNames.length - 1; i++) { + if ( + isNaN(Number(sortedFileNames[i])) || + isNaN(Number(sortedFileNames[i + 1])) || + parseInt(sortedFileNames[i]) !== parseInt(sortedFileNames[i + 1]) - 1 + ) { + toast.error('The file names should be in numerical order.') + addLogItem({ + id: uid(), + message: 'The file names should be in numerical order.', + type: 'Error', + timestamp: new Date(), + }) + event.target.value = '' + return + } + } } let loadedFileCount = 0 const files: File[] = [] diff --git a/contracts/baseMinter/contract.ts b/contracts/baseMinter/contract.ts index 1945412..d02275a 100644 --- a/contracts/baseMinter/contract.ts +++ b/contracts/baseMinter/contract.ts @@ -33,13 +33,13 @@ export interface BaseMinterInstance { //Execute mint: (senderAddress: string, tokenUri: string) => Promise updateStartTradingTime: (senderAddress: string, time?: Timestamp) => Promise - batchMint: (senderAddress: string, recipient: string, batchCount: number) => Promise + batchMint: (senderAddress: string, recipient: string, batchCount: number, startFrom: number) => Promise } export interface BaseMinterMessages { mint: (tokenUri: string) => MintMessage updateStartTradingTime: (time: Timestamp) => UpdateStartTradingTimeMessage - batchMint: (recipient: string, batchNumber: number) => CustomMessage + batchMint: (recipient: string, batchNumber: number, startFrom: number) => CustomMessage } export interface MintMessage { @@ -178,7 +178,12 @@ export const baseMinter = (client: SigningCosmWasmClient, txSigner: string): Bas return res.transactionHash } - const batchMint = async (senderAddress: string, baseUri: string, batchCount: number): Promise => { + const batchMint = async ( + senderAddress: string, + baseUri: string, + batchCount: number, + startFrom: number, + ): Promise => { const txHash = await getConfig().then(async (response) => { const factoryParameters = await toast.promise(getFactoryParameters(response?.config?.factory), { loading: 'Querying Factory Parameters...', @@ -198,7 +203,7 @@ export const baseMinter = (client: SigningCosmWasmClient, txSigner: string): Bas const executeContractMsgs: MsgExecuteContractEncodeObject[] = [] for (let i = 0; i < batchCount; i++) { const msg = { - mint: { token_uri: `${baseUri}/${i + 1}` }, + mint: { token_uri: `${baseUri}/${i + startFrom}` }, } const executeContractMsg: MsgExecuteContractEncodeObject = { typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract', @@ -282,10 +287,10 @@ export const baseMinter = (client: SigningCosmWasmClient, txSigner: string): Bas } } - const batchMint = (baseUri: string, batchCount: number): CustomMessage => { + const batchMint = (baseUri: string, batchCount: number, startFrom: number): CustomMessage => { const msg: Record[] = [] for (let i = 0; i < batchCount; i++) { - msg.push({ mint: { token_uri: `${baseUri}/${i + 1}` } }) + msg.push({ mint: { token_uri: `${baseUri}/${i + startFrom}` } }) } return { sender: txSigner, diff --git a/pages/collections/create.tsx b/pages/collections/create.tsx index e25ac80..c8efbc3 100644 --- a/pages/collections/create.tsx +++ b/pages/collections/create.tsx @@ -449,7 +449,12 @@ const CollectionCreationPage: NextPage = () => { setBaseTokenUri(baseUri) const result = await baseMinterContract .use(baseMinterDetails?.existingBaseMinter as string) - ?.batchMint(wallet.address, `ipfs://${baseUri}`, uploadDetails.assetFiles.length) + ?.batchMint( + wallet.address, + `ipfs://${baseUri}`, + uploadDetails.assetFiles.length, + parseInt(uploadDetails.assetFiles[0].name.split('.')[0]), + ) console.log(result) return result }) @@ -698,7 +703,12 @@ const CollectionCreationPage: NextPage = () => { .promise( baseMinterContract .use(data.baseMinterAddress) - ?.batchMint(wallet.address, baseUri, uploadDetails?.assetFiles.length as number) as Promise, + ?.batchMint( + wallet.address, + baseUri, + uploadDetails?.assetFiles.length as number, + parseInt(uploadDetails?.assetFiles[0].name.split('.')[0] as string), + ) as Promise, { loading: 'Minting tokens...', success: (result) => {