permissionless 0.2.33 → 0.2.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/_cjs/accounts/kernel/toKernelSmartAccount.js +3 -3
  3. package/_cjs/accounts/kernel/toKernelSmartAccount.js.map +1 -1
  4. package/_cjs/accounts/kernel/utils/signMessage.js +2 -2
  5. package/_cjs/accounts/kernel/utils/signMessage.js.map +1 -1
  6. package/_cjs/accounts/safe/toSafeSmartAccount.js +6 -2
  7. package/_cjs/accounts/safe/toSafeSmartAccount.js.map +1 -1
  8. package/_cjs/actions/passkeyServer/getCredentials.js +24 -0
  9. package/_cjs/actions/passkeyServer/getCredentials.js.map +1 -0
  10. package/_cjs/actions/passkeyServer/startRegistration.js +80 -0
  11. package/_cjs/actions/passkeyServer/startRegistration.js.map +1 -0
  12. package/_cjs/actions/passkeyServer/verifyRegistration.js +71 -0
  13. package/_cjs/actions/passkeyServer/verifyRegistration.js.map +1 -0
  14. package/_cjs/actions/passkeyServer.js +10 -0
  15. package/_cjs/actions/passkeyServer.js.map +1 -0
  16. package/_cjs/clients/decorators/passkeyServer.js +13 -0
  17. package/_cjs/clients/decorators/passkeyServer.js.map +1 -0
  18. package/_cjs/clients/passkeyServer.js +15 -0
  19. package/_cjs/clients/passkeyServer.js.map +1 -0
  20. package/_cjs/types/passkeyServer.js +3 -0
  21. package/_cjs/types/passkeyServer.js.map +1 -0
  22. package/_esm/accounts/kernel/toKernelSmartAccount.js +3 -3
  23. package/_esm/accounts/kernel/toKernelSmartAccount.js.map +1 -1
  24. package/_esm/accounts/kernel/utils/signMessage.js +2 -2
  25. package/_esm/accounts/kernel/utils/signMessage.js.map +1 -1
  26. package/_esm/accounts/safe/toSafeSmartAccount.js +6 -2
  27. package/_esm/accounts/safe/toSafeSmartAccount.js.map +1 -1
  28. package/_esm/actions/passkeyServer/getCredentials.js +20 -0
  29. package/_esm/actions/passkeyServer/getCredentials.js.map +1 -0
  30. package/_esm/actions/passkeyServer/startRegistration.js +85 -0
  31. package/_esm/actions/passkeyServer/startRegistration.js.map +1 -0
  32. package/_esm/actions/passkeyServer/verifyRegistration.js +67 -0
  33. package/_esm/actions/passkeyServer/verifyRegistration.js.map +1 -0
  34. package/_esm/actions/passkeyServer.js +5 -0
  35. package/_esm/actions/passkeyServer.js.map +1 -0
  36. package/_esm/clients/decorators/passkeyServer.js +9 -0
  37. package/_esm/clients/decorators/passkeyServer.js.map +1 -0
  38. package/_esm/clients/passkeyServer.js +12 -0
  39. package/_esm/clients/passkeyServer.js.map +1 -0
  40. package/_esm/types/passkeyServer.js +2 -0
  41. package/_esm/types/passkeyServer.js.map +1 -0
  42. package/_types/accounts/kernel/toKernelSmartAccount.d.ts.map +1 -1
  43. package/_types/accounts/kernel/utils/signMessage.d.ts.map +1 -1
  44. package/_types/accounts/safe/toSafeSmartAccount.d.ts +2 -1
  45. package/_types/accounts/safe/toSafeSmartAccount.d.ts.map +1 -1
  46. package/_types/actions/passkeyServer/getCredentials.d.ts +11 -0
  47. package/_types/actions/passkeyServer/getCredentials.d.ts.map +1 -0
  48. package/_types/actions/passkeyServer/startRegistration.d.ts +9 -0
  49. package/_types/actions/passkeyServer/startRegistration.d.ts.map +1 -0
  50. package/_types/actions/passkeyServer/verifyRegistration.d.ts +14 -0
  51. package/_types/actions/passkeyServer/verifyRegistration.d.ts.map +1 -0
  52. package/_types/actions/passkeyServer.d.ts +5 -0
  53. package/_types/actions/passkeyServer.d.ts.map +1 -0
  54. package/_types/clients/decorators/passkeyServer.d.ts +12 -0
  55. package/_types/clients/decorators/passkeyServer.d.ts.map +1 -0
  56. package/_types/clients/passkeyServer.d.ts +7 -0
  57. package/_types/clients/passkeyServer.d.ts.map +1 -0
  58. package/_types/types/passkeyServer.d.ts +74 -0
  59. package/_types/types/passkeyServer.d.ts.map +1 -0
  60. package/accounts/kernel/toKernelSmartAccount.ts +6 -7
  61. package/accounts/kernel/utils/signMessage.ts +2 -2
  62. package/accounts/safe/toSafeSmartAccount.ts +11 -2
  63. package/actions/passkeyServer/getCredentials.ts +47 -0
  64. package/actions/passkeyServer/startRegistration.ts +125 -0
  65. package/actions/passkeyServer/verifyRegistration.ts +114 -0
  66. package/actions/passkeyServer.ts +29 -0
  67. package/clients/decorators/passkeyServer.ts +42 -0
  68. package/clients/passkeyServer.ts +69 -0
  69. package/package.json +18 -3
  70. package/types/passkeyServer.ts +82 -0
@@ -0,0 +1,12 @@
1
+ import type { Account, Chain, Client, Transport } from "viem";
2
+ import { type GetCredentialsParameters, type GetCredentialsReturnType } from "../../actions/passkeyServer/getCredentials.js";
3
+ import { type StartRegistrationParameters, type StartRegistrationReturnType } from "../../actions/passkeyServer/startRegistration.js";
4
+ import { type VerifyRegistrationParameters, type VerifyRegistrationReturnType } from "../../actions/passkeyServer/verifyRegistration.js";
5
+ import type { PasskeyServerRpcSchema } from "../../types/passkeyServer.js";
6
+ export type PasskeyServerActions = {
7
+ startRegistration: (args: StartRegistrationParameters) => Promise<StartRegistrationReturnType>;
8
+ verifyRegistration: (args: VerifyRegistrationParameters) => Promise<VerifyRegistrationReturnType>;
9
+ getCredentials: (args: GetCredentialsParameters) => Promise<GetCredentialsReturnType>;
10
+ };
11
+ export declare const passkeyServerActions: (client: Client<Transport, Chain | undefined, Account | undefined, PasskeyServerRpcSchema>) => PasskeyServerActions;
12
+ //# sourceMappingURL=passkeyServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passkeyServer.d.ts","sourceRoot":"","sources":["../../../clients/decorators/passkeyServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,MAAM,CAAA;AAC7D,OAAO,EACH,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAEhC,MAAM,+CAA+C,CAAA;AACtD,OAAO,EACH,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,EAEnC,MAAM,kDAAkD,CAAA;AACzD,OAAO,EACH,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,EAEpC,MAAM,mDAAmD,CAAA;AAC1D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAA;AAE1E,MAAM,MAAM,oBAAoB,GAAG;IAC/B,iBAAiB,EAAE,CACf,IAAI,EAAE,2BAA2B,KAChC,OAAO,CAAC,2BAA2B,CAAC,CAAA;IACzC,kBAAkB,EAAE,CAChB,IAAI,EAAE,4BAA4B,KACjC,OAAO,CAAC,4BAA4B,CAAC,CAAA;IAC1C,cAAc,EAAE,CACZ,IAAI,EAAE,wBAAwB,KAC7B,OAAO,CAAC,wBAAwB,CAAC,CAAA;CACzC,CAAA;AAED,eAAO,MAAM,oBAAoB,WACrB,MAAM,CACV,SAAS,EACT,KAAK,GAAG,SAAS,EACjB,OAAO,GAAG,SAAS,EACnB,sBAAsB,CACzB,KACF,oBAID,CAAA"}
@@ -0,0 +1,7 @@
1
+ import type { Account, Chain, Client, ClientConfig, Prettify, RpcSchema, Transport } from "viem";
2
+ import type { PasskeyServerRpcSchema } from "../types/passkeyServer.js";
3
+ import { type PasskeyServerActions } from "./decorators/passkeyServer.js";
4
+ export type PasskeyServerClient<rpcSchema extends RpcSchema | undefined = undefined> = Prettify<Client<Transport, Chain | undefined, Account | undefined, rpcSchema extends RpcSchema ? [...PasskeyServerRpcSchema, ...rpcSchema] : [...PasskeyServerRpcSchema], PasskeyServerActions>>;
5
+ export type PasskeyServerClientConfig<rpcSchema extends RpcSchema | undefined = undefined> = Prettify<Pick<ClientConfig<Transport, Chain | undefined, Account | undefined, rpcSchema>, "account" | "cacheTime" | "chain" | "key" | "name" | "pollingInterval" | "rpcSchema" | "transport">>;
6
+ export declare function createPasskeyServerClient<rpcSchema extends RpcSchema | undefined = undefined>(parameters: PasskeyServerClientConfig<rpcSchema>): PasskeyServerClient<rpcSchema>;
7
+ //# sourceMappingURL=passkeyServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passkeyServer.d.ts","sourceRoot":"","sources":["../../clients/passkeyServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,OAAO,EACP,KAAK,EACL,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,SAAS,EACZ,MAAM,MAAM,CAAA;AAEb,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AACvE,OAAO,EACH,KAAK,oBAAoB,EAE5B,MAAM,+BAA+B,CAAA;AAEtC,MAAM,MAAM,mBAAmB,CAC3B,SAAS,SAAS,SAAS,GAAG,SAAS,GAAG,SAAS,IACnD,QAAQ,CACR,MAAM,CACF,SAAS,EACT,KAAK,GAAG,SAAS,EACjB,OAAO,GAAG,SAAS,EACnB,SAAS,SAAS,SAAS,GACrB,CAAC,GAAG,sBAAsB,EAAE,GAAG,SAAS,CAAC,GACzC,CAAC,GAAG,sBAAsB,CAAC,EACjC,oBAAoB,CACvB,CACJ,CAAA;AAED,MAAM,MAAM,yBAAyB,CACjC,SAAS,SAAS,SAAS,GAAG,SAAS,GAAG,SAAS,IACnD,QAAQ,CACR,IAAI,CACA,YAAY,CACR,SAAS,EACT,KAAK,GAAG,SAAS,EACjB,OAAO,GAAG,SAAS,EACnB,SAAS,CACZ,EACC,SAAS,GACT,WAAW,GACX,OAAO,GACP,KAAK,GACL,MAAM,GACN,iBAAiB,GACjB,WAAW,GACX,WAAW,CAChB,CACJ,CAAA;AAED,wBAAgB,yBAAyB,CACrC,SAAS,SAAS,SAAS,GAAG,SAAS,GAAG,SAAS,EAEnD,UAAU,EAAE,yBAAyB,CAAC,SAAS,CAAC,GACjD,mBAAmB,CAAC,SAAS,CAAC,CAAA"}
@@ -0,0 +1,74 @@
1
+ import type { Hex } from "viem";
2
+ export type PasskeyServerRpcSchema = [
3
+ {
4
+ Method: "pks_startRegistration";
5
+ Parameters: [context: unknown];
6
+ ReturnType: {
7
+ rp: {
8
+ id: string;
9
+ name: string;
10
+ };
11
+ user: {
12
+ id: string;
13
+ name: string;
14
+ displayName: string;
15
+ };
16
+ challenge: string;
17
+ timeout?: number;
18
+ authenticatorSelection?: {
19
+ authenticatorAttachment?: "platform" | "cross-platform";
20
+ requireResidentKey?: boolean;
21
+ residentKey?: "required" | "preferred" | "discouraged";
22
+ userVerification?: "required" | "preferred" | "discouraged";
23
+ };
24
+ attestation: "direct" | "enterprise" | "indirect" | "none";
25
+ extensions?: {
26
+ appid?: string;
27
+ credProps?: boolean;
28
+ hmacCreateSecret?: boolean;
29
+ minPinLength?: boolean;
30
+ };
31
+ };
32
+ },
33
+ {
34
+ Method: "pks_verifyRegistration";
35
+ Parameters: [
36
+ {
37
+ id: string;
38
+ rawId: string;
39
+ response: {
40
+ clientDataJSON: string;
41
+ attestationObject: string;
42
+ authenticatorData?: string;
43
+ transports?: ("ble" | "cable" | "hybrid" | "internal" | "nfc" | "smart-card" | "usb")[];
44
+ publicKeyAlgorithm?: number;
45
+ publicKeyType?: string;
46
+ };
47
+ authenticatorAttachment: "cross-platform" | "platform";
48
+ clientExtensionResults: {
49
+ appid?: boolean;
50
+ credProps?: {
51
+ rk?: boolean;
52
+ };
53
+ hmacCreateSecret?: boolean;
54
+ };
55
+ type: "public-key";
56
+ },
57
+ context: unknown
58
+ ];
59
+ ReturnType: {
60
+ success: boolean;
61
+ id: string;
62
+ publicKey: Hex;
63
+ };
64
+ },
65
+ {
66
+ Method: "pks_getCredentials";
67
+ Parameters: [context: unknown];
68
+ ReturnType: {
69
+ id: string;
70
+ publicKey: Hex;
71
+ }[];
72
+ }
73
+ ];
74
+ //# sourceMappingURL=passkeyServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"passkeyServer.d.ts","sourceRoot":"","sources":["../../types/passkeyServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,MAAM,CAAA;AAE/B,MAAM,MAAM,sBAAsB,GAAG;IACjC;QACI,MAAM,EAAE,uBAAuB,CAAA;QAC/B,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAC9B,UAAU,EAAE;YACR,EAAE,EAAE;gBACA,EAAE,EAAE,MAAM,CAAA;gBACV,IAAI,EAAE,MAAM,CAAA;aACf,CAAA;YACD,IAAI,EAAE;gBACF,EAAE,EAAE,MAAM,CAAA;gBACV,IAAI,EAAE,MAAM,CAAA;gBACZ,WAAW,EAAE,MAAM,CAAA;aACtB,CAAA;YACD,SAAS,EAAE,MAAM,CAAA;YACjB,OAAO,CAAC,EAAE,MAAM,CAAA;YAChB,sBAAsB,CAAC,EAAE;gBACrB,uBAAuB,CAAC,EAAE,UAAU,GAAG,gBAAgB,CAAA;gBACvD,kBAAkB,CAAC,EAAE,OAAO,CAAA;gBAC5B,WAAW,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,aAAa,CAAA;gBACtD,gBAAgB,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,aAAa,CAAA;aAC9D,CAAA;YACD,WAAW,EAAE,QAAQ,GAAG,YAAY,GAAG,UAAU,GAAG,MAAM,CAAA;YAC1D,UAAU,CAAC,EAAE;gBACT,KAAK,CAAC,EAAE,MAAM,CAAA;gBACd,SAAS,CAAC,EAAE,OAAO,CAAA;gBACnB,gBAAgB,CAAC,EAAE,OAAO,CAAA;gBAC1B,YAAY,CAAC,EAAE,OAAO,CAAA;aACzB,CAAA;SACJ,CAAA;KACJ;IACD;QACI,MAAM,EAAE,wBAAwB,CAAA;QAChC,UAAU,EAAE;YACR;gBACI,EAAE,EAAE,MAAM,CAAA;gBACV,KAAK,EAAE,MAAM,CAAA;gBACb,QAAQ,EAAE;oBACN,cAAc,EAAE,MAAM,CAAA;oBACtB,iBAAiB,EAAE,MAAM,CAAA;oBACzB,iBAAiB,CAAC,EAAE,MAAM,CAAA;oBAC1B,UAAU,CAAC,EAAE,CACP,KAAK,GACL,OAAO,GACP,QAAQ,GACR,UAAU,GACV,KAAK,GACL,YAAY,GACZ,KAAK,CACV,EAAE,CAAA;oBACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;oBAC3B,aAAa,CAAC,EAAE,MAAM,CAAA;iBACzB,CAAA;gBACD,uBAAuB,EAAE,gBAAgB,GAAG,UAAU,CAAA;gBACtD,sBAAsB,EAAE;oBACpB,KAAK,CAAC,EAAE,OAAO,CAAA;oBACf,SAAS,CAAC,EAAE;wBACR,EAAE,CAAC,EAAE,OAAO,CAAA;qBACf,CAAA;oBACD,gBAAgB,CAAC,EAAE,OAAO,CAAA;iBAC7B,CAAA;gBACD,IAAI,EAAE,YAAY,CAAA;aACrB;YACD,OAAO,EAAE,OAAO;SACnB,CAAA;QACD,UAAU,EAAE;YACR,OAAO,EAAE,OAAO,CAAA;YAChB,EAAE,EAAE,MAAM,CAAA;YACV,SAAS,EAAE,GAAG,CAAA;SACjB,CAAA;KACJ;IACD;QACI,MAAM,EAAE,oBAAoB,CAAA;QAC5B,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAC9B,UAAU,EAAE;YACR,EAAE,EAAE,MAAM,CAAA;YACV,SAAS,EAAE,GAAG,CAAA;SACjB,EAAE,CAAA;KACN;CACJ,CAAA"}
@@ -1,3 +1,4 @@
1
+ import { Base64, Hex, PublicKey } from "ox"
1
2
  import type {
2
3
  Account,
3
4
  Assign,
@@ -9,7 +10,6 @@ import type {
9
10
  import {
10
11
  type Address,
11
12
  type Client,
12
- type Hex,
13
13
  type LocalAccount,
14
14
  type TypedDataDefinition,
15
15
  concatHex,
@@ -32,7 +32,6 @@ import {
32
32
  } from "viem/account-abstraction"
33
33
  import { signMessage as _signMessage, getChainId } from "viem/actions"
34
34
  import { getAction } from "viem/utils"
35
- import { base64UrlToBytes, bytesToHex, parsePublicKey } from "webauthn-p256"
36
35
  import { getAccountNonce } from "../../actions/public/getAccountNonce.js"
37
36
  import { getSenderAddress } from "../../actions/public/getSenderAddress.js"
38
37
  import { type EthereumProvider, toOwner } from "../../utils/toOwner.js"
@@ -225,7 +224,7 @@ const getInitializationData = <entryPointVersion extends "0.6" | "0.7">({
225
224
  entryPoint: {
226
225
  version: entryPointVersion
227
226
  }
228
- validatorData: Hex
227
+ validatorData: Hex.Hex
229
228
  validatorAddress: Address
230
229
  }) => {
231
230
  if (entryPointVersion === "0.6") {
@@ -268,9 +267,9 @@ const getValidatorData = async (owner: WebAuthnAccount | LocalAccount) => {
268
267
  }
269
268
 
270
269
  if (isWebAuthnAccount(owner)) {
271
- const parsedPublicKey = parsePublicKey(owner.publicKey)
270
+ const parsedPublicKey = PublicKey.fromHex(owner.publicKey)
272
271
  const authenticatorIdHash = keccak256(
273
- bytesToHex(base64UrlToBytes(owner.id))
272
+ Hex.fromBytes(Base64.toBytes(owner.id))
274
273
  )
275
274
 
276
275
  return encodeAbiParameters(
@@ -322,13 +321,13 @@ const getAccountInitCode = async <entryPointVersion extends "0.6" | "0.7">({
322
321
  }: {
323
322
  kernelVersion: KernelVersion<entryPointVersion>
324
323
  entryPointVersion: entryPointVersion
325
- validatorData: Hex
324
+ validatorData: Hex.Hex
326
325
  index: bigint
327
326
  factoryAddress: Address
328
327
  accountLogicAddress: Address
329
328
  validatorAddress: Address
330
329
  useMetaFactory: boolean
331
- }): Promise<Hex> => {
330
+ }): Promise<Hex.Hex> => {
332
331
  // Build the account initialization data
333
332
  const initializationData = getInitializationData({
334
333
  entryPoint: { version: entryPointVersion },
@@ -1,3 +1,4 @@
1
+ import { Signature } from "ox"
1
2
  import {
2
3
  type Hash,
3
4
  type LocalAccount,
@@ -8,7 +9,6 @@ import {
8
9
  } from "viem"
9
10
  import type { WebAuthnAccount } from "viem/account-abstraction"
10
11
  import { signMessage as _signMessage } from "viem/actions"
11
- import { parseSignature } from "webauthn-p256"
12
12
  import { isWebAuthnAccount } from "./isWebAuthnAccount.js"
13
13
  import {
14
14
  type WrapMessageHashParams,
@@ -51,7 +51,7 @@ export async function signMessage({
51
51
  const { signature: signatureData, webauthn } = await owner.sign({
52
52
  hash: messageContent as Hash
53
53
  })
54
- const signature = parseSignature(signatureData)
54
+ const signature = Signature.fromHex(signatureData)
55
55
 
56
56
  // encode signature
57
57
  const encodedSignature = encodeAbiParameters(
@@ -928,6 +928,7 @@ type GetErc7579Params<TErc7579 extends Address | undefined> =
928
928
  safeModuleSetupAddress?: Address
929
929
  multiSendAddress?: Address
930
930
  multiSendCallOnlyAddress?: Address
931
+ // @deprecated This field is deprecated. It is recommended to make any setup transactions in the userOperation's calldata.
931
932
  setupTransactions?: {
932
933
  to: Address
933
934
  data: Address
@@ -975,6 +976,7 @@ export type ToSafeSmartAccountParameters<
975
976
  paymentToken?: Address
976
977
  payment?: bigint
977
978
  paymentReceiver?: Address
979
+ onchainIdentifier?: Hex
978
980
  } & GetErc7579Params<TErc7579>
979
981
 
980
982
  function isErc7579Args<entryPointVersion extends "0.6" | "0.7" = "0.7">(
@@ -1149,7 +1151,8 @@ export async function toSafeSmartAccount<
1149
1151
  nonceKey,
1150
1152
  paymentToken,
1151
1153
  payment,
1152
- paymentReceiver
1154
+ paymentReceiver,
1155
+ onchainIdentifier
1153
1156
  } = parameters
1154
1157
 
1155
1158
  const owners = await Promise.all(
@@ -1421,11 +1424,17 @@ export async function toSafeSmartAccount<
1421
1424
  value = call.value ?? 0n
1422
1425
  }
1423
1426
 
1424
- return encodeFunctionData({
1427
+ const calldata = encodeFunctionData({
1425
1428
  abi: executeUserOpWithErrorStringAbi,
1426
1429
  functionName: "executeUserOpWithErrorString",
1427
1430
  args: [to, value, data, operationType]
1428
1431
  })
1432
+
1433
+ if (onchainIdentifier) {
1434
+ return concat([calldata, onchainIdentifier])
1435
+ }
1436
+
1437
+ return calldata
1429
1438
  },
1430
1439
  async decodeCalls(callData) {
1431
1440
  try {
@@ -0,0 +1,47 @@
1
+ import type { Account, Chain, Client, Hex, Transport } from "viem"
2
+ import type { PasskeyServerRpcSchema } from "../../types/passkeyServer.js"
3
+
4
+ export type GetCredentialsParameters = {
5
+ context?: Record<string, unknown>
6
+ }
7
+
8
+ export type GetCredentialsReturnType = {
9
+ id: string
10
+ publicKey: Hex
11
+ }[]
12
+
13
+ export const getCredentials = async (
14
+ client: Client<
15
+ Transport,
16
+ Chain | undefined,
17
+ Account | undefined,
18
+ PasskeyServerRpcSchema
19
+ >,
20
+ args?: GetCredentialsParameters
21
+ ): Promise<GetCredentialsReturnType> => {
22
+ const response = await client.request({
23
+ method: "pks_getCredentials",
24
+ params: [args?.context]
25
+ })
26
+
27
+ if (!Array.isArray(response)) {
28
+ throw new Error("Invalid response from server - expected array")
29
+ }
30
+
31
+ for (const passkey of response) {
32
+ if (typeof passkey?.id !== "string") {
33
+ throw new Error("Invalid passkey id returned from server")
34
+ }
35
+
36
+ if (
37
+ typeof passkey?.publicKey !== "string" ||
38
+ !passkey.publicKey.startsWith("0x")
39
+ ) {
40
+ throw new Error(
41
+ "Invalid public key returned from server - must be hex string starting with 0x"
42
+ )
43
+ }
44
+ }
45
+
46
+ return response
47
+ }
@@ -0,0 +1,125 @@
1
+ import { Base64 } from "ox"
2
+ import type { Account, Chain, Client, Transport } from "viem"
3
+ import type { CreateWebAuthnCredentialParameters } from "viem/account-abstraction"
4
+ import type { PasskeyServerRpcSchema } from "../../types/passkeyServer.js"
5
+
6
+ const validateAttestation = (attestation: unknown): boolean => {
7
+ return (
8
+ !!attestation &&
9
+ ["direct", "enterprise", "indirect", "none"].includes(
10
+ attestation as string
11
+ )
12
+ )
13
+ }
14
+
15
+ const validateAuthenticatorSelection = (
16
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
17
+ authenticatorSelection: any
18
+ ): boolean => {
19
+ if (!authenticatorSelection) return false
20
+
21
+ const validAttachments = ["platform", "cross-platform"]
22
+ const validKeyOptions = ["required", "preferred", "discouraged"]
23
+
24
+ return (
25
+ validAttachments.includes(
26
+ authenticatorSelection.authenticatorAttachment
27
+ ) &&
28
+ typeof authenticatorSelection.requireResidentKey === "boolean" &&
29
+ validKeyOptions.includes(authenticatorSelection.residentKey) &&
30
+ validKeyOptions.includes(authenticatorSelection.userVerification)
31
+ )
32
+ }
33
+
34
+ const validateChallenge = (challenge: unknown): boolean => {
35
+ return !!challenge && typeof challenge === "string"
36
+ }
37
+
38
+ const validateExtensions = (extensions: unknown): boolean => {
39
+ if (!extensions) return true
40
+ if (typeof extensions !== "object") return false
41
+
42
+ const ext = extensions as Record<string, unknown>
43
+
44
+ // Optional appid must be string if present
45
+ if ("appid" in ext && typeof ext.appid !== "string") return false
46
+
47
+ // Optional credProps must be boolean if present
48
+ if ("credProps" in ext && typeof ext.credProps !== "boolean") return false
49
+
50
+ // Optional hmacCreateSecret must be boolean if present
51
+ if ("hmacCreateSecret" in ext && typeof ext.hmacCreateSecret !== "boolean")
52
+ return false
53
+
54
+ // Optional minPinLength must be boolean if present
55
+ if ("minPinLength" in ext && typeof ext.minPinLength !== "boolean")
56
+ return false
57
+
58
+ return true
59
+ }
60
+
61
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
62
+ const validateRp = (rp: any): boolean => {
63
+ return !!rp && typeof rp.id === "string" && typeof rp.name === "string"
64
+ }
65
+
66
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
67
+ const validateUser = (user: any): boolean => {
68
+ return (
69
+ !!user &&
70
+ typeof user.id === "string" &&
71
+ typeof user.name === "string" &&
72
+ typeof user.displayName === "string"
73
+ )
74
+ }
75
+
76
+ export type StartRegistrationParameters = {
77
+ context?: Record<string, unknown>
78
+ }
79
+ export type StartRegistrationReturnType = CreateWebAuthnCredentialParameters
80
+
81
+ export const startRegistration = async (
82
+ client: Client<
83
+ Transport,
84
+ Chain | undefined,
85
+ Account | undefined,
86
+ PasskeyServerRpcSchema
87
+ >,
88
+ args?: StartRegistrationParameters
89
+ ): Promise<StartRegistrationReturnType> => {
90
+ const response = await client.request({
91
+ method: "pks_startRegistration",
92
+ params: [args?.context]
93
+ })
94
+
95
+ // Validate the response matches expected schema
96
+ if (
97
+ !validateAttestation(response.attestation) ||
98
+ !validateAuthenticatorSelection(response.authenticatorSelection) ||
99
+ !validateChallenge(response.challenge) ||
100
+ !validateExtensions(response.extensions) ||
101
+ !validateRp(response.rp) ||
102
+ !validateUser(response.user)
103
+ ) {
104
+ throw new Error("Invalid response format from passkey server")
105
+ }
106
+
107
+ const credentialOptions: StartRegistrationReturnType = {
108
+ attestation: response.attestation,
109
+ authenticatorSelection: response.authenticatorSelection,
110
+ challenge: Base64.toBytes(response.challenge),
111
+ extensions: response.extensions
112
+ ? {
113
+ ...response.extensions
114
+ }
115
+ : undefined,
116
+ rp: response.rp,
117
+ timeout: response.timeout,
118
+ user: {
119
+ id: Base64.toBytes(response.user.id),
120
+ name: response.user.name,
121
+ displayName: response.user.displayName
122
+ }
123
+ }
124
+ return credentialOptions
125
+ }
@@ -0,0 +1,114 @@
1
+ import { Base64 } from "ox"
2
+ import type { Account, Chain, Client, Hex, Transport } from "viem"
3
+ import type { CreateWebAuthnCredentialReturnType } from "viem/account-abstraction"
4
+ import type { PasskeyServerRpcSchema } from "../../types/passkeyServer.js"
5
+
6
+ export type VerifyRegistrationParameters = {
7
+ credential: CreateWebAuthnCredentialReturnType
8
+ context: unknown
9
+ }
10
+
11
+ export type VerifyRegistrationReturnType = {
12
+ success: boolean
13
+ id: string
14
+ publicKey: Hex
15
+ }
16
+
17
+ export const verifyRegistration = async (
18
+ client: Client<
19
+ Transport,
20
+ Chain | undefined,
21
+ Account | undefined,
22
+ PasskeyServerRpcSchema
23
+ >,
24
+ args: VerifyRegistrationParameters
25
+ ): Promise<VerifyRegistrationReturnType> => {
26
+ const { credential, context } = args
27
+
28
+ const response = credential.raw
29
+ .response as unknown as AuthenticatorAttestationResponse
30
+
31
+ let responsePublicKeyAlgorithm: number | undefined = undefined
32
+ if (typeof response.getPublicKeyAlgorithm === "function") {
33
+ try {
34
+ responsePublicKeyAlgorithm = response.getPublicKeyAlgorithm()
35
+ } catch (error) {
36
+ throw new Error("getPublicKeyAlgorithm() is not supported")
37
+ }
38
+ }
39
+
40
+ let responseAuthenticatorData: string | undefined
41
+ if (typeof response.getAuthenticatorData === "function") {
42
+ try {
43
+ responseAuthenticatorData = Base64.fromBytes(
44
+ new Uint8Array(response.getAuthenticatorData())
45
+ )
46
+ } catch (error) {
47
+ throw new Error("getAuthenticatorData() is not supported")
48
+ }
49
+ }
50
+
51
+ const serverResponse = await client.request({
52
+ method: "pks_verifyRegistration",
53
+ params: [
54
+ {
55
+ id: credential.id,
56
+ rawId: Base64.fromBytes(new Uint8Array(credential.raw.rawId), {
57
+ pad: false,
58
+ url: true
59
+ }),
60
+ response: {
61
+ clientDataJSON: Base64.fromBytes(
62
+ new Uint8Array(response.clientDataJSON)
63
+ ),
64
+ attestationObject: Base64.fromBytes(
65
+ new Uint8Array(response.attestationObject),
66
+ {
67
+ url: true
68
+ }
69
+ ),
70
+ transports:
71
+ typeof response.getTransports === "function"
72
+ ? (response.getTransports() as (
73
+ | "ble"
74
+ | "cable"
75
+ | "hybrid"
76
+ | "internal"
77
+ | "nfc"
78
+ | "smart-card"
79
+ | "usb"
80
+ )[])
81
+ : undefined,
82
+ publicKeyAlgorithm: responsePublicKeyAlgorithm,
83
+ authenticatorData: responseAuthenticatorData
84
+ },
85
+ authenticatorAttachment: credential.raw
86
+ .authenticatorAttachment as "cross-platform" | "platform",
87
+ clientExtensionResults:
88
+ credential.raw.getClientExtensionResults(),
89
+ type: credential.raw.type as "public-key"
90
+ },
91
+ context
92
+ ]
93
+ })
94
+
95
+ const success = Boolean(serverResponse?.success)
96
+ const id = serverResponse?.id
97
+ const publicKey = serverResponse?.publicKey
98
+
99
+ if (typeof id !== "string") {
100
+ throw new Error("Invalid passkey id returned from server")
101
+ }
102
+
103
+ if (typeof publicKey !== "string" || !publicKey.startsWith("0x")) {
104
+ throw new Error(
105
+ "Invalid public key returned from server - must be hex string starting with 0x"
106
+ )
107
+ }
108
+
109
+ return {
110
+ success,
111
+ id,
112
+ publicKey: publicKey as Hex
113
+ }
114
+ }
@@ -0,0 +1,29 @@
1
+ import {
2
+ type StartRegistrationParameters,
3
+ type StartRegistrationReturnType,
4
+ startRegistration
5
+ } from "./passkeyServer/startRegistration.js"
6
+
7
+ import {
8
+ type VerifyRegistrationParameters,
9
+ type VerifyRegistrationReturnType,
10
+ verifyRegistration
11
+ } from "./passkeyServer/verifyRegistration.js"
12
+
13
+ import {
14
+ type GetCredentialsParameters,
15
+ type GetCredentialsReturnType,
16
+ getCredentials
17
+ } from "./passkeyServer/getCredentials.js"
18
+
19
+ export {
20
+ type StartRegistrationParameters,
21
+ type StartRegistrationReturnType,
22
+ type VerifyRegistrationParameters,
23
+ type VerifyRegistrationReturnType,
24
+ type GetCredentialsParameters,
25
+ type GetCredentialsReturnType,
26
+ startRegistration,
27
+ verifyRegistration,
28
+ getCredentials
29
+ }
@@ -0,0 +1,42 @@
1
+ import type { Account, Chain, Client, Transport } from "viem"
2
+ import {
3
+ type GetCredentialsParameters,
4
+ type GetCredentialsReturnType,
5
+ getCredentials
6
+ } from "../../actions/passkeyServer/getCredentials.js"
7
+ import {
8
+ type StartRegistrationParameters,
9
+ type StartRegistrationReturnType,
10
+ startRegistration
11
+ } from "../../actions/passkeyServer/startRegistration.js"
12
+ import {
13
+ type VerifyRegistrationParameters,
14
+ type VerifyRegistrationReturnType,
15
+ verifyRegistration
16
+ } from "../../actions/passkeyServer/verifyRegistration.js"
17
+ import type { PasskeyServerRpcSchema } from "../../types/passkeyServer.js"
18
+
19
+ export type PasskeyServerActions = {
20
+ startRegistration: (
21
+ args: StartRegistrationParameters
22
+ ) => Promise<StartRegistrationReturnType>
23
+ verifyRegistration: (
24
+ args: VerifyRegistrationParameters
25
+ ) => Promise<VerifyRegistrationReturnType>
26
+ getCredentials: (
27
+ args: GetCredentialsParameters
28
+ ) => Promise<GetCredentialsReturnType>
29
+ }
30
+
31
+ export const passkeyServerActions = (
32
+ client: Client<
33
+ Transport,
34
+ Chain | undefined,
35
+ Account | undefined,
36
+ PasskeyServerRpcSchema
37
+ >
38
+ ): PasskeyServerActions => ({
39
+ startRegistration: (args) => startRegistration(client, args),
40
+ verifyRegistration: (args) => verifyRegistration(client, args),
41
+ getCredentials: (args) => getCredentials(client, args)
42
+ })
@@ -0,0 +1,69 @@
1
+ import type {
2
+ Account,
3
+ Chain,
4
+ Client,
5
+ ClientConfig,
6
+ Prettify,
7
+ RpcSchema,
8
+ Transport
9
+ } from "viem"
10
+ import { createClient } from "viem"
11
+ import type { PasskeyServerRpcSchema } from "../types/passkeyServer.js"
12
+ import {
13
+ type PasskeyServerActions,
14
+ passkeyServerActions
15
+ } from "./decorators/passkeyServer.js"
16
+
17
+ export type PasskeyServerClient<
18
+ rpcSchema extends RpcSchema | undefined = undefined
19
+ > = Prettify<
20
+ Client<
21
+ Transport,
22
+ Chain | undefined,
23
+ Account | undefined,
24
+ rpcSchema extends RpcSchema
25
+ ? [...PasskeyServerRpcSchema, ...rpcSchema]
26
+ : [...PasskeyServerRpcSchema],
27
+ PasskeyServerActions
28
+ >
29
+ >
30
+
31
+ export type PasskeyServerClientConfig<
32
+ rpcSchema extends RpcSchema | undefined = undefined
33
+ > = Prettify<
34
+ Pick<
35
+ ClientConfig<
36
+ Transport,
37
+ Chain | undefined,
38
+ Account | undefined,
39
+ rpcSchema
40
+ >,
41
+ | "account"
42
+ | "cacheTime"
43
+ | "chain"
44
+ | "key"
45
+ | "name"
46
+ | "pollingInterval"
47
+ | "rpcSchema"
48
+ | "transport"
49
+ >
50
+ >
51
+
52
+ export function createPasskeyServerClient<
53
+ rpcSchema extends RpcSchema | undefined = undefined
54
+ >(
55
+ parameters: PasskeyServerClientConfig<rpcSchema>
56
+ ): PasskeyServerClient<rpcSchema>
57
+
58
+ export function createPasskeyServerClient(
59
+ parameters: PasskeyServerClientConfig
60
+ ): PasskeyServerClient {
61
+ const { key = "public", name = "Passkey Server Client" } = parameters
62
+
63
+ return createClient({
64
+ ...parameters,
65
+ key,
66
+ name,
67
+ type: "passkeyServerClient"
68
+ }).extend(passkeyServerActions)
69
+ }