@phantom/react-native-sdk 1.0.0-beta.1 → 1.0.0-beta.3

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
@@ -89,12 +89,9 @@ export default function App() {
89
89
  return (
90
90
  <PhantomProvider
91
91
  config={{
92
- appId: "your-app-id",
92
+ appId: "your-app-id", // Get your app ID from phantom.com/portal
93
93
  scheme: "mywalletapp", // Must match app.json scheme
94
- embeddedWalletType: "user-wallet",
95
94
  addressTypes: [AddressType.solana],
96
- apiBaseUrl: "https://api.phantom.app/v1/wallets",
97
- solanaProvider: "web3js",
98
95
  authOptions: {
99
96
  redirectUrl: "mywalletapp://phantom-auth-callback",
100
97
  },
@@ -132,8 +129,10 @@ export function WalletScreen() {
132
129
 
133
130
  const handleSignSolanaMessage = async () => {
134
131
  try {
135
- const signature = await solana.signMessage("Hello from Solana!");
136
- Alert.alert("Solana Signed!", `Signature: ${signature.signature.slice(0, 10)}...`);
132
+ if (solana.isAvailable) {
133
+ const signature = await solana.solana.signMessage("Hello from Solana!");
134
+ Alert.alert("Solana Signed!", `Signature: ${signature.signature.slice(0, 10)}...`);
135
+ }
137
136
  } catch (error) {
138
137
  Alert.alert("Error", `Failed to sign: ${error.message}`);
139
138
  }
@@ -141,9 +140,11 @@ export function WalletScreen() {
141
140
 
142
141
  const handleSignEthereumMessage = async () => {
143
142
  try {
144
- const accounts = await ethereum.getAccounts();
145
- const signature = await ethereum.signPersonalMessage("Hello from Ethereum!", accounts[0]);
146
- Alert.alert("Ethereum Signed!", `Signature: ${signature.signature.slice(0, 10)}...`);
143
+ if (ethereum.isAvailable) {
144
+ const accounts = await ethereum.ethereum.getAccounts();
145
+ const signature = await ethereum.ethereum.signPersonalMessage("Hello from Ethereum!", accounts[0]);
146
+ Alert.alert("Ethereum Signed!", `Signature: ${signature.slice(0, 10)}...`);
147
+ }
147
148
  } catch (error) {
148
149
  Alert.alert("Error", `Failed to sign: ${error.message}`);
149
150
  }
@@ -198,15 +199,17 @@ The main provider component that initializes the SDK and provides context to all
198
199
  ```typescript
199
200
  interface PhantomSDKConfig {
200
201
  scheme: string; // Custom URL scheme for your app
201
- embeddedWalletType: "user-wallet" | "app-wallet";
202
+ appId: string; // Your app ID from phantom.com/portal (required)
202
203
  addressTypes: [AddressType, ...AddressType[]]; // e.g., [AddressType.solana]
203
- apiBaseUrl: string; // e.g., "https://api.phantom.app/v1/wallets"
204
- solanaProvider: "web3js" | "kit"; // Solana provider to use
204
+
205
+ // Optional configuration
206
+ embeddedWalletType?: "user-wallet"; // optional, defaults to "user-wallet", currently the only supported type
207
+ apiBaseUrl?: string; // e.g., "https://api.phantom.app/v1/wallets" (optional, has default)
205
208
  authOptions?: {
206
209
  authUrl?: string; // Custom auth URL (optional)
207
210
  redirectUrl?: string; // Custom redirect URL (optional)
208
211
  };
209
- autoConnect?: boolean; // Auto-connect to existing session on SDK instantiation (default: true)
212
+ autoConnect?: boolean; // Auto-connect to existing session on SDK instantiation (optional, defaults to true)
210
213
  }
211
214
  ```
212
215
 
@@ -242,13 +245,18 @@ const {
242
245
  Provides access to Solana-specific operations.
243
246
 
244
247
  ```typescript
245
- const solana = useSolana();
248
+ const { solana, isAvailable } = useSolana();
246
249
 
247
- // Sign a message
248
- const signature = await solana.signMessage("Hello Solana!");
250
+ if (isAvailable) {
251
+ // Sign a message
252
+ const signature = await solana.signMessage("Hello Solana!");
249
253
 
250
- // Sign and send a transaction
251
- const result = await solana.signAndSendTransaction(transaction);
254
+ // Sign a transaction (without sending)
255
+ const signedTx = await solana.signTransaction(transaction);
256
+
257
+ // Sign and send a transaction
258
+ const result = await solana.signAndSendTransaction(transaction);
259
+ }
252
260
  ```
253
261
 
254
262
  #### useEthereum
@@ -256,19 +264,24 @@ const result = await solana.signAndSendTransaction(transaction);
256
264
  Provides access to Ethereum-specific operations.
257
265
 
258
266
  ```typescript
259
- const ethereum = useEthereum();
267
+ const { ethereum, isAvailable } = useEthereum();
268
+
269
+ if (isAvailable) {
270
+ // Get accounts
271
+ const accounts = await ethereum.getAccounts();
260
272
 
261
- // Get accounts
262
- const accounts = await ethereum.getAccounts();
273
+ // Sign a personal message
274
+ const signature = await ethereum.signPersonalMessage("Hello Ethereum!", accounts[0]);
263
275
 
264
- // Sign a personal message
265
- const signature = await ethereum.signPersonalMessage("Hello Ethereum!", accounts[0]);
276
+ // Sign a transaction (without sending)
277
+ const signedTx = await ethereum.signTransaction(transactionData);
266
278
 
267
- // Send a transaction
268
- const result = await ethereum.sendTransaction(transactionData);
279
+ // Sign and send a transaction
280
+ const result = await ethereum.sendTransaction(transactionData);
269
281
 
270
- // Get current chain ID
271
- const chainId = await ethereum.getChainId();
282
+ // Get current chain ID
283
+ const chainId = await ethereum.getChainId();
284
+ }
272
285
  ```
273
286
 
274
287
  #### useDisconnect
@@ -330,11 +343,9 @@ import { PhantomProvider, AddressType } from "@phantom/react-native-sdk";
330
343
 
331
344
  <PhantomProvider
332
345
  config={{
333
- appId: "app_123456789",
346
+ appId: "your-app-id",
334
347
  scheme: "myapp",
335
- embeddedWalletType: "user-wallet",
336
348
  addressTypes: [AddressType.solana],
337
- apiBaseUrl: "https://api.phantom.app/v1/wallets",
338
349
  }}
339
350
  >
340
351
  <App />
@@ -348,14 +359,10 @@ import { PhantomProvider, AddressType } from "@phantom/react-native-sdk";
348
359
 
349
360
  <PhantomProvider
350
361
  config={{
351
- appId: "app_123456789",
362
+ appId: "your-app-id",
352
363
  scheme: "mycompany-wallet",
353
- embeddedWalletType: "user-wallet",
354
364
  addressTypes: [AddressType.solana, AddressType.ethereum],
355
- apiBaseUrl: "https://api.phantom.app/v1/wallets",
356
- solanaProvider: "web3js",
357
365
  authOptions: {
358
- authUrl: "https://connect.phantom.app",
359
366
  redirectUrl: "mycompany-wallet://auth/success",
360
367
  },
361
368
  }}
@@ -389,13 +396,9 @@ import { PhantomProvider, AddressType } from '@phantom/react-native-sdk';
389
396
  const testConfig = {
390
397
  appId: "test-app",
391
398
  scheme: "testapp",
392
- embeddedWalletType: "app-wallet" as const,
393
399
  addressTypes: [AddressType.solana],
394
- apiBaseUrl: "https://api.phantom.app/v1/wallets",
395
-
396
400
  };
397
401
 
398
- // Use app-wallet for testing (no OAuth required)
399
402
  <PhantomProvider config={testConfig}>
400
403
  <TestApp />
401
404
  </PhantomProvider>
@@ -444,6 +447,7 @@ import { PhantomProvider, type PhantomSDKConfig, type PhantomDebugConfig } from
444
447
  function App() {
445
448
  // SDK configuration - static, won't change when debug settings change
446
449
  const config: PhantomSDKConfig = {
450
+ appId: "your-app-id",
447
451
  scheme: "mywalletapp",
448
452
  // ... other config
449
453
  };
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { ReactNode } from 'react';
3
3
  import * as _phantom_embedded_provider_core from '@phantom/embedded-provider-core';
4
4
  import { EmbeddedProviderConfig, EmbeddedProvider, WalletAddress, ConnectResult } from '@phantom/embedded-provider-core';
5
5
  export { ConnectResult, SignAndSendTransactionParams, SignMessageParams, SignMessageResult, SignedTransaction, WalletAddress } from '@phantom/embedded-provider-core';
6
- import { ISolanaChain, IEthereumChain, EthTransactionRequest } from '@phantom/chains';
6
+ import * as _phantom_chains from '@phantom/chains';
7
7
  export { AddressType } from '@phantom/client';
8
8
  export { NetworkId } from '@phantom/constants';
9
9
 
@@ -11,11 +11,15 @@ interface PhantomDebugConfig {
11
11
  /** Enable debug logging */
12
12
  enabled?: boolean;
13
13
  }
14
- interface PhantomSDKConfig extends EmbeddedProviderConfig {
14
+ interface PhantomSDKConfig extends Omit<EmbeddedProviderConfig, "apiBaseUrl" | "embeddedWalletType"> {
15
15
  /** Custom URL scheme for your app (e.g., "myapp") */
16
16
  scheme: string;
17
17
  /** Enable auto-connect to existing sessions (default: true) */
18
18
  autoConnect?: boolean;
19
+ /** Base URL for Phantom API (default: "https://api.phantom.app/v1/wallets") */
20
+ apiBaseUrl?: string;
21
+ /** Authentication options */
22
+ embeddedWalletType?: "app-wallet" | "user-wallet";
19
23
  }
20
24
  interface ConnectOptions {
21
25
  /** OAuth provider to use */
@@ -27,7 +31,7 @@ interface ConnectOptions {
27
31
  }
28
32
 
29
33
  interface PhantomContextValue {
30
- sdk: EmbeddedProvider | null;
34
+ sdk: EmbeddedProvider;
31
35
  isConnected: boolean;
32
36
  isConnecting: boolean;
33
37
  connectError: Error | null;
@@ -64,50 +68,21 @@ declare function useAccounts(): {
64
68
  /**
65
69
  * Hook for Solana chain operations in React Native
66
70
  *
67
- * @returns Solana chain interface and convenient methods
71
+ * @returns Solana chain interface with connection enforcement
68
72
  */
69
73
  declare function useSolana(): {
70
- solana: ISolanaChain | null;
71
- signMessage: (message: string | Uint8Array) => Promise<{
72
- signature: Uint8Array;
73
- publicKey: string;
74
- }>;
75
- signTransaction: <T>(transaction: T) => Promise<T>;
76
- signAndSendTransaction: <T>(transaction: T) => Promise<{
77
- signature: string;
78
- }>;
79
- connect: (options?: {
80
- onlyIfTrusted?: boolean;
81
- }) => Promise<{
82
- publicKey: string;
83
- }>;
84
- disconnect: () => Promise<void>;
85
- switchNetwork: (network: "mainnet" | "devnet") => Promise<void | undefined>;
86
- getPublicKey: () => Promise<string | null>;
74
+ solana: _phantom_chains.ISolanaChain;
87
75
  isAvailable: boolean;
88
- isConnected: boolean;
89
76
  };
90
77
 
91
78
  /**
92
79
  * Hook for Ethereum chain operations in React Native
93
80
  *
94
- * @returns Ethereum chain interface and convenient methods
81
+ * @returns Ethereum chain interface with connection enforcement
95
82
  */
96
83
  declare function useEthereum(): {
97
- ethereum: IEthereumChain | null;
98
- request: <T = any>(args: {
99
- method: string;
100
- params?: unknown[];
101
- }) => Promise<T>;
102
- signPersonalMessage: (message: string, address: string) => Promise<string>;
103
- signMessage: (message: string) => Promise<string>;
104
- signTypedData: (typedData: any) => Promise<string>;
105
- sendTransaction: (transaction: EthTransactionRequest) => Promise<string>;
106
- switchChain: (chainId: number) => Promise<void>;
107
- getChainId: () => Promise<number>;
108
- getAccounts: () => Promise<string[]>;
84
+ ethereum: _phantom_chains.IEthereumChain;
109
85
  isAvailable: boolean;
110
- isConnected: boolean;
111
86
  };
112
87
 
113
88
  export { ConnectOptions, PhantomDebugConfig, PhantomProvider, PhantomSDKConfig, useAccounts, useConnect, useDisconnect, useEthereum, usePhantom, useSolana };
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
33
  AddressType: () => import_client.AddressType,
34
- NetworkId: () => import_constants.NetworkId,
34
+ NetworkId: () => import_constants3.NetworkId,
35
35
  PhantomProvider: () => PhantomProvider,
36
36
  useAccounts: () => useAccounts,
37
37
  useConnect: () => useConnect,
@@ -45,6 +45,7 @@ module.exports = __toCommonJS(src_exports);
45
45
  // src/PhantomProvider.tsx
46
46
  var import_react = require("react");
47
47
  var import_embedded_provider_core = require("@phantom/embedded-provider-core");
48
+ var import_constants2 = require("@phantom/constants");
48
49
 
49
50
  // src/providers/embedded/storage.ts
50
51
  var SecureStore = __toESM(require("expo-secure-store"));
@@ -96,7 +97,7 @@ var ExpoSecureStorage = class {
96
97
 
97
98
  // src/providers/embedded/auth.ts
98
99
  var WebBrowser = __toESM(require("expo-web-browser"));
99
- var DEFAULT_AUTH_URL = "https://auth.phantom.app";
100
+ var import_constants = require("@phantom/constants");
100
101
  var ExpoAuthProvider = class {
101
102
  async authenticate(options) {
102
103
  if ("jwtToken" in options) {
@@ -111,7 +112,7 @@ var ExpoAuthProvider = class {
111
112
  throw new Error("organizationId, sessionId and appId are required for authentication");
112
113
  }
113
114
  try {
114
- const baseUrl = authUrl || DEFAULT_AUTH_URL;
115
+ const baseUrl = authUrl || import_constants.DEFAULT_AUTH_URL;
115
116
  const params = new URLSearchParams({
116
117
  organization_id: organizationId,
117
118
  parent_organization_id: parentOrganizationId,
@@ -459,18 +460,20 @@ function PhantomProvider({ children, config, debugConfig }) {
459
460
  const [connectError, setConnectError] = (0, import_react.useState)(null);
460
461
  const [addresses, setAddresses] = (0, import_react.useState)([]);
461
462
  const [walletId, setWalletId] = (0, import_react.useState)(null);
462
- const [sdk, setSdk] = (0, import_react.useState)(null);
463
463
  const memoizedConfig = (0, import_react.useMemo)(() => {
464
464
  const redirectUrl = config.authOptions?.redirectUrl || `${config.scheme}://phantom-auth-callback`;
465
465
  return {
466
466
  ...config,
467
+ apiBaseUrl: config.apiBaseUrl || import_constants2.DEFAULT_WALLET_API_URL,
468
+ embeddedWalletType: config.embeddedWalletType || import_constants2.DEFAULT_EMBEDDED_WALLET_TYPE,
467
469
  authOptions: {
468
470
  ...config.authOptions || {},
469
- redirectUrl
471
+ redirectUrl,
472
+ authUrl: config.authOptions?.authUrl || import_constants2.DEFAULT_AUTH_URL
470
473
  }
471
474
  };
472
475
  }, [config]);
473
- (0, import_react.useEffect)(() => {
476
+ const sdk = (0, import_react.useMemo)(() => {
474
477
  const storage = new ExpoSecureStorage();
475
478
  const authProvider = new ExpoAuthProvider();
476
479
  const urlParamsAccessor = new ExpoURLParamsAccessor();
@@ -479,14 +482,26 @@ function PhantomProvider({ children, config, debugConfig }) {
479
482
  keyPrefix: `phantom-rn-${memoizedConfig.organizationId}`,
480
483
  organizationId: memoizedConfig.organizationId
481
484
  });
485
+ const platformName = `${import_react_native2.Platform.OS}-${import_react_native2.Platform.Version}`;
482
486
  const platform = {
483
487
  storage,
484
488
  authProvider,
485
489
  urlParamsAccessor,
486
490
  stamper,
487
- name: `${import_react_native2.Platform.OS}-${import_react_native2.Platform.Version}`
491
+ name: platformName,
492
+ analyticsHeaders: {
493
+ [import_constants2.ANALYTICS_HEADERS.SDK_TYPE]: "react-native",
494
+ [import_constants2.ANALYTICS_HEADERS.PLATFORM]: import_react_native2.Platform.OS,
495
+ [import_constants2.ANALYTICS_HEADERS.PLATFORM_VERSION]: `${import_react_native2.Platform.Version}`,
496
+ [import_constants2.ANALYTICS_HEADERS.APP_ID]: config.appId,
497
+ [import_constants2.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
498
+ [import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.3"
499
+ // Replaced at build time
500
+ }
488
501
  };
489
- const sdkInstance = new import_embedded_provider_core.EmbeddedProvider(memoizedConfig, platform, logger);
502
+ return new import_embedded_provider_core.EmbeddedProvider(memoizedConfig, platform, logger);
503
+ }, [memoizedConfig, debugConfig, config.appId, config.embeddedWalletType]);
504
+ (0, import_react.useEffect)(() => {
490
505
  const handleConnectStart = () => {
491
506
  setIsConnecting(true);
492
507
  setConnectError(null);
@@ -495,12 +510,12 @@ function PhantomProvider({ children, config, debugConfig }) {
495
510
  try {
496
511
  setIsConnected(true);
497
512
  setIsConnecting(false);
498
- const addrs = await sdkInstance.getAddresses();
513
+ const addrs = await sdk.getAddresses();
499
514
  setAddresses(addrs);
500
515
  } catch (err) {
501
516
  console.error("Error connecting:", err);
502
517
  try {
503
- await sdkInstance.disconnect();
518
+ await sdk.disconnect();
504
519
  } catch (err2) {
505
520
  console.error("Error disconnecting:", err2);
506
521
  }
@@ -517,21 +532,18 @@ function PhantomProvider({ children, config, debugConfig }) {
517
532
  setAddresses([]);
518
533
  setWalletId(null);
519
534
  };
520
- sdkInstance.on("connect_start", handleConnectStart);
521
- sdkInstance.on("connect", handleConnect);
522
- sdkInstance.on("connect_error", handleConnectError);
523
- sdkInstance.on("disconnect", handleDisconnect);
524
- setSdk(sdkInstance);
535
+ sdk.on("connect_start", handleConnectStart);
536
+ sdk.on("connect", handleConnect);
537
+ sdk.on("connect_error", handleConnectError);
538
+ sdk.on("disconnect", handleDisconnect);
525
539
  return () => {
526
- sdkInstance.off("connect_start", handleConnectStart);
527
- sdkInstance.off("connect", handleConnect);
528
- sdkInstance.off("connect_error", handleConnectError);
529
- sdkInstance.off("disconnect", handleDisconnect);
540
+ sdk.off("connect_start", handleConnectStart);
541
+ sdk.off("connect", handleConnect);
542
+ sdk.off("connect_error", handleConnectError);
543
+ sdk.off("disconnect", handleDisconnect);
530
544
  };
531
- }, [memoizedConfig, debugConfig]);
545
+ }, [sdk]);
532
546
  (0, import_react.useEffect)(() => {
533
- if (!sdk)
534
- return;
535
547
  if (config.autoConnect !== false) {
536
548
  sdk.autoConnect().catch(() => {
537
549
  });
@@ -628,181 +640,30 @@ function useAccounts() {
628
640
  }
629
641
 
630
642
  // src/hooks/useSolana.ts
631
- var import_react4 = require("react");
632
643
  function useSolana() {
633
644
  const { sdk, isConnected } = usePhantom();
634
- const solanaChain = (0, import_react4.useMemo)(() => {
635
- if (!sdk || !isConnected)
636
- return null;
637
- try {
638
- return sdk.solana;
639
- } catch {
640
- return null;
641
- }
642
- }, [sdk, isConnected]);
643
- const signMessage = (0, import_react4.useCallback)(
644
- async (message) => {
645
- if (!solanaChain)
646
- throw new Error("Solana chain not available. Ensure SDK is connected.");
647
- return await solanaChain.signMessage(message);
648
- },
649
- [solanaChain]
650
- );
651
- const signTransaction = (0, import_react4.useCallback)(
652
- async (transaction) => {
653
- if (!solanaChain)
654
- throw new Error("Solana chain not available. Ensure SDK is connected.");
655
- return await solanaChain.signTransaction(transaction);
656
- },
657
- [solanaChain]
658
- );
659
- const signAndSendTransaction = (0, import_react4.useCallback)(
660
- async (transaction) => {
661
- if (!solanaChain)
662
- throw new Error("Solana chain not available. Ensure SDK is connected.");
663
- return await solanaChain.signAndSendTransaction(transaction);
664
- },
665
- [solanaChain]
666
- );
667
- const connect = (0, import_react4.useCallback)(
668
- async (options) => {
669
- if (!solanaChain)
670
- throw new Error("Solana chain not available. Ensure SDK is connected.");
671
- return await solanaChain.connect(options);
672
- },
673
- [solanaChain]
674
- );
675
- const disconnect = (0, import_react4.useCallback)(async () => {
676
- if (!solanaChain)
677
- throw new Error("Solana chain not available. Ensure SDK is connected.");
678
- return await solanaChain.disconnect();
679
- }, [solanaChain]);
680
- const switchNetwork = (0, import_react4.useCallback)(
681
- async (network) => {
682
- if (!solanaChain)
683
- throw new Error("Solana chain not available. Ensure SDK is connected.");
684
- return await solanaChain.switchNetwork?.(network);
685
- },
686
- [solanaChain]
687
- );
688
- const getPublicKey = (0, import_react4.useCallback)(async () => {
689
- if (!solanaChain)
690
- return null;
691
- return await solanaChain.getPublicKey();
692
- }, [solanaChain]);
693
645
  return {
694
- // Chain instance for advanced usage
695
- solana: solanaChain,
696
- // Convenient methods
697
- signMessage,
698
- signTransaction,
699
- signAndSendTransaction,
700
- connect,
701
- disconnect,
702
- switchNetwork,
703
- getPublicKey,
646
+ // Chain instance with connection enforcement for signing methods
647
+ solana: sdk.solana,
704
648
  // State
705
- isAvailable: !!solanaChain,
706
- isConnected: solanaChain?.isConnected() ?? false
649
+ isAvailable: !!isConnected
707
650
  };
708
651
  }
709
652
 
710
653
  // src/hooks/useEthereum.ts
711
- var import_react5 = require("react");
712
654
  function useEthereum() {
713
655
  const { sdk, isConnected } = usePhantom();
714
- const ethereumChain = (0, import_react5.useMemo)(() => {
715
- if (!sdk || !isConnected)
716
- return null;
717
- try {
718
- return sdk.ethereum;
719
- } catch {
720
- return null;
721
- }
722
- }, [sdk, isConnected]);
723
- const request = (0, import_react5.useCallback)(
724
- async (args) => {
725
- if (!ethereumChain)
726
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
727
- return await ethereumChain.request(args);
728
- },
729
- [ethereumChain]
730
- );
731
- const signPersonalMessage = (0, import_react5.useCallback)(
732
- async (message, address) => {
733
- if (!ethereumChain)
734
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
735
- return await ethereumChain.signPersonalMessage(message, address);
736
- },
737
- [ethereumChain]
738
- );
739
- const sendTransaction = (0, import_react5.useCallback)(
740
- async (transaction) => {
741
- if (!ethereumChain)
742
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
743
- return await ethereumChain.sendTransaction(transaction);
744
- },
745
- [ethereumChain]
746
- );
747
- const switchChain = (0, import_react5.useCallback)(
748
- async (chainId) => {
749
- if (!ethereumChain)
750
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
751
- return await ethereumChain.switchChain(chainId);
752
- },
753
- [ethereumChain]
754
- );
755
- const getChainId = (0, import_react5.useCallback)(async () => {
756
- if (!ethereumChain)
757
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
758
- return await ethereumChain.getChainId();
759
- }, [ethereumChain]);
760
- const getAccounts = (0, import_react5.useCallback)(async () => {
761
- if (!ethereumChain)
762
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
763
- return await ethereumChain.getAccounts();
764
- }, [ethereumChain]);
765
- const signMessage = (0, import_react5.useCallback)(
766
- async (message) => {
767
- const accounts = await getAccounts();
768
- return await request({
769
- method: "eth_sign",
770
- params: [accounts[0], message]
771
- });
772
- },
773
- [request, getAccounts]
774
- );
775
- const signTypedData = (0, import_react5.useCallback)(
776
- async (typedData) => {
777
- if (!ethereumChain)
778
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
779
- const accounts = await getAccounts();
780
- return await ethereumChain.signTypedData(typedData, accounts[0]);
781
- },
782
- [ethereumChain, getAccounts]
783
- );
784
656
  return {
785
- // Chain instance for advanced usage
786
- ethereum: ethereumChain,
787
- // Standard EIP-1193 interface
788
- request,
789
- // Convenient methods
790
- signPersonalMessage,
791
- signMessage,
792
- signTypedData,
793
- sendTransaction,
794
- switchChain,
795
- getChainId,
796
- getAccounts,
657
+ // Chain instance with connection enforcement for signing methods
658
+ ethereum: sdk.ethereum,
797
659
  // State
798
- isAvailable: !!ethereumChain,
799
- isConnected: ethereumChain?.isConnected() ?? false
660
+ isAvailable: !!isConnected
800
661
  };
801
662
  }
802
663
 
803
664
  // src/index.ts
804
665
  var import_client = require("@phantom/client");
805
- var import_constants = require("@phantom/constants");
666
+ var import_constants3 = require("@phantom/constants");
806
667
  // Annotate the CommonJS export names for ESM import in node:
807
668
  0 && (module.exports = {
808
669
  AddressType,
package/dist/index.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  // src/PhantomProvider.tsx
2
2
  import { createContext, useContext, useState, useEffect, useMemo } from "react";
3
3
  import { EmbeddedProvider } from "@phantom/embedded-provider-core";
4
+ import { ANALYTICS_HEADERS, DEFAULT_WALLET_API_URL, DEFAULT_EMBEDDED_WALLET_TYPE, DEFAULT_AUTH_URL as DEFAULT_AUTH_URL2 } from "@phantom/constants";
4
5
 
5
6
  // src/providers/embedded/storage.ts
6
7
  import * as SecureStore from "expo-secure-store";
@@ -52,7 +53,7 @@ var ExpoSecureStorage = class {
52
53
 
53
54
  // src/providers/embedded/auth.ts
54
55
  import * as WebBrowser from "expo-web-browser";
55
- var DEFAULT_AUTH_URL = "https://auth.phantom.app";
56
+ import { DEFAULT_AUTH_URL } from "@phantom/constants";
56
57
  var ExpoAuthProvider = class {
57
58
  async authenticate(options) {
58
59
  if ("jwtToken" in options) {
@@ -415,18 +416,20 @@ function PhantomProvider({ children, config, debugConfig }) {
415
416
  const [connectError, setConnectError] = useState(null);
416
417
  const [addresses, setAddresses] = useState([]);
417
418
  const [walletId, setWalletId] = useState(null);
418
- const [sdk, setSdk] = useState(null);
419
419
  const memoizedConfig = useMemo(() => {
420
420
  const redirectUrl = config.authOptions?.redirectUrl || `${config.scheme}://phantom-auth-callback`;
421
421
  return {
422
422
  ...config,
423
+ apiBaseUrl: config.apiBaseUrl || DEFAULT_WALLET_API_URL,
424
+ embeddedWalletType: config.embeddedWalletType || DEFAULT_EMBEDDED_WALLET_TYPE,
423
425
  authOptions: {
424
426
  ...config.authOptions || {},
425
- redirectUrl
427
+ redirectUrl,
428
+ authUrl: config.authOptions?.authUrl || DEFAULT_AUTH_URL2
426
429
  }
427
430
  };
428
431
  }, [config]);
429
- useEffect(() => {
432
+ const sdk = useMemo(() => {
430
433
  const storage = new ExpoSecureStorage();
431
434
  const authProvider = new ExpoAuthProvider();
432
435
  const urlParamsAccessor = new ExpoURLParamsAccessor();
@@ -435,14 +438,26 @@ function PhantomProvider({ children, config, debugConfig }) {
435
438
  keyPrefix: `phantom-rn-${memoizedConfig.organizationId}`,
436
439
  organizationId: memoizedConfig.organizationId
437
440
  });
441
+ const platformName = `${Platform.OS}-${Platform.Version}`;
438
442
  const platform = {
439
443
  storage,
440
444
  authProvider,
441
445
  urlParamsAccessor,
442
446
  stamper,
443
- name: `${Platform.OS}-${Platform.Version}`
447
+ name: platformName,
448
+ analyticsHeaders: {
449
+ [ANALYTICS_HEADERS.SDK_TYPE]: "react-native",
450
+ [ANALYTICS_HEADERS.PLATFORM]: Platform.OS,
451
+ [ANALYTICS_HEADERS.PLATFORM_VERSION]: `${Platform.Version}`,
452
+ [ANALYTICS_HEADERS.APP_ID]: config.appId,
453
+ [ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
454
+ [ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.3"
455
+ // Replaced at build time
456
+ }
444
457
  };
445
- const sdkInstance = new EmbeddedProvider(memoizedConfig, platform, logger);
458
+ return new EmbeddedProvider(memoizedConfig, platform, logger);
459
+ }, [memoizedConfig, debugConfig, config.appId, config.embeddedWalletType]);
460
+ useEffect(() => {
446
461
  const handleConnectStart = () => {
447
462
  setIsConnecting(true);
448
463
  setConnectError(null);
@@ -451,12 +466,12 @@ function PhantomProvider({ children, config, debugConfig }) {
451
466
  try {
452
467
  setIsConnected(true);
453
468
  setIsConnecting(false);
454
- const addrs = await sdkInstance.getAddresses();
469
+ const addrs = await sdk.getAddresses();
455
470
  setAddresses(addrs);
456
471
  } catch (err) {
457
472
  console.error("Error connecting:", err);
458
473
  try {
459
- await sdkInstance.disconnect();
474
+ await sdk.disconnect();
460
475
  } catch (err2) {
461
476
  console.error("Error disconnecting:", err2);
462
477
  }
@@ -473,21 +488,18 @@ function PhantomProvider({ children, config, debugConfig }) {
473
488
  setAddresses([]);
474
489
  setWalletId(null);
475
490
  };
476
- sdkInstance.on("connect_start", handleConnectStart);
477
- sdkInstance.on("connect", handleConnect);
478
- sdkInstance.on("connect_error", handleConnectError);
479
- sdkInstance.on("disconnect", handleDisconnect);
480
- setSdk(sdkInstance);
491
+ sdk.on("connect_start", handleConnectStart);
492
+ sdk.on("connect", handleConnect);
493
+ sdk.on("connect_error", handleConnectError);
494
+ sdk.on("disconnect", handleDisconnect);
481
495
  return () => {
482
- sdkInstance.off("connect_start", handleConnectStart);
483
- sdkInstance.off("connect", handleConnect);
484
- sdkInstance.off("connect_error", handleConnectError);
485
- sdkInstance.off("disconnect", handleDisconnect);
496
+ sdk.off("connect_start", handleConnectStart);
497
+ sdk.off("connect", handleConnect);
498
+ sdk.off("connect_error", handleConnectError);
499
+ sdk.off("disconnect", handleDisconnect);
486
500
  };
487
- }, [memoizedConfig, debugConfig]);
501
+ }, [sdk]);
488
502
  useEffect(() => {
489
- if (!sdk)
490
- return;
491
503
  if (config.autoConnect !== false) {
492
504
  sdk.autoConnect().catch(() => {
493
505
  });
@@ -584,175 +596,24 @@ function useAccounts() {
584
596
  }
585
597
 
586
598
  // src/hooks/useSolana.ts
587
- import { useCallback as useCallback3, useMemo as useMemo2 } from "react";
588
599
  function useSolana() {
589
600
  const { sdk, isConnected } = usePhantom();
590
- const solanaChain = useMemo2(() => {
591
- if (!sdk || !isConnected)
592
- return null;
593
- try {
594
- return sdk.solana;
595
- } catch {
596
- return null;
597
- }
598
- }, [sdk, isConnected]);
599
- const signMessage = useCallback3(
600
- async (message) => {
601
- if (!solanaChain)
602
- throw new Error("Solana chain not available. Ensure SDK is connected.");
603
- return await solanaChain.signMessage(message);
604
- },
605
- [solanaChain]
606
- );
607
- const signTransaction = useCallback3(
608
- async (transaction) => {
609
- if (!solanaChain)
610
- throw new Error("Solana chain not available. Ensure SDK is connected.");
611
- return await solanaChain.signTransaction(transaction);
612
- },
613
- [solanaChain]
614
- );
615
- const signAndSendTransaction = useCallback3(
616
- async (transaction) => {
617
- if (!solanaChain)
618
- throw new Error("Solana chain not available. Ensure SDK is connected.");
619
- return await solanaChain.signAndSendTransaction(transaction);
620
- },
621
- [solanaChain]
622
- );
623
- const connect = useCallback3(
624
- async (options) => {
625
- if (!solanaChain)
626
- throw new Error("Solana chain not available. Ensure SDK is connected.");
627
- return await solanaChain.connect(options);
628
- },
629
- [solanaChain]
630
- );
631
- const disconnect = useCallback3(async () => {
632
- if (!solanaChain)
633
- throw new Error("Solana chain not available. Ensure SDK is connected.");
634
- return await solanaChain.disconnect();
635
- }, [solanaChain]);
636
- const switchNetwork = useCallback3(
637
- async (network) => {
638
- if (!solanaChain)
639
- throw new Error("Solana chain not available. Ensure SDK is connected.");
640
- return await solanaChain.switchNetwork?.(network);
641
- },
642
- [solanaChain]
643
- );
644
- const getPublicKey = useCallback3(async () => {
645
- if (!solanaChain)
646
- return null;
647
- return await solanaChain.getPublicKey();
648
- }, [solanaChain]);
649
601
  return {
650
- // Chain instance for advanced usage
651
- solana: solanaChain,
652
- // Convenient methods
653
- signMessage,
654
- signTransaction,
655
- signAndSendTransaction,
656
- connect,
657
- disconnect,
658
- switchNetwork,
659
- getPublicKey,
602
+ // Chain instance with connection enforcement for signing methods
603
+ solana: sdk.solana,
660
604
  // State
661
- isAvailable: !!solanaChain,
662
- isConnected: solanaChain?.isConnected() ?? false
605
+ isAvailable: !!isConnected
663
606
  };
664
607
  }
665
608
 
666
609
  // src/hooks/useEthereum.ts
667
- import { useCallback as useCallback4, useMemo as useMemo3 } from "react";
668
610
  function useEthereum() {
669
611
  const { sdk, isConnected } = usePhantom();
670
- const ethereumChain = useMemo3(() => {
671
- if (!sdk || !isConnected)
672
- return null;
673
- try {
674
- return sdk.ethereum;
675
- } catch {
676
- return null;
677
- }
678
- }, [sdk, isConnected]);
679
- const request = useCallback4(
680
- async (args) => {
681
- if (!ethereumChain)
682
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
683
- return await ethereumChain.request(args);
684
- },
685
- [ethereumChain]
686
- );
687
- const signPersonalMessage = useCallback4(
688
- async (message, address) => {
689
- if (!ethereumChain)
690
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
691
- return await ethereumChain.signPersonalMessage(message, address);
692
- },
693
- [ethereumChain]
694
- );
695
- const sendTransaction = useCallback4(
696
- async (transaction) => {
697
- if (!ethereumChain)
698
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
699
- return await ethereumChain.sendTransaction(transaction);
700
- },
701
- [ethereumChain]
702
- );
703
- const switchChain = useCallback4(
704
- async (chainId) => {
705
- if (!ethereumChain)
706
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
707
- return await ethereumChain.switchChain(chainId);
708
- },
709
- [ethereumChain]
710
- );
711
- const getChainId = useCallback4(async () => {
712
- if (!ethereumChain)
713
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
714
- return await ethereumChain.getChainId();
715
- }, [ethereumChain]);
716
- const getAccounts = useCallback4(async () => {
717
- if (!ethereumChain)
718
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
719
- return await ethereumChain.getAccounts();
720
- }, [ethereumChain]);
721
- const signMessage = useCallback4(
722
- async (message) => {
723
- const accounts = await getAccounts();
724
- return await request({
725
- method: "eth_sign",
726
- params: [accounts[0], message]
727
- });
728
- },
729
- [request, getAccounts]
730
- );
731
- const signTypedData = useCallback4(
732
- async (typedData) => {
733
- if (!ethereumChain)
734
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
735
- const accounts = await getAccounts();
736
- return await ethereumChain.signTypedData(typedData, accounts[0]);
737
- },
738
- [ethereumChain, getAccounts]
739
- );
740
612
  return {
741
- // Chain instance for advanced usage
742
- ethereum: ethereumChain,
743
- // Standard EIP-1193 interface
744
- request,
745
- // Convenient methods
746
- signPersonalMessage,
747
- signMessage,
748
- signTypedData,
749
- sendTransaction,
750
- switchChain,
751
- getChainId,
752
- getAccounts,
613
+ // Chain instance with connection enforcement for signing methods
614
+ ethereum: sdk.ethereum,
753
615
  // State
754
- isAvailable: !!ethereumChain,
755
- isConnected: ethereumChain?.isConnected() ?? false
616
+ isAvailable: !!isConnected
756
617
  };
757
618
  }
758
619
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/react-native-sdk",
3
- "version": "1.0.0-beta.1",
3
+ "version": "1.0.0-beta.3",
4
4
  "description": "Phantom Wallet SDK for React Native and Expo applications",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -45,14 +45,14 @@
45
45
  "directory": "packages/react-native-sdk"
46
46
  },
47
47
  "dependencies": {
48
- "@phantom/api-key-stamper": "^1.0.0-beta.1",
49
- "@phantom/base64url": "^1.0.0-beta.1",
50
- "@phantom/chains": "^1.0.0-beta.1",
51
- "@phantom/client": "^1.0.0-beta.1",
52
- "@phantom/constants": "^1.0.0-beta.1",
53
- "@phantom/crypto": "^1.0.0-beta.1",
54
- "@phantom/embedded-provider-core": "^1.0.0-beta.1",
55
- "@phantom/sdk-types": "^1.0.0-beta.1",
48
+ "@phantom/api-key-stamper": "^1.0.0-beta.3",
49
+ "@phantom/base64url": "^1.0.0-beta.3",
50
+ "@phantom/chains": "^1.0.0-beta.3",
51
+ "@phantom/client": "^1.0.0-beta.3",
52
+ "@phantom/constants": "^1.0.0-beta.3",
53
+ "@phantom/crypto": "^1.0.0-beta.3",
54
+ "@phantom/embedded-provider-core": "^1.0.0-beta.3",
55
+ "@phantom/sdk-types": "^1.0.0-beta.3",
56
56
  "@types/bs58": "^5.0.0",
57
57
  "bs58": "^6.0.0",
58
58
  "buffer": "^6.0.3"