Upload generated meme to Pinata #9

Merged
ashwin merged 8 commits from pm-upload-to-pinata into main 2025-02-04 15:16:25 +00:00
8 changed files with 1048 additions and 1112 deletions

View File

@ -1,7 +1,12 @@
# Get key from https://fal.ai
FAL_AI_KEY= FAL_AI_KEY=
NEXT_PUBLIC_MTM_TOKEN_MINT=97RggLo3zV5kFGYW4yoQTxr4Xkz4Vg2WPHzNYXXWpump NEXT_PUBLIC_MTM_TOKEN_MINT=97RggLo3zV5kFGYW4yoQTxr4Xkz4Vg2WPHzNYXXWpump
NEXT_PUBLIC_PAYMENT_RECEIVER_ADDRESS=FFDx3SdAEeXrp6BTmStB4BDHpctGsaasZq4FFcowRobY NEXT_PUBLIC_PAYMENT_RECEIVER_ADDRESS=FFDx3SdAEeXrp6BTmStB4BDHpctGsaasZq4FFcowRobY
NEXT_PUBLIC_SOLANA_RPC_URL=https://young-radial-orb.solana-mainnet.quiknode.pro/67612b364664616c29514e551bf5de38447ca3d4 NEXT_PUBLIC_SOLANA_RPC_URL=https://young-radial-orb.solana-mainnet.quiknode.pro/67612b364664616c29514e551bf5de38447ca3d4
NEXT_PUBLIC_SOLANA_WEBSOCKET_URL=wss://young-radial-orb.solana-mainnet.quiknode.pro/67612b364664616c29514e551bf5de38447ca3d4 NEXT_PUBLIC_SOLANA_WEBSOCKET_URL=wss://young-radial-orb.solana-mainnet.quiknode.pro/67612b364664616c29514e551bf5de38447ca3d4
NEXT_PUBLIC_USDC_MINT=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v NEXT_PUBLIC_USDC_MINT=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
# Get keys from https://app.pinata.cloud/developers/api-keys
PINATA_JWT=
PINATA_GATEWAY=

View File

@ -16,31 +16,38 @@ This project is a Solana-based meme generator that allows users to connect their
## Setup ## Setup
1. Install dependencies: - Install dependencies:
```sh ```sh
npm install npm install
``` ```
2. Copy the `.env.example` file to `.env.local` and add your FAL AI key: - Copy the `.env.example` file to `.env.local` and add your API keys:
```sh ```sh
cp .env.example .env.local cp .env.example .env.local
``` ```
3. Add your FAL AI key to the `.env.local` file: - Add your FAL AI key to the `.env.local` file:
```env ```env
# Get key from https://fal.ai/ # Get key from https://fal.ai/
FAL_AI_KEY=your_fal_ai_key FAL_AI_KEY=your_fal_ai_key
``` ```
4. Run the development server: - Setup a project on <https://app.pinata.cloud> then add the following to `.env.example`:
```env
# Get keys from https://app.pinata.cloud/developers/api-keys
PINATA_JWT=
PINATA_GATEWAY=
```
- Run the development server:
```sh ```sh
npm run dev npm run dev
``` ```
5. Open your browser and navigate to `http://localhost:3000`. - Open your browser and navigate to `http://localhost:3000`.
## Usage ## Usage
1. Connect your Solflare or Phantom wallet using the "Connect Wallet" button. - Connect your Solflare or Phantom wallet using the "Connect Wallet" button.
2. Select an AI model and enter a prompt to generate a meme. - Select an AI model and enter a prompt to generate a meme.
3. Pay the required MTM tokens and wait for the meme to be generated. - Pay the required MTM tokens and wait for the meme to be generated.

2081
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"next": "13.5.4", "next": "13.5.4",
"openai": "^4.77.0", "openai": "^4.77.0",
"pinata-web3": "^0.5.4",
"react": "^18", "react": "^18",
"react-dom": "^18", "react-dom": "^18",
"sqlite3": "^5.1.7", "sqlite3": "^5.1.7",

View File

@ -5,6 +5,7 @@ import { fal } from "@fal-ai/client"
import { FLUX_MODELS } from '../../../services/fluxService' import { FLUX_MODELS } from '../../../services/fluxService'
import { initializeDataSource } from '../../../data-source' import { initializeDataSource } from '../../../data-source'
import { verifyPayment, markSignatureAsUsed } from '../../../utils/verifyPayment'; import { verifyPayment, markSignatureAsUsed } from '../../../utils/verifyPayment';
import { uploadToPinata } from '../../../utils/uploadToPinata';
if (!process.env.FAL_AI_KEY) { if (!process.env.FAL_AI_KEY) {
throw new Error('FAL_AI_KEY is not configured in environment variables') throw new Error('FAL_AI_KEY is not configured in environment variables')
@ -97,7 +98,18 @@ export async function POST(req: NextRequest): Promise<NextResponse> {
) )
} }
return NextResponse.json({ imageUrl }) const pinataResult = await uploadToPinata(imageUrl);
if (pinataResult.error) {
return NextResponse.json(
{ error: 'Failed to upload image to Pinata' },
{ status: 500 }
)
}
const publicUrl = pinataResult.imageUrl;
return NextResponse.json({ imageUrl: publicUrl })
} catch (error) { } catch (error) {
console.error('Flux generation error:', error) console.error('Flux generation error:', error)
return NextResponse.json( return NextResponse.json(

View File

@ -87,10 +87,10 @@ const Page: React.FC = (): React.ReactElement => {
if (!transactionSignature) { if (!transactionSignature) {
return { error: 'Transaction signature not found' } return { error: 'Transaction signature not found' }
} };
// Generate image with specified model and transaction reference // Generate image with specified model and transaction reference
return generateWithFlux(prompt, modelId, transactionSignature) return generateWithFlux(prompt, modelId, transactionSignature);
} catch (error) { } catch (error) {
console.error('Error in handleFluxGeneration:', error) console.error('Error in handleFluxGeneration:', error)
return { error: error instanceof Error ? error.message : 'Unknown error' } return { error: error instanceof Error ? error.message : 'Unknown error' }

View File

@ -0,0 +1,28 @@
import { PinataSDK } from 'pinata-web3';
import 'dotenv/config';
import assert from 'assert';
import { FluxGenerationResult } from '../services/fluxService';
assert(process.env.PINATA_JWT, "PINATA_JWT is required");
assert(process.env.PINATA_GATEWAY, "PINATA_GATEWAY is required");
const pinata = new PinataSDK({
pinataJwt: process.env.PINATA_JWT,
pinataGateway: process.env.PINATA_GATEWAY,
});
export async function uploadToPinata(imageUrl: string): Promise<FluxGenerationResult> {
try {
const upload = await pinata.upload.url(imageUrl);
const publicURL = await pinata.gateways.convert(upload.IpfsHash);
return { imageUrl: publicURL };
} catch (error) {
console.error('Error uploading to Pinata:', error)
return {
error: error instanceof Error ? error.message : 'Upload failed'
};
}
}

View File

@ -10,4 +10,4 @@
"noEmit": false "noEmit": false
}, },
"include": ["server.ts"] "include": ["server.ts"]
} }