This commit is contained in:
zramsay 2025-03-21 21:24:50 -04:00
parent 89484ad2a9
commit 3f6052e5ed
4 changed files with 161 additions and 9 deletions

View File

@ -0,0 +1,71 @@
import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth';
import { awardTokensForSighting } from '@/services/blockchain/tokenRewardService';
import { logger } from '@/services/constants';
export async function POST(req: NextRequest) {
try {
logger.info('award-tokens API called');
// Log all request headers for debugging
logger.info('Request headers:', Object.fromEntries(req.headers.entries()));
// Make authentication optional for demonstration - we'll allow both authenticated and
// unauthenticated requests for testing purposes
let userEmail = 'unknown@example.com';
try {
const session = await getServerSession(authOptions);
if (session?.user?.email) {
userEmail = session.user.email;
logger.info(`Authenticated user: ${userEmail}`);
} else {
logger.warn('No authenticated session found, but continuing for demonstration');
}
} catch (authError) {
logger.error('Authentication error but continuing:', authError);
}
// Parse request body
let data;
try {
data = await req.json();
logger.info('Request body:', data);
} catch (parseError) {
logger.error('Failed to parse request body:', parseError);
return NextResponse.json({ error: 'Invalid request body' }, { status: 400 });
}
const { walletAddress, animalName } = data;
if (!walletAddress) {
logger.error('No wallet address provided for token award');
return NextResponse.json({ error: 'Wallet address is required' }, { status: 400 });
}
logger.info(`Processing token award for wallet ${walletAddress} and animal ${animalName || 'Unknown'}`);
// Check for environment variables
const apiUrl = process.env.NEXT_PUBLIC_TOKEN_BACKEND_URL;
const apiKey = process.env.NEXT_PUBLIC_TOKEN_API_KEY;
logger.info(`Using backend URL: ${apiUrl || 'Not set'}, API key exists: ${!!apiKey}`);
const result = await awardTokensForSighting(walletAddress, userEmail, animalName || 'Unknown wildlife');
logger.info(`Token award result:`, result);
// Return the complete result directly without nesting
return NextResponse.json(result);
} catch (error) {
logger.error('Error in award-tokens API:', error);
return NextResponse.json({
success: false,
error: error instanceof Error ? error.message : 'Failed to award tokens'
}, { status: 500 });
}
}
// Ensure dynamic routing
export const dynamic = 'force-dynamic'

View File

@ -85,12 +85,65 @@ const ImageAnalysisCard: React.FC<ImageAnalysisCardProps> = ({
}
if (result.description) {
// Check if we should award tokens - if an animal was identified and wallet is connected
let tokenReward = result.tokenReward || null;
// If the image contains an animal and the user has a wallet connected
if (result.isAnimal && isWalletConnected()) {
try {
console.log('Animal detected and wallet connected. Attempting to award tokens...');
// Import the necessary services
const { getWalletAddress } = await import('../services/blockchain/seiService');
const walletAddress = getWalletAddress();
if (walletAddress) {
console.log(`Found wallet address: ${walletAddress}, awarding tokens`);
// Call our new token award endpoint
const tokenResponse = await fetch('/api/award-tokens', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
walletAddress: walletAddress,
animalName: result.animalType || 'Unknown wildlife'
})
});
if (tokenResponse.ok) {
const tokenResult = await tokenResponse.json();
console.log('Token award result:', tokenResult);
if (tokenResult.success) {
// Update token reward information
tokenReward = {
amount: tokenResult.amount,
txHash: tokenResult.txHash
};
console.log(`Successfully awarded ${tokenResult.amount} tokens`);
} else {
console.error('Token award failed:', tokenResult.error);
}
} else {
console.error('Failed to call token award endpoint:', tokenResponse.status);
}
} else {
console.log('Wallet is connected but no address available');
}
} catch (tokenError) {
console.error('Error awarding tokens:', tokenError);
// Continue with analysis result even if token award fails
}
}
setAnalysisState({
loading: false,
imageUrl: analysisState.imageUrl,
description: result.description,
error: null,
tokenReward: result.tokenReward || null
tokenReward: tokenReward
})
} else {
throw new Error('No analysis received')

View File

@ -100,30 +100,56 @@ const WildlifeIdentifier: React.FC = () => {
// make a separate call to award tokens
let tokenResult = null;
// ENHANCED DEBUG: Check each condition separately with explicit logging
console.log('Token award eligibility check:', {
isAnimal: analysisResult.isAnimal,
userAddressAvailable: !!userAddress,
walletIsConnected: isConnected,
userAddressValue: userAddress,
animalType: analysisResult.animalType
});
if (analysisResult.isAnimal && userAddress && isConnected) {
try {
console.log('Animal detected and wallet connected. Awarding tokens separately...');
console.log('✅ All conditions met! Awarding tokens separately...');
// Log the exact request we're about to make
const requestBody = {
walletAddress: userAddress,
animalName: analysisResult.animalType || 'Unknown wildlife'
};
console.log('Token award request body:', JSON.stringify(requestBody));
const tokenResponse = await fetch('/api/award-tokens', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
walletAddress: userAddress,
animalName: analysisResult.animalType || 'Unknown wildlife'
})
body: JSON.stringify(requestBody)
});
console.log('Token award response status:', tokenResponse.status);
if (tokenResponse.ok) {
tokenResult = await tokenResponse.json();
console.log('Token award result:', tokenResult);
console.log('Token award success result:', tokenResult);
// The response format is now different (no nested result structure)
// so we use the response directly
if (tokenResult.success) {
console.log(`Successfully awarded ${tokenResult.amount} tokens with tx hash ${tokenResult.txHash}`);
} else {
console.error('Token award returned failure status:', tokenResult.error);
}
} else {
console.error('Failed to award tokens:', await tokenResponse.json());
const errorData = await tokenResponse.json().catch(e => ({ error: 'Failed to parse error response' }));
console.error('Failed to award tokens:', errorData);
}
} catch (tokenError) {
console.error('Error awarding tokens:', tokenError);
console.error('Exception during token award process:', tokenError);
}
} else {
console.log('❌ Not awarding tokens - conditions not met');
}
// Format the result for display

View File

@ -7,6 +7,8 @@ export interface VisionAnalysisResult {
error?: string
isAnimal?: boolean
rawResponse?: any
animalType?: string
pointsAwarded?: number
}
export interface VisionConfig {