@phantom/react-native-sdk 1.0.0-beta.0 → 1.0.0-beta.10

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,16 +89,12 @@ export default function App() {
89
89
  return (
90
90
  <PhantomProvider
91
91
  config={{
92
- organizationId: "your-organization-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
  },
101
- appName: "My Wallet App", // Optional branding
102
98
  }}
103
99
  >
104
100
  <YourAppContent />
@@ -133,8 +129,10 @@ export function WalletScreen() {
133
129
 
134
130
  const handleSignSolanaMessage = async () => {
135
131
  try {
136
- const signature = await solana.signMessage("Hello from Solana!");
137
- 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
+ }
138
136
  } catch (error) {
139
137
  Alert.alert("Error", `Failed to sign: ${error.message}`);
140
138
  }
@@ -142,9 +140,11 @@ export function WalletScreen() {
142
140
 
143
141
  const handleSignEthereumMessage = async () => {
144
142
  try {
145
- const accounts = await ethereum.getAccounts();
146
- const signature = await ethereum.signPersonalMessage("Hello from Ethereum!", accounts[0]);
147
- 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
+ }
148
148
  } catch (error) {
149
149
  Alert.alert("Error", `Failed to sign: ${error.message}`);
150
150
  }
@@ -172,17 +172,9 @@ export function WalletScreen() {
172
172
  </Text>
173
173
  ))}
174
174
 
175
- <Button
176
- title="Sign Solana Message"
177
- onPress={handleSignSolanaMessage}
178
- style={{ marginTop: 10 }}
179
- />
175
+ <Button title="Sign Solana Message" onPress={handleSignSolanaMessage} style={{ marginTop: 10 }} />
180
176
 
181
- <Button
182
- title="Sign Ethereum Message"
183
- onPress={handleSignEthereumMessage}
184
- style={{ marginTop: 10 }}
185
- />
177
+ <Button title="Sign Ethereum Message" onPress={handleSignEthereumMessage} style={{ marginTop: 10 }} />
186
178
 
187
179
  <Button title="Disconnect" onPress={disconnect} style={{ marginTop: 10 }} />
188
180
  </View>
@@ -206,19 +198,18 @@ The main provider component that initializes the SDK and provides context to all
206
198
 
207
199
  ```typescript
208
200
  interface PhantomSDKConfig {
209
- organizationId: string; // Your Phantom organization ID
210
201
  scheme: string; // Custom URL scheme for your app
211
- embeddedWalletType: "user-wallet" | "app-wallet";
202
+ appId: string; // Your app ID from phantom.com/portal (required)
212
203
  addressTypes: [AddressType, ...AddressType[]]; // e.g., [AddressType.solana]
213
- apiBaseUrl: string; // e.g., "https://api.phantom.app/v1/wallets"
214
- 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)
215
208
  authOptions?: {
216
209
  authUrl?: string; // Custom auth URL (optional)
217
210
  redirectUrl?: string; // Custom redirect URL (optional)
218
211
  };
219
- appName?: string; // Optional app name for branding
220
- appLogo?: string; // Optional app logo URL for branding
221
- 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)
222
213
  }
223
214
  ```
224
215
 
@@ -254,13 +245,18 @@ const {
254
245
  Provides access to Solana-specific operations.
255
246
 
256
247
  ```typescript
257
- const solana = useSolana();
248
+ const { solana, isAvailable } = useSolana();
258
249
 
259
- // Sign a message
260
- const signature = await solana.signMessage("Hello Solana!");
250
+ if (isAvailable) {
251
+ // Sign a message
252
+ const signature = await solana.signMessage("Hello Solana!");
261
253
 
262
- // Sign and send a transaction
263
- 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
+ }
264
260
  ```
265
261
 
266
262
  #### useEthereum
@@ -268,19 +264,24 @@ const result = await solana.signAndSendTransaction(transaction);
268
264
  Provides access to Ethereum-specific operations.
269
265
 
270
266
  ```typescript
271
- const ethereum = useEthereum();
267
+ const { ethereum, isAvailable } = useEthereum();
268
+
269
+ if (isAvailable) {
270
+ // Get accounts
271
+ const accounts = await ethereum.getAccounts();
272
272
 
273
- // Get accounts
274
- const accounts = await ethereum.getAccounts();
273
+ // Sign a personal message
274
+ const signature = await ethereum.signPersonalMessage("Hello Ethereum!", accounts[0]);
275
275
 
276
- // Sign a personal message
277
- const signature = await ethereum.signPersonalMessage("Hello Ethereum!", accounts[0]);
276
+ // Sign a transaction (without sending)
277
+ const signedTx = await ethereum.signTransaction(transactionData);
278
278
 
279
- // Send a transaction
280
- const result = await ethereum.sendTransaction(transactionData);
279
+ // Sign and send a transaction
280
+ const result = await ethereum.sendTransaction(transactionData);
281
281
 
282
- // Get current chain ID
283
- const chainId = await ethereum.getChainId();
282
+ // Get current chain ID
283
+ const chainId = await ethereum.getChainId();
284
+ }
284
285
  ```
285
286
 
286
287
  #### useDisconnect
@@ -342,11 +343,9 @@ import { PhantomProvider, AddressType } from "@phantom/react-native-sdk";
342
343
 
343
344
  <PhantomProvider
344
345
  config={{
345
- organizationId: "org_123456789",
346
+ appId: "your-app-id",
346
347
  scheme: "myapp",
347
- embeddedWalletType: "user-wallet",
348
348
  addressTypes: [AddressType.solana],
349
- apiBaseUrl: "https://api.phantom.app/v1/wallets",
350
349
  }}
351
350
  >
352
351
  <App />
@@ -360,14 +359,10 @@ import { PhantomProvider, AddressType } from "@phantom/react-native-sdk";
360
359
 
361
360
  <PhantomProvider
362
361
  config={{
363
- organizationId: "org_123456789",
362
+ appId: "your-app-id",
364
363
  scheme: "mycompany-wallet",
365
- embeddedWalletType: "user-wallet",
366
364
  addressTypes: [AddressType.solana, AddressType.ethereum],
367
- apiBaseUrl: "https://api.phantom.app/v1/wallets",
368
- solanaProvider: "web3js",
369
365
  authOptions: {
370
- authUrl: "https://connect.phantom.app",
371
366
  redirectUrl: "mycompany-wallet://auth/success",
372
367
  },
373
368
  }}
@@ -399,15 +394,11 @@ import { PhantomProvider, AddressType } from "@phantom/react-native-sdk";
399
394
  import { PhantomProvider, AddressType } from '@phantom/react-native-sdk';
400
395
 
401
396
  const testConfig = {
402
- organizationId: "test-org",
397
+ appId: "test-app",
403
398
  scheme: "testapp",
404
- embeddedWalletType: "app-wallet" as const,
405
399
  addressTypes: [AddressType.solana],
406
- apiBaseUrl: "https://api.phantom.app/v1/wallets",
407
-
408
400
  };
409
401
 
410
- // Use app-wallet for testing (no OAuth required)
411
402
  <PhantomProvider config={testConfig}>
412
403
  <TestApp />
413
404
  </PhantomProvider>
@@ -432,7 +423,7 @@ adb shell am start -W -a android.intent.action.VIEW -d "myapp://phantom-auth-cal
432
423
  - Check `app.json` (Expo) or platform-specific configuration
433
424
 
434
425
  2. **"Authentication failed"**
435
- - Verify your organization ID is correct
426
+ - Verify your app ID is correct
436
427
  - Check network connectivity
437
428
  - Ensure redirect URL matches your scheme
438
429
 
@@ -456,7 +447,7 @@ import { PhantomProvider, type PhantomSDKConfig, type PhantomDebugConfig } from
456
447
  function App() {
457
448
  // SDK configuration - static, won't change when debug settings change
458
449
  const config: PhantomSDKConfig = {
459
- organizationId: "your-org-id",
450
+ appId: "your-app-id",
460
451
  scheme: "mywalletapp",
461
452
  // ... other config
462
453
  };
package/dist/index.d.ts CHANGED
@@ -3,8 +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';
7
- import { ParsedSignatureResult, ParsedTransactionResult } from '@phantom/parsers';
6
+ import * as _phantom_chain_interfaces from '@phantom/chain-interfaces';
8
7
  export { AddressType } from '@phantom/client';
9
8
  export { NetworkId } from '@phantom/constants';
10
9
 
@@ -12,11 +11,19 @@ interface PhantomDebugConfig {
12
11
  /** Enable debug logging */
13
12
  enabled?: boolean;
14
13
  }
15
- interface PhantomSDKConfig extends EmbeddedProviderConfig {
14
+ interface PhantomSDKConfig extends Omit<EmbeddedProviderConfig, "apiBaseUrl" | "embeddedWalletType" | "authOptions"> {
16
15
  /** Custom URL scheme for your app (e.g., "myapp") */
17
16
  scheme: string;
18
17
  /** Enable auto-connect to existing sessions (default: true) */
19
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";
23
+ authOptions?: {
24
+ authUrl?: string;
25
+ redirectUrl?: string;
26
+ };
20
27
  }
21
28
  interface ConnectOptions {
22
29
  /** OAuth provider to use */
@@ -28,7 +35,7 @@ interface ConnectOptions {
28
35
  }
29
36
 
30
37
  interface PhantomContextValue {
31
- sdk: EmbeddedProvider | null;
38
+ sdk: EmbeddedProvider;
32
39
  isConnected: boolean;
33
40
  isConnecting: boolean;
34
41
  connectError: Error | null;
@@ -65,45 +72,21 @@ declare function useAccounts(): {
65
72
  /**
66
73
  * Hook for Solana chain operations in React Native
67
74
  *
68
- * @returns Solana chain interface and convenient methods
75
+ * @returns Solana chain interface with connection enforcement
69
76
  */
70
77
  declare function useSolana(): {
71
- solana: ISolanaChain | null;
72
- signMessage: (message: string | Uint8Array) => Promise<ParsedSignatureResult>;
73
- signTransaction: <T>(transaction: T) => Promise<T>;
74
- signAndSendTransaction: <T>(transaction: T) => Promise<ParsedTransactionResult>;
75
- connect: (options?: {
76
- onlyIfTrusted?: boolean;
77
- }) => Promise<{
78
- publicKey: string;
79
- }>;
80
- disconnect: () => Promise<void>;
81
- switchNetwork: (network: "mainnet" | "devnet") => Promise<void>;
82
- getPublicKey: () => Promise<string | null>;
78
+ solana: _phantom_chain_interfaces.ISolanaChain;
83
79
  isAvailable: boolean;
84
- isConnected: boolean;
85
80
  };
86
81
 
87
82
  /**
88
83
  * Hook for Ethereum chain operations in React Native
89
84
  *
90
- * @returns Ethereum chain interface and convenient methods
85
+ * @returns Ethereum chain interface with connection enforcement
91
86
  */
92
87
  declare function useEthereum(): {
93
- ethereum: IEthereumChain | null;
94
- request: <T = any>(args: {
95
- method: string;
96
- params?: unknown[];
97
- }) => Promise<T>;
98
- signPersonalMessage: (message: string, address: string) => Promise<ParsedSignatureResult>;
99
- signMessage: (message: string) => Promise<string>;
100
- signTypedData: (typedData: any) => Promise<ParsedSignatureResult>;
101
- sendTransaction: (transaction: EthTransactionRequest) => Promise<ParsedTransactionResult>;
102
- switchChain: (chainId: number) => Promise<void>;
103
- getChainId: () => Promise<number>;
104
- getAccounts: () => Promise<string[]>;
88
+ ethereum: _phantom_chain_interfaces.IEthereumChain;
105
89
  isAvailable: boolean;
106
- isConnected: boolean;
107
90
  };
108
91
 
109
92
  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,42 +97,29 @@ 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) {
103
104
  return;
104
105
  }
105
106
  const phantomOptions = options;
106
- const {
107
- authUrl,
108
- redirectUrl,
109
- organizationId,
110
- parentOrganizationId,
111
- sessionId,
112
- provider,
113
- customAuthData,
114
- appName,
115
- appLogo
116
- } = phantomOptions;
107
+ const { authUrl, redirectUrl, organizationId, sessionId, provider, customAuthData, appId } = phantomOptions;
117
108
  if (!redirectUrl) {
118
109
  throw new Error("redirectUrl is required for web browser authentication");
119
110
  }
120
- if (!organizationId || !sessionId) {
121
- throw new Error("organizationId and sessionId are required for authentication");
111
+ if (!organizationId || !sessionId || !appId) {
112
+ throw new Error("organizationId, sessionId and appId are required for authentication");
122
113
  }
123
114
  try {
124
- const baseUrl = authUrl || DEFAULT_AUTH_URL;
115
+ const baseUrl = authUrl || import_constants.DEFAULT_AUTH_URL;
125
116
  const params = new URLSearchParams({
126
117
  organization_id: organizationId,
127
- parent_organization_id: parentOrganizationId,
118
+ app_id: appId,
128
119
  redirect_uri: redirectUrl,
129
120
  session_id: sessionId,
130
121
  clear_previous_session: "true",
131
- app_name: appName || "",
132
- // Optional app name
133
- app_logo: appLogo || ""
134
- // Optional app logo URL
122
+ sdk_version: "1.0.0-beta.10"
135
123
  });
136
124
  if (provider) {
137
125
  console.log("[ExpoAuthProvider] Provider specified, will skip selection", { provider });
@@ -149,7 +137,6 @@ var ExpoAuthProvider = class {
149
137
  baseUrl,
150
138
  redirectUrl,
151
139
  organizationId,
152
- parentOrganizationId,
153
140
  sessionId,
154
141
  provider,
155
142
  hasCustomData: !!customAuthData
@@ -275,7 +262,7 @@ var ReactNativeStamper = class {
275
262
  this.algorithm = import_sdk_types.Algorithm.ed25519;
276
263
  this.type = "PKI";
277
264
  this.keyPrefix = config.keyPrefix || "phantom-rn-stamper";
278
- this.organizationId = config.organizationId || "default";
265
+ this.appId = config.appId || "default";
279
266
  }
280
267
  /**
281
268
  * Initialize the stamper and generate/load cryptographic keys
@@ -428,10 +415,10 @@ var ReactNativeStamper = class {
428
415
  return null;
429
416
  }
430
417
  getActiveKeyName() {
431
- return `${this.keyPrefix}-${this.organizationId}-active`;
418
+ return `${this.keyPrefix}-${this.appId}-active`;
432
419
  }
433
420
  getPendingKeyName() {
434
- return `${this.keyPrefix}-${this.organizationId}-pending`;
421
+ return `${this.keyPrefix}-${this.appId}-pending`;
435
422
  }
436
423
  };
437
424
 
@@ -472,34 +459,48 @@ function PhantomProvider({ children, config, debugConfig }) {
472
459
  const [connectError, setConnectError] = (0, import_react.useState)(null);
473
460
  const [addresses, setAddresses] = (0, import_react.useState)([]);
474
461
  const [walletId, setWalletId] = (0, import_react.useState)(null);
475
- const [sdk, setSdk] = (0, import_react.useState)(null);
476
462
  const memoizedConfig = (0, import_react.useMemo)(() => {
477
463
  const redirectUrl = config.authOptions?.redirectUrl || `${config.scheme}://phantom-auth-callback`;
478
464
  return {
479
465
  ...config,
466
+ apiBaseUrl: config.apiBaseUrl || import_constants2.DEFAULT_WALLET_API_URL,
467
+ embeddedWalletType: config.embeddedWalletType || import_constants2.DEFAULT_EMBEDDED_WALLET_TYPE,
480
468
  authOptions: {
481
469
  ...config.authOptions || {},
482
- redirectUrl
470
+ redirectUrl,
471
+ authUrl: config.authOptions?.authUrl || import_constants2.DEFAULT_AUTH_URL
483
472
  }
484
473
  };
485
474
  }, [config]);
486
- (0, import_react.useEffect)(() => {
475
+ const sdk = (0, import_react.useMemo)(() => {
487
476
  const storage = new ExpoSecureStorage();
488
477
  const authProvider = new ExpoAuthProvider();
489
478
  const urlParamsAccessor = new ExpoURLParamsAccessor();
490
479
  const logger = new ExpoLogger(debugConfig?.enabled || false);
491
480
  const stamper = new ReactNativeStamper({
492
- keyPrefix: `phantom-rn-${memoizedConfig.organizationId}`,
493
- organizationId: memoizedConfig.organizationId
481
+ keyPrefix: `phantom-rn-${memoizedConfig.appId}`,
482
+ appId: memoizedConfig.appId
494
483
  });
484
+ const platformName = `${import_react_native2.Platform.OS}-${import_react_native2.Platform.Version}`;
495
485
  const platform = {
496
486
  storage,
497
487
  authProvider,
498
488
  urlParamsAccessor,
499
489
  stamper,
500
- name: `${import_react_native2.Platform.OS}-${import_react_native2.Platform.Version}`
490
+ name: platformName,
491
+ analyticsHeaders: {
492
+ [import_constants2.ANALYTICS_HEADERS.SDK_TYPE]: "react-native",
493
+ [import_constants2.ANALYTICS_HEADERS.PLATFORM]: import_react_native2.Platform.OS,
494
+ [import_constants2.ANALYTICS_HEADERS.PLATFORM_VERSION]: `${import_react_native2.Platform.Version}`,
495
+ [import_constants2.ANALYTICS_HEADERS.APP_ID]: config.appId,
496
+ [import_constants2.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
497
+ [import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.10"
498
+ // Replaced at build time
499
+ }
501
500
  };
502
- const sdkInstance = new import_embedded_provider_core.EmbeddedProvider(memoizedConfig, platform, logger);
501
+ return new import_embedded_provider_core.EmbeddedProvider(memoizedConfig, platform, logger);
502
+ }, [memoizedConfig, debugConfig, config.appId, config.embeddedWalletType]);
503
+ (0, import_react.useEffect)(() => {
503
504
  const handleConnectStart = () => {
504
505
  setIsConnecting(true);
505
506
  setConnectError(null);
@@ -508,12 +509,12 @@ function PhantomProvider({ children, config, debugConfig }) {
508
509
  try {
509
510
  setIsConnected(true);
510
511
  setIsConnecting(false);
511
- const addrs = await sdkInstance.getAddresses();
512
+ const addrs = await sdk.getAddresses();
512
513
  setAddresses(addrs);
513
514
  } catch (err) {
514
515
  console.error("Error connecting:", err);
515
516
  try {
516
- await sdkInstance.disconnect();
517
+ await sdk.disconnect();
517
518
  } catch (err2) {
518
519
  console.error("Error disconnecting:", err2);
519
520
  }
@@ -530,21 +531,18 @@ function PhantomProvider({ children, config, debugConfig }) {
530
531
  setAddresses([]);
531
532
  setWalletId(null);
532
533
  };
533
- sdkInstance.on("connect_start", handleConnectStart);
534
- sdkInstance.on("connect", handleConnect);
535
- sdkInstance.on("connect_error", handleConnectError);
536
- sdkInstance.on("disconnect", handleDisconnect);
537
- setSdk(sdkInstance);
534
+ sdk.on("connect_start", handleConnectStart);
535
+ sdk.on("connect", handleConnect);
536
+ sdk.on("connect_error", handleConnectError);
537
+ sdk.on("disconnect", handleDisconnect);
538
538
  return () => {
539
- sdkInstance.off("connect_start", handleConnectStart);
540
- sdkInstance.off("connect", handleConnect);
541
- sdkInstance.off("connect_error", handleConnectError);
542
- sdkInstance.off("disconnect", handleDisconnect);
539
+ sdk.off("connect_start", handleConnectStart);
540
+ sdk.off("connect", handleConnect);
541
+ sdk.off("connect_error", handleConnectError);
542
+ sdk.off("disconnect", handleDisconnect);
543
543
  };
544
- }, [memoizedConfig, debugConfig]);
544
+ }, [sdk]);
545
545
  (0, import_react.useEffect)(() => {
546
- if (!sdk)
547
- return;
548
546
  if (config.autoConnect !== false) {
549
547
  sdk.autoConnect().catch(() => {
550
548
  });
@@ -560,15 +558,7 @@ function PhantomProvider({ children, config, debugConfig }) {
560
558
  walletId,
561
559
  setWalletId
562
560
  }),
563
- [
564
- sdk,
565
- isConnected,
566
- isConnecting,
567
- connectError,
568
- addresses,
569
- walletId,
570
- setWalletId
571
- ]
561
+ [sdk, isConnected, isConnecting, connectError, addresses, walletId, setWalletId]
572
562
  );
573
563
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PhantomContext.Provider, { value, children });
574
564
  }
@@ -649,148 +639,30 @@ function useAccounts() {
649
639
  }
650
640
 
651
641
  // src/hooks/useSolana.ts
652
- var import_react4 = require("react");
653
642
  function useSolana() {
654
643
  const { sdk, isConnected } = usePhantom();
655
- const solanaChain = (0, import_react4.useMemo)(() => {
656
- if (!sdk || !isConnected)
657
- return null;
658
- try {
659
- return sdk.solana;
660
- } catch {
661
- return null;
662
- }
663
- }, [sdk, isConnected]);
664
- const signMessage = (0, import_react4.useCallback)(async (message) => {
665
- if (!solanaChain)
666
- throw new Error("Solana chain not available. Ensure SDK is connected.");
667
- return await solanaChain.signMessage(message);
668
- }, [solanaChain]);
669
- const signTransaction = (0, import_react4.useCallback)(async (transaction) => {
670
- if (!solanaChain)
671
- throw new Error("Solana chain not available. Ensure SDK is connected.");
672
- return await solanaChain.signTransaction(transaction);
673
- }, [solanaChain]);
674
- const signAndSendTransaction = (0, import_react4.useCallback)(async (transaction) => {
675
- if (!solanaChain)
676
- throw new Error("Solana chain not available. Ensure SDK is connected.");
677
- return await solanaChain.signAndSendTransaction(transaction);
678
- }, [solanaChain]);
679
- const connect = (0, import_react4.useCallback)(async (options) => {
680
- if (!solanaChain)
681
- throw new Error("Solana chain not available. Ensure SDK is connected.");
682
- return await solanaChain.connect(options);
683
- }, [solanaChain]);
684
- const disconnect = (0, import_react4.useCallback)(async () => {
685
- if (!solanaChain)
686
- throw new Error("Solana chain not available. Ensure SDK is connected.");
687
- return await solanaChain.disconnect();
688
- }, [solanaChain]);
689
- const switchNetwork = (0, import_react4.useCallback)(async (network) => {
690
- if (!solanaChain)
691
- throw new Error("Solana chain not available. Ensure SDK is connected.");
692
- return await solanaChain.switchNetwork(network);
693
- }, [solanaChain]);
694
- const getPublicKey = (0, import_react4.useCallback)(async () => {
695
- if (!solanaChain)
696
- return null;
697
- return await solanaChain.getPublicKey();
698
- }, [solanaChain]);
699
644
  return {
700
- // Chain instance for advanced usage
701
- solana: solanaChain,
702
- // Convenient methods
703
- signMessage,
704
- signTransaction,
705
- signAndSendTransaction,
706
- connect,
707
- disconnect,
708
- switchNetwork,
709
- getPublicKey,
645
+ // Chain instance with connection enforcement for signing methods
646
+ solana: sdk.solana,
710
647
  // State
711
- isAvailable: !!solanaChain,
712
- isConnected: solanaChain?.isConnected() ?? false
648
+ isAvailable: !!isConnected
713
649
  };
714
650
  }
715
651
 
716
652
  // src/hooks/useEthereum.ts
717
- var import_react5 = require("react");
718
653
  function useEthereum() {
719
654
  const { sdk, isConnected } = usePhantom();
720
- const ethereumChain = (0, import_react5.useMemo)(() => {
721
- if (!sdk || !isConnected)
722
- return null;
723
- try {
724
- return sdk.ethereum;
725
- } catch {
726
- return null;
727
- }
728
- }, [sdk, isConnected]);
729
- const request = (0, import_react5.useCallback)(async (args) => {
730
- if (!ethereumChain)
731
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
732
- return await ethereumChain.request(args);
733
- }, [ethereumChain]);
734
- const signPersonalMessage = (0, import_react5.useCallback)(async (message, address) => {
735
- if (!ethereumChain)
736
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
737
- return await ethereumChain.signPersonalMessage(message, address);
738
- }, [ethereumChain]);
739
- const sendTransaction = (0, import_react5.useCallback)(async (transaction) => {
740
- if (!ethereumChain)
741
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
742
- return await ethereumChain.sendTransaction(transaction);
743
- }, [ethereumChain]);
744
- const switchChain = (0, import_react5.useCallback)(async (chainId) => {
745
- if (!ethereumChain)
746
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
747
- return await ethereumChain.switchChain(chainId);
748
- }, [ethereumChain]);
749
- const getChainId = (0, import_react5.useCallback)(async () => {
750
- if (!ethereumChain)
751
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
752
- return await ethereumChain.getChainId();
753
- }, [ethereumChain]);
754
- const getAccounts = (0, import_react5.useCallback)(async () => {
755
- if (!ethereumChain)
756
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
757
- return await ethereumChain.getAccounts();
758
- }, [ethereumChain]);
759
- const signMessage = (0, import_react5.useCallback)(async (message) => {
760
- const accounts = await getAccounts();
761
- return await request({
762
- method: "eth_sign",
763
- params: [accounts[0], message]
764
- });
765
- }, [request, getAccounts]);
766
- const signTypedData = (0, import_react5.useCallback)(async (typedData) => {
767
- if (!ethereumChain)
768
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
769
- const accounts = await getAccounts();
770
- return await ethereumChain.signTypedData(typedData, accounts[0]);
771
- }, [ethereumChain, getAccounts]);
772
655
  return {
773
- // Chain instance for advanced usage
774
- ethereum: ethereumChain,
775
- // Standard EIP-1193 interface
776
- request,
777
- // Convenient methods
778
- signPersonalMessage,
779
- signMessage,
780
- signTypedData,
781
- sendTransaction,
782
- switchChain,
783
- getChainId,
784
- getAccounts,
656
+ // Chain instance with connection enforcement for signing methods
657
+ ethereum: sdk.ethereum,
785
658
  // State
786
- isAvailable: !!ethereumChain,
787
- isConnected: ethereumChain?.isConnected() ?? false
659
+ isAvailable: !!isConnected
788
660
  };
789
661
  }
790
662
 
791
663
  // src/index.ts
792
664
  var import_client = require("@phantom/client");
793
- var import_constants = require("@phantom/constants");
665
+ var import_constants3 = require("@phantom/constants");
794
666
  // Annotate the CommonJS export names for ESM import in node:
795
667
  0 && (module.exports = {
796
668
  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,42 +53,29 @@ 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) {
59
60
  return;
60
61
  }
61
62
  const phantomOptions = options;
62
- const {
63
- authUrl,
64
- redirectUrl,
65
- organizationId,
66
- parentOrganizationId,
67
- sessionId,
68
- provider,
69
- customAuthData,
70
- appName,
71
- appLogo
72
- } = phantomOptions;
63
+ const { authUrl, redirectUrl, organizationId, sessionId, provider, customAuthData, appId } = phantomOptions;
73
64
  if (!redirectUrl) {
74
65
  throw new Error("redirectUrl is required for web browser authentication");
75
66
  }
76
- if (!organizationId || !sessionId) {
77
- throw new Error("organizationId and sessionId are required for authentication");
67
+ if (!organizationId || !sessionId || !appId) {
68
+ throw new Error("organizationId, sessionId and appId are required for authentication");
78
69
  }
79
70
  try {
80
71
  const baseUrl = authUrl || DEFAULT_AUTH_URL;
81
72
  const params = new URLSearchParams({
82
73
  organization_id: organizationId,
83
- parent_organization_id: parentOrganizationId,
74
+ app_id: appId,
84
75
  redirect_uri: redirectUrl,
85
76
  session_id: sessionId,
86
77
  clear_previous_session: "true",
87
- app_name: appName || "",
88
- // Optional app name
89
- app_logo: appLogo || ""
90
- // Optional app logo URL
78
+ sdk_version: "1.0.0-beta.10"
91
79
  });
92
80
  if (provider) {
93
81
  console.log("[ExpoAuthProvider] Provider specified, will skip selection", { provider });
@@ -105,7 +93,6 @@ var ExpoAuthProvider = class {
105
93
  baseUrl,
106
94
  redirectUrl,
107
95
  organizationId,
108
- parentOrganizationId,
109
96
  sessionId,
110
97
  provider,
111
98
  hasCustomData: !!customAuthData
@@ -231,7 +218,7 @@ var ReactNativeStamper = class {
231
218
  this.algorithm = Algorithm.ed25519;
232
219
  this.type = "PKI";
233
220
  this.keyPrefix = config.keyPrefix || "phantom-rn-stamper";
234
- this.organizationId = config.organizationId || "default";
221
+ this.appId = config.appId || "default";
235
222
  }
236
223
  /**
237
224
  * Initialize the stamper and generate/load cryptographic keys
@@ -384,10 +371,10 @@ var ReactNativeStamper = class {
384
371
  return null;
385
372
  }
386
373
  getActiveKeyName() {
387
- return `${this.keyPrefix}-${this.organizationId}-active`;
374
+ return `${this.keyPrefix}-${this.appId}-active`;
388
375
  }
389
376
  getPendingKeyName() {
390
- return `${this.keyPrefix}-${this.organizationId}-pending`;
377
+ return `${this.keyPrefix}-${this.appId}-pending`;
391
378
  }
392
379
  };
393
380
 
@@ -428,34 +415,48 @@ function PhantomProvider({ children, config, debugConfig }) {
428
415
  const [connectError, setConnectError] = useState(null);
429
416
  const [addresses, setAddresses] = useState([]);
430
417
  const [walletId, setWalletId] = useState(null);
431
- const [sdk, setSdk] = useState(null);
432
418
  const memoizedConfig = useMemo(() => {
433
419
  const redirectUrl = config.authOptions?.redirectUrl || `${config.scheme}://phantom-auth-callback`;
434
420
  return {
435
421
  ...config,
422
+ apiBaseUrl: config.apiBaseUrl || DEFAULT_WALLET_API_URL,
423
+ embeddedWalletType: config.embeddedWalletType || DEFAULT_EMBEDDED_WALLET_TYPE,
436
424
  authOptions: {
437
425
  ...config.authOptions || {},
438
- redirectUrl
426
+ redirectUrl,
427
+ authUrl: config.authOptions?.authUrl || DEFAULT_AUTH_URL2
439
428
  }
440
429
  };
441
430
  }, [config]);
442
- useEffect(() => {
431
+ const sdk = useMemo(() => {
443
432
  const storage = new ExpoSecureStorage();
444
433
  const authProvider = new ExpoAuthProvider();
445
434
  const urlParamsAccessor = new ExpoURLParamsAccessor();
446
435
  const logger = new ExpoLogger(debugConfig?.enabled || false);
447
436
  const stamper = new ReactNativeStamper({
448
- keyPrefix: `phantom-rn-${memoizedConfig.organizationId}`,
449
- organizationId: memoizedConfig.organizationId
437
+ keyPrefix: `phantom-rn-${memoizedConfig.appId}`,
438
+ appId: memoizedConfig.appId
450
439
  });
440
+ const platformName = `${Platform.OS}-${Platform.Version}`;
451
441
  const platform = {
452
442
  storage,
453
443
  authProvider,
454
444
  urlParamsAccessor,
455
445
  stamper,
456
- name: `${Platform.OS}-${Platform.Version}`
446
+ name: platformName,
447
+ analyticsHeaders: {
448
+ [ANALYTICS_HEADERS.SDK_TYPE]: "react-native",
449
+ [ANALYTICS_HEADERS.PLATFORM]: Platform.OS,
450
+ [ANALYTICS_HEADERS.PLATFORM_VERSION]: `${Platform.Version}`,
451
+ [ANALYTICS_HEADERS.APP_ID]: config.appId,
452
+ [ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
453
+ [ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.10"
454
+ // Replaced at build time
455
+ }
457
456
  };
458
- const sdkInstance = new EmbeddedProvider(memoizedConfig, platform, logger);
457
+ return new EmbeddedProvider(memoizedConfig, platform, logger);
458
+ }, [memoizedConfig, debugConfig, config.appId, config.embeddedWalletType]);
459
+ useEffect(() => {
459
460
  const handleConnectStart = () => {
460
461
  setIsConnecting(true);
461
462
  setConnectError(null);
@@ -464,12 +465,12 @@ function PhantomProvider({ children, config, debugConfig }) {
464
465
  try {
465
466
  setIsConnected(true);
466
467
  setIsConnecting(false);
467
- const addrs = await sdkInstance.getAddresses();
468
+ const addrs = await sdk.getAddresses();
468
469
  setAddresses(addrs);
469
470
  } catch (err) {
470
471
  console.error("Error connecting:", err);
471
472
  try {
472
- await sdkInstance.disconnect();
473
+ await sdk.disconnect();
473
474
  } catch (err2) {
474
475
  console.error("Error disconnecting:", err2);
475
476
  }
@@ -486,21 +487,18 @@ function PhantomProvider({ children, config, debugConfig }) {
486
487
  setAddresses([]);
487
488
  setWalletId(null);
488
489
  };
489
- sdkInstance.on("connect_start", handleConnectStart);
490
- sdkInstance.on("connect", handleConnect);
491
- sdkInstance.on("connect_error", handleConnectError);
492
- sdkInstance.on("disconnect", handleDisconnect);
493
- setSdk(sdkInstance);
490
+ sdk.on("connect_start", handleConnectStart);
491
+ sdk.on("connect", handleConnect);
492
+ sdk.on("connect_error", handleConnectError);
493
+ sdk.on("disconnect", handleDisconnect);
494
494
  return () => {
495
- sdkInstance.off("connect_start", handleConnectStart);
496
- sdkInstance.off("connect", handleConnect);
497
- sdkInstance.off("connect_error", handleConnectError);
498
- sdkInstance.off("disconnect", handleDisconnect);
495
+ sdk.off("connect_start", handleConnectStart);
496
+ sdk.off("connect", handleConnect);
497
+ sdk.off("connect_error", handleConnectError);
498
+ sdk.off("disconnect", handleDisconnect);
499
499
  };
500
- }, [memoizedConfig, debugConfig]);
500
+ }, [sdk]);
501
501
  useEffect(() => {
502
- if (!sdk)
503
- return;
504
502
  if (config.autoConnect !== false) {
505
503
  sdk.autoConnect().catch(() => {
506
504
  });
@@ -516,15 +514,7 @@ function PhantomProvider({ children, config, debugConfig }) {
516
514
  walletId,
517
515
  setWalletId
518
516
  }),
519
- [
520
- sdk,
521
- isConnected,
522
- isConnecting,
523
- connectError,
524
- addresses,
525
- walletId,
526
- setWalletId
527
- ]
517
+ [sdk, isConnected, isConnecting, connectError, addresses, walletId, setWalletId]
528
518
  );
529
519
  return /* @__PURE__ */ jsx(PhantomContext.Provider, { value, children });
530
520
  }
@@ -605,142 +595,24 @@ function useAccounts() {
605
595
  }
606
596
 
607
597
  // src/hooks/useSolana.ts
608
- import { useCallback as useCallback3, useMemo as useMemo2 } from "react";
609
598
  function useSolana() {
610
599
  const { sdk, isConnected } = usePhantom();
611
- const solanaChain = useMemo2(() => {
612
- if (!sdk || !isConnected)
613
- return null;
614
- try {
615
- return sdk.solana;
616
- } catch {
617
- return null;
618
- }
619
- }, [sdk, isConnected]);
620
- const signMessage = useCallback3(async (message) => {
621
- if (!solanaChain)
622
- throw new Error("Solana chain not available. Ensure SDK is connected.");
623
- return await solanaChain.signMessage(message);
624
- }, [solanaChain]);
625
- const signTransaction = useCallback3(async (transaction) => {
626
- if (!solanaChain)
627
- throw new Error("Solana chain not available. Ensure SDK is connected.");
628
- return await solanaChain.signTransaction(transaction);
629
- }, [solanaChain]);
630
- const signAndSendTransaction = useCallback3(async (transaction) => {
631
- if (!solanaChain)
632
- throw new Error("Solana chain not available. Ensure SDK is connected.");
633
- return await solanaChain.signAndSendTransaction(transaction);
634
- }, [solanaChain]);
635
- const connect = useCallback3(async (options) => {
636
- if (!solanaChain)
637
- throw new Error("Solana chain not available. Ensure SDK is connected.");
638
- return await solanaChain.connect(options);
639
- }, [solanaChain]);
640
- const disconnect = useCallback3(async () => {
641
- if (!solanaChain)
642
- throw new Error("Solana chain not available. Ensure SDK is connected.");
643
- return await solanaChain.disconnect();
644
- }, [solanaChain]);
645
- const switchNetwork = useCallback3(async (network) => {
646
- if (!solanaChain)
647
- throw new Error("Solana chain not available. Ensure SDK is connected.");
648
- return await solanaChain.switchNetwork(network);
649
- }, [solanaChain]);
650
- const getPublicKey = useCallback3(async () => {
651
- if (!solanaChain)
652
- return null;
653
- return await solanaChain.getPublicKey();
654
- }, [solanaChain]);
655
600
  return {
656
- // Chain instance for advanced usage
657
- solana: solanaChain,
658
- // Convenient methods
659
- signMessage,
660
- signTransaction,
661
- signAndSendTransaction,
662
- connect,
663
- disconnect,
664
- switchNetwork,
665
- getPublicKey,
601
+ // Chain instance with connection enforcement for signing methods
602
+ solana: sdk.solana,
666
603
  // State
667
- isAvailable: !!solanaChain,
668
- isConnected: solanaChain?.isConnected() ?? false
604
+ isAvailable: !!isConnected
669
605
  };
670
606
  }
671
607
 
672
608
  // src/hooks/useEthereum.ts
673
- import { useCallback as useCallback4, useMemo as useMemo3 } from "react";
674
609
  function useEthereum() {
675
610
  const { sdk, isConnected } = usePhantom();
676
- const ethereumChain = useMemo3(() => {
677
- if (!sdk || !isConnected)
678
- return null;
679
- try {
680
- return sdk.ethereum;
681
- } catch {
682
- return null;
683
- }
684
- }, [sdk, isConnected]);
685
- const request = useCallback4(async (args) => {
686
- if (!ethereumChain)
687
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
688
- return await ethereumChain.request(args);
689
- }, [ethereumChain]);
690
- const signPersonalMessage = useCallback4(async (message, address) => {
691
- if (!ethereumChain)
692
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
693
- return await ethereumChain.signPersonalMessage(message, address);
694
- }, [ethereumChain]);
695
- const sendTransaction = useCallback4(async (transaction) => {
696
- if (!ethereumChain)
697
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
698
- return await ethereumChain.sendTransaction(transaction);
699
- }, [ethereumChain]);
700
- const switchChain = useCallback4(async (chainId) => {
701
- if (!ethereumChain)
702
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
703
- return await ethereumChain.switchChain(chainId);
704
- }, [ethereumChain]);
705
- const getChainId = useCallback4(async () => {
706
- if (!ethereumChain)
707
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
708
- return await ethereumChain.getChainId();
709
- }, [ethereumChain]);
710
- const getAccounts = useCallback4(async () => {
711
- if (!ethereumChain)
712
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
713
- return await ethereumChain.getAccounts();
714
- }, [ethereumChain]);
715
- const signMessage = useCallback4(async (message) => {
716
- const accounts = await getAccounts();
717
- return await request({
718
- method: "eth_sign",
719
- params: [accounts[0], message]
720
- });
721
- }, [request, getAccounts]);
722
- const signTypedData = useCallback4(async (typedData) => {
723
- if (!ethereumChain)
724
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
725
- const accounts = await getAccounts();
726
- return await ethereumChain.signTypedData(typedData, accounts[0]);
727
- }, [ethereumChain, getAccounts]);
728
611
  return {
729
- // Chain instance for advanced usage
730
- ethereum: ethereumChain,
731
- // Standard EIP-1193 interface
732
- request,
733
- // Convenient methods
734
- signPersonalMessage,
735
- signMessage,
736
- signTypedData,
737
- sendTransaction,
738
- switchChain,
739
- getChainId,
740
- getAccounts,
612
+ // Chain instance with connection enforcement for signing methods
613
+ ethereum: sdk.ethereum,
741
614
  // State
742
- isAvailable: !!ethereumChain,
743
- isConnected: ethereumChain?.isConnected() ?? false
615
+ isAvailable: !!isConnected
744
616
  };
745
617
  }
746
618
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/react-native-sdk",
3
- "version": "1.0.0-beta.0",
3
+ "version": "1.0.0-beta.10",
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,15 +45,14 @@
45
45
  "directory": "packages/react-native-sdk"
46
46
  },
47
47
  "dependencies": {
48
- "@phantom/api-key-stamper": "^1.0.0-beta.0",
49
- "@phantom/base64url": "^1.0.0-beta.0",
50
- "@phantom/chains": "^1.0.0-beta.0",
51
- "@phantom/client": "^1.0.0-beta.0",
52
- "@phantom/constants": "^1.0.0-beta.0",
53
- "@phantom/crypto": "^1.0.0-beta.0",
54
- "@phantom/embedded-provider-core": "^1.0.0-beta.0",
55
- "@phantom/parsers": "^1.0.0-beta.0",
56
- "@phantom/sdk-types": "^1.0.0-beta.0",
48
+ "@phantom/api-key-stamper": "^1.0.0-beta.6",
49
+ "@phantom/base64url": "^1.0.0-beta.6",
50
+ "@phantom/chain-interfaces": "^1.0.0-beta.6",
51
+ "@phantom/client": "^1.0.0-beta.10",
52
+ "@phantom/constants": "^1.0.0-beta.6",
53
+ "@phantom/crypto": "^1.0.0-beta.6",
54
+ "@phantom/embedded-provider-core": "^1.0.0-beta.10",
55
+ "@phantom/sdk-types": "^1.0.0-beta.6",
57
56
  "@types/bs58": "^5.0.0",
58
57
  "bs58": "^6.0.0",
59
58
  "buffer": "^6.0.3"