@zerodev/wallet-core 0.0.1-alpha.14 → 0.0.1-alpha.16

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 (105) hide show
  1. package/dist/_cjs/actions/auth/{getUserEmail.js → getAuthenticators.js} +6 -6
  2. package/dist/_cjs/actions/auth/getAuthenticators.js.map +1 -0
  3. package/dist/_cjs/actions/auth/index.js +3 -3
  4. package/dist/_cjs/actions/auth/index.js.map +1 -1
  5. package/dist/_cjs/actions/index.js +6 -3
  6. package/dist/_cjs/actions/index.js.map +1 -1
  7. package/dist/_cjs/actions/wallet/index.js +9 -3
  8. package/dist/_cjs/actions/wallet/index.js.map +1 -1
  9. package/dist/_cjs/actions/wallet/sign7702Authorization.js +16 -0
  10. package/dist/_cjs/actions/wallet/sign7702Authorization.js.map +1 -0
  11. package/dist/_cjs/actions/wallet/signMessage.js +17 -0
  12. package/dist/_cjs/actions/wallet/signMessage.js.map +1 -0
  13. package/dist/_cjs/actions/wallet/signTransaction.js +9 -18
  14. package/dist/_cjs/actions/wallet/signTransaction.js.map +1 -1
  15. package/dist/_cjs/actions/wallet/signTypedDataV4.js +17 -0
  16. package/dist/_cjs/actions/wallet/signTypedDataV4.js.map +1 -0
  17. package/dist/_cjs/actions/wallet/signUserOperation.js +17 -0
  18. package/dist/_cjs/actions/wallet/signUserOperation.js.map +1 -0
  19. package/dist/_cjs/actions/wallet/signingUtils.js +64 -0
  20. package/dist/_cjs/actions/wallet/signingUtils.js.map +1 -0
  21. package/dist/_cjs/adapters/viem.js +57 -24
  22. package/dist/_cjs/adapters/viem.js.map +1 -1
  23. package/dist/_cjs/client/decorators/client.js +6 -4
  24. package/dist/_cjs/client/decorators/client.js.map +1 -1
  25. package/dist/_cjs/index.js +6 -2
  26. package/dist/_cjs/index.js.map +1 -1
  27. package/dist/_esm/actions/auth/getAuthenticators.js +36 -0
  28. package/dist/_esm/actions/auth/getAuthenticators.js.map +1 -0
  29. package/dist/_esm/actions/auth/index.js +1 -1
  30. package/dist/_esm/actions/auth/index.js.map +1 -1
  31. package/dist/_esm/actions/index.js +2 -2
  32. package/dist/_esm/actions/index.js.map +1 -1
  33. package/dist/_esm/actions/wallet/index.js +4 -1
  34. package/dist/_esm/actions/wallet/index.js.map +1 -1
  35. package/dist/_esm/actions/wallet/sign7702Authorization.js +13 -0
  36. package/dist/_esm/actions/wallet/sign7702Authorization.js.map +1 -0
  37. package/dist/_esm/actions/wallet/signMessage.js +14 -0
  38. package/dist/_esm/actions/wallet/signMessage.js.map +1 -0
  39. package/dist/_esm/actions/wallet/signTransaction.js +9 -36
  40. package/dist/_esm/actions/wallet/signTransaction.js.map +1 -1
  41. package/dist/_esm/actions/wallet/signTypedDataV4.js +14 -0
  42. package/dist/_esm/actions/wallet/signTypedDataV4.js.map +1 -0
  43. package/dist/_esm/actions/wallet/signUserOperation.js +14 -0
  44. package/dist/_esm/actions/wallet/signUserOperation.js.map +1 -0
  45. package/dist/_esm/actions/wallet/signingUtils.js +69 -0
  46. package/dist/_esm/actions/wallet/signingUtils.js.map +1 -0
  47. package/dist/_esm/adapters/viem.js +60 -27
  48. package/dist/_esm/adapters/viem.js.map +1 -1
  49. package/dist/_esm/client/decorators/client.js +6 -4
  50. package/dist/_esm/client/decorators/client.js.map +1 -1
  51. package/dist/_esm/index.js +2 -2
  52. package/dist/_esm/index.js.map +1 -1
  53. package/dist/_types/actions/auth/getAuthenticators.d.ts +65 -0
  54. package/dist/_types/actions/auth/getAuthenticators.d.ts.map +1 -0
  55. package/dist/_types/actions/auth/index.d.ts +1 -1
  56. package/dist/_types/actions/auth/index.d.ts.map +1 -1
  57. package/dist/_types/actions/index.d.ts +2 -2
  58. package/dist/_types/actions/index.d.ts.map +1 -1
  59. package/dist/_types/actions/wallet/index.d.ts +4 -1
  60. package/dist/_types/actions/wallet/index.d.ts.map +1 -1
  61. package/dist/_types/actions/wallet/sign7702Authorization.d.ts +19 -0
  62. package/dist/_types/actions/wallet/sign7702Authorization.d.ts.map +1 -0
  63. package/dist/_types/actions/wallet/signMessage.d.ts +19 -0
  64. package/dist/_types/actions/wallet/signMessage.d.ts.map +1 -0
  65. package/dist/_types/actions/wallet/signTransaction.d.ts +1 -19
  66. package/dist/_types/actions/wallet/signTransaction.d.ts.map +1 -1
  67. package/dist/_types/actions/wallet/signTypedDataV4.d.ts +21 -0
  68. package/dist/_types/actions/wallet/signTypedDataV4.d.ts.map +1 -0
  69. package/dist/_types/actions/wallet/signUserOperation.d.ts +21 -0
  70. package/dist/_types/actions/wallet/signUserOperation.d.ts.map +1 -0
  71. package/dist/_types/actions/wallet/signingUtils.d.ts +32 -0
  72. package/dist/_types/actions/wallet/signingUtils.d.ts.map +1 -0
  73. package/dist/_types/adapters/viem.d.ts.map +1 -1
  74. package/dist/_types/client/decorators/client.d.ts +18 -6
  75. package/dist/_types/client/decorators/client.d.ts.map +1 -1
  76. package/dist/_types/index.d.ts +2 -2
  77. package/dist/_types/index.d.ts.map +1 -1
  78. package/dist/tsconfig.build.tsbuildinfo +1 -1
  79. package/package.json +1 -1
  80. package/src/actions/auth/getAuthenticators.ts +89 -0
  81. package/src/actions/auth/index.ts +9 -5
  82. package/src/actions/index.ts +19 -6
  83. package/src/actions/wallet/index.ts +22 -4
  84. package/src/actions/wallet/sign7702Authorization.ts +48 -0
  85. package/src/actions/wallet/signMessage.ts +47 -0
  86. package/src/actions/wallet/signTransaction.ts +19 -38
  87. package/src/actions/wallet/signTypedDataV4.ts +52 -0
  88. package/src/actions/wallet/signUserOperation.ts +56 -0
  89. package/src/actions/wallet/signingUtils.ts +110 -0
  90. package/src/adapters/viem.ts +71 -39
  91. package/src/client/decorators/client.ts +49 -19
  92. package/src/index.ts +19 -3
  93. package/dist/_cjs/actions/auth/getUserEmail.js.map +0 -1
  94. package/dist/_cjs/actions/wallet/signRawPayload.js +0 -27
  95. package/dist/_cjs/actions/wallet/signRawPayload.js.map +0 -1
  96. package/dist/_esm/actions/auth/getUserEmail.js +0 -33
  97. package/dist/_esm/actions/auth/getUserEmail.js.map +0 -1
  98. package/dist/_esm/actions/wallet/signRawPayload.js +0 -42
  99. package/dist/_esm/actions/wallet/signRawPayload.js.map +0 -1
  100. package/dist/_types/actions/auth/getUserEmail.d.ts +0 -32
  101. package/dist/_types/actions/auth/getUserEmail.d.ts.map +0 -1
  102. package/dist/_types/actions/wallet/signRawPayload.d.ts +0 -39
  103. package/dist/_types/actions/wallet/signRawPayload.d.ts.map +0 -1
  104. package/src/actions/auth/getUserEmail.ts +0 -52
  105. package/src/actions/wallet/signRawPayload.ts +0 -75
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerodev/wallet-core",
3
- "version": "0.0.1-alpha.14",
3
+ "version": "0.0.1-alpha.16",
4
4
  "description": "ZeroDev Wallet SDK built on Turnkey",
5
5
  "main": "./dist/_cjs/index.js",
6
6
  "module": "./dist/_esm/index.js",
@@ -0,0 +1,89 @@
1
+ import type { Client } from '../../client/types.js'
2
+
3
+ export type GetAuthenticatorsParameters = {
4
+ /** The sub-organization ID to query authenticators for */
5
+ subOrganizationId: string
6
+ /** The project ID for the request */
7
+ projectId: string
8
+ /** The session token for authorization */
9
+ token: string
10
+ }
11
+
12
+ /** An OAuth authenticator linked to the user (PascalCase from Go default marshaling) */
13
+ export type OAuthAuthenticator = {
14
+ Provider?: string
15
+ ClientId?: string
16
+ Subject?: string
17
+ [key: string]: unknown
18
+ }
19
+
20
+ /** A passkey (WebAuthn) authenticator (PascalCase from Go default marshaling) */
21
+ export type PasskeyAuthenticator = {
22
+ RpId?: string
23
+ PublicKey?: string
24
+ CredentialId?: string
25
+ [key: string]: unknown
26
+ }
27
+
28
+ /** An email contact linked to the user (PascalCase from Go default marshaling) */
29
+ export type EmailContact = {
30
+ Email?: string
31
+ [key: string]: unknown
32
+ }
33
+
34
+ /** An API key authenticator (PascalCase from Go default marshaling) */
35
+ export type ApiKeyAuthenticator = {
36
+ ApiKey?: string
37
+ [key: string]: unknown
38
+ }
39
+
40
+ export type GetAuthenticatorsReturnType = {
41
+ /** OAuth providers linked to the user (null if none) */
42
+ oauths: OAuthAuthenticator[] | null
43
+ /** Passkey authenticators registered for the user (null if none) */
44
+ passkeys: PasskeyAuthenticator[] | null
45
+ /** Email contacts associated with the user (null if none) */
46
+ emailContacts: EmailContact[] | null
47
+ /** API keys associated with the user (null if none) */
48
+ apiKeys: ApiKeyAuthenticator[] | null
49
+ }
50
+
51
+ /**
52
+ * Fetches all authenticators (oauths, passkeys, emailContacts, apiKeys) for
53
+ * the authenticated user within the given project/sub-organization.
54
+ *
55
+ * Corresponds to `POST /api/v1/{projectId}/authenticators`.
56
+ *
57
+ * @param client - The ZeroDev Wallet client
58
+ * @param params - The parameters for the authenticators request
59
+ * @returns The user's authenticators grouped by type
60
+ *
61
+ * @example
62
+ * ```ts
63
+ * const authenticators = await getAuthenticators(client, {
64
+ * subOrganizationId: 'suborg_123',
65
+ * projectId: 'proj_456',
66
+ * token: 'session_token_abc',
67
+ * });
68
+ * console.log(authenticators.oauths, authenticators.passkeys);
69
+ * ```
70
+ */
71
+ export async function getAuthenticators(
72
+ client: Client,
73
+ params: GetAuthenticatorsParameters,
74
+ ): Promise<GetAuthenticatorsReturnType> {
75
+ const { subOrganizationId, projectId, token } = params
76
+
77
+ return await client.request({
78
+ path: `${projectId}/authenticators`,
79
+ method: 'POST',
80
+ body: {
81
+ subOrganizationId,
82
+ },
83
+ headers: {
84
+ Authorization: `Bearer ${token}`,
85
+ },
86
+ stamp: true,
87
+ stampPostion: 'headers',
88
+ })
89
+ }
@@ -10,15 +10,19 @@ export {
10
10
  type AuthenticateWithOAuthReturnType,
11
11
  authenticateWithOAuth,
12
12
  } from './authenticateWithOAuth.js'
13
+ export {
14
+ type ApiKeyAuthenticator,
15
+ type EmailContact,
16
+ type GetAuthenticatorsParameters,
17
+ type GetAuthenticatorsReturnType,
18
+ getAuthenticators,
19
+ type OAuthAuthenticator,
20
+ type PasskeyAuthenticator,
21
+ } from './getAuthenticators.js'
13
22
  export {
14
23
  type GetAuthProxyConfigIdReturnType,
15
24
  getAuthProxyConfigId,
16
25
  } from './getAuthProxyConfigId.js'
17
- export {
18
- type GetUserEmailParameters,
19
- type GetUserEmailReturnType,
20
- getUserEmail,
21
- } from './getUserEmail.js'
22
26
  export {
23
27
  type GetWhoamiParameters,
24
28
  type GetWhoamiReturnType,
@@ -1,24 +1,28 @@
1
1
  // Auth actions
2
2
  export {
3
+ type ApiKeyAuthenticator,
3
4
  type AuthenticateWithEmailParameters,
4
5
  type AuthenticateWithEmailReturnType,
5
6
  type AuthenticateWithOAuthParameters,
6
7
  type AuthenticateWithOAuthReturnType,
7
8
  authenticateWithEmail,
8
9
  authenticateWithOAuth,
10
+ type EmailContact,
9
11
  type EmailCustomization,
12
+ type GetAuthenticatorsParameters,
13
+ type GetAuthenticatorsReturnType,
10
14
  type GetAuthProxyConfigIdReturnType,
11
- type GetUserEmailParameters,
12
- type GetUserEmailReturnType,
13
15
  type GetWhoamiParameters,
14
16
  type GetWhoamiReturnType,
17
+ getAuthenticators,
15
18
  getAuthProxyConfigId,
16
- getUserEmail,
17
19
  getWhoami,
18
20
  type LoginWithOTPParameters,
19
21
  type LoginWithOTPReturnType,
20
22
  loginWithOTP,
23
+ type OAuthAuthenticator,
21
24
  type OtpContact,
25
+ type PasskeyAuthenticator,
22
26
  type RegisterWithOTPParameters,
23
27
  type RegisterWithOTPReturnType,
24
28
  type RegisterWithPasskeyParameters,
@@ -32,10 +36,19 @@ export {
32
36
  type GetUserWalletParameters,
33
37
  type GetUserWalletReturnType,
34
38
  getUserWallet,
35
- type SignRawPayloadParameters,
36
- type SignRawPayloadReturnType,
39
+ type Sign7702AuthorizationParameters,
40
+ type Sign7702AuthorizationReturnType,
41
+ type SignMessageParameters,
42
+ type SignMessageReturnType,
37
43
  type SignTransactionParameters,
38
44
  type SignTransactionReturnType,
39
- signRawPayload,
45
+ type SignTypedDataV4Parameters,
46
+ type SignTypedDataV4ReturnType,
47
+ type SignUserOperationParameters,
48
+ type SignUserOperationReturnType,
49
+ sign7702Authorization,
50
+ signMessage,
40
51
  signTransaction,
52
+ signTypedDataV4,
53
+ signUserOperation,
41
54
  } from './wallet/index.js'
@@ -5,13 +5,31 @@ export {
5
5
  } from './getUserWallet.js'
6
6
 
7
7
  export {
8
- type SignRawPayloadParameters,
9
- type SignRawPayloadReturnType,
10
- signRawPayload,
11
- } from './signRawPayload.js'
8
+ type Sign7702AuthorizationParameters,
9
+ type Sign7702AuthorizationReturnType,
10
+ sign7702Authorization,
11
+ } from './sign7702Authorization.js'
12
+
13
+ export {
14
+ type SignMessageParameters,
15
+ type SignMessageReturnType,
16
+ signMessage,
17
+ } from './signMessage.js'
12
18
 
13
19
  export {
14
20
  type SignTransactionParameters,
15
21
  type SignTransactionReturnType,
16
22
  signTransaction,
17
23
  } from './signTransaction.js'
24
+
25
+ export {
26
+ type SignTypedDataV4Parameters,
27
+ type SignTypedDataV4ReturnType,
28
+ signTypedDataV4,
29
+ } from './signTypedDataV4.js'
30
+
31
+ export {
32
+ type SignUserOperationParameters,
33
+ type SignUserOperationReturnType,
34
+ signUserOperation,
35
+ } from './signUserOperation.js'
@@ -0,0 +1,48 @@
1
+ import type { Hex } from 'viem'
2
+ import type { Client } from '../../client/types.js'
3
+ import { buildTurnkeyPayload, sendSigningRequest } from './signingUtils.js'
4
+
5
+ export type Sign7702AuthorizationParameters = {
6
+ /** The organization ID */
7
+ organizationId: string
8
+ /** The project ID for the request */
9
+ projectId: string
10
+ /** The session token for authorization */
11
+ token: string
12
+ /** The address to sign with */
13
+ address: Hex
14
+ /** The hex-encoded EIP-7702 authorization to be signed (without 0x prefix) */
15
+ unsignedTransaction: string
16
+ /** The hashed authorization (hex without 0x prefix) */
17
+ hashedAuthorization: string
18
+ }
19
+
20
+ export type Sign7702AuthorizationReturnType = Hex
21
+
22
+ export async function sign7702Authorization(
23
+ client: Client,
24
+ params: Sign7702AuthorizationParameters,
25
+ ): Promise<Sign7702AuthorizationReturnType> {
26
+ const {
27
+ organizationId,
28
+ projectId,
29
+ token,
30
+ address,
31
+ unsignedTransaction,
32
+ hashedAuthorization,
33
+ } = params
34
+
35
+ const turnkeyPayload = buildTurnkeyPayload(
36
+ organizationId,
37
+ address,
38
+ hashedAuthorization,
39
+ )
40
+
41
+ return sendSigningRequest(client, {
42
+ projectId,
43
+ token,
44
+ path: 'sign/7702-authorization',
45
+ turnkeyPayload,
46
+ bodyFields: { unsignedTransaction },
47
+ })
48
+ }
@@ -0,0 +1,47 @@
1
+ import type { Hex } from 'viem'
2
+ import type { Client } from '../../client/types.js'
3
+ import {
4
+ buildTurnkeyPayload,
5
+ computeMessagePayloadHash,
6
+ sendSigningRequest,
7
+ } from './signingUtils.js'
8
+
9
+ export type SignMessageParameters = {
10
+ /** The organization ID */
11
+ organizationId: string
12
+ /** The project ID for the request */
13
+ projectId: string
14
+ /** The session token for authorization */
15
+ token: string
16
+ /** The address to sign with */
17
+ address: Hex
18
+ /** The message to sign */
19
+ message: string
20
+ /** The encoding of the message ('utf8' or 'hex') */
21
+ encoding: 'utf8' | 'hex'
22
+ }
23
+
24
+ export type SignMessageReturnType = Hex
25
+
26
+ export async function signMessage(
27
+ client: Client,
28
+ params: SignMessageParameters,
29
+ ): Promise<SignMessageReturnType> {
30
+ const { organizationId, projectId, token, address, message, encoding } =
31
+ params
32
+
33
+ const payloadHash = computeMessagePayloadHash(message, encoding)
34
+ const turnkeyPayload = buildTurnkeyPayload(
35
+ organizationId,
36
+ address,
37
+ payloadHash,
38
+ )
39
+
40
+ return sendSigningRequest(client, {
41
+ projectId,
42
+ token,
43
+ path: 'sign/message',
44
+ turnkeyPayload,
45
+ bodyFields: { message, encoding },
46
+ })
47
+ }
@@ -1,5 +1,10 @@
1
1
  import type { Hex } from 'viem'
2
2
  import type { Client } from '../../client/types.js'
3
+ import {
4
+ buildTurnkeyPayload,
5
+ computeDataPayloadHash,
6
+ sendSigningRequest,
7
+ } from './signingUtils.js'
3
8
 
4
9
  export type SignTransactionParameters = {
5
10
  /** The organization ID */
@@ -10,30 +15,12 @@ export type SignTransactionParameters = {
10
15
  token: string
11
16
  /** The address to sign with */
12
17
  address: Hex
13
- /** The unsigned transaction to sign */
18
+ /** The unsigned transaction to sign (hex without 0x prefix) */
14
19
  unsignedTransaction: string
15
20
  }
16
21
 
17
22
  export type SignTransactionReturnType = Hex
18
23
 
19
- /**
20
- * Signs a raw transaction with the user's wallet
21
- *
22
- * @param client - The ZeroDev Wallet client
23
- * @param params - The parameters for signing
24
- * @returns The signature
25
- *
26
- * @example
27
- * ```ts
28
- * const result = await signTransaction(client, {
29
- * organizationId: 'org_123',
30
- * projectId: 'proj_456',
31
- * address: '0x123...',
32
- * unsignedTransaction: 'abc123...',
33
- * });
34
- * console.log(result.signature); // '0x...'
35
- * ```
36
- */
37
24
  export async function signTransaction(
38
25
  client: Client,
39
26
  params: SignTransactionParameters,
@@ -41,24 +28,18 @@ export async function signTransaction(
41
28
  const { organizationId, projectId, token, address, unsignedTransaction } =
42
29
  params
43
30
 
44
- const { signature } = await client.request({
45
- path: `${projectId}/sign/transaction`,
46
- body: {
47
- type: 'ACTIVITY_TYPE_SIGN_TRANSACTION_V2',
48
- timestampMs: Date.now().toString(),
49
- organizationId,
50
- parameters: {
51
- signWith: address,
52
- type: 'TRANSACTION_TYPE_ETHEREUM',
53
- unsignedTransaction,
54
- },
55
- },
56
- headers: {
57
- Authorization: `Bearer ${token}`,
58
- },
59
- stamp: true,
60
- stampPostion: 'headers',
61
- })
31
+ const payloadHash = computeDataPayloadHash(unsignedTransaction, 'hex')
32
+ const turnkeyPayload = buildTurnkeyPayload(
33
+ organizationId,
34
+ address,
35
+ payloadHash,
36
+ )
62
37
 
63
- return `0x${signature}` as Hex
38
+ return sendSigningRequest(client, {
39
+ projectId,
40
+ token,
41
+ path: 'sign/transaction',
42
+ turnkeyPayload,
43
+ bodyFields: { unsignedTransaction },
44
+ })
64
45
  }
@@ -0,0 +1,52 @@
1
+ import type { Hex } from 'viem'
2
+ import type { Client } from '../../client/types.js'
3
+ import { buildTurnkeyPayload, sendSigningRequest } from './signingUtils.js'
4
+
5
+ export type SignTypedDataV4Parameters = {
6
+ /** The organization ID */
7
+ organizationId: string
8
+ /** The project ID for the request */
9
+ projectId: string
10
+ /** The session token for authorization */
11
+ token: string
12
+ /** The address to sign with */
13
+ address: Hex
14
+ /** The serialized EIP-712 typed data to sign */
15
+ unsignedTypedDataV4: string
16
+ /** The encoding of the typed data ('utf8' or 'hex') */
17
+ encoding: 'utf8' | 'hex'
18
+ /** Pre-computed EIP-712 hash (hex without 0x prefix), used as the Turnkey payload. */
19
+ typedDataHash: string
20
+ }
21
+
22
+ export type SignTypedDataV4ReturnType = Hex
23
+
24
+ export async function signTypedDataV4(
25
+ client: Client,
26
+ params: SignTypedDataV4Parameters,
27
+ ): Promise<SignTypedDataV4ReturnType> {
28
+ const {
29
+ organizationId,
30
+ projectId,
31
+ token,
32
+ address,
33
+ unsignedTypedDataV4,
34
+ encoding,
35
+ typedDataHash,
36
+ } = params
37
+
38
+ const payloadHash = typedDataHash
39
+ const turnkeyPayload = buildTurnkeyPayload(
40
+ organizationId,
41
+ address,
42
+ payloadHash,
43
+ )
44
+
45
+ return sendSigningRequest(client, {
46
+ projectId,
47
+ token,
48
+ path: 'sign/typed-data-v4',
49
+ turnkeyPayload,
50
+ bodyFields: { unsignedTypedDataV4, encoding },
51
+ })
52
+ }
@@ -0,0 +1,56 @@
1
+ import type { Hex } from 'viem'
2
+ import type { Client } from '../../client/types.js'
3
+ import {
4
+ buildTurnkeyPayload,
5
+ computeDataPayloadHash,
6
+ sendSigningRequest,
7
+ } from './signingUtils.js'
8
+
9
+ export type SignUserOperationParameters = {
10
+ /** The organization ID */
11
+ organizationId: string
12
+ /** The project ID for the request */
13
+ projectId: string
14
+ /** The session token for authorization */
15
+ token: string
16
+ /** The address to sign with */
17
+ address: Hex
18
+ /** The unsigned user operation to sign */
19
+ unsignedUserOperation: string
20
+ /** The chain ID for the user operation */
21
+ chainId: number
22
+ /** The encoding of the user operation ('utf8' or 'hex') */
23
+ encoding: 'utf8' | 'hex'
24
+ }
25
+
26
+ export type SignUserOperationReturnType = Hex
27
+
28
+ export async function signUserOperation(
29
+ client: Client,
30
+ params: SignUserOperationParameters,
31
+ ): Promise<SignUserOperationReturnType> {
32
+ const {
33
+ organizationId,
34
+ projectId,
35
+ token,
36
+ address,
37
+ unsignedUserOperation,
38
+ chainId,
39
+ encoding,
40
+ } = params
41
+
42
+ const payloadHash = computeDataPayloadHash(unsignedUserOperation, encoding)
43
+ const turnkeyPayload = buildTurnkeyPayload(
44
+ organizationId,
45
+ address,
46
+ payloadHash,
47
+ )
48
+
49
+ return sendSigningRequest(client, {
50
+ projectId,
51
+ token,
52
+ path: 'sign/user-operation',
53
+ turnkeyPayload,
54
+ bodyFields: { unsignedUserOperation, chainId, encoding },
55
+ })
56
+ }
@@ -0,0 +1,110 @@
1
+ import { canonicalizeEx } from 'json-canonicalize'
2
+ import type { Hex } from 'viem'
3
+ import { hashMessage, keccak256, toHex } from 'viem'
4
+ import type { Client } from '../../client/types.js'
5
+
6
+ export type TurnkeyPayload = {
7
+ type: string
8
+ timestampMs: string
9
+ organizationId: string
10
+ parameters: {
11
+ signWith: string
12
+ payload: string
13
+ encoding: string
14
+ hashFunction: string
15
+ }
16
+ }
17
+
18
+ export function buildTurnkeyPayload(
19
+ organizationId: string,
20
+ address: Hex,
21
+ payloadHash: string,
22
+ ): TurnkeyPayload {
23
+ return {
24
+ type: 'ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2',
25
+ timestampMs: Date.now().toString(),
26
+ organizationId,
27
+ parameters: {
28
+ signWith: address,
29
+ payload: payloadHash,
30
+ encoding: 'PAYLOAD_ENCODING_HEXADECIMAL',
31
+ hashFunction: 'HASH_FUNCTION_NO_OP',
32
+ },
33
+ }
34
+ }
35
+
36
+ export async function sendSigningRequest(
37
+ client: Client,
38
+ params: {
39
+ projectId: string
40
+ token: string
41
+ path: string
42
+ turnkeyPayload: TurnkeyPayload
43
+ bodyFields: Record<string, unknown>
44
+ },
45
+ ): Promise<Hex> {
46
+ const { projectId, token, path, turnkeyPayload, bodyFields } = params
47
+
48
+ // Inner stamp over the Turnkey payload (for Turnkey verification)
49
+ const innerBodyString = canonicalizeEx(turnkeyPayload)
50
+ const innerStamp = await client.indexedDbStamper.stamp(innerBodyString)
51
+
52
+ // Build full body with inner stamp embedded
53
+ const fullBody = {
54
+ ...bodyFields,
55
+ turnkeyPayload,
56
+ stampHeader: {
57
+ stampHeaderName: innerStamp.stampHeaderName,
58
+ stampHeaderValue: innerStamp.stampHeaderValue,
59
+ },
60
+ }
61
+
62
+ // Outer stamp over full body (for KMS middleware)
63
+ const fullBodyString = canonicalizeEx(fullBody)
64
+ const outerStamp = await client.indexedDbStamper.stamp(fullBodyString)
65
+
66
+ const { signature } = await client.request({
67
+ path: `${projectId}/${path}`,
68
+ method: 'POST',
69
+ body: fullBody,
70
+ headers: {
71
+ [outerStamp.stampHeaderName]: outerStamp.stampHeaderValue,
72
+ Authorization: `Bearer ${token}`,
73
+ },
74
+ })
75
+
76
+ return (signature.startsWith('0x') ? signature : `0x${signature}`) as Hex
77
+ }
78
+
79
+ /**
80
+ * Compute payload hash for message signing (EIP-191).
81
+ * Uses viem's hashMessage directly to guarantee correct EIP-191 hashing.
82
+ */
83
+ export function computeMessagePayloadHash(
84
+ message: string,
85
+ encoding: 'utf8' | 'hex',
86
+ ): string {
87
+ if (encoding === 'utf8') {
88
+ return hashMessage(message).slice(2)
89
+ }
90
+ const hex = message.replace(/^0x/, '')
91
+ return hashMessage({ raw: `0x${hex}` as Hex }).slice(2)
92
+ }
93
+
94
+ /**
95
+ * Compute payload hash for data signing (transaction, user operation).
96
+ * Hashes the raw decoded bytes: keccak256(hexDecode(hexData))
97
+ */
98
+ export function computeDataPayloadHash(
99
+ data: string,
100
+ encoding: 'utf8' | 'hex',
101
+ ): string {
102
+ let hexData: string
103
+ if (encoding === 'utf8') {
104
+ hexData = toHex(data).slice(2)
105
+ } else {
106
+ hexData = data.replace(/^0x/, '')
107
+ }
108
+
109
+ return keccak256(`0x${hexData}` as Hex).slice(2)
110
+ }