Documentation
Learn how to integrate, build, and validate gaming-ready ERC-721 token metadata slabs. Build compliance-ready contracts with the official Pokédev SDK.
Overview
Pokédev defines a standard schema format for describing collectible on-chain card attributes (slabs). By aligning token metadata structure with OpenSea ERC-721 compliance traits, developers can seamlessly load, render, mutate, and display their collector cards directly in web browsers, marketplaces, and game clients.
Slab metadata contains standard properties like name, description, and image alongside an attributes array tracking custom stats like Level, XP, Attack, Defense, and Wins.
Installation
Install the official Pokédev SDK package via NPM to integrate validation utilities and code generators inside your Node.js or React applications:
npm install @pokedev/sdkFor local linking or development inside the repository workspace, install directly via file link reference:
npm install ./pokedev-sdkMetadata Schema
Every Pokédev ERC-721 token URI should resolve to a JSON structure tracking standard elements. Below is a compliant schema template containing all required gaming attributes:
{
"name": "Voltbeat #904",
"description": "A bug-type firefly Pokémon wreathed in electric tail-light glow.",
"image": "ipfs://QmVoltbeatGenesisSlabImageHash",
"attributes": [
{ "trait_type": "Species", "value": "Voltbeat" },
{ "trait_type": "Type", "value": "Thunder" },
{ "trait_type": "Rarity", "value": "Epic" },
{ "trait_type": "Level", "value": 12 },
{ "trait_type": "XP", "value": 450 },
{ "trait_type": "Attack", "value": 92 },
{ "trait_type": "Defense", "value": 50 },
{ "trait_type": "Speed", "value": 115 },
{ "trait_type": "Intelligence", "value": 98 },
{ "trait_type": "Wins", "value": 68 },
{ "trait_type": "Losses", "value": 22 }
]
}Attributes Specifications
| Trait Type | Type | Description / Range |
|---|---|---|
| Species | string | The Pokémon class name (e.g. Voltbeat, Emberfang, Mossjaw) |
| Type | string | Elemental affinity (Flame, Thunder, Nature, Frost, Spirit) |
| Rarity | string | Card rarity classification (Common, Rare, Epic, Legendary) |
| Level | number | Progress rating from 1 to 100 |
| XP | number | Accumulated battle experience points |
| Attack / Defense | number | On-chain stats bounded from 0 to 255 (standard byte boundaries) |
| Speed / Intelligence | number | On-chain stats bounded from 0 to 255 |
SDK Validation
Use the exported validateMetadata() function to verify structural compliance for OpenSea format layouts. This returns detailed issues list with severity tags:
import { validateMetadata } from '@pokedev/sdk';
const metadata = {
name: "Voltbeat #904",
description: "A bug-type firefly Pokémon...",
image: "ipfs://QmVoltbeatGenesisSlabImageHash",
attributes: [
{ trait_type: "Species", value: "Voltbeat" },
{ trait_type: "Level", value: 12 }
]
};
const result = validateMetadata(metadata);
if (!result.isValid) {
console.error("Compliance check failed:");
result.issues.forEach(issue => {
console.log(`[${issue.severity.toUpperCase()}] ${issue.field}: ${issue.message}`);
});
} else {
console.log("Metadata is compliant with OpenSea and Pokédev standards!");
}Metadata Generator
Construct your schemas dynamically with typings and predefined base statistics by using the fluent PokémonMetadataBuilder pattern:
import { PokémonMetadataBuilder } from '@pokedev/sdk';
const metadata = new PokémonMetadataBuilder()
.setName("Emberfang #119")
.setDescription("A fiery dragon-canid that specializes in rapid flame bursts.")
.setImage("ipfs://QmEmberfangGenesisSlabHash")
.setBaseStats("Emberfang", "Flame", "Rare")
.setStats(85, 62, 90, 75) // Attack, Defense, Speed, Intelligence
.addTrait("Wins", 34)
.addTrait("Losses", 12)
.build();
console.log(JSON.stringify(metadata, null, 2));On-Chain Mutations
Metadata lifecycle properties (like XP increases, stats adjustments, and Species Evolution transitions) are triggered dynamically during gameplay events. The following example demonstrates standard modifier transformations on the token attributes:
// 1. Battle Win Simulation: +15 XP, +1 Win, & Check Level-Up
function handleBattleWin(metadata: any) {
const xpAttr = metadata.attributes.find((t: any) => t.trait_type === "XP");
const winAttr = metadata.attributes.find((t: any) => t.trait_type === "Wins");
const lvlAttr = metadata.attributes.find((t: any) => t.trait_type === "Level");
if (xpAttr && winAttr && lvlAttr) {
const currentXP = Number(xpAttr.value);
const nextXP = currentXP + 15;
xpAttr.value = nextXP;
// Check level boundaries (every 100 XP triggers a Level increment)
if (Math.floor(nextXP / 100) > Math.floor(currentXP / 100)) {
lvlAttr.value = Number(lvlAttr.value) + 1;
}
winAttr.value = Number(winAttr.value) + 1;
}
return metadata;
}