@frontiertower/frontier-sdk 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 ADDED
@@ -0,0 +1,107 @@
1
+ # Frontier Wallet SDK
2
+
3
+ Official SDK for building apps on Frontier Wallet.
4
+
5
+ ## Example Project
6
+
7
+ Check out [**frontier-kickstarter**](https://github.com/BerlinhouseLabs/frontier-kickstarter) - a complete example project that demonstrates how to use this SDK to build a decentralized crowdfunding platform on Frontier Wallet.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @frontier-wallet/sdk
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```typescript
18
+ import { FrontierSDK } from '@frontier-wallet/sdk';
19
+ import { isInFrontierApp, renderStandaloneMessage } from '@frontier-wallet/sdk/ui-utils';
20
+
21
+ // Initialize the SDK
22
+ const sdk = new FrontierSDK();
23
+
24
+ // Check if running in Frontier Wallet
25
+ if (!isInFrontierApp()) {
26
+ renderStandaloneMessage(document.body, 'My App');
27
+ return;
28
+ }
29
+
30
+ // Access wallet information
31
+ const balance = await sdk.getWallet().getBalance();
32
+ const address = await sdk.getWallet().getAddress();
33
+
34
+ // Use persistent storage
35
+ await sdk.getStorage().set('myKey', { value: 'myData' });
36
+ const data = await sdk.getStorage().get('myKey');
37
+ ```
38
+
39
+
40
+ ## Permissions
41
+
42
+ Your app must declare required permissions in the Frontier app registry:
43
+
44
+ ### Wallet Permissions
45
+ - `wallet:getBalance` - Access wallet balance
46
+ - `wallet:getBalanceFormatted` - Access formatted wallet balance
47
+ - `wallet:getAddress` - Access wallet address
48
+ - `wallet:getSmartAccount` - Access smart account details
49
+ - `wallet:transferERC20` - Transfer ERC20 tokens
50
+ - `wallet:approveERC20` - Approve ERC20 token spending
51
+ - `wallet:transferNative` - Transfer native currency (ETH)
52
+ - `wallet:executeCall` - Execute arbitrary contract calls
53
+
54
+ ### Storage Permissions
55
+ - `storage:get` - Read from storage
56
+ - `storage:set` - Write to storage
57
+ - `storage:remove` - Remove from storage
58
+ - `storage:clear` - Clear all storage
59
+ - `storage:*` - Full storage access (wildcard for all storage methods)
60
+
61
+ ### User Permissions
62
+ - `user:getDetails` - Access current user details
63
+ - `user:getProfile` - Access user profile information
64
+
65
+ ### Chain Permissions
66
+ - `chain:getCurrentNetwork` - Get current network name
67
+ - `chain:getAvailableNetworks` - Get list of available networks
68
+ - `chain:switchNetwork` - Switch to a different network
69
+ - `chain:getCurrentChainConfig` - Get full chain configuration
70
+
71
+ ## Security
72
+
73
+ The SDK verifies that apps are running in legitimate Frontier Wallet instances. Allowed origins:
74
+
75
+ - `http://localhost:5173` (development)
76
+ - `https://sandbox.wallet.frontiertower.io`
77
+ - `https://alpha.wallet.frontiertower.io`
78
+ - `https://beta.wallet.frontiertower.io`
79
+ - `https://wallet.frontiertower.io` (production)
80
+
81
+ ## Development
82
+
83
+ ```bash
84
+ # Install dependencies
85
+ npm install
86
+
87
+ # Run tests
88
+ npm test
89
+
90
+ # Build the SDK
91
+ npm run build
92
+
93
+ # Watch mode for development
94
+ npm run dev
95
+ ```
96
+
97
+ ## Contributing
98
+
99
+ Contributions are welcome! Please feel free to submit a Pull Request.
100
+
101
+ ## License
102
+
103
+ MIT © Frontier Tower
104
+
105
+ ## Support
106
+
107
+ For questions and support, please visit [Frontier Tower](https://frontiertower.io) or open an issue on GitHub.
@@ -0,0 +1,542 @@
1
+ /**
2
+ * Smart account information
3
+ */
4
+ interface SmartAccount {
5
+ /** Unique identifier for the smart account */
6
+ id: number;
7
+ /** Owner's EOA address */
8
+ ownerAddress: string;
9
+ /** Deployed smart contract address (null if not yet deployed) */
10
+ contractAddress: string | null;
11
+ /** Network identifier (e.g., 'sepolia', 'mainnet') */
12
+ network: string;
13
+ /** Deployment status */
14
+ status: string;
15
+ /** Transaction hash of the deployment */
16
+ deploymentTransactionHash: string;
17
+ /** Creation timestamp */
18
+ createdAt: string;
19
+ }
20
+ /**
21
+ * Transaction receipt from a user operation
22
+ */
23
+ interface UserOperationReceipt {
24
+ /** User operation hash */
25
+ userOpHash: string;
26
+ /** Transaction hash */
27
+ transactionHash: string;
28
+ /** Block number */
29
+ blockNumber: bigint;
30
+ /** Whether the operation was successful */
31
+ success: boolean;
32
+ }
33
+ /**
34
+ * Gas override options for transactions
35
+ */
36
+ interface GasOverrides {
37
+ /** Maximum fee per gas */
38
+ maxFeePerGas?: bigint;
39
+ /** Maximum priority fee per gas */
40
+ maxPriorityFeePerGas?: bigint;
41
+ /** Gas limit */
42
+ gasLimit?: bigint;
43
+ }
44
+ /**
45
+ * Execute call parameters for arbitrary contract interactions
46
+ */
47
+ interface ExecuteCall {
48
+ /** Target contract address */
49
+ to: string;
50
+ /** Value to send (in wei) */
51
+ value?: bigint;
52
+ /** Calldata */
53
+ data: string;
54
+ }
55
+ /**
56
+ * Wallet access class for interacting with the user's wallet
57
+ *
58
+ * This class provides methods to:
59
+ * - Query wallet addresses and smart accounts
60
+ * - Check balances for stablecoins
61
+ * - Transfer ERC20 tokens and native currency
62
+ * - Execute arbitrary contract calls
63
+ *
64
+ * All methods use the current chain from the chain manager.
65
+ * All methods require appropriate permissions and may trigger biometric authentication.
66
+ */
67
+ declare class WalletAccess {
68
+ private sdk;
69
+ constructor(sdk: FrontierSDK);
70
+ /**
71
+ * Get the current wallet balance
72
+ *
73
+ * Returns the total USD stablecoin balance for the current network,
74
+ * normalized to 18 decimals for consistency.
75
+ *
76
+ * @returns Balance as bigint (18 decimals)
77
+ * @throws {Error} If no wallet exists
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const balance = await sdk.getWallet().getBalance();
82
+ * console.log('Balance:', balance.toString());
83
+ * ```
84
+ */
85
+ getBalance(): Promise<bigint>;
86
+ /**
87
+ * Get the current wallet balance formatted for display
88
+ *
89
+ * Returns the total USD stablecoin balance as a formatted string
90
+ * with currency symbol (e.g., '$10.50').
91
+ *
92
+ * @returns Formatted balance string with $ sign
93
+ * @throws {Error} If no wallet exists
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * const balance = await sdk.getWallet().getBalanceFormatted();
98
+ * console.log('Balance:', balance); // '$10.50'
99
+ * ```
100
+ */
101
+ getBalanceFormatted(): Promise<string>;
102
+ /**
103
+ * Get the wallet address for the current network
104
+ *
105
+ * Returns the smart account contract address for the current chain.
106
+ *
107
+ * @returns The wallet address as a hex string
108
+ * @throws {Error} If no wallet exists
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * const address = await sdk.getWallet().getAddress();
113
+ * console.log('Address:', address);
114
+ * ```
115
+ */
116
+ getAddress(): Promise<string>;
117
+ /**
118
+ * Get smart account for the current network
119
+ *
120
+ * Returns detailed information about the smart account including
121
+ * deployment status and network information.
122
+ *
123
+ * @returns Smart account information
124
+ * @throws {Error} If no smart account found for current network
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * const account = await sdk.getWallet().getSmartAccount();
129
+ * console.log('Contract address:', account.contractAddress);
130
+ * console.log('Network:', account.network);
131
+ * ```
132
+ */
133
+ getSmartAccount(): Promise<SmartAccount>;
134
+ /**
135
+ * Transfer ERC20 tokens
136
+ *
137
+ * Sends ERC20 tokens to a recipient address using the current network.
138
+ * Requires biometric authentication and sufficient balance.
139
+ *
140
+ * @param tokenAddress - ERC20 token contract address
141
+ * @param to - Recipient address
142
+ * @param amount - Amount to send (in token's smallest unit, e.g., wei)
143
+ * @param overrides - Optional gas overrides
144
+ * @returns User operation receipt with transaction details
145
+ * @throws {Error} If insufficient balance or transaction fails
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * import { parseUnits } from 'viem';
150
+ *
151
+ * const receipt = await sdk.getWallet().transferERC20(
152
+ * '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238', // USDC on Sepolia
153
+ * '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
154
+ * parseUnits('10.5', 6) // 10.5 USDC (6 decimals)
155
+ * );
156
+ * console.log('Transaction:', receipt.transactionHash);
157
+ * ```
158
+ */
159
+ transferERC20(tokenAddress: string, to: string, amount: bigint, overrides?: GasOverrides): Promise<UserOperationReceipt>;
160
+ /**
161
+ * Approve ERC20 tokens for spending
162
+ *
163
+ * Approves a spender to transfer tokens on your behalf.
164
+ * Required before interacting with DeFi protocols.
165
+ *
166
+ * @param tokenAddress - ERC20 token contract address
167
+ * @param spender - Address allowed to spend tokens
168
+ * @param amount - Amount to approve (in token's smallest unit)
169
+ * @param overrides - Optional gas overrides
170
+ * @returns User operation receipt with transaction details
171
+ * @throws {Error} If transaction fails
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * import { parseUnits } from 'viem';
176
+ *
177
+ * const receipt = await sdk.getWallet().approveERC20(
178
+ * '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238', // USDC
179
+ * '0xProtocolAddress',
180
+ * parseUnits('100', 6) // Approve 100 USDC
181
+ * );
182
+ * ```
183
+ */
184
+ approveERC20(tokenAddress: string, spender: string, amount: bigint, overrides?: GasOverrides): Promise<UserOperationReceipt>;
185
+ /**
186
+ * Transfer native currency (ETH)
187
+ *
188
+ * Sends native currency to a recipient address.
189
+ * Requires biometric authentication and sufficient balance.
190
+ *
191
+ * @param to - Recipient address
192
+ * @param amount - Amount to send in wei
193
+ * @param overrides - Optional gas overrides
194
+ * @returns User operation receipt with transaction details
195
+ * @throws {Error} If insufficient balance or transaction fails
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * import { parseEther } from 'viem';
200
+ *
201
+ * const receipt = await sdk.getWallet().transferNative(
202
+ * '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
203
+ * parseEther('0.1') // 0.1 ETH
204
+ * );
205
+ * ```
206
+ */
207
+ transferNative(to: string, amount: bigint, overrides?: GasOverrides): Promise<UserOperationReceipt>;
208
+ /**
209
+ * Execute arbitrary contract call
210
+ *
211
+ * Executes a custom contract interaction with full control over
212
+ * the target address, value, and calldata.
213
+ *
214
+ * @param call - Execute call parameters
215
+ * @param overrides - Optional gas overrides
216
+ * @returns User operation receipt with transaction details
217
+ * @throws {Error} If transaction fails
218
+ *
219
+ * @example
220
+ * ```typescript
221
+ * import { encodeFunctionData } from 'viem';
222
+ *
223
+ * const receipt = await sdk.getWallet().executeCall({
224
+ * to: '0xContractAddress',
225
+ * value: 0n,
226
+ * data: encodeFunctionData({
227
+ * abi: contractABI,
228
+ * functionName: 'someFunction',
229
+ * args: [arg1, arg2]
230
+ * })
231
+ * });
232
+ * ```
233
+ */
234
+ executeCall(call: ExecuteCall, overrides?: GasOverrides): Promise<UserOperationReceipt>;
235
+ }
236
+
237
+ /**
238
+ * Storage access class for persistent app storage
239
+ */
240
+ declare class StorageAccess {
241
+ private sdk;
242
+ constructor(sdk: FrontierSDK);
243
+ /**
244
+ * Get data from persistent storage
245
+ * Requires permission: storage:get or storage:*
246
+ */
247
+ get(key: string): Promise<any>;
248
+ /**
249
+ * Store data persistently
250
+ * Requires permission: storage:set or storage:*
251
+ */
252
+ set(key: string, value: any): Promise<void>;
253
+ /**
254
+ * Remove data from persistent storage
255
+ * Requires permission: storage:remove or storage:*
256
+ */
257
+ remove(key: string): Promise<void>;
258
+ /**
259
+ * Clear all data from persistent storage
260
+ * Requires permission: storage:clear or storage:*
261
+ */
262
+ clear(): Promise<void>;
263
+ }
264
+
265
+ /**
266
+ * Chain configuration information
267
+ */
268
+ interface ChainConfig {
269
+ /** Chain ID */
270
+ id: number;
271
+ /** Chain name */
272
+ name: string;
273
+ /** Network identifier */
274
+ network: string;
275
+ /** Native currency information */
276
+ nativeCurrency: {
277
+ name: string;
278
+ symbol: string;
279
+ decimals: number;
280
+ };
281
+ /** RPC URL */
282
+ rpcUrl: string;
283
+ /** Block explorer information */
284
+ blockExplorer: {
285
+ name: string;
286
+ url: string;
287
+ };
288
+ /** Whether this is a testnet */
289
+ testnet: boolean;
290
+ }
291
+ /**
292
+ * Chain access class for interacting with blockchain networks
293
+ *
294
+ * This class provides methods to:
295
+ * - Query current network information
296
+ * - Get available networks
297
+ * - Switch between networks
298
+ * - Get full chain configuration
299
+ *
300
+ * All methods require appropriate permissions.
301
+ */
302
+ declare class ChainAccess {
303
+ private sdk;
304
+ constructor(sdk: FrontierSDK);
305
+ /**
306
+ * Get the current network name
307
+ *
308
+ * Returns the network identifier for the currently active chain
309
+ * (e.g., 'base', 'base-sepolia', 'ethereum').
310
+ *
311
+ * @returns Network identifier string
312
+ *
313
+ * @example
314
+ * ```typescript
315
+ * const network = await sdk.getChain().getCurrentNetwork();
316
+ * console.log('Current network:', network); // 'base-sepolia'
317
+ * ```
318
+ */
319
+ getCurrentNetwork(): Promise<string>;
320
+ /**
321
+ * Get all available networks
322
+ *
323
+ * Returns a list of network identifiers that the app can switch to.
324
+ *
325
+ * @returns Array of network identifier strings
326
+ *
327
+ * @example
328
+ * ```typescript
329
+ * const networks = await sdk.getChain().getAvailableNetworks();
330
+ * console.log('Available networks:', networks); // ['base', 'base-sepolia']
331
+ * ```
332
+ */
333
+ getAvailableNetworks(): Promise<string[]>;
334
+ /**
335
+ * Switch to a different network
336
+ *
337
+ * Changes the active blockchain network. This will affect all subsequent
338
+ * wallet operations and contract interactions.
339
+ *
340
+ * @param network - The network identifier to switch to
341
+ * @throws {Error} If the network is not available or switching fails
342
+ *
343
+ * @example
344
+ * ```typescript
345
+ * await sdk.getChain().switchNetwork('base');
346
+ * console.log('Switched to Base mainnet');
347
+ * ```
348
+ */
349
+ switchNetwork(network: string): Promise<void>;
350
+ /**
351
+ * Get full chain configuration for current network
352
+ *
353
+ * Returns detailed configuration including chain ID, RPC URLs,
354
+ * block explorer, and native currency information.
355
+ *
356
+ * @returns Complete chain configuration object
357
+ *
358
+ * @example
359
+ * ```typescript
360
+ * const config = await sdk.getChain().getCurrentChainConfig();
361
+ * console.log('Chain ID:', config.id);
362
+ * console.log('Block explorer:', config.blockExplorer.url);
363
+ * ```
364
+ */
365
+ getCurrentChainConfig(): Promise<ChainConfig>;
366
+ }
367
+
368
+ /**
369
+ * Basic user information
370
+ */
371
+ interface User {
372
+ /** Unique user identifier */
373
+ id: string;
374
+ /** User's email address */
375
+ email: string;
376
+ /** User's first name (optional) */
377
+ firstName?: string;
378
+ /** User's last name (optional) */
379
+ lastName?: string;
380
+ /** Username (optional) */
381
+ username?: string;
382
+ }
383
+ /**
384
+ * Detailed user profile information
385
+ */
386
+ interface UserProfile {
387
+ /** Profile ID */
388
+ id: number;
389
+ /** Associated user ID */
390
+ user: number;
391
+ /** First name */
392
+ firstName: string;
393
+ /** Last name */
394
+ lastName: string;
395
+ /** Nickname */
396
+ nickname: string;
397
+ /** Profile picture URL */
398
+ profilePicture: string;
399
+ /** Phone number */
400
+ phoneNumber: string;
401
+ /** Community identifier */
402
+ community: string;
403
+ /** Community name */
404
+ communityName: string;
405
+ /** Organization name */
406
+ organization: string;
407
+ /** Role in organization */
408
+ organizationRole: string;
409
+ /** Social media site */
410
+ socialSite: string;
411
+ /** Social media handle */
412
+ socialHandle: string;
413
+ /** GitHub username */
414
+ githubHandle: string;
415
+ /** Current work description */
416
+ currentWork: string;
417
+ /** Notable work achievements */
418
+ notableWork: string;
419
+ /** Whether user wants to receive updates */
420
+ receiveUpdates: boolean;
421
+ /** Notification preference: community events */
422
+ notificationCommunityEvent: boolean;
423
+ /** Notification preference: tower events */
424
+ notificationTowerEvent: boolean;
425
+ /** Notification preference: upcoming events */
426
+ notificationUpcomingEvent: boolean;
427
+ /** Notification preference: tweet picked */
428
+ notificationTweetPicked: boolean;
429
+ /** Notification preference: event invites */
430
+ notifyEventInvites: boolean;
431
+ /** Whether user opted in for SMS */
432
+ optInSms: boolean;
433
+ /** How user heard about the platform */
434
+ howDidYouHearAboutUs: string;
435
+ /** User's bragging statement */
436
+ braggingStatement: string;
437
+ /** User's contribution statement */
438
+ contributionStatement: string;
439
+ /** Whether user has a usable password */
440
+ hasUsablePassword: string;
441
+ }
442
+ /**
443
+ * User access class for interacting with user information
444
+ *
445
+ * This class provides methods to:
446
+ * - Get current user details
447
+ * - Get detailed user profiles
448
+ *
449
+ * All methods require appropriate permissions and authentication.
450
+ */
451
+ declare class UserAccess {
452
+ private sdk;
453
+ constructor(sdk: FrontierSDK);
454
+ /**
455
+ * Get current user details
456
+ *
457
+ * Returns basic information about the currently authenticated user,
458
+ * including their ID, email, and name.
459
+ *
460
+ * @returns User object with basic information
461
+ * @throws {Error} If user is not authenticated
462
+ *
463
+ * @example
464
+ * ```typescript
465
+ * const user = await sdk.getUser().getDetails();
466
+ * console.log('User email:', user.email);
467
+ * console.log('User name:', `${user.firstName} ${user.lastName}`);
468
+ * ```
469
+ */
470
+ getDetails(): Promise<User>;
471
+ /**
472
+ * Get user profile by ID
473
+ *
474
+ * Returns detailed profile information for a specific user,
475
+ * including social media handles, preferences, and community information.
476
+ *
477
+ * @param id - The profile ID to fetch
478
+ * @returns UserProfile object with detailed information
479
+ * @throws {Error} If profile is not found or access is denied
480
+ *
481
+ * @example
482
+ * ```typescript
483
+ * const profile = await sdk.getUser().getProfile(123);
484
+ * console.log('Nickname:', profile.nickname);
485
+ * console.log('GitHub:', profile.githubHandle);
486
+ * console.log('Community:', profile.communityName);
487
+ * ```
488
+ */
489
+ getProfile(id: number): Promise<UserProfile>;
490
+ }
491
+
492
+ declare class FrontierSDK {
493
+ private requestId;
494
+ private pendingRequests;
495
+ private wallet;
496
+ private storage;
497
+ private chain;
498
+ private user;
499
+ constructor();
500
+ private handleMessage;
501
+ /**
502
+ * Internal request method used by access classes
503
+ * @internal
504
+ */
505
+ request(type: string, payload?: any): Promise<any>;
506
+ private notifyReady;
507
+ /**
508
+ * Get wallet access instance
509
+ */
510
+ getWallet(): WalletAccess;
511
+ /**
512
+ * Get storage access instance
513
+ */
514
+ getStorage(): StorageAccess;
515
+ /**
516
+ * Get chain access instance
517
+ */
518
+ getChain(): ChainAccess;
519
+ /**
520
+ * Get user access instance
521
+ */
522
+ getUser(): UserAccess;
523
+ /**
524
+ * Cleanup: Remove event listeners
525
+ * Call this when your app is being destroyed
526
+ */
527
+ destroy(): void;
528
+ }
529
+
530
+ interface SDKRequest {
531
+ type: string;
532
+ requestId: string;
533
+ payload?: any;
534
+ }
535
+ interface SDKResponse {
536
+ type: 'response' | 'error';
537
+ requestId: string;
538
+ result?: any;
539
+ error?: string;
540
+ }
541
+
542
+ export { ChainAccess, type ChainConfig, type ExecuteCall, FrontierSDK, type GasOverrides, type SDKRequest, type SDKResponse, type SmartAccount, StorageAccess, type User, UserAccess, type UserOperationReceipt, type UserProfile, WalletAccess };