You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: AGENTS.md
+61-41Lines changed: 61 additions & 41 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -136,6 +136,37 @@ snaps-simulation
136
136
snaps-jest
137
137
```
138
138
139
+
## Key Architectural Concepts
140
+
141
+
### SES and Compartments
142
+
143
+
Snaps run in [SES (Secure EcmaScript)](https://github.com/endojs/endo/tree/master/packages/ses) compartments for isolation. The compartment limits access to globals.
144
+
145
+
### Permission System
146
+
147
+
The platform uses `PermissionController` from `@metamask/permission-controller` extensively:
148
+
149
+
-**Subjects**: Websites, Snaps, or extensions that request permissions
150
+
-**Targets**: JSON-RPC methods or endowments being permissioned
151
+
-**Restricted methods**: JSON-RPC methods that require permission to call (e.g., `snap_getBip32Entropy`)
152
+
-**Permitted methods**: JSON-RPC methods available without special permission (e.g., `wallet_requestSnaps`). These generally do not pass through the `PermissionController`.
153
+
-**Endowment**: Capability granted to a Snap (e.g., `endowment:network-access`). May grant access to JavaScript globals.
154
+
-**Caveats**: Constraints that attenuate what a permission grants (e.g., limiting derivation paths)
155
+
-**Caveat mappers**: Functions that convert manifest values to caveat objects
156
+
157
+
### JSON-RPC Flow
158
+
159
+
Requests flow through a middleware stack in `json-rpc-engine`. Each connection (dapp or Snap) gets its own engine instance. The permission middleware checks authorization before allowing restricted method calls.
160
+
161
+
### Execution Flow
162
+
163
+
1.**SnapController** receives a request and starts the Snap if needed
164
+
2.**ExecutionService** creates an execution environment (iframe, worker, etc.)
165
+
3.**ExecutionEnvironment** sets up SES compartment with allowed endowments
166
+
4. Snap code is evaluated in the compartment
167
+
5. Exported handlers are registered and can receive requests
168
+
6. Responses are validated as JSON-serializable before returning
-**Job**: Execution task with Snap ID, streams, and JSON-RPC engine
201
-
-**Endowments**: APIs available in Snap context
202
-
203
210
## Adding New Platform Features
204
211
205
212
When implementing a new Snaps Platform feature (e.g., a new permission, endowment, or RPC method), include:
@@ -250,8 +257,23 @@ See `packages/examples/packages/multichain-provider/` for a complete example.
250
257
251
258
## Code Guidelines
252
259
260
+
### General
261
+
262
+
- Packages use `workspace:^` for internal dependencies
263
+
- Build uses `ts-bridge` (not tsc directly) to produce ESM and CJS outputs
264
+
- Tests use Jest with SWC for transformation; some packages also have Vitest browser tests
265
+
- JSX components use `@metamask/snaps-sdk/jsx` with automatic runtime
266
+
- Coverage threshold is 100% by default (some packages override this)
267
+
- Workspace package names use `@metamask/` scope (e.g., `@metamask/snaps-controllers`, not the directory name `snaps-controllers`)
268
+
- Use uppercase "Snap" (not "snap") in comments and documentation when referring to MetaMask Snaps
269
+
- Document all functions, classes, and types with JSDoc
270
+
- Use `@metamask/superstruct` for runtime validation of data structures, RPC parameters, and API inputs/outputs
271
+
- Define a `[Type]Struct` and infer the TypeScript type from it: `type MyType = Infer<typeof MyTypeStruct>`
272
+
- Validate early at system boundaries (RPC handlers, external data) rather than deep in business logic
273
+
253
274
### Controllers
254
275
276
+
- Controllers are generally used whenever we need to store state in the MetaMask clients
255
277
- Controller classes should extend `BaseController`
256
278
- Controllers must have state; stateless logic belongs in services
257
279
- Define public messenger types with actions and events
@@ -261,16 +283,14 @@ See `packages/examples/packages/multichain-provider/` for a complete example.
261
283
### Exports
262
284
263
285
- Each package has an `index.ts` that defines all public exports
264
-
- Use barrel exports (`export * from './module'`)
265
-
- Superstruct validators define both the struct and inferred type together
286
+
- Some packages have platform-specific entry points (e.g., `@metamask/snaps-utils/node`, `@metamask/snaps-controllers/node`, `@metamask/snaps-controllers/react-native`) for platform-specific APIs that shouldn't be bundled for other environments
266
287
267
-
### General
288
+
##Further Reading
268
289
269
-
- Packages use `workspace:^` for internal dependencies
270
-
- Build uses `ts-bridge` (not tsc directly) to produce ESM and CJS outputs
271
-
- Tests use Jest with SWC for transformation; some packages also have Vitest browser tests
272
-
- JSX components use `@metamask/snaps-sdk/jsx` with automatic runtime
273
-
- Coverage threshold is 100% by default (some packages override this)
274
-
- Workspace package names use `@metamask/` scope (e.g., `@metamask/snaps-controllers`, not the directory name `snaps-controllers`)
275
-
- Use uppercase "Snap" (not "snap") in comments and documentation when referring to MetaMask Snaps
276
-
- Document all functions, classes, and types with JSDoc
290
+
See `docs/` for detailed platform internals:
291
+
292
+
-`docs/internals/architecture.md` — System overview with sequence diagrams
293
+
-`docs/internals/permissions.md` — Permission system deep dive
294
+
-`docs/internals/execution.md` — SES sandboxing and endowments
0 commit comments