Headless embedded wallets using Passkeys
Summary
This guide will show you how to create a secured embedded wallet with a passkey, completely headlessly. We will use the createPasskey and createEmbeddedWallet methods, available from the useEmbeddedWallet hook. Here are the steps we need to follow:
- Ensure the user is logged in
- Create a passkey for the user
- Create the embedded wallet with the passkey provided from the previous step
Pre-requisites
- You have already set up the Dynamic SDK and wrapped your app with the
DynamicContextProvider
. - You have enabled Dynamic-powered embedded wallets and toggled “Manual Mode” on in the configuration.
- You do not have the DynamicWidget component in your application code.
Step by step
Ensure the user is logged in
You can do this by implementing signup/login i.e. via email, or via SMS.
Create a passkey for the user
To create a passkey for the user, we will use the createPasskey method from the useEmbeddedWallet hook. This method will request the user create a passkey through their device UI and return a WebAuthnAttestation object to be used next while creating the embedded wallet.
Method signature:
createPasskey(): Promise<WebAuthnAttestation>
Implementation:
const { createPasskey } = useEmbeddedWallet();
const createPasskeyHandler = async () => {
const webAuthnAttestation = await createPasskey({});
console.log(webAuthnAttestation);
};
Create the embedded wallet
To create the embedded wallet, we will use the createEmbeddedWallet
method from the useEmbeddedWallet
hook. This method will create the wallet with the passkey we generated in the previous step.
Method signature:
createEmbeddedWallet(chains?: ChainEnum[], options?: { webAuthnAttestation: WebAuthnAttestation }): Promise<Wallet | undefined>
Implementation:
const { createEmbeddedWallet } = useEmbeddedWallet();
const createWalletHandler = async () => {
const wallet = await createEmbeddedWallet(['EVM'], { webAuthnAttestation });
console.log(wallet);
};
Full code example
export const CreateEmbeddedWalletWithPasskey: FC = () => {
const { createEmbeddedWallet, createPasskey } = useEmbeddedWallet();
const [result, setResult] = useState<string | undefined>(undefined);
const onSubmitHandler = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
event.stopPropagation();
const webAuthnAttestation = await createPasskey({});
createEmbeddedWallet([ChainEnum.EVM, ChainEnum.Sol], { webAuthnAttestation })
.then((result) => setResult(JSON.stringify(result, null, 2)))
.catch((error) => setResult(JSON.stringify(error, null, 2)));
};
return (
<form onSubmit={onSubmitHandler} className='create-session-method'>
<p>Click to start the wallet creation flow</p>
<button type='submit'>Create Wallet with passkey</button>
{result}
</form>
);
};
Was this page helpful?