mirror of
https://github.com/mito-systems/ranger-app.git
synced 2026-03-19 01:24:09 +00:00
166 lines
5.4 KiB
TypeScript
166 lines
5.4 KiB
TypeScript
// src/services/blockchain/tokenRewardService.ts
|
|
import { isWalletConnected, getWalletAddress } from './seiService';
|
|
|
|
// Note: These reward amounts are for display purposes only
|
|
// The actual reward amounts are determined by the WILD token contract on Sei
|
|
export const TOKEN_REWARDS = {
|
|
WILDLIFE_SIGHTING: 10, // Base WILD token reward for any wildlife sighting
|
|
RARE_SPECIES: 25, // Additional WILD tokens for rare species
|
|
};
|
|
|
|
// List of species considered rare for bonus rewards
|
|
const RARE_SPECIES = [
|
|
'elephant',
|
|
'tiger',
|
|
'rhino',
|
|
'panda',
|
|
'gorilla',
|
|
'whale',
|
|
'dolphin',
|
|
'snow leopard',
|
|
'eagle',
|
|
// Add more rare species as needed
|
|
];
|
|
|
|
/**
|
|
* Determine if a species is considered rare
|
|
* @param species The detected animal species
|
|
* @returns True if the species is considered rare
|
|
*/
|
|
export const isRareSpecies = (species: string): boolean => {
|
|
if (!species) return false;
|
|
const normalizedSpecies = species.toLowerCase().trim();
|
|
return RARE_SPECIES.some(rareSpecies =>
|
|
normalizedSpecies.includes(rareSpecies)
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Award tokens for a wildlife sighting if wallet is connected
|
|
* @param species The detected animal species
|
|
* @param points Optional number of points to convert to tokens (if not provided, calculates based on species)
|
|
* @param explicitWalletAddress Optional wallet address to use instead of checking connection state
|
|
* @returns Object containing success status and transaction info
|
|
*/
|
|
export const awardTokensForSighting = async (
|
|
species: string,
|
|
points?: number,
|
|
explicitWalletAddress?: string
|
|
): Promise<{
|
|
success: boolean;
|
|
tokenAmount?: number;
|
|
txHash?: string;
|
|
error?: string;
|
|
walletConnected: boolean;
|
|
}> => {
|
|
try {
|
|
// Determine wallet address - either from parameter or connected wallet
|
|
let walletAddress = explicitWalletAddress;
|
|
|
|
// If explicit address was provided, use it directly (server-side case)
|
|
if (walletAddress) {
|
|
console.log('Using explicitly provided wallet address:', walletAddress);
|
|
} else {
|
|
// Client-side case - check if wallet is connected
|
|
console.log('No explicit wallet address provided, checking wallet connection state...');
|
|
|
|
// Try to get from memory first
|
|
if (isWalletConnected()) {
|
|
walletAddress = getWalletAddress();
|
|
console.log('Found connected wallet in memory:', walletAddress);
|
|
}
|
|
|
|
// Try localStorage as a fallback (client-side only)
|
|
if (!walletAddress && typeof window !== 'undefined') {
|
|
try {
|
|
const storedAddress = localStorage.getItem('wildlife_wallet_address');
|
|
if (storedAddress) {
|
|
console.log('Using wallet address from localStorage:', storedAddress);
|
|
walletAddress = storedAddress;
|
|
}
|
|
} catch (e) {
|
|
console.warn('Error accessing localStorage:', e);
|
|
}
|
|
}
|
|
|
|
// If we still don't have an address, return no wallet connected
|
|
if (!walletAddress) {
|
|
console.log('No wallet connected, skipping token award.');
|
|
return {
|
|
success: false,
|
|
error: 'No wallet connected',
|
|
walletConnected: false
|
|
};
|
|
}
|
|
}
|
|
|
|
// Validate we have a wallet address by this point
|
|
if (!walletAddress) {
|
|
console.log('No valid wallet address available for token award.');
|
|
return {
|
|
success: false,
|
|
error: 'No wallet address available',
|
|
walletConnected: false
|
|
};
|
|
}
|
|
|
|
console.log('Processing token award for wallet:', walletAddress);
|
|
|
|
// Calculate token reward amount - either from points or from species
|
|
let totalReward: number;
|
|
|
|
if (typeof points === 'number' && points > 0) {
|
|
// If points are provided, use them directly (1 point = 1 token)
|
|
totalReward = points;
|
|
} else {
|
|
// Otherwise calculate based on species
|
|
const baseReward = TOKEN_REWARDS.WILDLIFE_SIGHTING;
|
|
const isRare = isRareSpecies(species);
|
|
const rareBonus = isRare ? TOKEN_REWARDS.RARE_SPECIES : 0;
|
|
totalReward = baseReward + rareBonus;
|
|
}
|
|
|
|
// Call the backend service to award tokens through the distributor
|
|
const apiUrl = process.env.NEXT_PUBLIC_TOKEN_BACKEND_URL || 'http://localhost:3001';
|
|
const apiKey = process.env.NEXT_PUBLIC_TOKEN_API_KEY || '';
|
|
|
|
// Request tokens from the backend service
|
|
const response = await fetch(`${apiUrl}/api/award-tokens`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'x-api-key': apiKey
|
|
},
|
|
body: JSON.stringify({
|
|
recipientAddress: walletAddress,
|
|
species: species.toLowerCase()
|
|
})
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errorData = await response.json();
|
|
throw new Error(errorData.error || 'Error from token service');
|
|
}
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.success) {
|
|
console.log(`Awarded tokens for ${species} sighting to wallet ${walletAddress}`);
|
|
return {
|
|
success: true,
|
|
tokenAmount: result.amount,
|
|
txHash: result.txHash,
|
|
walletConnected: true
|
|
};
|
|
} else {
|
|
throw new Error(result.error || 'Failed to award tokens');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error in token reward service:', error);
|
|
return {
|
|
success: false,
|
|
error: error instanceof Error ? error.message : 'Unknown error processing token reward',
|
|
walletConnected: true
|
|
};
|
|
}
|
|
}; |