@phantom/react-native-sdk 1.0.0-beta.9 → 1.0.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/README.md CHANGED
@@ -30,10 +30,10 @@ yarn add @phantom/react-native-sdk
30
30
 
31
31
  ```bash
32
32
  # For Expo projects
33
- npx expo install expo-secure-store expo-web-browser expo-auth-session expo-router
33
+ npx expo install expo-secure-store expo-web-browser expo-auth-session expo-router react-native-svg
34
34
 
35
35
  # For bare React Native projects (additional setup required)
36
- npm install expo-secure-store expo-web-browser expo-auth-session
36
+ npm install expo-secure-store expo-web-browser expo-auth-session react-native-svg
37
37
 
38
38
  # Required polyfill for cryptographic operations
39
39
  npm install react-native-get-random-values
@@ -83,12 +83,13 @@ Wrap your app with `PhantomProvider`:
83
83
 
84
84
  ```tsx
85
85
  // App.tsx or _layout.tsx (for Expo Router)
86
- import { PhantomProvider, AddressType } from "@phantom/react-native-sdk";
86
+ import { PhantomProvider, AddressType, darkTheme } from "@phantom/react-native-sdk";
87
87
 
88
88
  export default function App() {
89
89
  return (
90
90
  <PhantomProvider
91
91
  config={{
92
+ providers: ["google", "apple"],
92
93
  appId: "your-app-id", // Get your app ID from phantom.com/portal
93
94
  scheme: "mywalletapp", // Must match app.json scheme
94
95
  addressTypes: [AddressType.solana],
@@ -96,6 +97,9 @@ export default function App() {
96
97
  redirectUrl: "mywalletapp://phantom-auth-callback",
97
98
  },
98
99
  }}
100
+ theme={darkTheme} // Optional: Customize modal appearance
101
+ appIcon="https://your-app.com/icon.png" // Optional: Your app icon
102
+ appName="Your App Name" // Optional: Your app name
99
103
  >
100
104
  <YourAppContent />
101
105
  </PhantomProvider>
@@ -103,7 +107,53 @@ export default function App() {
103
107
  }
104
108
  ```
105
109
 
106
- ### 3. Use hooks in your components
110
+ ### 3. Use the connection modal (Recommended)
111
+
112
+ The SDK includes a built-in bottom sheet modal that provides a user-friendly interface for connecting to Phantom. The modal supports multiple authentication methods (Google, Apple) and handles all connection logic automatically.
113
+
114
+ ```tsx
115
+ // WalletScreen.tsx
116
+ import React from "react";
117
+ import { View, Button, Text } from "react-native";
118
+ import { useModal, useAccounts } from "@phantom/react-native-sdk";
119
+
120
+ export function WalletScreen() {
121
+ const modal = useModal();
122
+ const { isConnected, addresses } = useAccounts();
123
+
124
+ if (!isConnected) {
125
+ return (
126
+ <View style={{ padding: 20 }}>
127
+ <Button title="Connect Wallet" onPress={() => modal.open()} />
128
+ </View>
129
+ );
130
+ }
131
+
132
+ return (
133
+ <View style={{ padding: 20 }}>
134
+ <Text style={{ fontSize: 18, marginBottom: 10 }}>Wallet Connected</Text>
135
+ {addresses.map((addr, index) => (
136
+ <Text key={index}>
137
+ {addr.addressType}: {addr.address}
138
+ </Text>
139
+ ))}
140
+ <Button title="Manage Wallet" onPress={() => modal.open()} />
141
+ </View>
142
+ );
143
+ }
144
+ ```
145
+
146
+ **Modal Features:**
147
+
148
+ - **Multiple Auth Providers**: Google, Apple
149
+ - **Bottom Sheet UI**: Native bottom sheet design for mobile
150
+ - **Automatic State Management**: Shows connect screen when disconnected, wallet management when connected
151
+ - **Error Handling**: Clear error messages displayed in the modal
152
+ - **Loading States**: Visual feedback during connection attempts
153
+
154
+ ### 4. Or use hooks directly
155
+
156
+ Alternatively, you can use the hooks directly for more control:
107
157
 
108
158
  ```tsx
109
159
  // WalletScreen.tsx
@@ -114,8 +164,8 @@ import { useConnect, useAccounts, useSolana, useEthereum, useDisconnect } from "
114
164
  export function WalletScreen() {
115
165
  const { connect, isConnecting, error: connectError } = useConnect();
116
166
  const { addresses, isConnected } = useAccounts();
117
- const solana = useSolana();
118
- const ethereum = useEthereum();
167
+ const { solana } = useSolana();
168
+ const { ethereum } = useEthereum();
119
169
  const { disconnect } = useDisconnect();
120
170
 
121
171
  const handleConnect = async () => {
@@ -197,11 +247,20 @@ The main provider component that initializes the SDK and provides context to all
197
247
  #### Configuration Options
198
248
 
199
249
  ```typescript
250
+ interface PhantomProviderProps {
251
+ config: PhantomSDKConfig;
252
+ debugConfig?: PhantomDebugConfig;
253
+ theme?: PhantomTheme; // Optional: Customize modal appearance
254
+ appIcon?: string; // Optional: Your app icon URL (shown in modal)
255
+ appName?: string; // Optional: Your app name (shown in modal)
256
+ children: ReactNode;
257
+ }
258
+
200
259
  interface PhantomSDKConfig {
201
260
  scheme: string; // Custom URL scheme for your app
202
261
  appId: string; // Your app ID from phantom.com/portal (required)
203
262
  addressTypes: [AddressType, ...AddressType[]]; // e.g., [AddressType.solana]
204
-
263
+
205
264
  // Optional configuration
206
265
  embeddedWalletType?: "user-wallet"; // optional, defaults to "user-wallet", currently the only supported type
207
266
  apiBaseUrl?: string; // e.g., "https://api.phantom.app/v1/wallets" (optional, has default)
@@ -209,12 +268,39 @@ interface PhantomSDKConfig {
209
268
  authUrl?: string; // Custom auth URL (optional)
210
269
  redirectUrl?: string; // Custom redirect URL (optional)
211
270
  };
212
- autoConnect?: boolean; // Auto-connect to existing session on SDK instantiation (optional, defaults to true)
213
271
  }
214
272
  ```
215
273
 
216
274
  ### Hooks
217
275
 
276
+ #### useModal
277
+
278
+ Control the connection modal visibility. The modal automatically shows the appropriate content based on connection status.
279
+
280
+ ```typescript
281
+ const modal = useModal();
282
+
283
+ // Open the modal
284
+ modal.open(); // Shows connect options when disconnected, wallet management when connected
285
+
286
+ // Close the modal
287
+ modal.close();
288
+
289
+ // Check if modal is open
290
+ const isOpen = modal.isOpened;
291
+ ```
292
+
293
+ **Returns:**
294
+
295
+ - `open()` - Function to open the modal
296
+ - `close()` - Function to close the modal
297
+ - `isOpened` - Boolean indicating if modal is currently visible
298
+
299
+ **Modal Behavior:**
300
+
301
+ - **When disconnected**: Shows authentication provider options (Google, Apple)
302
+ - **When connected**: Shows connected wallet addresses and disconnect button
303
+
218
304
  #### useConnect
219
305
 
220
306
  Manages wallet connection functionality.
@@ -222,10 +308,9 @@ Manages wallet connection functionality.
222
308
  ```typescript
223
309
  const { connect, isConnecting, error } = useConnect();
224
310
 
225
- // Connect with specific provider
226
- await connect({ provider: "google" });
227
- await connect({ provider: "apple" });
228
- await connect({ provider: "jwt", jwtToken: "your-jwt-token" });
311
+ // Connect with specific provider (React Native supported providers)
312
+ await connect({ provider: "google" }); // Google OAuth
313
+ await connect({ provider: "apple" }); // Apple ID
229
314
  ```
230
315
 
231
316
  #### useAccounts
@@ -276,14 +361,44 @@ if (isAvailable) {
276
361
  // Sign a transaction (without sending)
277
362
  const signedTx = await ethereum.signTransaction(transactionData);
278
363
 
279
- // Sign and send a transaction
364
+ // Sign and send a transaction
280
365
  const result = await ethereum.sendTransaction(transactionData);
281
366
 
367
+ // Switch to a different chain
368
+ await ethereum.switchChain(137); // Switch to Polygon
369
+ await ethereum.switchChain("0x89"); // Also accepts hex strings
370
+
282
371
  // Get current chain ID
283
372
  const chainId = await ethereum.getChainId();
284
373
  }
285
374
  ```
286
375
 
376
+ **Available Methods:**
377
+
378
+ - `getAccounts()` - Get connected Ethereum accounts
379
+ - `signPersonalMessage(message, address)` - Sign personal message
380
+ - `signTypedData(typedData, address)` - Sign EIP-712 typed data
381
+ - `signTransaction(transaction)` - Sign transaction without sending
382
+ - `sendTransaction(transaction)` - Sign and send transaction
383
+ - `switchChain(chainId)` - Switch chains (accepts chain ID as number or hex string)
384
+ - `getChainId()` - Get current chain ID
385
+ - `isConnected()` - Check connection status
386
+
387
+ **Supported EVM Networks:**
388
+
389
+ | Network | Chain ID | Usage |
390
+ | ---------------- | ---------- | -------------------------------- |
391
+ | Ethereum Mainnet | `1` | `ethereum.switchChain(1)` |
392
+ | Ethereum Sepolia | `11155111` | `ethereum.switchChain(11155111)` |
393
+ | Polygon Mainnet | `137` | `ethereum.switchChain(137)` |
394
+ | Polygon Amoy | `80002` | `ethereum.switchChain(80002)` |
395
+ | Base Mainnet | `8453` | `ethereum.switchChain(8453)` |
396
+ | Base Sepolia | `84532` | `ethereum.switchChain(84532)` |
397
+ | Arbitrum One | `42161` | `ethereum.switchChain(42161)` |
398
+ | Arbitrum Sepolia | `421614` | `ethereum.switchChain(421614)` |
399
+ | Monad Mainnet | `143` | `ethereum.switchChain(143)` |
400
+ | Monad Testnet | `10143` | `ethereum.switchChain(10143)` |
401
+
287
402
  #### useDisconnect
288
403
 
289
404
  Manages wallet disconnection.
@@ -294,15 +409,70 @@ const { disconnect, isDisconnecting } = useDisconnect();
294
409
  await disconnect();
295
410
  ```
296
411
 
412
+ ## Theming
413
+
414
+ Customize the modal appearance by passing a `theme` prop to the `PhantomProvider`. The SDK includes built-in `darkTheme` (default).
415
+
416
+ ### Using Built-in Theme
417
+
418
+ ```tsx
419
+ import { PhantomProvider, darkTheme } from "@phantom/react-native-sdk";
420
+
421
+ <PhantomProvider config={config} theme={darkTheme} appIcon="https://your-app.com/icon.png" appName="Your App Name">
422
+ <App />
423
+ </PhantomProvider>;
424
+ ```
425
+
426
+ ### Custom Theme
427
+
428
+ You can pass a partial theme object to customize specific properties:
429
+
430
+ ```tsx
431
+ import { PhantomProvider } from "@phantom/react-native-sdk";
432
+
433
+ const customTheme = {
434
+ brand: "#7C3AED", // Primary brand color
435
+ background: "#1A1A1A", // Background color
436
+ primary: "#FFFFFF", // Primary text color
437
+ secondary: "#A0A0A0", // Secondary text color
438
+ error: "#EF4444", // Error color
439
+ borderRadius: 12, // Border radius for elements
440
+ };
441
+
442
+ <PhantomProvider config={config} theme={customTheme}>
443
+ <App />
444
+ </PhantomProvider>;
445
+ ```
446
+
447
+ **Theme Properties:**
448
+
449
+ - `brand` - Primary brand color (buttons, accents)
450
+ - `background` - Background color for modal
451
+ - `primary` - Primary text color
452
+ - `secondary` - Secondary text color (labels, descriptions)
453
+ - `error` - Error text and border color
454
+ - `borderRadius` - Border radius for buttons and containers
455
+
297
456
  ## Authentication Flows
298
457
 
299
- ### OAuth Providers
458
+ ### Available Providers
459
+
460
+ The SDK supports multiple authentication providers that you specify when calling `connect()`:
461
+
462
+ - **Google** (`provider: "google"`) - Google OAuth authentication
463
+ - **Apple** (`provider: "apple"`) - Apple ID authentication
300
464
 
301
- The SDK supports multiple OAuth providers:
465
+ > **Note**: React Native SDK does not support Phantom Login or injected provider (browser extension) authentication. These are only available in the Browser SDK and React SDK for web applications.
302
466
 
303
- - **Google** (`provider: 'google'`)
304
- - **Apple** (`provider: 'apple'`)
305
- - **JWT** (`provider: 'jwt'`) - For custom authentication
467
+ **Example Usage:**
468
+
469
+ ```tsx
470
+ // Google OAuth
471
+ await connect({ provider: "google" });
472
+
473
+ // Apple ID
474
+ await connect({ provider: "apple" });
475
+ ```
306
476
 
307
477
  ### Authentication Process
308
478
 
@@ -344,6 +514,7 @@ import { PhantomProvider, AddressType } from "@phantom/react-native-sdk";
344
514
  <PhantomProvider
345
515
  config={{
346
516
  appId: "your-app-id",
517
+ providers: ["google", "apple"],
347
518
  scheme: "myapp",
348
519
  addressTypes: [AddressType.solana],
349
520
  }}
@@ -360,6 +531,7 @@ import { PhantomProvider, AddressType } from "@phantom/react-native-sdk";
360
531
  <PhantomProvider
361
532
  config={{
362
533
  appId: "your-app-id",
534
+ providers: ["google", "apple"],
363
535
  scheme: "mycompany-wallet",
364
536
  addressTypes: [AddressType.solana, AddressType.ethereum],
365
537
  authOptions: {
@@ -472,12 +644,3 @@ interface PhantomDebugConfig {
472
644
  enabled?: boolean; // Enable debug logging (default: false)
473
645
  }
474
646
  ```
475
-
476
- ## Support
477
-
478
- - **Documentation**: [phantom.app/docs](https://phantom.app/docs)
479
- - **GitHub Issues**: [github.com/phantom/wallet-sdk/issues](https://github.com/phantom/wallet-sdk/issues)
480
-
481
- ## License
482
-
483
- MIT License - see [LICENSE](LICENSE) file for details.
package/dist/index.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
  import * as _phantom_embedded_provider_core from '@phantom/embedded-provider-core';
4
- import { EmbeddedProviderConfig, EmbeddedProvider, WalletAddress, ConnectResult } from '@phantom/embedded-provider-core';
5
- export { ConnectResult, SignAndSendTransactionParams, SignMessageParams, SignMessageResult, SignedTransaction, WalletAddress } from '@phantom/embedded-provider-core';
6
- import * as _phantom_chain_interfaces from '@phantom/chain-interfaces';
4
+ import { EmbeddedProviderConfig, EmbeddedProviderAuthType, EmbeddedProvider, WalletAddress, ConnectResult } from '@phantom/embedded-provider-core';
5
+ export { ConnectErrorEventData, ConnectEventData, ConnectResult, ConnectStartEventData, DisconnectEventData, EmbeddedProviderEvent, EmbeddedProviderEventMap, EventCallback, SignAndSendTransactionParams, SignMessageParams, SignMessageResult, SignedTransaction, WalletAddress } from '@phantom/embedded-provider-core';
6
+ import { PhantomTheme } from '@phantom/wallet-sdk-ui';
7
+ export { PhantomTheme, darkTheme, lightTheme } from '@phantom/wallet-sdk-ui';
8
+ import { ISolanaChain, IEthereumChain } from '@phantom/chain-interfaces';
7
9
  export { AddressType } from '@phantom/client';
8
10
  export { NetworkId } from '@phantom/constants';
9
11
 
@@ -12,10 +14,9 @@ interface PhantomDebugConfig {
12
14
  enabled?: boolean;
13
15
  }
14
16
  interface PhantomSDKConfig extends Omit<EmbeddedProviderConfig, "apiBaseUrl" | "embeddedWalletType" | "authOptions"> {
17
+ providers: EmbeddedProviderAuthType[];
15
18
  /** Custom URL scheme for your app (e.g., "myapp") */
16
19
  scheme: string;
17
- /** Enable auto-connect to existing sessions (default: true) */
18
- autoConnect?: boolean;
19
20
  /** Base URL for Phantom API (default: "https://api.phantom.app/v1/wallets") */
20
21
  apiBaseUrl?: string;
21
22
  /** Authentication options */
@@ -26,35 +27,50 @@ interface PhantomSDKConfig extends Omit<EmbeddedProviderConfig, "apiBaseUrl" | "
26
27
  };
27
28
  }
28
29
  interface ConnectOptions {
29
- /** OAuth provider to use */
30
- provider?: "google" | "apple" | "jwt";
31
- /** JWT token for JWT authentication */
32
- jwtToken?: string;
30
+ /** OAuth provider to use (required) */
31
+ provider: EmbeddedProviderAuthType;
33
32
  /** Custom authentication data */
34
33
  customAuthData?: Record<string, any>;
35
34
  }
36
35
 
36
+ interface PhantomProviderProps {
37
+ children: ReactNode;
38
+ config: PhantomSDKConfig;
39
+ debugConfig?: PhantomDebugConfig;
40
+ theme?: Partial<PhantomTheme>;
41
+ appIcon?: string;
42
+ appName?: string;
43
+ }
44
+ declare function PhantomProvider({ children, config, debugConfig, theme, appIcon, appName }: PhantomProviderProps): react_jsx_runtime.JSX.Element;
45
+
46
+ interface PhantomErrors {
47
+ connect?: Error;
48
+ spendingLimit?: boolean;
49
+ }
37
50
  interface PhantomContextValue {
38
51
  sdk: EmbeddedProvider;
39
52
  isConnected: boolean;
40
53
  isConnecting: boolean;
41
- connectError: Error | null;
54
+ errors: PhantomErrors;
42
55
  addresses: WalletAddress[];
43
56
  walletId: string | null;
44
57
  setWalletId: (walletId: string | null) => void;
58
+ user: ConnectResult | null;
59
+ allowedProviders: EmbeddedProviderAuthType[];
60
+ clearError: (key: keyof PhantomErrors) => void;
45
61
  }
46
- interface PhantomProviderProps {
47
- children: ReactNode;
48
- config: PhantomSDKConfig;
49
- debugConfig?: PhantomDebugConfig;
50
- }
51
- declare function PhantomProvider({ children, config, debugConfig }: PhantomProviderProps): react_jsx_runtime.JSX.Element;
52
62
  declare function usePhantom(): PhantomContextValue;
53
63
 
64
+ declare function useModal(): {
65
+ open: () => void;
66
+ close: () => void;
67
+ isOpened: boolean;
68
+ };
69
+
54
70
  declare function useConnect(): {
55
- connect: (_options?: ConnectOptions) => Promise<ConnectResult>;
71
+ connect: (options: ConnectOptions) => Promise<ConnectResult>;
56
72
  isConnecting: boolean;
57
- error: Error | null;
73
+ error: Error | undefined;
58
74
  };
59
75
 
60
76
  declare function useDisconnect(): {
@@ -75,7 +91,7 @@ declare function useAccounts(): {
75
91
  * @returns Solana chain interface with connection enforcement
76
92
  */
77
93
  declare function useSolana(): {
78
- solana: _phantom_chain_interfaces.ISolanaChain;
94
+ solana: ISolanaChain;
79
95
  isAvailable: boolean;
80
96
  };
81
97
 
@@ -85,8 +101,8 @@ declare function useSolana(): {
85
101
  * @returns Ethereum chain interface with connection enforcement
86
102
  */
87
103
  declare function useEthereum(): {
88
- ethereum: _phantom_chain_interfaces.IEthereumChain;
104
+ ethereum: IEthereumChain;
89
105
  isAvailable: boolean;
90
106
  };
91
107
 
92
- export { ConnectOptions, PhantomDebugConfig, PhantomProvider, PhantomSDKConfig, useAccounts, useConnect, useDisconnect, useEthereum, usePhantom, useSolana };
108
+ export { ConnectOptions, PhantomDebugConfig, PhantomProvider, PhantomSDKConfig, useAccounts, useConnect, useDisconnect, useEthereum, useModal, usePhantom, useSolana };