diff --git a/src/app/page.tsx b/src/app/page.tsx index 487ab1f..2e5358f 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,82 +1,21 @@ 'use client' import React, { useState } from 'react' -import { Connection, PublicKey, Transaction } from '@solana/web3.js' -import { - TOKEN_PROGRAM_ID, - createTransferInstruction, - getAssociatedTokenAddress, - createAssociatedTokenAccountInstruction as createATAInstruction, - ASSOCIATED_TOKEN_PROGRAM_ID -} from '@solana/spl-token' - -import { fal } from "@fal-ai/client" +import WalletHeader from '../components/WalletHeader' +import AIServiceCard from '../components/AIServiceCard' +import { generateWithFlux, FluxGenerationResult } from '../services/fluxService' +import { processMTMPayment } from '../services/paymentService' interface WalletState { connected: boolean publicKey: string | null } -/* -interface PaymentStatus { - paid: boolean - processing: boolean - error: string | null -} -*/ - -interface GenerationState { - loading: boolean - processing: boolean - imageUrl: string | null - error: string | null -} - -// Solflare wallet type definition -interface SolflareWallet { - connect(): Promise - disconnect(): Promise - signAndSendTransaction( - transaction: Transaction | VersionedTransaction, - options?: { skipPreflight?: boolean } - ): Promise<{ signature: string; publicKey: string }> - publicKey: PublicKey - connected: boolean -} - -declare global { - interface Window { - solflare?: SolflareWallet - } -} - -// Replace these with your actual addresses -const MTM_TOKEN_MINT: string = '97RggLo3zV5kFGYW4yoQTxr4Xkz4Vg2WPHzNYXXWpump' -const PAYMENT_RECEIVER_ADDRESS: string = '9B3mGyeJTUN7ZTqyLWHLL37zL92eif239hH2pYSkvq8J' -const REQUIRED_PAYMENT_AMOUNT: number = 2 -const SOLANA_NETWORK: string = 'mainnet' -const SOLANA_RPC_URL: string = 'https://young-radial-orb.solana-mainnet.quiknode.pro/67612b364664616c29514e551bf5de38447ca3d4' -const SOLANA_WEBSOCKET_URL: string = 'wss://young-radial-orb.solana-mainnet.quiknode.pro/67612b364664616c29514e551bf5de38447ca3d4' -const connection = new Connection( - SOLANA_RPC_URL, - { - commitment: 'confirmed', - wsEndpoint: SOLANA_WEBSOCKET_URL, - confirmTransactionInitialTimeout: 30000, // 30 seconds - } -) const Page: React.FC = (): React.ReactElement => { const [walletState, setWalletState] = useState({ connected: false, publicKey: null, }) - const [inputText, setInputText] = useState('') - const [generationState, setGenerationState] = useState({ - loading: false, - processing: false, - imageUrl: null, - error: null, - }) const connectWallet = async (): Promise => { try { @@ -85,7 +24,7 @@ const Page: React.FC = (): React.ReactElement => { } await window.solflare.connect() - + if (!window.solflare.publicKey) { throw new Error('Failed to connect to wallet') } @@ -104,240 +43,57 @@ const Page: React.FC = (): React.ReactElement => { } } -const processPaymentAndGenerate = async (): Promise => { - if (!walletState.connected || !walletState.publicKey || !window.solflare || !inputText) { - return + const handleFluxGeneration = async (prompt: string): Promise => { + if (!walletState.connected || !walletState.publicKey || !window.solflare) { + return { error: 'Wallet not connected' } } - setGenerationState({ - ...generationState, - processing: true, - error: null, - }) + // First process payment + const paymentResult = await processMTMPayment( + walletState.publicKey, + 1, // 1 MTM token + window.solflare + ) - try { - // Process payment first - const senderPublicKey = new PublicKey(walletState.publicKey) - const mintPublicKey = new PublicKey(MTM_TOKEN_MINT) - const receiverPublicKey = new PublicKey(PAYMENT_RECEIVER_ADDRESS) - - // Get the associated token accounts - const senderATA = await getAssociatedTokenAddress( - mintPublicKey, - senderPublicKey - ) - const receiverATA = await getAssociatedTokenAddress( - mintPublicKey, - receiverPublicKey - ) - - // Create transaction - const transaction = new Transaction() - - // Check if receiver's ATA exists - const receiverATAInfo = await connection.getAccountInfo(receiverATA) - if (!receiverATAInfo) { - console.log('Creating receiver ATA...') - transaction.add( - createATAInstruction( - senderPublicKey, // payer - receiverATA, // ata - receiverPublicKey, // owner - mintPublicKey, // mint - TOKEN_PROGRAM_ID, - ASSOCIATED_TOKEN_PROGRAM_ID - ) - ) - } - - // Check if sender's ATA exists - const senderATAInfo = await connection.getAccountInfo(senderATA) - if (!senderATAInfo) { - console.log('Creating sender ATA...') - transaction.add( - createATAInstruction( - senderPublicKey, // payer - senderATA, // ata - senderPublicKey, // owner - mintPublicKey, // mint - TOKEN_PROGRAM_ID, - ASSOCIATED_TOKEN_PROGRAM_ID - ) - ) - } - - // Add transfer instruction - const transferInstruction = createTransferInstruction( - senderATA, - receiverATA, - senderPublicKey, - BigInt(REQUIRED_PAYMENT_AMOUNT * (10 ** 9)) - ) - transaction.add(transferInstruction) - - const latestBlockhash = await connection.getLatestBlockhash('confirmed') - transaction.recentBlockhash = latestBlockhash.blockhash - transaction.feePayer = senderPublicKey - - console.log('Sending transaction...') - // Sign and send transaction - const { signature } = await window.solflare.signAndSendTransaction(transaction, { - skipPreflight: false // Enable preflight checks - }) - - console.log('Transaction sent:', signature) - - // Wait for confirmation - const confirmation = await connection.confirmTransaction({ - signature, - blockhash: latestBlockhash.blockhash, - lastValidBlockHeight: latestBlockhash.lastValidBlockHeight, - }, 'confirmed') - - console.log('Transaction confirmed:', confirmation) - - if (confirmation.value.err) { - throw new Error('Payment failed to confirm') - } - - // After payment is confirmed, generate the meme - setGenerationState(prev => ({ ...prev, loading: true })) - - // Call our secure API endpoint instead of direct Fal.ai call - const response = await fetch('/api/generate', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - prompt: inputText, - }), - }) - - if (!response.ok) { - throw new Error('Failed to generate image') - } - - const result = await response.json() - console.log("Generation Response:", result) - - if (result.data && result.data.images && result.data.images[0]?.url) { - setGenerationState({ - loading: false, - processing: false, - imageUrl: result.data.images[0].url, - error: null, - }) - } else { - throw new Error('No image URL in response') - } - } catch (error) { - console.error('Generation error:', error) - setGenerationState({ - ...generationState, - loading: false, - processing: false, - error: error instanceof Error ? error.message : 'Failed to process payment or generate meme.', - }) + if (!paymentResult.success) { + return { error: paymentResult.error } } + + // Then generate image + return generateWithFlux(prompt) } return (
-
+
{/* Header */} -
+

- AI Meme Generator + AI Content Generator

-

- Connect your Solflare wallet and pay {REQUIRED_PAYMENT_AMOUNT} MTM token per meme +

+ Generate amazing content using different AI models

+ +
- {/* Main Content */} -
-
- {!walletState.connected ? ( - - ) : ( -
- {/* Wallet Info */} -
- Connected Wallet - - {walletState.publicKey?.slice(0, 8)}... - -
- - {/* Input Area */} -
-