@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 +38 -51
- package/dist/index.d.ts +13 -5
- package/dist/index.js +166 -149
- package/dist/index.mjs +167 -150
- package/package.json +4 -4
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(
|
|
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 ?
|
|
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 ?
|
|
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(
|
|
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(
|
|
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
|
|
782
|
-
|
|
|
783
|
-
| `useConnect`
|
|
784
|
-
| `useAccounts`
|
|
785
|
-
| `useIsExtensionInstalled`
|
|
786
|
-
| `useDisconnect`
|
|
787
|
-
| `useAutoConfirm`
|
|
788
|
-
| `useSolana`
|
|
789
|
-
| `useEthereum`
|
|
790
|
-
| `usePhantom`
|
|
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
|
-
|
|
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;
|
|
823
|
-
level?: DebugLevel;
|
|
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;
|
|
870
|
-
level: DebugLevel;
|
|
871
|
-
category: string;
|
|
872
|
-
message: string;
|
|
873
|
-
data?: any;
|
|
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<
|
|
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<
|
|
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<
|
|
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 (
|
|
136
|
+
if (memoizedConfig.autoConnect !== false) {
|
|
135
137
|
sdk.autoConnect().catch(() => {
|
|
136
138
|
});
|
|
137
139
|
}
|
|
138
140
|
};
|
|
139
141
|
initialize();
|
|
140
|
-
}, [sdk,
|
|
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
|
|
241
|
-
const [
|
|
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
|
-
|
|
245
|
-
|
|
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.
|
|
257
|
-
|
|
258
|
-
|
|
239
|
+
const result = await (0, import_browser_sdk2.waitForPhantomExtension)(3e3);
|
|
240
|
+
if (isMounted) {
|
|
241
|
+
setIsInstalled(result);
|
|
242
|
+
}
|
|
259
243
|
} catch (error) {
|
|
260
|
-
|
|
261
|
-
|
|
244
|
+
if (isMounted) {
|
|
245
|
+
setIsInstalled(false);
|
|
246
|
+
}
|
|
262
247
|
} finally {
|
|
263
|
-
|
|
248
|
+
if (isMounted) {
|
|
249
|
+
setIsLoading(false);
|
|
250
|
+
}
|
|
264
251
|
}
|
|
265
252
|
};
|
|
266
253
|
checkExtension();
|
|
267
|
-
|
|
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
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
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)(
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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)(
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
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)(
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
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)(
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
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 (
|
|
88
|
+
if (memoizedConfig.autoConnect !== false) {
|
|
87
89
|
sdk.autoConnect().catch(() => {
|
|
88
90
|
});
|
|
89
91
|
}
|
|
90
92
|
};
|
|
91
93
|
initialize();
|
|
92
|
-
}, [sdk,
|
|
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 {
|
|
190
|
-
var cachedIsInstalled = null;
|
|
182
|
+
import { waitForPhantomExtension } from "@phantom/browser-sdk";
|
|
191
183
|
function useIsExtensionInstalled() {
|
|
192
|
-
const
|
|
193
|
-
const [
|
|
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
|
-
|
|
197
|
-
|
|
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 =
|
|
209
|
-
|
|
210
|
-
|
|
191
|
+
const result = await waitForPhantomExtension(3e3);
|
|
192
|
+
if (isMounted) {
|
|
193
|
+
setIsInstalled(result);
|
|
194
|
+
}
|
|
211
195
|
} catch (error) {
|
|
212
|
-
|
|
213
|
-
|
|
196
|
+
if (isMounted) {
|
|
197
|
+
setIsInstalled(false);
|
|
198
|
+
}
|
|
214
199
|
} finally {
|
|
215
|
-
|
|
200
|
+
if (isMounted) {
|
|
201
|
+
setIsLoading(false);
|
|
202
|
+
}
|
|
216
203
|
}
|
|
217
204
|
};
|
|
218
205
|
checkExtension();
|
|
219
|
-
|
|
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
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
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(
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
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(
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
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(
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
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.
|
|
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.
|
|
30
|
-
"@phantom/chains": "^1.0.0-beta.
|
|
31
|
-
"@phantom/constants": "^1.0.0-beta.
|
|
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",
|