Soroban contract for storing non-transferable Stellar Wrap records by wallet and reporting successful wrap mints through events.
The contract is split into focused modules:
src/lib.rs: contract type and module wiringsrc/admin.rs: initialization and admin updatessrc/mint.rs: period validation, signature verification, wrap minting, event emissionsrc/queries.rs: read-only queries and metadatasrc/errors.rs: contract error codessrc/storage_types.rs: storage keys and persisted record types
Each wrap record stores:
timestamp: u64data_hash: BytesN<32>archetype: Symbolperiod: u64
period is encoded as YYYYMM and validated on mint:
- year must be between
2024and2100 - month must be between
01and12
DataKey::AdminDataKey::AdminPubKeyDataKey::Wrap(Address, u64)DataKey::WrapCount(Address)DataKey::LatestPeriod(Address)
initialize(e: Env, admin: Address, admin_pubkey: BytesN<32>)update_admin(e: Env, new_admin: Address)mint_wrap(e: Env, user: Address, period: u64, archetype: Symbol, data_hash: BytesN<32>, signature: BytesN<64>)
get_wrap(e: Env, user: Address, period: u64) -> Option<WrapRecord>balance_of(e: Env, user: Address) -> i128verify_data(e: Env, user: Address, period: u64, data: Bytes) -> boolget_latest_wrap(e: Env, user: Address) -> Option<WrapRecord>get_admin(e: Env) -> Option<Address>name(e: Env) -> Stringsymbol(e: Env) -> Stringdecimals(e: Env) -> u32
Successful wrap mints emit one event:
- Topic 0:
mint - Topic 1:
user(Address) - Topic 2:
period(u64,YYYYMM) - Data:
archetype(Symbol)
Properties relevant to indexers:
- the event is emitted only after signature verification and storage writes succeed
- duplicate
(user, period)mints are rejected, so one event equals one successful new wrap periodis always a validatedYYYYMMvalue
Issue #68 is implemented as an off-chain leaderboard strategy.
Reasoning:
- Soroban storage does not support efficient range scans for ranking
- maintaining an on-chain sorted top-N list would add write amplification and higher gas costs to every mint
- indexers already need mint events for analytics, so leaderboard aggregation fits the existing data flow
Recommended aggregation rule:
- index every
mintevent - group by topic 1 (
user) - count events per user
- sort descending by count to produce the leaderboard
Run the test suite with:
cargo test