import { ethers } from 'ethers'; import { GoTakeSDK, NetworkId, getNetworkById, getNetworkByName } from '../src'; import { TokenUtils } from '../src/utils/token-utils'; import { getNetworkKeyFromId } from '../src/utils/addresses'; import * as dotenv from 'dotenv'; // Load environment variables dotenv.config(); /** * Simple preflight checks - only check balance and contract existence */ async function preflightChecks(sdk: GoTakeSDK, userAddress: string): Promise { console.log('\n๐Ÿ” Running preflight checks...'); console.log('==============================='); try { // 1. Check ETH balance console.log('๐Ÿ’ฐ Checking account balance...'); const balance = await sdk.provider.getBalance(userAddress); const balanceETH = parseFloat(ethers.utils.formatEther(balance)); const minETH = 0.001; // Minimum 0.001 ETH needed console.log(` Balance: ${balanceETH.toFixed(4)} ETH`); if (balanceETH < minETH) { console.log(` โŒ Insufficient balance, at least ${minETH} ETH needed for transactions`); console.log(' ๐Ÿ’ฐ Get test ETH: https://www.coinbase.com/faucets/base-ethereum-sepolia-faucet'); return false; } else { console.log(' โœ… ETH balance sufficient'); } // 2. Check contract deployment console.log('๐Ÿ“‹ Verifying VideoPayment contract...'); await sdk.videoPayment.init(); // Debug: Print the actual contract address being used const wrapper = (sdk.videoPayment as any)._videoPaymentWrapper; if (wrapper) { const contractAddress = wrapper.getContractAddress('videoPayment'); console.log(` ๐Ÿ“ Using VideoPayment contract: ${contractAddress}`); } console.log(' โœ… VideoPayment contract initialized'); console.log('\nโœ… All preflight checks passed!'); return true; } catch (error) { console.error('โŒ Preflight check failed:', error.message); return false; } } /** * Simple content purchaser that works with the actual SDK */ class ContentPurchaser { public sdk: GoTakeSDK; constructor(network: NetworkId | string, private signer: ethers.Signer) { // Initialize SDK with proper options this.sdk = new GoTakeSDK({ network: network, signer: this.signer }); } /** * Purchase single content with ETH */ async purchaseWithETH(contentId: number): Promise { console.log(`\n๐Ÿ›’ Purchasing Content ID: ${contentId} with ETH`); console.log('='.repeat(50)); try { // Check if user already has permission const hasPermission = await this.sdk.videoPayment.hasViewPermission(contentId); if (hasPermission) { console.log('โš ๏ธ You already have access to this content'); return; } // Get content purchase information first console.log('\n๐Ÿ“‹ Getting content purchase information...'); const contentInfo = await this.sdk.videoPayment.getContentInfo(contentId); console.log(` Content Price: ${ethers.utils.formatEther(contentInfo.nativePrice)} ETH`); console.log(` View Count: ${contentInfo.viewCount} views`); console.log(` Active: ${contentInfo.isActive ? 'Yes' : 'No'}`); if (!contentInfo.isActive) { console.log('โŒ This content is not available for purchase'); return; } // Check if ETH is supported const ethSupported = ethers.constants.AddressZero in contentInfo.tokenPrices; if (!ethSupported) { console.log('โŒ ETH payment is not supported for this content'); return; } // Get optimal gas configuration console.log('\nโ›ฝ Getting optimal gas configuration...'); const gasPrices = await this.sdk.getGasPrice({ multiplier: 1.2, // 20% buffer for base fee priorityMultiplier: 1.1 // 10% buffer for priority fee }); console.log(` Base Fee: ${gasPrices.baseFeePerGas ? ethers.utils.formatUnits(gasPrices.baseFeePerGas, "gwei") + ' gwei' : 'N/A'}`); console.log(` Max Fee: ${ethers.utils.formatUnits(gasPrices.maxFeePerGas, "gwei")} gwei`); console.log(` Priority Fee: ${gasPrices.maxPriorityFeePerGas ? ethers.utils.formatUnits(gasPrices.maxPriorityFeePerGas, "gwei") + ' gwei' : 'N/A'}`); // Create gas configuration const gasConfig = { maxFeePerGas: gasPrices.maxFeePerGas, maxPriorityFeePerGas: gasPrices.maxPriorityFeePerGas // Let system auto-estimate gas limit }; // Make the purchase with gas configuration console.log('\n๐Ÿ’ณ Initiating Purchase Transaction...'); const result = await this.sdk.videoPayment.purchaseContent(contentId, 'ETH', undefined, { gasConfig }); console.log('\nโœ… Purchase Successful!'); console.log(` Transaction Hash: ${result.transactionHash}`); console.log(` Content ID: ${result.contentId}`); // Verify purchase const verifyPermission = await this.sdk.videoPayment.hasViewPermission(contentId); console.log(` Purchase Verified: ${verifyPermission ? 'Yes' : 'No'}`); } catch (error) { console.error('\nโŒ Purchase Failed:', error.message); throw error; } } /** * Purchase single content with ERC20 token */ async purchaseWithToken(contentId: number, tokenAddress?: string): Promise { console.log(`\n๐Ÿ›’ Purchasing Content ID: ${contentId} with Token`); console.log('='.repeat(50)); try { // Check if user already has permission const hasPermission = await this.sdk.videoPayment.hasViewPermission(contentId); if (hasPermission) { console.log('โš ๏ธ You already have access to this content'); return; } // Get content purchase information first console.log('\n๐Ÿ“‹ Getting content purchase information...'); const contentInfo = await this.sdk.videoPayment.getContentInfo(contentId); console.log(` Content Active: ${contentInfo.isActive ? 'Yes' : 'No'}`); console.log(` View Count: ${contentInfo.viewCount} views`); if (!contentInfo.isActive) { console.log('โŒ This content is not available for purchase'); return; } // Show available tokens and prices const availableTokens = Object.keys(contentInfo.tokenPrices).filter( token => token !== ethers.constants.AddressZero ); if (availableTokens.length === 0) { console.log('โŒ No ERC20 tokens are supported for this content'); return; } console.log('\n๐Ÿ’ฐ Available ERC20 payment options:'); availableTokens.forEach((token, index) => { const price = contentInfo.tokenPrices[token]; console.log(` ${index + 1}. Token: ${token}`); // Get network key for proper token formatting const networkKey = getNetworkKeyFromId(this.sdk.networkId!); const formattedPrice = TokenUtils.formatTokenAmountWithSymbol(price, token, networkKey); console.log(` Price: ${formattedPrice}`); }); // Auto-select token if not provided const finalTokenAddress = tokenAddress || availableTokens[0]; console.log(`\n Using Token: ${finalTokenAddress}`); // Get optimal gas configuration console.log('\nโ›ฝ Getting optimal gas configuration...'); const gasPrices = await this.sdk.getGasPrice({ multiplier: 1.2, // 20% buffer for base fee priorityMultiplier: 1.1 // 10% buffer for priority fee }); console.log(` Base Fee: ${gasPrices.baseFeePerGas ? ethers.utils.formatUnits(gasPrices.baseFeePerGas, "gwei") + ' gwei' : 'N/A'}`); console.log(` Max Fee: ${ethers.utils.formatUnits(gasPrices.maxFeePerGas, "gwei")} gwei`); console.log(` Priority Fee: ${gasPrices.maxPriorityFeePerGas ? ethers.utils.formatUnits(gasPrices.maxPriorityFeePerGas, "gwei") + ' gwei' : 'N/A'}`); // Create gas configuration const gasConfig = { maxFeePerGas: gasPrices.maxFeePerGas, maxPriorityFeePerGas: gasPrices.maxPriorityFeePerGas // Let system auto-estimate gas limit }; // Make the purchase with gas configuration console.log('\n๐Ÿ’ณ Initiating Token Purchase Transaction...'); const result = await this.sdk.videoPayment.purchaseContent(contentId, 'ERC20', finalTokenAddress, { gasConfig }); console.log('\nโœ… Purchase Successful!'); console.log(` Transaction Hash: ${result.transactionHash}`); console.log(` Content ID: ${result.contentId}`); // Verify purchase const verifyPermission = await this.sdk.videoPayment.hasViewPermission(contentId); console.log(` Purchase Verified: ${verifyPermission ? 'Yes' : 'No'}`); } catch (error) { console.error('\nโŒ Purchase Failed:', error.message); throw error; } } /** * Check content information and purchase options */ async checkContent(contentId: number): Promise { console.log(`\n๐Ÿ“‹ Content Information for ID: ${contentId}`); console.log('='.repeat(50)); try { // Get content purchase information const contentInfo = await this.sdk.videoPayment.getContentInfo(contentId); console.log('\n๐Ÿ“Š Content Details:'); console.log(` Active: ${contentInfo.isActive ? 'Yes โœ…' : 'No โŒ'}`); console.log(` View Count: ${contentInfo.viewCount} views`); console.log('\n๐Ÿ’ฐ Payment Options:'); Object.entries(contentInfo.tokenPrices).forEach(([token, price]) => { if (token === ethers.constants.AddressZero) { console.log(` ๐Ÿ’Ž ETH: ${ethers.utils.formatEther(price)} ETH`); } else { // Get network key for proper token formatting const networkKey = getNetworkKeyFromId(this.sdk.networkId!); const formattedPrice = TokenUtils.formatTokenAmountWithSymbol(price, token, networkKey); console.log(` ๐Ÿช™ ${token}: ${formattedPrice}`); } }); // Check user permissions const hasPermission = await this.sdk.videoPayment.hasViewPermission(contentId); console.log(`\n๐Ÿ” Your Access: ${hasPermission ? 'Yes โœ…' : 'No โŒ'}`); if (hasPermission) { const permissions = await this.sdk.videoPayment.getMyPermissions(contentId); console.log(` Remaining Views: ${permissions.remainingViews.toNumber()}`); console.log(` Purchase Time: ${new Date(permissions.purchaseTime.toNumber() * 1000).toLocaleString()}`); console.log(` Permission Valid: ${permissions.isValid ? 'Yes' : 'No'}`); } else if (contentInfo.isActive) { console.log('\n๐Ÿ’ก Purchase Suggestions:'); if (ethers.constants.AddressZero in contentInfo.tokenPrices) { console.log(` ETH: npm run purchase-content buy ${contentId}`); } const erc20Tokens = Object.keys(contentInfo.tokenPrices).filter( token => token !== ethers.constants.AddressZero ); if (erc20Tokens.length > 0) { console.log(` Token: npm run purchase-content token ${contentId} ${erc20Tokens[0]}`); } } } catch (error) { console.error('โŒ Failed to get content info:', error.message); throw error; } } /** * Smart purchase: automatically detect and purchase with all available payment methods */ async smartPurchase(contentId: number): Promise { console.log(`\n๐Ÿง  Smart Purchase for Content ID: ${contentId}`); console.log('='.repeat(60)); try { // Step 1: Check current access const hasPermission = await this.sdk.videoPayment.hasViewPermission(contentId); if (hasPermission) { console.log('โš ๏ธ You already have access to this content'); const permissions = await this.sdk.videoPayment.getMyPermissions(contentId); console.log(` Remaining Views: ${permissions.remainingViews.toNumber()}`); return; } // Step 2: Get content info and payment options console.log('\n๐Ÿ“‹ Analyzing content and payment options...'); const contentInfo = await this.sdk.videoPayment.getContentInfo(contentId); if (!contentInfo.isActive) { console.log('โŒ This content is not available for purchase'); return; } console.log(` View Count: ${contentInfo.viewCount} views`); // Step 3: Identify available payment methods const ethSupported = ethers.constants.AddressZero in contentInfo.tokenPrices; const erc20Tokens = Object.keys(contentInfo.tokenPrices).filter( token => token !== ethers.constants.AddressZero ); console.log('\n๐Ÿ’ฐ Available Payment Methods:'); if (ethSupported) { const ethPrice = contentInfo.tokenPrices[ethers.constants.AddressZero]; console.log(` ๐Ÿ’Ž ETH: ${ethers.utils.formatEther(ethPrice)} ETH`); } erc20Tokens.forEach(token => { const price = contentInfo.tokenPrices[token]; // Get network key for proper token formatting const networkKey = getNetworkKeyFromId(this.sdk.networkId!); const formattedPrice = TokenUtils.formatTokenAmountWithSymbol(price, token, networkKey); console.log(` ๐Ÿช™ Token: ${formattedPrice} (${token.slice(0, 10)}...)`); }); // Step 4: Purchase with ETH if available if (ethSupported) { console.log('\n๐Ÿš€ Attempting ETH purchase...'); try { const ethResult = await this.sdk.videoPayment.purchaseContent(contentId, 'ETH'); console.log(` โœ… ETH Purchase Successful! TX: ${ethResult.transactionHash}`); } catch (error) { console.log(` โŒ ETH Purchase Failed: ${error.message}`); } } // Step 5: Purchase with each ERC20 token for (const tokenAddress of erc20Tokens) { console.log(`\n๐Ÿช™ Attempting ERC20 purchase with ${tokenAddress.slice(0, 10)}...`); try { const tokenResult = await this.sdk.videoPayment.purchaseContent(contentId, 'ERC20', tokenAddress); console.log(` โœ… ERC20 Purchase Successful! TX: ${tokenResult.transactionHash}`); } catch (error) { console.log(` โŒ ERC20 Purchase Failed: ${error.message}`); } } // Step 6: Final verification console.log('\n๐Ÿ” Final Access Verification...'); const finalPermission = await this.sdk.videoPayment.hasViewPermission(contentId); if (finalPermission) { const permissions = await this.sdk.videoPayment.getMyPermissions(contentId); console.log(` โœ… Purchase completed successfully!`); console.log(` Remaining Views: ${permissions.remainingViews.toNumber()}`); } else { console.log(` โŒ No successful purchases - access not granted`); } } catch (error) { console.error('\nโŒ Smart Purchase Failed:', error.message); throw error; } } /** * Batch purchase multiple content items */ async batchPurchase(contentIds: number[]): Promise { console.log(`\n๐Ÿ›’ Batch Purchase: ${contentIds.length} items`); console.log('='.repeat(50)); try { const result = await this.sdk.videoPayment.batchPurchaseContent(contentIds, 'ETH'); console.log('\nโœ… Batch Purchase Successful!'); console.log(` Transaction Hash: ${result.transactionHash}`); console.log(` Content IDs: ${contentIds.join(', ')}`); // Verify purchases let successCount = 0; for (const contentId of contentIds) { const hasPermission = await this.sdk.videoPayment.hasViewPermission(contentId); if (hasPermission) { successCount++; } } console.log(`\n๐Ÿ“Š Batch Purchase Summary:`); console.log(` Total Items: ${contentIds.length}`); console.log(` Successful: ${successCount}`); console.log(` Success Rate: ${((successCount / contentIds.length) * 100).toFixed(1)}%`); } catch (error) { console.error('\nโŒ Batch Purchase Failed:', error.message); throw error; } } /** * Full test purchase: query prices and purchase with all available methods */ async fullTestPurchase(contentId: number): Promise { console.log(`\n๐Ÿงช Full Test Purchase for Content ID: ${contentId}`); console.log('='.repeat(60)); try { // Step 1: Check current access const hasPermission = await this.sdk.videoPayment.hasViewPermission(contentId); if (hasPermission) { console.log('โš ๏ธ You already have access to this content'); const permissions = await this.sdk.videoPayment.getMyPermissions(contentId); console.log(` Remaining Views: ${permissions.remainingViews.toNumber()}`); return; } // Step 2: Query content and prices console.log('\n๐Ÿ” Step 1: Querying content information and prices...'); const contentInfo = await this.sdk.videoPayment.getContentInfo(contentId); if (!contentInfo.isActive) { console.log('โŒ This content is not available for purchase'); return; } console.log(` Content ID: ${contentId}`); console.log(` View Count: ${contentInfo.viewCount} views`); console.log(` Active: ${contentInfo.isActive ? 'Yes' : 'No'}`); // Step 3: Display all available prices console.log('\n๐Ÿ’ฐ Step 2: Available Payment Methods and Prices:'); const ethSupported = ethers.constants.AddressZero in contentInfo.tokenPrices; const erc20Tokens = Object.keys(contentInfo.tokenPrices).filter( token => token !== ethers.constants.AddressZero ); if (ethSupported) { const ethPrice = contentInfo.tokenPrices[ethers.constants.AddressZero]; console.log(` ๐Ÿ’Ž ETH: ${ethers.utils.formatEther(ethPrice)} ETH`); } erc20Tokens.forEach(token => { const price = contentInfo.tokenPrices[token]; // Get network key for proper token formatting const networkKey = getNetworkKeyFromId(this.sdk.networkId!); const formattedPrice = TokenUtils.formatTokenAmountWithSymbol(price, token, networkKey); console.log(` ๐Ÿช™ ERC20 (${token}): ${formattedPrice}`); }); // Step 4: Purchase with ETH if available and price > 0 if (ethSupported) { const ethPrice = contentInfo.tokenPrices[ethers.constants.AddressZero]; if (ethPrice.gt(0)) { console.log('\n๐Ÿ’Ž Step 3: Attempting ETH purchase...'); console.log(` ETH Price: ${ethers.utils.formatEther(ethPrice)} ETH`); // Get optimal gas configuration for ETH purchase console.log('\n โ›ฝ Getting optimal gas configuration...'); const gasPrices = await this.sdk.getGasPrice({ multiplier: 1.2, // 20% buffer for base fee priorityMultiplier: 1.1 // 10% buffer for priority fee }); console.log(` Base Fee: ${gasPrices.baseFeePerGas ? ethers.utils.formatUnits(gasPrices.baseFeePerGas, "gwei") + ' gwei' : 'N/A'}`); console.log(` Max Fee: ${ethers.utils.formatUnits(gasPrices.maxFeePerGas, "gwei")} gwei`); console.log(` Priority Fee: ${gasPrices.maxPriorityFeePerGas ? ethers.utils.formatUnits(gasPrices.maxPriorityFeePerGas, "gwei") + ' gwei' : 'N/A'}`); try { const gasConfig = { maxFeePerGas: gasPrices.maxFeePerGas, maxPriorityFeePerGas: gasPrices.maxPriorityFeePerGas // Let system auto-estimate gas limit }; const ethResult = await this.sdk.videoPayment.purchaseContent(contentId, 'ETH', undefined, { gasConfig }); console.log(` โœ… ETH Purchase Successful! TX: ${ethResult.transactionHash}`); // Verify ETH purchase const ethPermission = await this.sdk.videoPayment.hasViewPermission(contentId); console.log(` โœ… ETH Purchase Verified: ${ethPermission ? 'Success' : 'Failed'}`); } catch (error) { console.log(` โŒ ETH Purchase Failed: ${error.message}`); } } else { console.log('\n๐Ÿ’Ž Step 3: ETH price is 0, skipping ETH purchase...'); } } else { console.log('\n๐Ÿ’Ž Step 3: ETH payment not supported, skipping...'); } // Step 5: Purchase with each ERC20 token if (erc20Tokens.length > 0) { console.log('\n๐Ÿช™ Step 4: Attempting ERC20 purchases...'); // Get gas configuration once for all ERC20 purchases console.log('\n โ›ฝ Getting optimal gas configuration for ERC20 purchases...'); const erc20GasPrices = await this.sdk.getGasPrice({ multiplier: 1.2, // 20% buffer for base fee priorityMultiplier: 1.1 // 10% buffer for priority fee }); console.log(` Base Fee: ${erc20GasPrices.baseFeePerGas ? ethers.utils.formatUnits(erc20GasPrices.baseFeePerGas, "gwei") + ' gwei' : 'N/A'}`); console.log(` Max Fee: ${ethers.utils.formatUnits(erc20GasPrices.maxFeePerGas, "gwei")} gwei`); console.log(` Priority Fee: ${erc20GasPrices.maxPriorityFeePerGas ? ethers.utils.formatUnits(erc20GasPrices.maxPriorityFeePerGas, "gwei") + ' gwei' : 'N/A'}`); for (const tokenAddress of erc20Tokens) { const tokenPrice = contentInfo.tokenPrices[tokenAddress]; console.log(`\n ๐Ÿ”น Testing token: ${tokenAddress.slice(0, 10)}...${tokenAddress.slice(-8)}`); // Get network key for proper token formatting const networkKey = getNetworkKeyFromId(this.sdk.networkId!); const formattedPrice = TokenUtils.formatTokenAmountWithSymbol(tokenPrice, tokenAddress, networkKey); console.log(` Price: ${formattedPrice}`); try { const gasConfig = { maxFeePerGas: erc20GasPrices.maxFeePerGas, maxPriorityFeePerGas: erc20GasPrices.maxPriorityFeePerGas // Let system auto-estimate gas limit }; const tokenResult = await this.sdk.videoPayment.purchaseContent(contentId, 'ERC20', tokenAddress, { gasConfig }); console.log(` โœ… ERC20 Purchase Successful! TX: ${tokenResult.transactionHash}`); // Verify ERC20 purchase const tokenPermission = await this.sdk.videoPayment.hasViewPermission(contentId); console.log(` โœ… ERC20 Purchase Verified: ${tokenPermission ? 'Success' : 'Failed'}`); } catch (error) { console.log(` โŒ ERC20 Purchase Failed: ${error.message}`); } } } else { console.log('\n๐Ÿช™ Step 4: No ERC20 tokens available, skipping...'); } // Step 6: Final verification and summary console.log('\n๐Ÿ“Š Step 5: Final Purchase Summary...'); const finalPermission = await this.sdk.videoPayment.hasViewPermission(contentId); if (finalPermission) { const permissions = await this.sdk.videoPayment.getMyPermissions(contentId); console.log(` โœ… Content access successfully acquired!`); console.log(` Remaining Views: ${permissions.remainingViews.toNumber()}`); console.log(` Purchase Time: ${new Date(permissions.purchaseTime.toNumber() * 1000).toLocaleString()}`); console.log(` Permission Valid: ${permissions.isValid ? 'Yes' : 'No'}`); } else { console.log(` โŒ No successful purchases - access not granted`); } } catch (error) { console.error('\nโŒ Full Test Purchase Failed:', error.message); throw error; } } } async function main() { console.log('๐Ÿ›’ GoTake Content Purchaser'); console.log('===========================\n'); // Environment configuration - support network selection const NETWORK = process.env.NETWORK || 'Base Sepolia'; const PRIVATE_KEY = process.env.PRIVATE_KEY; if (!PRIVATE_KEY) { console.error('โŒ Please set PRIVATE_KEY environment variable'); process.exit(1); } try { // Resolve network configuration let networkConfig; if (typeof NETWORK === 'string' && !isNaN(Number(NETWORK))) { // Network ID provided const networkId = Number(NETWORK) as NetworkId; networkConfig = getNetworkById(networkId); } else { // Network name provided networkConfig = getNetworkByName(NETWORK); } if (!networkConfig) { console.error(`โŒ Unsupported network: ${NETWORK}`); console.log('Supported networks: Base Mainnet, Base Sepolia, Base Goerli, Ethereum Mainnet, Ethereum Sepolia'); process.exit(1); } console.log(`๐ŸŒ Network: ${networkConfig.name} (ID: ${networkConfig.id})`); console.log(`๐Ÿ”— RPC: ${networkConfig.rpcUrl}`); // Create provider and signer const provider = new ethers.providers.JsonRpcProvider(networkConfig.rpcUrl); const signer = new ethers.Wallet(PRIVATE_KEY, provider); console.log(`๐Ÿ‘ค Wallet Address: ${signer.address}`); const purchaser = new ContentPurchaser(networkConfig.id, signer); // Check wallet balance const balance = await purchaser.sdk.provider.getBalance(signer.address); console.log(`๐Ÿ’ฐ Wallet Balance: ${ethers.utils.formatEther(balance)} ETH\n`); if (balance.lt(ethers.utils.parseEther('0.001'))) { console.log('โš ๏ธ Warning: Low ETH balance, may not be sufficient for transactions'); } // Run preflight checks const preflightPassed = await preflightChecks(purchaser.sdk, signer.address); if (!preflightPassed) { console.log('\nโŒ Preflight checks failed. Please resolve the issues above before continuing.'); process.exit(1); } // Parse command line arguments const command = process.argv[2]; switch (command) { case 'buy': // Purchase single content with ETH const contentId = parseInt(process.argv[3]); if (!contentId) { console.error('Usage: npm run purchase-content buy '); process.exit(1); } await purchaser.purchaseWithETH(contentId); break; case 'token': // Purchase with ERC20 token const tokenContentId = parseInt(process.argv[3]); const tokenAddress = process.argv[4]; if (!tokenContentId || !tokenAddress) { console.error('Usage: npm run purchase-content token '); process.exit(1); } await purchaser.purchaseWithToken(tokenContentId, tokenAddress); break; case 'check': // Check content information const checkContentId = parseInt(process.argv[3]); if (!checkContentId) { console.error('Usage: npm run purchase-content check '); process.exit(1); } await purchaser.checkContent(checkContentId); break; case 'smart': // Smart purchase with all available payment methods const smartContentId = parseInt(process.argv[3]); if (!smartContentId) { console.error('Usage: npm run purchase-content smart '); process.exit(1); } await purchaser.smartPurchase(smartContentId); break; case 'batch': // Batch purchase multiple content const contentIds = process.argv.slice(3).map(id => parseInt(id)); if (contentIds.length === 0) { console.error('Usage: npm run purchase-content batch [contentId2] ...'); process.exit(1); } await purchaser.batchPurchase(contentIds); break; case 'fulltest': // Full test purchase const fullTestContentId = parseInt(process.argv[3]); if (!fullTestContentId) { console.error('Usage: npm run purchase-content fulltest '); process.exit(1); } await purchaser.fullTestPurchase(fullTestContentId); break; default: console.log('Available commands:'); console.log(' buy - Purchase content with ETH'); console.log(' token - Purchase content with ERC20 token'); console.log(' check - Check content information'); console.log(' smart - Smart purchase with all available methods'); console.log(' batch [id2] ... - Batch purchase multiple content'); console.log(' fulltest - Full test purchase'); console.log('\nExamples:'); console.log(' npm run purchase-content buy 1'); console.log(' npm run purchase-content token 1 0x4D1F4F683AB7122fBb77aB544aC03c5678acA968'); console.log(' npm run purchase-content check 1'); console.log(' npm run purchase-content smart 1'); console.log(' npm run purchase-content batch 1 2 3'); console.log(' npm run purchase-content fulltest 1'); break; } } catch (error) { console.error('โŒ Purchase operation failed:', error); console.error('Details:', error.message); process.exit(1); } } // Run the script if (require.main === module) { main().catch(console.error); }