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

chore(sdk): Update passkeys documentation #649

Open
wants to merge 6 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions pages/sdk/protocol-kit/reference/safe.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1081,3 +1081,32 @@ const signedMessage = await protocolKit.signMessage(signedMessage, SigningMethod
const signedMessage = await protocolKit.signMessage(signedMessage, SigningMethod.ETH_SIGN)
const signedMessage = await protocolKit.signMessage(signedMessage, SigningMethod.SAFE_SIGNATURE, parentSafeAddress).
```

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yagopv be careful, I see the development branch doesn't contain the latest changes. I will merge them.

The Protocol Kit reference is now split in many different files (check it here: https://docs.safe.global/reference-sdk-protocol-kit/overview) so a new "Passkeys" entry should be added to the reference with the new function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just rebased the developement branch with the latest changes from main

## Passkeys

### `createPasskeySigner`

Creates a new passkey signer using a [WebAuthn credential](https://developer.mozilla.org/en-US/docs/Web/API/Credential).

```typescript
const rpcUrl = "https://..."
const credential = window.navigator.credentials.create({ ... })

const passkeySigner = await Safe.createPasskeySigner(credential)

const protocolKit = await Safe.init({
provider: rpcURL,
signer: passkeySigner,
safeAddress
})
```

Return an object of type `PasskeyArgType` that should be stored securely containing:

- `rawId`: The `rawId` of the credential.
- `coordinates`: The coordinates of the credential. The coordinates are used to sign using Safe smart contracts

You can add these optional properties to the resulting object before instantiating the Protocol Kit:
- `customVerifierAddress`: The custom verifier address. This is optional and only needed if the Safe is using a custom verifier.
- `getFn`: The function used to obtain the credential. This is optional and only necessary if you are creating the credential in environments where the WebAuthN API does not exist, such as React Native.

68 changes: 47 additions & 21 deletions pages/sdk/signers/passkeys.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { Callout, Steps, Tabs } from 'nextra/components'

In this guide, you will learn how to create a Passkey signer that can be added as a Safe owner and used to initialize any of the kits from the Safe\{Core\} SDK.

**Note:** Please always use a combination of passkeys and other authentication methods to ensure the security of your users' assets.
<Callout type="warning" emoji="⚠️">
Please always use a combination of passkeys and other authentication methods to ensure the security of your users' assets.
</Callout>

## Prerequisites

Expand Down Expand Up @@ -46,7 +48,7 @@ In this guide, you will learn how to create a Passkey signer that can be added a
{/* <!-- vale off --> */}

```typescript
import { extractPasskeyData } from '@safe-global/protocol-kit'
import Safe from '@safe-global/protocol-kit'
```

{/* <!-- vale on --> */}
Expand All @@ -55,7 +57,7 @@ In this guide, you will learn how to create a Passkey signer that can be added a

### Create a passkey

Firstly, you need to generate a passkey credential using the WebAuthn API in a supporting browser environment.
Firstly, you need to generate a passkey credential using the [WebAuthn API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API) in a supporting browser environment.

{/* <!-- vale off --> */}

Expand Down Expand Up @@ -89,7 +91,7 @@ In this guide, you will learn how to create a Passkey signer that can be added a

{/* <!-- vale on --> */}

After generating the `passkeyCredential` object, you need to create a new object with the `PasskeyArgType` type that will contain the `rawId` and the `coordinates` information.
After generating the `passkeyCredential` object, you need to create the signer. This signer will be an `PasskeyArgType` object containing the `rawId` and the `coordinates` information.

{/* <!-- vale off --> */}

Expand All @@ -98,44 +100,68 @@ In this guide, you will learn how to create a Passkey signer that can be added a
throw Error('Passkey creation failed: No credential was returned.')
}

const passkey = await extractPasskeyData(passkeyCredential)
const passkeySigner = await Safe.createPasskeySigner(passkeyCredential)
```

{/* <!-- vale on --> */}

At this point, it's critical to securely store the information in the `passkey` object in a persistent service. Losing access to this data will result in the user being unable to access their passkey and, therefore, their Safe Smart Account.
At this point, it's critical to securely store the information in the `passkeySigner` object in a persistent service. Losing access to this data will result in the user being unable to access their passkey and, therefore, their Safe Smart Account.

### Get the provider and signer

Once the passkey is created, you can get the `provider` and `signer`, which is the externally-owned account of the user that was derived from its credentials.
Once the passkey is created, you need the `provider` and `signer` props that the Safe\{Core\} SDK require to instantiate the kits.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Once the passkey is created, you need the `provider` and `signer` props that the Safe\{Core\} SDK require to instantiate the kits.
Once the passkey is created, you need the `provider` and `signer` properties required to instantiate the Safe\{Core\} SDK kits.


[How to initialize the Protocol Kit](https://docs.safe.global/reference-sdk-protocol-kit/initialization/init)

The `provider` (eip1193 compatible or rpc) can be obtained by using `viem` in several ways:
{/* <!-- vale off --> */}

<Tabs items={['viem']}>
<Tabs items={['eip1193', 'rpcUrl']}>
<Tabs.Tab>
You can instantiate the provider using `viem` and the following imports:

```typescript
import { createWalletClient, http } from 'viem'
import { sepolia } from 'viem/chains'
```
```typescript
import { createWalletClient, http } from 'viem'
import { sepolia } from 'viem/chains'

```typescript
const provider = createWalletClient({
chain: sepolia,
transport: http('https://rpc.ankr.com/eth_sepolia')
})
const walletClient = createWalletClient({
chain: sepolia,
transport: http('https://rpc.ankr.com/eth_sepolia')
})

const signer = passkey
const provider = { request: walletClient.request }
const signer = passkeySigner
```
</Tabs.Tab>
<Tabs.Tab>
```typescript
import { sepolia } from 'viem/chains'

const provider = sepolia.rpcUrls.default.http[0]
const signer = passkeySigner
```
Comment on lines +116 to +140
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is out of scope for this PR.
The used provider is just an example to provide to the kits, all the different ways to create it are covered in the reference here: https://docs.safe.global/reference-sdk-protocol-kit/initialization/init#provider

In fact, I think the provider could also be reemoved as this is just about the generating the signer. This also applies to all the Safe Signers guides, so I think it's out of scope for this PR.

</Tabs.Tab>
</Tabs>

{/* <!-- vale on --> */}

### Instantiate SDK

With the `provider` and `signer` you are ready to instantiate any of the kits from the Safe\{Core\} SDK and set up or use this signer as a Safe owner.

</Steps>
For example, you can instantiate the `protocol-kit` as follows and sign a transaction with the passkey signer:

{/* <!-- vale off --> */}

```typescript
const protocolKit = await Safe.init({ provider, signer, safeAddress })

const transaction = { to: '0x1234', value: '0x0', data: '0x' }
const safeTransaction = await protocolKit.createTransaction({ transactions: [transaction] })
const signedSafeTransaction = await protocolKit.signTransaction(safeTransaction)
```

{/* <!-- vale on --> */}

</Steps>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
</Steps>
</Steps>


## Recap and further reading

Expand Down
Loading