@gelatonetwork/smartwallet-react-privy 0.0.2-alpha.0

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.
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@gelatonetwork/smartwallet-react-privy",
3
+ "version": "0.0.2-alpha.0",
4
+ "author": "Gelato",
5
+ "type": "module",
6
+ "description": "Context provider supporting Privy WaaS",
7
+ "main": "./_dist/index.js",
8
+ "types": "./_dist/index.d.ts",
9
+ "typings": "./_dist/index.d.ts",
10
+ "peerDependencies": {
11
+ "typescript": "^5.3",
12
+ "viem": "^2.28",
13
+ "wagmi": "^2.15"
14
+ },
15
+ "peerDependenciesMeta": {
16
+ "typescript": {
17
+ "optional": true
18
+ },
19
+ "wagmi": {
20
+ "optional": true
21
+ }
22
+ },
23
+ "dependencies": {
24
+ "@privy-io/react-auth": "^2.10.0",
25
+ "@privy-io/wagmi": "^1.0.3",
26
+ "@tanstack/react-query": "^5.74",
27
+ "caip": "^1",
28
+ "react": "^18.2",
29
+ "react-dom": "^18.2",
30
+ "viem": "^2.28",
31
+ "wagmi": "^2.15",
32
+ "zod": "^3.24.3",
33
+ "@gelatonetwork/smartwallet-react-types": "0.0.2-alpha.0"
34
+ },
35
+ "devDependencies": {
36
+ "@types/react": "^18",
37
+ "@types/react-dom": "^18"
38
+ },
39
+ "scripts": {
40
+ "build": "tsc --project ./tsconfig.build.json"
41
+ }
42
+ }
@@ -0,0 +1,21 @@
1
+ import { useLogin, usePrivy } from "@privy-io/react-auth";
2
+ import type { FC, ReactNode } from "react";
3
+
4
+ interface GelatoSmartWalletPrivyConnectButtonProps {
5
+ children: ReactNode;
6
+ }
7
+
8
+ export const GelatoSmartWalletPrivyConnectButton: FC<GelatoSmartWalletPrivyConnectButtonProps> = ({
9
+ children
10
+ }) => {
11
+ const { ready, authenticated } = usePrivy();
12
+ const { login } = useLogin();
13
+
14
+ const disableLogin = !ready || (ready && authenticated);
15
+
16
+ return (
17
+ <button type="button" disabled={disableLogin} onClick={login}>
18
+ {children}
19
+ </button>
20
+ );
21
+ };
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ export {
2
+ GelatoSmartWalletPrivyContextProvider,
3
+ useGelatoSmartWalletPrivyContext
4
+ } from "./provider.js";
5
+ export { GelatoSmartWalletPrivyConnectButton } from "./components/connect.js";
@@ -0,0 +1,167 @@
1
+ import { PrivyProvider, usePrivy, useSignAuthorization, useWallets } from "@privy-io/react-auth";
2
+ import { WagmiProvider, createConfig } from "@privy-io/wagmi";
3
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4
+ import { ChainId } from "caip";
5
+ import { createContext, useContext, useEffect, useState } from "react";
6
+ import {
7
+ type Account,
8
+ type Chain,
9
+ type Hex,
10
+ type Transport,
11
+ type WalletClient,
12
+ createWalletClient,
13
+ custom
14
+ } from "viem";
15
+ import * as chains from "viem/chains";
16
+ import { extractChain } from "viem/utils";
17
+
18
+ import type { wallet } from "@gelatonetwork/smartwallet-react-types";
19
+ import type { FC, ReactNode } from "react";
20
+ import type { Config as WagmiConfig } from "wagmi";
21
+
22
+ type GelatoSmartWalletPrivyContextType = wallet.ProviderContext;
23
+
24
+ const GelatoSmartWalletPrivyProviderContext = createContext<
25
+ GelatoSmartWalletPrivyContextType | undefined
26
+ >(undefined);
27
+
28
+ export const useGelatoSmartWalletPrivyContext = () => {
29
+ const context = useContext(GelatoSmartWalletPrivyProviderContext);
30
+ if (!context) {
31
+ throw new Error(
32
+ "useGelatoSmartWalletPrivyProvider must be used within a GelatoSmartWalletPrivyProvider"
33
+ );
34
+ }
35
+ return context;
36
+ };
37
+
38
+ type GelatoSmartWalletPrivyContextProps = wallet.ProviderProps;
39
+
40
+ const GelatoSmartWalletPrivyInternal: FC<{
41
+ children: ReactNode;
42
+ wagmi: { config: WagmiConfig | undefined };
43
+ }> = ({ children, wagmi }) => {
44
+ const { ready, authenticated, logout } = usePrivy();
45
+ const { wallets, ready: walletsReady } = useWallets();
46
+ const { signAuthorization } = useSignAuthorization();
47
+
48
+ const [walletClient, setWalletClient] = useState<WalletClient | null>(null);
49
+
50
+ const logoutWrapper = async () => {
51
+ if (!walletClient) {
52
+ return;
53
+ }
54
+
55
+ setWalletClient(null);
56
+ await logout();
57
+ };
58
+
59
+ const switchNetwork = async (chain: Chain) => {
60
+ if (!walletClient) {
61
+ return;
62
+ }
63
+
64
+ const primaryWallet = wallets[0];
65
+
66
+ await primaryWallet.switchChain(chain.id);
67
+ walletClient.switchChain({ id: chain.id });
68
+ };
69
+
70
+ useEffect(() => {
71
+ if (!ready || !walletsReady) {
72
+ return;
73
+ }
74
+
75
+ if (!authenticated || !wallets || wallets.length === 0) {
76
+ setWalletClient(null);
77
+ return;
78
+ }
79
+
80
+ const fetchWalletClient = async () => {
81
+ const primaryWallet = wallets[0];
82
+
83
+ try {
84
+ // Privy wallet provides chainId in CAIP2 format
85
+ const { reference: chainId } = ChainId.parse(primaryWallet.chainId);
86
+ // biome-ignore lint/suspicious/noExplicitAny: <explanation>
87
+ const chain = extractChain({ chains: Object.values(chains), id: Number(chainId) as any });
88
+
89
+ if (!chain) {
90
+ return;
91
+ }
92
+
93
+ const provider = await primaryWallet.getEthereumProvider();
94
+ const walletClient = createWalletClient({
95
+ account: primaryWallet.address as Hex,
96
+ chain,
97
+ transport: custom(provider)
98
+ });
99
+
100
+ walletClient.signAuthorization = async (parameters) => {
101
+ const { chainId, nonce } = parameters;
102
+ const contractAddress = parameters.contractAddress ?? parameters.address;
103
+
104
+ if (!contractAddress) {
105
+ throw new Error("Contract address is required");
106
+ }
107
+
108
+ const signedAuthorization = await signAuthorization({
109
+ contractAddress,
110
+ chainId,
111
+ nonce
112
+ });
113
+
114
+ return signedAuthorization;
115
+ };
116
+
117
+ setWalletClient(walletClient);
118
+ } catch (error) {
119
+ console.error("Failed to get wallet client:", error);
120
+ }
121
+ };
122
+
123
+ fetchWalletClient();
124
+ }, [ready, wallets, walletsReady, authenticated, signAuthorization]);
125
+
126
+ return (
127
+ <GelatoSmartWalletPrivyProviderContext.Provider
128
+ value={{
129
+ wagmi: {
130
+ config: wagmi.config,
131
+ client: walletClient as WalletClient<Transport, Chain, Account>
132
+ },
133
+ logout: logoutWrapper,
134
+ switchNetwork
135
+ }}
136
+ >
137
+ {children}
138
+ </GelatoSmartWalletPrivyProviderContext.Provider>
139
+ );
140
+ };
141
+
142
+ export const GelatoSmartWalletPrivyContextProvider: FC<GelatoSmartWalletPrivyContextProps> = ({
143
+ children,
144
+ settings
145
+ }) => {
146
+ const queryClient = new QueryClient();
147
+ const wagmiConfig = settings.wagmi ? createConfig(settings.wagmi.config) : undefined;
148
+
149
+ return (
150
+ <PrivyProvider
151
+ appId={settings.waas.appId}
152
+ config={{
153
+ defaultChain: settings.defaultChain ?? chains.sepolia
154
+ }}
155
+ >
156
+ <GelatoSmartWalletPrivyInternal wagmi={{ config: wagmiConfig }}>
157
+ {wagmiConfig ? (
158
+ <QueryClientProvider client={queryClient}>
159
+ <WagmiProvider config={wagmiConfig}>{children}</WagmiProvider>
160
+ </QueryClientProvider>
161
+ ) : (
162
+ children
163
+ )}
164
+ </GelatoSmartWalletPrivyInternal>
165
+ </PrivyProvider>
166
+ );
167
+ };
@@ -0,0 +1,22 @@
1
+ {
2
+ "extends": "../../../tsconfig.build.json",
3
+ "compilerOptions": {
4
+ "jsx": "react-jsx",
5
+ "declaration": true,
6
+ "declarationMap": true,
7
+ "sourceMap": true,
8
+ "composite": true,
9
+ "noEmit": false,
10
+ "outDir": "./_dist",
11
+ "rootDir": "src",
12
+ "tsBuildInfoFile": "./_dist/tsconfig.tsbuildinfo"
13
+ },
14
+ "exclude": [
15
+ "node_modules",
16
+ "_dist",
17
+ "**/*.test.ts",
18
+ "**/*.spec.ts",
19
+ "**/*.test.tsx",
20
+ "**/*.spec.tsx"
21
+ ]
22
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "../../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "jsx": "react-jsx"
5
+ }
6
+ }