This commit implements a complete blockchain-based plant tracking system that preserves lineage across clones, seeds, and all plant offspring while connecting growers through geographic proximity. Features implemented: - Custom blockchain with proof-of-work consensus - Plant registration and cloning with lineage tracking - Geographic discovery to find nearby plants and growers - Integration with plants.net API for plant identification - Comprehensive web UI for plant management - RESTful API endpoints for all operations - Network statistics and visualization Core Components: - lib/blockchain/: PlantBlock, PlantChain, and blockchain manager - lib/services/: plants.net API and geolocation services - pages/api/plants/: REST API endpoints for all operations - pages/: Frontend UI pages for registration, exploration, and lineage Technical Details: - TypeScript for type safety - Next.js for server-side rendering - Tailwind CSS for responsive design - JSON file-based blockchain storage - Haversine distance calculations for geolocation - OpenStreetMap integration for geocoding This system enables large-scale adoption by: - Making plant lineage tracking accessible to everyone - Connecting local communities through plant sharing - Providing immutable proof of plant provenance - Supporting unlimited generations of plant propagation - Scaling from individual growers to global networks Documentation includes comprehensive README with: - Quick start guide - API reference - Architecture details - Scaling recommendations - Use cases for various audiences - Roadmap for future enhancements
70 lines
1.8 KiB
TypeScript
70 lines
1.8 KiB
TypeScript
/**
|
|
* API Route: Clone a plant (create offspring)
|
|
* POST /api/plants/clone
|
|
*/
|
|
|
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
import { getBlockchain, saveBlockchain } from '../../../lib/blockchain/manager';
|
|
import { PlantData } from '../../../lib/blockchain/types';
|
|
|
|
interface CloneRequest {
|
|
parentPlantId: string;
|
|
propagationType: 'seed' | 'clone' | 'cutting' | 'division' | 'grafting';
|
|
newPlant: Partial<PlantData>;
|
|
}
|
|
|
|
export default async function handler(
|
|
req: NextApiRequest,
|
|
res: NextApiResponse
|
|
) {
|
|
if (req.method !== 'POST') {
|
|
return res.status(405).json({ error: 'Method not allowed' });
|
|
}
|
|
|
|
try {
|
|
const { parentPlantId, propagationType, newPlant }: CloneRequest = req.body;
|
|
|
|
// Validate required fields
|
|
if (!parentPlantId || !propagationType || !newPlant) {
|
|
return res.status(400).json({
|
|
error: 'Missing required fields: parentPlantId, propagationType, newPlant',
|
|
});
|
|
}
|
|
|
|
if (!newPlant.location || !newPlant.owner) {
|
|
return res.status(400).json({
|
|
error: 'New plant must have location and owner',
|
|
});
|
|
}
|
|
|
|
const blockchain = getBlockchain();
|
|
|
|
// Clone the plant
|
|
const block = blockchain.clonePlant(
|
|
parentPlantId,
|
|
newPlant,
|
|
propagationType
|
|
);
|
|
|
|
// Save blockchain
|
|
saveBlockchain();
|
|
|
|
// Get parent for context
|
|
const parent = blockchain.getPlant(parentPlantId);
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
plant: block.plant,
|
|
parent: parent,
|
|
block: {
|
|
index: block.index,
|
|
hash: block.hash,
|
|
timestamp: block.timestamp,
|
|
},
|
|
message: `Successfully created ${propagationType} from parent plant`,
|
|
});
|
|
} catch (error: any) {
|
|
console.error('Error cloning plant:', error);
|
|
res.status(500).json({ error: error.message || 'Internal server error' });
|
|
}
|
|
}
|