@phantom/browser-sdk 0.2.3 → 0.3.2
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 +71 -86
- package/dist/index.d.ts +35 -21
- package/dist/index.js +179 -38
- package/dist/index.mjs +169 -38
- package/package.json +7 -5
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ import { BrowserSDK, AddressType, NetworkId } from "@phantom/browser-sdk";
|
|
|
37
37
|
const sdk = new BrowserSDK({
|
|
38
38
|
providerType: "embedded",
|
|
39
39
|
addressTypes: [AddressType.solana, AddressType.ethereum],
|
|
40
|
-
apiBaseUrl: "https://api.phantom.
|
|
40
|
+
apiBaseUrl: "https://api.phantom.app/v1/wallets",
|
|
41
41
|
organizationId: "your-org-id",
|
|
42
42
|
});
|
|
43
43
|
|
|
@@ -80,13 +80,19 @@ Creates a non-custodial wallet embedded in your application. Requires API config
|
|
|
80
80
|
const sdk = new BrowserSDK({
|
|
81
81
|
providerType: "embedded",
|
|
82
82
|
addressTypes: [AddressType.solana, AddressType.ethereum],
|
|
83
|
-
apiBaseUrl: "https://api.phantom.
|
|
83
|
+
apiBaseUrl: "https://api.phantom.app/v1/wallets",
|
|
84
84
|
organizationId: "your-org-id",
|
|
85
85
|
embeddedWalletType: "app-wallet", // or 'user-wallet'
|
|
86
86
|
authOptions: {
|
|
87
87
|
authUrl: "https://auth.phantom.app", // optional, defaults to "https://connect.phantom.app"
|
|
88
88
|
redirectUrl: "https://yourapp.com/callback", // optional, defaults to current page
|
|
89
89
|
},
|
|
90
|
+
appName: "My DApp", // optional, for branding
|
|
91
|
+
appLogo: "https://myapp.com/logo.png", // optional, for branding
|
|
92
|
+
debug: {
|
|
93
|
+
enabled: true, // optional, enable debug logging
|
|
94
|
+
level: "info", // optional, debug level
|
|
95
|
+
},
|
|
90
96
|
});
|
|
91
97
|
```
|
|
92
98
|
|
|
@@ -169,9 +175,11 @@ new BrowserSDK(config: BrowserSDKConfig)
|
|
|
169
175
|
```typescript
|
|
170
176
|
interface BrowserSDKConfig {
|
|
171
177
|
providerType: "injected" | "embedded";
|
|
178
|
+
appName?: string; // Optional app name for branding
|
|
179
|
+
appLogo?: string; // Optional app logo URL for branding
|
|
180
|
+
addressTypes?: AddressType[]; // Networks to enable (e.g., [AddressType.solana])
|
|
172
181
|
|
|
173
182
|
// Required for embedded provider only
|
|
174
|
-
addressTypes?: AddressType[]; // Networks to enable
|
|
175
183
|
apiBaseUrl?: string; // Phantom API base URL
|
|
176
184
|
organizationId?: string; // Your organization ID
|
|
177
185
|
authOptions?: {
|
|
@@ -180,6 +188,13 @@ interface BrowserSDKConfig {
|
|
|
180
188
|
};
|
|
181
189
|
embeddedWalletType?: "app-wallet" | "user-wallet"; // Wallet type
|
|
182
190
|
solanaProvider?: "web3js" | "kit"; // Solana library choice (default: 'web3js')
|
|
191
|
+
|
|
192
|
+
// Debug options
|
|
193
|
+
debug?: {
|
|
194
|
+
enabled?: boolean; // Enable debug logging
|
|
195
|
+
level?: "info" | "warn" | "error"; // Debug level
|
|
196
|
+
callback?: (level: string, message: string, data?: any) => void; // Custom debug callback
|
|
197
|
+
};
|
|
183
198
|
}
|
|
184
199
|
```
|
|
185
200
|
|
|
@@ -237,7 +252,6 @@ const result = await sdk.connect({
|
|
|
237
252
|
**Authentication Flow Types:**
|
|
238
253
|
|
|
239
254
|
1. **Phantom Connect (Redirect-based)**: Used when `provider` is undefined, `"google"`, or `"apple"`
|
|
240
|
-
|
|
241
255
|
- Redirects to `https://connect.phantom.app` (or custom `authOptions.authUrl` from config)
|
|
242
256
|
- Handles OAuth flow with selected provider
|
|
243
257
|
- Returns to your app with authentication result using `authOptions.redirectUrl` or current page
|
|
@@ -317,17 +331,35 @@ npm install @solana/web3.js
|
|
|
317
331
|
```
|
|
318
332
|
|
|
319
333
|
```typescript
|
|
320
|
-
import {
|
|
334
|
+
import {
|
|
335
|
+
VersionedTransaction,
|
|
336
|
+
TransactionMessage,
|
|
337
|
+
SystemProgram,
|
|
338
|
+
PublicKey,
|
|
339
|
+
LAMPORTS_PER_SOL,
|
|
340
|
+
Connection,
|
|
341
|
+
} from "@solana/web3.js";
|
|
321
342
|
import { BrowserSDK, NetworkId } from "@phantom/browser-sdk";
|
|
322
343
|
|
|
323
|
-
//
|
|
324
|
-
const
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
)
|
|
344
|
+
// Get recent blockhash
|
|
345
|
+
const connection = new Connection("https://api.mainnet-beta.solana.com");
|
|
346
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
347
|
+
|
|
348
|
+
// Create transfer instruction
|
|
349
|
+
const transferInstruction = SystemProgram.transfer({
|
|
350
|
+
fromPubkey: new PublicKey(fromAddress),
|
|
351
|
+
toPubkey: new PublicKey(toAddress),
|
|
352
|
+
lamports: 0.001 * LAMPORTS_PER_SOL,
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// Create VersionedTransaction
|
|
356
|
+
const messageV0 = new TransactionMessage({
|
|
357
|
+
payerKey: new PublicKey(fromAddress),
|
|
358
|
+
recentBlockhash: blockhash,
|
|
359
|
+
instructions: [transferInstruction],
|
|
360
|
+
}).compileToV0Message();
|
|
361
|
+
|
|
362
|
+
const transaction = new VersionedTransaction(messageV0);
|
|
331
363
|
|
|
332
364
|
// Send native transaction object - no encoding needed!
|
|
333
365
|
const result = await sdk.signAndSendTransaction({
|
|
@@ -553,19 +585,31 @@ import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
|
|
|
553
585
|
|
|
554
586
|
const sdk = new BrowserSDK({
|
|
555
587
|
addressTypes: [AddressType.solana, AddressType.ethereum, AddressType.sui],
|
|
556
|
-
apiBaseUrl: "https://api.phantom.
|
|
588
|
+
apiBaseUrl: "https://api.phantom.app/v1/wallets",
|
|
557
589
|
organizationId: "your-org-id",
|
|
558
590
|
});
|
|
559
591
|
|
|
560
592
|
class MultiChainWallet {
|
|
561
593
|
async sendSolana(amount: number, recipient: string) {
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
594
|
+
// Get recent blockhash
|
|
595
|
+
const connection = new Connection("https://api.mainnet-beta.solana.com");
|
|
596
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
597
|
+
|
|
598
|
+
// Create transfer instruction
|
|
599
|
+
const transferInstruction = SystemProgram.transfer({
|
|
600
|
+
fromPubkey: new PublicKey(this.solanaAddress),
|
|
601
|
+
toPubkey: new PublicKey(recipient),
|
|
602
|
+
lamports: amount * LAMPORTS_PER_SOL,
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
// Create VersionedTransaction
|
|
606
|
+
const messageV0 = new TransactionMessage({
|
|
607
|
+
payerKey: new PublicKey(this.solanaAddress),
|
|
608
|
+
recentBlockhash: blockhash,
|
|
609
|
+
instructions: [transferInstruction],
|
|
610
|
+
}).compileToV0Message();
|
|
611
|
+
|
|
612
|
+
const transaction = new VersionedTransaction(messageV0);
|
|
569
613
|
|
|
570
614
|
return await sdk.signAndSendTransaction({
|
|
571
615
|
networkId: NetworkId.SOLANA_MAINNET,
|
|
@@ -633,12 +677,12 @@ try {
|
|
|
633
677
|
|
|
634
678
|
2. **Install dependencies based on enabled networks**:
|
|
635
679
|
|
|
636
|
-
| AddressType | Required Dependencies |
|
|
637
|
-
| --------------------------- | ---------------------------------- |
|
|
638
|
-
| `AddressType.solana` | `@solana/web3.js` OR `@solana/kit` |
|
|
639
|
-
| `AddressType.ethereum` | `viem` |
|
|
640
|
-
| `AddressType.bitcoinSegwit` | `bitcoinjs-lib` |
|
|
641
|
-
| `AddressType.sui` | `@mysten/sui.js` |
|
|
680
|
+
| AddressType | Required Dependencies |
|
|
681
|
+
| --------------------------- | ---------------------------------- |
|
|
682
|
+
| `AddressType.solana` | `@solana/web3.js` OR `@solana/kit` |
|
|
683
|
+
| `AddressType.ethereum` | `viem` |
|
|
684
|
+
| `AddressType.bitcoinSegwit` | `bitcoinjs-lib` |
|
|
685
|
+
| `AddressType.sui` | `@mysten/sui.js` |
|
|
642
686
|
|
|
643
687
|
**Example package.json for Solana + Ethereum (using @solana/web3.js)**:
|
|
644
688
|
|
|
@@ -713,62 +757,3 @@ try {
|
|
|
713
757
|
}
|
|
714
758
|
}
|
|
715
759
|
```
|
|
716
|
-
|
|
717
|
-
3. **Monitor bundle size**:
|
|
718
|
-
```bash
|
|
719
|
-
# Analyze your bundle
|
|
720
|
-
npx webpack-bundle-analyzer dist/main.js
|
|
721
|
-
```
|
|
722
|
-
|
|
723
|
-
## Server Setup for Embedded Wallets
|
|
724
|
-
|
|
725
|
-
For embedded wallets, you need to set up a backend endpoint. Add the `serverUrl` parameter to your SDK configuration:
|
|
726
|
-
|
|
727
|
-
```typescript
|
|
728
|
-
const sdk = new BrowserSDK({
|
|
729
|
-
providerType: "embedded",
|
|
730
|
-
addressTypes: [AddressType.solana],
|
|
731
|
-
apiBaseUrl: "https://api.phantom.com",
|
|
732
|
-
organizationId: "your-org-id",
|
|
733
|
-
serverUrl: "http://localhost:3000/api",
|
|
734
|
-
});
|
|
735
|
-
```
|
|
736
|
-
|
|
737
|
-
### Required Backend Endpoint
|
|
738
|
-
|
|
739
|
-
Your backend needs an endpoint that uses the server-sdk:
|
|
740
|
-
|
|
741
|
-
```javascript
|
|
742
|
-
// server.js
|
|
743
|
-
const express = require("express");
|
|
744
|
-
const { ServerSDK } = require("@phantom/server-sdk");
|
|
745
|
-
|
|
746
|
-
const app = express();
|
|
747
|
-
app.use(express.json());
|
|
748
|
-
|
|
749
|
-
const serverSDK = new ServerSDK({
|
|
750
|
-
organizationId: process.env.ORGANIZATION_ID,
|
|
751
|
-
apiPrivateKey: process.env.PRIVATE_KEY,
|
|
752
|
-
apiBaseUrl: process.env.API_URL,
|
|
753
|
-
});
|
|
754
|
-
|
|
755
|
-
app.post("/api/organizations", async (req, res) => {
|
|
756
|
-
try {
|
|
757
|
-
const { userId } = req.body;
|
|
758
|
-
|
|
759
|
-
if (!userId) {
|
|
760
|
-
return res.status(400).json({ error: "userId is required" });
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
const organization = await serverSDK.getOrCreateChildOrganizationByTag({
|
|
764
|
-
tag: userId,
|
|
765
|
-
});
|
|
766
|
-
|
|
767
|
-
res.json({ organizationId: organization.id });
|
|
768
|
-
} catch (error) {
|
|
769
|
-
res.status(500).json({ error: "Failed to process request" });
|
|
770
|
-
}
|
|
771
|
-
});
|
|
772
|
-
|
|
773
|
-
app.listen(3000);
|
|
774
|
-
```
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { AddressType } from '@phantom/client';
|
|
2
|
-
export { AddressType
|
|
3
|
-
import { AuthOptions, ConnectResult, SignMessageParams, SignAndSendTransactionParams, SignedTransaction, WalletAddress } from '@phantom/embedded-provider-core';
|
|
4
|
-
export { AuthOptions, ConnectResult, SignAndSendTransactionParams, SignMessageParams, SignedTransaction, WalletAddress } from '@phantom/embedded-provider-core';
|
|
2
|
+
export { AddressType } from '@phantom/client';
|
|
3
|
+
import { AuthOptions, ConnectResult, SignMessageParams, SignMessageResult, SignAndSendTransactionParams, SignedTransaction, WalletAddress } from '@phantom/embedded-provider-core';
|
|
4
|
+
export { AuthOptions, ConnectResult, SignAndSendTransactionParams, SignMessageParams, SignMessageResult, SignedTransaction, WalletAddress } from '@phantom/embedded-provider-core';
|
|
5
|
+
export { NetworkId } from '@phantom/constants';
|
|
5
6
|
|
|
6
7
|
declare enum DebugLevel {
|
|
7
8
|
ERROR = 0,
|
|
@@ -50,6 +51,7 @@ declare const DebugCategory: {
|
|
|
50
51
|
interface BrowserSDKConfig {
|
|
51
52
|
providerType: "injected" | "embedded" | (string & Record<never, never>);
|
|
52
53
|
appName?: string;
|
|
54
|
+
appLogo?: string;
|
|
53
55
|
addressTypes?: AddressType[];
|
|
54
56
|
apiBaseUrl?: string;
|
|
55
57
|
organizationId?: string;
|
|
@@ -59,25 +61,17 @@ interface BrowserSDKConfig {
|
|
|
59
61
|
};
|
|
60
62
|
embeddedWalletType?: "app-wallet" | "user-wallet" | (string & Record<never, never>);
|
|
61
63
|
solanaProvider?: "web3js" | "kit";
|
|
62
|
-
serverUrl?: string;
|
|
63
64
|
debug?: {
|
|
64
65
|
enabled?: boolean;
|
|
65
66
|
level?: DebugLevel;
|
|
66
67
|
callback?: DebugCallback;
|
|
67
68
|
};
|
|
68
69
|
}
|
|
69
|
-
interface CreateUserOrganizationParams {
|
|
70
|
-
userId: string;
|
|
71
|
-
[key: string]: any;
|
|
72
|
-
}
|
|
73
|
-
interface CreateUserOrganizationResult {
|
|
74
|
-
organizationId: string;
|
|
75
|
-
}
|
|
76
70
|
|
|
77
71
|
interface Provider {
|
|
78
72
|
connect(authOptions?: AuthOptions): Promise<ConnectResult>;
|
|
79
73
|
disconnect(): Promise<void>;
|
|
80
|
-
signMessage(params: SignMessageParams): Promise<
|
|
74
|
+
signMessage(params: SignMessageParams): Promise<SignMessageResult>;
|
|
81
75
|
signAndSendTransaction(params: SignAndSendTransactionParams): Promise<SignedTransaction>;
|
|
82
76
|
getAddresses(): WalletAddress[];
|
|
83
77
|
isConnected(): boolean;
|
|
@@ -93,7 +87,6 @@ interface SwitchProviderOptions {
|
|
|
93
87
|
|
|
94
88
|
declare class BrowserSDK {
|
|
95
89
|
private providerManager;
|
|
96
|
-
private config;
|
|
97
90
|
constructor(config: BrowserSDKConfig);
|
|
98
91
|
/**
|
|
99
92
|
* Connect to the wallet with optional provider switching
|
|
@@ -125,7 +118,7 @@ declare class BrowserSDK {
|
|
|
125
118
|
* @param networkId - Network identifier
|
|
126
119
|
* @returns Signature string
|
|
127
120
|
*/
|
|
128
|
-
signMessage(params: SignMessageParams): Promise<
|
|
121
|
+
signMessage(params: SignMessageParams): Promise<SignMessageResult>;
|
|
129
122
|
/**
|
|
130
123
|
* Sign and send a transaction
|
|
131
124
|
* @param params - Transaction parameters with native transaction object
|
|
@@ -144,12 +137,6 @@ declare class BrowserSDK {
|
|
|
144
137
|
* Get the current wallet ID (for embedded wallets)
|
|
145
138
|
*/
|
|
146
139
|
getWalletId(): string | null;
|
|
147
|
-
/**
|
|
148
|
-
* Create a user organization via your backend API
|
|
149
|
-
* @param params - Parameters including userId and any additional options
|
|
150
|
-
* @returns Organization creation result with organizationId
|
|
151
|
-
*/
|
|
152
|
-
createUserOrganization(params: CreateUserOrganizationParams): Promise<CreateUserOrganizationResult>;
|
|
153
140
|
}
|
|
154
141
|
|
|
155
142
|
/**
|
|
@@ -158,4 +145,31 @@ declare class BrowserSDK {
|
|
|
158
145
|
declare const DEFAULT_AUTH_URL = "https://connect.phantom.app";
|
|
159
146
|
declare const DEFAULT_WALLET_API_URL = "https://api.phantom.app/v1/wallets";
|
|
160
147
|
|
|
161
|
-
|
|
148
|
+
/**
|
|
149
|
+
* Browser detection utility to identify browser name and version
|
|
150
|
+
*/
|
|
151
|
+
interface BrowserInfo {
|
|
152
|
+
name: string;
|
|
153
|
+
version: string;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Parse browser information from a user agent string
|
|
157
|
+
* This is the core parsing logic that can be unit tested independently
|
|
158
|
+
*/
|
|
159
|
+
declare function parseBrowserFromUserAgent(userAgent: string, hasBraveAPI?: boolean): BrowserInfo;
|
|
160
|
+
/**
|
|
161
|
+
* Detect the current browser and version from the user agent string
|
|
162
|
+
*/
|
|
163
|
+
declare function detectBrowser(): BrowserInfo;
|
|
164
|
+
/**
|
|
165
|
+
* Get a formatted platform name for use in authenticator names
|
|
166
|
+
* Format: "browsername-v123" (e.g., "chrome-v120", "firefox-v119")
|
|
167
|
+
*/
|
|
168
|
+
declare function getPlatformName(): string;
|
|
169
|
+
/**
|
|
170
|
+
* Get detailed browser information as a string
|
|
171
|
+
* Format: "Chrome 120.0" or "Firefox 119.0"
|
|
172
|
+
*/
|
|
173
|
+
declare function getBrowserDisplayName(): string;
|
|
174
|
+
|
|
175
|
+
export { BrowserInfo, BrowserSDK, BrowserSDKConfig, DEFAULT_AUTH_URL, DEFAULT_WALLET_API_URL, DebugCallback, DebugCategory, DebugLevel, DebugMessage, Provider, debug, detectBrowser, getBrowserDisplayName, getPlatformName, parseBrowserFromUserAgent };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -26,8 +36,12 @@ __export(src_exports, {
|
|
|
26
36
|
DEFAULT_WALLET_API_URL: () => DEFAULT_WALLET_API_URL,
|
|
27
37
|
DebugCategory: () => DebugCategory,
|
|
28
38
|
DebugLevel: () => DebugLevel,
|
|
29
|
-
NetworkId: () =>
|
|
30
|
-
debug: () => debug
|
|
39
|
+
NetworkId: () => import_constants3.NetworkId,
|
|
40
|
+
debug: () => debug,
|
|
41
|
+
detectBrowser: () => detectBrowser,
|
|
42
|
+
getBrowserDisplayName: () => getBrowserDisplayName,
|
|
43
|
+
getPlatformName: () => getPlatformName,
|
|
44
|
+
parseBrowserFromUserAgent: () => parseBrowserFromUserAgent
|
|
31
45
|
});
|
|
32
46
|
module.exports = __toCommonJS(src_exports);
|
|
33
47
|
|
|
@@ -112,6 +126,9 @@ var DebugCategory = {
|
|
|
112
126
|
};
|
|
113
127
|
|
|
114
128
|
// src/providers/injected/index.ts
|
|
129
|
+
var import_base64url = require("@phantom/base64url");
|
|
130
|
+
var import_constants = require("@phantom/constants");
|
|
131
|
+
var import_bs58 = __toESM(require("bs58"));
|
|
115
132
|
var InjectedProvider = class {
|
|
116
133
|
constructor(config) {
|
|
117
134
|
this.connected = false;
|
|
@@ -210,18 +227,24 @@ var InjectedProvider = class {
|
|
|
210
227
|
throw new Error("Wallet not connected");
|
|
211
228
|
}
|
|
212
229
|
const networkPrefix = params.networkId.split(":")[0].toLowerCase();
|
|
230
|
+
let signatureResult;
|
|
213
231
|
if (networkPrefix === "solana") {
|
|
214
232
|
const { signature } = await this.phantom.solana.signMessage(new TextEncoder().encode(params.message));
|
|
215
|
-
|
|
233
|
+
signatureResult = import_bs58.default.encode(signature);
|
|
216
234
|
} else if (networkPrefix === "ethereum" || networkPrefix === "polygon" || networkPrefix === "eip155") {
|
|
217
235
|
const address = this.addresses.find((addr) => addr.addressType === import_client.AddressType.ethereum)?.address;
|
|
218
236
|
if (!address) {
|
|
219
237
|
throw new Error("No address available");
|
|
220
238
|
}
|
|
221
239
|
const signature = await this.phantom.ethereum.signPersonalMessage(params.message, address);
|
|
222
|
-
|
|
240
|
+
signatureResult = signature;
|
|
241
|
+
} else {
|
|
242
|
+
throw new Error(`Network ${params.networkId} is not supported for injected wallets`);
|
|
223
243
|
}
|
|
224
|
-
|
|
244
|
+
return {
|
|
245
|
+
signature: signatureResult,
|
|
246
|
+
rawSignature: (0, import_base64url.base64urlEncode)(signatureResult)
|
|
247
|
+
};
|
|
225
248
|
}
|
|
226
249
|
async signAndSendTransaction(params) {
|
|
227
250
|
if (!this.connected) {
|
|
@@ -232,7 +255,9 @@ var InjectedProvider = class {
|
|
|
232
255
|
const transaction = params.transaction;
|
|
233
256
|
const result = await this.phantom.solana.signAndSendTransaction(transaction);
|
|
234
257
|
return {
|
|
235
|
-
|
|
258
|
+
hash: result.signature,
|
|
259
|
+
rawTransaction: (0, import_base64url.base64urlEncode)(result.signature),
|
|
260
|
+
blockExplorer: (0, import_constants.getExplorerUrl)(params.networkId, "transaction", result.signature)
|
|
236
261
|
};
|
|
237
262
|
} else if (networkPrefix === "ethereum" || networkPrefix === "polygon" || networkPrefix === "eip155") {
|
|
238
263
|
const toHex = (value) => {
|
|
@@ -255,7 +280,9 @@ var InjectedProvider = class {
|
|
|
255
280
|
};
|
|
256
281
|
const txHash = await this.phantom.ethereum.sendTransaction(txRequest);
|
|
257
282
|
return {
|
|
258
|
-
|
|
283
|
+
hash: txHash,
|
|
284
|
+
rawTransaction: (0, import_base64url.base64urlEncode)(txHash),
|
|
285
|
+
blockExplorer: (0, import_constants.getExplorerUrl)(params.networkId, "transaction", txHash)
|
|
259
286
|
};
|
|
260
287
|
}
|
|
261
288
|
throw new Error(`Network ${params.networkId} is not supported for injected wallets`);
|
|
@@ -270,6 +297,7 @@ var InjectedProvider = class {
|
|
|
270
297
|
|
|
271
298
|
// src/providers/embedded/index.ts
|
|
272
299
|
var import_embedded_provider_core = require("@phantom/embedded-provider-core");
|
|
300
|
+
var import_indexed_db_stamper = require("@phantom/indexed-db-stamper");
|
|
273
301
|
|
|
274
302
|
// src/providers/embedded/adapters/storage.ts
|
|
275
303
|
var BrowserStorage = class {
|
|
@@ -390,7 +418,11 @@ var BrowserAuthProvider = class {
|
|
|
390
418
|
parent_organization_id: phantomOptions.parentOrganizationId,
|
|
391
419
|
redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? window.location.href : ""),
|
|
392
420
|
session_id: phantomOptions.sessionId,
|
|
393
|
-
clear_previous_session: true.toString()
|
|
421
|
+
clear_previous_session: true.toString(),
|
|
422
|
+
app_name: phantomOptions.appName || "",
|
|
423
|
+
// Optional app name
|
|
424
|
+
app_logo: phantomOptions.appLogo || ""
|
|
425
|
+
// Optional app logo URL
|
|
394
426
|
});
|
|
395
427
|
if (phantomOptions.provider) {
|
|
396
428
|
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Provider specified, will skip selection", {
|
|
@@ -495,16 +527,133 @@ var BrowserLogger = class {
|
|
|
495
527
|
}
|
|
496
528
|
};
|
|
497
529
|
|
|
530
|
+
// src/utils/browser-detection.ts
|
|
531
|
+
function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
|
|
532
|
+
let name = "unknown";
|
|
533
|
+
let version = "unknown";
|
|
534
|
+
if (!userAgent || typeof userAgent !== "string") {
|
|
535
|
+
return { name, version };
|
|
536
|
+
}
|
|
537
|
+
try {
|
|
538
|
+
if (userAgent.includes("Edg/")) {
|
|
539
|
+
name = "edge";
|
|
540
|
+
const match = userAgent.match(/Edg\/([0-9]+(?:\.[0-9]+)*)/);
|
|
541
|
+
if (match)
|
|
542
|
+
version = match[1].split(".")[0];
|
|
543
|
+
} else if (userAgent.includes("OPR/") || userAgent.includes("Opera/")) {
|
|
544
|
+
name = "opera";
|
|
545
|
+
const match = userAgent.match(/(?:OPR|Opera)\/([0-9]+(?:\.[0-9]+)*)/);
|
|
546
|
+
if (match)
|
|
547
|
+
version = match[1].split(".")[0];
|
|
548
|
+
} else if (userAgent.includes("SamsungBrowser/")) {
|
|
549
|
+
name = "samsung";
|
|
550
|
+
const match = userAgent.match(/SamsungBrowser\/([0-9]+(?:\.[0-9]+)*)/);
|
|
551
|
+
if (match)
|
|
552
|
+
version = match[1].split(".")[0];
|
|
553
|
+
} else if (userAgent.includes("DuckDuckGo/")) {
|
|
554
|
+
name = "duckduckgo";
|
|
555
|
+
const match = userAgent.match(/DuckDuckGo\/([0-9]+(?:\.[0-9]+)*)/);
|
|
556
|
+
if (match)
|
|
557
|
+
version = match[1].split(".")[0];
|
|
558
|
+
} else if (userAgent.includes("Chrome/") && hasBraveAPI) {
|
|
559
|
+
name = "brave";
|
|
560
|
+
const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
|
|
561
|
+
if (match)
|
|
562
|
+
version = match[1].split(".")[0];
|
|
563
|
+
} else if (userAgent.includes("Mobile/") || userAgent.includes("Android")) {
|
|
564
|
+
if (userAgent.includes("Chrome/")) {
|
|
565
|
+
name = "chrome-mobile";
|
|
566
|
+
const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
|
|
567
|
+
if (match)
|
|
568
|
+
version = match[1].split(".")[0];
|
|
569
|
+
} else if (userAgent.includes("Firefox/")) {
|
|
570
|
+
name = "firefox-mobile";
|
|
571
|
+
const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
|
|
572
|
+
if (match)
|
|
573
|
+
version = match[1].split(".")[0];
|
|
574
|
+
} else if (userAgent.includes("Safari/") && userAgent.includes("Mobile/")) {
|
|
575
|
+
name = "safari-mobile";
|
|
576
|
+
const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
|
|
577
|
+
if (match)
|
|
578
|
+
version = match[1].split(".")[0];
|
|
579
|
+
} else {
|
|
580
|
+
name = "mobile";
|
|
581
|
+
}
|
|
582
|
+
} else if (userAgent.includes("Chrome/")) {
|
|
583
|
+
name = "chrome";
|
|
584
|
+
const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
|
|
585
|
+
if (match)
|
|
586
|
+
version = match[1].split(".")[0];
|
|
587
|
+
} else if (userAgent.includes("Firefox/")) {
|
|
588
|
+
name = "firefox";
|
|
589
|
+
const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
|
|
590
|
+
if (match)
|
|
591
|
+
version = match[1].split(".")[0];
|
|
592
|
+
} else if (userAgent.includes("Safari/") && !userAgent.includes("Chrome/")) {
|
|
593
|
+
name = "safari";
|
|
594
|
+
const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
|
|
595
|
+
if (match)
|
|
596
|
+
version = match[1].split(".")[0];
|
|
597
|
+
}
|
|
598
|
+
if (name === "unknown") {
|
|
599
|
+
const patterns = [
|
|
600
|
+
{ regex: /Chrome\/([0-9]+)/, name: "chrome" },
|
|
601
|
+
{ regex: /Firefox\/([0-9]+)/, name: "firefox" },
|
|
602
|
+
{ regex: /Safari\/([0-9]+)/, name: "safari" },
|
|
603
|
+
{ regex: /Edge\/([0-9]+)/, name: "edge" },
|
|
604
|
+
{ regex: /Opera\/([0-9]+)/, name: "opera" }
|
|
605
|
+
];
|
|
606
|
+
for (const pattern of patterns) {
|
|
607
|
+
const match = userAgent.match(pattern.regex);
|
|
608
|
+
if (match) {
|
|
609
|
+
name = pattern.name;
|
|
610
|
+
version = match[1];
|
|
611
|
+
break;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
} catch (error) {
|
|
616
|
+
}
|
|
617
|
+
return { name, version };
|
|
618
|
+
}
|
|
619
|
+
function detectBrowser() {
|
|
620
|
+
if (typeof window === "undefined" || !window.navigator?.userAgent) {
|
|
621
|
+
return { name: "unknown", version: "unknown" };
|
|
622
|
+
}
|
|
623
|
+
const userAgent = window.navigator.userAgent;
|
|
624
|
+
const hasBraveAPI = !!navigator.brave;
|
|
625
|
+
return parseBrowserFromUserAgent(userAgent, hasBraveAPI);
|
|
626
|
+
}
|
|
627
|
+
function getPlatformName() {
|
|
628
|
+
const { name, version } = detectBrowser();
|
|
629
|
+
return version !== "unknown" ? `${name}-v${version}` : name;
|
|
630
|
+
}
|
|
631
|
+
function getBrowserDisplayName() {
|
|
632
|
+
const { name, version } = detectBrowser();
|
|
633
|
+
const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
|
|
634
|
+
return version !== "unknown" ? `${capitalizedName} ${version}` : capitalizedName;
|
|
635
|
+
}
|
|
636
|
+
|
|
498
637
|
// src/providers/embedded/index.ts
|
|
499
638
|
var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvider {
|
|
500
639
|
constructor(config) {
|
|
501
640
|
debug.log(DebugCategory.EMBEDDED_PROVIDER, "Initializing Browser EmbeddedProvider", { config });
|
|
502
641
|
const urlParamsAccessor = new BrowserURLParamsAccessor();
|
|
642
|
+
const stamper = new import_indexed_db_stamper.IndexedDbStamper({
|
|
643
|
+
dbName: `phantom-embedded-sdk-${config.organizationId}`,
|
|
644
|
+
storeName: "crypto-keys",
|
|
645
|
+
keyName: "signing-key"
|
|
646
|
+
});
|
|
647
|
+
const platformName = getPlatformName();
|
|
503
648
|
const platform = {
|
|
504
649
|
storage: new BrowserStorage(),
|
|
505
650
|
authProvider: new BrowserAuthProvider(urlParamsAccessor),
|
|
506
|
-
urlParamsAccessor
|
|
651
|
+
urlParamsAccessor,
|
|
652
|
+
stamper,
|
|
653
|
+
name: platformName
|
|
654
|
+
// Use detected browser name and version for identification
|
|
507
655
|
};
|
|
656
|
+
debug.log(DebugCategory.EMBEDDED_PROVIDER, "Detected platform", { platformName });
|
|
508
657
|
const logger = new BrowserLogger();
|
|
509
658
|
super(config, platform, logger);
|
|
510
659
|
debug.info(DebugCategory.EMBEDDED_PROVIDER, "Browser EmbeddedProvider initialized");
|
|
@@ -748,7 +897,6 @@ var BrowserSDK = class {
|
|
|
748
897
|
);
|
|
749
898
|
}
|
|
750
899
|
config.embeddedWalletType = embeddedWalletType;
|
|
751
|
-
this.config = config;
|
|
752
900
|
debug.log(DebugCategory.BROWSER_SDK, "Creating ProviderManager", { config });
|
|
753
901
|
this.providerManager = new ProviderManager(config);
|
|
754
902
|
debug.info(DebugCategory.BROWSER_SDK, "BrowserSDK initialized successfully");
|
|
@@ -841,7 +989,17 @@ var BrowserSDK = class {
|
|
|
841
989
|
* @returns Signature string
|
|
842
990
|
*/
|
|
843
991
|
async signMessage(params) {
|
|
844
|
-
|
|
992
|
+
debug.info(DebugCategory.BROWSER_SDK, "Signing message", {
|
|
993
|
+
message: params.message,
|
|
994
|
+
networkId: params.networkId
|
|
995
|
+
});
|
|
996
|
+
const result = await this.providerManager.signMessage(params);
|
|
997
|
+
debug.info(DebugCategory.BROWSER_SDK, "Message signed successfully", {
|
|
998
|
+
message: params.message,
|
|
999
|
+
networkId: params.networkId,
|
|
1000
|
+
result
|
|
1001
|
+
});
|
|
1002
|
+
return result;
|
|
845
1003
|
}
|
|
846
1004
|
/**
|
|
847
1005
|
* Sign and send a transaction
|
|
@@ -849,7 +1007,15 @@ var BrowserSDK = class {
|
|
|
849
1007
|
* @returns Transaction result
|
|
850
1008
|
*/
|
|
851
1009
|
async signAndSendTransaction(params) {
|
|
852
|
-
|
|
1010
|
+
debug.info(DebugCategory.BROWSER_SDK, "Signing and sending transaction", {
|
|
1011
|
+
networkId: params.networkId
|
|
1012
|
+
});
|
|
1013
|
+
const result = await this.providerManager.signAndSendTransaction(params);
|
|
1014
|
+
debug.info(DebugCategory.BROWSER_SDK, "Transaction signed and sent successfully", {
|
|
1015
|
+
networkId: params.networkId,
|
|
1016
|
+
result
|
|
1017
|
+
});
|
|
1018
|
+
return result;
|
|
853
1019
|
}
|
|
854
1020
|
/**
|
|
855
1021
|
* Get wallet addresses
|
|
@@ -869,33 +1035,8 @@ var BrowserSDK = class {
|
|
|
869
1035
|
getWalletId() {
|
|
870
1036
|
return this.providerManager.getWalletId();
|
|
871
1037
|
}
|
|
872
|
-
/**
|
|
873
|
-
* Create a user organization via your backend API
|
|
874
|
-
* @param params - Parameters including userId and any additional options
|
|
875
|
-
* @returns Organization creation result with organizationId
|
|
876
|
-
*/
|
|
877
|
-
async createUserOrganization(params) {
|
|
878
|
-
if (!this.config.serverUrl) {
|
|
879
|
-
throw new Error("serverUrl is required in config to create user organizations");
|
|
880
|
-
}
|
|
881
|
-
try {
|
|
882
|
-
const response = await fetch(`${this.config.serverUrl}/organizations`, {
|
|
883
|
-
method: "POST",
|
|
884
|
-
headers: {
|
|
885
|
-
"Content-Type": "application/json"
|
|
886
|
-
},
|
|
887
|
-
body: JSON.stringify(params)
|
|
888
|
-
});
|
|
889
|
-
if (!response.ok) {
|
|
890
|
-
throw new Error(`Failed to create organization: ${response.status} ${response.statusText}`);
|
|
891
|
-
}
|
|
892
|
-
const result = await response.json();
|
|
893
|
-
return result;
|
|
894
|
-
} catch (error) {
|
|
895
|
-
throw new Error(`Error creating user organization: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
1038
|
};
|
|
899
1039
|
|
|
900
1040
|
// src/index.ts
|
|
1041
|
+
var import_constants3 = require("@phantom/constants");
|
|
901
1042
|
var import_client2 = require("@phantom/client");
|
package/dist/index.mjs
CHANGED
|
@@ -79,6 +79,9 @@ var DebugCategory = {
|
|
|
79
79
|
};
|
|
80
80
|
|
|
81
81
|
// src/providers/injected/index.ts
|
|
82
|
+
import { base64urlEncode } from "@phantom/base64url";
|
|
83
|
+
import { getExplorerUrl } from "@phantom/constants";
|
|
84
|
+
import bs58 from "bs58";
|
|
82
85
|
var InjectedProvider = class {
|
|
83
86
|
constructor(config) {
|
|
84
87
|
this.connected = false;
|
|
@@ -177,18 +180,24 @@ var InjectedProvider = class {
|
|
|
177
180
|
throw new Error("Wallet not connected");
|
|
178
181
|
}
|
|
179
182
|
const networkPrefix = params.networkId.split(":")[0].toLowerCase();
|
|
183
|
+
let signatureResult;
|
|
180
184
|
if (networkPrefix === "solana") {
|
|
181
185
|
const { signature } = await this.phantom.solana.signMessage(new TextEncoder().encode(params.message));
|
|
182
|
-
|
|
186
|
+
signatureResult = bs58.encode(signature);
|
|
183
187
|
} else if (networkPrefix === "ethereum" || networkPrefix === "polygon" || networkPrefix === "eip155") {
|
|
184
188
|
const address = this.addresses.find((addr) => addr.addressType === AddressType.ethereum)?.address;
|
|
185
189
|
if (!address) {
|
|
186
190
|
throw new Error("No address available");
|
|
187
191
|
}
|
|
188
192
|
const signature = await this.phantom.ethereum.signPersonalMessage(params.message, address);
|
|
189
|
-
|
|
193
|
+
signatureResult = signature;
|
|
194
|
+
} else {
|
|
195
|
+
throw new Error(`Network ${params.networkId} is not supported for injected wallets`);
|
|
190
196
|
}
|
|
191
|
-
|
|
197
|
+
return {
|
|
198
|
+
signature: signatureResult,
|
|
199
|
+
rawSignature: base64urlEncode(signatureResult)
|
|
200
|
+
};
|
|
192
201
|
}
|
|
193
202
|
async signAndSendTransaction(params) {
|
|
194
203
|
if (!this.connected) {
|
|
@@ -199,7 +208,9 @@ var InjectedProvider = class {
|
|
|
199
208
|
const transaction = params.transaction;
|
|
200
209
|
const result = await this.phantom.solana.signAndSendTransaction(transaction);
|
|
201
210
|
return {
|
|
202
|
-
|
|
211
|
+
hash: result.signature,
|
|
212
|
+
rawTransaction: base64urlEncode(result.signature),
|
|
213
|
+
blockExplorer: getExplorerUrl(params.networkId, "transaction", result.signature)
|
|
203
214
|
};
|
|
204
215
|
} else if (networkPrefix === "ethereum" || networkPrefix === "polygon" || networkPrefix === "eip155") {
|
|
205
216
|
const toHex = (value) => {
|
|
@@ -222,7 +233,9 @@ var InjectedProvider = class {
|
|
|
222
233
|
};
|
|
223
234
|
const txHash = await this.phantom.ethereum.sendTransaction(txRequest);
|
|
224
235
|
return {
|
|
225
|
-
|
|
236
|
+
hash: txHash,
|
|
237
|
+
rawTransaction: base64urlEncode(txHash),
|
|
238
|
+
blockExplorer: getExplorerUrl(params.networkId, "transaction", txHash)
|
|
226
239
|
};
|
|
227
240
|
}
|
|
228
241
|
throw new Error(`Network ${params.networkId} is not supported for injected wallets`);
|
|
@@ -237,6 +250,7 @@ var InjectedProvider = class {
|
|
|
237
250
|
|
|
238
251
|
// src/providers/embedded/index.ts
|
|
239
252
|
import { EmbeddedProvider as CoreEmbeddedProvider } from "@phantom/embedded-provider-core";
|
|
253
|
+
import { IndexedDbStamper } from "@phantom/indexed-db-stamper";
|
|
240
254
|
|
|
241
255
|
// src/providers/embedded/adapters/storage.ts
|
|
242
256
|
var BrowserStorage = class {
|
|
@@ -357,7 +371,11 @@ var BrowserAuthProvider = class {
|
|
|
357
371
|
parent_organization_id: phantomOptions.parentOrganizationId,
|
|
358
372
|
redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? window.location.href : ""),
|
|
359
373
|
session_id: phantomOptions.sessionId,
|
|
360
|
-
clear_previous_session: true.toString()
|
|
374
|
+
clear_previous_session: true.toString(),
|
|
375
|
+
app_name: phantomOptions.appName || "",
|
|
376
|
+
// Optional app name
|
|
377
|
+
app_logo: phantomOptions.appLogo || ""
|
|
378
|
+
// Optional app logo URL
|
|
361
379
|
});
|
|
362
380
|
if (phantomOptions.provider) {
|
|
363
381
|
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Provider specified, will skip selection", {
|
|
@@ -462,16 +480,133 @@ var BrowserLogger = class {
|
|
|
462
480
|
}
|
|
463
481
|
};
|
|
464
482
|
|
|
483
|
+
// src/utils/browser-detection.ts
|
|
484
|
+
function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
|
|
485
|
+
let name = "unknown";
|
|
486
|
+
let version = "unknown";
|
|
487
|
+
if (!userAgent || typeof userAgent !== "string") {
|
|
488
|
+
return { name, version };
|
|
489
|
+
}
|
|
490
|
+
try {
|
|
491
|
+
if (userAgent.includes("Edg/")) {
|
|
492
|
+
name = "edge";
|
|
493
|
+
const match = userAgent.match(/Edg\/([0-9]+(?:\.[0-9]+)*)/);
|
|
494
|
+
if (match)
|
|
495
|
+
version = match[1].split(".")[0];
|
|
496
|
+
} else if (userAgent.includes("OPR/") || userAgent.includes("Opera/")) {
|
|
497
|
+
name = "opera";
|
|
498
|
+
const match = userAgent.match(/(?:OPR|Opera)\/([0-9]+(?:\.[0-9]+)*)/);
|
|
499
|
+
if (match)
|
|
500
|
+
version = match[1].split(".")[0];
|
|
501
|
+
} else if (userAgent.includes("SamsungBrowser/")) {
|
|
502
|
+
name = "samsung";
|
|
503
|
+
const match = userAgent.match(/SamsungBrowser\/([0-9]+(?:\.[0-9]+)*)/);
|
|
504
|
+
if (match)
|
|
505
|
+
version = match[1].split(".")[0];
|
|
506
|
+
} else if (userAgent.includes("DuckDuckGo/")) {
|
|
507
|
+
name = "duckduckgo";
|
|
508
|
+
const match = userAgent.match(/DuckDuckGo\/([0-9]+(?:\.[0-9]+)*)/);
|
|
509
|
+
if (match)
|
|
510
|
+
version = match[1].split(".")[0];
|
|
511
|
+
} else if (userAgent.includes("Chrome/") && hasBraveAPI) {
|
|
512
|
+
name = "brave";
|
|
513
|
+
const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
|
|
514
|
+
if (match)
|
|
515
|
+
version = match[1].split(".")[0];
|
|
516
|
+
} else if (userAgent.includes("Mobile/") || userAgent.includes("Android")) {
|
|
517
|
+
if (userAgent.includes("Chrome/")) {
|
|
518
|
+
name = "chrome-mobile";
|
|
519
|
+
const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
|
|
520
|
+
if (match)
|
|
521
|
+
version = match[1].split(".")[0];
|
|
522
|
+
} else if (userAgent.includes("Firefox/")) {
|
|
523
|
+
name = "firefox-mobile";
|
|
524
|
+
const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
|
|
525
|
+
if (match)
|
|
526
|
+
version = match[1].split(".")[0];
|
|
527
|
+
} else if (userAgent.includes("Safari/") && userAgent.includes("Mobile/")) {
|
|
528
|
+
name = "safari-mobile";
|
|
529
|
+
const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
|
|
530
|
+
if (match)
|
|
531
|
+
version = match[1].split(".")[0];
|
|
532
|
+
} else {
|
|
533
|
+
name = "mobile";
|
|
534
|
+
}
|
|
535
|
+
} else if (userAgent.includes("Chrome/")) {
|
|
536
|
+
name = "chrome";
|
|
537
|
+
const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
|
|
538
|
+
if (match)
|
|
539
|
+
version = match[1].split(".")[0];
|
|
540
|
+
} else if (userAgent.includes("Firefox/")) {
|
|
541
|
+
name = "firefox";
|
|
542
|
+
const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
|
|
543
|
+
if (match)
|
|
544
|
+
version = match[1].split(".")[0];
|
|
545
|
+
} else if (userAgent.includes("Safari/") && !userAgent.includes("Chrome/")) {
|
|
546
|
+
name = "safari";
|
|
547
|
+
const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
|
|
548
|
+
if (match)
|
|
549
|
+
version = match[1].split(".")[0];
|
|
550
|
+
}
|
|
551
|
+
if (name === "unknown") {
|
|
552
|
+
const patterns = [
|
|
553
|
+
{ regex: /Chrome\/([0-9]+)/, name: "chrome" },
|
|
554
|
+
{ regex: /Firefox\/([0-9]+)/, name: "firefox" },
|
|
555
|
+
{ regex: /Safari\/([0-9]+)/, name: "safari" },
|
|
556
|
+
{ regex: /Edge\/([0-9]+)/, name: "edge" },
|
|
557
|
+
{ regex: /Opera\/([0-9]+)/, name: "opera" }
|
|
558
|
+
];
|
|
559
|
+
for (const pattern of patterns) {
|
|
560
|
+
const match = userAgent.match(pattern.regex);
|
|
561
|
+
if (match) {
|
|
562
|
+
name = pattern.name;
|
|
563
|
+
version = match[1];
|
|
564
|
+
break;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
} catch (error) {
|
|
569
|
+
}
|
|
570
|
+
return { name, version };
|
|
571
|
+
}
|
|
572
|
+
function detectBrowser() {
|
|
573
|
+
if (typeof window === "undefined" || !window.navigator?.userAgent) {
|
|
574
|
+
return { name: "unknown", version: "unknown" };
|
|
575
|
+
}
|
|
576
|
+
const userAgent = window.navigator.userAgent;
|
|
577
|
+
const hasBraveAPI = !!navigator.brave;
|
|
578
|
+
return parseBrowserFromUserAgent(userAgent, hasBraveAPI);
|
|
579
|
+
}
|
|
580
|
+
function getPlatformName() {
|
|
581
|
+
const { name, version } = detectBrowser();
|
|
582
|
+
return version !== "unknown" ? `${name}-v${version}` : name;
|
|
583
|
+
}
|
|
584
|
+
function getBrowserDisplayName() {
|
|
585
|
+
const { name, version } = detectBrowser();
|
|
586
|
+
const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
|
|
587
|
+
return version !== "unknown" ? `${capitalizedName} ${version}` : capitalizedName;
|
|
588
|
+
}
|
|
589
|
+
|
|
465
590
|
// src/providers/embedded/index.ts
|
|
466
591
|
var EmbeddedProvider = class extends CoreEmbeddedProvider {
|
|
467
592
|
constructor(config) {
|
|
468
593
|
debug.log(DebugCategory.EMBEDDED_PROVIDER, "Initializing Browser EmbeddedProvider", { config });
|
|
469
594
|
const urlParamsAccessor = new BrowserURLParamsAccessor();
|
|
595
|
+
const stamper = new IndexedDbStamper({
|
|
596
|
+
dbName: `phantom-embedded-sdk-${config.organizationId}`,
|
|
597
|
+
storeName: "crypto-keys",
|
|
598
|
+
keyName: "signing-key"
|
|
599
|
+
});
|
|
600
|
+
const platformName = getPlatformName();
|
|
470
601
|
const platform = {
|
|
471
602
|
storage: new BrowserStorage(),
|
|
472
603
|
authProvider: new BrowserAuthProvider(urlParamsAccessor),
|
|
473
|
-
urlParamsAccessor
|
|
604
|
+
urlParamsAccessor,
|
|
605
|
+
stamper,
|
|
606
|
+
name: platformName
|
|
607
|
+
// Use detected browser name and version for identification
|
|
474
608
|
};
|
|
609
|
+
debug.log(DebugCategory.EMBEDDED_PROVIDER, "Detected platform", { platformName });
|
|
475
610
|
const logger = new BrowserLogger();
|
|
476
611
|
super(config, platform, logger);
|
|
477
612
|
debug.info(DebugCategory.EMBEDDED_PROVIDER, "Browser EmbeddedProvider initialized");
|
|
@@ -715,7 +850,6 @@ var BrowserSDK = class {
|
|
|
715
850
|
);
|
|
716
851
|
}
|
|
717
852
|
config.embeddedWalletType = embeddedWalletType;
|
|
718
|
-
this.config = config;
|
|
719
853
|
debug.log(DebugCategory.BROWSER_SDK, "Creating ProviderManager", { config });
|
|
720
854
|
this.providerManager = new ProviderManager(config);
|
|
721
855
|
debug.info(DebugCategory.BROWSER_SDK, "BrowserSDK initialized successfully");
|
|
@@ -808,7 +942,17 @@ var BrowserSDK = class {
|
|
|
808
942
|
* @returns Signature string
|
|
809
943
|
*/
|
|
810
944
|
async signMessage(params) {
|
|
811
|
-
|
|
945
|
+
debug.info(DebugCategory.BROWSER_SDK, "Signing message", {
|
|
946
|
+
message: params.message,
|
|
947
|
+
networkId: params.networkId
|
|
948
|
+
});
|
|
949
|
+
const result = await this.providerManager.signMessage(params);
|
|
950
|
+
debug.info(DebugCategory.BROWSER_SDK, "Message signed successfully", {
|
|
951
|
+
message: params.message,
|
|
952
|
+
networkId: params.networkId,
|
|
953
|
+
result
|
|
954
|
+
});
|
|
955
|
+
return result;
|
|
812
956
|
}
|
|
813
957
|
/**
|
|
814
958
|
* Sign and send a transaction
|
|
@@ -816,7 +960,15 @@ var BrowserSDK = class {
|
|
|
816
960
|
* @returns Transaction result
|
|
817
961
|
*/
|
|
818
962
|
async signAndSendTransaction(params) {
|
|
819
|
-
|
|
963
|
+
debug.info(DebugCategory.BROWSER_SDK, "Signing and sending transaction", {
|
|
964
|
+
networkId: params.networkId
|
|
965
|
+
});
|
|
966
|
+
const result = await this.providerManager.signAndSendTransaction(params);
|
|
967
|
+
debug.info(DebugCategory.BROWSER_SDK, "Transaction signed and sent successfully", {
|
|
968
|
+
networkId: params.networkId,
|
|
969
|
+
result
|
|
970
|
+
});
|
|
971
|
+
return result;
|
|
820
972
|
}
|
|
821
973
|
/**
|
|
822
974
|
* Get wallet addresses
|
|
@@ -836,36 +988,11 @@ var BrowserSDK = class {
|
|
|
836
988
|
getWalletId() {
|
|
837
989
|
return this.providerManager.getWalletId();
|
|
838
990
|
}
|
|
839
|
-
/**
|
|
840
|
-
* Create a user organization via your backend API
|
|
841
|
-
* @param params - Parameters including userId and any additional options
|
|
842
|
-
* @returns Organization creation result with organizationId
|
|
843
|
-
*/
|
|
844
|
-
async createUserOrganization(params) {
|
|
845
|
-
if (!this.config.serverUrl) {
|
|
846
|
-
throw new Error("serverUrl is required in config to create user organizations");
|
|
847
|
-
}
|
|
848
|
-
try {
|
|
849
|
-
const response = await fetch(`${this.config.serverUrl}/organizations`, {
|
|
850
|
-
method: "POST",
|
|
851
|
-
headers: {
|
|
852
|
-
"Content-Type": "application/json"
|
|
853
|
-
},
|
|
854
|
-
body: JSON.stringify(params)
|
|
855
|
-
});
|
|
856
|
-
if (!response.ok) {
|
|
857
|
-
throw new Error(`Failed to create organization: ${response.status} ${response.statusText}`);
|
|
858
|
-
}
|
|
859
|
-
const result = await response.json();
|
|
860
|
-
return result;
|
|
861
|
-
} catch (error) {
|
|
862
|
-
throw new Error(`Error creating user organization: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
991
|
};
|
|
866
992
|
|
|
867
993
|
// src/index.ts
|
|
868
|
-
import { NetworkId
|
|
994
|
+
import { NetworkId } from "@phantom/constants";
|
|
995
|
+
import { AddressType as AddressType2 } from "@phantom/client";
|
|
869
996
|
export {
|
|
870
997
|
AddressType2 as AddressType,
|
|
871
998
|
BrowserSDK,
|
|
@@ -874,5 +1001,9 @@ export {
|
|
|
874
1001
|
DebugCategory,
|
|
875
1002
|
DebugLevel,
|
|
876
1003
|
NetworkId,
|
|
877
|
-
debug
|
|
1004
|
+
debug,
|
|
1005
|
+
detectBrowser,
|
|
1006
|
+
getBrowserDisplayName,
|
|
1007
|
+
getPlatformName,
|
|
1008
|
+
parseBrowserFromUserAgent
|
|
878
1009
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phantom/browser-sdk",
|
|
3
|
-
"version": "0.2
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Browser SDK for Phantom Wallet with unified interface",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -24,15 +24,17 @@
|
|
|
24
24
|
"test": "jest",
|
|
25
25
|
"test:watch": "jest --watch",
|
|
26
26
|
"lint": "tsc --noEmit && eslint --cache . --ext .ts,.tsx",
|
|
27
|
+
"check-types": "tsc --noEmit",
|
|
27
28
|
"prettier": "prettier --write \"src/**/*.{ts,tsx}\""
|
|
28
29
|
},
|
|
29
30
|
"dependencies": {
|
|
30
|
-
"@phantom/api-key-stamper": "^0.1.1",
|
|
31
31
|
"@phantom/base64url": "^0.1.0",
|
|
32
32
|
"@phantom/browser-injected-sdk": "^0.0.9",
|
|
33
|
-
"@phantom/client": "^0.1.
|
|
34
|
-
"@phantom/
|
|
35
|
-
"@phantom/
|
|
33
|
+
"@phantom/client": "^0.1.6",
|
|
34
|
+
"@phantom/constants": "^0.0.2",
|
|
35
|
+
"@phantom/embedded-provider-core": "^0.1.3",
|
|
36
|
+
"@phantom/indexed-db-stamper": "^0.1.2",
|
|
37
|
+
"@phantom/parsers": "^0.0.6",
|
|
36
38
|
"axios": "^1.10.0",
|
|
37
39
|
"bs58": "^6.0.0",
|
|
38
40
|
"buffer": "^6.0.3",
|