package chunk import ( "chain" "chain/runtime" "strconv" "gno.land/p/demo/tokens/grc721" "gno.land/p/nt/ufmt" ) const ( GrantMasterEvent = "GrantMaster" RevokeMasterEvent = "RevokeMaster" ) var ( // World masters: worldID -> address -> bool worldMasters = make(map[uint32]map[address]bool) ) // ==================== Admin Functions ==================== // GrantMaster grants master role to a user for a world (admin only) func GrantMaster(cur realm, worldID uint32, user address) { caller := runtime.PreviousRealm().Address() assertIsAdmin(caller) mustGetWorld(worldID) if _, found := worldMasters[worldID]; !found { worldMasters[worldID] = make(map[address]bool) } if worldMasters[worldID][user] { panic("user " + user.String() + " is already a master for world " + ufmt.Sprintf("%d", worldID)) } worldMasters[worldID][user] = true chain.Emit( GrantMasterEvent, "worldID", ufmt.Sprintf("%d", worldID), "user", user.String(), ) } // RevokeMaster revokes master role from a user for a world (admin only) func RevokeMaster(cur realm, worldID uint32, user address) { caller := runtime.PreviousRealm().Address() assertIsAdmin(caller) if _, found := worldMasters[worldID]; !found { panic("user " + user.String() + " is not a master for world " + ufmt.Sprintf("%d", worldID)) } if !worldMasters[worldID][user] { panic("user " + user.String() + " is not a master for world " + ufmt.Sprintf("%d", worldID)) } delete(worldMasters[worldID], user) // Clean up empty map if len(worldMasters[worldID]) == 0 { delete(worldMasters, worldID) } chain.Emit( RevokeMasterEvent, "worldID", ufmt.Sprintf("%d", worldID), "user", user.String(), ) } // ==================== Query Functions ==================== // IsMaster checks if a user is a master for a world func IsMaster(worldID uint32, user address) bool { if _, found := worldMasters[worldID]; !found { return false } return worldMasters[worldID][user] } // ListWorldMasters returns all masters for a world func ListWorldMasters(worldID uint32) []address { result := []address{} if masters, found := worldMasters[worldID]; found { for addr := range masters { result = append(result, addr) } } return result } // ListMasterWorlds returns all worlds where a user is a master func ListMasterWorlds(user address) []uint32 { result := []uint32{} for worldID, masters := range worldMasters { if masters[user] { result = append(result, worldID) } } return result } // ==================== Helper Functions ==================== // getWorldIDFromTokenID extracts worldID from tokenID func getWorldIDFromTokenID(tid grc721.TokenID) uint32 { worldIDStr, _ := parseTokenID(tid) worldID, err := strconv.Atoi(worldIDStr) if err != nil { panic("invalid worldID: " + worldIDStr) } return uint32(worldID) }