Skip to content

Commit

Permalink
Merge pull request #57 from thomas779/main
Browse files Browse the repository at this point in the history
refac: webauthn guide
  • Loading branch information
kopy-kat authored Jan 27, 2025
2 parents 4330d1e + c3f9d43 commit 1af85c9
Showing 1 changed file with 19 additions and 19 deletions.
38 changes: 19 additions & 19 deletions pages/module-sdk/using-modules/webauthn.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,20 @@ We will first set up the smart account, install the Webauthn Module, and use a p

### Install the packages

First, install the required packages. We use the latest version of module sdk, permissionless ^0.2, viem ^2.21, wagmi ^2.14 and webauthn-p256 ^0.0.10.
First, install the required packages. We use the latest version of module sdk, permissionless ^0.2, viem ^2.21 and ox ^0.6.0.

```sh npm2yarn
npm i viem @rhinestone/module-sdk permissionless wagmi webauthn-p256
npm i viem @rhinestone/module-sdk permissionless ox
```

### Import the required functions and constants

```typescript copy
import { useCallback, useState } from "react";
import { useAccount, usePublicClient, useWalletClient } from "wagmi";
import {
toSafeSmartAccount,
ToSafeSmartAccountReturnType,
} from "permissionless/accounts";
import { Chain, http, Transport } from "viem";
import { Erc7579Actions } from "permissionless/actions/erc7579";
import { http, Transport } from "viem";
import { createSmartAccountClient, SmartAccountClient } from "permissionless";
import {
createWebAuthnCredential,
Expand All @@ -46,9 +43,11 @@ import {
getWebauthnValidatorSignature,
} from "@rhinestone/module-sdk";
import { baseSepolia } from "viem/chains";
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
import { getAccountNonce } from "permissionless/actions";
import { parsePublicKey, parseSignature, sign } from "webauthn-p256";
import { erc7579Actions } from "permissionless/actions/erc7579";
import { PublicKey } from "ox";
import { sign } from "ox/WebAuthnP256";
```

### Create the clients
Expand All @@ -58,7 +57,7 @@ Create the smart account client and the pimlico client. You will need to add you
```typescript copy
const publicClient = createPublicClient({
transport: http(rpcUrl),
chain: chain,
chain: baseSepolia,
})

const pimlicoClient = createPimlicoClient({
Expand All @@ -72,10 +71,12 @@ const pimlicoClient = createPimlicoClient({

### Create the signer

The Safe account will need to have a signer to sign user operations. In this case, since we are developing this code in a frontend, we can use wagmi to access the connected wallet signer.
The Safe account will need to have a signer to sign user operations. In permissionless.js, the default Safe account validates ECDSA signatures.

For example, to create a signer based on a private key:

```typescript copy
const walletClient = useWalletClient();
const owner = privateKeyToAccount(generatePrivateKey());
```

### Create the Safe account
Expand All @@ -85,7 +86,7 @@ Create the Safe account object using the signer.
```typescript copy
const safeAccount = await toSafeSmartAccount({
client: publicClient,
owners: [walletClient.data],
owners: [owner],
version: '1.4.1',
entryPoint: {
address: entryPoint07Address,
Expand All @@ -107,7 +108,7 @@ The smart account client is used to interact with the smart account. You will ne
```typescript copy
const smartAccountClient = createSmartAccountClient({
account: safeAccount,
chain: chain,
chain: baseSepolia,
bundlerTransport: http(bundlerUrl),
paymaster: pimlicoClient,
userOperation: {
Expand All @@ -123,6 +124,7 @@ const smartAccountClient = createSmartAccountClient({
Next, we will create a Webauthn Credential. This will be used to sign the UserOperation.

```typescript copy
// You could also use the `createCredential` function from the `ox` package to create the credential.
const credential = await createWebAuthnCredential({
name: "Wallet Owner",
});
Expand All @@ -133,7 +135,7 @@ const credential = await createWebAuthnCredential({
Next, we will install the Webauthn Module on the Safe account so that the user can use their passkey to sign a UserOperation.

```typescript copy
const { x, y, prefix } = parsePublicKey(credential.publicKey);
const { x, y, prefix } = PublicKey.from(credential.publicKey);
const validator = getWebAuthnValidator({
pubKey: { x, y, prefix },
authenticatorId: credential.id,
Expand Down Expand Up @@ -189,9 +191,9 @@ const userOpHashToSign = getUserOperationHash({
Next, the nominee will have to sign the recovery UserOperation.

```typescript copy
const cred = await sign({
const { metadata: webauthn, signature } = await sign({
credentialId: credential.id,
hash: userOpHashToSign,
challenge: userOpHashToSign,
});
```

Expand All @@ -200,11 +202,9 @@ Next, the nominee will have to sign the recovery UserOperation.
Finally, we will encode the signature and add it to the UserOperation.

```typescript copy
const parsedSignature = parseSignature(cred.signature);

const encodedSignature = getWebauthnValidatorSignature({
webauthn: cred.webauthn,
signature: parsedSignature,
webauthn,
signature,
usePrecompiled: false,
});

Expand Down

0 comments on commit 1af85c9

Please sign in to comment.