@metamask/keyring-api 1.0.0-rc.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/README.md +196 -40
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.0.0]
11
+
12
+ ### Added
13
+
14
+ - Add migration steps to 1.0.0 ([#149](https://github.com/MetaMask/keyring-api/pull/149)).
15
+ - Add Account Snaps security guidelines ([#143](https://github.com/MetaMask/keyring-api/pull/143)).
16
+
17
+ ### Changed
18
+
19
+ - Bump @metamask/rpc-errors from 6.0.0 to 6.1.0 ([#151](https://github.com/MetaMask/keyring-api/pull/151)).
20
+ - Bump postcss from 8.4.24 to 8.4.31 ([#150](https://github.com/MetaMask/keyring-api/pull/150)).
21
+
10
22
  ## [1.0.0-rc.1]
11
23
 
12
24
  ### Added
@@ -136,7 +148,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
136
148
  - SnapController keyring client. It is intended to be used by MetaMask to talk to the snap.
137
149
  - Helper functions to create keyring handler in the snap.
138
150
 
139
- [Unreleased]: https://github.com/MetaMask/keyring-api/compare/v1.0.0-rc.1...HEAD
151
+ [Unreleased]: https://github.com/MetaMask/keyring-api/compare/v1.0.0...HEAD
152
+ [1.0.0]: https://github.com/MetaMask/keyring-api/compare/v1.0.0-rc.1...v1.0.0
140
153
  [1.0.0-rc.1]: https://github.com/MetaMask/keyring-api/compare/v0.2.7...v1.0.0-rc.1
141
154
  [0.2.7]: https://github.com/MetaMask/keyring-api/compare/v0.2.6...v0.2.7
142
155
  [0.2.6]: https://github.com/MetaMask/keyring-api/compare/v0.2.5...v0.2.6
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > This TypeScript module is maintained in the style of the MetaMask team.
4
4
 
5
- This TypeScript module simplifies the integration of snaps with MetaMask using
5
+ This TypeScript module simplifies the integration of Snaps with MetaMask using
6
6
  the Keyring API.
7
7
 
8
8
  Features:
@@ -12,17 +12,17 @@ Features:
12
12
  MetaMask and leverage its functionality.
13
13
 
14
14
  - **Dapp Client**: The module includes a client that enables dapps to
15
- communicate with the Keyring snap. This client allows dapps to send requests
16
- to the snap, such as retrieving account information or submitting requests.
15
+ communicate with the Keyring Snap. This client allows dapps to send requests
16
+ to the Snap, such as retrieving account information or submitting requests.
17
17
 
18
18
  - **MetaMask Client**: The module provides a client specifically designed for
19
19
  MetaMask integration. This client enables MetaMask to send requests directly
20
- to the Keyring snap, facilitating smooth interoperability between the two
20
+ to the Keyring Snap, facilitating smooth interoperability between the two
21
21
  applications.
22
22
 
23
23
  - **Request Handler Helper Functions**: The module offers a set of helper
24
24
  functions to simplify the implementation of the request handler in the
25
- Keyring snap. These functions assist in processing incoming requests,
25
+ Keyring Snap. These functions assist in processing incoming requests,
26
26
  validating data, and handling various request types from dapps and MetaMask.
27
27
 
28
28
  ## Installation
@@ -33,54 +33,196 @@ or
33
33
 
34
34
  `npm install @metamask/keyring-api`
35
35
 
36
- ## Usage
36
+ ## Keyring Snaps
37
37
 
38
- ### In a snap
38
+ Starting with MetaMask 11.5, Snaps can implement the Keyring API. This allows
39
+ users to manage their accounts in a more flexible way, and enables developers
40
+ to build new types of accounts.
39
41
 
40
- Inside the snap, implement the `Keyring` API:
42
+ > [!IMPORTANT]
43
+ > Before implementing your Snap, please make sure to read the [security
44
+ > recommendations](./docs/security.md) and the [architecture
45
+ > document](./docs/architecture.md).
41
46
 
42
- ```typescript
43
- class MySnapKeyring implements Keyring {
44
- // Implement the required methods.
45
- }
46
- ```
47
+ Follow these steps to implement the Keyring API in your Snap. Please note that
48
+ these instruction assume that you are already familiar with the process of
49
+ [developing a Snap](https://docs.metamask.io/).
47
50
 
48
- Then create a handler that uses an instance of your keyring:
51
+ 1. **Implement the Keyring API:**
49
52
 
50
- ```typescript
51
- import { keyringRpcDispatcher } from '@metamask/keyring-api';
53
+ Inside your Snap, implement the `Keyring` API:
52
54
 
53
- // Create a new MySnapKeyring instance
54
- keyring = new MySnapKeyring(keyringState);
55
- // ...
55
+ ```typescript
56
+ class MySnapKeyring implements Keyring {
57
+ // Implement the required methods here...
58
+ }
59
+ ```
56
60
 
57
- // And wrap it in a handler
58
- const keyringHandler: OnRpcRequestHandler = async ({ request }) => {
59
- // Load the keyring state if needed
60
- // ...
61
- return await keyringRpcDispatcher(keyring, request);
62
- };
63
- ```
61
+ > [!WARNING]
62
+ > Ensure that your keyring implements the [methods called by
63
+ > MetaMask](./docs/security.md#limit-the-methods-exposed-to-dapps),
64
+ > otherwise some features may not work.
64
65
 
65
- Now expose this handler:
66
+ 2. **Handle requests submitted by MetaMask:**
66
67
 
67
- ```typescript
68
- export const onRpcRequest: OnRpcRequestHandler = keyringHandler;
69
- ```
68
+ MetaMask will submit requests through the `submitRequest` method of your the
69
+ Keyring API (check the supported [EVM methods](./docs/evm_methods.md)). Here
70
+ is an example of request:
70
71
 
71
- Or chain it with other handlers:
72
+ ```json
73
+ {
74
+ "id": "d6e23af6-4bea-48dd-aeb0-7d3c30ea67f9",
75
+ "scope": "",
76
+ "account": "69438371-bef3-4957-9f91-c3f22c1d75f3",
77
+ "request": {
78
+ "method": "personal_sign",
79
+ "params": [
80
+ "0x4578616d706c652060706572736f6e616c5f7369676e60206d657373616765",
81
+ "0x5874174dcf1ab6F7Efd8496f4f09404CD1c5bA84"
82
+ ]
83
+ }
84
+ }
85
+ ```
72
86
 
73
- ```typescript
74
- import { chainHandlers } from '@metamask/keyring-api';
87
+ Where:
75
88
 
76
- export const onRpcRequest: OnRpcRequestHandler = chainHandlers(
77
- // Other handlers...
78
- keyringHandler,
79
- // Other handlers...
80
- );
81
- ```
89
+ - `id` is unique identifier for the request.
90
+
91
+ - `scope` is the CAIP-2 chain ID of the selected chain. Currently, this
92
+ property is always an empty string. Your Snap should use the chain ID
93
+ present in the request object instead.
94
+
95
+ - `account` is the ID of the account that should handle the request.
82
96
 
83
- ### Migrating from API 0.1.x to 0.2.x
97
+ - `request` is the request object.
98
+
99
+ Your Snap must respond with either a synchronous result:
100
+
101
+ ```typescript
102
+ return { pending: false, result };
103
+ ```
104
+
105
+ Or an asynchronous result:
106
+
107
+ ```typescript
108
+ return { pending: true, redirect: { message, url } };
109
+ ```
110
+
111
+ The redirect message and URL will be displayed to the user to inform them
112
+ about how to continue the transaction flow.
113
+
114
+ 3. **Notify MetaMask about events:**
115
+
116
+ The following actions must be notified to MetaMask:
117
+
118
+ 1. When an account is created:
119
+
120
+ ```typescript
121
+ try {
122
+ emitSnapKeyringEvent(snap, KeyringEvent.AccountCreated, { account });
123
+ // Update your snap's state...
124
+ } catch (error) {
125
+ // Handle the error...
126
+ }
127
+ ```
128
+
129
+ MetaMask will return an error if the account already exists or if the
130
+ account object is invalid.
131
+
132
+ 2. When an account is updated:
133
+
134
+ ```typescript
135
+ try {
136
+ emitSnapKeyringEvent(snap, KeyringEvent.AccountUpdated, { account });
137
+ // Update your snap's state...
138
+ } catch (error) {
139
+ // Handle the error...
140
+ }
141
+ ```
142
+
143
+ MetaMask will return an error if the account does not exist, if the
144
+ account object is invalid, or if the account address changed.
145
+
146
+ 3. When an account is deleted:
147
+
148
+ ```typescript
149
+ try {
150
+ emitSnapKeyringEvent(snap, KeyringEvent.AccountDeleted, {
151
+ id: account.id,
152
+ });
153
+ // Update your snap's state...
154
+ } catch (error) {
155
+ // Handle the error...
156
+ }
157
+ ```
158
+
159
+ The delete event is idempotent, so it is safe to emit it even if the
160
+ account does not exist.
161
+
162
+ 4. When a request is approved:
163
+
164
+ ```typescript
165
+ try {
166
+ emitSnapKeyringEvent(snap, KeyringEvent.RequestApproved, {
167
+ id: request.id,
168
+ result,
169
+ });
170
+ // Update your snap's state...
171
+ } catch (error) {
172
+ // Handle the error...
173
+ }
174
+ ```
175
+
176
+ MetaMask will return an error if the request does not exist.
177
+
178
+ > [!NOTE]
179
+ > This only applies to Snaps that implement the [async
180
+ > flow](./docs/architecture.md#transaction-flow).
181
+
182
+ 5. When a request is rejected:
183
+
184
+ ```typescript
185
+ try {
186
+ emitSnapKeyringEvent(snap, KeyringEvent.RequestRejected, {
187
+ id: request.id,
188
+ });
189
+ // Update your snap's state...
190
+ } catch (error) {
191
+ // Handle the error...
192
+ }
193
+ ```
194
+
195
+ MetaMask will return an error if the request does not exist.
196
+
197
+ > [!NOTE]
198
+ > This only applies to Snaps that implement the [async
199
+ > flow](./docs/architecture.md#transaction-flow).
200
+
201
+ 4. **Expose the Keyring API:**
202
+
203
+ Then create a handler to expose the keyring methods to MetaMask and your dapp:
204
+
205
+ ```typescript
206
+ export const onKeyringRequest: OnKeyringRequestHandler = async ({
207
+ origin,
208
+ request,
209
+ }) => {
210
+ // Your custom logic here...
211
+ return handleKeyringRequest(keyring, request);
212
+ };
213
+ ```
214
+
215
+ 5. **Call the keyring methods from your dapp:**
216
+
217
+ Now you should be able to call your Keyring Snap from your dapp, for
218
+ example:
219
+
220
+ ```typescript
221
+ const client = new KeyringSnapRpcClient(snapId, window.ethereum);
222
+ const accounts = await client.listAccounts();
223
+ ```
224
+
225
+ ## Migrating from 0.1.x to 0.2.x
84
226
 
85
227
  The following changes were made to the API, which may require changes to your
86
228
  implementation:
@@ -180,6 +322,20 @@ implementation:
180
322
  };
181
323
  ```
182
324
 
325
+ ## Migrating from 0.2.x to 1.x.x
326
+
327
+ The following changes were made to the API, which may require changes to your
328
+ implementation:
329
+
330
+ - Your Snap must expose the Keyring methods through the `onKeyringRequest`
331
+ export instead of the `onRpcRequest` export.
332
+
333
+ - Your Snap must request the new `endowment:keyring` endowment, and list any
334
+ dapp that should be allowed to call the Keyring methods.
335
+
336
+ For more details about the changes, please refer to the [security
337
+ guidelines](./docs/security.md).
338
+
183
339
  ## API
184
340
 
185
341
  See our documentation:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/keyring-api",
3
- "version": "1.0.0-rc.1",
3
+ "version": "1.0.0",
4
4
  "description": "MetaMask Keyring API",
5
5
  "keywords": [
6
6
  "metamask",