mirror of
https://github.com/mito-systems/ranger-app.git
synced 2026-03-04 01:04:07 +00:00
not earn
This commit is contained in:
parent
89484ad2a9
commit
3f6052e5ed
71
src/app/api/award-tokens/route.ts
Normal file
71
src/app/api/award-tokens/route.ts
Normal 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'
|
||||
@ -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')
|
||||
|
||||
@ -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
|
||||
|
||||
@ -7,6 +7,8 @@ export interface VisionAnalysisResult {
|
||||
error?: string
|
||||
isAnimal?: boolean
|
||||
rawResponse?: any
|
||||
animalType?: string
|
||||
pointsAwarded?: number
|
||||
}
|
||||
|
||||
export interface VisionConfig {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user