From 60f1b153984a18f259127f876e3e80ab78edd658 Mon Sep 17 00:00:00 2001 From: bvvvp009 Date: Thu, 4 Sep 2025 01:53:18 +0530 Subject: [PATCH 1/6] feat: make ox package an optional peer dependency - Create ox.ts utility module for optional ox imports - Update all files that import ox to use getOxExports utility - Add proper error handling when ox is not installed - Update package.json to mark ox as optional peer dependency - Update README.md with installation instructions for WebAuthn - Fix Windows compatibility in build scripts (printf -> echo) Closes #399 --- package.json | 10 ++-- packages/permissionless/README.md | 18 +++++++ .../accounts/kernel/toKernelSmartAccount.ts | 11 +++-- .../accounts/kernel/utils/signMessage.ts | 3 +- .../accounts/safe/signUserOperation.ts | 3 +- .../accounts/safe/toSafeSmartAccount.ts | 3 +- .../passkeyServer/startAuthentication.ts | 10 ++-- .../passkeyServer/startRegistration.ts | 3 +- .../passkeyServer/verifyAuthentication.ts | 18 ++++++- .../passkeyServer/verifyRegistration.ts | 3 +- packages/permissionless/utils/index.ts | 3 ++ packages/permissionless/utils/ox.ts | 48 +++++++++++++++++++ packages/wagmi-demo/src/PasskeyServerDemo.tsx | 3 +- 13 files changed, 114 insertions(+), 22 deletions(-) create mode 100644 packages/permissionless/utils/ox.ts diff --git a/package.json b/package.json index 0a634732..d8fe471e 100644 --- a/package.json +++ b/package.json @@ -52,13 +52,13 @@ "build:permissionless": "bun run clean:permissionless && bun run build:permissionless:cjs && bun run build:permissionless:esm && bun run build:permissionless:types", "build:mock-paymaster": "bun run clean:mock-paymaster && bun run build:mock-paymaster:cjs && bun run build:mock-paymaster:esm && bun run build:mock-paymaster:types", "build:wagmi": "bun run clean:wagmi && bun run build:wagmi:esm && bun run build:wagmi:types", - "build:permissionless:cjs": "tsc --project ./tsconfig/tsconfig.permissionless.cjs.json && tsc-alias -p ./tsconfig/tsconfig.permissionless.cjs.json && printf '{\"type\":\"commonjs\"}' > ./packages/permissionless/_cjs/package.json", - "build:permissionless:esm": "tsc --project ./tsconfig/tsconfig.permissionless.esm.json && tsc-alias -p ./tsconfig/tsconfig.permissionless.esm.json && printf '{\"type\": \"module\",\"sideEffects\":false}' > ./packages/permissionless/_esm/package.json", + "build:permissionless:cjs": "tsc --project ./tsconfig/tsconfig.permissionless.cjs.json && tsc-alias -p ./tsconfig/tsconfig.permissionless.cjs.json && echo {\"type\":\"commonjs\"} > ./packages/permissionless/_cjs/package.json", + "build:permissionless:esm": "tsc --project ./tsconfig/tsconfig.permissionless.esm.json && tsc-alias -p ./tsconfig/tsconfig.permissionless.esm.json && echo {\"type\": \"module\",\"sideEffects\":false} > ./packages/permissionless/_esm/package.json", "build:permissionless:types": "tsc --project ./tsconfig/tsconfig.permissionless.types.json && tsc-alias -p ./tsconfig/tsconfig.permissionless.types.json", "build:wagmi:types": "tsc --project ./tsconfig/tsconfig.wagmi.types.json && tsc-alias -p ./tsconfig/tsconfig.wagmi.types.json", - "build:wagmi:esm": "tsc --project ./tsconfig/tsconfig.wagmi.esm.json && tsc-alias -p ./tsconfig/tsconfig.wagmi.esm.json && printf '{\"type\": \"module\",\"sideEffects\":false}' > ./packages/wagmi/_esm/package.json", - "build:mock-paymaster:cjs": "tsc --project ./tsconfig/tsconfig.mock-paymaster.cjs.json && tsc-alias -p ./tsconfig/tsconfig.mock-paymaster.cjs.json && printf '{\"type\":\"commonjs\"}' > ./packages/mock-paymaster/_cjs/package.json", - "build:mock-paymaster:esm": "tsc --project ./tsconfig/tsconfig.mock-paymaster.esm.json && tsc-alias -p ./tsconfig/tsconfig.mock-paymaster.esm.json && printf '{\"type\": \"module\",\"sideEffects\":false}' > ./packages/mock-paymaster/_esm/package.json", + "build:wagmi:esm": "tsc --project ./tsconfig/tsconfig.wagmi.esm.json && tsc-alias -p ./tsconfig/tsconfig.wagmi.esm.json && echo {\"type\": \"module\",\"sideEffects\":false} > ./packages/wagmi/_esm/package.json", + "build:mock-paymaster:cjs": "tsc --project ./tsconfig/tsconfig.mock-paymaster.cjs.json && tsc-alias -p ./tsconfig/tsconfig.mock-paymaster.cjs.json && echo {\"type\":\"commonjs\"} > ./packages/mock-paymaster/_cjs/package.json", + "build:mock-paymaster:esm": "tsc --project ./tsconfig/tsconfig.mock-paymaster.esm.json && tsc-alias -p ./tsconfig/tsconfig.mock-paymaster.esm.json && echo {\"type\": \"module\",\"sideEffects\":false} > ./packages/mock-paymaster/_esm/package.json", "build:mock-paymaster:types": "tsc --project ./tsconfig/tsconfig.mock-paymaster.types.json && tsc-alias -p ./tsconfig/tsconfig.mock-paymaster.types.json", "clean": "bun run clean:permissionless && bun run clean:wagmi && bun run clean:mock-paymaster", "clean:permissionless": "rimraf ./packages/permissionless/_esm ./packages/permissionless/_cjs ./packages/permissionless/_types", diff --git a/packages/permissionless/README.md b/packages/permissionless/README.md index a559797d..8b5ae2d4 100644 --- a/packages/permissionless/README.md +++ b/packages/permissionless/README.md @@ -50,6 +50,24 @@ bun install viem permissionless yarn add viem permissionless ``` +### Optional Dependencies + +For WebAuthn functionality (passkeys), you'll also need to install the `ox` package: + +```bash +npm install ox +``` + +```bash +bun install ox +``` + +```bash +yarn add ox +``` + +**Note**: The `ox` package is optional and only required if you plan to use WebAuthn/passkey features. The library will throw a helpful error message if you try to use WebAuthn functionality without installing `ox`. + ## Quick Start ```typescript diff --git a/packages/permissionless/accounts/kernel/toKernelSmartAccount.ts b/packages/permissionless/accounts/kernel/toKernelSmartAccount.ts index e8f63aac..51be2b4a 100644 --- a/packages/permissionless/accounts/kernel/toKernelSmartAccount.ts +++ b/packages/permissionless/accounts/kernel/toKernelSmartAccount.ts @@ -1,4 +1,4 @@ -import { Base64, Hex, PublicKey } from "ox" +import { getOxExports } from "../../utils/ox.js" import type { Account, Assign, @@ -245,7 +245,7 @@ const getInitializationData = ({ entryPoint: { version: entryPointVersion } - validatorData: Hex.Hex + validatorData: `0x${string}` validatorAddress: Address }) => { if (entryPointVersion === "0.6") { @@ -288,6 +288,7 @@ const getValidatorData = async (owner: WebAuthnAccount | LocalAccount) => { } if (isWebAuthnAccount(owner)) { + const { PublicKey, Hex, Base64 } = await getOxExports() const parsedPublicKey = PublicKey.fromHex(owner.publicKey) const authenticatorIdHash = keccak256( Hex.fromBytes(Base64.toBytes(owner.id)) @@ -342,13 +343,13 @@ const getAccountInitCode = async ({ }: { kernelVersion: KernelVersion entryPointVersion: entryPointVersion - validatorData: Hex.Hex + validatorData: `0x${string}` index: bigint factoryAddress: Address accountLogicAddress: Address validatorAddress: Address useMetaFactory: boolean -}): Promise => { +}): Promise<`0x${string}`> => { // Build the account initialization data const initializationData = getInitializationData({ entryPoint: { version: entryPointVersion }, @@ -605,7 +606,7 @@ export async function toKernelSmartAccount< entryPoint.version === "0.6" || _useMetaFactory === false ? factoryAddress : metaFactoryAddress, - factoryData: await generateInitCode(_useMetaFactory) + factoryData: await generateInitCode(_useMetaFactory) as `0x${string}` } } diff --git a/packages/permissionless/accounts/kernel/utils/signMessage.ts b/packages/permissionless/accounts/kernel/utils/signMessage.ts index 05230b01..b5704a47 100644 --- a/packages/permissionless/accounts/kernel/utils/signMessage.ts +++ b/packages/permissionless/accounts/kernel/utils/signMessage.ts @@ -1,4 +1,4 @@ -import { Signature } from "ox" +import { getOxExports } from "../../../utils/ox.js" import { type Hash, type LocalAccount, @@ -51,6 +51,7 @@ export async function signMessage({ const { signature: signatureData, webauthn } = await owner.sign({ hash: messageContent as Hash }) + const { Signature } = await getOxExports() const signature = Signature.fromHex(signatureData) // encode signature diff --git a/packages/permissionless/accounts/safe/signUserOperation.ts b/packages/permissionless/accounts/safe/signUserOperation.ts index e10c4f0f..8a007583 100644 --- a/packages/permissionless/accounts/safe/signUserOperation.ts +++ b/packages/permissionless/accounts/safe/signUserOperation.ts @@ -1,4 +1,4 @@ -import { Signature } from "ox" +import { getOxExports } from "../../utils/ox.js" import { type Account, type Address, @@ -84,6 +84,7 @@ export const getWebAuthnSignature = async ({ hash }) + const { Signature } = await getOxExports() const signature = Signature.fromHex(signatureData) const match = webauthn.clientDataJSON.match( diff --git a/packages/permissionless/accounts/safe/toSafeSmartAccount.ts b/packages/permissionless/accounts/safe/toSafeSmartAccount.ts index d2c4c63a..d274ba55 100644 --- a/packages/permissionless/accounts/safe/toSafeSmartAccount.ts +++ b/packages/permissionless/accounts/safe/toSafeSmartAccount.ts @@ -1,4 +1,4 @@ -import { PublicKey } from "ox" +import { getOxExports } from "../../utils/ox.js" import { type Account, type Address, @@ -874,6 +874,7 @@ const getInitializerCode = async ({ safeWebAuthnSharedSignerAddress && safeP256VerifierAddress ) { + const { PublicKey } = await getOxExports() const parsedPublicKey = PublicKey.fromHex(webAuthnOwner.publicKey) multiCalls.push({ diff --git a/packages/permissionless/actions/passkeyServer/startAuthentication.ts b/packages/permissionless/actions/passkeyServer/startAuthentication.ts index ad9acfb8..f8767f78 100644 --- a/packages/permissionless/actions/passkeyServer/startAuthentication.ts +++ b/packages/permissionless/actions/passkeyServer/startAuthentication.ts @@ -1,5 +1,4 @@ -import { Base64 } from "ox" -import type { WebAuthnP256 } from "ox" +import { getOxExports } from "../../utils/ox.js" import { type Account, type Chain, @@ -9,7 +8,10 @@ import { } from "viem" import type { PasskeyServerRpcSchema } from "../../types/passkeyServer.js" -export type StartAuthenticationReturnType = WebAuthnP256.sign.Options & { +export type StartAuthenticationReturnType = { + challenge: string + rpId: string + userVerification?: string uuid: string } @@ -27,7 +29,7 @@ export const startAuthentication = async ( }) return { - challenge: toHex(Base64.toBytes(response.challenge)), + challenge: toHex((await getOxExports()).Base64.toBytes(response.challenge)), rpId: response.rpId, userVerification: response.userVerification, uuid: response.uuid diff --git a/packages/permissionless/actions/passkeyServer/startRegistration.ts b/packages/permissionless/actions/passkeyServer/startRegistration.ts index 69f02166..6c03b52a 100644 --- a/packages/permissionless/actions/passkeyServer/startRegistration.ts +++ b/packages/permissionless/actions/passkeyServer/startRegistration.ts @@ -1,4 +1,4 @@ -import { Base64 } from "ox" +import { getOxExports } from "../../utils/ox.js" import type { Account, Chain, Client, Transport } from "viem" import type { CreateWebAuthnCredentialParameters } from "viem/account-abstraction" import type { PasskeyServerRpcSchema } from "../../types/passkeyServer.js" @@ -104,6 +104,7 @@ export const startRegistration = async ( throw new Error("Invalid response format from passkey server") } + const { Base64 } = await getOxExports() const credentialOptions: StartRegistrationReturnType = { attestation: response.attestation, authenticatorSelection: response.authenticatorSelection, diff --git a/packages/permissionless/actions/passkeyServer/verifyAuthentication.ts b/packages/permissionless/actions/passkeyServer/verifyAuthentication.ts index fe4ffe05..1a02c61b 100644 --- a/packages/permissionless/actions/passkeyServer/verifyAuthentication.ts +++ b/packages/permissionless/actions/passkeyServer/verifyAuthentication.ts @@ -1,9 +1,22 @@ -import { Base64, type WebAuthnP256 } from "ox" +import { getOxExports } from "../../utils/ox.js" // import { Base64 } from "ox" import type { Account, Chain, Client, Hex, Transport } from "viem" import type { PasskeyServerRpcSchema } from "../../types/passkeyServer.js" -export type VerifyAuthenticationParameters = WebAuthnP256.sign.ReturnType & { +export type VerifyAuthenticationParameters = { + raw: { + id: string + rawId: ArrayBuffer + authenticatorAttachment: string + response: { + authenticatorData?: ArrayBuffer + signature?: ArrayBuffer + userHandle?: ArrayBuffer + clientDataJSON: ArrayBuffer + } + getClientExtensionResults: () => Record + type: string + } uuid: string } @@ -24,6 +37,7 @@ export const verifyAuthentication = async ( args: VerifyAuthenticationParameters ): Promise => { const { raw, uuid } = args + const { Base64 } = await getOxExports() let responseAuthenticatorData: string diff --git a/packages/permissionless/actions/passkeyServer/verifyRegistration.ts b/packages/permissionless/actions/passkeyServer/verifyRegistration.ts index 118a1d7b..e59a4959 100644 --- a/packages/permissionless/actions/passkeyServer/verifyRegistration.ts +++ b/packages/permissionless/actions/passkeyServer/verifyRegistration.ts @@ -1,4 +1,4 @@ -import { Base64 } from "ox" +import { getOxExports } from "../../utils/ox.js" import type { Account, Chain, Client, Hex, Transport } from "viem" import type { CreateWebAuthnCredentialReturnType } from "viem/account-abstraction" import type { PasskeyServerRpcSchema } from "../../types/passkeyServer.js" @@ -25,6 +25,7 @@ export const verifyRegistration = async ( args: VerifyRegistrationParameters ): Promise => { const { credential, context } = args + const { Base64 } = await getOxExports() const response = credential.raw .response as unknown as AuthenticatorAttestationResponse diff --git a/packages/permissionless/utils/index.ts b/packages/permissionless/utils/index.ts index 312ce41e..c7553dc5 100644 --- a/packages/permissionless/utils/index.ts +++ b/packages/permissionless/utils/index.ts @@ -57,3 +57,6 @@ export { type Erc20AllowanceOverrideParameters, type Erc20BalanceOverrideParameters } + +// Export ox utilities +export { getOxExports, hasOxModule } from "./ox.js" diff --git a/packages/permissionless/utils/ox.ts b/packages/permissionless/utils/ox.ts new file mode 100644 index 00000000..2884735b --- /dev/null +++ b/packages/permissionless/utils/ox.ts @@ -0,0 +1,48 @@ +/** + * Utility module for handling optional ox imports + * This allows the library to work without ox being installed + */ + +let oxModule: any = null + +// Try to load ox module +try { + // Use dynamic import for ESM compatibility + const importPromise = import("ox") + // Note: This will be handled in the functions that need ox + oxModule = { importPromise } +} catch (error) { + // ox is not installed, this is fine for optional dependency +} + +export async function getOxModule() { + if (!oxModule) { + throw new Error( + "The 'ox' package is required for WebAuthn functionality. Please install it: npm install ox" + ) + } + + try { + return await oxModule.importPromise + } catch (error) { + throw new Error( + "The 'ox' package is required for WebAuthn functionality. Please install it: npm install ox" + ) + } +} + +export function hasOxModule(): boolean { + return oxModule !== null +} + +// Helper function to get ox exports +export async function getOxExports() { + const ox = await getOxModule() + return { + Base64: ox.Base64, + Hex: ox.Hex, + PublicKey: ox.PublicKey, + Signature: ox.Signature, + WebAuthnP256: ox.WebAuthnP256 + } +} diff --git a/packages/wagmi-demo/src/PasskeyServerDemo.tsx b/packages/wagmi-demo/src/PasskeyServerDemo.tsx index 4ae6fc63..e2f6ad2b 100644 --- a/packages/wagmi-demo/src/PasskeyServerDemo.tsx +++ b/packages/wagmi-demo/src/PasskeyServerDemo.tsx @@ -1,4 +1,4 @@ -import { WebAuthnP256 } from "ox" +import { getOxExports } from "permissionless/utils/ox.js" import { type SmartAccountClient, createSmartAccountClient @@ -154,6 +154,7 @@ export function PasskeyServerDemo() { const loginCredential = async () => { const credentials = await passkeyServerClient.startAuthentication() + const { WebAuthnP256 } = await getOxExports() const response = await WebAuthnP256.sign(credentials) const verifiedCredential = From 1d11ce57b7da2dfa97c27e26da20e03818a8c21f Mon Sep 17 00:00:00 2001 From: plusminushalf Date: Thu, 13 Nov 2025 10:48:00 +0000 Subject: [PATCH 2/6] use type Hex from viem instead & lint --- packages/mock-paymaster/relay.ts | 3 ++- .../mock-aa-infra/alto/instance.ts | 11 ++++++----- .../accounts/etherspot/utils/getInitMSAData.ts | 8 ++++---- .../accounts/kernel/toKernelSmartAccount.ts | 11 ++++++----- .../accounts/kernel/utils/signMessage.ts | 2 +- .../permissionless/accounts/safe/signUserOperation.ts | 2 +- .../accounts/safe/toSafeSmartAccount.ts | 6 +++--- .../accounts/thirdweb/utils/decodeCallData.ts | 2 +- .../accounts/trust/utils/decodeCallData.ts | 2 +- .../accounts/trust/utils/getFactoryData.ts | 4 ++-- .../actions/passkeyServer/startAuthentication.ts | 6 ++++-- .../actions/passkeyServer/startRegistration.ts | 2 +- .../actions/passkeyServer/verifyAuthentication.ts | 2 +- .../actions/passkeyServer/verifyRegistration.ts | 2 +- .../actions/smartAccount/getCallsStatus.ts | 5 +++-- packages/permissionless/utils/ox.ts | 2 +- packages/wagmi-demo/src/PasskeyServerDemo.tsx | 4 ++-- 17 files changed, 40 insertions(+), 34 deletions(-) diff --git a/packages/mock-paymaster/relay.ts b/packages/mock-paymaster/relay.ts index e0823c8e..3bee67e1 100644 --- a/packages/mock-paymaster/relay.ts +++ b/packages/mock-paymaster/relay.ts @@ -13,6 +13,7 @@ import { getAddress, toHex } from "viem" +import type { Hex } from "viem" import { type BundlerClient, type UserOperation, @@ -175,7 +176,7 @@ const handleMethod = async ({ getSingletonPaymaster08Address(paymasterSigner.account.address) ] - const epToPaymaster: Record<`0x${string}`, `0x${string}`> = { + const epToPaymaster: Record = { [entryPoint06Address]: paymaster06, [entryPoint07Address]: paymaster07, [entryPoint08Address]: paymaster08 diff --git a/packages/permissionless-test/mock-aa-infra/alto/instance.ts b/packages/permissionless-test/mock-aa-infra/alto/instance.ts index ab08d238..81078629 100644 --- a/packages/permissionless-test/mock-aa-infra/alto/instance.ts +++ b/packages/permissionless-test/mock-aa-infra/alto/instance.ts @@ -2,6 +2,7 @@ import { resolve } from "node:path" import { defineInstance } from "prool" import { toArgs } from "prool" import { execa } from "prool/processes" +import type { Hex } from "viem" export type AltoParameters = { /** @@ -19,7 +20,7 @@ export type AltoParameters = { /** * Address of the `BundleBulker` contract. */ - bundleBulkerAddress?: `0x${string}` | undefined + bundleBulkerAddress?: Hex | undefined /** * Set if the bundler bundle user operations automatically or only when calling `debug_bundler_sendBundleNow`. * @default "auto" @@ -54,15 +55,15 @@ export type AltoParameters = { /** * EntryPoint contract addresses. */ - entrypoints: readonly `0x${string}`[] + entrypoints: readonly Hex[] /** * Address of the EntryPoint simulations contract. */ - entrypointSimulationContract?: `0x${string}` | undefined + entrypointSimulationContract?: Hex | undefined /** * Private keys of the executor accounts. */ - executorPrivateKeys?: readonly `0x${string}`[] + executorPrivateKeys?: readonly Hex[] /** * Interval to refill the signer balance (seconds). * @default 1200 @@ -184,7 +185,7 @@ export type AltoParameters = { /** * Address of the `PerOpInflator` contract. */ - perOpInflatorAddress?: `0x${string}` | undefined + perOpInflatorAddress?: Hex | undefined /** * Polling interval for querying for new blocks (ms). * @default 1000 diff --git a/packages/permissionless/accounts/etherspot/utils/getInitMSAData.ts b/packages/permissionless/accounts/etherspot/utils/getInitMSAData.ts index 8ad162d1..5b53f885 100644 --- a/packages/permissionless/accounts/etherspot/utils/getInitMSAData.ts +++ b/packages/permissionless/accounts/etherspot/utils/getInitMSAData.ts @@ -1,4 +1,4 @@ -import { type Address, encodeFunctionData, zeroAddress } from "viem" +import { type Address, type Hex, encodeFunctionData, zeroAddress } from "viem" import { EtherspotBootstrapAbi, EtherspotOnInstallAbi @@ -29,7 +29,7 @@ const _makeBootstrapConfig = (module: string, data: string) => { config.data = encodeFunctionData({ abi: EtherspotOnInstallAbi, functionName: "onInstall", - args: [data as `0x${string}`] + args: [data as Hex] }) return config @@ -38,13 +38,13 @@ const _makeBootstrapConfig = (module: string, data: string) => { const makeBootstrapConfig = (module: string, data: string) => { const config: { module: string - data: `0x${string}` + data: Hex }[] = [] const data1 = encodeFunctionData({ abi: EtherspotOnInstallAbi, functionName: "onInstall", - args: [data as `0x${string}`] + args: [data as Hex] }) const newConfig = { diff --git a/packages/permissionless/accounts/kernel/toKernelSmartAccount.ts b/packages/permissionless/accounts/kernel/toKernelSmartAccount.ts index bd508ee3..604529ff 100644 --- a/packages/permissionless/accounts/kernel/toKernelSmartAccount.ts +++ b/packages/permissionless/accounts/kernel/toKernelSmartAccount.ts @@ -1,8 +1,8 @@ -import { getOxExports } from "../../utils/ox.js" import type { Account, Assign, Chain, + Hex, JsonRpcAccount, OneOf, PrivateKeyAccount, @@ -36,6 +36,7 @@ import { getChainId } from "viem/actions" import { getAction } from "viem/utils" import { getAccountNonce } from "../../actions/public/getAccountNonce.js" import { getSenderAddress } from "../../actions/public/getSenderAddress.js" +import { getOxExports } from "../../utils/ox.js" import { type EthereumProvider, toOwner } from "../../utils/toOwner.js" import { KernelInitAbi } from "./abi/KernelAccountAbi.js" import { @@ -249,7 +250,7 @@ const getInitializationData = ({ entryPoint: { version: entryPointVersion } - validatorData: `0x${string}` + validatorData: Hex validatorAddress: Address }) => { if (entryPointVersion === "0.6") { @@ -347,13 +348,13 @@ const getAccountInitCode = async ({ }: { kernelVersion: KernelVersion entryPointVersion: entryPointVersion - validatorData: `0x${string}` + validatorData: Hex index: bigint factoryAddress: Address accountLogicAddress: Address validatorAddress: Address useMetaFactory: boolean -}): Promise<`0x${string}`> => { +}): Promise => { // Build the account initialization data const initializationData = getInitializationData({ entryPoint: { version: entryPointVersion }, @@ -610,7 +611,7 @@ export async function toKernelSmartAccount< entryPoint.version === "0.6" || _useMetaFactory === false ? factoryAddress : metaFactoryAddress, - factoryData: await generateInitCode(_useMetaFactory) as `0x${string}` + factoryData: (await generateInitCode(_useMetaFactory)) as Hex } } diff --git a/packages/permissionless/accounts/kernel/utils/signMessage.ts b/packages/permissionless/accounts/kernel/utils/signMessage.ts index 1d186356..54c21ed7 100644 --- a/packages/permissionless/accounts/kernel/utils/signMessage.ts +++ b/packages/permissionless/accounts/kernel/utils/signMessage.ts @@ -1,4 +1,3 @@ -import { getOxExports } from "../../../utils/ox.js" import { type Hash, type LocalAccount, @@ -9,6 +8,7 @@ import { } from "viem" import type { WebAuthnAccount } from "viem/account-abstraction" import { signMessage as _signMessage } from "viem/actions" +import { getOxExports } from "../../../utils/ox.js" import { isWebAuthnAccount } from "./isWebAuthnAccount.js" import { type WrapMessageHashParams, diff --git a/packages/permissionless/accounts/safe/signUserOperation.ts b/packages/permissionless/accounts/safe/signUserOperation.ts index 8a007583..5f40b8c9 100644 --- a/packages/permissionless/accounts/safe/signUserOperation.ts +++ b/packages/permissionless/accounts/safe/signUserOperation.ts @@ -1,4 +1,3 @@ -import { getOxExports } from "../../utils/ox.js" import { type Account, type Address, @@ -17,6 +16,7 @@ import { } from "viem" import type { UserOperation, WebAuthnAccount } from "viem/account-abstraction" import { toOwner } from "../../utils/index.js" +import { getOxExports } from "../../utils/ox.js" import type { EthereumProvider } from "../../utils/toOwner.js" import { EIP712_SAFE_OPERATION_TYPE_V06, diff --git a/packages/permissionless/accounts/safe/toSafeSmartAccount.ts b/packages/permissionless/accounts/safe/toSafeSmartAccount.ts index d274ba55..29b8784d 100644 --- a/packages/permissionless/accounts/safe/toSafeSmartAccount.ts +++ b/packages/permissionless/accounts/safe/toSafeSmartAccount.ts @@ -1,4 +1,3 @@ -import { getOxExports } from "../../utils/ox.js" import { type Account, type Address, @@ -48,6 +47,7 @@ import { getAccountNonce } from "../../actions/public/getAccountNonce.js" import { decode7579Calls } from "../../utils/decode7579Calls.js" import { encode7579Calls } from "../../utils/encode7579Calls.js" import { isSmartAccountDeployed } from "../../utils/isSmartAccountDeployed.js" +import { getOxExports } from "../../utils/ox.js" import { type EthereumProvider, toOwner } from "../../utils/toOwner.js" import { concatSignatures, @@ -594,8 +594,8 @@ const encodeMultiSend = ( value: bigint operation: 0 | 1 }[] -): `0x${string}` => { - const data: `0x${string}` = `0x${txs +): Hex => { + const data: Hex = `0x${txs .map((tx) => encodeInternalTransaction(tx)) .join("")}` diff --git a/packages/permissionless/accounts/thirdweb/utils/decodeCallData.ts b/packages/permissionless/accounts/thirdweb/utils/decodeCallData.ts index 8324739c..d20a3b3a 100644 --- a/packages/permissionless/accounts/thirdweb/utils/decodeCallData.ts +++ b/packages/permissionless/accounts/thirdweb/utils/decodeCallData.ts @@ -1,6 +1,6 @@ import { type Address, type Hex, decodeFunctionData } from "viem" -export const decodeCallData = async (callData: `0x${string}`) => { +export const decodeCallData = async (callData: Hex) => { try { const decodedBatch = decodeFunctionData({ abi: [ diff --git a/packages/permissionless/accounts/trust/utils/decodeCallData.ts b/packages/permissionless/accounts/trust/utils/decodeCallData.ts index 8324739c..d20a3b3a 100644 --- a/packages/permissionless/accounts/trust/utils/decodeCallData.ts +++ b/packages/permissionless/accounts/trust/utils/decodeCallData.ts @@ -1,6 +1,6 @@ import { type Address, type Hex, decodeFunctionData } from "viem" -export const decodeCallData = async (callData: `0x${string}`) => { +export const decodeCallData = async (callData: Hex) => { try { const decodedBatch = decodeFunctionData({ abi: [ diff --git a/packages/permissionless/accounts/trust/utils/getFactoryData.ts b/packages/permissionless/accounts/trust/utils/getFactoryData.ts index 5b1e0b2f..16777f0e 100644 --- a/packages/permissionless/accounts/trust/utils/getFactoryData.ts +++ b/packages/permissionless/accounts/trust/utils/getFactoryData.ts @@ -1,4 +1,4 @@ -import type { Address } from "viem" +import type { Address, Hex } from "viem" import { encodeFunctionData } from "viem" /** @@ -9,7 +9,7 @@ export const getFactoryData = async ({ index, secp256k1VerificationFacetAddress }: { - bytes: `0x${string}` + bytes: Hex index: bigint secp256k1VerificationFacetAddress: Address }) => { diff --git a/packages/permissionless/actions/passkeyServer/startAuthentication.ts b/packages/permissionless/actions/passkeyServer/startAuthentication.ts index f8767f78..c2f0ebc7 100644 --- a/packages/permissionless/actions/passkeyServer/startAuthentication.ts +++ b/packages/permissionless/actions/passkeyServer/startAuthentication.ts @@ -1,4 +1,3 @@ -import { getOxExports } from "../../utils/ox.js" import { type Account, type Chain, @@ -7,6 +6,7 @@ import { toHex } from "viem" import type { PasskeyServerRpcSchema } from "../../types/passkeyServer.js" +import { getOxExports } from "../../utils/ox.js" export type StartAuthenticationReturnType = { challenge: string @@ -29,7 +29,9 @@ export const startAuthentication = async ( }) return { - challenge: toHex((await getOxExports()).Base64.toBytes(response.challenge)), + challenge: toHex( + (await getOxExports()).Base64.toBytes(response.challenge) + ), rpId: response.rpId, userVerification: response.userVerification, uuid: response.uuid diff --git a/packages/permissionless/actions/passkeyServer/startRegistration.ts b/packages/permissionless/actions/passkeyServer/startRegistration.ts index 6c03b52a..2e333118 100644 --- a/packages/permissionless/actions/passkeyServer/startRegistration.ts +++ b/packages/permissionless/actions/passkeyServer/startRegistration.ts @@ -1,7 +1,7 @@ -import { getOxExports } from "../../utils/ox.js" import type { Account, Chain, Client, Transport } from "viem" import type { CreateWebAuthnCredentialParameters } from "viem/account-abstraction" import type { PasskeyServerRpcSchema } from "../../types/passkeyServer.js" +import { getOxExports } from "../../utils/ox.js" const validateAttestation = (attestation: unknown): boolean => { return ( diff --git a/packages/permissionless/actions/passkeyServer/verifyAuthentication.ts b/packages/permissionless/actions/passkeyServer/verifyAuthentication.ts index 1a02c61b..b8f7f3f1 100644 --- a/packages/permissionless/actions/passkeyServer/verifyAuthentication.ts +++ b/packages/permissionless/actions/passkeyServer/verifyAuthentication.ts @@ -1,7 +1,7 @@ -import { getOxExports } from "../../utils/ox.js" // import { Base64 } from "ox" import type { Account, Chain, Client, Hex, Transport } from "viem" import type { PasskeyServerRpcSchema } from "../../types/passkeyServer.js" +import { getOxExports } from "../../utils/ox.js" export type VerifyAuthenticationParameters = { raw: { diff --git a/packages/permissionless/actions/passkeyServer/verifyRegistration.ts b/packages/permissionless/actions/passkeyServer/verifyRegistration.ts index e59a4959..bdc6e120 100644 --- a/packages/permissionless/actions/passkeyServer/verifyRegistration.ts +++ b/packages/permissionless/actions/passkeyServer/verifyRegistration.ts @@ -1,7 +1,7 @@ -import { getOxExports } from "../../utils/ox.js" import type { Account, Chain, Client, Hex, Transport } from "viem" import type { CreateWebAuthnCredentialReturnType } from "viem/account-abstraction" import type { PasskeyServerRpcSchema } from "../../types/passkeyServer.js" +import { getOxExports } from "../../utils/ox.js" export type VerifyRegistrationParameters = { credential: CreateWebAuthnCredentialReturnType diff --git a/packages/permissionless/actions/smartAccount/getCallsStatus.ts b/packages/permissionless/actions/smartAccount/getCallsStatus.ts index c497ceaa..d7955d3a 100644 --- a/packages/permissionless/actions/smartAccount/getCallsStatus.ts +++ b/packages/permissionless/actions/smartAccount/getCallsStatus.ts @@ -3,6 +3,7 @@ import type { Client, GetCallsStatusParameters, GetCallsStatusReturnType, + Hex, Transport } from "viem" import { @@ -38,7 +39,7 @@ export async function getCallsStatus< client: Client, args: GetCallsStatusParameters ): Promise { - const userOperationHash = args.id as `0x${string}` + const userOperationHash = args.id as Hex const chainId = client.chain?.id ?? @@ -51,7 +52,7 @@ export async function getCallsStatus< getUserOperationReceipt, "getUserOperationReceipt" )({ - hash: args.id as `0x${string}` + hash: args.id as Hex }) const userOpStatus = receipt.success diff --git a/packages/permissionless/utils/ox.ts b/packages/permissionless/utils/ox.ts index 2884735b..fd56d39d 100644 --- a/packages/permissionless/utils/ox.ts +++ b/packages/permissionless/utils/ox.ts @@ -21,7 +21,7 @@ export async function getOxModule() { "The 'ox' package is required for WebAuthn functionality. Please install it: npm install ox" ) } - + try { return await oxModule.importPromise } catch (error) { diff --git a/packages/wagmi-demo/src/PasskeyServerDemo.tsx b/packages/wagmi-demo/src/PasskeyServerDemo.tsx index e2f6ad2b..d354c48e 100644 --- a/packages/wagmi-demo/src/PasskeyServerDemo.tsx +++ b/packages/wagmi-demo/src/PasskeyServerDemo.tsx @@ -1,4 +1,3 @@ -import { getOxExports } from "permissionless/utils/ox.js" import { type SmartAccountClient, createSmartAccountClient @@ -9,6 +8,7 @@ import { } from "permissionless/accounts" import { createPasskeyServerClient } from "permissionless/clients/passkeyServer" import { createPimlicoClient } from "permissionless/clients/pimlico" +import { getOxExports } from "permissionless/utils/ox.js" import * as React from "react" import { http, @@ -173,7 +173,7 @@ export function PasskeyServerDemo() { if (!smartAccountClient) return const formData = new FormData(event.currentTarget) - const to = formData.get("to") as `0x${string}` + const to = formData.get("to") as Hex const value = formData.get("value") as string const hash = await smartAccountClient.sendUserOperation({ From cde7a4c73d7d439f55558ff09d7e535771267532 Mon Sep 17 00:00:00 2001 From: plusminushalf Date: Thu, 13 Nov 2025 11:17:16 +0000 Subject: [PATCH 3/6] fix wagmi-demo --- bun.lock | 3 +++ package.json | 3 ++- packages/mock-paymaster/relay.ts | 1 - packages/wagmi-demo/src/PasskeyServerDemo.tsx | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/bun.lock b/bun.lock index 7409b933..9f825ce0 100644 --- a/bun.lock +++ b/bun.lock @@ -2,6 +2,9 @@ "lockfileVersion": 1, "workspaces": { "": { + "dependencies": { + "@wagmi/core": "2.17.1", + }, "devDependencies": { "@biomejs/biome": "^1.0.0", "@changesets/changelog-git": "^0.1.14", diff --git a/package.json b/package.json index 45b2b5e1..1c02dca9 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,8 @@ "viem": "2.28.1", "vite": "^5.4.10", "vitest": "^2.1.5", - "wagmi": "^2.15.1" + "wagmi": "^2.15.1", + "@wagmi/core": "2.17.1" }, "description": "", "keywords": [], diff --git a/packages/mock-paymaster/relay.ts b/packages/mock-paymaster/relay.ts index 5fd1619b..3c351271 100644 --- a/packages/mock-paymaster/relay.ts +++ b/packages/mock-paymaster/relay.ts @@ -13,7 +13,6 @@ import { getAddress, toHex } from "viem" -import type { Hex } from "viem" import { type BundlerClient, type UserOperation, diff --git a/packages/wagmi-demo/src/PasskeyServerDemo.tsx b/packages/wagmi-demo/src/PasskeyServerDemo.tsx index d354c48e..d54ae18e 100644 --- a/packages/wagmi-demo/src/PasskeyServerDemo.tsx +++ b/packages/wagmi-demo/src/PasskeyServerDemo.tsx @@ -8,7 +8,7 @@ import { } from "permissionless/accounts" import { createPasskeyServerClient } from "permissionless/clients/passkeyServer" import { createPimlicoClient } from "permissionless/clients/pimlico" -import { getOxExports } from "permissionless/utils/ox.js" +import { getOxExports } from "permissionless/utils" import * as React from "react" import { http, From b2900056b457dedfca1a81c009c9da83bb6565dc Mon Sep 17 00:00:00 2001 From: bvvvp009 Date: Thu, 13 Nov 2025 17:07:46 +0530 Subject: [PATCH 4/6] chore: address maintainer feedback - use utils index import and add @wagmi/core --- packages/wagmi-demo/src/PasskeyServerDemo.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wagmi-demo/src/PasskeyServerDemo.tsx b/packages/wagmi-demo/src/PasskeyServerDemo.tsx index d54ae18e..c1ce2fd8 100644 --- a/packages/wagmi-demo/src/PasskeyServerDemo.tsx +++ b/packages/wagmi-demo/src/PasskeyServerDemo.tsx @@ -1,3 +1,4 @@ +import { getOxExports } from "permissionless/utils" import { type SmartAccountClient, createSmartAccountClient @@ -8,7 +9,6 @@ import { } from "permissionless/accounts" import { createPasskeyServerClient } from "permissionless/clients/passkeyServer" import { createPimlicoClient } from "permissionless/clients/pimlico" -import { getOxExports } from "permissionless/utils" import * as React from "react" import { http, From fff92fbeab73d9377ed34540646f35b879c83dd0 Mon Sep 17 00:00:00 2001 From: plusminushalf Date: Thu, 13 Nov 2025 11:45:39 +0000 Subject: [PATCH 5/6] Add changeset --- .changeset/sharp-comics-sing.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/sharp-comics-sing.md diff --git a/.changeset/sharp-comics-sing.md b/.changeset/sharp-comics-sing.md new file mode 100644 index 00000000..8670c1b2 --- /dev/null +++ b/.changeset/sharp-comics-sing.md @@ -0,0 +1,5 @@ +--- +"permissionless": patch +--- + +Dynamically loads ox, thank to @Bvvvp009 From 61494f2d6ca5ae0393e36468d6bf0c2a1aee474a Mon Sep 17 00:00:00 2001 From: plusminushalf Date: Thu, 13 Nov 2025 11:52:12 +0000 Subject: [PATCH 6/6] update bun lock --- bun.lock | 4 +--- packages/wagmi-demo/src/PasskeyServerDemo.tsx | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/bun.lock b/bun.lock index 9f825ce0..cdb9c8f3 100644 --- a/bun.lock +++ b/bun.lock @@ -2,9 +2,6 @@ "lockfileVersion": 1, "workspaces": { "": { - "dependencies": { - "@wagmi/core": "2.17.1", - }, "devDependencies": { "@biomejs/biome": "^1.0.0", "@changesets/changelog-git": "^0.1.14", @@ -21,6 +18,7 @@ "@vitejs/plugin-react": "^4.2.1", "@vitest/coverage-v8": "^2.1.5", "@wagmi/cli": "latest", + "@wagmi/core": "2.17.1", "async-mutex": "^0.5.0", "buffer": "^6.0.3", "bun-types": "^1.0.7", diff --git a/packages/wagmi-demo/src/PasskeyServerDemo.tsx b/packages/wagmi-demo/src/PasskeyServerDemo.tsx index c1ce2fd8..d54ae18e 100644 --- a/packages/wagmi-demo/src/PasskeyServerDemo.tsx +++ b/packages/wagmi-demo/src/PasskeyServerDemo.tsx @@ -1,4 +1,3 @@ -import { getOxExports } from "permissionless/utils" import { type SmartAccountClient, createSmartAccountClient @@ -9,6 +8,7 @@ import { } from "permissionless/accounts" import { createPasskeyServerClient } from "permissionless/clients/passkeyServer" import { createPimlicoClient } from "permissionless/clients/pimlico" +import { getOxExports } from "permissionless/utils" import * as React from "react" import { http,