@phantom/react-native-sdk 1.0.0-beta.21 → 1.0.0-beta.24

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, X, TikTok) 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, X (Twitter), TikTok
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
@@ -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, X, TikTok)
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,11 @@ 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
314
+ await connect({ provider: "x" }); // X/Twitter
315
+ await connect({ provider: "tiktok" }); // TikTok
229
316
  ```
230
317
 
231
318
  #### useAccounts
@@ -301,18 +388,18 @@ if (isAvailable) {
301
388
 
302
389
  **Supported EVM Networks:**
303
390
 
304
- | Network | Chain ID | Usage |
305
- |---------|----------|-------|
306
- | Ethereum Mainnet | `1` | `ethereum.switchChain(1)` |
391
+ | Network | Chain ID | Usage |
392
+ | ---------------- | ---------- | -------------------------------- |
393
+ | Ethereum Mainnet | `1` | `ethereum.switchChain(1)` |
307
394
  | Ethereum Sepolia | `11155111` | `ethereum.switchChain(11155111)` |
308
- | Polygon Mainnet | `137` | `ethereum.switchChain(137)` |
309
- | Polygon Amoy | `80002` | `ethereum.switchChain(80002)` |
310
- | Base Mainnet | `8453` | `ethereum.switchChain(8453)` |
311
- | Base Sepolia | `84532` | `ethereum.switchChain(84532)` |
312
- | Arbitrum One | `42161` | `ethereum.switchChain(42161)` |
313
- | Arbitrum Sepolia | `421614` | `ethereum.switchChain(421614)` |
314
- | Monad Mainnet | `143` | `ethereum.switchChain(143)` |
315
- | Monad Testnet | `10143` | `ethereum.switchChain(10143)` |
395
+ | Polygon Mainnet | `137` | `ethereum.switchChain(137)` |
396
+ | Polygon Amoy | `80002` | `ethereum.switchChain(80002)` |
397
+ | Base Mainnet | `8453` | `ethereum.switchChain(8453)` |
398
+ | Base Sepolia | `84532` | `ethereum.switchChain(84532)` |
399
+ | Arbitrum One | `42161` | `ethereum.switchChain(42161)` |
400
+ | Arbitrum Sepolia | `421614` | `ethereum.switchChain(421614)` |
401
+ | Monad Mainnet | `143` | `ethereum.switchChain(143)` |
402
+ | Monad Testnet | `10143` | `ethereum.switchChain(10143)` |
316
403
 
317
404
  #### useDisconnect
318
405
 
@@ -324,15 +411,78 @@ const { disconnect, isDisconnecting } = useDisconnect();
324
411
  await disconnect();
325
412
  ```
326
413
 
414
+ ## Theming
415
+
416
+ Customize the modal appearance by passing a `theme` prop to the `PhantomProvider`. The SDK includes built-in `darkTheme` (default).
417
+
418
+ ### Using Built-in Theme
419
+
420
+ ```tsx
421
+ import { PhantomProvider, darkTheme } from "@phantom/react-native-sdk";
422
+
423
+ <PhantomProvider config={config} theme={darkTheme} appIcon="https://your-app.com/icon.png" appName="Your App Name">
424
+ <App />
425
+ </PhantomProvider>;
426
+ ```
427
+
428
+ ### Custom Theme
429
+
430
+ You can pass a partial theme object to customize specific properties:
431
+
432
+ ```tsx
433
+ import { PhantomProvider } from "@phantom/react-native-sdk";
434
+
435
+ const customTheme = {
436
+ brand: "#7C3AED", // Primary brand color
437
+ background: "#1A1A1A", // Background color
438
+ primary: "#FFFFFF", // Primary text color
439
+ secondary: "#A0A0A0", // Secondary text color
440
+ error: "#EF4444", // Error color
441
+ borderRadius: 12, // Border radius for elements
442
+ };
443
+
444
+ <PhantomProvider config={config} theme={customTheme}>
445
+ <App />
446
+ </PhantomProvider>;
447
+ ```
448
+
449
+ **Theme Properties:**
450
+
451
+ - `brand` - Primary brand color (buttons, accents)
452
+ - `background` - Background color for modal
453
+ - `primary` - Primary text color
454
+ - `secondary` - Secondary text color (labels, descriptions)
455
+ - `error` - Error text and border color
456
+ - `borderRadius` - Border radius for buttons and containers
457
+
327
458
  ## Authentication Flows
328
459
 
329
- ### OAuth Providers
460
+ ### Available Providers
461
+
462
+ The SDK supports multiple authentication providers that you specify when calling `connect()`:
330
463
 
331
- The SDK supports multiple OAuth providers:
464
+ - **Google** (`provider: "google"`) - Google OAuth authentication
465
+ - **Apple** (`provider: "apple"`) - Apple ID authentication
466
+ - **X** (`provider: "x"`) - X/Twitter authentication
467
+ - **TikTok** (`provider: "tiktok"`) - TikTok authentication
332
468
 
333
- - **Google** (`provider: 'google'`)
334
- - **Apple** (`provider: 'apple'`)
335
- - **JWT** (`provider: 'jwt'`) - For custom authentication
469
+ > **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.
470
+
471
+ **Example Usage:**
472
+
473
+ ```tsx
474
+ // Google OAuth
475
+ await connect({ provider: "google" });
476
+
477
+ // Apple ID
478
+ await connect({ provider: "apple" });
479
+
480
+ // X/Twitter
481
+ await connect({ provider: "x" });
482
+
483
+ // TikTok
484
+ await connect({ provider: "tiktok" });
485
+ ```
336
486
 
337
487
  ### Authentication Process
338
488
 
@@ -374,6 +524,7 @@ import { PhantomProvider, AddressType } from "@phantom/react-native-sdk";
374
524
  <PhantomProvider
375
525
  config={{
376
526
  appId: "your-app-id",
527
+ providers: ["google", "apple"],
377
528
  scheme: "myapp",
378
529
  addressTypes: [AddressType.solana],
379
530
  }}
@@ -390,6 +541,7 @@ import { PhantomProvider, AddressType } from "@phantom/react-native-sdk";
390
541
  <PhantomProvider
391
542
  config={{
392
543
  appId: "your-app-id",
544
+ providers: ["google", "apple"],
393
545
  scheme: "mycompany-wallet",
394
546
  addressTypes: [AddressType.solana, AddressType.ethereum],
395
547
  authOptions: {
@@ -502,4 +654,3 @@ interface PhantomDebugConfig {
502
654
  enabled?: boolean; // Enable debug logging (default: false)
503
655
  }
504
656
  ```
505
-
package/dist/index.d.ts CHANGED
@@ -1,8 +1,10 @@
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';
4
+ import { EmbeddedProviderConfig, EmbeddedProviderAuthType, EmbeddedProvider, WalletAddress, ConnectResult } from '@phantom/embedded-provider-core';
5
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';
6
8
  import { ISolanaChain, IEthereumChain } from '@phantom/chain-interfaces';
7
9
  export { AddressType } from '@phantom/client';
8
10
  export { NetworkId } from '@phantom/constants';
@@ -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 */
@@ -27,13 +28,21 @@ interface PhantomSDKConfig extends Omit<EmbeddedProviderConfig, "apiBaseUrl" | "
27
28
  }
28
29
  interface ConnectOptions {
29
30
  /** OAuth provider to use (required) */
30
- provider: "google" | "apple" | "jwt" | "phantom";
31
- /** JWT token for JWT authentication */
32
- jwtToken?: string;
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
+
37
46
  interface PhantomContextValue {
38
47
  sdk: EmbeddedProvider;
39
48
  isConnected: boolean;
@@ -43,15 +52,16 @@ interface PhantomContextValue {
43
52
  walletId: string | null;
44
53
  setWalletId: (walletId: string | null) => void;
45
54
  user: ConnectResult | null;
55
+ allowedProviders: EmbeddedProviderAuthType[];
46
56
  }
47
- interface PhantomProviderProps {
48
- children: ReactNode;
49
- config: PhantomSDKConfig;
50
- debugConfig?: PhantomDebugConfig;
51
- }
52
- declare function PhantomProvider({ children, config, debugConfig }: PhantomProviderProps): react_jsx_runtime.JSX.Element;
53
57
  declare function usePhantom(): PhantomContextValue;
54
58
 
59
+ declare function useModal(): {
60
+ open: () => void;
61
+ close: () => void;
62
+ isOpened: boolean;
63
+ };
64
+
55
65
  declare function useConnect(): {
56
66
  connect: (options: ConnectOptions) => Promise<ConnectResult>;
57
67
  isConnecting: boolean;
@@ -90,4 +100,4 @@ declare function useEthereum(): {
90
100
  isAvailable: boolean;
91
101
  };
92
102
 
93
- export { ConnectOptions, PhantomDebugConfig, PhantomProvider, PhantomSDKConfig, useAccounts, useConnect, useDisconnect, useEthereum, usePhantom, useSolana };
103
+ export { ConnectOptions, PhantomDebugConfig, PhantomProvider, PhantomSDKConfig, useAccounts, useConnect, useDisconnect, useEthereum, useModal, usePhantom, useSolana };