Skip to content

Commit 97a69d3

Browse files
committed
fix: change imports to all 4337 sdk
1 parent 1d3dfed commit 97a69d3

File tree

4 files changed

+163
-13
lines changed

4 files changed

+163
-13
lines changed

packages/auth-server/composables/useConfigurableAccount.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
import type { Address } from "viem";
2-
import { fetchAccount } from "zksync-sso/client";
2+
import { fetchAccount } from "zksync-sso-4337";
33
import { WebAuthnValidatorAbi } from "zksync-sso-4337/abi";
44

55
export const useConfigurableAccount = () => {
6-
const { getPublicClient, getConfigurableClient, defaultChain } = useClientStore();
6+
const { getPublicClient, getConfigurableClient, defaultChain, contractsByChain } = useClientStore();
77

88
const { inProgress: getConfigurableAccountInProgress, error: getConfigurableAccountError, execute: getConfigurableAccount } = useAsync(async ({ address }: { address: Address }) => {
99
const publicClient = getPublicClient({ chainId: defaultChain.id });
10-
const factoryAddress = contractsByChain[defaultChain.id].accountFactory;
10+
const webauthnValidatorAddress = contractsByChain[defaultChain.id].webauthnValidator;
1111

1212
// FIXME: events should be scoped to the origin domain
1313
// As well, this doesn't seem to be a reliable way of retrieving a `credentialId`
1414
// but works for now.
1515
const [events, removedEvents] = await Promise.all([
1616
publicClient.getContractEvents({
17-
address: factoryAddress,
17+
address: webauthnValidatorAddress,
1818
abi: WebAuthnValidatorAbi,
1919
eventName: "PasskeyCreated",
2020
args: {
@@ -24,7 +24,7 @@ export const useConfigurableAccount = () => {
2424
strict: true,
2525
}),
2626
publicClient.getContractEvents({
27-
address: factoryAddress,
27+
address: webauthnValidatorAddress,
2828
abi: WebAuthnValidatorAbi,
2929
eventName: "PasskeyRemoved",
3030
args: {
@@ -52,17 +52,19 @@ export const useConfigurableAccount = () => {
5252

5353
const latestEvent = activeEvents[activeEvents.length - 1];
5454

55-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
56-
const { username, passkeyPublicKey } = await fetchAccount(publicClient as any, {
57-
contracts: contractsByChain[defaultChain.id],
58-
uniqueAccountId: latestEvent.args.credentialId,
55+
const { credentialId } = await fetchAccount({
56+
client: publicClient,
57+
contracts: {
58+
webauthnValidator: webauthnValidatorAddress,
59+
},
60+
originDomain: window.location.origin,
61+
credentialId: latestEvent.args.credentialId,
5962
});
6063

6164
return getConfigurableClient({
6265
chainId: defaultChain.id,
6366
address,
64-
credentialPublicKey: passkeyPublicKey,
65-
username,
67+
credentialId,
6668
});
6769
});
6870

packages/sdk-4337/src/client/actions/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ export { getAccountAddressFromLogs, prepareDeploySmartAccount } from "./deploy.j
2121
export type {
2222
AddPasskeyParams,
2323
AddPasskeyResult,
24+
FetchAccountParams,
25+
FetchAccountResult,
2426
FindAddressesByPasskeyParams,
2527
FindAddressesByPasskeyResult,
2628
} from "./passkey.js";
27-
export { addPasskey, findAddressesByPasskey } from "./passkey.js";
29+
export { addPasskey, fetchAccount, findAddressesByPasskey } from "./passkey.js";
2830

2931
// Utilities
3032
export { generateAccountId } from "./utils.js";

packages/sdk-4337/src/client/actions/passkey.ts

Lines changed: 146 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import type { Address, Hex, PublicClient } from "viem";
2-
import { hexToBytes } from "viem";
2+
import { hexToBytes, toHex } from "viem";
3+
import { readContract } from "viem/actions";
34
import {
45
decode_get_account_list_result,
56
encode_add_passkey_call_data,
67
encode_get_account_list_call_data,
78
PasskeyPayload,
89
} from "zksync-sso-web-sdk/bundler";
910

11+
import { WebAuthnValidatorAbi } from "../../abi/WebAuthnValidator.js";
12+
import { base64urlToUint8Array } from "../passkey/webauthn.js";
13+
1014
/**
1115
* Parameters for adding a passkey to a smart account
1216
*/
@@ -197,3 +201,144 @@ export async function findAddressesByPasskey(
197201

198202
return { addresses };
199203
}
204+
205+
/**
206+
* Parameters for fetching account details by passkey
207+
*/
208+
export type FetchAccountParams = {
209+
/** Public client for making RPC calls */
210+
client: PublicClient;
211+
212+
/** Contract addresses */
213+
contracts: {
214+
/** WebAuthn validator address */
215+
webauthnValidator: Address;
216+
};
217+
218+
/** Origin domain (e.g., "https://example.com" or window.location.origin) */
219+
originDomain: string;
220+
221+
/** Optional: credential ID if known, otherwise will prompt user */
222+
credentialId?: string;
223+
};
224+
225+
/**
226+
* Result from fetching account details
227+
*/
228+
export type FetchAccountResult = {
229+
/** Credential ID (username) */
230+
credentialId: string;
231+
/** Smart account address */
232+
address: Address;
233+
/** Passkey public key as Uint8Array (COSE format) */
234+
passkeyPublicKey: Uint8Array;
235+
};
236+
237+
/**
238+
* Fetch account details for a passkey credential.
239+
* If credentialId is not provided, will prompt the user to select a passkey.
240+
* This queries the WebAuthnValidator contract to get the account address and public key.
241+
*
242+
* @param params - Parameters including client, validator address, and optional credential ID
243+
* @returns Account details including credentialId, address, and public key
244+
*
245+
* @example
246+
* ```typescript
247+
* import { createPublicClient, http } from "viem";
248+
* import { fetchAccount } from "zksync-sso-4337/actions";
249+
*
250+
* const publicClient = createPublicClient({
251+
* chain: zkSyncSepoliaTestnet,
252+
* transport: http(),
253+
* });
254+
*
255+
* const { credentialId, address, passkeyPublicKey } = await fetchAccount({
256+
* client: publicClient,
257+
* contracts: {
258+
* webauthnValidator: "0x...",
259+
* },
260+
* originDomain: window.location.origin,
261+
* });
262+
*
263+
* console.log(`Account address: ${address}`);
264+
* ```
265+
*/
266+
export async function fetchAccount(
267+
params: FetchAccountParams,
268+
): Promise<FetchAccountResult> {
269+
const { client, contracts, originDomain, credentialId: providedCredentialId } = params;
270+
271+
let credentialId = providedCredentialId;
272+
273+
// If no credential ID provided, prompt user to select a passkey
274+
if (!credentialId) {
275+
const credential = (await navigator.credentials.get({
276+
publicKey: {
277+
challenge: new Uint8Array(32), // Dummy challenge
278+
userVerification: "discouraged",
279+
},
280+
})) as PublicKeyCredential | null;
281+
282+
if (!credential) {
283+
throw new Error("No passkey credential selected");
284+
}
285+
286+
credentialId = credential.id;
287+
}
288+
289+
// Convert credential ID to hex
290+
const credentialIdHex = toHex(base64urlToUint8Array(credentialId));
291+
292+
// Get account list for this credential
293+
const { addresses } = await findAddressesByPasskey({
294+
client,
295+
contracts,
296+
passkey: {
297+
credentialId: credentialIdHex,
298+
originDomain,
299+
},
300+
});
301+
302+
if (addresses.length === 0) {
303+
throw new Error(`No account found for credential ID: ${credentialId}`);
304+
}
305+
306+
// Get the first account (most common case is one account per passkey)
307+
const address = addresses[0];
308+
309+
// Get the public key for this account
310+
const publicKeyCoords = await readContract(client, {
311+
abi: WebAuthnValidatorAbi,
312+
address: contracts.webauthnValidator,
313+
functionName: "getAccountKey",
314+
args: [originDomain, credentialIdHex, address],
315+
});
316+
317+
if (!publicKeyCoords || !publicKeyCoords[0] || !publicKeyCoords[1]) {
318+
throw new Error(`Passkey credentials not found in on-chain module for passkey ${credentialId}`);
319+
}
320+
321+
// Convert the public key coordinates back to COSE format
322+
// The coordinates are returned as bytes32[2], we need to convert them to a COSE public key
323+
// For now, we'll return them as a simple concatenated Uint8Array
324+
// This matches what the legacy SDK's getPasskeySignatureFromPublicKeyBytes expects
325+
const xBytes = hexToBytes(publicKeyCoords[0]);
326+
const yBytes = hexToBytes(publicKeyCoords[1]);
327+
328+
// Create COSE-encoded public key (simplified version)
329+
// This is a minimal CBOR map encoding for ES256 key
330+
const coseKey = new Uint8Array([
331+
0xa5, // Map with 5 items
332+
0x01, 0x02, // kty: 2 (EC2)
333+
0x03, 0x26, // alg: -7 (ES256)
334+
0x20, 0x01, // crv: 1 (P-256)
335+
0x21, 0x58, 0x20, ...xBytes, // x: 32-byte coordinate
336+
0x22, 0x58, 0x20, ...yBytes, // y: 32-byte coordinate
337+
]);
338+
339+
return {
340+
credentialId,
341+
address,
342+
passkeyPublicKey: coseKey,
343+
};
344+
}

packages/sdk-4337/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ export * from "./errors/index.js";
99

1010
// Re-export actions
1111
export * from "./actions/sendUserOperation.js";
12+
export * from "./client/actions/index.js";

0 commit comments

Comments
 (0)