@phantom/browser-sdk 0.0.9 → 0.1.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 +643 -96
- package/dist/index.d.ts +117 -15
- package/dist/index.js +772 -10
- package/dist/index.mjs +770 -8
- package/package.json +27 -30
- package/dist/auto-confirm/index.d.ts +0 -37
- 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/solana/index.d.ts +0 -139
- package/dist/solana/index.js +0 -550
- package/dist/solana/index.mjs +0 -515
package/README.md
CHANGED
|
@@ -1,135 +1,296 @@
|
|
|
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(message, networkId)
|
|
214
|
+
|
|
215
|
+
Sign a message string.
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
const signature = await sdk.signMessage("Hello from Phantom!", NetworkId.SOLANA_MAINNET);
|
|
219
|
+
```
|
|
60
220
|
|
|
61
|
-
|
|
221
|
+
#### getAddresses()
|
|
62
222
|
|
|
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.
|
|
223
|
+
Get connected wallet addresses.
|
|
75
224
|
|
|
76
|
-
|
|
225
|
+
```typescript
|
|
226
|
+
const addresses = await sdk.getAddresses();
|
|
227
|
+
// Returns addresses matching configured AddressTypes
|
|
228
|
+
```
|
|
77
229
|
|
|
78
|
-
|
|
230
|
+
#### disconnect()
|
|
79
231
|
|
|
80
|
-
|
|
232
|
+
Disconnect from wallet and clear session.
|
|
81
233
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
- For the `accountChanged` event, the callback receives the new public key (as a string).
|
|
86
|
-
- Returns a function that, when called, will unregister the callback.
|
|
87
|
-
- Multiple callbacks can be registered for the same event.
|
|
234
|
+
```typescript
|
|
235
|
+
await sdk.disconnect();
|
|
236
|
+
```
|
|
88
237
|
|
|
89
|
-
|
|
238
|
+
## Transaction Examples
|
|
90
239
|
|
|
91
|
-
|
|
92
|
-
const phantom = createPhantom({ plugins: [createSolanaPlugin()] });
|
|
240
|
+
### Solana Transactions
|
|
93
241
|
|
|
94
|
-
|
|
95
|
-
console.log(`Wallet connected with public key: ${address}`);
|
|
96
|
-
};
|
|
242
|
+
The SDK supports two different Solana transaction libraries. Choose based on your needs:
|
|
97
243
|
|
|
98
|
-
|
|
244
|
+
#### Option 1: @solana/web3.js (Legacy Library)
|
|
99
245
|
|
|
100
|
-
|
|
101
|
-
console.log(`Account changed to: ${newAddress}`);
|
|
102
|
-
};
|
|
246
|
+
Traditional Solana library with broader ecosystem support.
|
|
103
247
|
|
|
104
|
-
|
|
248
|
+
```bash
|
|
249
|
+
npm install @solana/web3.js
|
|
250
|
+
```
|
|
105
251
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
252
|
+
```typescript
|
|
253
|
+
import { Transaction, SystemProgram, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js";
|
|
254
|
+
import { BrowserSDK, NetworkId } from "@phantom/browser-sdk";
|
|
255
|
+
|
|
256
|
+
// Create native Solana transaction
|
|
257
|
+
const transaction = new Transaction().add(
|
|
258
|
+
SystemProgram.transfer({
|
|
259
|
+
fromPubkey: new PublicKey(fromAddress),
|
|
260
|
+
toPubkey: new PublicKey(toAddress),
|
|
261
|
+
lamports: 0.001 * LAMPORTS_PER_SOL,
|
|
262
|
+
}),
|
|
263
|
+
);
|
|
110
264
|
|
|
111
|
-
|
|
265
|
+
// Send native transaction object - no encoding needed!
|
|
266
|
+
const result = await sdk.signAndSendTransaction({
|
|
267
|
+
networkId: NetworkId.SOLANA_MAINNET,
|
|
268
|
+
transaction: transaction,
|
|
269
|
+
});
|
|
112
270
|
|
|
113
|
-
|
|
271
|
+
console.log("Transaction signature:", result.rawTransaction);
|
|
272
|
+
```
|
|
114
273
|
|
|
115
|
-
|
|
274
|
+
**VersionedTransaction with @solana/web3.js:**
|
|
116
275
|
|
|
117
|
-
|
|
118
|
-
|
|
276
|
+
```typescript
|
|
277
|
+
import { VersionedTransaction } from "@solana/web3.js";
|
|
119
278
|
|
|
120
|
-
|
|
121
|
-
console.log("Wallet disconnected");
|
|
122
|
-
};
|
|
279
|
+
const versionedTx = new VersionedTransaction(message);
|
|
123
280
|
|
|
124
|
-
|
|
281
|
+
const result = await sdk.signAndSendTransaction({
|
|
282
|
+
networkId: NetworkId.SOLANA_DEVNET,
|
|
283
|
+
transaction: versionedTx,
|
|
284
|
+
});
|
|
285
|
+
```
|
|
125
286
|
|
|
126
|
-
|
|
127
|
-
// phantom.solana.removeEventListener("disconnect", handleDisconnect);
|
|
128
|
-
```
|
|
287
|
+
#### Option 2: @solana/kit (Modern Library)
|
|
129
288
|
|
|
130
|
-
|
|
289
|
+
New high-performance Solana library with better TypeScript support.
|
|
131
290
|
|
|
132
|
-
|
|
291
|
+
```bash
|
|
292
|
+
npm install @solana/kit
|
|
293
|
+
```
|
|
133
294
|
|
|
134
295
|
```typescript
|
|
135
296
|
import {
|
|
@@ -141,20 +302,406 @@ import {
|
|
|
141
302
|
address,
|
|
142
303
|
compileTransaction,
|
|
143
304
|
} from "@solana/kit";
|
|
305
|
+
import { BrowserSDK, NetworkId } from "@phantom/browser-sdk";
|
|
144
306
|
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
const rpc = createSolanaRpc("https://my-rpc-url.com"); // Replace with your own RPC URL
|
|
148
|
-
|
|
307
|
+
// Create transaction with @solana/kit
|
|
308
|
+
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
|
|
149
309
|
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
|
|
150
310
|
|
|
151
311
|
const transactionMessage = pipe(
|
|
152
312
|
createTransactionMessage({ version: 0 }),
|
|
153
|
-
tx => setTransactionMessageFeePayer(address(userPublicKey
|
|
313
|
+
tx => setTransactionMessageFeePayer(address(userPublicKey), tx),
|
|
154
314
|
tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
|
|
155
315
|
);
|
|
156
316
|
|
|
157
317
|
const transaction = compileTransaction(transactionMessage);
|
|
158
318
|
|
|
159
|
-
const
|
|
319
|
+
const result = await sdk.signAndSendTransaction({
|
|
320
|
+
networkId: NetworkId.SOLANA_MAINNET,
|
|
321
|
+
transaction: transaction,
|
|
322
|
+
});
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Ethereum Transactions (with Viem)
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
import { parseEther, parseGwei, encodeFunctionData } from "viem";
|
|
329
|
+
import { BrowserSDK, NetworkId } from "@phantom/browser-sdk";
|
|
330
|
+
|
|
331
|
+
// Simple ETH transfer
|
|
332
|
+
const result = await sdk.signAndSendTransaction({
|
|
333
|
+
networkId: NetworkId.ETHEREUM_MAINNET,
|
|
334
|
+
transaction: {
|
|
335
|
+
to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
336
|
+
value: parseEther("1"), // 1 ETH
|
|
337
|
+
gas: 21000n,
|
|
338
|
+
gasPrice: parseGwei("20"), // 20 gwei
|
|
339
|
+
},
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// EIP-1559 transaction with maxFeePerGas
|
|
343
|
+
const result = await sdk.signAndSendTransaction({
|
|
344
|
+
networkId: NetworkId.ETHEREUM_MAINNET,
|
|
345
|
+
transaction: {
|
|
346
|
+
to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
347
|
+
value: parseEther("1"),
|
|
348
|
+
data: encodeFunctionData({
|
|
349
|
+
abi: tokenAbi,
|
|
350
|
+
functionName: "transfer",
|
|
351
|
+
args: ["0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E", parseEther("1")],
|
|
352
|
+
}),
|
|
353
|
+
gas: 50000n,
|
|
354
|
+
maxFeePerGas: parseGwei("30"), // 30 gwei
|
|
355
|
+
maxPriorityFeePerGas: parseGwei("2"), // 2 gwei
|
|
356
|
+
type: "eip1559",
|
|
357
|
+
},
|
|
358
|
+
});
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
#### Other EVM Networks
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
// Polygon transaction
|
|
365
|
+
const result = await sdk.signAndSendTransaction({
|
|
366
|
+
networkId: NetworkId.POLYGON_MAINNET,
|
|
367
|
+
transaction: {
|
|
368
|
+
to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
369
|
+
value: parseEther("1"), // 1 MATIC
|
|
370
|
+
gas: 21000n,
|
|
371
|
+
},
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
// Arbitrum transaction
|
|
375
|
+
const result = await sdk.signAndSendTransaction({
|
|
376
|
+
networkId: NetworkId.ARBITRUM_ONE,
|
|
377
|
+
transaction: {
|
|
378
|
+
to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
379
|
+
value: parseEther("0.1"), // 0.1 ETH
|
|
380
|
+
gas: 21000n,
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Bitcoin Transactions
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
// Bitcoin transaction
|
|
389
|
+
const result = await sdk.signAndSendTransaction({
|
|
390
|
+
networkId: NetworkId.BITCOIN_MAINNET,
|
|
391
|
+
transaction: {
|
|
392
|
+
inputs: [
|
|
393
|
+
{
|
|
394
|
+
txid: "previous-transaction-id",
|
|
395
|
+
vout: 0,
|
|
396
|
+
scriptSig: "...",
|
|
397
|
+
},
|
|
398
|
+
],
|
|
399
|
+
outputs: [
|
|
400
|
+
{
|
|
401
|
+
value: 50000, // satoshis
|
|
402
|
+
scriptPubKey: "76a914...88ac", // P2PKH script
|
|
403
|
+
},
|
|
404
|
+
],
|
|
405
|
+
version: 2,
|
|
406
|
+
locktime: 0,
|
|
407
|
+
},
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
// Bitcoin testnet
|
|
411
|
+
const result = await sdk.signAndSendTransaction({
|
|
412
|
+
networkId: NetworkId.BITCOIN_TESTNET,
|
|
413
|
+
transaction: {
|
|
414
|
+
// ... transaction details
|
|
415
|
+
},
|
|
416
|
+
});
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Sui Transactions
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
import { TransactionBlock } from "@mysten/sui.js/transactions";
|
|
423
|
+
|
|
424
|
+
// Create Sui transaction block
|
|
425
|
+
const txb = new TransactionBlock();
|
|
426
|
+
txb.transferObjects([coin], recipientAddress);
|
|
427
|
+
|
|
428
|
+
const result = await sdk.signAndSendTransaction({
|
|
429
|
+
networkId: NetworkId.SUI_MAINNET,
|
|
430
|
+
transaction: {
|
|
431
|
+
kind: "moveCall", // or 'transferObject', 'transferSui', 'pay'
|
|
432
|
+
data: txb, // TransactionBlock from @mysten/sui.js
|
|
433
|
+
},
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// Sui testnet
|
|
437
|
+
const result = await sdk.signAndSendTransaction({
|
|
438
|
+
networkId: NetworkId.SUI_TESTNET,
|
|
439
|
+
transaction: {
|
|
440
|
+
kind: "transferSui",
|
|
441
|
+
data: suiTransactionData,
|
|
442
|
+
},
|
|
443
|
+
});
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
## Network IDs Reference
|
|
447
|
+
|
|
448
|
+
Use the exported `NetworkId` enum for type safety:
|
|
449
|
+
|
|
450
|
+
```typescript
|
|
451
|
+
import { NetworkId } from "@phantom/browser-sdk";
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### Solana
|
|
455
|
+
|
|
456
|
+
- `NetworkId.SOLANA_MAINNET` - Solana Mainnet Beta
|
|
457
|
+
- `NetworkId.SOLANA_DEVNET` - Solana Devnet
|
|
458
|
+
- `NetworkId.SOLANA_TESTNET` - Solana Testnet
|
|
459
|
+
|
|
460
|
+
### Ethereum/EVM
|
|
461
|
+
|
|
462
|
+
- `NetworkId.ETHEREUM_MAINNET` - Ethereum Mainnet
|
|
463
|
+
- `NetworkId.ETHEREUM_SEPOLIA` - Ethereum Sepolia Testnet
|
|
464
|
+
- `NetworkId.POLYGON_MAINNET` - Polygon Mainnet
|
|
465
|
+
- `NetworkId.ARBITRUM_ONE` - Arbitrum One
|
|
466
|
+
- `NetworkId.OPTIMISM_MAINNET` - Optimism Mainnet
|
|
467
|
+
- `NetworkId.BASE_MAINNET` - Base Mainnet
|
|
468
|
+
|
|
469
|
+
### Bitcoin
|
|
470
|
+
|
|
471
|
+
- `NetworkId.BITCOIN_MAINNET` - Bitcoin Mainnet
|
|
472
|
+
- `NetworkId.BITCOIN_TESTNET` - Bitcoin Testnet
|
|
473
|
+
|
|
474
|
+
### Sui
|
|
475
|
+
|
|
476
|
+
- `NetworkId.SUI_MAINNET` - Sui Mainnet
|
|
477
|
+
- `NetworkId.SUI_TESTNET` - Sui Testnet
|
|
478
|
+
- `NetworkId.SUI_DEVNET` - Sui Devnet
|
|
479
|
+
|
|
480
|
+
## Advanced Usage
|
|
481
|
+
|
|
482
|
+
### Multi-Chain Application
|
|
483
|
+
|
|
484
|
+
```typescript
|
|
485
|
+
import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
|
|
486
|
+
|
|
487
|
+
const sdk = new BrowserSDK({
|
|
488
|
+
addressTypes: [AddressType.solana, AddressType.ethereum, AddressType.sui],
|
|
489
|
+
apiBaseUrl: "https://api.phantom.com",
|
|
490
|
+
organizationId: "your-org-id",
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
class MultiChainWallet {
|
|
494
|
+
async sendSolana(amount: number, recipient: string) {
|
|
495
|
+
const transaction = new Transaction().add(
|
|
496
|
+
SystemProgram.transfer({
|
|
497
|
+
fromPubkey: new PublicKey(this.solanaAddress),
|
|
498
|
+
toPubkey: new PublicKey(recipient),
|
|
499
|
+
lamports: amount * LAMPORTS_PER_SOL,
|
|
500
|
+
}),
|
|
501
|
+
);
|
|
502
|
+
|
|
503
|
+
return await sdk.signAndSendTransaction({
|
|
504
|
+
networkId: NetworkId.SOLANA_MAINNET,
|
|
505
|
+
transaction,
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
async sendEthereum(amount: string, recipient: string) {
|
|
510
|
+
return await sdk.signAndSendTransaction({
|
|
511
|
+
networkId: NetworkId.ETHEREUM_MAINNET,
|
|
512
|
+
transaction: {
|
|
513
|
+
to: recipient,
|
|
514
|
+
value: parseEther(amount),
|
|
515
|
+
gas: 21000n,
|
|
516
|
+
},
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
async sendSui(coinId: string, recipient: string) {
|
|
521
|
+
const txb = new TransactionBlock();
|
|
522
|
+
txb.transferObjects([coinId], recipient);
|
|
523
|
+
|
|
524
|
+
return await sdk.signAndSendTransaction({
|
|
525
|
+
networkId: NetworkId.SUI_MAINNET,
|
|
526
|
+
transaction: {
|
|
527
|
+
kind: "transferObject",
|
|
528
|
+
data: txb,
|
|
529
|
+
},
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
### Error Handling
|
|
536
|
+
|
|
537
|
+
```typescript
|
|
538
|
+
try {
|
|
539
|
+
const result = await sdk.signAndSendTransaction({
|
|
540
|
+
networkId: NetworkId.SOLANA_MAINNET,
|
|
541
|
+
transaction: myTransaction,
|
|
542
|
+
});
|
|
543
|
+
console.log("Success:", result);
|
|
544
|
+
} catch (error) {
|
|
545
|
+
if (error.message.includes("User rejected")) {
|
|
546
|
+
console.log("User cancelled the transaction");
|
|
547
|
+
} else if (error.message.includes("insufficient funds")) {
|
|
548
|
+
console.log("Not enough balance");
|
|
549
|
+
} else {
|
|
550
|
+
console.error("Transaction failed:", error);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### Bundle Optimization Tips
|
|
556
|
+
|
|
557
|
+
1. **Only include networks you need**:
|
|
558
|
+
|
|
559
|
+
```typescript
|
|
560
|
+
// Good: Only Solana (~250KB)
|
|
561
|
+
addressTypes: [AddressType.solana];
|
|
562
|
+
|
|
563
|
+
// Avoid: All networks if not needed (~800KB+)
|
|
564
|
+
addressTypes: [AddressType.solana, AddressType.ethereum, AddressType.sui, AddressType.bitcoinSegwit];
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
2. **Install dependencies based on enabled networks**:
|
|
568
|
+
|
|
569
|
+
| AddressType | Required Dependencies | Bundle Size |
|
|
570
|
+
| --------------------------- | ---------------------------------- | ----------- |
|
|
571
|
+
| `AddressType.solana` | `@solana/web3.js` OR `@solana/kit` | ~250KB |
|
|
572
|
+
| `AddressType.ethereum` | `viem` | ~300KB |
|
|
573
|
+
| `AddressType.bitcoinSegwit` | `bitcoinjs-lib` | ~200KB |
|
|
574
|
+
| `AddressType.sui` | `@mysten/sui.js` | ~250KB |
|
|
575
|
+
|
|
576
|
+
**Example package.json for Solana + Ethereum (using @solana/web3.js)**:
|
|
577
|
+
|
|
578
|
+
```json
|
|
579
|
+
{
|
|
580
|
+
"dependencies": {
|
|
581
|
+
"@phantom/browser-sdk": "^1.0.0",
|
|
582
|
+
"@solana/web3.js": "^1.87.0",
|
|
583
|
+
"viem": "^2.0.0"
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
**Example package.json for Solana + Ethereum (using @solana/kit)**:
|
|
589
|
+
|
|
590
|
+
```json
|
|
591
|
+
{
|
|
592
|
+
"dependencies": {
|
|
593
|
+
"@phantom/browser-sdk": "^1.0.0",
|
|
594
|
+
"@solana/kit": "^2.0.0",
|
|
595
|
+
"viem": "^2.0.0"
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
**Example package.json for Solana only (using @solana/web3.js)**:
|
|
601
|
+
|
|
602
|
+
```json
|
|
603
|
+
{
|
|
604
|
+
"dependencies": {
|
|
605
|
+
"@phantom/browser-sdk": "^1.0.0",
|
|
606
|
+
"@solana/web3.js": "^1.87.0"
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
**Example package.json for Solana only (using @solana/kit)**:
|
|
612
|
+
|
|
613
|
+
```json
|
|
614
|
+
{
|
|
615
|
+
"dependencies": {
|
|
616
|
+
"@phantom/browser-sdk": "^1.0.0",
|
|
617
|
+
"@solana/kit": "^2.0.0"
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
**Example package.json for all networks (using @solana/web3.js)**:
|
|
623
|
+
|
|
624
|
+
```json
|
|
625
|
+
{
|
|
626
|
+
"dependencies": {
|
|
627
|
+
"@phantom/browser-sdk": "^1.0.0",
|
|
628
|
+
"@solana/web3.js": "^1.87.0",
|
|
629
|
+
"viem": "^2.0.0",
|
|
630
|
+
"bitcoinjs-lib": "^6.1.0",
|
|
631
|
+
"@mysten/sui.js": "^0.50.0"
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
**Example package.json for all networks (using @solana/kit)**:
|
|
637
|
+
|
|
638
|
+
```json
|
|
639
|
+
{
|
|
640
|
+
"dependencies": {
|
|
641
|
+
"@phantom/browser-sdk": "^1.0.0",
|
|
642
|
+
"@solana/kit": "^2.0.0",
|
|
643
|
+
"viem": "^2.0.0",
|
|
644
|
+
"bitcoinjs-lib": "^6.1.0",
|
|
645
|
+
"@mysten/sui.js": "^0.50.0"
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
3. **Monitor bundle size**:
|
|
651
|
+
```bash
|
|
652
|
+
# Analyze your bundle
|
|
653
|
+
npx webpack-bundle-analyzer dist/main.js
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
## Server Setup for Embedded Wallets
|
|
657
|
+
|
|
658
|
+
For embedded wallets, you need to set up a backend endpoint. Add the `serverUrl` parameter to your SDK configuration:
|
|
659
|
+
|
|
660
|
+
```typescript
|
|
661
|
+
const sdk = new BrowserSDK({
|
|
662
|
+
providerType: "embedded",
|
|
663
|
+
addressTypes: [AddressType.solana],
|
|
664
|
+
apiBaseUrl: "https://api.phantom.com",
|
|
665
|
+
organizationId: "your-org-id",
|
|
666
|
+
serverUrl: "http://localhost:3000/api",
|
|
667
|
+
});
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
### Required Backend Endpoint
|
|
671
|
+
|
|
672
|
+
Your backend needs an endpoint that uses the server-sdk:
|
|
673
|
+
|
|
674
|
+
```javascript
|
|
675
|
+
// server.js
|
|
676
|
+
const express = require("express");
|
|
677
|
+
const { ServerSDK } = require("@phantom/server-sdk");
|
|
678
|
+
|
|
679
|
+
const app = express();
|
|
680
|
+
app.use(express.json());
|
|
681
|
+
|
|
682
|
+
const serverSDK = new ServerSDK({
|
|
683
|
+
organizationId: process.env.ORGANIZATION_ID,
|
|
684
|
+
apiPrivateKey: process.env.PRIVATE_KEY,
|
|
685
|
+
apiBaseUrl: process.env.API_URL,
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
app.post("/api/organizations", async (req, res) => {
|
|
689
|
+
try {
|
|
690
|
+
const { userId } = req.body;
|
|
691
|
+
|
|
692
|
+
if (!userId) {
|
|
693
|
+
return res.status(400).json({ error: "userId is required" });
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
const organization = await serverSDK.getOrCreateChildOrganizationByTag({
|
|
697
|
+
tag: userId,
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
res.json({ organizationId: organization.id });
|
|
701
|
+
} catch (error) {
|
|
702
|
+
res.status(500).json({ error: "Failed to process request" });
|
|
703
|
+
}
|
|
704
|
+
});
|
|
705
|
+
|
|
706
|
+
app.listen(3000);
|
|
160
707
|
```
|