diff --git a/package.json b/package.json index 6609750..13f0a7a 100644 --- a/package.json +++ b/package.json @@ -1,85 +1,4 @@ { -<<<<<<< HEAD - "name": "studio", - "version": "0.1.0", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint" - }, - "dependencies": { - "@google/model-viewer": "^4.0.0", - "@hookform/resolvers": "^3.6.0", - "@metaplex-foundation/js": "^0.20.1", - "@radix-ui/react-checkbox": "^1.0.4", - "@radix-ui/react-dialog": "^1.0.5", - "@radix-ui/react-label": "^2.0.2", - "@radix-ui/react-navigation-menu": "^1.1.4", - "@radix-ui/react-radio-group": "^1.1.3", - "@radix-ui/react-select": "^2.1.2", - "@radix-ui/react-slot": "^1.0.2", - "@react-three/drei": "^9.120.3", - "@react-three/fiber": "^8.17.10", - "@react-three/postprocessing": "^2.15.1", - "@readyplayerme/react-avatar-creator": "^0.5.0", - "@readyplayerme/visage": "^5.1.0", - "@solana/wallet-adapter-base": "^0.9.23", - "@solana/wallet-adapter-react": "^0.15.35", - "@solana/wallet-adapter-react-ui": "^0.9.35", - "@solana/wallet-adapter-wallets": "^0.19.32", - "@solana/web3.js": "^1.98.0", - "@tanstack/react-query": "^5.51.23", - "@uploadthing/react": "^6.6.0", - "@web3modal/wagmi": "^5.0.11", - "axios": "^1.7.9", - "canvas-confetti": "^1.9.3", - "class-variance-authority": "^0.7.0", - "clsx": "^2.1.1", - "form-data": "^4.0.1", - "formidable": "^3.5.2", - "install": "^0.13.0", - "lucide-react": "^0.394.0", - "next": "14.2.4", - "next-auth": "^4.24.10", - "nft.storage": "^7.1.1", - "permissionless": "^0.1.31", -<<<<<<< HEAD - "postprocessing": "^6.36.4", -======= - "postprocessing": "^6.36.5", ->>>>>>> cdd9263 (chore: fix build issue) - "react": "^18", - "react-dom": "^18", - "react-form-repeater": "^0.3.0", - "react-hook-form": "^7.52.0", - "react-toastify": "^10.0.5", - "tailwind-merge": "^2.3.0", - "tailwindcss-animate": "^1.0.7", - "three": "^0.171.0", - "three-mesh-bvh": "^0.5.24", - "uploadthing": "^6.12.0", - "uuid": "^10.0.0", - "viem": "^2.19.4", - "wagmi": "^2.12.5", - "zod": "^3.23.8" - }, - "devDependencies": { - "@types/canvas-confetti": "^1.6.4", - "@types/formidable": "^3.4.5", - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", - "@types/three": "^0.152.1", - "@types/uuid": "^10.0.0", - "eslint": "^8", - "eslint-config-next": "14.2.4", - "postcss": "^8", - "tailwindcss": "^3.4.1", - "typescript": "^5" - } -======= "name": "studio", "version": "0.1.0", "private": true, @@ -161,5 +80,4 @@ "optionalDependencies": { "prebuild-install": "^7.1.1" } ->>>>>>> cd51a59 (chorE: update files) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1b2ff9b..1463f0d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,10 +1,4 @@ -<<<<<<< HEAD -<<<<<<< HEAD -======= -lockfileVersion: '9.0' -======= lockfileVersion: '6.0' ->>>>>>> cdd9263 (chore: fix build issue) settings: autoInstallPeers: true @@ -17430,9 +17424,4 @@ packages: dependencies: '@types/react': 18.3.18 react: 18.3.1 -<<<<<<< HEAD - use-sync-external-store: 1.2.0(react@18.3.1) ->>>>>>> 1adb8d0 (chore: work on solana integration) -======= - dev: false ->>>>>>> cdd9263 (chore: fix build issue) + dev: false \ No newline at end of file diff --git a/src/app/api/upload/route.ts b/src/app/api/upload/route.ts index b978d8d..e240231 100644 --- a/src/app/api/upload/route.ts +++ b/src/app/api/upload/route.ts @@ -1,25 +1,3 @@ -<<<<<<< HEAD -import { NextResponse } from "next/server"; -import { writeFile } from "fs/promises"; -import { join } from "path"; - -// Remove this old config export -// export const config = { -// api: { -// bodyParser: false, -// }, -// }; - -// Add this new config for large file uploads -export const runtime = "nodejs"; -export const dynamic = "force-dynamic"; -export const maxDuration = 60; - -export async function POST(request: Request) { - try { - const formData = await request.formData(); - const file = formData.get("file") as File; -======= import { NextRequest, NextResponse } from "next/server"; import formidable from "formidable"; import fs from "fs"; @@ -38,22 +16,11 @@ async function POST(req: NextRequest) { // Convert the request to a NodeJS readable stream const data = await req.formData(); const file = data.get("file") as File; ->>>>>>> cdd9263 (chore: fix build issue) if (!file) { return NextResponse.json({ error: "No file uploaded" }, { status: 400 }); } -<<<<<<< HEAD - const bytes = await file.arrayBuffer(); - const buffer = Buffer.from(bytes); - - // Upload to Pinata - const formDataForPinata = new FormData(); - formDataForPinata.append("file", new Blob([buffer]), file.name); - - const pinataRes = await fetch( -======= // Create a temporary file const bytes = await file.arrayBuffer(); const buffer = Buffer.from(bytes); @@ -68,31 +35,21 @@ async function POST(req: NextRequest) { // Upload to Pinata const pinataRes = await axios.post( ->>>>>>> cdd9263 (chore: fix build issue) "https://api.pinata.cloud/pinning/pinFileToIPFS", + formData, { - method: "POST", headers: { + "Content-Type": `multipart/form-data; boundary=${formData.getBoundary()}`, pinata_api_key: process.env.PINATA_API_KEY!, pinata_secret_api_key: process.env.PINATA_SECRET_KEY!, }, - body: formDataForPinata, } ); -<<<<<<< HEAD - if (!pinataRes.ok) { - throw new Error("Failed to upload to Pinata"); - } - - const data = await pinataRes.json(); - return NextResponse.json(data); -======= // Clean up the temporary file fs.unlinkSync(tempFilePath); return NextResponse.json(pinataRes.data); ->>>>>>> cdd9263 (chore: fix build issue) } catch (error) { console.error("Upload error:", error); return NextResponse.json( diff --git a/src/components/BrandForm.tsx b/src/components/BrandForm.tsx index 43dec09..33ed8ff 100644 --- a/src/components/BrandForm.tsx +++ b/src/components/BrandForm.tsx @@ -21,13 +21,9 @@ import { useForm } from "react-hook-form"; import { z } from "zod"; import { toast, ToastContainer } from "react-toastify"; import { useRouter } from "next/navigation"; -import { useAccount, useChainId, useWalletClient } from "wagmi"; -import { NFTStorage } from "nft.storage"; -import { Hex, createPublicClient, http } from "viem"; -import { base } from "viem/chains"; -import { v4 as uuidv4 } from 'uuid'; -import Simplestore from "@/lib/Simplestore.json"; -import tradehub from "@/lib/tradehub.json"; +import { useAccount } from "wagmi"; +import axios from "axios"; +import { v4 as uuidv4 } from "uuid"; import { clusterApiUrl, Connection, PublicKey } from "@solana/web3.js"; import { useWallet } from "@solana/wallet-adapter-react"; import { Metaplex, walletAdapterIdentity } from "@metaplex-foundation/js"; @@ -142,13 +138,14 @@ export default function CreateBrand({ const [cid, setCid] = useState(""); const [cidCover, setCidCover] = useState(""); const [uploading, setUploading] = useState(false); - const [uploadingCover, setUploadingCover] = useState(false); const [loading, setLoading] = useState(false); const [imageError, setImageError] = useState(false); const [logoUploading, setLogoUploading] = useState(false); const [coverUploading, setCoverUploading] = useState(false); + const wallet = useWallet(); const { publicKey, connected } = wallet; + const inputFile = useRef(null); const connection = new Connection(clusterApiUrl("devnet")); const metaplex = useMemo(() => { @@ -157,32 +154,6 @@ export default function CreateBrand({ } }, [wallet, connection]); - const wallet = useWallet(); - const { publicKey, connected } = wallet; - const inputFile = useRef(null); - - const API_KEY = process.env.NEXT_PUBLIC_STORAGE_API; - if (!API_KEY) { - throw new Error("Missing NFT.storage API key"); - } - - const initializeNFTStorage = () => { - try { - return new NFTStorage({ token: API_KEY }); - } catch (error) { - console.error("Failed to initialize NFT.storage:", error); - throw error; - } - }; - - const client = initializeNFTStorage(); - - // Initialize public client - const publicClient = createPublicClient({ - chain: base, - transport: http(), - }); - const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { @@ -267,84 +238,12 @@ export default function CreateBrand({ } }; - const createAndUploadMetadata = async ( - brandData: any, - isCollection: boolean - ) => { - try { - const metadata = { - name: isCollection ? `${brandData.name} Collection` : brandData.name, - symbol: isCollection ? "BRAND" : "NFT", - description: brandData.description, - image: brandData.logo_image, // Your IPFS logo URL - external_url: brandData.website, - attributes: [ - { - trait_type: "Brand Representative", - value: brandData.representative, - }, - { - trait_type: "Region", - value: brandData.elevate_region || "Global", - }, - ], - properties: { - files: [ - { - uri: brandData.logo_image, - type: "image/png", // adjust based on your image type - }, - ], - category: "image", - }, - }; - - // Upload to NFT.storage - // const client = new NFTStorage({ token: API_KEY }); // You already have this setup - const metadataBlob = new Blob([JSON.stringify(metadata)], { - type: "application/json", - }); - const cid = await client.storeBlob(metadataBlob); - - return `ipfs://${cid}`; - } catch (error) { - console.error("Error uploading metadata:", error); - throw error; - } - }; - const getWebsiteUrl = () => { const websiteLink = socialLinks.find((link) => link.platform === "website"); return websiteLink?.url || ""; }; - // Contract Deployment Functions const deployContract = async () => { - // if (!walletClient) { - // throw new Error("Wallet client not available"); - // } - - // try { - // const hash = await walletClient.deployContract({ - // abi: Simplestore.abi, - // bytecode: Simplestore.bytecode as Hex, - // account: walletAddress, - // args: ["0xf5d0A178a61A2543c98FC4a73E3e78a097DBD9EE"], - // }); - - // if (!hash) { - // throw new Error("Failed to execute deploy contract transaction"); - // } - - // const txn = await publicClient.waitForTransactionReceipt({ hash }); - // setIsDeployed(true); - // return txn.contractAddress; - // } catch (error) { - // console.error("Deployment error:", error); - // toast.error("Error deploying AccessMaster contract: " + error); - // throw error; - // } - if (!publicKey || !metaplex) { throw new Error("Wallet not connected"); } @@ -352,13 +251,12 @@ export default function CreateBrand({ console.log(getWebsiteUrl()); try { - // Create and upload metadata const metadata = { name: form.getValues("name"), symbol: "BRAND", description: form.getValues("description"), - image: `ipfs://${cid}`, // Your logo IPFS URI - external_url: getWebsiteUrl(), + image: `ipfs://${cid}`, + external_url: "", attributes: [ { trait_type: "Brand Representative", @@ -371,25 +269,35 @@ export default function CreateBrand({ ], }; - const metadataBlob = new Blob([JSON.stringify(metadata)], { - type: "application/json", + // Upload metadata to Pinata + const response = await fetch("/api/upload-json", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ content: metadata }), }); - const metadataCid = await createAndUploadMetadata(metadataBlob, false); - const metadataUri = `ipfs://${metadataCid}`; - // Create NFT Collection - const collectionNft = await metaplex.nfts().createSft({ - name: `${form.getValues("name")} Collection`, - symbol: "BRAND", + if (!response.ok) { + const errorData = await response.json(); + throw new Error(`Upload failed: ${JSON.stringify(errorData)}`); + } + + const data = await response.json(); + const metadataUri = `ipfs://${data.IpfsHash}`; + + // Create NFT Collection using Metaplex + const { nft: collectionNft } = await metaplex.nfts().create({ uri: metadataUri, - sellerFeeBasisPoints: 500, // 5% royalties + name: form.getValues("name"), + sellerFeeBasisPoints: 500, + symbol: "BRAND", isCollection: true, - collectionAuthority: publicKey as any, - updateAuthority: publicKey as any, + updateAuthority: metaplex.identity(), }); setIsDeployed(true); - return collectionNft.mintAddress.toString(); + return collectionNft.address.toString(); } catch (error) { console.error("Deployment error:", error); toast.error("Error deploying collection: " + error); @@ -401,67 +309,55 @@ export default function CreateBrand({ platformFee: number, memory_name: string ) => { - // if (!walletClient) { - // throw new Error("Wallet client not available"); - // } - // const AccessMasterAddress = localStorage.getItem("AccessMasterAddress"); - // try { - // const hash = await walletClient.deployContract({ - // abi: tradehub.abi, - // bytecode: tradehub.bytecode as Hex, - // account: walletAddress, - // args: [platformFee, memory_name, `${AccessMasterAddress}`], - // }); - - // if (!hash) { - // throw new Error("Failed to execute deploy contract transaction"); - // } - - // const txn = await publicClient.waitForTransactionReceipt({ hash }); - // setIsDeployed(true); - // return txn.contractAddress; - // } catch (error) { - // console.error("Deployment error:", error); - // toast.error("Error deploying TradeHub contract: " + error); - // throw error; - // } - if (!publicKey || !metaplex) { throw new Error("Wallet not connected"); } try { - // Create trading collection metadata const metadata = { name: memory_name, symbol: "TRADE", description: `Trading collection for ${form.getValues("name")}`, image: `ipfs://${cidCover}`, external_url: getWebsiteUrl(), + attributes: [ + { + trait_type: "Platform Fee", + value: platformFee.toString(), + }, + ], }; - const metadataBlob = new Blob([JSON.stringify(metadata)], { - type: "application/json", + const response = await fetch("/api/upload-json", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ content: metadata }), }); - const metadataCid = await createAndUploadMetadata(metadataBlob, true); - const metadataUri = `ipfs://${metadataCid}`; - // Create Trading Collection - const tradingCollection = await metaplex.nfts().createSft({ - name: memory_name, - symbol: "TRADE", + if (!response.ok) { + const errorData = await response.json(); + throw new Error(`Upload failed: ${JSON.stringify(errorData)}`); + } + + const data = await response.json(); + const metadataUri = `ipfs://${data.IpfsHash}`; + + const { nft: tradingCollection } = await metaplex.nfts().create({ uri: metadataUri, + name: memory_name, sellerFeeBasisPoints: platformFee * 100, + symbol: "TRADE", isCollection: true, - collectionAuthority: publicKey as any, - updateAuthority: publicKey as any, + updateAuthority: metaplex.identity(), }); setIsDeployed(true); return { - mintAddress: tradingCollection.mintAddress.toString(), + mintAddress: tradingCollection.address.toString(), metadataAddress: tradingCollection.metadataAddress.toString(), - tokenAddress: tradingCollection.tokenAddress?.toString() || null, + // tokenAddress: tradingCollection.tokenAddress?.toString() || null, }; } catch (error) { console.error("Deployment error:", error); @@ -493,34 +389,12 @@ export default function CreateBrand({ } }; - const TradehubDeploy = async (): Promise => { - // try { - // const address = await deployTradehubContract(30, "NFT BAZAAR"); - // localStorage.setItem("TradehubAddress", address as `0x${string}`); - // console.log("TradeHub Contract deployed at:", address); - // return address !== null; - // } catch (error) { - // console.error("Error deploying TradeHub contract:", error); - // toast.error("Failed to deploy TradeHub contract"); - // return false; - // } - - try { - const addresses = await deployTradehubContract(30, "NFT BAZAAR"); - localStorage.setItem("TradehubAddress", addresses.mintAddress); - localStorage.setItem( - "TradehubMetadataAddress", - addresses.metadataAddress - ); - if (addresses.tokenAddress) { - localStorage.setItem("TradehubTokenAddress", addresses.tokenAddress); - } - console.log("TradeHub Collection deployed at:", addresses.mintAddress); - return true; - } catch (error) { - console.error("Error deploying TradeHub collection:", error); - toast.error("Failed to deploy TradeHub collection"); - return false; + const mintNFTToCollection = async ( + collectionAddress: string, + metadata: any + ) => { + if (!publicKey || !metaplex) { + throw new Error("Wallet not connected"); } try { @@ -581,10 +455,6 @@ export default function CreateBrand({ }; async function onSubmit(values: z.infer) { - // if (!account.addresses) { - // toast.warning("Connect your wallet"); - // return; - // } if (!publicKey || !metaplex) { throw new Error("Wallet not connected"); } @@ -802,11 +672,9 @@ export default function CreateBrand({ ) : ( - // Your form content
- {/* Basic Information */} - {/* Image Upload Sections */}

Upload Logo*

@@ -943,7 +810,6 @@ export default function CreateBrand({
- {/* Cover Image Upload */}

Upload Cover Image*

@@ -1015,7 +881,6 @@ export default function CreateBrand({
- {/* Contact Information */} - {/* Social Links Section */}
Social Links @@ -1167,7 +1031,6 @@ export default function CreateBrand({ )}
- {/* WebXR Experience Section */}
- {/* Elevate Program Section */}
@@ -1293,4 +1153,4 @@ export default function CreateBrand({ ); -} +} \ No newline at end of file