Skip to content

Commit

Permalink
feat: EIP-3074 signAuthMessage + utils (#2155)
Browse files Browse the repository at this point in the history
* wip: signAuthMessage + utils

* docs

* chore: update snaps

* chore: changeset
  • Loading branch information
jxom committed Apr 19, 2024
1 parent ca133ce commit 803fa0d
Show file tree
Hide file tree
Showing 48 changed files with 1,223 additions and 127 deletions.
9 changes: 9 additions & 0 deletions .changeset/tiny-papayas-guess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"viem": patch
---

Added experimental 3074 utilties:

- `signAuthMessage`
- `recoverAuthMessageAddress`
- `verifyAuthMessage`
2 changes: 1 addition & 1 deletion site/pages/experimental.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const client = createWalletClient({

### 3. Consume Experimental Actions

Now that you have an Experimental Client set up, you can now and consume [Actions](/experimental/actions/sendCalls)!
Now that you have an Experimental Client set up, you can now and consume [Actions](/experimental/eip5792/sendCalls)!

```tsx
import { createWalletClient, custom, parseEther } from 'viem'
Expand Down
139 changes: 139 additions & 0 deletions site/pages/experimental/eip3074/recoverAuthMessageAddress.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
---
description: Recovers the original signing address from an auth message & signature.
---

# recoverAuthMessageAddress

Recovers the original signing address from an auth message & signature.

## Usage

:::code-group

```ts twoslash [example.ts]
import { recoverAuthMessageAddress } from 'viem/experimental'
import { account, walletClient } from './config'

const args = {
chainId: 1,
commit: keccak256('0x1234'),
invokerAddress: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
nonce: 69,
}

const signature = await walletClient.signAuthMessage({
...args,
account,
})

const address = await recoverAuthMessageAddress({ // [!code focus:99]
...args,
signature,
})
```

```ts twoslash [config.ts] filename="config.ts"
import { createWalletClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { walletActionsEip3074 } from 'viem/experimental'

export const walletClient = createWalletClient({
chain: mainnet,
transport: http(),
}).extend(walletActionsEip3074())
```

:::

## Returns

`Address`

The recovered address.

## Parameters

### chainId

- **Type:** `number`

The chain ID.

```ts
const address = await recoverAuthMessageAddress({
chainId: 1, // [!code focus]
commit: keccak256('0x1234'),
invokerAddress: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
nonce: 69,
signature:
'0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c',
})
```

### commit

- **Type:** `Hash`

The commit.

```ts
const address = await recoverAuthMessageAddress({
chainId: 1,
commit: keccak256('0x1234'), // [!code focus]
invokerAddress: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
nonce: 69,
signature:
'0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c',
})
```

### invokerAddress

- **Type:** `Hash`

Address of the intended invoker.

```ts
const address = await recoverAuthMessageAddress({
chainId: 1,
commit: keccak256('0x1234'),
invokerAddress: '0xd2135CfB216b74109775236E36d4b433F1DF507B', // [!code focus]
nonce: 69,
signature:
'0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c',
})
```

### nonce

- **Type:** `Hash`

Nonce of the sender account.

```ts
const address = await recoverAuthMessageAddress({
chainId: 1,
commit: keccak256('0x1234'),
invokerAddress: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
nonce: 69, // [!code focus]
signature:
'0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c',
})
```

### signature

- **Type:** `Hex | ByteArray`

The signature that was generated by signing the message with the address's private key.

```ts
const address = await recoverAuthMessageAddress({
chainId: 1,
commit: keccak256('0x1234'),
invokerAddress: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
nonce: 69,
signature: // [!code focus:2]
'0x66edc32e2ab001213321ab7d959a2207fcef5190cc9abb6da5b0d2a8a9af2d4d2b0700e2c317c4106f337fd934fbbb0bf62efc8811a78603b33a8265d3b8f8cb1c',
})
```
186 changes: 186 additions & 0 deletions site/pages/experimental/eip3074/signAuthMessage.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
# signAuthMessage

Calculates an [EIP-3074](https://eips.ethereum.org/EIPS/eip-3074) auth signature.

With the calculated signature, you can:

- pass it to an EIP-3074 compatible invoker contract,
- use [`verifyAuthMessage`](/experimental/eip3074/verifyAuthMessage) to verify the signature,
- use [`recoverAuthMessageAddress`](/experimental/eip3074/recoverAuthMessageAddress) to recover the signing address from a signature.

## Usage

:::code-group

```ts twoslash [example.ts]
import { privateKeyToAccount } from 'viem/accounts'
import { account, walletClient } from './config'

const account = privateKeyToAccount('0x...')

const signature = await walletClient.signAuthMessage({ // [!code focus:99]
account,
chainId: 1,
commit: keccak256('0x1234'),
invokerAddress: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
nonce: 69,
})
```

```ts twoslash [config.ts] filename="config.ts"
import { createWalletClient, http } from 'viem'
import { mainnet } from 'viem/chains'
import { walletActionsEip3074 } from 'viem/experimental'

export const walletClient = createWalletClient({
chain: mainnet,
transport: http(),
}).extend(walletActionsEip3074())
```

:::

:::tip[Tip]

Viem also exposes an `experimental_signAuthMessage` method on the `LocalAccount` interface.

Helpful if you don't need the ceremony of setting up a Viem Client.

```ts twoslash
import { keccak256 } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'

// ---cut---
const account = privateKeyToAccount('0x...')

const signature = await account.experimental_signAuthMessage({
chainId: 1,
commit: keccak256('0x1234'),
invokerAddress: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
nonce: 69,
})
```

:::

### Account Hoisting

If you do not wish to pass an `account` to every `signAuthMessage`, you can also hoist the Account on the Wallet Client (see `config.ts`).

[Learn more](/docs/clients/wallet#withaccount).

:::code-group

```ts twoslash [example.ts]
import { walletClient } from './config'

const signature = await walletClient.signAuthMessage({ // [!code focus:99]
chainId: 1,
commit: keccak256('0x1234'),
invokerAddress: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
nonce: 69,
})
```

```ts twoslash [config.ts] filename="config.ts"
import { createWalletClient, http } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { mainnet } from 'viem/chains'
import { walletActionsEip3074 } from 'viem/experimental'

export const walletClient = createWalletClient({
account: privateKeyToAccount('0x...'), // [!code ++]
chain: mainnet,
transport: http(),
}).extend(walletActionsEip3074())
```

:::

## Returns

[`Hex`](/docs/glossary/types#hex)

The signed auth message.

## Parameters

### chainId

- **Type:** `number`

The chain ID.

```ts twoslash
import { keccak256 } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'

const account = privateKeyToAccount('0x...')
// ---cut---
const signature = await account.experimental_signAuthMessage({
chainId: 1, // [!code focus]
commit: keccak256('0x1234'),
invokerAddress: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
nonce: 69,
})
```

### commit

- **Type:** `Hash`

The commit.

```ts twoslash
import { keccak256 } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'

const account = privateKeyToAccount('0x...')
// ---cut---
const signature = await account.experimental_signAuthMessage({
chainId: 1,
commit: keccak256('0x1234'), // [!code focus]
invokerAddress: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
nonce: 69,
})
```

### invokerAddress

- **Type:** `Hash`

Address of the intended invoker.

```ts twoslash
import { keccak256 } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'

const account = privateKeyToAccount('0x...')
// ---cut---
const signature = await account.experimental_signAuthMessage({
chainId: 1,
commit: keccak256('0x1234'),
invokerAddress: '0xd2135CfB216b74109775236E36d4b433F1DF507B', // [!code focus]
nonce: 69,
})
```

### nonce

- **Type:** `Hash`

Nonce of the sender account.

```ts twoslash
import { keccak256 } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'

const account = privateKeyToAccount('0x...')
// ---cut---
const signature = await account.experimental_signAuthMessage({
chainId: 1,
commit: keccak256('0x1234'),
invokerAddress: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
nonce: 69, // [!code focus]
})
```
Loading

0 comments on commit 803fa0d

Please sign in to comment.