@phantom/react-native-sdk 1.0.0-beta.2 → 1.0.0-beta.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
@@ -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,16 +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 a transaction (without sending)
251
- const signedTx = await solana.signTransaction(transaction);
254
+ // Sign a transaction (without sending)
255
+ const signedTx = await solana.signTransaction(transaction);
252
256
 
253
- // Sign and send a transaction
254
- const result = await solana.signAndSendTransaction(transaction);
257
+ // Sign and send a transaction
258
+ const result = await solana.signAndSendTransaction(transaction);
259
+ }
255
260
  ```
256
261
 
257
262
  #### useEthereum
@@ -259,22 +264,24 @@ const result = await solana.signAndSendTransaction(transaction);
259
264
  Provides access to Ethereum-specific operations.
260
265
 
261
266
  ```typescript
262
- const ethereum = useEthereum();
267
+ const { ethereum, isAvailable } = useEthereum();
263
268
 
264
- // Get accounts
265
- const accounts = await ethereum.getAccounts();
269
+ if (isAvailable) {
270
+ // Get accounts
271
+ const accounts = await ethereum.getAccounts();
266
272
 
267
- // Sign a personal message
268
- const signature = await ethereum.signPersonalMessage("Hello Ethereum!", accounts[0]);
273
+ // Sign a personal message
274
+ const signature = await ethereum.signPersonalMessage("Hello Ethereum!", accounts[0]);
269
275
 
270
- // Sign a transaction (without sending)
271
- const signedTx = await ethereum.signTransaction(transactionData);
276
+ // Sign a transaction (without sending)
277
+ const signedTx = await ethereum.signTransaction(transactionData);
272
278
 
273
- // Sign and send a transaction
274
- const result = await ethereum.sendTransaction(transactionData);
279
+ // Sign and send a transaction
280
+ const result = await ethereum.sendTransaction(transactionData);
275
281
 
276
- // Get current chain ID
277
- const chainId = await ethereum.getChainId();
282
+ // Get current chain ID
283
+ const chainId = await ethereum.getChainId();
284
+ }
278
285
  ```
279
286
 
280
287
  #### useDisconnect
@@ -336,11 +343,9 @@ import { PhantomProvider, AddressType } from "@phantom/react-native-sdk";
336
343
 
337
344
  <PhantomProvider
338
345
  config={{
339
- appId: "app_123456789",
346
+ appId: "your-app-id",
340
347
  scheme: "myapp",
341
- embeddedWalletType: "user-wallet",
342
348
  addressTypes: [AddressType.solana],
343
- apiBaseUrl: "https://api.phantom.app/v1/wallets",
344
349
  }}
345
350
  >
346
351
  <App />
@@ -354,14 +359,10 @@ import { PhantomProvider, AddressType } from "@phantom/react-native-sdk";
354
359
 
355
360
  <PhantomProvider
356
361
  config={{
357
- appId: "app_123456789",
362
+ appId: "your-app-id",
358
363
  scheme: "mycompany-wallet",
359
- embeddedWalletType: "user-wallet",
360
364
  addressTypes: [AddressType.solana, AddressType.ethereum],
361
- apiBaseUrl: "https://api.phantom.app/v1/wallets",
362
- solanaProvider: "web3js",
363
365
  authOptions: {
364
- authUrl: "https://connect.phantom.app",
365
366
  redirectUrl: "mycompany-wallet://auth/success",
366
367
  },
367
368
  }}
@@ -395,13 +396,9 @@ import { PhantomProvider, AddressType } from '@phantom/react-native-sdk';
395
396
  const testConfig = {
396
397
  appId: "test-app",
397
398
  scheme: "testapp",
398
- embeddedWalletType: "app-wallet" as const,
399
399
  addressTypes: [AddressType.solana],
400
- apiBaseUrl: "https://api.phantom.app/v1/wallets",
401
-
402
400
  };
403
401
 
404
- // Use app-wallet for testing (no OAuth required)
405
402
  <PhantomProvider config={testConfig}>
406
403
  <TestApp />
407
404
  </PhantomProvider>
@@ -450,6 +447,7 @@ import { PhantomProvider, type PhantomSDKConfig, type PhantomDebugConfig } from
450
447
  function App() {
451
448
  // SDK configuration - static, won't change when debug settings change
452
449
  const config: PhantomSDKConfig = {
450
+ appId: "your-app-id",
453
451
  scheme: "mywalletapp",
454
452
  // ... other config
455
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,51 +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
- signTransaction: (transaction: EthTransactionRequest) => Promise<string>;
105
- signTypedData: (typedData: any) => Promise<string>;
106
- sendTransaction: (transaction: EthTransactionRequest) => Promise<string>;
107
- switchChain: (chainId: number) => Promise<void>;
108
- getChainId: () => Promise<number>;
109
- getAccounts: () => Promise<string[]>;
84
+ ethereum: _phantom_chains.IEthereumChain;
110
85
  isAvailable: boolean;
111
- isConnected: boolean;
112
86
  };
113
87
 
114
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.4"
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,190 +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 getSolanaChain = (0, import_react4.useCallback)(() => {
635
- if (!sdk)
636
- throw new Error("Phantom SDK not initialized.");
637
- if (!sdk.isConnected())
638
- throw new Error("Phantom SDK not connected. Call connect() first.");
639
- return sdk.solana;
640
- }, [sdk]);
641
- const solanaChain = (0, import_react4.useMemo)(() => {
642
- if (!sdk || !isConnected)
643
- return null;
644
- try {
645
- return sdk.solana;
646
- } catch {
647
- return null;
648
- }
649
- }, [sdk, isConnected]);
650
- const signMessage = (0, import_react4.useCallback)(
651
- async (message) => {
652
- const chain = getSolanaChain();
653
- return await chain.signMessage(message);
654
- },
655
- [getSolanaChain]
656
- );
657
- const signTransaction = (0, import_react4.useCallback)(
658
- async (transaction) => {
659
- const chain = getSolanaChain();
660
- return await chain.signTransaction(transaction);
661
- },
662
- [getSolanaChain]
663
- );
664
- const signAndSendTransaction = (0, import_react4.useCallback)(
665
- async (transaction) => {
666
- const chain = getSolanaChain();
667
- return await chain.signAndSendTransaction(transaction);
668
- },
669
- [getSolanaChain]
670
- );
671
- const connect = (0, import_react4.useCallback)(
672
- async (options) => {
673
- const chain = getSolanaChain();
674
- return await chain.connect(options);
675
- },
676
- [getSolanaChain]
677
- );
678
- const disconnect = (0, import_react4.useCallback)(async () => {
679
- const chain = getSolanaChain();
680
- return await chain.disconnect();
681
- }, [getSolanaChain]);
682
- const switchNetwork = (0, import_react4.useCallback)(
683
- async (network) => {
684
- const chain = getSolanaChain();
685
- return await chain.switchNetwork?.(network);
686
- },
687
- [getSolanaChain]
688
- );
689
- const getPublicKey = (0, import_react4.useCallback)(async () => {
690
- if (!sdk || !sdk.isConnected())
691
- return null;
692
- return await sdk.solana.getPublicKey();
693
- }, [sdk]);
694
645
  return {
695
- // Chain instance for advanced usage
696
- solana: solanaChain,
697
- // Convenient methods
698
- signMessage,
699
- signTransaction,
700
- signAndSendTransaction,
701
- connect,
702
- disconnect,
703
- switchNetwork,
704
- getPublicKey,
646
+ // Chain instance with connection enforcement for signing methods
647
+ solana: sdk.solana,
705
648
  // State
706
- isAvailable: !!solanaChain,
707
- isConnected: solanaChain?.isConnected() ?? false
649
+ isAvailable: !!isConnected
708
650
  };
709
651
  }
710
652
 
711
653
  // src/hooks/useEthereum.ts
712
- var import_react5 = require("react");
713
654
  function useEthereum() {
714
655
  const { sdk, isConnected } = usePhantom();
715
- const getEthereumChain = (0, import_react5.useCallback)(() => {
716
- if (!sdk)
717
- throw new Error("Phantom SDK not initialized.");
718
- if (!sdk.isConnected())
719
- throw new Error("Phantom SDK not connected. Call connect() first.");
720
- return sdk.ethereum;
721
- }, [sdk]);
722
- const ethereumChain = (0, import_react5.useMemo)(() => {
723
- if (!sdk || !isConnected)
724
- return null;
725
- try {
726
- return sdk.ethereum;
727
- } catch {
728
- return null;
729
- }
730
- }, [sdk, isConnected]);
731
- const request = (0, import_react5.useCallback)(
732
- async (args) => {
733
- const chain = getEthereumChain();
734
- return await chain.request(args);
735
- },
736
- [getEthereumChain]
737
- );
738
- const signPersonalMessage = (0, import_react5.useCallback)(
739
- async (message, address) => {
740
- const chain = getEthereumChain();
741
- return await chain.signPersonalMessage(message, address);
742
- },
743
- [getEthereumChain]
744
- );
745
- const signTransaction = (0, import_react5.useCallback)(
746
- async (transaction) => {
747
- const chain = getEthereumChain();
748
- return await chain.signTransaction(transaction);
749
- },
750
- [getEthereumChain]
751
- );
752
- const sendTransaction = (0, import_react5.useCallback)(
753
- async (transaction) => {
754
- const chain = getEthereumChain();
755
- return await chain.sendTransaction(transaction);
756
- },
757
- [getEthereumChain]
758
- );
759
- const switchChain = (0, import_react5.useCallback)(
760
- async (chainId) => {
761
- const chain = getEthereumChain();
762
- return await chain.switchChain(chainId);
763
- },
764
- [getEthereumChain]
765
- );
766
- const getChainId = (0, import_react5.useCallback)(async () => {
767
- const chain = getEthereumChain();
768
- return await chain.getChainId();
769
- }, [getEthereumChain]);
770
- const getAccounts = (0, import_react5.useCallback)(async () => {
771
- const chain = getEthereumChain();
772
- return await chain.getAccounts();
773
- }, [getEthereumChain]);
774
- const signMessage = (0, import_react5.useCallback)(
775
- async (message) => {
776
- const accounts = await getAccounts();
777
- return await request({
778
- method: "eth_sign",
779
- params: [accounts[0], message]
780
- });
781
- },
782
- [request, getAccounts]
783
- );
784
- const signTypedData = (0, import_react5.useCallback)(
785
- async (typedData) => {
786
- const chain = getEthereumChain();
787
- const accounts = await getAccounts();
788
- return await chain.signTypedData(typedData, accounts[0]);
789
- },
790
- [getEthereumChain, getAccounts]
791
- );
792
656
  return {
793
- // Chain instance for advanced usage
794
- ethereum: ethereumChain,
795
- // Standard EIP-1193 interface
796
- request,
797
- // Convenient methods
798
- signPersonalMessage,
799
- signMessage,
800
- signTransaction,
801
- signTypedData,
802
- sendTransaction,
803
- switchChain,
804
- getChainId,
805
- getAccounts,
657
+ // Chain instance with connection enforcement for signing methods
658
+ ethereum: sdk.ethereum,
806
659
  // State
807
- isAvailable: !!ethereumChain,
808
- isConnected: ethereumChain?.isConnected() ?? false
660
+ isAvailable: !!isConnected
809
661
  };
810
662
  }
811
663
 
812
664
  // src/index.ts
813
665
  var import_client = require("@phantom/client");
814
- var import_constants = require("@phantom/constants");
666
+ var import_constants3 = require("@phantom/constants");
815
667
  // Annotate the CommonJS export names for ESM import in node:
816
668
  0 && (module.exports = {
817
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.4"
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,184 +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 getSolanaChain = useCallback3(() => {
591
- if (!sdk)
592
- throw new Error("Phantom SDK not initialized.");
593
- if (!sdk.isConnected())
594
- throw new Error("Phantom SDK not connected. Call connect() first.");
595
- return sdk.solana;
596
- }, [sdk]);
597
- const solanaChain = useMemo2(() => {
598
- if (!sdk || !isConnected)
599
- return null;
600
- try {
601
- return sdk.solana;
602
- } catch {
603
- return null;
604
- }
605
- }, [sdk, isConnected]);
606
- const signMessage = useCallback3(
607
- async (message) => {
608
- const chain = getSolanaChain();
609
- return await chain.signMessage(message);
610
- },
611
- [getSolanaChain]
612
- );
613
- const signTransaction = useCallback3(
614
- async (transaction) => {
615
- const chain = getSolanaChain();
616
- return await chain.signTransaction(transaction);
617
- },
618
- [getSolanaChain]
619
- );
620
- const signAndSendTransaction = useCallback3(
621
- async (transaction) => {
622
- const chain = getSolanaChain();
623
- return await chain.signAndSendTransaction(transaction);
624
- },
625
- [getSolanaChain]
626
- );
627
- const connect = useCallback3(
628
- async (options) => {
629
- const chain = getSolanaChain();
630
- return await chain.connect(options);
631
- },
632
- [getSolanaChain]
633
- );
634
- const disconnect = useCallback3(async () => {
635
- const chain = getSolanaChain();
636
- return await chain.disconnect();
637
- }, [getSolanaChain]);
638
- const switchNetwork = useCallback3(
639
- async (network) => {
640
- const chain = getSolanaChain();
641
- return await chain.switchNetwork?.(network);
642
- },
643
- [getSolanaChain]
644
- );
645
- const getPublicKey = useCallback3(async () => {
646
- if (!sdk || !sdk.isConnected())
647
- return null;
648
- return await sdk.solana.getPublicKey();
649
- }, [sdk]);
650
601
  return {
651
- // Chain instance for advanced usage
652
- solana: solanaChain,
653
- // Convenient methods
654
- signMessage,
655
- signTransaction,
656
- signAndSendTransaction,
657
- connect,
658
- disconnect,
659
- switchNetwork,
660
- getPublicKey,
602
+ // Chain instance with connection enforcement for signing methods
603
+ solana: sdk.solana,
661
604
  // State
662
- isAvailable: !!solanaChain,
663
- isConnected: solanaChain?.isConnected() ?? false
605
+ isAvailable: !!isConnected
664
606
  };
665
607
  }
666
608
 
667
609
  // src/hooks/useEthereum.ts
668
- import { useCallback as useCallback4, useMemo as useMemo3 } from "react";
669
610
  function useEthereum() {
670
611
  const { sdk, isConnected } = usePhantom();
671
- const getEthereumChain = useCallback4(() => {
672
- if (!sdk)
673
- throw new Error("Phantom SDK not initialized.");
674
- if (!sdk.isConnected())
675
- throw new Error("Phantom SDK not connected. Call connect() first.");
676
- return sdk.ethereum;
677
- }, [sdk]);
678
- const ethereumChain = useMemo3(() => {
679
- if (!sdk || !isConnected)
680
- return null;
681
- try {
682
- return sdk.ethereum;
683
- } catch {
684
- return null;
685
- }
686
- }, [sdk, isConnected]);
687
- const request = useCallback4(
688
- async (args) => {
689
- const chain = getEthereumChain();
690
- return await chain.request(args);
691
- },
692
- [getEthereumChain]
693
- );
694
- const signPersonalMessage = useCallback4(
695
- async (message, address) => {
696
- const chain = getEthereumChain();
697
- return await chain.signPersonalMessage(message, address);
698
- },
699
- [getEthereumChain]
700
- );
701
- const signTransaction = useCallback4(
702
- async (transaction) => {
703
- const chain = getEthereumChain();
704
- return await chain.signTransaction(transaction);
705
- },
706
- [getEthereumChain]
707
- );
708
- const sendTransaction = useCallback4(
709
- async (transaction) => {
710
- const chain = getEthereumChain();
711
- return await chain.sendTransaction(transaction);
712
- },
713
- [getEthereumChain]
714
- );
715
- const switchChain = useCallback4(
716
- async (chainId) => {
717
- const chain = getEthereumChain();
718
- return await chain.switchChain(chainId);
719
- },
720
- [getEthereumChain]
721
- );
722
- const getChainId = useCallback4(async () => {
723
- const chain = getEthereumChain();
724
- return await chain.getChainId();
725
- }, [getEthereumChain]);
726
- const getAccounts = useCallback4(async () => {
727
- const chain = getEthereumChain();
728
- return await chain.getAccounts();
729
- }, [getEthereumChain]);
730
- const signMessage = useCallback4(
731
- async (message) => {
732
- const accounts = await getAccounts();
733
- return await request({
734
- method: "eth_sign",
735
- params: [accounts[0], message]
736
- });
737
- },
738
- [request, getAccounts]
739
- );
740
- const signTypedData = useCallback4(
741
- async (typedData) => {
742
- const chain = getEthereumChain();
743
- const accounts = await getAccounts();
744
- return await chain.signTypedData(typedData, accounts[0]);
745
- },
746
- [getEthereumChain, getAccounts]
747
- );
748
612
  return {
749
- // Chain instance for advanced usage
750
- ethereum: ethereumChain,
751
- // Standard EIP-1193 interface
752
- request,
753
- // Convenient methods
754
- signPersonalMessage,
755
- signMessage,
756
- signTransaction,
757
- signTypedData,
758
- sendTransaction,
759
- switchChain,
760
- getChainId,
761
- getAccounts,
613
+ // Chain instance with connection enforcement for signing methods
614
+ ethereum: sdk.ethereum,
762
615
  // State
763
- isAvailable: !!ethereumChain,
764
- isConnected: ethereumChain?.isConnected() ?? false
616
+ isAvailable: !!isConnected
765
617
  };
766
618
  }
767
619
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/react-native-sdk",
3
- "version": "1.0.0-beta.2",
3
+ "version": "1.0.0-beta.4",
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.2",
49
- "@phantom/base64url": "^1.0.0-beta.2",
50
- "@phantom/chains": "^1.0.0-beta.2",
51
- "@phantom/client": "^1.0.0-beta.2",
52
- "@phantom/constants": "^1.0.0-beta.2",
53
- "@phantom/crypto": "^1.0.0-beta.2",
54
- "@phantom/embedded-provider-core": "^1.0.0-beta.2",
55
- "@phantom/sdk-types": "^1.0.0-beta.2",
48
+ "@phantom/api-key-stamper": "^1.0.0-beta.4",
49
+ "@phantom/base64url": "^1.0.0-beta.4",
50
+ "@phantom/chains": "^1.0.0-beta.4",
51
+ "@phantom/client": "^1.0.0-beta.4",
52
+ "@phantom/constants": "^1.0.0-beta.4",
53
+ "@phantom/crypto": "^1.0.0-beta.4",
54
+ "@phantom/embedded-provider-core": "^1.0.0-beta.4",
55
+ "@phantom/sdk-types": "^1.0.0-beta.4",
56
56
  "@types/bs58": "^5.0.0",
57
57
  "bs58": "^6.0.0",
58
58
  "buffer": "^6.0.3"