@account-kit/privy-integration 4.73.1-alpha.10 → 4.73.1-alpha.11

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.
@@ -1,5 +1,7 @@
1
1
  import { useCallback } from "react";
2
2
  import { usePrivy, useEmbeddedEthereumWallet, } from "@privy-io/expo";
3
+ import { hashAuthorization } from "viem/utils";
4
+ import { parseSignature } from "viem";
3
5
  /**
4
6
  * React Native (Expo) adapter for @privy-io/expo
5
7
  * Implements platform-specific hooks for React Native applications
@@ -41,47 +43,28 @@ export const reactNativeAdapter = {
41
43
  throw new Error("Implementation address is required for EIP-7702 authorization");
42
44
  }
43
45
  console.log("[RN Adapter] Signing 7702 auth for address:", implementationAddress);
44
- // EIP-7702 Authorization structure
46
+ // Create the authorization structure (matches Privy's implementation)
45
47
  const authorization = {
46
- domain: {
47
- name: "EIP-7702",
48
- version: "1",
49
- chainId: unsignedAuth.chainId,
50
- },
51
- types: {
52
- Authorization: [
53
- { name: "chainId", type: "uint256" },
54
- { name: "address", type: "address" },
55
- { name: "nonce", type: "uint256" },
56
- ],
57
- },
58
- primaryType: "Authorization",
59
- message: {
60
- chainId: unsignedAuth.chainId,
61
- address: implementationAddress,
62
- nonce: unsignedAuth.nonce,
63
- },
48
+ chainId: unsignedAuth.chainId,
49
+ address: implementationAddress,
50
+ nonce: unsignedAuth.nonce,
64
51
  };
52
+ // Hash the authorization using viem (same as Privy does)
53
+ const authorizationHash = hashAuthorization(authorization);
54
+ console.log("[RN Adapter] Authorization hash:", authorizationHash);
55
+ // Sign the hash directly with secp256k1_sign (same as Privy)
65
56
  const signature = (await provider.request({
66
- method: "eth_signTypedData_v4",
67
- params: [wallet.address, JSON.stringify(authorization)],
57
+ method: "secp256k1_sign",
58
+ params: [authorizationHash],
68
59
  }));
69
60
  console.log("[RN Adapter] Received signature:", signature);
70
- // Parse the signature into r, s, v components
71
- // Signature format: 0x[r(64)][s(64)][v(2)]
72
- const r = `0x${signature.slice(2, 66)}`;
73
- const s = `0x${signature.slice(66, 130)}`;
74
- const v = parseInt(signature.slice(130, 132), 16);
75
- // Convert v to yParity (0 or 1)
76
- // v can be 27/28 (legacy) or 0/1 (EIP-155)
77
- const yParity = v >= 27 ? v - 27 : v;
61
+ // Parse the signature using viem (same as Privy)
62
+ const parsedSignature = parseSignature(signature);
78
63
  const result = {
79
64
  chainId: unsignedAuth.chainId,
80
65
  address: implementationAddress,
81
66
  nonce: unsignedAuth.nonce,
82
- r,
83
- s,
84
- yParity,
67
+ ...parsedSignature,
85
68
  };
86
69
  console.log("[RN Adapter] Returning authorization:", result);
87
70
  return result;
@@ -1 +1 @@
1
- {"version":3,"file":"react-native.js","sourceRoot":"","sources":["../../../src/adapters/react-native.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback } from \"react\";\nimport {\n usePrivy,\n useEmbeddedEthereumWallet,\n type PrivyEmbeddedWalletProvider,\n} from \"@privy-io/expo\";\nimport type { Authorization } from \"viem\";\nimport type { AuthorizationRequest } from \"@aa-sdk/core\";\nimport type { PrivyAdapter, EmbeddedWallet, PrivyAuthState } from \"./types.js\";\n\n/**\n * Wallet type from @privy-io/expo\n * Based on the example app structure\n */\ninterface ExpoEmbeddedWallet {\n address: string;\n chainId?: string;\n getProvider?: () => Promise<PrivyEmbeddedWalletProvider>;\n}\n\n/**\n * React Native (Expo) adapter for @privy-io/expo\n * Implements platform-specific hooks for React Native applications\n */\nexport const reactNativeAdapter: PrivyAdapter = {\n useEmbeddedWallet() {\n const { wallets } = useEmbeddedEthereumWallet();\n\n const getEmbeddedWallet = useCallback((): EmbeddedWallet => {\n const wallet = wallets?.[0];\n if (!wallet) {\n throw new Error(\n \"Privy embedded wallet not found. Please ensure the user is authenticated and has created a wallet.\",\n );\n }\n\n return adaptExpoWallet(wallet);\n }, [wallets]);\n\n return getEmbeddedWallet;\n },\n\n usePrivyAuth(): PrivyAuthState {\n const { user } = usePrivy();\n return { authenticated: !!user, user };\n },\n\n useAuthorizationSigner() {\n const { wallets } = useEmbeddedEthereumWallet();\n\n // Don't memoize the callback - create it fresh each time to ensure we have the latest wallets\n const signAuthorization = async (\n unsignedAuth: AuthorizationRequest<number>,\n ): Promise<Authorization<number, true>> => {\n console.log(\"[RN Adapter] signAuthorization called with:\", unsignedAuth);\n console.log(\"[RN Adapter] Current wallets:\", wallets);\n\n const wallet = wallets?.[0];\n if (!wallet) {\n throw new Error(\n \"Privy embedded wallet not found. Please ensure the user is authenticated and has created a wallet.\",\n );\n }\n\n console.log(\"[RN Adapter] Using wallet:\", wallet.address);\n\n const provider = await wallet.getProvider?.();\n if (!provider) {\n throw new Error(\n \"Provider not available on this wallet. Ensure you're using the embedded Ethereum wallet.\",\n );\n }\n\n // Extract the implementation address (handle both 'address' and 'contractAddress' fields)\n const implementationAddress =\n unsignedAuth.address ?? unsignedAuth.contractAddress;\n\n if (!implementationAddress) {\n throw new Error(\n \"Implementation address is required for EIP-7702 authorization\",\n );\n }\n\n console.log(\n \"[RN Adapter] Signing 7702 auth for address:\",\n implementationAddress,\n );\n\n // EIP-7702 Authorization structure\n const authorization = {\n domain: {\n name: \"EIP-7702\",\n version: \"1\",\n chainId: unsignedAuth.chainId,\n },\n types: {\n Authorization: [\n { name: \"chainId\", type: \"uint256\" },\n { name: \"address\", type: \"address\" },\n { name: \"nonce\", type: \"uint256\" },\n ],\n },\n primaryType: \"Authorization\" as const,\n message: {\n chainId: unsignedAuth.chainId,\n address: implementationAddress,\n nonce: unsignedAuth.nonce,\n },\n };\n\n const signature = (await provider.request({\n method: \"eth_signTypedData_v4\",\n params: [wallet.address, JSON.stringify(authorization)],\n })) as `0x${string}`;\n\n console.log(\"[RN Adapter] Received signature:\", signature);\n\n // Parse the signature into r, s, v components\n // Signature format: 0x[r(64)][s(64)][v(2)]\n const r = `0x${signature.slice(2, 66)}` as `0x${string}`;\n const s = `0x${signature.slice(66, 130)}` as `0x${string}`;\n const v = parseInt(signature.slice(130, 132), 16);\n\n // Convert v to yParity (0 or 1)\n // v can be 27/28 (legacy) or 0/1 (EIP-155)\n const yParity = v >= 27 ? v - 27 : v;\n\n const result = {\n chainId: unsignedAuth.chainId,\n address: implementationAddress,\n nonce: unsignedAuth.nonce,\n r,\n s,\n yParity,\n };\n\n console.log(\"[RN Adapter] Returning authorization:\", result);\n return result;\n };\n\n return signAuthorization;\n },\n};\n\n/**\n * Adapts an Expo wallet to the common EmbeddedWallet interface\n *\n * @param {ExpoEmbeddedWallet} wallet - The Expo embedded wallet to adapt\n * @returns {EmbeddedWallet} The adapted wallet following the common interface\n */\nfunction adaptExpoWallet(wallet: ExpoEmbeddedWallet): EmbeddedWallet {\n // Use closure to maintain up-to-date chain ID across chain switches\n let cachedChainId = wallet.chainId || \"1\";\n\n return {\n address: wallet.address as `0x${string}`,\n get chainId() {\n return cachedChainId;\n },\n getEthereumProvider: async () => {\n if (!wallet.getProvider) {\n throw new Error(\n \"getProvider is not available on this wallet. Ensure you're using the embedded Ethereum wallet.\",\n );\n }\n const provider = await wallet.getProvider();\n\n // Always fetch current chain ID when provider is accessed\n // This ensures we have the latest chain after wallet_switchEthereumChain calls\n try {\n const currentChainId = (await provider.request({\n method: \"eth_chainId\",\n params: [],\n })) as string;\n\n // Convert hex to decimal string format (e.g., \"0x1\" -> \"1\")\n cachedChainId = parseInt(currentChainId, 16).toString();\n console.log(\"[RN Adapter] Updated chain ID to:\", cachedChainId);\n } catch (err) {\n console.warn(\n \"[Privy Integration] Failed to fetch current chain ID:\",\n err,\n );\n // Fall back to cached value if fetch fails\n }\n\n return provider;\n },\n };\n}\n"]}
1
+ {"version":3,"file":"react-native.js","sourceRoot":"","sources":["../../../src/adapters/react-native.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback } from \"react\";\nimport {\n usePrivy,\n useEmbeddedEthereumWallet,\n type PrivyEmbeddedWalletProvider,\n} from \"@privy-io/expo\";\nimport type { Authorization } from \"viem\";\nimport { hashAuthorization } from \"viem/utils\";\nimport { parseSignature } from \"viem\";\nimport type { AuthorizationRequest } from \"@aa-sdk/core\";\nimport type { PrivyAdapter, EmbeddedWallet, PrivyAuthState } from \"./types.js\";\n\n/**\n * Wallet type from @privy-io/expo\n * Based on the example app structure\n */\ninterface ExpoEmbeddedWallet {\n address: string;\n chainId?: string;\n getProvider?: () => Promise<PrivyEmbeddedWalletProvider>;\n}\n\n/**\n * React Native (Expo) adapter for @privy-io/expo\n * Implements platform-specific hooks for React Native applications\n */\nexport const reactNativeAdapter: PrivyAdapter = {\n useEmbeddedWallet() {\n const { wallets } = useEmbeddedEthereumWallet();\n\n const getEmbeddedWallet = useCallback((): EmbeddedWallet => {\n const wallet = wallets?.[0];\n if (!wallet) {\n throw new Error(\n \"Privy embedded wallet not found. Please ensure the user is authenticated and has created a wallet.\",\n );\n }\n\n return adaptExpoWallet(wallet);\n }, [wallets]);\n\n return getEmbeddedWallet;\n },\n\n usePrivyAuth(): PrivyAuthState {\n const { user } = usePrivy();\n return { authenticated: !!user, user };\n },\n\n useAuthorizationSigner() {\n const { wallets } = useEmbeddedEthereumWallet();\n\n // Don't memoize the callback - create it fresh each time to ensure we have the latest wallets\n const signAuthorization = async (\n unsignedAuth: AuthorizationRequest<number>,\n ): Promise<Authorization<number, true>> => {\n console.log(\"[RN Adapter] signAuthorization called with:\", unsignedAuth);\n console.log(\"[RN Adapter] Current wallets:\", wallets);\n\n const wallet = wallets?.[0];\n if (!wallet) {\n throw new Error(\n \"Privy embedded wallet not found. Please ensure the user is authenticated and has created a wallet.\",\n );\n }\n\n console.log(\"[RN Adapter] Using wallet:\", wallet.address);\n\n const provider = await wallet.getProvider?.();\n if (!provider) {\n throw new Error(\n \"Provider not available on this wallet. Ensure you're using the embedded Ethereum wallet.\",\n );\n }\n\n // Extract the implementation address (handle both 'address' and 'contractAddress' fields)\n const implementationAddress =\n unsignedAuth.address ?? unsignedAuth.contractAddress;\n\n if (!implementationAddress) {\n throw new Error(\n \"Implementation address is required for EIP-7702 authorization\",\n );\n }\n\n console.log(\n \"[RN Adapter] Signing 7702 auth for address:\",\n implementationAddress,\n );\n\n // Create the authorization structure (matches Privy's implementation)\n const authorization = {\n chainId: unsignedAuth.chainId,\n address: implementationAddress,\n nonce: unsignedAuth.nonce,\n };\n\n // Hash the authorization using viem (same as Privy does)\n const authorizationHash = hashAuthorization(authorization);\n console.log(\"[RN Adapter] Authorization hash:\", authorizationHash);\n\n // Sign the hash directly with secp256k1_sign (same as Privy)\n const signature = (await provider.request({\n method: \"secp256k1_sign\",\n params: [authorizationHash],\n })) as `0x${string}`;\n\n console.log(\"[RN Adapter] Received signature:\", signature);\n\n // Parse the signature using viem (same as Privy)\n const parsedSignature = parseSignature(signature);\n\n const result = {\n chainId: unsignedAuth.chainId,\n address: implementationAddress,\n nonce: unsignedAuth.nonce,\n ...parsedSignature,\n };\n\n console.log(\"[RN Adapter] Returning authorization:\", result);\n return result;\n };\n\n return signAuthorization;\n },\n};\n\n/**\n * Adapts an Expo wallet to the common EmbeddedWallet interface\n *\n * @param {ExpoEmbeddedWallet} wallet - The Expo embedded wallet to adapt\n * @returns {EmbeddedWallet} The adapted wallet following the common interface\n */\nfunction adaptExpoWallet(wallet: ExpoEmbeddedWallet): EmbeddedWallet {\n // Use closure to maintain up-to-date chain ID across chain switches\n let cachedChainId = wallet.chainId || \"1\";\n\n return {\n address: wallet.address as `0x${string}`,\n get chainId() {\n return cachedChainId;\n },\n getEthereumProvider: async () => {\n if (!wallet.getProvider) {\n throw new Error(\n \"getProvider is not available on this wallet. Ensure you're using the embedded Ethereum wallet.\",\n );\n }\n const provider = await wallet.getProvider();\n\n // Always fetch current chain ID when provider is accessed\n // This ensures we have the latest chain after wallet_switchEthereumChain calls\n try {\n const currentChainId = (await provider.request({\n method: \"eth_chainId\",\n params: [],\n })) as string;\n\n // Convert hex to decimal string format (e.g., \"0x1\" -> \"1\")\n cachedChainId = parseInt(currentChainId, 16).toString();\n console.log(\"[RN Adapter] Updated chain ID to:\", cachedChainId);\n } catch (err) {\n console.warn(\n \"[Privy Integration] Failed to fetch current chain ID:\",\n err,\n );\n // Fall back to cached value if fetch fails\n }\n\n return provider;\n },\n };\n}\n"]}
@@ -1 +1 @@
1
- export declare const VERSION = "4.73.1-alpha.10";
1
+ export declare const VERSION = "4.73.1-alpha.11";
@@ -1,4 +1,4 @@
1
1
  // This file is autogenerated by inject-version.ts. Any changes will be
2
2
  // overwritten on commit!
3
- export const VERSION = "4.73.1-alpha.10";
3
+ export const VERSION = "4.73.1-alpha.11";
4
4
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,yBAAyB;AACzB,MAAM,CAAC,MAAM,OAAO,GAAG,iBAAiB,CAAC","sourcesContent":["// This file is autogenerated by inject-version.ts. Any changes will be\n// overwritten on commit!\nexport const VERSION = \"4.73.1-alpha.10\";\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,yBAAyB;AACzB,MAAM,CAAC,MAAM,OAAO,GAAG,iBAAiB,CAAC","sourcesContent":["// This file is autogenerated by inject-version.ts. Any changes will be\n// overwritten on commit!\nexport const VERSION = \"4.73.1-alpha.11\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"react-native.d.ts","sourceRoot":"","sources":["../../../src/adapters/react-native.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAkC,MAAM,YAAY,CAAC;AAY/E;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,YAsHhC,CAAC"}
1
+ {"version":3,"file":"react-native.d.ts","sourceRoot":"","sources":["../../../src/adapters/react-native.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,YAAY,EAAkC,MAAM,YAAY,CAAC;AAY/E;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,YAmGhC,CAAC"}
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "4.73.1-alpha.10";
1
+ export declare const VERSION = "4.73.1-alpha.11";
2
2
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@account-kit/privy-integration",
3
- "version": "4.73.1-alpha.10",
3
+ "version": "4.73.1-alpha.11",
4
4
  "description": "Use Alchemy gas sponsorship, swaps and more with Privy",
5
5
  "author": "Alchemy",
6
6
  "license": "MIT",
@@ -64,8 +64,8 @@
64
64
  "typescript-template": "*"
65
65
  },
66
66
  "dependencies": {
67
- "@account-kit/infra": "^4.73.1-alpha.10",
68
- "@account-kit/wallet-client": "^4.73.1-alpha.10"
67
+ "@account-kit/infra": "^4.73.1-alpha.11",
68
+ "@account-kit/wallet-client": "^4.73.1-alpha.11"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "@privy-io/expo": "^0.58.0",
@@ -95,5 +95,5 @@
95
95
  "url": "https://github.com/alchemyplatform/aa-sdk/issues"
96
96
  },
97
97
  "homepage": "https://github.com/alchemyplatform/aa-sdk#readme",
98
- "gitHead": "d79ab9ab7104919deba2b60db8c6ba0c1656a45e"
98
+ "gitHead": "29d8866afdb4f5019403ef0897bd13f88dcfa2b4"
99
99
  }
@@ -5,6 +5,8 @@ import {
5
5
  type PrivyEmbeddedWalletProvider,
6
6
  } from "@privy-io/expo";
7
7
  import type { Authorization } from "viem";
8
+ import { hashAuthorization } from "viem/utils";
9
+ import { parseSignature } from "viem";
8
10
  import type { AuthorizationRequest } from "@aa-sdk/core";
9
11
  import type { PrivyAdapter, EmbeddedWallet, PrivyAuthState } from "./types.js";
10
12
 
@@ -86,52 +88,33 @@ export const reactNativeAdapter: PrivyAdapter = {
86
88
  implementationAddress,
87
89
  );
88
90
 
89
- // EIP-7702 Authorization structure
91
+ // Create the authorization structure (matches Privy's implementation)
90
92
  const authorization = {
91
- domain: {
92
- name: "EIP-7702",
93
- version: "1",
94
- chainId: unsignedAuth.chainId,
95
- },
96
- types: {
97
- Authorization: [
98
- { name: "chainId", type: "uint256" },
99
- { name: "address", type: "address" },
100
- { name: "nonce", type: "uint256" },
101
- ],
102
- },
103
- primaryType: "Authorization" as const,
104
- message: {
105
- chainId: unsignedAuth.chainId,
106
- address: implementationAddress,
107
- nonce: unsignedAuth.nonce,
108
- },
93
+ chainId: unsignedAuth.chainId,
94
+ address: implementationAddress,
95
+ nonce: unsignedAuth.nonce,
109
96
  };
110
97
 
98
+ // Hash the authorization using viem (same as Privy does)
99
+ const authorizationHash = hashAuthorization(authorization);
100
+ console.log("[RN Adapter] Authorization hash:", authorizationHash);
101
+
102
+ // Sign the hash directly with secp256k1_sign (same as Privy)
111
103
  const signature = (await provider.request({
112
- method: "eth_signTypedData_v4",
113
- params: [wallet.address, JSON.stringify(authorization)],
104
+ method: "secp256k1_sign",
105
+ params: [authorizationHash],
114
106
  })) as `0x${string}`;
115
107
 
116
108
  console.log("[RN Adapter] Received signature:", signature);
117
109
 
118
- // Parse the signature into r, s, v components
119
- // Signature format: 0x[r(64)][s(64)][v(2)]
120
- const r = `0x${signature.slice(2, 66)}` as `0x${string}`;
121
- const s = `0x${signature.slice(66, 130)}` as `0x${string}`;
122
- const v = parseInt(signature.slice(130, 132), 16);
123
-
124
- // Convert v to yParity (0 or 1)
125
- // v can be 27/28 (legacy) or 0/1 (EIP-155)
126
- const yParity = v >= 27 ? v - 27 : v;
110
+ // Parse the signature using viem (same as Privy)
111
+ const parsedSignature = parseSignature(signature);
127
112
 
128
113
  const result = {
129
114
  chainId: unsignedAuth.chainId,
130
115
  address: implementationAddress,
131
116
  nonce: unsignedAuth.nonce,
132
- r,
133
- s,
134
- yParity,
117
+ ...parsedSignature,
135
118
  };
136
119
 
137
120
  console.log("[RN Adapter] Returning authorization:", result);
package/src/version.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  // This file is autogenerated by inject-version.ts. Any changes will be
2
2
  // overwritten on commit!
3
- export const VERSION = "4.73.1-alpha.10";
3
+ export const VERSION = "4.73.1-alpha.11";