@phantom/react-sdk 0.0.2 → 0.0.4

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/README.md CHANGED
@@ -11,10 +11,9 @@ npm install @phantom/react-sdk @phantom/browser-sdk
11
11
  ## Quick Start
12
12
 
13
13
  ```tsx
14
- import React from 'react';
15
- import { PhantomProvider } from '@phantom/react-sdk';
16
- import { createSolanaPlugin } from '@phantom/browser-sdk/solana';
17
- import { useProvider } from '@phantom/react-sdk/solana';
14
+ import React from "react";
15
+ import { PhantomProvider, useConnect } from "@phantom/react-sdk";
16
+ import { createSolanaPlugin } from "@phantom/browser-sdk/solana";
18
17
 
19
18
  function App() {
20
19
  return (
@@ -25,29 +24,25 @@ function App() {
25
24
  }
26
25
 
27
26
  function WalletComponent() {
28
- const { status, provider } = useProvider();
29
-
30
- if (status === 'loading') {
31
- return <div>Loading wallet...</div>;
32
- }
33
-
34
- if (status === 'error') {
35
- return <div>Error</div>;
36
- }
37
-
38
- if (status === 'success') {
39
- return (
40
- <div>
41
- <div>Wallet connected!</div>
42
- <button onClick={() => provider.connect()}>
43
- Connect to Solana
44
- </button>
45
- </div>
46
- );
47
- }
48
-
49
- return null;
27
+ const { connect } = useConnect();
28
+
29
+ const handleConnect = async () => {
30
+ try {
31
+ const connectedAccount = await connect();
32
+ console.log("Wallet connected:", connectedAccount?.publicKey?.toString());
33
+ } catch (error) {
34
+ console.error("Connection failed:", error);
35
+ }
36
+ };
37
+
38
+ return (
39
+ <div>
40
+ <button onClick={handleConnect}>Connect to Solana</button>
41
+ </div>
42
+ );
50
43
  }
44
+
45
+ export default App;
51
46
  ```
52
47
 
53
48
  ## API Reference
@@ -57,15 +52,19 @@ function WalletComponent() {
57
52
  The PhantomProvider component provides the Phantom context to child components.
58
53
 
59
54
  ```tsx
60
- import { PhantomProvider } from '@phantom/react-sdk';
61
- import { createSolanaPlugin } from '@phantom/browser-sdk/solana';
55
+ import { PhantomProvider } from "@phantom/react-sdk";
56
+ import { createSolanaPlugin } from "@phantom/browser-sdk/solana";
62
57
 
63
- <PhantomProvider config={{ chainPlugins: [createSolanaPlugin()] }}>
64
- {children}
65
- </PhantomProvider>
58
+ <PhantomProvider config={{ chainPlugins: [createSolanaPlugin()] }}>{children}</PhantomProvider>;
66
59
  ```
67
60
 
68
- ### useProvider (Solana)
61
+ ### usePhantom
62
+
63
+ The `usePhantom` hoo provides access to the phantom instance. With Phantom instance you can call browser-sdk methods directly.
64
+
65
+ ## Solana API Reference
66
+
67
+ ### useProvider
69
68
 
70
69
  The `useProvider` hook provides access to the Solana provider with automatic retry logic and state management.
71
70
 
@@ -75,3 +74,225 @@ The hook returns an object with the following properties:
75
74
 
76
75
  - `status: 'loading' | 'success' | 'error'` - Current status of the provider
77
76
  - `provider: NonNullable<unknown> | null` - The Solana provider instance (null when not available)
77
+
78
+ ### useConnect (Solana)
79
+
80
+ The `useConnect` hook provides a function to connect to the Phantom wallet for Solana.
81
+
82
+ #### Props
83
+
84
+ - `autoConnect?: boolean` (optional) - If `true`, attempts to connect to the wallet automatically when the component mounts. Defaults to `false`.
85
+
86
+ #### Return Value
87
+
88
+ The hook returns an object with the following property:
89
+
90
+ - `connect: () => Promise<ConnectResponse>` - An asynchronous function that initiates the connection process. Returns a promise that resolves with the connection response (e.g., `{ publicKey: string }`) or rejects if connection fails.
91
+
92
+ ```tsx
93
+ import { useConnect } from "@phantom/react-sdk"; // Or '@phantom/react-sdk/solana' if specific
94
+
95
+ function MyComponent() {
96
+ const { connect } = useConnect({ autoConnect: true });
97
+
98
+ const handleConnectClick = async () => {
99
+ try {
100
+ const res = await connect();
101
+ console.log("Connected:", res.publicKey.toString());
102
+ } catch (err) {
103
+ console.error("Connection error:", err);
104
+ }
105
+ };
106
+ // ...
107
+ }
108
+ ```
109
+
110
+ ### useDisconnect (Solana)
111
+
112
+ The `useDisconnect` hook provides a function to disconnect from the Phantom wallet for Solana.
113
+
114
+ #### Return Value
115
+
116
+ The hook returns an object with the following property:
117
+
118
+ - `disconnect: () => Promise<void>` - An asynchronous function that initiates the disconnection process. Returns a promise that resolves when disconnection is complete or rejects if disconnection fails.
119
+
120
+ ```tsx
121
+ import { useDisconnect } from "@phantom/react-sdk"; // Or '@phantom/react-sdk/solana' if specific
122
+
123
+ function MyComponent() {
124
+ const { disconnect } = useDisconnect();
125
+
126
+ const handleDisconnectClick = async () => {
127
+ try {
128
+ await disconnect();
129
+ console.log("Disconnected");
130
+ } catch (err) {
131
+ console.error("Disconnection error:", err);
132
+ }
133
+ };
134
+ // ...
135
+ }
136
+ ```
137
+
138
+ ### useAccount
139
+
140
+ The `useAccount` hook provides access the currently connected account state. It is reactive and changes according to the connected account state.
141
+
142
+ #### Return Value
143
+
144
+ The hook returns an object with the following properties:
145
+
146
+ - `status: 'loading' | 'connected' | 'disconnected'` - Current account status
147
+ - `publicKey: string | null` - Current public key of the connected account or null when account is not connected.
148
+
149
+ ### useSignIn (Solana)
150
+
151
+ The `useSignIn` hook provides a function to initiate a sign-in request to the Phantom wallet for Solana. This is compliant with SIP-001 (Sign In With Solana).
152
+
153
+ #### Return Value
154
+
155
+ The hook returns an object with the following property:
156
+
157
+ - `signIn: (signInData: SolanaSignInData) => Promise<{ address: string; signature: Uint8Array; signedMessage: Uint8Array }>` - An asynchronous function that initiates the sign-in process. `SolanaSignInData` is a type imported from `@phantom/browser-sdk/solana`. Returns a promise that resolves with the `address` (string), `signature` (Uint8Array), and `signedMessage` (Uint8Array), or rejects if the sign-in fails.
158
+
159
+ ```tsx
160
+ import { useSignIn } from "@phantom/react-sdk"; // Or '@phantom/react-sdk/solana' if specific
161
+ import { SolanaSignInData } from "@phantom/browser-sdk/solana"; // This type might be needed from the browser-sdk
162
+
163
+ function MyComponent() {
164
+ const { signIn } = useSignIn();
165
+
166
+ const handleSignInClick = async () => {
167
+ // Construct SolanaSignInData according to your needs
168
+ // This typically includes the domain and a statement for the user.
169
+ const signInData: SolanaSignInData = {
170
+ domain: window.location.host,
171
+ statement: "Please sign in to access exclusive features.",
172
+ // Other fields like `nonce`, `chainId`, `resources` can be added as per SIP-001
173
+ };
174
+
175
+ try {
176
+ const result = await signIn(signInData);
177
+ console.log("Sign In successful. Address:", result.address.toString());
178
+ // You can now verify the signature and signedMessage on your backend
179
+ // Handle successful sign-in (e.g., update UI, set user session)
180
+ } catch (err) {
181
+ console.error("Sign In error:", err);
182
+ // Handle sign-in error (e.g., show error message to user)
183
+ }
184
+ };
185
+
186
+ return <button onClick={handleSignInClick}>Sign In with Solana</button>;
187
+ }
188
+ ```
189
+
190
+ ### useSignMessage (Solana)
191
+
192
+ The `useSignMessage` hook provides a function to prompt the user to sign an arbitrary message with their Solana account.
193
+
194
+ #### Return Value
195
+
196
+ The hook returns an object with the following property:
197
+
198
+ - `signMessage: (message: Uint8Array, display?: 'utf8' | 'hex') => Promise<{ signature: Uint8Array; publicKey: string }>` - An asynchronous function that prompts the user to sign a message. The `message` must be a `Uint8Array`. The optional `display` parameter can be 'utf8' (default) or 'hex' to suggest how the wallet should display the message bytes. Returns a promise that resolves with the `signature` (Uint8Array) and `publicKey` (string) of the signer, or rejects if signing fails.
199
+
200
+ ```tsx
201
+ import { useSignMessage } from "@phantom/react-sdk"; // Or '@phantom/react-sdk/solana' if specific
202
+
203
+ function MyComponent() {
204
+ const { signMessage } = useSignMessage();
205
+
206
+ const handleSignMessage = async () => {
207
+ const messageToSign = "Please confirm your action by signing this message.";
208
+ const messageBytes = new TextEncoder().encode(messageToSign);
209
+ try {
210
+ const { signature, publicKey } = await signMessage(messageBytes, "utf8");
211
+ console.log("Message signed successfully!");
212
+ console.log("Signature:", signature);
213
+ console.log("Public Key:", publicKey);
214
+ // You can now verify this signature on a backend or use it as needed.
215
+ } catch (err) {
216
+ console.error("Sign message error:", err);
217
+ // Handle error (e.g., user rejected, wallet error)
218
+ }
219
+ };
220
+
221
+ return <button onClick={handleSignMessage}>Sign Message</button>;
222
+ }
223
+ ```
224
+
225
+ ### useSignAndSendTransaction (Solana)
226
+
227
+ The `useSignAndSendTransaction` hook prompts the user to sign **and** send a Kit-style transaction.
228
+
229
+ #### Return Value
230
+
231
+ The hook returns an object with the following property:
232
+
233
+ - `signAndSendTransaction(transaction: Transaction): Promise<{ signature: string; publicKey?: string }>` – accepts a `Transaction` built with **`@solana/kit`** and returns the confirmed signature.
234
+
235
+ ```tsx
236
+ import { useSignAndSendTransaction } from "@phantom/react-sdk/solana"; // scoped import is fine
237
+ import {
238
+ createSolanaRpc,
239
+ createTransactionMessage,
240
+ setTransactionMessageFeePayer,
241
+ setTransactionMessageLifetimeUsingBlockhash,
242
+ pipe,
243
+ address,
244
+ compileTransaction,
245
+ } from "@solana/kit";
246
+
247
+ function MyComponent() {
248
+ const { signAndSendTransaction } = useSignAndSendTransaction();
249
+
250
+ const handlePayment = async (publicKey: string) => {
251
+ // 0️⃣ Ensure the wallet is connected and we have a fee-payer address
252
+ if (!publicKey) return console.error("Wallet not connected");
253
+
254
+ try {
255
+ // 1️⃣ Fetch a recent blockhash
256
+ const rpc = createSolanaRpc("https://api.devnet.solana.com");
257
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
258
+
259
+ // 2️⃣ Build a minimal v0 transaction message (no instructions – demo only)
260
+ const txMessage = pipe(
261
+ createTransactionMessage({ version: 0 }),
262
+ tx => setTransactionMessageFeePayer(address(publicKey), tx),
263
+ tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
264
+ );
265
+
266
+ const transaction = compileTransaction(txMessage);
267
+
268
+ // 3️⃣ Prompt the user to sign and send
269
+ const { signature } = await signAndSendTransaction(transaction);
270
+ console.log("Transaction signature:", signature);
271
+ } catch (err) {
272
+ console.error("Transaction error:", err);
273
+ }
274
+ };
275
+
276
+ return <button onClick={() => handlePayment("YOUR_CONNECTED_WALLET_PUBLIC_KEY")}>Send 0.001 SOL</button>;
277
+ }
278
+ ```
279
+
280
+ ### useAccountEffect
281
+
282
+ The `useAccountEffect` hook provides easy way to subscribe to events like `connect`, `disconnect` and `accountChanged`. You can subscribe by calling the hook and declaring event callbacks you want to react to.
283
+
284
+ Example:
285
+
286
+ ```tsx
287
+ useAccountEffect({
288
+ onConnect: data => {
289
+ console.log("Connected to Phantom with public key:", data.publicKey);
290
+ },
291
+ onDisconnect: () => {
292
+ console.log("Disconnected from Phantom");
293
+ },
294
+ onAccountChanged: data => {
295
+ console.log("Account changed to:", data.publicKey);
296
+ },
297
+ });
298
+ ```
@@ -1,9 +1,12 @@
1
+ import { PhantomSolanaProvider, SolanaSignInData } from '@phantom/browser-sdk/solana';
2
+ import { Transaction } from '@solana/kit';
3
+
1
4
  type ProviderState = {
2
5
  status: "loading";
3
6
  provider: null;
4
7
  } | {
5
8
  status: "success";
6
- provider: NonNullable<unknown>;
9
+ provider: PhantomSolanaProvider;
7
10
  } | {
8
11
  status: "error";
9
12
  provider: null;
@@ -14,4 +17,70 @@ type ProviderState = {
14
17
  */
15
18
  declare function useProvider(): ProviderState;
16
19
 
17
- export { useProvider };
20
+ type UseConnectProps = {
21
+ autoConnect?: boolean;
22
+ };
23
+ declare function useConnect({ autoConnect }?: UseConnectProps): {
24
+ connect: () => Promise<string | undefined>;
25
+ };
26
+
27
+ declare function useDisconnect(): {
28
+ disconnect: () => Promise<void>;
29
+ };
30
+
31
+ interface UseSignInResult {
32
+ signIn: (signInData: SolanaSignInData) => Promise<{
33
+ address: string;
34
+ signature: Uint8Array;
35
+ signedMessage: Uint8Array;
36
+ }>;
37
+ }
38
+ declare function useSignIn(): UseSignInResult;
39
+
40
+ interface UseSignAndSendTransactionResult {
41
+ signAndSendTransaction: (transaction: Transaction) => Promise<{
42
+ signature: string;
43
+ publicKey?: string;
44
+ }>;
45
+ }
46
+ declare function useSignAndSendTransaction(): UseSignAndSendTransactionResult;
47
+
48
+ interface UseSignMessageResult {
49
+ signMessage: (message: Uint8Array, display?: "utf8" | "hex") => Promise<{
50
+ signature: Uint8Array;
51
+ address: string;
52
+ }>;
53
+ }
54
+ declare function useSignMessage(): UseSignMessageResult;
55
+
56
+ type UseAccountResult = {
57
+ status: "connected";
58
+ address: string;
59
+ } | {
60
+ status: "disconnected" | "loading";
61
+ address: null;
62
+ };
63
+ /**
64
+ * React hook that provides the current account connection status and public key.
65
+ * Automatically updates when the account connects, disconnects, or changes.
66
+ *
67
+ * @returns Object containing status ('connected' | 'disconnected') and address (string | null)
68
+ */
69
+ declare function useAccount(): UseAccountResult;
70
+
71
+ type UseAccountEffectParameters = {
72
+ onConnect?(data: {
73
+ publicKey: string;
74
+ }): void;
75
+ onDisconnect?(): void;
76
+ onAccountChanged?(data: {
77
+ publicKey: string;
78
+ }): void;
79
+ };
80
+ /**
81
+ * Hook for listening to account lifecycle events.
82
+ * Provides callbacks for connect, disconnect, and account change events.
83
+ */
84
+ declare function useAccountEffect(parameters?: UseAccountEffectParameters): void;
85
+
86
+ export { useAccount, useAccountEffect, useConnect, useDisconnect, useProvider, useSignAndSendTransaction, useSignIn, useSignMessage };
@@ -30,7 +30,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/solana/index.ts
31
31
  var solana_exports = {};
32
32
  __export(solana_exports, {
33
- useProvider: () => useProvider
33
+ useAccount: () => useAccount,
34
+ useAccountEffect: () => useAccountEffect,
35
+ useConnect: () => useConnect,
36
+ useDisconnect: () => useDisconnect,
37
+ useProvider: () => useProvider,
38
+ useSignAndSendTransaction: () => useSignAndSendTransaction,
39
+ useSignIn: () => useSignIn,
40
+ useSignMessage: () => useSignMessage
34
41
  });
35
42
  module.exports = __toCommonJS(solana_exports);
36
43
  var import_solana = require("@phantom/browser-sdk/solana");
@@ -117,7 +124,188 @@ function useProvider() {
117
124
  }, [isReady, tryResolvingProvider]);
118
125
  return state;
119
126
  }
127
+
128
+ // src/solana/useConnect.ts
129
+ var React3 = __toESM(require("react"));
130
+ function useConnect({ autoConnect = false } = {}) {
131
+ const { phantom } = usePhantom();
132
+ const connect = React3.useCallback(async () => {
133
+ if (!phantom?.solana) {
134
+ throw new Error("Phantom solana plugin not found.");
135
+ }
136
+ return await phantom.solana.connect();
137
+ }, [phantom]);
138
+ React3.useEffect(() => {
139
+ if (autoConnect && phantom?.solana) {
140
+ connect();
141
+ }
142
+ }, [autoConnect, connect, phantom?.solana]);
143
+ return { connect };
144
+ }
145
+
146
+ // src/solana/useDisconnect.ts
147
+ var React4 = __toESM(require("react"));
148
+ function useDisconnect() {
149
+ const { phantom } = usePhantom();
150
+ const disconnect = React4.useCallback(async () => {
151
+ if (!phantom?.solana) {
152
+ throw new Error("Phantom solana disconnect method not found.");
153
+ }
154
+ return await phantom.solana.disconnect();
155
+ }, [phantom]);
156
+ return { disconnect };
157
+ }
158
+
159
+ // src/solana/useSignIn.ts
160
+ var import_react = require("react");
161
+ function useSignIn() {
162
+ const { phantom } = usePhantom();
163
+ const signIn = (0, import_react.useCallback)(
164
+ async (signInData) => {
165
+ if (!phantom?.solana) {
166
+ throw new Error("Phantom Solana provider not available.");
167
+ }
168
+ const result = await phantom.solana.signIn(signInData);
169
+ return result;
170
+ },
171
+ [phantom]
172
+ );
173
+ return { signIn };
174
+ }
175
+
176
+ // src/solana/useSignAndSendTransaction.ts
177
+ var import_react2 = require("react");
178
+ function useSignAndSendTransaction() {
179
+ const { phantom } = usePhantom();
180
+ const signAndSendTransaction = (0, import_react2.useCallback)(
181
+ async (transaction) => {
182
+ if (!phantom?.solana) {
183
+ throw new Error("Phantom Solana provider not available.");
184
+ }
185
+ const result = await phantom.solana.signAndSendTransaction(transaction);
186
+ return result;
187
+ },
188
+ [phantom]
189
+ );
190
+ return { signAndSendTransaction };
191
+ }
192
+
193
+ // src/solana/useSignMessage.ts
194
+ var import_react3 = require("react");
195
+ function useSignMessage() {
196
+ const { phantom } = usePhantom();
197
+ const signMessage = (0, import_react3.useCallback)(
198
+ async (message, display) => {
199
+ if (!phantom?.solana) {
200
+ throw new Error("Phantom Solana provider not available.");
201
+ }
202
+ const result = await phantom.solana.signMessage(message, display);
203
+ return result;
204
+ },
205
+ [phantom]
206
+ );
207
+ return { signMessage };
208
+ }
209
+
210
+ // src/solana/useAccount.ts
211
+ var React5 = __toESM(require("react"));
212
+
213
+ // src/solana/assertions.ts
214
+ function assertSolanaConfigured(phantom) {
215
+ if (!phantom?.solana) {
216
+ throw new Error(
217
+ "Phantom solana chain plugin not found. Please ensure the solana chain plugin is installed and configured properly."
218
+ );
219
+ }
220
+ }
221
+
222
+ // src/solana/useAccount.ts
223
+ function useAccount() {
224
+ const { phantom, isReady } = usePhantom();
225
+ const { status: providerStatus, provider } = useProvider();
226
+ const [account, setAccount] = React5.useState(() => {
227
+ if (!isReady)
228
+ return { status: "loading", address: null };
229
+ assertSolanaConfigured(phantom);
230
+ return phantom.solana.getAccount();
231
+ });
232
+ React5.useEffect(() => {
233
+ if (!isReady)
234
+ return;
235
+ assertSolanaConfigured(phantom);
236
+ if (providerStatus !== "success" || !provider)
237
+ return;
238
+ if (account.status === "loading") {
239
+ setAccount(phantom.solana.getAccount());
240
+ }
241
+ const updateAccount = () => {
242
+ setAccount(phantom.solana.getAccount());
243
+ };
244
+ phantom.solana.addEventListener("connect", updateAccount);
245
+ phantom.solana.addEventListener("disconnect", updateAccount);
246
+ phantom.solana.addEventListener("accountChanged", updateAccount);
247
+ return () => {
248
+ phantom.solana.removeEventListener("connect", updateAccount);
249
+ phantom.solana.removeEventListener("disconnect", updateAccount);
250
+ phantom.solana.removeEventListener("accountChanged", updateAccount);
251
+ };
252
+ }, [provider, phantom, providerStatus, isReady, account.status]);
253
+ return account;
254
+ }
255
+
256
+ // src/solana/useAccountEffect.ts
257
+ var React6 = __toESM(require("react"));
258
+ function useAccountEffect(parameters = {}) {
259
+ const { onConnect, onDisconnect, onAccountChanged } = parameters;
260
+ const { phantom, isReady } = usePhantom();
261
+ const { status: providerStatus, provider } = useProvider();
262
+ React6.useEffect(() => {
263
+ if (!isReady || providerStatus !== "success" || !provider)
264
+ return;
265
+ assertSolanaConfigured(phantom);
266
+ const handleConnect = (publicKey) => {
267
+ onConnect?.({
268
+ publicKey
269
+ });
270
+ };
271
+ const handleDisconnect = () => {
272
+ onDisconnect?.();
273
+ };
274
+ const handleAccountChanged = (publicKey) => {
275
+ onAccountChanged?.({
276
+ publicKey
277
+ });
278
+ };
279
+ if (onConnect) {
280
+ phantom.solana.addEventListener("connect", handleConnect);
281
+ }
282
+ if (onDisconnect) {
283
+ phantom.solana.addEventListener("disconnect", handleDisconnect);
284
+ }
285
+ if (onAccountChanged) {
286
+ phantom.solana.addEventListener("accountChanged", handleAccountChanged);
287
+ }
288
+ return () => {
289
+ if (onConnect) {
290
+ phantom.solana.removeEventListener("connect", handleConnect);
291
+ }
292
+ if (onDisconnect) {
293
+ phantom.solana.removeEventListener("disconnect", handleDisconnect);
294
+ }
295
+ if (onAccountChanged) {
296
+ phantom.solana.removeEventListener("accountChanged", handleAccountChanged);
297
+ }
298
+ };
299
+ }, [isReady, providerStatus, provider, phantom, onConnect, onDisconnect, onAccountChanged]);
300
+ }
120
301
  // Annotate the CommonJS export names for ESM import in node:
121
302
  0 && (module.exports = {
122
- useProvider
303
+ useAccount,
304
+ useAccountEffect,
305
+ useConnect,
306
+ useDisconnect,
307
+ useProvider,
308
+ useSignAndSendTransaction,
309
+ useSignIn,
310
+ useSignMessage
123
311
  });
@@ -72,6 +72,187 @@ function useProvider() {
72
72
  }, [isReady, tryResolvingProvider]);
73
73
  return state;
74
74
  }
75
+
76
+ // src/solana/useConnect.ts
77
+ import * as React2 from "react";
78
+ function useConnect({ autoConnect = false } = {}) {
79
+ const { phantom } = usePhantom();
80
+ const connect = React2.useCallback(async () => {
81
+ if (!phantom?.solana) {
82
+ throw new Error("Phantom solana plugin not found.");
83
+ }
84
+ return await phantom.solana.connect();
85
+ }, [phantom]);
86
+ React2.useEffect(() => {
87
+ if (autoConnect && phantom?.solana) {
88
+ connect();
89
+ }
90
+ }, [autoConnect, connect, phantom?.solana]);
91
+ return { connect };
92
+ }
93
+
94
+ // src/solana/useDisconnect.ts
95
+ import * as React3 from "react";
96
+ function useDisconnect() {
97
+ const { phantom } = usePhantom();
98
+ const disconnect = React3.useCallback(async () => {
99
+ if (!phantom?.solana) {
100
+ throw new Error("Phantom solana disconnect method not found.");
101
+ }
102
+ return await phantom.solana.disconnect();
103
+ }, [phantom]);
104
+ return { disconnect };
105
+ }
106
+
107
+ // src/solana/useSignIn.ts
108
+ import { useCallback as useCallback4 } from "react";
109
+ function useSignIn() {
110
+ const { phantom } = usePhantom();
111
+ const signIn = useCallback4(
112
+ async (signInData) => {
113
+ if (!phantom?.solana) {
114
+ throw new Error("Phantom Solana provider not available.");
115
+ }
116
+ const result = await phantom.solana.signIn(signInData);
117
+ return result;
118
+ },
119
+ [phantom]
120
+ );
121
+ return { signIn };
122
+ }
123
+
124
+ // src/solana/useSignAndSendTransaction.ts
125
+ import { useCallback as useCallback5 } from "react";
126
+ function useSignAndSendTransaction() {
127
+ const { phantom } = usePhantom();
128
+ const signAndSendTransaction = useCallback5(
129
+ async (transaction) => {
130
+ if (!phantom?.solana) {
131
+ throw new Error("Phantom Solana provider not available.");
132
+ }
133
+ const result = await phantom.solana.signAndSendTransaction(transaction);
134
+ return result;
135
+ },
136
+ [phantom]
137
+ );
138
+ return { signAndSendTransaction };
139
+ }
140
+
141
+ // src/solana/useSignMessage.ts
142
+ import { useCallback as useCallback6 } from "react";
143
+ function useSignMessage() {
144
+ const { phantom } = usePhantom();
145
+ const signMessage = useCallback6(
146
+ async (message, display) => {
147
+ if (!phantom?.solana) {
148
+ throw new Error("Phantom Solana provider not available.");
149
+ }
150
+ const result = await phantom.solana.signMessage(message, display);
151
+ return result;
152
+ },
153
+ [phantom]
154
+ );
155
+ return { signMessage };
156
+ }
157
+
158
+ // src/solana/useAccount.ts
159
+ import * as React4 from "react";
160
+
161
+ // src/solana/assertions.ts
162
+ function assertSolanaConfigured(phantom) {
163
+ if (!phantom?.solana) {
164
+ throw new Error(
165
+ "Phantom solana chain plugin not found. Please ensure the solana chain plugin is installed and configured properly."
166
+ );
167
+ }
168
+ }
169
+
170
+ // src/solana/useAccount.ts
171
+ function useAccount() {
172
+ const { phantom, isReady } = usePhantom();
173
+ const { status: providerStatus, provider } = useProvider();
174
+ const [account, setAccount] = React4.useState(() => {
175
+ if (!isReady)
176
+ return { status: "loading", address: null };
177
+ assertSolanaConfigured(phantom);
178
+ return phantom.solana.getAccount();
179
+ });
180
+ React4.useEffect(() => {
181
+ if (!isReady)
182
+ return;
183
+ assertSolanaConfigured(phantom);
184
+ if (providerStatus !== "success" || !provider)
185
+ return;
186
+ if (account.status === "loading") {
187
+ setAccount(phantom.solana.getAccount());
188
+ }
189
+ const updateAccount = () => {
190
+ setAccount(phantom.solana.getAccount());
191
+ };
192
+ phantom.solana.addEventListener("connect", updateAccount);
193
+ phantom.solana.addEventListener("disconnect", updateAccount);
194
+ phantom.solana.addEventListener("accountChanged", updateAccount);
195
+ return () => {
196
+ phantom.solana.removeEventListener("connect", updateAccount);
197
+ phantom.solana.removeEventListener("disconnect", updateAccount);
198
+ phantom.solana.removeEventListener("accountChanged", updateAccount);
199
+ };
200
+ }, [provider, phantom, providerStatus, isReady, account.status]);
201
+ return account;
202
+ }
203
+
204
+ // src/solana/useAccountEffect.ts
205
+ import * as React5 from "react";
206
+ function useAccountEffect(parameters = {}) {
207
+ const { onConnect, onDisconnect, onAccountChanged } = parameters;
208
+ const { phantom, isReady } = usePhantom();
209
+ const { status: providerStatus, provider } = useProvider();
210
+ React5.useEffect(() => {
211
+ if (!isReady || providerStatus !== "success" || !provider)
212
+ return;
213
+ assertSolanaConfigured(phantom);
214
+ const handleConnect = (publicKey) => {
215
+ onConnect?.({
216
+ publicKey
217
+ });
218
+ };
219
+ const handleDisconnect = () => {
220
+ onDisconnect?.();
221
+ };
222
+ const handleAccountChanged = (publicKey) => {
223
+ onAccountChanged?.({
224
+ publicKey
225
+ });
226
+ };
227
+ if (onConnect) {
228
+ phantom.solana.addEventListener("connect", handleConnect);
229
+ }
230
+ if (onDisconnect) {
231
+ phantom.solana.addEventListener("disconnect", handleDisconnect);
232
+ }
233
+ if (onAccountChanged) {
234
+ phantom.solana.addEventListener("accountChanged", handleAccountChanged);
235
+ }
236
+ return () => {
237
+ if (onConnect) {
238
+ phantom.solana.removeEventListener("connect", handleConnect);
239
+ }
240
+ if (onDisconnect) {
241
+ phantom.solana.removeEventListener("disconnect", handleDisconnect);
242
+ }
243
+ if (onAccountChanged) {
244
+ phantom.solana.removeEventListener("accountChanged", handleAccountChanged);
245
+ }
246
+ };
247
+ }, [isReady, providerStatus, provider, phantom, onConnect, onDisconnect, onAccountChanged]);
248
+ }
75
249
  export {
76
- useProvider
250
+ useAccount,
251
+ useAccountEffect,
252
+ useConnect,
253
+ useDisconnect,
254
+ useProvider,
255
+ useSignAndSendTransaction,
256
+ useSignIn,
257
+ useSignMessage
77
258
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/react-sdk",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",