Imported from Provable-Games/game-components (
packages/interfaces/src/AGENTS.md). Install upstream withnpx skills add Provable-Games/game-components --skill src. Copyright stays with the author.
Package: interfaces
Single source of truth for all game component interface definitions. Other packages import from here for cross-contract calls and SRC5 interface detection.
Interface Modules
| Module | Interfaces | Purpose |
|---|---|---|
metagame |
IMetagame, IMetagameContext, IMetagameCallback |
Game management, context extensions |
minigame |
IMinigame, IMinigameTokenData, IMinigameSettings, IMinigameObjectives |
Game logic, score/game_over queries |
token (token/core) |
IMinigameToken |
THE minigame token standard: gas-optimized token embedded in the game contract itself (self-bound, no registry, no mutable state), plus the IMinigameTokenMinter surface |
token/game_fee |
IMinigameTokenGameFee |
Game fee recipient (payout sink) + license + fee rate on the standard token (replaces the registry's game_fee_info); setters gated on the game contract's Ownable owner |
leaderboard |
ILeaderboard, ILeaderboardAdmin, IGameDetails |
Tournament scoring and rankings |
tokenomics/buyback |
IBuyback, IBuybackAdmin |
Autonomous buyback via Ekubo TWAMM |
tokenomics/stream |
IStreamToken, IStreamTokenFactory |
Token distribution streams |
Struct Modules
| Module | Structs |
|---|---|
structs/token |
TokenMetadata, Lifecycle, MintBatchRecipient, GameFeeTerms |
structs/minigame |
GameMetadata, GameDetail, GameSettingDetails, GameSetting, GameObjective |
structs/metagame |
GameContextDetails, GameContext |
structs/leaderboard |
LeaderboardConfig, LeaderboardEntry, LeaderboardResult, LeaderboardStoreConfig |
Interface ID Constants
pub const IMETAGAME_CONTEXT_ID: felt252 = 0x...;
pub const IMINIGAME_ID: felt252 = 0x...;
pub const IMINIGAME_SETTINGS_ID: felt252 = 0x...;
pub const IMINIGAME_OBJECTIVES_ID: felt252 = 0x...;
pub const IMINIGAME_TOKEN_ID: felt252 = 0x...;
pub const IMINIGAME_TOKEN_MINTER_ID: felt252 = 0x...;
pub const IMINIGAME_TOKEN_GAME_FEE_ID: felt252 = 0x...;
pub const ILEADERBOARD_ID: felt252 = 0x...;
Usage Patterns
Cross-Contract Calls (Dispatcher Pattern)
use game_components_interfaces::{
IMinigameDispatcher, IMinigameDispatcherTrait,
IMinigameTokenDispatcher, IMinigameTokenDispatcherTrait,
};
// Call another contract
let minigame = IMinigameDispatcher { contract_address: game_address };
let score = minigame.score(token_id);
let is_over = minigame.game_over(token_id);
SRC5 Interface Registration
use game_components_interfaces::{IMINIGAME_ID, IMINIGAME_SETTINGS_ID};
use openzeppelin_introspection::src5::SRC5Component;
// In component initialization
self.src5.register_interface(IMINIGAME_ID);
// Check if contract supports interface
let supports = src5_dispatcher.supports_interface(IMINIGAME_SETTINGS_ID);
Importing Structs
use game_components_interfaces::{
TokenMetadata, Lifecycle, MintBatchRecipient,
GameMetadata, GameDetail,
LeaderboardEntry, LeaderboardConfig,
};
Key Interface Methods
IMinigameTokenData (required for minigame contracts):
score(token_id: u64) -> u32- Get token's current scoregame_over(token_id: u64) -> bool- Check if game has ended
IMinigame (identity views only — self-bound game returns its own address):
token_address() -> ContractAddresssettings_address() -> ContractAddressobjectives_address() -> ContractAddress
ILeaderboard:
submit_score(tournament_id, token_id, score, position) -> LeaderboardResultget_entries(tournament_id) -> Array<LeaderboardEntry>qualifies(tournament_id, score) -> bool
Computing SRC5 Interface IDs
Use src5_rs parse to compute interface IDs. The tool is pre-installed at ~/.cargo/bin/src5_rs.
Critical: src5_rs v2.0.0 cannot parse modern Cairo <TState> generics or self parameters. You must create a temporary stripped-down file:
- Remove
<TState>generic from the trait - Remove
self: @TState/ref self: TStatefrom all function signatures - Include struct definitions inline (the tool doesn't resolve imports)
- Remove
#[starknet::interface]andpubmodifiers
Example — to compute the ID for:
#[starknet::interface]
pub trait IMinigameTokenObjectives<TState> {
fn create_objective(
ref self: TState,
game_address: ContractAddress,
creator_address: ContractAddress,
objective_id: u32,
objective_details: GameObjectiveDetails,
);
}
Create /tmp/src5_input.cairo:
use starknet::ContractAddress;
struct GameObjective {
name: ByteArray,
value: ByteArray,
}
struct GameObjectiveDetails {
name: ByteArray,
description: ByteArray,
objectives: Span<GameObjective>,
}
trait IMinigameTokenObjectives {
fn create_objective(
game_address: ContractAddress,
creator_address: ContractAddress,
objective_id: u32,
objective_details: GameObjectiveDetails,
);
}
Then run:
src5_rs parse /tmp/src5_input.cairo
The tool outputs the extended function selectors and the final XOR'd interface ID.
Important notes:
ByteArrayexpands to(Array<bytes31>,felt252,usize)— noteusize, notu32boolexpands toE((),())(an enum)Span<T>expands to(@Array<T>)- For multi-function interfaces, the ID is the XOR of all extended function selectors
- For single-function interfaces, the ID equals the single extended function selector
- Always update the EFS comment above the constant to match the tool's output
Methods excluded from IMINIGAME_TOKEN_ID
IMINIGAME_TOKEN_ID is derived over IMinigameToken minus refresh_metadata.
Omit that method from the stripped input file or the constant will not reproduce
(the per-selector breakdown is kept in the doc comment above the constant in
token/core.cairo).
The ID is registered on-chain by every deployed token contract. Rederiving it to
cover an additive, optional method would make
supports_interface(IMINIGAME_TOKEN_ID) return false on all of them and break
interface discovery for every existing consumer — a breaking change across the
ecosystem in exchange for nothing a caller can act on. The ID identifies the
original surface, which those contracts all still implement in full.
Apply the same reasoning to future additive methods: extend the trait, leave the ID alone, and note the exclusion here. Change the ID only for a genuinely breaking change to the existing surface.
Frozen IMINIGAME_TOKEN_ID value
The token interface-id VALUE is frozen — deployed contracts register it on-chain. When the lite token became the standard, only the NAME moved:
| Constant (today) | Value | Was named |
|---|---|---|
IMINIGAME_TOKEN_ID |
0x20253de95bcdb23620c88405a5f97da040b91de832ad98a34b45c4f3331d13b |
IMINIGAME_TOKEN_LITE_ID |
Dependencies
None - this is a leaf package with no internal dependencies. Uses only:
starknetstdlibekubo(for tokenomics interfaces only)