@phantom/react-sdk 1.0.0-beta.1 → 1.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -62
- package/dist/index.d.ts +6 -35
- package/dist/index.js +20 -174
- package/dist/index.mjs +20 -174
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -94,9 +94,8 @@ function App() {
|
|
|
94
94
|
<PhantomProvider
|
|
95
95
|
config={{
|
|
96
96
|
providerType: "embedded",
|
|
97
|
-
|
|
97
|
+
appId: "your-app-id", // Get your app ID from phantom.com/portal
|
|
98
98
|
addressTypes: [AddressType.solana, AddressType.ethereum],
|
|
99
|
-
apiBaseUrl: "https://api.phantom.app/v1/wallets",
|
|
100
99
|
}}
|
|
101
100
|
>
|
|
102
101
|
<YourApp />
|
|
@@ -181,26 +180,7 @@ Uses the Phantom browser extension installed by the user.
|
|
|
181
180
|
|
|
182
181
|
Creates non-custodial wallets embedded in your application.
|
|
183
182
|
|
|
184
|
-
####
|
|
185
|
-
|
|
186
|
-
- **New wallets** created per application
|
|
187
|
-
- **Unfunded** by default - you need to fund them
|
|
188
|
-
- **Independent** from user's existing Phantom wallet
|
|
189
|
-
|
|
190
|
-
```tsx
|
|
191
|
-
<PhantomProvider
|
|
192
|
-
config={{
|
|
193
|
-
providerType: "embedded",
|
|
194
|
-
embeddedWalletType: "app-wallet",
|
|
195
|
-
addressTypes: [AddressType.solana],
|
|
196
|
-
apiBaseUrl: "https://api.phantom.app/v1/wallets",
|
|
197
|
-
}}
|
|
198
|
-
>
|
|
199
|
-
<YourApp />
|
|
200
|
-
</PhantomProvider>
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
#### User Wallet (For existing Phantom users)
|
|
183
|
+
#### User Wallet
|
|
204
184
|
|
|
205
185
|
- **Uses Phantom authentication** - user logs in with existing account
|
|
206
186
|
- **Potentially funded** - brings existing wallet balance
|
|
@@ -210,41 +190,14 @@ Creates non-custodial wallets embedded in your application.
|
|
|
210
190
|
<PhantomProvider
|
|
211
191
|
config={{
|
|
212
192
|
providerType: "embedded",
|
|
213
|
-
|
|
193
|
+
appId: "your-app-id",
|
|
214
194
|
addressTypes: [AddressType.solana, AddressType.ethereum],
|
|
215
|
-
apiBaseUrl: "https://api.phantom.app/v1/wallets",
|
|
216
|
-
}}
|
|
217
|
-
>
|
|
218
|
-
<YourApp />
|
|
219
|
-
</PhantomProvider>
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
## Solana Provider Configuration
|
|
223
|
-
|
|
224
|
-
When using `AddressType.solana`, you can choose between two Solana libraries:
|
|
225
|
-
|
|
226
|
-
```tsx
|
|
227
|
-
<PhantomProvider
|
|
228
|
-
config={{
|
|
229
|
-
providerType: "embedded",
|
|
230
|
-
addressTypes: [AddressType.solana],
|
|
231
|
-
solanaProvider: "web3js", // or 'kit'
|
|
232
|
-
apiBaseUrl: "https://api.phantom.app/v1/wallets",
|
|
233
195
|
}}
|
|
234
196
|
>
|
|
235
197
|
<YourApp />
|
|
236
198
|
</PhantomProvider>
|
|
237
199
|
```
|
|
238
200
|
|
|
239
|
-
**Provider Options:**
|
|
240
|
-
|
|
241
|
-
- `'web3js'` (default) - Uses `@solana/web3.js` library
|
|
242
|
-
- `'kit'` - Uses `@solana/kit` library (modern, TypeScript-first)
|
|
243
|
-
|
|
244
|
-
**When to use each:**
|
|
245
|
-
|
|
246
|
-
- **@solana/web3.js**: Better ecosystem compatibility, wider community support
|
|
247
|
-
- **@solana/kit**: Better TypeScript support, modern architecture, smaller bundle size
|
|
248
201
|
|
|
249
202
|
## Available Hooks
|
|
250
203
|
|
|
@@ -392,7 +345,7 @@ function SolanaOperations() {
|
|
|
392
345
|
|
|
393
346
|
// Sign and send
|
|
394
347
|
const result = await solana.signAndSendTransaction(transaction);
|
|
395
|
-
console.log("Transaction sent:", result.
|
|
348
|
+
console.log("Transaction sent:", result.signature);
|
|
396
349
|
};
|
|
397
350
|
|
|
398
351
|
const switchNetwork = async () => {
|
|
@@ -470,6 +423,16 @@ function EthereumOperations() {
|
|
|
470
423
|
console.log("Typed data signature:", signature);
|
|
471
424
|
};
|
|
472
425
|
|
|
426
|
+
const signTransaction = async () => {
|
|
427
|
+
const signedTx = await ethereum.signTransaction({
|
|
428
|
+
to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
429
|
+
value: "1000000000000000000", // 1 ETH in wei
|
|
430
|
+
gas: "21000",
|
|
431
|
+
});
|
|
432
|
+
console.log("Transaction signed:", signedTx);
|
|
433
|
+
// Transaction is signed but not sent - you can broadcast it later
|
|
434
|
+
};
|
|
435
|
+
|
|
473
436
|
const sendTransaction = async () => {
|
|
474
437
|
const result = await ethereum.sendTransaction({
|
|
475
438
|
to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
@@ -487,7 +450,8 @@ function EthereumOperations() {
|
|
|
487
450
|
<div>
|
|
488
451
|
<button onClick={signPersonalMessage}>Sign Personal Message</button>
|
|
489
452
|
<button onClick={signTypedData}>Sign Typed Data</button>
|
|
490
|
-
<button onClick={
|
|
453
|
+
<button onClick={signTransaction}>Sign Transaction</button>
|
|
454
|
+
<button onClick={sendTransaction}>Sign & Send Transaction</button>
|
|
491
455
|
<button onClick={switchChain}>Switch to Polygon</button>
|
|
492
456
|
<p>Connected: {ethereum.isConnected ? "Yes" : "No"}</p>
|
|
493
457
|
</div>
|
|
@@ -500,7 +464,8 @@ function EthereumOperations() {
|
|
|
500
464
|
- `request(args)` - EIP-1193 requests
|
|
501
465
|
- `signPersonalMessage(message, address)` - Sign personal message
|
|
502
466
|
- `signTypedData(typedData)` - Sign EIP-712 typed data
|
|
503
|
-
- `
|
|
467
|
+
- `signTransaction(transaction)` - Sign transaction without sending
|
|
468
|
+
- `sendTransaction(transaction)` - Sign and send transaction
|
|
504
469
|
- `switchChain(chainId)` - Switch chains
|
|
505
470
|
- `getChainId()` - Get current chain ID
|
|
506
471
|
- `getAccounts()` - Get connected accounts
|
|
@@ -675,7 +640,7 @@ function SolanaExample() {
|
|
|
675
640
|
|
|
676
641
|
// Sign and send using chain-specific hook
|
|
677
642
|
const result = await solana.signAndSendTransaction(transaction);
|
|
678
|
-
console.log("Transaction sent:", result.
|
|
643
|
+
console.log("Transaction sent:", result.signature);
|
|
679
644
|
};
|
|
680
645
|
|
|
681
646
|
return <button onClick={sendTransaction}>Send SOL</button>;
|
|
@@ -714,7 +679,7 @@ function SolanaKitExample() {
|
|
|
714
679
|
|
|
715
680
|
// Sign and send using chain-specific hook
|
|
716
681
|
const result = await solana.signAndSendTransaction(transaction);
|
|
717
|
-
console.log("Transaction sent:", result.
|
|
682
|
+
console.log("Transaction sent:", result.signature);
|
|
718
683
|
};
|
|
719
684
|
|
|
720
685
|
return <button onClick={sendTransaction}>Send SOL</button>;
|
|
@@ -787,15 +752,16 @@ interface PhantomSDKConfig {
|
|
|
787
752
|
addressTypes?: [AddressType, ...AddressType[]]; // Networks to enable (e.g., [AddressType.solana])
|
|
788
753
|
|
|
789
754
|
// Required for embedded provider only
|
|
790
|
-
|
|
791
|
-
|
|
755
|
+
appId: string; // Your app ID from phantom.com/portal (required for embedded provider)
|
|
756
|
+
|
|
757
|
+
// Optional configuration
|
|
758
|
+
apiBaseUrl?: string; // Phantom API base URL (optional, has default)
|
|
792
759
|
authOptions?: {
|
|
793
|
-
authUrl?: string; // Custom auth URL (optional)
|
|
794
|
-
redirectUrl?: string; // Custom redirect URL (optional)
|
|
760
|
+
authUrl?: string; // Custom auth URL (optional, defaults to "https://connect.phantom.app/login")
|
|
761
|
+
redirectUrl?: string; // Custom redirect URL after authentication (optional)
|
|
795
762
|
};
|
|
796
|
-
embeddedWalletType?: "
|
|
797
|
-
|
|
798
|
-
autoConnect?: boolean; // Auto-connect to existing session on SDK instantiation (default: true for embedded, false for injected)
|
|
763
|
+
embeddedWalletType?: "user-wallet"; // Wallet type (optional, defaults to "user-wallet", currently the only supported type)
|
|
764
|
+
autoConnect?: boolean; // Auto-connect to existing session on SDK instantiation (optional, defaults to true for embedded, false for injected)
|
|
799
765
|
}
|
|
800
766
|
```
|
|
801
767
|
|
|
@@ -827,6 +793,7 @@ function App() {
|
|
|
827
793
|
// SDK configuration - static, won't change when debug settings change
|
|
828
794
|
const config: PhantomSDKConfig = {
|
|
829
795
|
providerType: "embedded",
|
|
796
|
+
appId: "your-app-id",
|
|
830
797
|
// ... other config
|
|
831
798
|
};
|
|
832
799
|
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ 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
|
|
6
|
+
import * as _phantom_chains from '@phantom/chains';
|
|
7
7
|
export { EthTransactionRequest, IEthereumChain, ISolanaChain } from '@phantom/chains';
|
|
8
8
|
|
|
9
9
|
interface PhantomSDKConfig extends BrowserSDKConfig {
|
|
@@ -16,7 +16,7 @@ interface ConnectOptions {
|
|
|
16
16
|
authOptions?: AuthOptions;
|
|
17
17
|
}
|
|
18
18
|
interface PhantomContextValue {
|
|
19
|
-
sdk: BrowserSDK
|
|
19
|
+
sdk: BrowserSDK;
|
|
20
20
|
isConnected: boolean;
|
|
21
21
|
isConnecting: boolean;
|
|
22
22
|
connectError: Error | null;
|
|
@@ -72,50 +72,21 @@ declare function useAutoConfirm(): UseAutoConfirmResult;
|
|
|
72
72
|
/**
|
|
73
73
|
* Hook for Solana chain operations
|
|
74
74
|
*
|
|
75
|
-
* @returns Solana chain interface
|
|
75
|
+
* @returns Solana chain interface with connection enforcement
|
|
76
76
|
*/
|
|
77
77
|
declare function useSolana(): {
|
|
78
|
-
solana: ISolanaChain
|
|
79
|
-
signMessage: (message: string | Uint8Array) => Promise<{
|
|
80
|
-
signature: Uint8Array;
|
|
81
|
-
publicKey: string;
|
|
82
|
-
}>;
|
|
83
|
-
signTransaction: <T>(transaction: T) => Promise<T>;
|
|
84
|
-
signAndSendTransaction: <T>(transaction: T) => Promise<{
|
|
85
|
-
signature: string;
|
|
86
|
-
}>;
|
|
87
|
-
connect: (options?: {
|
|
88
|
-
onlyIfTrusted?: boolean;
|
|
89
|
-
}) => Promise<{
|
|
90
|
-
publicKey: string;
|
|
91
|
-
}>;
|
|
92
|
-
disconnect: () => Promise<void>;
|
|
93
|
-
switchNetwork: (network: "mainnet" | "devnet") => Promise<void | undefined>;
|
|
94
|
-
getPublicKey: () => Promise<string | null>;
|
|
78
|
+
solana: _phantom_chains.ISolanaChain;
|
|
95
79
|
isAvailable: boolean;
|
|
96
|
-
isConnected: boolean;
|
|
97
80
|
};
|
|
98
81
|
|
|
99
82
|
/**
|
|
100
83
|
* Hook for Ethereum chain operations
|
|
101
84
|
*
|
|
102
|
-
* @returns Ethereum chain interface
|
|
85
|
+
* @returns Ethereum chain interface with connection enforcement
|
|
103
86
|
*/
|
|
104
87
|
declare function useEthereum(): {
|
|
105
|
-
ethereum: IEthereumChain
|
|
106
|
-
request: <T = any>(args: {
|
|
107
|
-
method: string;
|
|
108
|
-
params?: unknown[];
|
|
109
|
-
}) => Promise<T>;
|
|
110
|
-
signPersonalMessage: (message: string, address: string) => Promise<string>;
|
|
111
|
-
signMessage: (message: string) => Promise<string>;
|
|
112
|
-
signTypedData: (typedData: any) => Promise<string>;
|
|
113
|
-
sendTransaction: (transaction: EthTransactionRequest) => Promise<string>;
|
|
114
|
-
switchChain: (chainId: number) => Promise<void>;
|
|
115
|
-
getChainId: () => Promise<number>;
|
|
116
|
-
getAccounts: () => Promise<string[]>;
|
|
88
|
+
ethereum: _phantom_chains.IEthereumChain;
|
|
117
89
|
isAvailable: boolean;
|
|
118
|
-
isConnected: boolean;
|
|
119
90
|
};
|
|
120
91
|
|
|
121
92
|
type ProviderType = "injected" | "embedded";
|
package/dist/index.js
CHANGED
|
@@ -68,9 +68,8 @@ function PhantomProvider({ children, config, debugConfig }) {
|
|
|
68
68
|
memoizedConfig.providerType || null
|
|
69
69
|
);
|
|
70
70
|
const [isPhantomAvailable, setIsPhantomAvailable] = (0, import_react.useState)(false);
|
|
71
|
-
const
|
|
71
|
+
const sdk = (0, import_react.useMemo)(() => new import_browser_sdk.BrowserSDK(memoizedConfig), [memoizedConfig]);
|
|
72
72
|
(0, import_react.useEffect)(() => {
|
|
73
|
-
const sdkInstance = new import_browser_sdk.BrowserSDK(memoizedConfig);
|
|
74
73
|
const handleConnectStart = () => {
|
|
75
74
|
setIsConnecting(true);
|
|
76
75
|
setConnectError(null);
|
|
@@ -79,15 +78,15 @@ function PhantomProvider({ children, config, debugConfig }) {
|
|
|
79
78
|
try {
|
|
80
79
|
setIsConnected(true);
|
|
81
80
|
setIsConnecting(false);
|
|
82
|
-
const providerInfo =
|
|
81
|
+
const providerInfo = sdk.getCurrentProviderInfo();
|
|
83
82
|
setCurrentProviderType(providerInfo?.type || null);
|
|
84
|
-
const addrs = await
|
|
83
|
+
const addrs = await sdk.getAddresses();
|
|
85
84
|
setAddresses(addrs);
|
|
86
|
-
setWalletId(
|
|
85
|
+
setWalletId(sdk.getWalletId());
|
|
87
86
|
} catch (err) {
|
|
88
87
|
console.error("Error connecting:", err);
|
|
89
88
|
try {
|
|
90
|
-
await
|
|
89
|
+
await sdk.disconnect();
|
|
91
90
|
} catch (err2) {
|
|
92
91
|
console.error("Error disconnecting:", err2);
|
|
93
92
|
}
|
|
@@ -105,18 +104,17 @@ function PhantomProvider({ children, config, debugConfig }) {
|
|
|
105
104
|
setAddresses([]);
|
|
106
105
|
setWalletId(null);
|
|
107
106
|
};
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
setSdk(sdkInstance);
|
|
107
|
+
sdk.on("connect_start", handleConnectStart);
|
|
108
|
+
sdk.on("connect", handleConnect);
|
|
109
|
+
sdk.on("connect_error", handleConnectError);
|
|
110
|
+
sdk.on("disconnect", handleDisconnect);
|
|
113
111
|
return () => {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
112
|
+
sdk.off("connect_start", handleConnectStart);
|
|
113
|
+
sdk.off("connect", handleConnect);
|
|
114
|
+
sdk.off("connect_error", handleConnectError);
|
|
115
|
+
sdk.off("disconnect", handleDisconnect);
|
|
118
116
|
};
|
|
119
|
-
}, [
|
|
117
|
+
}, [sdk]);
|
|
120
118
|
(0, import_react.useEffect)(() => {
|
|
121
119
|
if (!sdk || !debugConfig)
|
|
122
120
|
return;
|
|
@@ -353,176 +351,24 @@ function useAutoConfirm() {
|
|
|
353
351
|
}
|
|
354
352
|
|
|
355
353
|
// src/hooks/useSolana.ts
|
|
356
|
-
var import_react5 = require("react");
|
|
357
354
|
function useSolana() {
|
|
358
355
|
const { sdk, isConnected } = usePhantom();
|
|
359
|
-
const solanaChain = (0, import_react5.useMemo)(() => {
|
|
360
|
-
if (!sdk || !isConnected)
|
|
361
|
-
return null;
|
|
362
|
-
try {
|
|
363
|
-
return sdk.solana;
|
|
364
|
-
} catch {
|
|
365
|
-
return null;
|
|
366
|
-
}
|
|
367
|
-
}, [sdk, isConnected]);
|
|
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
|
-
);
|
|
400
|
-
const disconnect = (0, import_react5.useCallback)(async () => {
|
|
401
|
-
if (!solanaChain)
|
|
402
|
-
throw new Error("Solana chain not available. Ensure SDK is connected.");
|
|
403
|
-
return solanaChain.disconnect();
|
|
404
|
-
}, [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
|
-
);
|
|
413
|
-
const getPublicKey = (0, import_react5.useCallback)(async () => {
|
|
414
|
-
if (!solanaChain)
|
|
415
|
-
return null;
|
|
416
|
-
return solanaChain.getPublicKey();
|
|
417
|
-
}, [solanaChain]);
|
|
418
356
|
return {
|
|
419
|
-
// Chain instance for
|
|
420
|
-
solana:
|
|
421
|
-
// Convenient methods
|
|
422
|
-
signMessage,
|
|
423
|
-
signTransaction,
|
|
424
|
-
signAndSendTransaction,
|
|
425
|
-
connect,
|
|
426
|
-
disconnect,
|
|
427
|
-
switchNetwork,
|
|
428
|
-
getPublicKey,
|
|
357
|
+
// Chain instance with connection enforcement for signing methods
|
|
358
|
+
solana: sdk.solana,
|
|
429
359
|
// State
|
|
430
|
-
isAvailable: !!
|
|
431
|
-
isConnected: solanaChain?.isConnected() ?? false
|
|
360
|
+
isAvailable: !!isConnected
|
|
432
361
|
};
|
|
433
362
|
}
|
|
434
363
|
|
|
435
364
|
// src/hooks/useEthereum.ts
|
|
436
|
-
var import_react6 = require("react");
|
|
437
365
|
function useEthereum() {
|
|
438
366
|
const { sdk, isConnected } = usePhantom();
|
|
439
|
-
const ethereumChain = (0, import_react6.useMemo)(() => {
|
|
440
|
-
if (!sdk || !isConnected)
|
|
441
|
-
return null;
|
|
442
|
-
try {
|
|
443
|
-
return sdk.ethereum;
|
|
444
|
-
} catch {
|
|
445
|
-
return null;
|
|
446
|
-
}
|
|
447
|
-
}, [sdk, isConnected]);
|
|
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
|
-
);
|
|
481
|
-
const getChainId = (0, import_react6.useCallback)(async () => {
|
|
482
|
-
if (!ethereumChain)
|
|
483
|
-
throw new Error("Ethereum chain not available. Ensure SDK is connected.");
|
|
484
|
-
return ethereumChain.getChainId();
|
|
485
|
-
}, [ethereumChain]);
|
|
486
|
-
const getAccounts = (0, import_react6.useCallback)(async () => {
|
|
487
|
-
if (!ethereumChain)
|
|
488
|
-
throw new Error("Ethereum chain not available. Ensure SDK is connected.");
|
|
489
|
-
return ethereumChain.getAccounts();
|
|
490
|
-
}, [ethereumChain]);
|
|
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
|
-
);
|
|
510
367
|
return {
|
|
511
|
-
// Chain instance for
|
|
512
|
-
ethereum:
|
|
513
|
-
// Standard EIP-1193 interface
|
|
514
|
-
request,
|
|
515
|
-
// Convenient methods
|
|
516
|
-
signPersonalMessage,
|
|
517
|
-
signMessage,
|
|
518
|
-
signTypedData,
|
|
519
|
-
sendTransaction,
|
|
520
|
-
switchChain,
|
|
521
|
-
getChainId,
|
|
522
|
-
getAccounts,
|
|
368
|
+
// Chain instance with connection enforcement for signing methods
|
|
369
|
+
ethereum: sdk.ethereum,
|
|
523
370
|
// State
|
|
524
|
-
isAvailable: !!
|
|
525
|
-
isConnected: ethereumChain?.isConnected() ?? false
|
|
371
|
+
isAvailable: !!isConnected
|
|
526
372
|
};
|
|
527
373
|
}
|
|
528
374
|
|
package/dist/index.mjs
CHANGED
|
@@ -20,9 +20,8 @@ function PhantomProvider({ children, config, debugConfig }) {
|
|
|
20
20
|
memoizedConfig.providerType || null
|
|
21
21
|
);
|
|
22
22
|
const [isPhantomAvailable, setIsPhantomAvailable] = useState(false);
|
|
23
|
-
const
|
|
23
|
+
const sdk = useMemo(() => new BrowserSDK(memoizedConfig), [memoizedConfig]);
|
|
24
24
|
useEffect(() => {
|
|
25
|
-
const sdkInstance = new BrowserSDK(memoizedConfig);
|
|
26
25
|
const handleConnectStart = () => {
|
|
27
26
|
setIsConnecting(true);
|
|
28
27
|
setConnectError(null);
|
|
@@ -31,15 +30,15 @@ function PhantomProvider({ children, config, debugConfig }) {
|
|
|
31
30
|
try {
|
|
32
31
|
setIsConnected(true);
|
|
33
32
|
setIsConnecting(false);
|
|
34
|
-
const providerInfo =
|
|
33
|
+
const providerInfo = sdk.getCurrentProviderInfo();
|
|
35
34
|
setCurrentProviderType(providerInfo?.type || null);
|
|
36
|
-
const addrs = await
|
|
35
|
+
const addrs = await sdk.getAddresses();
|
|
37
36
|
setAddresses(addrs);
|
|
38
|
-
setWalletId(
|
|
37
|
+
setWalletId(sdk.getWalletId());
|
|
39
38
|
} catch (err) {
|
|
40
39
|
console.error("Error connecting:", err);
|
|
41
40
|
try {
|
|
42
|
-
await
|
|
41
|
+
await sdk.disconnect();
|
|
43
42
|
} catch (err2) {
|
|
44
43
|
console.error("Error disconnecting:", err2);
|
|
45
44
|
}
|
|
@@ -57,18 +56,17 @@ function PhantomProvider({ children, config, debugConfig }) {
|
|
|
57
56
|
setAddresses([]);
|
|
58
57
|
setWalletId(null);
|
|
59
58
|
};
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
setSdk(sdkInstance);
|
|
59
|
+
sdk.on("connect_start", handleConnectStart);
|
|
60
|
+
sdk.on("connect", handleConnect);
|
|
61
|
+
sdk.on("connect_error", handleConnectError);
|
|
62
|
+
sdk.on("disconnect", handleDisconnect);
|
|
65
63
|
return () => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
64
|
+
sdk.off("connect_start", handleConnectStart);
|
|
65
|
+
sdk.off("connect", handleConnect);
|
|
66
|
+
sdk.off("connect_error", handleConnectError);
|
|
67
|
+
sdk.off("disconnect", handleDisconnect);
|
|
70
68
|
};
|
|
71
|
-
}, [
|
|
69
|
+
}, [sdk]);
|
|
72
70
|
useEffect(() => {
|
|
73
71
|
if (!sdk || !debugConfig)
|
|
74
72
|
return;
|
|
@@ -305,176 +303,24 @@ function useAutoConfirm() {
|
|
|
305
303
|
}
|
|
306
304
|
|
|
307
305
|
// src/hooks/useSolana.ts
|
|
308
|
-
import { useCallback as useCallback4, useMemo as useMemo2 } from "react";
|
|
309
306
|
function useSolana() {
|
|
310
307
|
const { sdk, isConnected } = usePhantom();
|
|
311
|
-
const solanaChain = useMemo2(() => {
|
|
312
|
-
if (!sdk || !isConnected)
|
|
313
|
-
return null;
|
|
314
|
-
try {
|
|
315
|
-
return sdk.solana;
|
|
316
|
-
} catch {
|
|
317
|
-
return null;
|
|
318
|
-
}
|
|
319
|
-
}, [sdk, isConnected]);
|
|
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
|
-
);
|
|
352
|
-
const disconnect = useCallback4(async () => {
|
|
353
|
-
if (!solanaChain)
|
|
354
|
-
throw new Error("Solana chain not available. Ensure SDK is connected.");
|
|
355
|
-
return solanaChain.disconnect();
|
|
356
|
-
}, [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
|
-
);
|
|
365
|
-
const getPublicKey = useCallback4(async () => {
|
|
366
|
-
if (!solanaChain)
|
|
367
|
-
return null;
|
|
368
|
-
return solanaChain.getPublicKey();
|
|
369
|
-
}, [solanaChain]);
|
|
370
308
|
return {
|
|
371
|
-
// Chain instance for
|
|
372
|
-
solana:
|
|
373
|
-
// Convenient methods
|
|
374
|
-
signMessage,
|
|
375
|
-
signTransaction,
|
|
376
|
-
signAndSendTransaction,
|
|
377
|
-
connect,
|
|
378
|
-
disconnect,
|
|
379
|
-
switchNetwork,
|
|
380
|
-
getPublicKey,
|
|
309
|
+
// Chain instance with connection enforcement for signing methods
|
|
310
|
+
solana: sdk.solana,
|
|
381
311
|
// State
|
|
382
|
-
isAvailable: !!
|
|
383
|
-
isConnected: solanaChain?.isConnected() ?? false
|
|
312
|
+
isAvailable: !!isConnected
|
|
384
313
|
};
|
|
385
314
|
}
|
|
386
315
|
|
|
387
316
|
// src/hooks/useEthereum.ts
|
|
388
|
-
import { useCallback as useCallback5, useMemo as useMemo3 } from "react";
|
|
389
317
|
function useEthereum() {
|
|
390
318
|
const { sdk, isConnected } = usePhantom();
|
|
391
|
-
const ethereumChain = useMemo3(() => {
|
|
392
|
-
if (!sdk || !isConnected)
|
|
393
|
-
return null;
|
|
394
|
-
try {
|
|
395
|
-
return sdk.ethereum;
|
|
396
|
-
} catch {
|
|
397
|
-
return null;
|
|
398
|
-
}
|
|
399
|
-
}, [sdk, isConnected]);
|
|
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
|
-
);
|
|
433
|
-
const getChainId = useCallback5(async () => {
|
|
434
|
-
if (!ethereumChain)
|
|
435
|
-
throw new Error("Ethereum chain not available. Ensure SDK is connected.");
|
|
436
|
-
return ethereumChain.getChainId();
|
|
437
|
-
}, [ethereumChain]);
|
|
438
|
-
const getAccounts = useCallback5(async () => {
|
|
439
|
-
if (!ethereumChain)
|
|
440
|
-
throw new Error("Ethereum chain not available. Ensure SDK is connected.");
|
|
441
|
-
return ethereumChain.getAccounts();
|
|
442
|
-
}, [ethereumChain]);
|
|
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
|
-
);
|
|
462
319
|
return {
|
|
463
|
-
// Chain instance for
|
|
464
|
-
ethereum:
|
|
465
|
-
// Standard EIP-1193 interface
|
|
466
|
-
request,
|
|
467
|
-
// Convenient methods
|
|
468
|
-
signPersonalMessage,
|
|
469
|
-
signMessage,
|
|
470
|
-
signTypedData,
|
|
471
|
-
sendTransaction,
|
|
472
|
-
switchChain,
|
|
473
|
-
getChainId,
|
|
474
|
-
getAccounts,
|
|
320
|
+
// Chain instance with connection enforcement for signing methods
|
|
321
|
+
ethereum: sdk.ethereum,
|
|
475
322
|
// State
|
|
476
|
-
isAvailable: !!
|
|
477
|
-
isConnected: ethereumChain?.isConnected() ?? false
|
|
323
|
+
isAvailable: !!isConnected
|
|
478
324
|
};
|
|
479
325
|
}
|
|
480
326
|
|
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.3",
|
|
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.3",
|
|
30
|
+
"@phantom/chains": "^1.0.0-beta.3",
|
|
31
|
+
"@phantom/constants": "^1.0.0-beta.3"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@testing-library/dom": "^10.4.0",
|