Skip to content

Commit

Permalink
add credential options
Browse files Browse the repository at this point in the history
  • Loading branch information
holic committed Nov 9, 2024
1 parent 1359882 commit 1d780b2
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 14 deletions.
3 changes: 3 additions & 0 deletions packages/entrykit/src/createWagmiConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Config, CreateConfigParameters, createConfig } from "wagmi";
import { passkeyWallet } from "./passkey/passkeyWallet";
import { mapObject } from "@latticexyz/common/utils";
import { wiresaw } from "@latticexyz/wiresaw/internal";
import { CredentialOptions } from "./passkey/common";

export type CreateWagmiConfigOptions<
chains extends readonly [Chain, ...Chain[]] = readonly [Chain, ...Chain[]],
Expand All @@ -18,6 +19,7 @@ export type CreateWagmiConfigOptions<
// TODO: make optional and hide wallet options if so?
readonly walletConnectProjectId: string;
readonly appName: string;
readonly credentialOptions?: CredentialOptions;
} & Pick<CreateConfigParameters<chains, transports>, "pollingInterval">;

export function createWagmiConfig<
Expand All @@ -32,6 +34,7 @@ export function createWagmiConfig<
passkeyWallet({
// TODO: allow any chain ID
chainId: config.chainId,
credentialOptions: config.credentialOptions,
}),
],
},
Expand Down
3 changes: 3 additions & 0 deletions packages/entrykit/src/passkey/common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { Hex } from "viem";
import { GetCredentialCreationOptionsParameters } from "webauthn-p256";

export type CredentialOptions = Pick<GetCredentialCreationOptionsParameters, "rp">;

export type SignatureAndMessage = {
signatureHex: Hex;
Expand Down
8 changes: 6 additions & 2 deletions packages/entrykit/src/passkey/createPasskey.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { cache } from "./cache";
import { PasskeyCredential } from "@latticexyz/id/internal";
import { createCredential } from "webauthn-p256";
import { CredentialOptions } from "./common";

export async function createPasskey(): Promise<PasskeyCredential> {
const credential = await createCredential({ name: "MUD Account" });
export async function createPasskey(opts: CredentialOptions): Promise<PasskeyCredential> {
const credential = await createCredential({
...opts,
name: "MUD Account",
});
console.log("created passkey", credential);

cache.setState((state) => ({
Expand Down
4 changes: 3 additions & 1 deletion packages/entrykit/src/passkey/getAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { cache } from "./cache";
import { P256Credential } from "webauthn-p256";
import { toCoinbaseSmartAccount, ToCoinbaseSmartAccountReturnType } from "@latticexyz/common/accounts";
import { toWebAuthnAccount } from "viem/account-abstraction";
import { CredentialOptions } from "./common";

export async function getAccount(
client: Client<Transport, Chain>,
id: P256Credential["id"],
credentialOptions: CredentialOptions,
): Promise<ToCoinbaseSmartAccountReturnType> {
const { publicKeys } = cache.getState();

Expand All @@ -16,7 +18,7 @@ export async function getAccount(
throw new Error("No public key found for passkey credential.");
}

const passkey = toWebAuthnAccount({ credential: { id, publicKey } });
const passkey = toWebAuthnAccount({ credential: { id, publicKey }, rpId: credentialOptions.rp?.id });
const owners = [passkey];

return await toCoinbaseSmartAccount({ client, owners });
Expand Down
18 changes: 10 additions & 8 deletions packages/entrykit/src/passkey/passkeyConnector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ import { createBundlerClient } from "../createBundlerClient";
import { getPaymasterAddress } from "../getPaymasterAddress";
import { getBundlerTransport } from "../getBundlerTransport";
import { wiresaw } from "@latticexyz/wiresaw/internal";
import { CredentialOptions } from "./common";

export type PasskeyConnectorOptions = {
// TODO: figure out what we wanna do across chains
chainId: number;
credentialOptions?: CredentialOptions;
};

export type PasskeyProvider = {
Expand All @@ -44,7 +46,7 @@ export type PasskeyConnector = ReturnType<CreatePasskeyConnector>;

passkeyConnector.type = "passkey" as const;

export function passkeyConnector({ chainId }: PasskeyConnectorOptions): CreatePasskeyConnector {
export function passkeyConnector({ chainId, credentialOptions = {} }: PasskeyConnectorOptions): CreatePasskeyConnector {
return createConnector((config) => {
// TODO: figure out how to use with config's `client` option?
if (!config.transports) {
Expand Down Expand Up @@ -78,14 +80,14 @@ export function passkeyConnector({ chainId }: PasskeyConnectorOptions): CreatePa
// supportsSimulation: true,

async createPasskey() {
const { credentialId } = await createPasskey();
const account = await getAccount(client, credentialId);
const { credentialId } = await createPasskey(credentialOptions);
const account = await getAccount(client, credentialId, credentialOptions);
this.onAccountsChanged([account.address]);
this.onConnect?.({ chainId: numberToHex(chainId) });
},
async reusePasskey() {
const { credentialId } = await reusePasskey();
const account = await getAccount(client, credentialId);
const { credentialId } = await reusePasskey(credentialOptions);
const account = await getAccount(client, credentialId, credentialOptions);
this.onAccountsChanged([account.address]);
this.onConnect?.({ chainId: numberToHex(chainId) });
},
Expand All @@ -103,7 +105,7 @@ export function passkeyConnector({ chainId }: PasskeyConnectorOptions): CreatePa
// attempt to reuse credential if this is called directly
// TODO: move this into wallet so it's only triggered via rainbowkit?
if (!cache.getState().activeCredential && !params?.isReconnecting) {
await reusePasskey();
await reusePasskey(credentialOptions);
}

const accounts = await this.getAccounts();
Expand All @@ -123,7 +125,7 @@ export function passkeyConnector({ chainId }: PasskeyConnectorOptions): CreatePa

try {
console.log("getting account for credential", id);
const account = await getAccount(client, id);
const account = await getAccount(client, id, credentialOptions);
console.log("got account", account);
return [account.address];
} catch (error) {
Expand Down Expand Up @@ -191,7 +193,7 @@ export function passkeyConnector({ chainId }: PasskeyConnectorOptions): CreatePa
const credentialId = cache.getState().activeCredential;
if (!credentialId) throw new Error("Not connected.");

const account = await getAccount(client, credentialId);
const account = await getAccount(client, credentialId, credentialOptions);

return createBundlerClient({
paymasterAddress,
Expand Down
7 changes: 4 additions & 3 deletions packages/entrykit/src/passkey/reusePasskey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import { getMessageHash } from "./getMessageHash";
import { findPublicKey } from "./findPublicKey";
import { PasskeyCredential } from "@latticexyz/id/internal";
import { sign } from "webauthn-p256";
import { CredentialOptions } from "./common";

export async function reusePasskey(): Promise<PasskeyCredential> {
export async function reusePasskey(opts: CredentialOptions): Promise<PasskeyCredential> {
const challenge = hashMessage(bytesToHex(crypto.getRandomValues(new Uint8Array(256))));
const {
raw: { id: credentialId },
signature,
webauthn: metadata,
} = await sign({ hash: challenge });
} = await sign({ hash: challenge, rpId: opts.rp?.id });

const publicKey = await (async () => {
const cachedPublicKey = cache.getState().publicKeys[credentialId];
Expand All @@ -21,7 +22,7 @@ export async function reusePasskey(): Promise<PasskeyCredential> {

const messageHash = await getMessageHash(metadata);
const challenge2 = hashMessage(signature);
const signature2 = await sign({ credentialId, hash: challenge2 });
const signature2 = await sign({ credentialId, hash: challenge2, rpId: opts.rp?.id });
if (signature2.raw.id !== credentialId) {
throw new Error("wrong credential");
}
Expand Down

0 comments on commit 1d780b2

Please sign in to comment.