'use client' import React, { useState } from 'react' import { Connection, PublicKey, Transaction } from '@solana/web3.js' import { TOKEN_PROGRAM_ID, createTransferInstruction, getAssociatedTokenAddress } from '@solana/spl-token' interface WalletState { connected: boolean publicKey: string | null } interface PaymentStatus { paid: boolean processing: boolean error: string | null } interface GenerationState { loading: 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 = 'JB8YCqKBKNtS4ZHcGPJXSJokcvdgdeeyWRxGqgyX5EwP' 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 [paymentStatus, setPaymentStatus] = useState({ paid: false, processing: false, error: null, }) const [inputText, setInputText] = useState('') const [generationState, setGenerationState] = useState({ loading: false, imageUrl: null, error: null, }) const connectWallet = async (): Promise => { try { if (typeof window === 'undefined' || !window.solflare) { throw new Error('Solflare wallet not found! Please install it first.') } await window.solflare.connect() if (!window.solflare.publicKey) { throw new Error('Failed to connect to wallet') } const publicKey: string = window.solflare.publicKey.toString() setWalletState({ connected: true, publicKey, }) } catch (error) { console.error('Wallet connection error:', error) setWalletState({ connected: false, publicKey: null, }) } } const processPayment = async (): Promise => { if (!walletState.connected || !walletState.publicKey || !window.solflare) { return } setPaymentStatus({ ...paymentStatus, processing: true, error: null }) try { // Convert string addresses to PublicKeys 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 for sender and receiver const senderATA = await getAssociatedTokenAddress( mintPublicKey, senderPublicKey ) const receiverATA = await getAssociatedTokenAddress( mintPublicKey, receiverPublicKey ) // Create transfer instruction const transferInstruction = createTransferInstruction( senderATA, receiverATA, senderPublicKey, BigInt(REQUIRED_PAYMENT_AMOUNT * (10 ** 6)) // Convert to proper format ) const latestBlockhash = await connection.getLatestBlockhash('confirmed') // Create transaction const transaction = new Transaction() transaction.add(transferInstruction) transaction.recentBlockhash = latestBlockhash.blockhash transaction.feePayer = senderPublicKey try { // Sign and send transaction with preflight disabled const { signature } = await window.solflare.signAndSendTransaction(transaction, { skipPreflight: true }) console.log('Transaction sent:', signature) // Wait for confirmation with WebSocket support 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('Transaction failed to confirm') } setPaymentStatus({ paid: true, processing: false, error: null, }) } catch (error) { console.error('Transaction error:', error) throw new Error(`Failed to sign or send transaction: ${error instanceof Error ? error.message : 'Unknown error'}`) } } catch (error) { console.error('Payment error:', error) setPaymentStatus({ ...paymentStatus, processing: false, error: error instanceof Error ? error.message : 'Payment failed. Please try again.', }) } } const generateMeme = async (): Promise => { if (!inputText || !paymentStatus.paid) { return } setGenerationState({ ...generationState, loading: true, error: null, }) try { const response = await fetch('/api/proxy', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ protocol: 'https', origin: 'api.openai.com', path: '/v1/images/generations', headers: { 'Authorization': `Bearer ${process.env.NEXT_PUBLIC_OPENAI_API_KEY}`, 'Content-Type': 'application/json', }, method: 'POST', body: JSON.stringify({ prompt: `Generate a meme with text: ${inputText}`, n: 1, size: '512x512', }), }), }) const data = await response.json() if (data.data && data.data[0].url) { setGenerationState({ loading: false, imageUrl: data.data[0].url, error: null, }) } else { throw new Error('Failed to generate image') } } catch (error) { setGenerationState({ ...generationState, loading: false, error: 'Failed to generate meme. Please try again.', }) } } return (

AI Meme Generator

Connect your Solflare wallet and pay with MTM tokens to generate custom memes!

{!walletState.connected ? ( ) : !paymentStatus.paid ? (

Wallet Connected: {walletState.publicKey?.slice(0, 8)}...

{paymentStatus.error && (

{paymentStatus.error}

)}
) : (