@phantom/browser-sdk 0.0.10 → 0.2.0
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 +648 -100
- package/dist/index.d.ts +118 -3
- package/dist/index.js +769 -10
- package/dist/index.mjs +767 -8
- package/package.json +26 -29
- package/dist/auto-confirm/index.d.ts +0 -10
- package/dist/auto-confirm/index.js +0 -107
- package/dist/auto-confirm/index.mjs +0 -82
- package/dist/chunk-GV6AIHPN.mjs +0 -18
- package/dist/extension/index.d.ts +0 -10
- package/dist/extension/index.js +0 -50
- package/dist/extension/index.mjs +0 -25
- package/dist/index-52a9bded.d.ts +0 -182
- package/dist/solana/index.d.ts +0 -10
- package/dist/solana/index.js +0 -550
- package/dist/solana/index.mjs +0 -515
package/README.md
CHANGED
|
@@ -1,142 +1,304 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @phantom/browser-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Browser SDK for Phantom Wallet supporting both injected and embedded non-custodial wallets.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
You can install the SDK using npm or yarn:
|
|
8
|
-
|
|
9
|
-
**npm:**
|
|
5
|
+
## Quick Start
|
|
10
6
|
|
|
11
7
|
```bash
|
|
12
8
|
npm install @phantom/browser-sdk
|
|
13
9
|
```
|
|
14
10
|
|
|
15
|
-
|
|
11
|
+
### Injected Provider (Browser Extension)
|
|
16
12
|
|
|
17
|
-
```
|
|
18
|
-
|
|
13
|
+
```typescript
|
|
14
|
+
import { BrowserSDK, NetworkId } from "@phantom/browser-sdk";
|
|
15
|
+
|
|
16
|
+
// Connect to Phantom browser extension
|
|
17
|
+
const sdk = new BrowserSDK({
|
|
18
|
+
providerType: "injected",
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const { addresses } = await sdk.connect();
|
|
22
|
+
console.log("Connected addresses:", addresses);
|
|
23
|
+
|
|
24
|
+
// Sign and send transactions
|
|
25
|
+
const result = await sdk.signAndSendTransaction({
|
|
26
|
+
networkId: NetworkId.SOLANA_MAINNET,
|
|
27
|
+
transaction: mySolanaTransaction,
|
|
28
|
+
});
|
|
19
29
|
```
|
|
20
30
|
|
|
21
|
-
|
|
31
|
+
### Embedded Provider
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { BrowserSDK, AddressType, NetworkId } from "@phantom/browser-sdk";
|
|
35
|
+
|
|
36
|
+
// Create embedded non-custodial wallet
|
|
37
|
+
const sdk = new BrowserSDK({
|
|
38
|
+
providerType: "embedded",
|
|
39
|
+
addressTypes: [AddressType.solana, AddressType.ethereum],
|
|
40
|
+
apiBaseUrl: "https://api.phantom.com",
|
|
41
|
+
organizationId: "your-org-id",
|
|
42
|
+
});
|
|
22
43
|
|
|
23
|
-
|
|
44
|
+
const { walletId, addresses } = await sdk.connect();
|
|
45
|
+
console.log("Wallet ID:", walletId);
|
|
46
|
+
console.log("Addresses:", addresses);
|
|
47
|
+
|
|
48
|
+
const result = await sdk.signAndSendTransaction({
|
|
49
|
+
networkId: NetworkId.SOLANA_MAINNET,
|
|
50
|
+
transaction: mySolanaTransaction,
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Features
|
|
55
|
+
|
|
56
|
+
- **🔒 Non-Custodial**: Full user control of private keys for both injected and embedded wallets
|
|
57
|
+
- **🌐 Dual Provider Support**: Works with Phantom browser extension or creates embedded wallets
|
|
58
|
+
- **🛠️ Native Transactions**: Work with blockchain-native objects, not base64url strings
|
|
59
|
+
- **🔗 Multi-Chain**: Solana, Ethereum, Bitcoin, Sui support
|
|
60
|
+
- **⚡ TypeScript**: Full type safety for all transaction formats
|
|
61
|
+
- **🎯 Unified API**: Same interface for both injected and embedded providers
|
|
62
|
+
|
|
63
|
+
## Provider Types
|
|
64
|
+
|
|
65
|
+
### Injected Provider
|
|
66
|
+
|
|
67
|
+
Uses the Phantom browser extension installed by the user. No additional configuration needed.
|
|
24
68
|
|
|
25
69
|
```typescript
|
|
26
|
-
|
|
27
|
-
|
|
70
|
+
const sdk = new BrowserSDK({
|
|
71
|
+
providerType: "injected",
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Embedded Provider
|
|
28
76
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
77
|
+
Creates a non-custodial wallet embedded in your application. Requires API configuration.
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
const sdk = new BrowserSDK({
|
|
81
|
+
providerType: "embedded",
|
|
82
|
+
addressTypes: [AddressType.solana, AddressType.ethereum],
|
|
83
|
+
apiBaseUrl: "https://api.phantom.com",
|
|
84
|
+
organizationId: "your-org-id",
|
|
85
|
+
embeddedWalletType: "app-wallet", // or 'user-wallet'
|
|
32
86
|
});
|
|
87
|
+
```
|
|
33
88
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
89
|
+
### Embedded Wallet Types
|
|
90
|
+
|
|
91
|
+
#### App Wallet (`'app-wallet'`)
|
|
92
|
+
|
|
93
|
+
- **New wallets** created per application
|
|
94
|
+
- **Unfunded** by default - you need to fund them
|
|
95
|
+
- **Independent** from user's existing Phantom wallet
|
|
96
|
+
- **Perfect for**: Gaming, DeFi protocols, or apps that need fresh wallets
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
const sdk = new BrowserSDK({
|
|
100
|
+
providerType: "embedded",
|
|
101
|
+
embeddedWalletType: "app-wallet",
|
|
102
|
+
addressTypes: [AddressType.solana],
|
|
103
|
+
// ... other config
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### User Wallet (`'user-wallet'`)
|
|
108
|
+
|
|
109
|
+
- **Uses Phantom authentication** - user logs in with existing Phantom account
|
|
110
|
+
- **Potentially funded** - brings in user's existing wallet balance
|
|
111
|
+
- **Connected** to user's Phantom ecosystem
|
|
112
|
+
- **Perfect for**: Trading platforms, NFT marketplaces, or apps needing funded wallets
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
const sdk = new BrowserSDK({
|
|
116
|
+
providerType: "embedded",
|
|
117
|
+
embeddedWalletType: "user-wallet",
|
|
118
|
+
addressTypes: [AddressType.solana, AddressType.ethereum],
|
|
119
|
+
// ... other config
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Available AddressTypes (Embedded Only)
|
|
124
|
+
|
|
125
|
+
| AddressType | Networks Supported |
|
|
126
|
+
| --------------------------- | ------------------------------------------- |
|
|
127
|
+
| `AddressType.solana` | Solana Mainnet, Devnet, Testnet |
|
|
128
|
+
| `AddressType.ethereum` | Ethereum, Polygon, Arbitrum, Optimism, Base |
|
|
129
|
+
| `AddressType.bitcoinSegwit` | Bitcoin Mainnet, Testnet |
|
|
130
|
+
| `AddressType.sui` | Sui Mainnet, Testnet, Devnet |
|
|
131
|
+
|
|
132
|
+
### Solana Provider Configuration
|
|
133
|
+
|
|
134
|
+
When using `AddressType.solana`, you can choose between two Solana libraries:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
const sdk = new BrowserSDK({
|
|
138
|
+
providerType: "embedded",
|
|
139
|
+
addressTypes: [AddressType.solana],
|
|
140
|
+
solanaProvider: "web3js", // or 'kit'
|
|
141
|
+
// ... other config
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**Provider Options:**
|
|
146
|
+
|
|
147
|
+
- `'web3js'` (default) - Uses `@solana/web3.js` library
|
|
148
|
+
- `'kit'` - Uses `@solana/kit` library (modern, TypeScript-first)
|
|
149
|
+
|
|
150
|
+
**When to use each:**
|
|
151
|
+
|
|
152
|
+
- **@solana/web3.js**: Better ecosystem compatibility, wider community support
|
|
153
|
+
- **@solana/kit**: Better TypeScript support, modern architecture, smaller bundle size
|
|
154
|
+
|
|
155
|
+
## API Reference
|
|
156
|
+
|
|
157
|
+
### Constructor
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
new BrowserSDK(config: BrowserSDKConfig)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
#### BrowserSDKConfig
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
interface BrowserSDKConfig {
|
|
167
|
+
providerType: "injected" | "embedded";
|
|
168
|
+
|
|
169
|
+
// Required for embedded provider only
|
|
170
|
+
addressTypes?: AddressType[]; // Networks to enable
|
|
171
|
+
apiBaseUrl?: string; // Phantom API base URL
|
|
172
|
+
organizationId?: string; // Your organization ID
|
|
173
|
+
authUrl?: string; // Custom auth URL (optional)
|
|
174
|
+
embeddedWalletType?: "app-wallet" | "user-wallet"; // Wallet type
|
|
175
|
+
solanaProvider?: "web3js" | "kit"; // Solana library choice (default: 'web3js')
|
|
54
176
|
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Methods
|
|
180
|
+
|
|
181
|
+
#### connect()
|
|
182
|
+
|
|
183
|
+
Connect to wallet and get addresses for configured AddressTypes.
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
const result = await sdk.connect();
|
|
187
|
+
// Returns: { walletId: string, addresses: WalletAddress[] }
|
|
188
|
+
// addresses only includes types from addressTypes config
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
#### signAndSendTransaction(transaction)
|
|
192
|
+
|
|
193
|
+
Sign and send a native transaction object.
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
// Solana transaction
|
|
197
|
+
const result = await sdk.signAndSendTransaction({
|
|
198
|
+
networkId: NetworkId.SOLANA_MAINNET,
|
|
199
|
+
transaction: solanaTransaction, // Native Transaction or VersionedTransaction
|
|
200
|
+
});
|
|
55
201
|
|
|
56
|
-
|
|
202
|
+
// Ethereum transaction
|
|
203
|
+
const result = await sdk.signAndSendTransaction({
|
|
204
|
+
networkId: NetworkId.ETHEREUM_MAINNET,
|
|
205
|
+
transaction: {
|
|
206
|
+
to: "0x...",
|
|
207
|
+
value: parseEther("1"), // 1 ETH
|
|
208
|
+
gas: 21000n,
|
|
209
|
+
},
|
|
210
|
+
});
|
|
57
211
|
```
|
|
58
212
|
|
|
59
|
-
|
|
213
|
+
#### signMessage(params)
|
|
214
|
+
|
|
215
|
+
Sign a message string.
|
|
60
216
|
|
|
61
|
-
|
|
217
|
+
```typescript
|
|
218
|
+
const signature = await sdk.signMessage({
|
|
219
|
+
message: "Hello from Phantom!",
|
|
220
|
+
networkId: NetworkId.SOLANA_MAINNET,
|
|
221
|
+
});
|
|
222
|
+
```
|
|
62
223
|
|
|
63
|
-
|
|
64
|
-
- Connects to the Phantom wallet. Optionally, `onlyIfTrusted` can be set to true to only connect if the dApp is already trusted.
|
|
65
|
-
- `disconnect(): Promise<void>`
|
|
66
|
-
- Disconnects from the Phantom wallet.
|
|
67
|
-
- `getAccount(): Promise<string | undefined>`
|
|
68
|
-
- Gets the current connected address
|
|
69
|
-
- `signIn(): Promise<SignInResult>`
|
|
70
|
-
- Initiates a sign-in request to the wallet.
|
|
71
|
-
- `signMessage(message: Uint8Array | string, display?: 'utf8' | 'hex'): Promise<SignedMessage>`
|
|
72
|
-
- Prompts the user to sign a given message.
|
|
73
|
-
- `signAndSendTransaction(transaction: Transaction): Promise<{ signature: string; address?: string }>`
|
|
74
|
-
- Prompts the user to sign **and send** a Kit `Transaction` and returns the confirmed signature.
|
|
224
|
+
**Parameters:**
|
|
75
225
|
|
|
76
|
-
|
|
226
|
+
- `params.message` (string) - Message to sign
|
|
227
|
+
- `params.networkId` (NetworkId) - Network identifier
|
|
77
228
|
|
|
78
|
-
|
|
229
|
+
#### getAddresses()
|
|
79
230
|
|
|
80
|
-
|
|
81
|
-
- Displays `true` if the phantom extension is installed, `false` if not
|
|
231
|
+
Get connected wallet addresses.
|
|
82
232
|
|
|
83
|
-
|
|
233
|
+
```typescript
|
|
234
|
+
const addresses = await sdk.getAddresses();
|
|
235
|
+
// Returns addresses matching configured AddressTypes
|
|
236
|
+
```
|
|
84
237
|
|
|
85
|
-
|
|
238
|
+
#### disconnect()
|
|
86
239
|
|
|
87
|
-
|
|
240
|
+
Disconnect from wallet and clear session.
|
|
88
241
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
- For the `accountChanged` event, the callback receives the new public key (as a string).
|
|
93
|
-
- Returns a function that, when called, will unregister the callback.
|
|
94
|
-
- Multiple callbacks can be registered for the same event.
|
|
242
|
+
```typescript
|
|
243
|
+
await sdk.disconnect();
|
|
244
|
+
```
|
|
95
245
|
|
|
96
|
-
|
|
246
|
+
## Transaction Examples
|
|
97
247
|
|
|
98
|
-
|
|
99
|
-
const phantom = createPhantom({ plugins: [createSolanaPlugin()] });
|
|
248
|
+
### Solana Transactions
|
|
100
249
|
|
|
101
|
-
|
|
102
|
-
console.log(`Wallet connected with public key: ${address}`);
|
|
103
|
-
};
|
|
250
|
+
The SDK supports two different Solana transaction libraries. Choose based on your needs:
|
|
104
251
|
|
|
105
|
-
|
|
252
|
+
#### Option 1: @solana/web3.js (Legacy Library)
|
|
106
253
|
|
|
107
|
-
|
|
108
|
-
console.log(`Account changed to: ${newAddress}`);
|
|
109
|
-
};
|
|
254
|
+
Traditional Solana library with broader ecosystem support.
|
|
110
255
|
|
|
111
|
-
|
|
256
|
+
```bash
|
|
257
|
+
npm install @solana/web3.js
|
|
258
|
+
```
|
|
112
259
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
260
|
+
```typescript
|
|
261
|
+
import { Transaction, SystemProgram, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js";
|
|
262
|
+
import { BrowserSDK, NetworkId } from "@phantom/browser-sdk";
|
|
263
|
+
|
|
264
|
+
// Create native Solana transaction
|
|
265
|
+
const transaction = new Transaction().add(
|
|
266
|
+
SystemProgram.transfer({
|
|
267
|
+
fromPubkey: new PublicKey(fromAddress),
|
|
268
|
+
toPubkey: new PublicKey(toAddress),
|
|
269
|
+
lamports: 0.001 * LAMPORTS_PER_SOL,
|
|
270
|
+
}),
|
|
271
|
+
);
|
|
117
272
|
|
|
118
|
-
|
|
273
|
+
// Send native transaction object - no encoding needed!
|
|
274
|
+
const result = await sdk.signAndSendTransaction({
|
|
275
|
+
networkId: NetworkId.SOLANA_MAINNET,
|
|
276
|
+
transaction: transaction,
|
|
277
|
+
});
|
|
119
278
|
|
|
120
|
-
|
|
279
|
+
console.log("Transaction signature:", result.rawTransaction);
|
|
280
|
+
```
|
|
121
281
|
|
|
122
|
-
|
|
282
|
+
**VersionedTransaction with @solana/web3.js:**
|
|
123
283
|
|
|
124
|
-
|
|
125
|
-
|
|
284
|
+
```typescript
|
|
285
|
+
import { VersionedTransaction } from "@solana/web3.js";
|
|
126
286
|
|
|
127
|
-
|
|
128
|
-
console.log("Wallet disconnected");
|
|
129
|
-
};
|
|
287
|
+
const versionedTx = new VersionedTransaction(message);
|
|
130
288
|
|
|
131
|
-
|
|
289
|
+
const result = await sdk.signAndSendTransaction({
|
|
290
|
+
networkId: NetworkId.SOLANA_DEVNET,
|
|
291
|
+
transaction: versionedTx,
|
|
292
|
+
});
|
|
293
|
+
```
|
|
132
294
|
|
|
133
|
-
|
|
134
|
-
// phantom.solana.removeEventListener("disconnect", handleDisconnect);
|
|
135
|
-
```
|
|
295
|
+
#### Option 2: @solana/kit (Modern Library)
|
|
136
296
|
|
|
137
|
-
|
|
297
|
+
New high-performance Solana library with better TypeScript support.
|
|
138
298
|
|
|
139
|
-
|
|
299
|
+
```bash
|
|
300
|
+
npm install @solana/kit
|
|
301
|
+
```
|
|
140
302
|
|
|
141
303
|
```typescript
|
|
142
304
|
import {
|
|
@@ -148,20 +310,406 @@ import {
|
|
|
148
310
|
address,
|
|
149
311
|
compileTransaction,
|
|
150
312
|
} from "@solana/kit";
|
|
313
|
+
import { BrowserSDK, NetworkId } from "@phantom/browser-sdk";
|
|
151
314
|
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
const rpc = createSolanaRpc("https://my-rpc-url.com"); // Replace with your own RPC URL
|
|
155
|
-
|
|
315
|
+
// Create transaction with @solana/kit
|
|
316
|
+
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
|
|
156
317
|
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
|
|
157
318
|
|
|
158
319
|
const transactionMessage = pipe(
|
|
159
320
|
createTransactionMessage({ version: 0 }),
|
|
160
|
-
tx => setTransactionMessageFeePayer(address(userPublicKey
|
|
321
|
+
tx => setTransactionMessageFeePayer(address(userPublicKey), tx),
|
|
161
322
|
tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
|
|
162
323
|
);
|
|
163
324
|
|
|
164
325
|
const transaction = compileTransaction(transactionMessage);
|
|
165
326
|
|
|
166
|
-
const
|
|
327
|
+
const result = await sdk.signAndSendTransaction({
|
|
328
|
+
networkId: NetworkId.SOLANA_MAINNET,
|
|
329
|
+
transaction: transaction,
|
|
330
|
+
});
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Ethereum Transactions (with Viem)
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
import { parseEther, parseGwei, encodeFunctionData } from "viem";
|
|
337
|
+
import { BrowserSDK, NetworkId } from "@phantom/browser-sdk";
|
|
338
|
+
|
|
339
|
+
// Simple ETH transfer
|
|
340
|
+
const result = await sdk.signAndSendTransaction({
|
|
341
|
+
networkId: NetworkId.ETHEREUM_MAINNET,
|
|
342
|
+
transaction: {
|
|
343
|
+
to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
344
|
+
value: parseEther("1"), // 1 ETH
|
|
345
|
+
gas: 21000n,
|
|
346
|
+
gasPrice: parseGwei("20"), // 20 gwei
|
|
347
|
+
},
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
// EIP-1559 transaction with maxFeePerGas
|
|
351
|
+
const result = await sdk.signAndSendTransaction({
|
|
352
|
+
networkId: NetworkId.ETHEREUM_MAINNET,
|
|
353
|
+
transaction: {
|
|
354
|
+
to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
355
|
+
value: parseEther("1"),
|
|
356
|
+
data: encodeFunctionData({
|
|
357
|
+
abi: tokenAbi,
|
|
358
|
+
functionName: "transfer",
|
|
359
|
+
args: ["0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E", parseEther("1")],
|
|
360
|
+
}),
|
|
361
|
+
gas: 50000n,
|
|
362
|
+
maxFeePerGas: parseGwei("30"), // 30 gwei
|
|
363
|
+
maxPriorityFeePerGas: parseGwei("2"), // 2 gwei
|
|
364
|
+
type: "eip1559",
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
#### Other EVM Networks
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
// Polygon transaction
|
|
373
|
+
const result = await sdk.signAndSendTransaction({
|
|
374
|
+
networkId: NetworkId.POLYGON_MAINNET,
|
|
375
|
+
transaction: {
|
|
376
|
+
to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
377
|
+
value: parseEther("1"), // 1 MATIC
|
|
378
|
+
gas: 21000n,
|
|
379
|
+
},
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
// Arbitrum transaction
|
|
383
|
+
const result = await sdk.signAndSendTransaction({
|
|
384
|
+
networkId: NetworkId.ARBITRUM_ONE,
|
|
385
|
+
transaction: {
|
|
386
|
+
to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
387
|
+
value: parseEther("0.1"), // 0.1 ETH
|
|
388
|
+
gas: 21000n,
|
|
389
|
+
},
|
|
390
|
+
});
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Bitcoin Transactions
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
// Bitcoin transaction
|
|
397
|
+
const result = await sdk.signAndSendTransaction({
|
|
398
|
+
networkId: NetworkId.BITCOIN_MAINNET,
|
|
399
|
+
transaction: {
|
|
400
|
+
inputs: [
|
|
401
|
+
{
|
|
402
|
+
txid: "previous-transaction-id",
|
|
403
|
+
vout: 0,
|
|
404
|
+
scriptSig: "...",
|
|
405
|
+
},
|
|
406
|
+
],
|
|
407
|
+
outputs: [
|
|
408
|
+
{
|
|
409
|
+
value: 50000, // satoshis
|
|
410
|
+
scriptPubKey: "76a914...88ac", // P2PKH script
|
|
411
|
+
},
|
|
412
|
+
],
|
|
413
|
+
version: 2,
|
|
414
|
+
locktime: 0,
|
|
415
|
+
},
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
// Bitcoin testnet
|
|
419
|
+
const result = await sdk.signAndSendTransaction({
|
|
420
|
+
networkId: NetworkId.BITCOIN_TESTNET,
|
|
421
|
+
transaction: {
|
|
422
|
+
// ... transaction details
|
|
423
|
+
},
|
|
424
|
+
});
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### Sui Transactions
|
|
428
|
+
|
|
429
|
+
```typescript
|
|
430
|
+
import { TransactionBlock } from "@mysten/sui.js/transactions";
|
|
431
|
+
|
|
432
|
+
// Create Sui transaction block
|
|
433
|
+
const txb = new TransactionBlock();
|
|
434
|
+
txb.transferObjects([coin], recipientAddress);
|
|
435
|
+
|
|
436
|
+
const result = await sdk.signAndSendTransaction({
|
|
437
|
+
networkId: NetworkId.SUI_MAINNET,
|
|
438
|
+
transaction: {
|
|
439
|
+
kind: "moveCall", // or 'transferObject', 'transferSui', 'pay'
|
|
440
|
+
data: txb, // TransactionBlock from @mysten/sui.js
|
|
441
|
+
},
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
// Sui testnet
|
|
445
|
+
const result = await sdk.signAndSendTransaction({
|
|
446
|
+
networkId: NetworkId.SUI_TESTNET,
|
|
447
|
+
transaction: {
|
|
448
|
+
kind: "transferSui",
|
|
449
|
+
data: suiTransactionData,
|
|
450
|
+
},
|
|
451
|
+
});
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
## Network IDs Reference
|
|
455
|
+
|
|
456
|
+
Use the exported `NetworkId` enum for type safety:
|
|
457
|
+
|
|
458
|
+
```typescript
|
|
459
|
+
import { NetworkId } from "@phantom/browser-sdk";
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### Solana
|
|
463
|
+
|
|
464
|
+
- `NetworkId.SOLANA_MAINNET` - Solana Mainnet Beta
|
|
465
|
+
- `NetworkId.SOLANA_DEVNET` - Solana Devnet
|
|
466
|
+
- `NetworkId.SOLANA_TESTNET` - Solana Testnet
|
|
467
|
+
|
|
468
|
+
### Ethereum/EVM
|
|
469
|
+
|
|
470
|
+
- `NetworkId.ETHEREUM_MAINNET` - Ethereum Mainnet
|
|
471
|
+
- `NetworkId.ETHEREUM_SEPOLIA` - Ethereum Sepolia Testnet
|
|
472
|
+
- `NetworkId.POLYGON_MAINNET` - Polygon Mainnet
|
|
473
|
+
- `NetworkId.ARBITRUM_ONE` - Arbitrum One
|
|
474
|
+
- `NetworkId.OPTIMISM_MAINNET` - Optimism Mainnet
|
|
475
|
+
- `NetworkId.BASE_MAINNET` - Base Mainnet
|
|
476
|
+
|
|
477
|
+
### Bitcoin
|
|
478
|
+
|
|
479
|
+
- `NetworkId.BITCOIN_MAINNET` - Bitcoin Mainnet
|
|
480
|
+
- `NetworkId.BITCOIN_TESTNET` - Bitcoin Testnet
|
|
481
|
+
|
|
482
|
+
### Sui
|
|
483
|
+
|
|
484
|
+
- `NetworkId.SUI_MAINNET` - Sui Mainnet
|
|
485
|
+
- `NetworkId.SUI_TESTNET` - Sui Testnet
|
|
486
|
+
- `NetworkId.SUI_DEVNET` - Sui Devnet
|
|
487
|
+
|
|
488
|
+
## Advanced Usage
|
|
489
|
+
|
|
490
|
+
### Multi-Chain Application
|
|
491
|
+
|
|
492
|
+
```typescript
|
|
493
|
+
import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
|
|
494
|
+
|
|
495
|
+
const sdk = new BrowserSDK({
|
|
496
|
+
addressTypes: [AddressType.solana, AddressType.ethereum, AddressType.sui],
|
|
497
|
+
apiBaseUrl: "https://api.phantom.com",
|
|
498
|
+
organizationId: "your-org-id",
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
class MultiChainWallet {
|
|
502
|
+
async sendSolana(amount: number, recipient: string) {
|
|
503
|
+
const transaction = new Transaction().add(
|
|
504
|
+
SystemProgram.transfer({
|
|
505
|
+
fromPubkey: new PublicKey(this.solanaAddress),
|
|
506
|
+
toPubkey: new PublicKey(recipient),
|
|
507
|
+
lamports: amount * LAMPORTS_PER_SOL,
|
|
508
|
+
}),
|
|
509
|
+
);
|
|
510
|
+
|
|
511
|
+
return await sdk.signAndSendTransaction({
|
|
512
|
+
networkId: NetworkId.SOLANA_MAINNET,
|
|
513
|
+
transaction,
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
async sendEthereum(amount: string, recipient: string) {
|
|
518
|
+
return await sdk.signAndSendTransaction({
|
|
519
|
+
networkId: NetworkId.ETHEREUM_MAINNET,
|
|
520
|
+
transaction: {
|
|
521
|
+
to: recipient,
|
|
522
|
+
value: parseEther(amount),
|
|
523
|
+
gas: 21000n,
|
|
524
|
+
},
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
async sendSui(coinId: string, recipient: string) {
|
|
529
|
+
const txb = new TransactionBlock();
|
|
530
|
+
txb.transferObjects([coinId], recipient);
|
|
531
|
+
|
|
532
|
+
return await sdk.signAndSendTransaction({
|
|
533
|
+
networkId: NetworkId.SUI_MAINNET,
|
|
534
|
+
transaction: {
|
|
535
|
+
kind: "transferObject",
|
|
536
|
+
data: txb,
|
|
537
|
+
},
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
### Error Handling
|
|
544
|
+
|
|
545
|
+
```typescript
|
|
546
|
+
try {
|
|
547
|
+
const result = await sdk.signAndSendTransaction({
|
|
548
|
+
networkId: NetworkId.SOLANA_MAINNET,
|
|
549
|
+
transaction: myTransaction,
|
|
550
|
+
});
|
|
551
|
+
console.log("Success:", result);
|
|
552
|
+
} catch (error) {
|
|
553
|
+
if (error.message.includes("User rejected")) {
|
|
554
|
+
console.log("User cancelled the transaction");
|
|
555
|
+
} else if (error.message.includes("insufficient funds")) {
|
|
556
|
+
console.log("Not enough balance");
|
|
557
|
+
} else {
|
|
558
|
+
console.error("Transaction failed:", error);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
### Bundle Optimization Tips
|
|
564
|
+
|
|
565
|
+
1. **Only include networks you need**:
|
|
566
|
+
|
|
567
|
+
```typescript
|
|
568
|
+
// Good: Only Solana (~250KB)
|
|
569
|
+
addressTypes: [AddressType.solana];
|
|
570
|
+
|
|
571
|
+
// Avoid: All networks if not needed (~800KB+)
|
|
572
|
+
addressTypes: [AddressType.solana, AddressType.ethereum, AddressType.sui, AddressType.bitcoinSegwit];
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
2. **Install dependencies based on enabled networks**:
|
|
576
|
+
|
|
577
|
+
| AddressType | Required Dependencies | Bundle Size |
|
|
578
|
+
| --------------------------- | ---------------------------------- | ----------- |
|
|
579
|
+
| `AddressType.solana` | `@solana/web3.js` OR `@solana/kit` | ~250KB |
|
|
580
|
+
| `AddressType.ethereum` | `viem` | ~300KB |
|
|
581
|
+
| `AddressType.bitcoinSegwit` | `bitcoinjs-lib` | ~200KB |
|
|
582
|
+
| `AddressType.sui` | `@mysten/sui.js` | ~250KB |
|
|
583
|
+
|
|
584
|
+
**Example package.json for Solana + Ethereum (using @solana/web3.js)**:
|
|
585
|
+
|
|
586
|
+
```json
|
|
587
|
+
{
|
|
588
|
+
"dependencies": {
|
|
589
|
+
"@phantom/browser-sdk": "^1.0.0",
|
|
590
|
+
"@solana/web3.js": "^1.87.0",
|
|
591
|
+
"viem": "^2.0.0"
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
**Example package.json for Solana + Ethereum (using @solana/kit)**:
|
|
597
|
+
|
|
598
|
+
```json
|
|
599
|
+
{
|
|
600
|
+
"dependencies": {
|
|
601
|
+
"@phantom/browser-sdk": "^1.0.0",
|
|
602
|
+
"@solana/kit": "^2.0.0",
|
|
603
|
+
"viem": "^2.0.0"
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
**Example package.json for Solana only (using @solana/web3.js)**:
|
|
609
|
+
|
|
610
|
+
```json
|
|
611
|
+
{
|
|
612
|
+
"dependencies": {
|
|
613
|
+
"@phantom/browser-sdk": "^1.0.0",
|
|
614
|
+
"@solana/web3.js": "^1.87.0"
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
**Example package.json for Solana only (using @solana/kit)**:
|
|
620
|
+
|
|
621
|
+
```json
|
|
622
|
+
{
|
|
623
|
+
"dependencies": {
|
|
624
|
+
"@phantom/browser-sdk": "^1.0.0",
|
|
625
|
+
"@solana/kit": "^2.0.0"
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
**Example package.json for all networks (using @solana/web3.js)**:
|
|
631
|
+
|
|
632
|
+
```json
|
|
633
|
+
{
|
|
634
|
+
"dependencies": {
|
|
635
|
+
"@phantom/browser-sdk": "^1.0.0",
|
|
636
|
+
"@solana/web3.js": "^1.87.0",
|
|
637
|
+
"viem": "^2.0.0",
|
|
638
|
+
"bitcoinjs-lib": "^6.1.0",
|
|
639
|
+
"@mysten/sui.js": "^0.50.0"
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
**Example package.json for all networks (using @solana/kit)**:
|
|
645
|
+
|
|
646
|
+
```json
|
|
647
|
+
{
|
|
648
|
+
"dependencies": {
|
|
649
|
+
"@phantom/browser-sdk": "^1.0.0",
|
|
650
|
+
"@solana/kit": "^2.0.0",
|
|
651
|
+
"viem": "^2.0.0",
|
|
652
|
+
"bitcoinjs-lib": "^6.1.0",
|
|
653
|
+
"@mysten/sui.js": "^0.50.0"
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
3. **Monitor bundle size**:
|
|
659
|
+
```bash
|
|
660
|
+
# Analyze your bundle
|
|
661
|
+
npx webpack-bundle-analyzer dist/main.js
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
## Server Setup for Embedded Wallets
|
|
665
|
+
|
|
666
|
+
For embedded wallets, you need to set up a backend endpoint. Add the `serverUrl` parameter to your SDK configuration:
|
|
667
|
+
|
|
668
|
+
```typescript
|
|
669
|
+
const sdk = new BrowserSDK({
|
|
670
|
+
providerType: "embedded",
|
|
671
|
+
addressTypes: [AddressType.solana],
|
|
672
|
+
apiBaseUrl: "https://api.phantom.com",
|
|
673
|
+
organizationId: "your-org-id",
|
|
674
|
+
serverUrl: "http://localhost:3000/api",
|
|
675
|
+
});
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
### Required Backend Endpoint
|
|
679
|
+
|
|
680
|
+
Your backend needs an endpoint that uses the server-sdk:
|
|
681
|
+
|
|
682
|
+
```javascript
|
|
683
|
+
// server.js
|
|
684
|
+
const express = require("express");
|
|
685
|
+
const { ServerSDK } = require("@phantom/server-sdk");
|
|
686
|
+
|
|
687
|
+
const app = express();
|
|
688
|
+
app.use(express.json());
|
|
689
|
+
|
|
690
|
+
const serverSDK = new ServerSDK({
|
|
691
|
+
organizationId: process.env.ORGANIZATION_ID,
|
|
692
|
+
apiPrivateKey: process.env.PRIVATE_KEY,
|
|
693
|
+
apiBaseUrl: process.env.API_URL,
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
app.post("/api/organizations", async (req, res) => {
|
|
697
|
+
try {
|
|
698
|
+
const { userId } = req.body;
|
|
699
|
+
|
|
700
|
+
if (!userId) {
|
|
701
|
+
return res.status(400).json({ error: "userId is required" });
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
const organization = await serverSDK.getOrCreateChildOrganizationByTag({
|
|
705
|
+
tag: userId,
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
res.json({ organizationId: organization.id });
|
|
709
|
+
} catch (error) {
|
|
710
|
+
res.status(500).json({ error: "Failed to process request" });
|
|
711
|
+
}
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
app.listen(3000);
|
|
167
715
|
```
|