/** * Unified Video Upload and Mint Script * * This script demonstrates the one-step method to upload a video and mint an NFT * when processing is complete. * * Usage: * 1. Create a .env file and set the following environment variables: * - PRIVATE_KEY: Private key of the NFT holder * - API_KEY: GoodTake API key (optional) * * 2. Prepare a test video file and place it in scripts/assets/ directory * * 3. Run the script: * npm run upload-and-mint * or * yarn upload-and-mint */ import { GoTakeSDK, NetworkId, VideoStatus } from "../src"; import * as dotenv from 'dotenv'; import { ethers } from 'ethers'; import * as fs from 'fs'; import * as path from 'path'; import { Blob } from 'fetch-blob'; import File from 'fetch-blob/file'; dotenv.config(); // Utility function: Convert file system file to browser File object function createFileFromPath(filePath: string): File { const fileName = path.basename(filePath); const fileBuffer = fs.readFileSync(filePath); const fileBlob = new Blob([fileBuffer]); return new File([fileBlob], fileName, { type: getMimeType(fileName) }); } // Utility function: Get MIME type based on file extension function getMimeType(fileName: string): string { const ext = fileName.split('.').pop()?.toLowerCase(); const mimeTypes: Record = { 'mp4': 'video/mp4', 'mov': 'video/quicktime', 'avi': 'video/x-msvideo', 'webm': 'video/webm' }; return mimeTypes[ext || ''] || 'application/octet-stream'; } async function main() { // Check required environment variables if (!process.env.PRIVATE_KEY) { throw new Error("PRIVATE_KEY is not defined in environment variables. Please set it in your .env file"); } const videoFilePath = path.join(__dirname, 'assets', 'sample-video.mp4'); if (!fs.existsSync(videoFilePath)) { throw new Error(`Test video file not found: ${videoFilePath}`); } try { console.log("=== GoodTake One-Step Upload and Mint Demo ==="); // Create Provider and Signer const rpcUrl = "https://sepolia.base.org"; const ethersProvider = new ethers.providers.JsonRpcProvider(rpcUrl); const ethersSigner = new ethers.Wallet(process.env.PRIVATE_KEY, ethersProvider); const userAddress = await ethersSigner.getAddress(); console.log(`Using address: ${userAddress}`); // Initialize SDK const sdk = new GoTakeSDK({ network: NetworkId.BASE_SEPOLIA, provider: ethersProvider, signer: ethersSigner, apiEndpoint: process.env.API_ENDPOINT || 'https://api.goodtake.io', apiKey: process.env.API_KEY }); console.log("SDK initialized successfully"); // Step 1: Check and create TBA if needed (done automatically by the unified method) console.log("\nChecking TBA account..."); // Step 2: Prepare video file console.log("\nPreparing video file..."); const videoFile = createFileFromPath(videoFilePath); console.log(`Video file: ${videoFile.name} (${videoFile.size} bytes)`); const videoMetadata = { title: "One-Step Upload Demo", description: "This video was uploaded and minted in one step", tags: ["demo", "sdk", "one-step"], creator: userAddress }; // Step 3: Use the unified method to upload and mint console.log("\n=== Starting Unified Upload and Mint Process ==="); console.log("This will automatically upload, monitor, and mint when ready"); // Track process completion let processCompleted = false; // Use the unified method const videoId = await sdk.uploadAndMintWhenReady( videoFile, videoMetadata, { statusCallback: (status) => { console.log(`Status update: ${status.status}, Progress: ${status.progress || 'unknown'}%`); if (status.status === VideoStatus.COMPLETED) { console.log("\n=== Process Completed Successfully ==="); console.log(`Video ID: ${videoId}`); if (status.mintInfo) { console.log(`NFT Token ID: ${status.mintInfo.tokenId}`); console.log(`NFT Transaction: ${status.mintInfo.transactionHash}`); } if (status.assetInfo?.playbackUrl) { console.log(`Playback URL: ${status.assetInfo.playbackUrl}`); } processCompleted = true; } else if (status.status === VideoStatus.ERROR) { console.error(`Error: ${status.error?.message || 'Unknown error'}`); processCompleted = true; } }, autoMint: true // Automatically mint when video is ready } ); console.log(`Process started! Video ID: ${videoId}`); console.log("The process will continue in the background."); console.log("Status updates will be displayed via the callback."); // Wait for process to complete or timeout after 10 minutes const timeout = 10 * 60 * 1000; // 10 minutes const startTime = Date.now(); while (!processCompleted && (Date.now() - startTime < timeout)) { await new Promise(resolve => setTimeout(resolve, 5000)); // Check every 5 seconds // Check status directly if needed if (!processCompleted && (Date.now() - startTime) % 30000 < 5000) { // Every 30 seconds const status = await sdk.getVideoStatus(videoId); console.log(`Current status: ${status.status}`); } } if (!processCompleted) { console.log("\nTimeout reached but process is still running in the background."); console.log(`You can check the status later using the video ID: ${videoId}`); } } catch (error) { console.error("Error during upload and mint process:"); console.error(error); process.exitCode = 1; } } main().catch(error => { console.error("Error executing script:"); console.error(error); process.exitCode = 1; });