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