GameFi Engine · Implementation
Как работают игровые механики
Два слоя: on-chain (редкость, уровень, PvP-результаты) и off-chain (ресурсы, экспедиции, энергия) для снижения газовых затрат.
📊 On-chain (Smart Contract)
- Владение NFT (ERC-721)
- Редкость звезды (immutable после минта)
- Уровень (level) — только владелец может повысить
- PvP-результаты (победы/поражения)
- Привязка к science_id
// Solidity — Star NFT с игровыми данными
contract ParagonStar is ERC721, ERC2981 {
struct StarData {
uint256 scienceId; // ссылка на каталог
uint8 rarity; // 0=common … 5=mythic
uint16 level; // 1-99
uint32 wins; // PvP победы
uint32 losses; // PvP поражения
}
mapping(uint256 => StarData) public stars;
mapping(uint256 => address) public lastBattleOpponent;
function levelUp(uint256 tokenId) external {
require(ownerOf(tokenId) == msg.sender);
require(stars[tokenId].level < 99);
// Проверка наличия ресурсов (off-chain оракул)
stars[tokenId].level++;
}
}
⚡ Off-chain (PostgreSQL + API)
- Энергия звезды (восстанавливается по времени)
- Ресурсы (Star Dust, Energy Crystals и др.)
- Экспедиции (запуск, прогресс, завершение)
- Созвездия (группировка звезд одного владельца)
- Научные ачивки (JWST, ISS, Mars)
// TypeScript — Серверный GameFi Engine
class GameFiEngine {
async startExpedition(starId: number, expeditionId: number) {
const star = await db.select().from(paragonStars)
.where(eq(paragonStars.id, starId)).limit(1);
const expedition = EXPEDITIONS.find(e => e.id === expeditionId);
if (star.energy < expedition.requiredEnergy)
throw new Error('Недостаточно энергии');
await db.insert(expeditionsLog).values({
starId, expeditionId, startTime: new Date(),
endTime: addHours(new Date(), expedition.durationHours),
});
return { status: 'started', endsAt: ... };
}
async claimExpedition(starId: number) {
const log = await db.select().from(expeditionsLog)
.where(and(
eq(expeditionsLog.starId, starId),
isNull(expeditionsLog.claimedAt)
)).limit(1);
if (!log || new Date() < log.endTime)
throw new Error('Экспедиция еще не завершена');
// Начисление ресурсов
await db.update(starResources)
.set({ star_dust: sql\`star_dust + $\{rewards.star_dust}\` })
.where(eq(starResources.starId, starId));
return { rewards };
}
}
Почему on-chain + off-chain? Полностью on-chain GameFi сделал бы каждое действие (добыча, экспедиция, ачивка) дорогим в газе. Off-chain слой хранит ресурсы и энергию, а on-chain — только финальные результаты (уровень, PvP, редкость). Это дает экономию газа в 100–1000 раз.