Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ERC-7846: Wallet Connection API #779

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
235 changes: 150 additions & 85 deletions ERCS/erc-7846.md
Original file line number Diff line number Diff line change
@@ -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<string, unknown>;
}]
}
```

```typescript
type WalletConnectParams = [{
version: string;
capabilities?: Record<string,any>; // 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<string,any>; // 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<string, unknown>;
}[]
}
```

#### 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

Loading