diff --git a/ERCS/erc-7846.md b/ERCS/erc-7846.md index a55396ddf8..bcbe752f23 100644 --- a/ERCS/erc-7846.md +++ b/ERCS/erc-7846.md @@ -12,129 +12,194 @@ created: 2024-12-15 ## Abstract -This ERC introduces a new wallet connection RPC method focused on extensibility. It leverages the modular capabilities approach defined in [ERC-5792](https://eips.ethereum.org/EIPS/eip-5792#wallet_getcapabilities) to streamline connections and authentication into a single interaction. +This ERC introduces a new wallet connection JSON-RPC method focused on extensibility. It leverages the modular capabilities approach defined in [ERC-5792](https://eips.ethereum.org/EIPS/eip-5792#wallet_getcapabilities) to streamline connections and authentication into a single interaction. ## Motivation -Current standards like `eth_requestAccounts` and `personal_sign` lack extensibility and require separate interactions for connection and authentication. This results in added complexity for both users and developers. A unified and extensible RPC can enhance user experience, simplify development, and prepare for increasing sophistication in wallet interactions. +With applications beginning to require support for more sophisticated functionality in wallet connection flows, the need for a unified and extensible wallet connection JSON-RPC method has become more apparent. + +This is especially evident in the case of attempting to batch connection with authentication, where existing methods like `eth_requestAccounts` and `personal_sign` lack extensibility and require at least two separate user interactions (ie. connect and then sign). ## Specification -### `wallet_connect` +### JSON-RPC Methods + +#### `wallet_connect` -Request the user to connect a single account and optionally confirm chain support and add capabilities. +Requests to connect account(s) with optional capabilities. -#### RPC Specification +##### Request -For each chain requested by the app, wallets MUST return a mapped capabilities object if the chain is supported and SHOULD return an empty object if no capabilities exist. Wallets MUST NOT return mapped capabilities objects for chains they do not support. If an app does not declare chains they would like to confirm support for, the wallet can return any chains it wishes to declare support for. +```ts +type Request = { + method: 'wallet_connect', + params: [{ + // JSON-RPC method version. + version: string; + // Optional capabilities to request (e.g. Sign In With Ethereum). + capabilities?: Record; + }] +} +``` -```typescript -type WalletConnectParams = [{ - version: string; - capabilities?: Record; // optional connection capabilities -}] +##### Response -type WalletConnectResult = { +List of connected accounts with their associated capabilities. + +```ts +type Response = { accounts: { - address: `0x${string}`; // connected account address - capabilities: Record; // results of this connection request's connection capabilities + // Address of the connected account. + address: `0x${string}`; + // Capabilities granted that is associated with this account. + capabilities: Record; }[] } ``` -#### Example Parameters - -```json -[{ - "version": "1", - "capabilities": { - "signInWithEthereum": { - "nonce": "12345678", - "chainId": "0x1" +##### Example + +```ts +const response = await provider.request({ + method: 'wallet_connect', + params: [{ + version: '1', + capabilities: { + signInWithEthereum: { + nonce: '12345678', + chainId: '0x1' + } } - } -}] + }] +}) +/** + * { + * accounts: [ + * { + * address: '0x...', + * capabilities: { + * signInWithEthereum: { + * message: 'app.com wants you to sign in with your Ethereum account:\n0x...', + * signature: '0x...' + * } + * } + * } + * ] + * } + */ ``` -#### Example Result - -```json -{ - "accounts": [ - { - "address": "0x...", - "capabilities": { - "signInWithEthereum": { - "message": "app.com wants you to sign in with your Ethereum account:\n0x...", - "signature": "0x..." - } - } - } - ] +#### `wallet_disconnect` + +Disconnects connected account(s). + +- The wallet SHOULD revoke any capabilities associated with the account(s) that were granted upon connection via `wallet_connect`. + +##### Request + +```ts +type Request = { + method: 'wallet_disconnect' } ``` -### `signInWithEthereum` Capability +##### Example -Adds authentication using the [ERC-4361](https://eips.ethereum.org/EIPS/eip-4361) Sign In WIth Ethereum standard. +```ts +await provider.request({ + method: 'wallet_disconnect', +}) +``` + +### Capabilities + +#### `signInWithEthereum` + +Adds support for offchain authentication using [ERC-4361: Sign-In with Ethereum](https://eips.ethereum.org/EIPS/eip-4361). -#### Capability Specification +##### Parameters Same as ERC-4361 specification with minor modifications: -* The casing of multi-word fields has been adjusted to mixedCase instead of hyphen-case. Resources are an array field. -* The account address returned by `wallet_connect` MUST be the same address that is auto-inserted into the SIWE message. +* The casing of multi-word fields has been adjusted to camelCase instead of kebab-case. Resources are an array field. +* The account address returned by `wallet_connect` MUST match the address inferred in the SIWE message. * `version` is optional and defaults to an accepted version defined in ERC-4361 if not provided. * `domain` is optional and defaults to the domain of the requesting app if not provided. * `uri` is optional and defaults to the uri of the requesting app if not provided. * `issuedAt` is optional and defaults to the current time if not provided. -The wallet MUST return a properly formatted ERC-4361 message that exactly matches the requested parameters and a signature over the EIP-191 hash of the message. The app SHOULD also verify that the two match for security. - -```typescript -type SignInWithEthereumCapabilityParams = { - nonce: string, - chainId: string, // EIP-155 hex-encoded - version?: string, - scheme?: string, - domain?: string, - uri?: string, - statement?: string - issuedAt?: string - expirationTime?: string, - notBefore?: string, - requestId?: string, - resources?: string[] -} - -type SignInWithEthereumCapabilityResult = { - message: string, // formatted SIWE message - signature: `0x${string}` // signed over EIP-191 hash of `message` +The wallet MUST return a ERC-4361-formatted message that exactly matches the requested parameters and a signature over the EIP-191 `personal_sign` hash of the message. The app SHOULD also verify that the two match for security. + +```ts +type Parameters = { + signInWithEthereum: { + nonce: string; + chainId: string; // EIP-155 hex-encoded + version?: string; + scheme?: string; + domain?: string; + uri?: string; + statement?: string; + issuedAt?: string; + expirationTime?: string; + notBefore?: string; + requestId?: string; + resources?: string[]; + } } ``` -#### Example Parameters - -```json -{ - "nonce": "12345678", - "chainId": "0x1", - "version": "1", - "domain": "app.com", - "uri": "https://app.com/connect", - "issuedAt": "2024-12-35T04:20:00Z", - "expirationTime": "2024-12-35T06:09:00Z" -} -``` +##### Response -#### Example Result +Formatted SIWE message and signature. -```json -{ - "message": "app.com wants you to sign in with your Ethereum account:\n0x...", - "signature": "0x..." +```ts +type Response = { + signInWithEthereum: { + // Formatted SIWE message. + message: string; + // Signature over the EIP-191 personal_sign hash of the message. + signature: `0x${string}`; + } } ``` +#### Example + +```ts +const result = await provider.request({ + method: 'wallet_connect', + params: [{ + version: '1', + capabilities: { + signInWithEthereum: { + nonce: '12345678', + chainId: '0x1', + version: '1', + domain: 'app.com', + uri: 'https://app.com/connect', + issuedAt: '2024-12-35T04:20:00Z', + expirationTime: '2024-12-35T06:09:00Z' + } + } + }] +}) +/** + * { + * accounts: [ + * { + * address: '0x...', + * capabilities: { + * signInWithEthereum: { + * message: 'app.com wants you to sign in with your Ethereum account:\n0x...', + * signature: '0x...' + * } + * } + * } + * ] + * } + */ +``` + ## Rationale ### Multiple Accounts @@ -153,7 +218,7 @@ By unifying connection and authentication into one step, apps can reduce frictio ## Backwards Compatibility -This standard builds on existing RPCs and complements ERC-5792 for future extensibility. Wallets can continue supporting legacy methods. +This standard builds on existing JSON-RPC methods and complements ERC-5792 for future extensibility. Wallets can continue supporting legacy methods. ## Security Considerations