Namespaces
Namespaces are used to partition and manage all registered systems and table resources in the autonomous world, forming resource subsets of systems and tables. Namespaces are closely related to permission control in the autonomous world.
Creating a Namespace
We typically use the configuration file mud.config.ts to create a
namespace.
import { defineWorld } from "@latticexyz/world";
export default defineWorld({
namespace: "muddoc",
tables: ...
systems: ...
});
The content of the above configuration file defines a namespace called
muddoc, and all tables and systems defined in tables and
systems will be registered under this namespace.
Manual Creation
We often need to manually create a namespace when using modules.
IWorld(worldAddress).registerNamespace({namespaceId: WorldResourceIdLib.encodeNamespace("muddoc")});
Creating Multiple Namespaces
Starting from Mud 2.1.0, we can create multiple namespaces using a
single configuration file.
import { defineWorld } from "@latticexyz/world";
export default defineWorld({
namespaces: {
muddoc: {
tables: ...
systems: ...
},
fun: {
tables: ...
systems: ...
}
},
// namespace: ... ❌
// tables: ... ❌
// systems: ... ❌
});
When we use namespaces, it means we’ve enabled multi-namespace mode,
and the namespace field will be disabled. Similarly, the tables
and systems fields are also disabled; these fields need to be used
under each individual namespace in namespaces. Each key-value pair
in namespaces defines a namespace. The key serves as the namespace
name, and the value is an object containing tables and systems.
Note
In multi-namespace mode, the usage of enums and userTypes
remains unchanged.
Using multi-namespace mode also requires us to organize our project directory according to namespaces, for example:
src
├── codegen
│ └── world
└── namespaces
├── fun
│ ├── codegen
│ │ └── tables
│ └── systems
└── app
├── codegen
│ └── tables
└── systems
The recommended location for systems is
src/namespaces/<namespace-name>/systems/.
Access Control
Without any access configuration, all addresses have some basic access, including:
Reading all tables
Using all systems with public access enabled
For registered systems, in addition to basic access, they can also:
Update all tables within the same namespace
Use all systems within the same namespace, even if they don’t have public access enabled
Any additional resource access beyond these designed rights requires authorization from the namespace owner.
The basic process of access checking is:
(If accessing a system) Check if the system has public access enabled.
Check if the accessor has been granted access to the namespace of the access object.
Note
If an accessor has namespace access, they can access all systems and tables within that namespace. No separate authorization is needed for each system and table.
Check if the accessor has been granted access to the access object.
Access Management
Access management include granting and revoking access. The objects of access management are resources, including tables, systems, and namespaces. The operator managing access must be the owner of the namespace to which the operation object belongs.
// table type resource
ResourceId tableId = WorldResourceIdLib.encode("tb", "muddoc", "Table1");
// system type resource
ResourceId systemId = WorldResourceIdLib.encode("sy", "muddoc", "System1");
// namespace type resource
ResourceId namespaceId = WorldResourceIdLib.encodeNamespace("muddoc");
// grant access to a resource
IWorld(worldAddress).grantAccess({
resourceId: specificResourceId,
grantee: granteeAddress
});
// revoke access to a resource
IWorld(worldAddress).revokeAccess({
resourceId: specificResourceId,
grantee: granteeAddress
});
Note
Granting access to a namespace is equivalent to granting access to all resources within that namespace.
Important
If an address has been granted access to individual systems or tables, revoking its access to the namespace won’t affect its access to these individual resources.
In this case, if you want to prohibit access to all internal resources, you need to revoke access to each previously individually authorized resource.
Namespace Ownership Management
The initial owner of a namespace is its creator. The namespace owner can transfer or renounce ownership.
// Transfer namespace ownership
IWorld(worldAddress).transferNamespaceOwnership({
namespaceId: WorldResourceIdLib.encodeNamespace("muddoc"),
newOwner: newOwnerAddress
});
// Renounce namespace ownership
IWorld(worldAddress).renounceOwnership({
namespaceId: WorldResourceIdLib.encodeNamespace("muddoc")
});
Note
When a namespace is created, it is granted access to its creator.
When ownership changes, the original owner will revoke their own access to the namespace, and the new owner will be granted access.
Important
If the original owner had granted themselves access to individual system or table resources, changing ownership won’t cause them to lose access to these resources. If the new owner wishes to prohibit these accesses, they should manually revoke these access.