@phantom/react-sdk 1.0.0-beta.0 → 1.0.0-beta.1

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
@@ -97,7 +97,6 @@ function App() {
97
97
  embeddedWalletType: "app-wallet", // or 'user-wallet'
98
98
  addressTypes: [AddressType.solana, AddressType.ethereum],
99
99
  apiBaseUrl: "https://api.phantom.app/v1/wallets",
100
- organizationId: "your-org-id",
101
100
  }}
102
101
  >
103
102
  <YourApp />
@@ -153,7 +152,7 @@ await connect({
153
152
  },
154
153
  });
155
154
 
156
- // Apple authentication (skips provider selection)
155
+ // Apple authentication (skips provider selection)
157
156
  await connect({
158
157
  authOptions: {
159
158
  provider: "apple",
@@ -195,7 +194,6 @@ Creates non-custodial wallets embedded in your application.
195
194
  embeddedWalletType: "app-wallet",
196
195
  addressTypes: [AddressType.solana],
197
196
  apiBaseUrl: "https://api.phantom.app/v1/wallets",
198
- organizationId: "your-org-id",
199
197
  }}
200
198
  >
201
199
  <YourApp />
@@ -215,7 +213,6 @@ Creates non-custodial wallets embedded in your application.
215
213
  embeddedWalletType: "user-wallet",
216
214
  addressTypes: [AddressType.solana, AddressType.ethereum],
217
215
  apiBaseUrl: "https://api.phantom.app/v1/wallets",
218
- organizationId: "your-org-id",
219
216
  }}
220
217
  >
221
218
  <YourApp />
@@ -233,7 +230,6 @@ When using `AddressType.solana`, you can choose between two Solana libraries:
233
230
  addressTypes: [AddressType.solana],
234
231
  solanaProvider: "web3js", // or 'kit'
235
232
  apiBaseUrl: "https://api.phantom.app/v1/wallets",
236
- organizationId: "your-org-id",
237
233
  }}
238
234
  >
239
235
  <YourApp />
@@ -378,7 +374,7 @@ function SolanaOperations() {
378
374
  // Create transaction
379
375
  const connection = new Connection("https://api.mainnet-beta.solana.com");
380
376
  const { blockhash } = await connection.getLatestBlockhash();
381
-
377
+
382
378
  const fromAddress = await solana.getPublicKey();
383
379
  const transferInstruction = SystemProgram.transfer({
384
380
  fromPubkey: new PublicKey(fromAddress),
@@ -400,7 +396,7 @@ function SolanaOperations() {
400
396
  };
401
397
 
402
398
  const switchNetwork = async () => {
403
- await solana.switchNetwork('devnet');
399
+ await solana.switchNetwork("devnet");
404
400
  };
405
401
 
406
402
  return (
@@ -408,13 +404,14 @@ function SolanaOperations() {
408
404
  <button onClick={signMessage}>Sign Message</button>
409
405
  <button onClick={signAndSendTransaction}>Send Transaction</button>
410
406
  <button onClick={switchNetwork}>Switch to Devnet</button>
411
- <p>Connected: {solana.isConnected ? 'Yes' : 'No'}</p>
407
+ <p>Connected: {solana.isConnected ? "Yes" : "No"}</p>
412
408
  </div>
413
409
  );
414
410
  }
415
411
  ```
416
412
 
417
413
  **Available methods:**
414
+
418
415
  - `signMessage(message)` - Sign a message
419
416
  - `signTransaction(transaction)` - Sign without sending
420
417
  - `signAndSendTransaction(transaction)` - Sign and send
@@ -447,26 +444,26 @@ function EthereumOperations() {
447
444
  { name: "name", type: "string" },
448
445
  { name: "version", type: "string" },
449
446
  { name: "chainId", type: "uint256" },
450
- { name: "verifyingContract", type: "address" }
447
+ { name: "verifyingContract", type: "address" },
451
448
  ],
452
449
  Mail: [
453
450
  { name: "from", type: "string" },
454
451
  { name: "to", type: "string" },
455
- { name: "contents", type: "string" }
456
- ]
452
+ { name: "contents", type: "string" },
453
+ ],
457
454
  },
458
455
  primaryType: "Mail",
459
456
  domain: {
460
457
  name: "Ether Mail",
461
458
  version: "1",
462
459
  chainId: 1,
463
- verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
460
+ verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
464
461
  },
465
462
  message: {
466
463
  from: "Alice",
467
464
  to: "Bob",
468
- contents: "Hello!"
469
- }
465
+ contents: "Hello!",
466
+ },
470
467
  };
471
468
 
472
469
  const signature = await ethereum.signTypedData(typedData);
@@ -492,13 +489,14 @@ function EthereumOperations() {
492
489
  <button onClick={signTypedData}>Sign Typed Data</button>
493
490
  <button onClick={sendTransaction}>Send Transaction</button>
494
491
  <button onClick={switchChain}>Switch to Polygon</button>
495
- <p>Connected: {ethereum.isConnected ? 'Yes' : 'No'}</p>
492
+ <p>Connected: {ethereum.isConnected ? "Yes" : "No"}</p>
496
493
  </div>
497
494
  );
498
495
  }
499
496
  ```
500
497
 
501
498
  **Available methods:**
499
+
502
500
  - `request(args)` - EIP-1193 requests
503
501
  - `signPersonalMessage(message, address)` - Sign personal message
504
502
  - `signTypedData(typedData)` - Sign EIP-712 typed data
@@ -521,21 +519,13 @@ Hook for managing auto-confirm functionality with the Phantom extension. Auto-co
521
519
  import { useAutoConfirm, NetworkId } from "@phantom/react-sdk";
522
520
 
523
521
  function AutoConfirmControls() {
524
- const {
525
- enable,
526
- disable,
527
- status,
528
- supportedChains,
529
- isLoading,
530
- error,
531
- refetch,
532
- } = useAutoConfirm();
522
+ const { enable, disable, status, supportedChains, isLoading, error, refetch } = useAutoConfirm();
533
523
 
534
524
  const handleEnable = async () => {
535
525
  try {
536
526
  // Enable auto-confirm for specific chains
537
527
  const result = await enable({
538
- chains: [NetworkId.SOLANA_DEVNET, NetworkId.ETHEREUM_MAINNET]
528
+ chains: [NetworkId.SOLANA_DEVNET, NetworkId.ETHEREUM_MAINNET],
539
529
  });
540
530
  console.log("Auto-confirm enabled:", result);
541
531
  } catch (err) {
@@ -563,14 +553,14 @@ function AutoConfirmControls() {
563
553
  return (
564
554
  <div>
565
555
  <h3>Auto-Confirm Settings</h3>
566
-
556
+
567
557
  <div>
568
558
  <strong>Status:</strong> {status?.enabled ? "Enabled" : "Disabled"}
569
559
  {status?.chains && (
570
560
  <div>
571
561
  <strong>Active Chains:</strong>
572
562
  <ul>
573
- {status.chains.map((chain) => (
563
+ {status.chains.map(chain => (
574
564
  <li key={chain}>{chain}</li>
575
565
  ))}
576
566
  </ul>
@@ -582,7 +572,7 @@ function AutoConfirmControls() {
582
572
  <strong>Supported Chains:</strong>
583
573
  {supportedChains?.chains && (
584
574
  <ul>
585
- {supportedChains.chains.map((chain) => (
575
+ {supportedChains.chains.map(chain => (
586
576
  <li key={chain}>{chain}</li>
587
577
  ))}
588
578
  </ul>
@@ -635,7 +625,7 @@ interface AutoConfirmSupportedChainsResult {
635
625
  **Available Methods:**
636
626
 
637
627
  - `enable(params)` - Enable auto-confirm for specific chains
638
- - `disable()` - Disable auto-confirm completely
628
+ - `disable()` - Disable auto-confirm completely
639
629
  - `refetch()` - Refresh status and supported chains from extension
640
630
  - `status` - Current auto-confirm status (enabled/disabled and active chains)
641
631
  - `supportedChains` - List of chains that support auto-confirm
@@ -778,29 +768,27 @@ function EthereumExample() {
778
768
 
779
769
  Quick reference of all available hooks:
780
770
 
781
- | Hook | Purpose | Returns |
782
- | --------------------------- | -------------------------- | ---------------------------------------------- |
783
- | `useConnect` | Connect to wallet | `{ connect, isConnecting, error }` |
784
- | `useAccounts` | Get wallet addresses | `WalletAddress[]` or `null` |
785
- | `useIsExtensionInstalled` | Check extension status | `{ isLoading, isInstalled }` |
786
- | `useDisconnect` | Disconnect from wallet | `{ disconnect, isDisconnecting }` |
787
- | `useAutoConfirm` | Auto-confirm management (injected only) | `{ enable, disable, status, supportedChains, ... }` |
788
- | `useSolana` | Solana chain operations | `{ signMessage, signAndSendTransaction, ... }` |
789
- | `useEthereum` | Ethereum chain operations | `{ signPersonalMessage, sendTransaction, ... }`|
790
- | `usePhantom` | Get provider context | `{ isConnected, isReady }` |
771
+ | Hook | Purpose | Returns |
772
+ | ------------------------- | --------------------------------------- | --------------------------------------------------- |
773
+ | `useConnect` | Connect to wallet | `{ connect, isConnecting, error }` |
774
+ | `useAccounts` | Get wallet addresses | `WalletAddress[]` or `null` |
775
+ | `useIsExtensionInstalled` | Check extension status | `{ isLoading, isInstalled }` |
776
+ | `useDisconnect` | Disconnect from wallet | `{ disconnect, isDisconnecting }` |
777
+ | `useAutoConfirm` | Auto-confirm management (injected only) | `{ enable, disable, status, supportedChains, ... }` |
778
+ | `useSolana` | Solana chain operations | `{ signMessage, signAndSendTransaction, ... }` |
779
+ | `useEthereum` | Ethereum chain operations | `{ signPersonalMessage, sendTransaction, ... }` |
780
+ | `usePhantom` | Get provider context | `{ isConnected, isReady }` |
791
781
 
792
782
  ## Configuration Reference
793
783
 
794
784
  ```typescript
795
785
  interface PhantomSDKConfig {
796
786
  providerType: "injected" | "embedded";
797
- appName?: string; // Optional app name for branding
798
- appLogo?: string; // Optional app logo URL for branding
799
787
  addressTypes?: [AddressType, ...AddressType[]]; // Networks to enable (e.g., [AddressType.solana])
800
788
 
801
789
  // Required for embedded provider only
802
790
  apiBaseUrl?: string; // Phantom API base URL
803
- organizationId?: string; // Your organization ID
791
+ appId: string; // Your app ID
804
792
  authOptions?: {
805
793
  authUrl?: string; // Custom auth URL (optional)
806
794
  redirectUrl?: string; // Custom redirect URL (optional)
@@ -819,8 +807,8 @@ The React SDK supports separate debug configuration that can be changed without
819
807
 
820
808
  ```typescript
821
809
  interface PhantomDebugConfig {
822
- enabled?: boolean; // Enable debug logging
823
- level?: DebugLevel; // Debug level (ERROR, WARN, INFO, DEBUG)
810
+ enabled?: boolean; // Enable debug logging
811
+ level?: DebugLevel; // Debug level (ERROR, WARN, INFO, DEBUG)
824
812
  callback?: DebugCallback; // Custom debug message handler
825
813
  }
826
814
  ```
@@ -839,7 +827,6 @@ function App() {
839
827
  // SDK configuration - static, won't change when debug settings change
840
828
  const config: PhantomSDKConfig = {
841
829
  providerType: "embedded",
842
- organizationId: "your-org-id",
843
830
  // ... other config
844
831
  };
845
832
 
@@ -866,12 +853,12 @@ Debug callbacks receive a `DebugMessage` object:
866
853
 
867
854
  ```typescript
868
855
  interface DebugMessage {
869
- timestamp: number; // Unix timestamp
870
- level: DebugLevel; // Message level
871
- category: string; // Component category
872
- message: string; // Debug message text
873
- data?: any; // Additional debug data (optional)
856
+ timestamp: number; // Unix timestamp
857
+ level: DebugLevel; // Message level
858
+ category: string; // Component category
859
+ message: string; // Debug message text
860
+ data?: any; // Additional debug data (optional)
874
861
  }
875
862
  ```
876
863
 
877
- For more details and examples, see the [@phantom/browser-sdk documentation](../browser-sdk/README.md).
864
+ For more details and examples, see the [@phantom/browser-sdk documentation](../browser-sdk/README.md).
package/dist/index.d.ts CHANGED
@@ -3,7 +3,6 @@ import { ReactNode } from 'react';
3
3
  import { BrowserSDKConfig, DebugConfig, AuthOptions, BrowserSDK, WalletAddress, AutoConfirmEnableParams, AutoConfirmResult, AutoConfirmSupportedChainsResult } from '@phantom/browser-sdk';
4
4
  export { AddressType, AutoConfirmEnableParams, AutoConfirmResult, AutoConfirmSupportedChainsResult, DebugLevel, DebugMessage, NetworkId, SignedTransaction, WalletAddress, debug } from '@phantom/browser-sdk';
5
5
  import * as _phantom_embedded_provider_core from '@phantom/embedded-provider-core';
6
- import * as _phantom_parsers from '@phantom/parsers';
7
6
  import { ISolanaChain, IEthereumChain, EthTransactionRequest } from '@phantom/chains';
8
7
  export { EthTransactionRequest, IEthereumChain, ISolanaChain } from '@phantom/chains';
9
8
 
@@ -50,6 +49,10 @@ declare function useDisconnect(): {
50
49
 
51
50
  declare function useAccounts(): _phantom_embedded_provider_core.WalletAddress[] | null;
52
51
 
52
+ /**
53
+ * React hook to check if Phantom extension is installed
54
+ * Uses waitForPhantomExtension for proper detection with retry logic
55
+ */
53
56
  declare function useIsExtensionInstalled(): {
54
57
  isLoading: boolean;
55
58
  isInstalled: boolean;
@@ -73,16 +76,21 @@ declare function useAutoConfirm(): UseAutoConfirmResult;
73
76
  */
74
77
  declare function useSolana(): {
75
78
  solana: ISolanaChain | null;
76
- signMessage: (message: string | Uint8Array) => Promise<_phantom_parsers.ParsedSignatureResult>;
79
+ signMessage: (message: string | Uint8Array) => Promise<{
80
+ signature: Uint8Array;
81
+ publicKey: string;
82
+ }>;
77
83
  signTransaction: <T>(transaction: T) => Promise<T>;
78
- signAndSendTransaction: <T>(transaction: T) => Promise<_phantom_parsers.ParsedTransactionResult>;
84
+ signAndSendTransaction: <T>(transaction: T) => Promise<{
85
+ signature: string;
86
+ }>;
79
87
  connect: (options?: {
80
88
  onlyIfTrusted?: boolean;
81
89
  }) => Promise<{
82
90
  publicKey: string;
83
91
  }>;
84
92
  disconnect: () => Promise<void>;
85
- switchNetwork: (network: "mainnet" | "devnet") => Promise<void>;
93
+ switchNetwork: (network: "mainnet" | "devnet") => Promise<void | undefined>;
86
94
  getPublicKey: () => Promise<string | null>;
87
95
  isAvailable: boolean;
88
96
  isConnected: boolean;
@@ -102,7 +110,7 @@ declare function useEthereum(): {
102
110
  signPersonalMessage: (message: string, address: string) => Promise<string>;
103
111
  signMessage: (message: string) => Promise<string>;
104
112
  signTypedData: (typedData: any) => Promise<string>;
105
- sendTransaction: (transaction: EthTransactionRequest) => Promise<_phantom_parsers.ParsedTransactionResult>;
113
+ sendTransaction: (transaction: EthTransactionRequest) => Promise<string>;
106
114
  switchChain: (chainId: number) => Promise<void>;
107
115
  getChainId: () => Promise<number>;
108
116
  getAccounts: () => Promise<string[]>;
package/dist/index.js CHANGED
@@ -52,14 +52,6 @@ var import_browser_sdk = require("@phantom/browser-sdk");
52
52
  var import_jsx_runtime = require("react/jsx-runtime");
53
53
  var PhantomContext = (0, import_react.createContext)(void 0);
54
54
  function PhantomProvider({ children, config, debugConfig }) {
55
- const [isConnected, setIsConnected] = (0, import_react.useState)(false);
56
- const [isConnecting, setIsConnecting] = (0, import_react.useState)(false);
57
- const [connectError, setConnectError] = (0, import_react.useState)(null);
58
- const [addresses, setAddresses] = (0, import_react.useState)([]);
59
- const [walletId, setWalletId] = (0, import_react.useState)(null);
60
- const [currentProviderType, setCurrentProviderType] = (0, import_react.useState)(config.providerType || null);
61
- const [isPhantomAvailable, setIsPhantomAvailable] = (0, import_react.useState)(false);
62
- const [sdk, setSdk] = (0, import_react.useState)(null);
63
55
  const memoizedConfig = (0, import_react.useMemo)(() => {
64
56
  return {
65
57
  ...config,
@@ -67,6 +59,16 @@ function PhantomProvider({ children, config, debugConfig }) {
67
59
  providerType: config.providerType || "embedded"
68
60
  };
69
61
  }, [config]);
62
+ const [isConnected, setIsConnected] = (0, import_react.useState)(false);
63
+ const [isConnecting, setIsConnecting] = (0, import_react.useState)(false);
64
+ const [connectError, setConnectError] = (0, import_react.useState)(null);
65
+ const [addresses, setAddresses] = (0, import_react.useState)([]);
66
+ const [walletId, setWalletId] = (0, import_react.useState)(null);
67
+ const [currentProviderType, setCurrentProviderType] = (0, import_react.useState)(
68
+ memoizedConfig.providerType || null
69
+ );
70
+ const [isPhantomAvailable, setIsPhantomAvailable] = (0, import_react.useState)(false);
71
+ const [sdk, setSdk] = (0, import_react.useState)(null);
70
72
  (0, import_react.useEffect)(() => {
71
73
  const sdkInstance = new import_browser_sdk.BrowserSDK(memoizedConfig);
72
74
  const handleConnectStart = () => {
@@ -123,21 +125,21 @@ function PhantomProvider({ children, config, debugConfig }) {
123
125
  (0, import_react.useEffect)(() => {
124
126
  if (!sdk)
125
127
  return;
126
- const initialize = () => {
128
+ const initialize = async () => {
127
129
  try {
128
- const available = import_browser_sdk.BrowserSDK.isPhantomInstalled();
130
+ const available = await import_browser_sdk.BrowserSDK.isPhantomInstalled();
129
131
  setIsPhantomAvailable(available);
130
132
  } catch (err) {
131
133
  console.error("Error checking Phantom extension:", err);
132
134
  setIsPhantomAvailable(false);
133
135
  }
134
- if (config.autoConnect !== false) {
136
+ if (memoizedConfig.autoConnect !== false) {
135
137
  sdk.autoConnect().catch(() => {
136
138
  });
137
139
  }
138
140
  };
139
141
  initialize();
140
- }, [sdk, config.autoConnect]);
142
+ }, [sdk, memoizedConfig.autoConnect]);
141
143
  const value = (0, import_react.useMemo)(
142
144
  () => ({
143
145
  sdk,
@@ -149,16 +151,7 @@ function PhantomProvider({ children, config, debugConfig }) {
149
151
  currentProviderType,
150
152
  isPhantomAvailable
151
153
  }),
152
- [
153
- sdk,
154
- isConnected,
155
- isConnecting,
156
- connectError,
157
- addresses,
158
- walletId,
159
- currentProviderType,
160
- isPhantomAvailable
161
- ]
154
+ [sdk, isConnected, isConnecting, connectError, addresses, walletId, currentProviderType, isPhantomAvailable]
162
155
  );
163
156
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PhantomContext.Provider, { value, children });
164
157
  }
@@ -235,36 +228,33 @@ function useAccounts() {
235
228
  // src/hooks/useIsExtensionInstalled.ts
236
229
  var React = __toESM(require("react"));
237
230
  var import_browser_sdk2 = require("@phantom/browser-sdk");
238
- var cachedIsInstalled = null;
239
231
  function useIsExtensionInstalled() {
240
- const { sdk } = usePhantom();
241
- const [isLoading, setIsLoading] = React.useState(cachedIsInstalled === null);
242
- const [isInstalled, setIsInstalled] = React.useState(cachedIsInstalled ?? false);
232
+ const [isLoading, setIsLoading] = React.useState(true);
233
+ const [isInstalled, setIsInstalled] = React.useState(false);
243
234
  React.useEffect(() => {
244
- if (!sdk) {
245
- setIsLoading(false);
246
- return;
247
- }
248
- if (cachedIsInstalled !== null) {
249
- setIsInstalled(cachedIsInstalled);
250
- setIsLoading(false);
251
- return;
252
- }
253
- const checkExtension = () => {
235
+ let isMounted = true;
236
+ const checkExtension = async () => {
254
237
  try {
255
238
  setIsLoading(true);
256
- const result = import_browser_sdk2.BrowserSDK.isPhantomInstalled();
257
- cachedIsInstalled = result;
258
- setIsInstalled(result);
239
+ const result = await (0, import_browser_sdk2.waitForPhantomExtension)(3e3);
240
+ if (isMounted) {
241
+ setIsInstalled(result);
242
+ }
259
243
  } catch (error) {
260
- cachedIsInstalled = false;
261
- setIsInstalled(false);
244
+ if (isMounted) {
245
+ setIsInstalled(false);
246
+ }
262
247
  } finally {
263
- setIsLoading(false);
248
+ if (isMounted) {
249
+ setIsLoading(false);
250
+ }
264
251
  }
265
252
  };
266
253
  checkExtension();
267
- }, [sdk]);
254
+ return () => {
255
+ isMounted = false;
256
+ };
257
+ }, []);
268
258
  return { isLoading, isInstalled };
269
259
  }
270
260
 
@@ -301,53 +291,47 @@ function useAutoConfirm() {
301
291
  },
302
292
  [sdk, isInjected]
303
293
  );
304
- const disable = (0, import_react4.useCallback)(
305
- async () => {
306
- if (!sdk) {
307
- throw new Error("SDK not initialized");
308
- }
309
- if (!isInjected) {
310
- throw new Error("Auto-confirm is only available for injected (extension) providers");
311
- }
312
- try {
313
- setIsLoading(true);
314
- setError(null);
315
- await sdk.disableAutoConfirm();
316
- const newStatus = await sdk.getAutoConfirmStatus();
317
- setStatus(newStatus);
318
- } catch (err) {
319
- const error2 = err instanceof Error ? err : new Error("Unknown error occurred");
320
- setError(error2);
321
- throw error2;
322
- } finally {
323
- setIsLoading(false);
324
- }
325
- },
326
- [sdk, isInjected]
327
- );
328
- const refetch = (0, import_react4.useCallback)(
329
- async () => {
330
- if (!sdk || !isInjected) {
331
- return;
332
- }
333
- try {
334
- setIsLoading(true);
335
- setError(null);
336
- const [statusResult, supportedResult] = await Promise.all([
337
- sdk.getAutoConfirmStatus(),
338
- sdk.getSupportedAutoConfirmChains()
339
- ]);
340
- setStatus(statusResult);
341
- setSupportedChains(supportedResult);
342
- } catch (err) {
343
- const error2 = err instanceof Error ? err : new Error("Failed to fetch auto-confirm data");
344
- setError(error2);
345
- } finally {
346
- setIsLoading(false);
347
- }
348
- },
349
- [sdk, isInjected]
350
- );
294
+ const disable = (0, import_react4.useCallback)(async () => {
295
+ if (!sdk) {
296
+ throw new Error("SDK not initialized");
297
+ }
298
+ if (!isInjected) {
299
+ throw new Error("Auto-confirm is only available for injected (extension) providers");
300
+ }
301
+ try {
302
+ setIsLoading(true);
303
+ setError(null);
304
+ await sdk.disableAutoConfirm();
305
+ const newStatus = await sdk.getAutoConfirmStatus();
306
+ setStatus(newStatus);
307
+ } catch (err) {
308
+ const error2 = err instanceof Error ? err : new Error("Unknown error occurred");
309
+ setError(error2);
310
+ throw error2;
311
+ } finally {
312
+ setIsLoading(false);
313
+ }
314
+ }, [sdk, isInjected]);
315
+ const refetch = (0, import_react4.useCallback)(async () => {
316
+ if (!sdk || !isInjected) {
317
+ return;
318
+ }
319
+ try {
320
+ setIsLoading(true);
321
+ setError(null);
322
+ const [statusResult, supportedResult] = await Promise.all([
323
+ sdk.getAutoConfirmStatus(),
324
+ sdk.getSupportedAutoConfirmChains()
325
+ ]);
326
+ setStatus(statusResult);
327
+ setSupportedChains(supportedResult);
328
+ } catch (err) {
329
+ const error2 = err instanceof Error ? err : new Error("Failed to fetch auto-confirm data");
330
+ setError(error2);
331
+ } finally {
332
+ setIsLoading(false);
333
+ }
334
+ }, [sdk, isInjected]);
351
335
  (0, import_react4.useEffect)(() => {
352
336
  if (sdk && isInjected) {
353
337
  refetch();
@@ -381,36 +365,51 @@ function useSolana() {
381
365
  return null;
382
366
  }
383
367
  }, [sdk, isConnected]);
384
- const signMessage = (0, import_react5.useCallback)(async (message) => {
385
- if (!solanaChain)
386
- throw new Error("Solana chain not available. Ensure SDK is connected.");
387
- return solanaChain.signMessage(message);
388
- }, [solanaChain]);
389
- const signTransaction = (0, import_react5.useCallback)(async (transaction) => {
390
- if (!solanaChain)
391
- throw new Error("Solana chain not available. Ensure SDK is connected.");
392
- return solanaChain.signTransaction(transaction);
393
- }, [solanaChain]);
394
- const signAndSendTransaction = (0, import_react5.useCallback)(async (transaction) => {
395
- if (!solanaChain)
396
- throw new Error("Solana chain not available. Ensure SDK is connected.");
397
- return solanaChain.signAndSendTransaction(transaction);
398
- }, [solanaChain]);
399
- const connect = (0, import_react5.useCallback)(async (options) => {
400
- if (!solanaChain)
401
- throw new Error("Solana chain not available. Ensure SDK is connected.");
402
- return solanaChain.connect(options);
403
- }, [solanaChain]);
368
+ const signMessage = (0, import_react5.useCallback)(
369
+ async (message) => {
370
+ if (!solanaChain)
371
+ throw new Error("Solana chain not available. Ensure SDK is connected.");
372
+ return solanaChain.signMessage(message);
373
+ },
374
+ [solanaChain]
375
+ );
376
+ const signTransaction = (0, import_react5.useCallback)(
377
+ async (transaction) => {
378
+ if (!solanaChain)
379
+ throw new Error("Solana chain not available. Ensure SDK is connected.");
380
+ return solanaChain.signTransaction(transaction);
381
+ },
382
+ [solanaChain]
383
+ );
384
+ const signAndSendTransaction = (0, import_react5.useCallback)(
385
+ async (transaction) => {
386
+ if (!solanaChain)
387
+ throw new Error("Solana chain not available. Ensure SDK is connected.");
388
+ return solanaChain.signAndSendTransaction(transaction);
389
+ },
390
+ [solanaChain]
391
+ );
392
+ const connect = (0, import_react5.useCallback)(
393
+ async (options) => {
394
+ if (!solanaChain)
395
+ throw new Error("Solana chain not available. Ensure SDK is connected.");
396
+ return solanaChain.connect(options);
397
+ },
398
+ [solanaChain]
399
+ );
404
400
  const disconnect = (0, import_react5.useCallback)(async () => {
405
401
  if (!solanaChain)
406
402
  throw new Error("Solana chain not available. Ensure SDK is connected.");
407
403
  return solanaChain.disconnect();
408
404
  }, [solanaChain]);
409
- const switchNetwork = (0, import_react5.useCallback)(async (network) => {
410
- if (!solanaChain)
411
- throw new Error("Solana chain not available. Ensure SDK is connected.");
412
- return solanaChain.switchNetwork(network);
413
- }, [solanaChain]);
405
+ const switchNetwork = (0, import_react5.useCallback)(
406
+ async (network) => {
407
+ if (!solanaChain)
408
+ throw new Error("Solana chain not available. Ensure SDK is connected.");
409
+ return solanaChain.switchNetwork?.(network);
410
+ },
411
+ [solanaChain]
412
+ );
414
413
  const getPublicKey = (0, import_react5.useCallback)(async () => {
415
414
  if (!solanaChain)
416
415
  return null;
@@ -446,27 +445,39 @@ function useEthereum() {
446
445
  return null;
447
446
  }
448
447
  }, [sdk, isConnected]);
449
- const request = (0, import_react6.useCallback)(async (args) => {
450
- if (!ethereumChain)
451
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
452
- return ethereumChain.request(args);
453
- }, [ethereumChain]);
454
- const signPersonalMessage = (0, import_react6.useCallback)(async (message, address) => {
455
- return request({
456
- method: "personal_sign",
457
- params: [message, address]
458
- });
459
- }, [request]);
460
- const sendTransaction = (0, import_react6.useCallback)(async (transaction) => {
461
- if (!ethereumChain)
462
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
463
- return ethereumChain.sendTransaction(transaction);
464
- }, [ethereumChain]);
465
- const switchChain = (0, import_react6.useCallback)(async (chainId) => {
466
- if (!ethereumChain)
467
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
468
- return ethereumChain.switchChain(chainId);
469
- }, [ethereumChain]);
448
+ const request = (0, import_react6.useCallback)(
449
+ async (args) => {
450
+ if (!ethereumChain)
451
+ throw new Error("Ethereum chain not available. Ensure SDK is connected.");
452
+ return ethereumChain.request(args);
453
+ },
454
+ [ethereumChain]
455
+ );
456
+ const signPersonalMessage = (0, import_react6.useCallback)(
457
+ async (message, address) => {
458
+ return request({
459
+ method: "personal_sign",
460
+ params: [message, address]
461
+ });
462
+ },
463
+ [request]
464
+ );
465
+ const sendTransaction = (0, import_react6.useCallback)(
466
+ async (transaction) => {
467
+ if (!ethereumChain)
468
+ throw new Error("Ethereum chain not available. Ensure SDK is connected.");
469
+ return ethereumChain.sendTransaction(transaction);
470
+ },
471
+ [ethereumChain]
472
+ );
473
+ const switchChain = (0, import_react6.useCallback)(
474
+ async (chainId) => {
475
+ if (!ethereumChain)
476
+ throw new Error("Ethereum chain not available. Ensure SDK is connected.");
477
+ return ethereumChain.switchChain(chainId);
478
+ },
479
+ [ethereumChain]
480
+ );
470
481
  const getChainId = (0, import_react6.useCallback)(async () => {
471
482
  if (!ethereumChain)
472
483
  throw new Error("Ethereum chain not available. Ensure SDK is connected.");
@@ -477,19 +488,25 @@ function useEthereum() {
477
488
  throw new Error("Ethereum chain not available. Ensure SDK is connected.");
478
489
  return ethereumChain.getAccounts();
479
490
  }, [ethereumChain]);
480
- const signMessage = (0, import_react6.useCallback)(async (message) => {
481
- return request({
482
- method: "eth_sign",
483
- params: [await getAccounts().then((accounts) => accounts[0]), message]
484
- });
485
- }, [request, getAccounts]);
486
- const signTypedData = (0, import_react6.useCallback)(async (typedData) => {
487
- const accounts = await getAccounts();
488
- return request({
489
- method: "eth_signTypedData_v4",
490
- params: [accounts[0], JSON.stringify(typedData)]
491
- });
492
- }, [request, getAccounts]);
491
+ const signMessage = (0, import_react6.useCallback)(
492
+ async (message) => {
493
+ return request({
494
+ method: "eth_sign",
495
+ params: [await getAccounts().then((accounts) => accounts[0]), message]
496
+ });
497
+ },
498
+ [request, getAccounts]
499
+ );
500
+ const signTypedData = (0, import_react6.useCallback)(
501
+ async (typedData) => {
502
+ const accounts = await getAccounts();
503
+ return request({
504
+ method: "eth_signTypedData_v4",
505
+ params: [accounts[0], JSON.stringify(typedData)]
506
+ });
507
+ },
508
+ [request, getAccounts]
509
+ );
493
510
  return {
494
511
  // Chain instance for advanced usage
495
512
  ethereum: ethereumChain,
package/dist/index.mjs CHANGED
@@ -4,14 +4,6 @@ import { BrowserSDK } from "@phantom/browser-sdk";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  var PhantomContext = createContext(void 0);
6
6
  function PhantomProvider({ children, config, debugConfig }) {
7
- const [isConnected, setIsConnected] = useState(false);
8
- const [isConnecting, setIsConnecting] = useState(false);
9
- const [connectError, setConnectError] = useState(null);
10
- const [addresses, setAddresses] = useState([]);
11
- const [walletId, setWalletId] = useState(null);
12
- const [currentProviderType, setCurrentProviderType] = useState(config.providerType || null);
13
- const [isPhantomAvailable, setIsPhantomAvailable] = useState(false);
14
- const [sdk, setSdk] = useState(null);
15
7
  const memoizedConfig = useMemo(() => {
16
8
  return {
17
9
  ...config,
@@ -19,6 +11,16 @@ function PhantomProvider({ children, config, debugConfig }) {
19
11
  providerType: config.providerType || "embedded"
20
12
  };
21
13
  }, [config]);
14
+ const [isConnected, setIsConnected] = useState(false);
15
+ const [isConnecting, setIsConnecting] = useState(false);
16
+ const [connectError, setConnectError] = useState(null);
17
+ const [addresses, setAddresses] = useState([]);
18
+ const [walletId, setWalletId] = useState(null);
19
+ const [currentProviderType, setCurrentProviderType] = useState(
20
+ memoizedConfig.providerType || null
21
+ );
22
+ const [isPhantomAvailable, setIsPhantomAvailable] = useState(false);
23
+ const [sdk, setSdk] = useState(null);
22
24
  useEffect(() => {
23
25
  const sdkInstance = new BrowserSDK(memoizedConfig);
24
26
  const handleConnectStart = () => {
@@ -75,21 +77,21 @@ function PhantomProvider({ children, config, debugConfig }) {
75
77
  useEffect(() => {
76
78
  if (!sdk)
77
79
  return;
78
- const initialize = () => {
80
+ const initialize = async () => {
79
81
  try {
80
- const available = BrowserSDK.isPhantomInstalled();
82
+ const available = await BrowserSDK.isPhantomInstalled();
81
83
  setIsPhantomAvailable(available);
82
84
  } catch (err) {
83
85
  console.error("Error checking Phantom extension:", err);
84
86
  setIsPhantomAvailable(false);
85
87
  }
86
- if (config.autoConnect !== false) {
88
+ if (memoizedConfig.autoConnect !== false) {
87
89
  sdk.autoConnect().catch(() => {
88
90
  });
89
91
  }
90
92
  };
91
93
  initialize();
92
- }, [sdk, config.autoConnect]);
94
+ }, [sdk, memoizedConfig.autoConnect]);
93
95
  const value = useMemo(
94
96
  () => ({
95
97
  sdk,
@@ -101,16 +103,7 @@ function PhantomProvider({ children, config, debugConfig }) {
101
103
  currentProviderType,
102
104
  isPhantomAvailable
103
105
  }),
104
- [
105
- sdk,
106
- isConnected,
107
- isConnecting,
108
- connectError,
109
- addresses,
110
- walletId,
111
- currentProviderType,
112
- isPhantomAvailable
113
- ]
106
+ [sdk, isConnected, isConnecting, connectError, addresses, walletId, currentProviderType, isPhantomAvailable]
114
107
  );
115
108
  return /* @__PURE__ */ jsx(PhantomContext.Provider, { value, children });
116
109
  }
@@ -186,37 +179,34 @@ function useAccounts() {
186
179
 
187
180
  // src/hooks/useIsExtensionInstalled.ts
188
181
  import * as React from "react";
189
- import { BrowserSDK as BrowserSDK2 } from "@phantom/browser-sdk";
190
- var cachedIsInstalled = null;
182
+ import { waitForPhantomExtension } from "@phantom/browser-sdk";
191
183
  function useIsExtensionInstalled() {
192
- const { sdk } = usePhantom();
193
- const [isLoading, setIsLoading] = React.useState(cachedIsInstalled === null);
194
- const [isInstalled, setIsInstalled] = React.useState(cachedIsInstalled ?? false);
184
+ const [isLoading, setIsLoading] = React.useState(true);
185
+ const [isInstalled, setIsInstalled] = React.useState(false);
195
186
  React.useEffect(() => {
196
- if (!sdk) {
197
- setIsLoading(false);
198
- return;
199
- }
200
- if (cachedIsInstalled !== null) {
201
- setIsInstalled(cachedIsInstalled);
202
- setIsLoading(false);
203
- return;
204
- }
205
- const checkExtension = () => {
187
+ let isMounted = true;
188
+ const checkExtension = async () => {
206
189
  try {
207
190
  setIsLoading(true);
208
- const result = BrowserSDK2.isPhantomInstalled();
209
- cachedIsInstalled = result;
210
- setIsInstalled(result);
191
+ const result = await waitForPhantomExtension(3e3);
192
+ if (isMounted) {
193
+ setIsInstalled(result);
194
+ }
211
195
  } catch (error) {
212
- cachedIsInstalled = false;
213
- setIsInstalled(false);
196
+ if (isMounted) {
197
+ setIsInstalled(false);
198
+ }
214
199
  } finally {
215
- setIsLoading(false);
200
+ if (isMounted) {
201
+ setIsLoading(false);
202
+ }
216
203
  }
217
204
  };
218
205
  checkExtension();
219
- }, [sdk]);
206
+ return () => {
207
+ isMounted = false;
208
+ };
209
+ }, []);
220
210
  return { isLoading, isInstalled };
221
211
  }
222
212
 
@@ -253,53 +243,47 @@ function useAutoConfirm() {
253
243
  },
254
244
  [sdk, isInjected]
255
245
  );
256
- const disable = useCallback3(
257
- async () => {
258
- if (!sdk) {
259
- throw new Error("SDK not initialized");
260
- }
261
- if (!isInjected) {
262
- throw new Error("Auto-confirm is only available for injected (extension) providers");
263
- }
264
- try {
265
- setIsLoading(true);
266
- setError(null);
267
- await sdk.disableAutoConfirm();
268
- const newStatus = await sdk.getAutoConfirmStatus();
269
- setStatus(newStatus);
270
- } catch (err) {
271
- const error2 = err instanceof Error ? err : new Error("Unknown error occurred");
272
- setError(error2);
273
- throw error2;
274
- } finally {
275
- setIsLoading(false);
276
- }
277
- },
278
- [sdk, isInjected]
279
- );
280
- const refetch = useCallback3(
281
- async () => {
282
- if (!sdk || !isInjected) {
283
- return;
284
- }
285
- try {
286
- setIsLoading(true);
287
- setError(null);
288
- const [statusResult, supportedResult] = await Promise.all([
289
- sdk.getAutoConfirmStatus(),
290
- sdk.getSupportedAutoConfirmChains()
291
- ]);
292
- setStatus(statusResult);
293
- setSupportedChains(supportedResult);
294
- } catch (err) {
295
- const error2 = err instanceof Error ? err : new Error("Failed to fetch auto-confirm data");
296
- setError(error2);
297
- } finally {
298
- setIsLoading(false);
299
- }
300
- },
301
- [sdk, isInjected]
302
- );
246
+ const disable = useCallback3(async () => {
247
+ if (!sdk) {
248
+ throw new Error("SDK not initialized");
249
+ }
250
+ if (!isInjected) {
251
+ throw new Error("Auto-confirm is only available for injected (extension) providers");
252
+ }
253
+ try {
254
+ setIsLoading(true);
255
+ setError(null);
256
+ await sdk.disableAutoConfirm();
257
+ const newStatus = await sdk.getAutoConfirmStatus();
258
+ setStatus(newStatus);
259
+ } catch (err) {
260
+ const error2 = err instanceof Error ? err : new Error("Unknown error occurred");
261
+ setError(error2);
262
+ throw error2;
263
+ } finally {
264
+ setIsLoading(false);
265
+ }
266
+ }, [sdk, isInjected]);
267
+ const refetch = useCallback3(async () => {
268
+ if (!sdk || !isInjected) {
269
+ return;
270
+ }
271
+ try {
272
+ setIsLoading(true);
273
+ setError(null);
274
+ const [statusResult, supportedResult] = await Promise.all([
275
+ sdk.getAutoConfirmStatus(),
276
+ sdk.getSupportedAutoConfirmChains()
277
+ ]);
278
+ setStatus(statusResult);
279
+ setSupportedChains(supportedResult);
280
+ } catch (err) {
281
+ const error2 = err instanceof Error ? err : new Error("Failed to fetch auto-confirm data");
282
+ setError(error2);
283
+ } finally {
284
+ setIsLoading(false);
285
+ }
286
+ }, [sdk, isInjected]);
303
287
  useEffect3(() => {
304
288
  if (sdk && isInjected) {
305
289
  refetch();
@@ -333,36 +317,51 @@ function useSolana() {
333
317
  return null;
334
318
  }
335
319
  }, [sdk, isConnected]);
336
- const signMessage = useCallback4(async (message) => {
337
- if (!solanaChain)
338
- throw new Error("Solana chain not available. Ensure SDK is connected.");
339
- return solanaChain.signMessage(message);
340
- }, [solanaChain]);
341
- const signTransaction = useCallback4(async (transaction) => {
342
- if (!solanaChain)
343
- throw new Error("Solana chain not available. Ensure SDK is connected.");
344
- return solanaChain.signTransaction(transaction);
345
- }, [solanaChain]);
346
- const signAndSendTransaction = useCallback4(async (transaction) => {
347
- if (!solanaChain)
348
- throw new Error("Solana chain not available. Ensure SDK is connected.");
349
- return solanaChain.signAndSendTransaction(transaction);
350
- }, [solanaChain]);
351
- const connect = useCallback4(async (options) => {
352
- if (!solanaChain)
353
- throw new Error("Solana chain not available. Ensure SDK is connected.");
354
- return solanaChain.connect(options);
355
- }, [solanaChain]);
320
+ const signMessage = useCallback4(
321
+ async (message) => {
322
+ if (!solanaChain)
323
+ throw new Error("Solana chain not available. Ensure SDK is connected.");
324
+ return solanaChain.signMessage(message);
325
+ },
326
+ [solanaChain]
327
+ );
328
+ const signTransaction = useCallback4(
329
+ async (transaction) => {
330
+ if (!solanaChain)
331
+ throw new Error("Solana chain not available. Ensure SDK is connected.");
332
+ return solanaChain.signTransaction(transaction);
333
+ },
334
+ [solanaChain]
335
+ );
336
+ const signAndSendTransaction = useCallback4(
337
+ async (transaction) => {
338
+ if (!solanaChain)
339
+ throw new Error("Solana chain not available. Ensure SDK is connected.");
340
+ return solanaChain.signAndSendTransaction(transaction);
341
+ },
342
+ [solanaChain]
343
+ );
344
+ const connect = useCallback4(
345
+ async (options) => {
346
+ if (!solanaChain)
347
+ throw new Error("Solana chain not available. Ensure SDK is connected.");
348
+ return solanaChain.connect(options);
349
+ },
350
+ [solanaChain]
351
+ );
356
352
  const disconnect = useCallback4(async () => {
357
353
  if (!solanaChain)
358
354
  throw new Error("Solana chain not available. Ensure SDK is connected.");
359
355
  return solanaChain.disconnect();
360
356
  }, [solanaChain]);
361
- const switchNetwork = useCallback4(async (network) => {
362
- if (!solanaChain)
363
- throw new Error("Solana chain not available. Ensure SDK is connected.");
364
- return solanaChain.switchNetwork(network);
365
- }, [solanaChain]);
357
+ const switchNetwork = useCallback4(
358
+ async (network) => {
359
+ if (!solanaChain)
360
+ throw new Error("Solana chain not available. Ensure SDK is connected.");
361
+ return solanaChain.switchNetwork?.(network);
362
+ },
363
+ [solanaChain]
364
+ );
366
365
  const getPublicKey = useCallback4(async () => {
367
366
  if (!solanaChain)
368
367
  return null;
@@ -398,27 +397,39 @@ function useEthereum() {
398
397
  return null;
399
398
  }
400
399
  }, [sdk, isConnected]);
401
- const request = useCallback5(async (args) => {
402
- if (!ethereumChain)
403
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
404
- return ethereumChain.request(args);
405
- }, [ethereumChain]);
406
- const signPersonalMessage = useCallback5(async (message, address) => {
407
- return request({
408
- method: "personal_sign",
409
- params: [message, address]
410
- });
411
- }, [request]);
412
- const sendTransaction = useCallback5(async (transaction) => {
413
- if (!ethereumChain)
414
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
415
- return ethereumChain.sendTransaction(transaction);
416
- }, [ethereumChain]);
417
- const switchChain = useCallback5(async (chainId) => {
418
- if (!ethereumChain)
419
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
420
- return ethereumChain.switchChain(chainId);
421
- }, [ethereumChain]);
400
+ const request = useCallback5(
401
+ async (args) => {
402
+ if (!ethereumChain)
403
+ throw new Error("Ethereum chain not available. Ensure SDK is connected.");
404
+ return ethereumChain.request(args);
405
+ },
406
+ [ethereumChain]
407
+ );
408
+ const signPersonalMessage = useCallback5(
409
+ async (message, address) => {
410
+ return request({
411
+ method: "personal_sign",
412
+ params: [message, address]
413
+ });
414
+ },
415
+ [request]
416
+ );
417
+ const sendTransaction = useCallback5(
418
+ async (transaction) => {
419
+ if (!ethereumChain)
420
+ throw new Error("Ethereum chain not available. Ensure SDK is connected.");
421
+ return ethereumChain.sendTransaction(transaction);
422
+ },
423
+ [ethereumChain]
424
+ );
425
+ const switchChain = useCallback5(
426
+ async (chainId) => {
427
+ if (!ethereumChain)
428
+ throw new Error("Ethereum chain not available. Ensure SDK is connected.");
429
+ return ethereumChain.switchChain(chainId);
430
+ },
431
+ [ethereumChain]
432
+ );
422
433
  const getChainId = useCallback5(async () => {
423
434
  if (!ethereumChain)
424
435
  throw new Error("Ethereum chain not available. Ensure SDK is connected.");
@@ -429,19 +440,25 @@ function useEthereum() {
429
440
  throw new Error("Ethereum chain not available. Ensure SDK is connected.");
430
441
  return ethereumChain.getAccounts();
431
442
  }, [ethereumChain]);
432
- const signMessage = useCallback5(async (message) => {
433
- return request({
434
- method: "eth_sign",
435
- params: [await getAccounts().then((accounts) => accounts[0]), message]
436
- });
437
- }, [request, getAccounts]);
438
- const signTypedData = useCallback5(async (typedData) => {
439
- const accounts = await getAccounts();
440
- return request({
441
- method: "eth_signTypedData_v4",
442
- params: [accounts[0], JSON.stringify(typedData)]
443
- });
444
- }, [request, getAccounts]);
443
+ const signMessage = useCallback5(
444
+ async (message) => {
445
+ return request({
446
+ method: "eth_sign",
447
+ params: [await getAccounts().then((accounts) => accounts[0]), message]
448
+ });
449
+ },
450
+ [request, getAccounts]
451
+ );
452
+ const signTypedData = useCallback5(
453
+ async (typedData) => {
454
+ const accounts = await getAccounts();
455
+ return request({
456
+ method: "eth_signTypedData_v4",
457
+ params: [accounts[0], JSON.stringify(typedData)]
458
+ });
459
+ },
460
+ [request, getAccounts]
461
+ );
445
462
  return {
446
463
  // Chain instance for advanced usage
447
464
  ethereum: ethereumChain,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/react-sdk",
3
- "version": "1.0.0-beta.0",
3
+ "version": "1.0.0-beta.1",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -26,9 +26,9 @@
26
26
  "prettier": "prettier --write \"src/**/*.{ts,tsx}\""
27
27
  },
28
28
  "dependencies": {
29
- "@phantom/browser-sdk": "^1.0.0-beta.0",
30
- "@phantom/chains": "^1.0.0-beta.0",
31
- "@phantom/constants": "^1.0.0-beta.0"
29
+ "@phantom/browser-sdk": "^1.0.0-beta.1",
30
+ "@phantom/chains": "^1.0.0-beta.1",
31
+ "@phantom/constants": "^1.0.0-beta.1"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@testing-library/dom": "^10.4.0",