frontier-os-app-builder 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +25 -0
  3. package/agents/fos-executor.md +22 -65
  4. package/agents/fos-plan-checker.md +13 -12
  5. package/agents/fos-planner.md +20 -67
  6. package/agents/fos-researcher.md +14 -10
  7. package/agents/fos-verifier.md +11 -5
  8. package/bin/fos-tools.cjs +48 -11
  9. package/bin/install.js +8 -5
  10. package/commands/fos/add-feature.md +1 -2
  11. package/commands/fos/discuss.md +0 -1
  12. package/commands/fos/new-app.md +1 -3
  13. package/commands/fos/new-milestone.md +1 -1
  14. package/commands/fos/plan.md +0 -2
  15. package/package.json +7 -1
  16. package/references/app-patterns.md +46 -28
  17. package/references/deployment.md +40 -74
  18. package/references/module-index.md +32 -0
  19. package/references/sdk/chain.md +92 -0
  20. package/references/sdk/communities.md +159 -0
  21. package/references/sdk/events.md +212 -0
  22. package/references/sdk/init.md +126 -0
  23. package/references/sdk/navigation.md +49 -0
  24. package/references/sdk/offices.md +76 -0
  25. package/references/sdk/partnerships.md +111 -0
  26. package/references/sdk/storage.md +44 -0
  27. package/references/sdk/thirdparty.md +240 -0
  28. package/references/sdk/token-amount.md +99 -0
  29. package/references/sdk/types.md +27 -0
  30. package/references/sdk/ui-utils.md +39 -0
  31. package/references/sdk/user.md +208 -0
  32. package/references/sdk/wallet.md +334 -0
  33. package/references/verification-rules.md +18 -18
  34. package/templates/app/frontier-services.tsx +75 -18
  35. package/templates/app/layout.tsx +19 -9
  36. package/templates/app/package.json +2 -1
  37. package/templates/app/public/favicon.svg +3 -0
  38. package/templates/app/sdk-context.tsx +7 -9
  39. package/templates/app/sdk-services.tsx +92 -117
  40. package/templates/app/vercel.json +8 -47
  41. package/templates/state/plan.md +32 -14
  42. package/templates/state/roadmap.md +2 -2
  43. package/templates/state/summary.md +26 -29
  44. package/workflows/add-feature.md +6 -1
  45. package/workflows/discuss.md +9 -3
  46. package/workflows/execute-plan.md +3 -3
  47. package/workflows/execute.md +17 -6
  48. package/workflows/new-app.md +54 -18
  49. package/workflows/new-milestone.md +9 -2
  50. package/workflows/plan.md +14 -5
  51. package/workflows/ship.md +26 -10
  52. package/workflows/status.md +0 -1
  53. package/references/module-inference.md +0 -348
  54. package/references/sdk-surface.md +0 -1600
  55. package/templates/app/main-simple-standalone.tsx +0 -19
  56. package/templates/app/main-simple.tsx +0 -19
  57. package/templates/state/manifest.json +0 -12
@@ -1,1600 +0,0 @@
1
- # Frontier SDK Surface Reference (v0.21.0)
2
-
3
- Complete API reference for `@frontiertower/frontier-sdk`. Every method, type, and permission extracted from source.
4
-
5
- Package: `@frontiertower/frontier-sdk`
6
- Import paths:
7
- - `@frontiertower/frontier-sdk` -- main SDK class and access modules
8
- - `@frontiertower/frontier-sdk/ui-utils` -- detection and standalone helpers
9
-
10
- ---
11
-
12
- ## 1. SDK Initialization
13
-
14
- ### Class: `FrontierSDK`
15
-
16
- ```typescript
17
- import { FrontierSDK } from '@frontiertower/frontier-sdk';
18
- ```
19
-
20
- #### Constructor
21
-
22
- ```typescript
23
- const sdk = new FrontierSDK();
24
- ```
25
-
26
- On construction the SDK:
27
- 1. Instantiates all ten access modules (wallet, storage, chain, user, partnerships, thirdParty, communities, events, offices, navigation).
28
- 2. Registers a `window.addEventListener('message', ...)` listener that routes `SDKResponse` messages from `window.parent`.
29
- 3. Sends an `{ type: 'app:ready', payload: null }` postMessage to `window.parent` to notify the host that the app iframe is ready.
30
-
31
- #### `destroy(): void`
32
-
33
- Call when the app is being torn down. Removes the message event listener, calls `this.navigation.destroy()` to clean up deep-link listeners, and clears all pending request promises.
34
-
35
- #### Internal: `request(type: string, payload?: any): Promise<any>`
36
-
37
- Used by all access classes. Sends an `SDKRequest` via `window.parent.postMessage` and returns a promise that resolves/rejects when the host responds. Requests time out after **30 000 ms**.
38
-
39
- ### PostMessage Protocol Types
40
-
41
- ```typescript
42
- interface SDKRequest {
43
- type: string; // e.g. 'wallet:getBalance'
44
- requestId: string; // `${Date.now()}-${incrementingId}`
45
- payload?: any;
46
- }
47
-
48
- interface SDKResponse {
49
- type: 'response' | 'error';
50
- requestId: string;
51
- result?: any;
52
- error?: string;
53
- }
54
- ```
55
-
56
- ### Module Getters
57
-
58
- | Getter | Returns | Module |
59
- |---|---|---|
60
- | `sdk.getWallet()` | `WalletAccess` | Wallet |
61
- | `sdk.getStorage()` | `StorageAccess` | Storage |
62
- | `sdk.getChain()` | `ChainAccess` | Chain |
63
- | `sdk.getUser()` | `UserAccess` | User |
64
- | `sdk.getPartnerships()` | `PartnershipsAccess` | Partnerships |
65
- | `sdk.getThirdParty()` | `ThirdPartyAccess` | Third-Party |
66
- | `sdk.getCommunities()` | `CommunitiesAccess` | Communities |
67
- | `sdk.getEvents()` | `EventsAccess` | Events |
68
- | `sdk.getOffices()` | `OfficesAccess` | Offices |
69
- | `sdk.getNavigation()` | `NavigationAccess` | Navigation |
70
-
71
- ---
72
-
73
- ## 2. Wallet Module
74
-
75
- Access via `sdk.getWallet()`. All methods use the current chain from the chain manager. Write operations require biometric authentication.
76
-
77
- ### Methods
78
-
79
- ```typescript
80
- getBalance(): Promise<WalletBalance>
81
- ```
82
- Returns raw balance breakdown (bigint values). Permission: `wallet:getBalance`
83
-
84
- ```typescript
85
- getBalanceFormatted(): Promise<WalletBalanceFormatted>
86
- ```
87
- Returns display-formatted balance strings (e.g. `'$10.50'`). Permission: `wallet:getBalanceFormatted`
88
-
89
- ```typescript
90
- getAddress(): Promise<string>
91
- ```
92
- Returns the smart account contract address for the current chain. Permission: `wallet:getAddress`
93
-
94
- ```typescript
95
- getSmartAccount(): Promise<SmartAccount>
96
- ```
97
- Returns detailed smart account info including deployment status. Permission: `wallet:getSmartAccount`
98
-
99
- ```typescript
100
- transferERC20(
101
- tokenAddress: string,
102
- to: string,
103
- amount: bigint,
104
- overrides?: GasOverrides
105
- ): Promise<UserOperationReceipt>
106
- ```
107
- Transfer ERC20 tokens. Amount in token's smallest unit. Permission: `wallet:transferERC20`
108
-
109
- ```typescript
110
- approveERC20(
111
- tokenAddress: string,
112
- spender: string,
113
- amount: bigint,
114
- overrides?: GasOverrides
115
- ): Promise<UserOperationReceipt>
116
- ```
117
- Approve a spender for ERC20 tokens. Permission: `wallet:approveERC20`
118
-
119
- ```typescript
120
- transferNative(
121
- to: string,
122
- amount: bigint,
123
- overrides?: GasOverrides
124
- ): Promise<UserOperationReceipt>
125
- ```
126
- Transfer native currency (ETH). Amount in wei. Permission: `wallet:transferNative`
127
-
128
- ```typescript
129
- executeCall(
130
- call: ExecuteCall,
131
- overrides?: GasOverrides
132
- ): Promise<UserOperationReceipt>
133
- ```
134
- Execute an arbitrary contract call. Permission: `wallet:executeCall`
135
-
136
- ```typescript
137
- executeBatchCall(
138
- calls: ExecuteCall[],
139
- overrides?: GasOverrides
140
- ): Promise<UserOperationReceipt>
141
- ```
142
- Execute multiple calls atomically in a single transaction. Permission: `wallet:executeBatchCall`
143
-
144
- ```typescript
145
- transferFrontierDollar(
146
- to: string,
147
- amount: string,
148
- overrides?: GasOverrides
149
- ): Promise<UserOperationReceipt>
150
- ```
151
- Transfer FND (Frontier Network Dollar). Amount is human-readable string (e.g. `'10.5'`). Permission: `wallet:transferFrontierDollar`
152
-
153
- ```typescript
154
- transferInternalFrontierDollar(
155
- to: string,
156
- amount: string,
157
- overrides?: GasOverrides
158
- ): Promise<UserOperationReceipt>
159
- ```
160
- Transfer iFND (Internal Frontier Network Dollar). Amount is human-readable string. Permission: `wallet:transferInternalFrontierDollar`
161
-
162
- ```typescript
163
- transferOverallFrontierDollar(
164
- to: string,
165
- amount: string,
166
- overrides?: GasOverrides
167
- ): Promise<UserOperationReceipt>
168
- ```
169
- Transfer using iFND first, falling back to FND for the remainder. Permission: `wallet:transferOverallFrontierDollar`
170
-
171
- ```typescript
172
- getSupportedTokens(): Promise<string[]>
173
- ```
174
- Returns token symbols supported for swaps on the current chain (e.g. `['FND', 'USDC', 'WETH']`). Permission: `wallet:getSupportedTokens`
175
-
176
- ```typescript
177
- swap(
178
- sourceToken: string,
179
- targetToken: string,
180
- sourceNetwork: string,
181
- targetNetwork: string,
182
- amount: string
183
- ): Promise<SwapResult>
184
- ```
185
- Execute a token swap (same-chain or cross-chain). Amount is human-readable. Permission: `wallet:swap`
186
-
187
- ```typescript
188
- quoteSwap(
189
- sourceToken: string,
190
- targetToken: string,
191
- sourceNetwork: string,
192
- targetNetwork: string,
193
- amount: string
194
- ): Promise<SwapQuote>
195
- ```
196
- Get a swap quote without executing. Permission: `wallet:quoteSwap`
197
-
198
- ```typescript
199
- getUsdDepositInstructions(): Promise<OnRampResponse<UsdDepositInstructions>>
200
- ```
201
- Get US bank details for fiat-to-crypto on-ramp. Requires approved KYC. Permission: `wallet:getUsdDepositInstructions`
202
-
203
- ```typescript
204
- getEurDepositInstructions(): Promise<OnRampResponse<EurDepositInstructions>>
205
- ```
206
- Get SEPA bank details for EUR fiat-to-crypto on-ramp. Requires approved KYC. Permission: `wallet:getEurDepositInstructions`
207
-
208
- ```typescript
209
- getLinkedBanks(): Promise<LinkedBanksResponse>
210
- ```
211
- Get all linked bank accounts for off-ramp withdrawals. Requires approved KYC. Permission: `wallet:getLinkedBanks`
212
-
213
- ```typescript
214
- linkUsBankAccount(
215
- accountOwnerName: string,
216
- bankName: string,
217
- routingNumber: string,
218
- accountNumber: string,
219
- checkingOrSavings: 'checking' | 'savings',
220
- address: BillingAddress
221
- ): Promise<LinkBankResponse>
222
- ```
223
- Link a US bank account for USD withdrawals via ACH. Requires approved KYC. Permission: `wallet:linkUsBankAccount`
224
-
225
- ```typescript
226
- linkEuroAccount(
227
- accountOwnerName: string,
228
- accountOwnerType: AccountOwnerType,
229
- firstName: string,
230
- lastName: string,
231
- ibanAccountNumber: string,
232
- bic?: string
233
- ): Promise<LinkBankResponse>
234
- ```
235
- Link a EUR/IBAN bank account for SEPA withdrawals. Requires approved KYC. Permission: `wallet:linkEuroAccount`
236
-
237
- ```typescript
238
- deleteLinkedBank(bankId: string): Promise<void>
239
- ```
240
- Delete a linked bank account. Permission: `wallet:deleteLinkedBank`
241
-
242
- ```typescript
243
- getDeprecatedSmartAccounts(): Promise<DeprecatedSmartAccount[]>
244
- ```
245
- Get deprecated smart accounts that still have active gas sponsorship. Permission: `wallet:getDeprecatedSmartAccounts`
246
-
247
- ### Wallet Types
248
-
249
- ```typescript
250
- interface SmartAccount {
251
- id: number;
252
- ownerAddress: string;
253
- contractAddress: string | null;
254
- network: string;
255
- status: string;
256
- deploymentTransactionHash: string;
257
- createdAt: string;
258
- }
259
-
260
- interface WalletBalance {
261
- total: bigint;
262
- fnd: bigint;
263
- internalFnd: bigint;
264
- }
265
-
266
- interface WalletBalanceFormatted {
267
- total: string; // e.g. '$10.50'
268
- fnd: string;
269
- internalFnd: string;
270
- }
271
-
272
- interface UserOperationReceipt {
273
- userOpHash: string;
274
- transactionHash: string;
275
- blockNumber: bigint;
276
- success: boolean;
277
- }
278
-
279
- interface GasOverrides {
280
- maxFeePerGas?: bigint;
281
- maxPriorityFeePerGas?: bigint;
282
- gasLimit?: bigint;
283
- }
284
-
285
- interface ExecuteCall {
286
- target: string;
287
- value?: bigint;
288
- data: string;
289
- }
290
-
291
- interface SwapParams {
292
- sourceToken: string;
293
- targetToken: string;
294
- sourceNetwork: string;
295
- targetNetwork: string;
296
- amount: string;
297
- }
298
-
299
- enum SwapResultStatus {
300
- COMPLETED = 'COMPLETED',
301
- SUBMITTED = 'SUBMITTED',
302
- }
303
-
304
- interface SwapResult {
305
- sourceChain: object;
306
- targetChain: object;
307
- sourceToken: object;
308
- targetToken: object;
309
- status: SwapResultStatus;
310
- }
311
-
312
- interface SwapQuote {
313
- sourceChain: object;
314
- targetChain: object;
315
- sourceToken: object;
316
- targetToken: object;
317
- expectedAmountOut: string;
318
- minAmountOut: string;
319
- }
320
-
321
- interface UsdDepositInstructions {
322
- currency: 'usd';
323
- bankName: string;
324
- bankAddress: string;
325
- bankRoutingNumber: string;
326
- bankAccountNumber: string;
327
- bankBeneficiaryName: string;
328
- paymentRail: string;
329
- }
330
-
331
- interface EurDepositInstructions {
332
- currency: 'eur';
333
- iban: string;
334
- bic: string;
335
- accountHolderName: string;
336
- }
337
-
338
- interface OnRampResponse<T = UsdDepositInstructions | EurDepositInstructions> {
339
- currency: 'usd' | 'eur';
340
- depositInstructions: T;
341
- destinationAddress: string;
342
- destinationNetwork: string;
343
- }
344
-
345
- interface LinkedBank {
346
- id: string;
347
- bankName: string;
348
- last4: string;
349
- withdrawalAddress: string;
350
- network: string;
351
- }
352
-
353
- interface LinkedBanksResponse {
354
- banks: LinkedBank[];
355
- }
356
-
357
- interface LinkBankResponse {
358
- externalAccountId: string;
359
- bankName: string;
360
- withdrawalAddress: string;
361
- network: string;
362
- }
363
-
364
- interface BillingAddress {
365
- streetLine1: string;
366
- streetLine2?: string;
367
- city: string;
368
- state: string;
369
- postalCode: string;
370
- country: string;
371
- }
372
-
373
- type AccountOwnerType = 'individual' | 'business';
374
-
375
- interface DeprecatedSmartAccount {
376
- id: number;
377
- ownerAddress: string;
378
- contractAddress: string;
379
- network: string;
380
- deprecatedAt: string;
381
- version: number;
382
- }
383
- ```
384
-
385
- ---
386
-
387
- ## 3. Storage Module
388
-
389
- Access via `sdk.getStorage()`. Provides persistent key-value storage scoped to the app.
390
-
391
- ### Methods
392
-
393
- ```typescript
394
- get<T = any>(key: string): Promise<T>
395
- ```
396
- Read a value by key. Permission: `storage:get`
397
-
398
- ```typescript
399
- set(key: string, value: any): Promise<void>
400
- ```
401
- Write a value by key. Permission: `storage:set`
402
-
403
- ```typescript
404
- remove(key: string): Promise<void>
405
- ```
406
- Delete a key. Permission: `storage:remove`
407
-
408
- ```typescript
409
- clear(): Promise<void>
410
- ```
411
- Delete all keys. Permission: `storage:clear`
412
-
413
- ### Storage Types
414
-
415
- No additional types -- uses generic `T` for get, `any` for set.
416
-
417
- ---
418
-
419
- ## 4. Chain Module
420
-
421
- Access via `sdk.getChain()`. Query and switch blockchain networks.
422
-
423
- ### Methods
424
-
425
- ```typescript
426
- getCurrentNetwork(): Promise<string>
427
- ```
428
- Returns the current network identifier (e.g. `'base'`, `'base-sepolia'`). Permission: `chain:getCurrentNetwork`
429
-
430
- ```typescript
431
- getAvailableNetworks(): Promise<string[]>
432
- ```
433
- Returns all network identifiers the app can switch to. Permission: `chain:getAvailableNetworks`
434
-
435
- ```typescript
436
- switchNetwork(network: string): Promise<void>
437
- ```
438
- Switch active blockchain network. Affects all subsequent wallet operations. Permission: `chain:switchNetwork`
439
-
440
- ```typescript
441
- getCurrentChainConfig(): Promise<ChainConfig>
442
- ```
443
- Returns full chain configuration for the current network. Permission: `chain:getCurrentChainConfig`
444
-
445
- ```typescript
446
- getContractAddresses(): Promise<{
447
- fnd: string;
448
- iFnd: string | null;
449
- paymentRouter: string;
450
- subscriptionManager: string;
451
- }>
452
- ```
453
- Returns addresses for FND, iFND (may be null), PaymentRouter, and SubscriptionManager contracts on the current chain. Permission: `chain:getContractAddresses`
454
-
455
- ### Chain Types
456
-
457
- ```typescript
458
- enum Underlying {
459
- USD = "USD",
460
- }
461
-
462
- interface Token {
463
- name: string;
464
- symbol: string;
465
- decimals: number;
466
- address: string;
467
- }
468
-
469
- interface StableCoin extends Token {
470
- underlying: Underlying;
471
- }
472
-
473
- interface ChainConfig {
474
- id: number;
475
- name: string;
476
- network: string;
477
- bridgeSwapRouterFactoryAddress: string;
478
- uniswapV3FactoryAddress: string;
479
- nativeCurrency: {
480
- name: string;
481
- symbol: string;
482
- decimals: number;
483
- };
484
- blockExplorer: {
485
- name: string;
486
- url: string;
487
- };
488
- stableCoins: StableCoin[];
489
- supportedTokens: Token[];
490
- testnet: boolean;
491
- }
492
- ```
493
-
494
- ---
495
-
496
- ## 5. User Module
497
-
498
- Access via `sdk.getUser()`. Query user info, profiles, referrals, KYC, and access controls.
499
-
500
- ### Methods
501
-
502
- ```typescript
503
- getDetails(): Promise<User>
504
- ```
505
- Returns basic user info (id, email, name, active/superuser status). Permission: `user:getDetails`
506
-
507
- ```typescript
508
- getProfile(): Promise<UserProfile>
509
- ```
510
- Returns detailed profile (social handles, preferences, community, notification settings). Permission: `user:getProfile`
511
-
512
- ```typescript
513
- getReferralOverview(): Promise<ReferralOverview>
514
- ```
515
- Returns referral statistics (count, ranking, referral link/code). Permission: `user:getReferralOverview`
516
-
517
- ```typescript
518
- getReferralDetails(page?: number): Promise<PaginatedResponse<ReferralDetails>>
519
- ```
520
- Returns paginated referral details. Permission: `user:getReferralDetails`
521
-
522
- ```typescript
523
- addUserContact(data: UserContactPayload): Promise<void>
524
- ```
525
- Submit contact information for the current user. Permission: `user:addUserContact`
526
-
527
- ```typescript
528
- getOrCreateKyc(redirectUri?: string): Promise<KycStatusResponse>
529
- ```
530
- Get or initiate KYC verification. Returns status and a KYC link if verification has been started. Permission: `user:getOrCreateKyc`
531
-
532
- ```typescript
533
- createSignupRequest(payload: CreateSignupRequestPayload): Promise<CreateSignupRequestResponse>
534
- ```
535
- Submit a new membership signup request with crypto payment. Permission: `user:createSignupRequest`
536
-
537
- ```typescript
538
- getVerifiedAccessControls(): Promise<AccessControlsPayload>
539
- ```
540
- Returns cryptographically verified access controls signed by the Frontier API server. The SDK verifies an ECDSA secp256k1 signature against hardcoded per-environment public keys inside the iframe. **Use this for all access-gating decisions** -- unsigned data from other SDK methods should not be trusted for feature gating. Throws if signature verification fails. Permission: `user:getVerifiedAccessControls`
541
-
542
- ### User Types
543
-
544
- ```typescript
545
- interface User {
546
- id: number;
547
- email: string;
548
- firstName: string;
549
- lastName: string;
550
- isActive: boolean;
551
- dateJoined: string;
552
- isSuperuser: boolean;
553
- }
554
-
555
- interface UserProfile {
556
- id: number;
557
- user: number;
558
- firstName: string;
559
- lastName: string;
560
- nickname: string;
561
- profilePicture: string;
562
- phoneNumber: string;
563
- community: string;
564
- communityName: string;
565
- organization: string;
566
- organizationRole: string;
567
- socialSite: string;
568
- socialHandle: string;
569
- githubHandle: string;
570
- currentWork: string;
571
- notableWork: string;
572
- receiveUpdates: boolean;
573
- notificationCommunityEvent: boolean;
574
- notificationTowerEvent: boolean;
575
- notificationUpcomingEvent: boolean;
576
- notificationTweetPicked: boolean;
577
- notifyEventInvites: boolean;
578
- optInSms: boolean;
579
- howDidYouHearAboutUs: string;
580
- braggingStatement: string;
581
- contributionStatement: string;
582
- hasUsablePassword: string;
583
- }
584
-
585
- interface PaginatedResponse<T> {
586
- count: number;
587
- results: T[];
588
- }
589
-
590
- interface ReferralOverview {
591
- referralCount: number;
592
- ranking: number;
593
- referralLink: string;
594
- referralCode: string;
595
- referredBy: string | null;
596
- }
597
-
598
- interface ReferralDetails {
599
- name: string;
600
- email: string;
601
- referralDate: string;
602
- reward: string;
603
- status: string;
604
- }
605
-
606
- interface UserContact {
607
- email: string;
608
- phone: string;
609
- name: string;
610
- }
611
-
612
- interface UserContactPayload {
613
- contacts: UserContact[];
614
- }
615
-
616
- type KycStatus = 'not_started' | 'pending' | 'in_review' | 'approved' | 'rejected';
617
- type TosStatus = 'pending' | 'approved';
618
-
619
- interface KycStatusResponse {
620
- status: KycStatus;
621
- isApproved: boolean;
622
- rejectionReason: string | null;
623
- kycLinkId: string | null;
624
- kycLink: string | null;
625
- tosStatus: TosStatus | null;
626
- tosLink: string | null;
627
- }
628
-
629
- interface CreateSignupRequestPayload {
630
- subscriptionPlan: string;
631
- subscriptionInterval: string;
632
- firstName: string;
633
- lastName: string;
634
- email: string;
635
- phoneNumber: string;
636
- socialSite: string;
637
- socialHandle: string;
638
- currentWork: string;
639
- howDidYouHearAboutUs: string;
640
- braggingStatement: string;
641
- contributionStatement: string;
642
- billingFirstName: string;
643
- billingLastName: string;
644
- billingEmail: string;
645
- billingPhoneNumber: string;
646
- paymentProvider: 'crypto';
647
- smartAccount: number;
648
- community: string;
649
- githubHandle?: string;
650
- notableWork?: string;
651
- referralCode?: string;
652
- receiveUpdates?: boolean;
653
- optInSms?: boolean;
654
- organization?: string;
655
- organizationRole?: string;
656
- }
657
-
658
- interface CreateSignupRequestResponse {
659
- subscriptionUuid: string;
660
- paymentProvider: string;
661
- }
662
- ```
663
-
664
- ### Access Controls Types
665
-
666
- ```typescript
667
- interface AccessControlsPayload {
668
- smartAccountAddress: string | null;
669
- email: string;
670
- isSuperuser: boolean;
671
- subscriptionStatus: string | null; // 'active' | 'canceled' | 'awaiting_approval' | null
672
- subscriptionPlan: string | null;
673
- subscriptionInterval: string | null;
674
- subscriptionType: string | null; // 'crypto' | 'stripe' | 'grant' | 'office' | 'internship' | null
675
- addOns: string[];
676
- communities: string[];
677
- managedCommunities: string[];
678
- timestamp: string;
679
- kid: string;
680
- }
681
-
682
- interface SignedAccessControls {
683
- accessControls: string; // Base64-encoded canonical JSON payload
684
- stage: string; // API stage (e.g. 'production', 'sandbox')
685
- signature: string; // Hex-encoded ECDSA signature (r||s, 128 hex chars)
686
- }
687
- ```
688
-
689
- ---
690
-
691
- ## 6. Partnerships Module
692
-
693
- Access via `sdk.getPartnerships()`. Manage sponsors and sponsor passes.
694
-
695
- ### Methods
696
-
697
- ```typescript
698
- createSponsorPass(payload: CreateSponsorPassRequest): Promise<SponsorPass>
699
- ```
700
- Create a new SponsorPass. Permission: `partnerships:createSponsorPass`
701
-
702
- ```typescript
703
- listActiveSponsorPasses(payload?: ListSponsorPassesParams): Promise<PaginatedResponse<SponsorPass>>
704
- ```
705
- List active (non-revoked) SponsorPasses, paginated. Permission: `partnerships:listActiveSponsorPasses`
706
-
707
- ```typescript
708
- listAllSponsorPasses(payload?: ListAllSponsorPassesParams): Promise<PaginatedResponse<SponsorPass>>
709
- ```
710
- List all SponsorPasses, optionally including revoked. Permission: `partnerships:listAllSponsorPasses`
711
-
712
- ```typescript
713
- listSponsors(payload?: ListSponsorsParams): Promise<PaginatedResponse<Sponsor>>
714
- ```
715
- List sponsors the user manages, paginated. Permission: `partnerships:listSponsors`
716
-
717
- ```typescript
718
- getSponsor(payload: { id: number }): Promise<Sponsor>
719
- ```
720
- Retrieve a Sponsor by ID. Permission: `partnerships:getSponsor`
721
-
722
- ```typescript
723
- getSponsorPass(payload: { id: number }): Promise<SponsorPass>
724
- ```
725
- Retrieve a SponsorPass by ID. Permission: `partnerships:getSponsorPass`
726
-
727
- ```typescript
728
- revokeSponsorPass(payload: { id: number }): Promise<void>
729
- ```
730
- Revoke (not delete) a SponsorPass. Permission: `partnerships:revokeSponsorPass`
731
-
732
- ### Partnerships Types
733
-
734
- ```typescript
735
- type SponsorPassStatus = 'active' | 'revoked';
736
-
737
- interface SponsorPass {
738
- id: number;
739
- sponsor: number;
740
- sponsorName: string;
741
- firstName: string;
742
- lastName: string;
743
- email: string;
744
- status: SponsorPassStatus;
745
- expiresAt: string | null;
746
- createdAt: string;
747
- updatedAt: string;
748
- revokedAt: string | null;
749
- }
750
-
751
- interface CreateSponsorPassRequest {
752
- sponsor: number;
753
- firstName: string;
754
- lastName: string;
755
- email: string;
756
- expiresAt?: string;
757
- }
758
-
759
- interface ListSponsorPassesParams {
760
- limit?: number;
761
- offset?: number;
762
- }
763
-
764
- interface ListAllSponsorPassesParams extends ListSponsorPassesParams {
765
- includeRevoked?: boolean;
766
- }
767
-
768
- interface Sponsor {
769
- id: number;
770
- name: string;
771
- dailyRate: string;
772
- notes: string;
773
- createdAt: string;
774
- updatedAt: string;
775
- }
776
-
777
- interface ListSponsorsParams {
778
- limit?: number;
779
- offset?: number;
780
- }
781
- ```
782
-
783
- ---
784
-
785
- ## 7. Third-Party Module
786
-
787
- Access via `sdk.getThirdParty()`. Manage developer accounts, registered apps, and webhooks.
788
-
789
- ### Developer Methods
790
-
791
- ```typescript
792
- listDevelopers(payload?: ListParams): Promise<PaginatedResponse<Developer>>
793
- ```
794
- List developer accounts, paginated. Permission: `thirdParty:listDevelopers`
795
-
796
- ```typescript
797
- getDeveloper(payload: { id: number }): Promise<Developer>
798
- ```
799
- Get developer details by ID. Permission: `thirdParty:getDeveloper`
800
-
801
- ```typescript
802
- updateDeveloper(payload: { id: number; data: UpdateDeveloperRequest }): Promise<Developer>
803
- ```
804
- Update developer information. Permission: `thirdParty:updateDeveloper`
805
-
806
- ```typescript
807
- rotateDeveloperApiKey(payload: { id: number }): Promise<RotateKeyResponse>
808
- ```
809
- Rotate developer API key. New key is only shown once in the response. Permission: `thirdParty:rotateDeveloperApiKey`
810
-
811
- ### App Methods
812
-
813
- ```typescript
814
- listApps(payload?: ListAppsParams): Promise<PaginatedResponse<App>>
815
- ```
816
- List registered apps, paginated. Optional `developerId` filter. Permission: `thirdParty:listApps`
817
-
818
- ```typescript
819
- createApp(payload: CreateAppRequest): Promise<App>
820
- ```
821
- Register a new app. Name, description, and icon are auto-fetched from URL metadata. Permission: `thirdParty:createApp`
822
-
823
- ```typescript
824
- getApp(payload: { id: number }): Promise<App>
825
- ```
826
- Get app details by ID. Permission: `thirdParty:getApp`
827
-
828
- ```typescript
829
- updateApp(payload: { id: number; data: UpdateAppRequest }): Promise<App>
830
- ```
831
- Update an app. Permission: `thirdParty:updateApp`
832
-
833
- ```typescript
834
- deleteApp(payload: { id: number }): Promise<void>
835
- ```
836
- Request app deactivation. Permission: `thirdParty:deleteApp`
837
-
838
- ### Webhook Methods
839
-
840
- ```typescript
841
- listWebhooks(payload?: ListWebhooksParams): Promise<PaginatedResponse<Webhook>>
842
- ```
843
- List webhooks, paginated. Max 3 webhooks per developer. Optional `developerId` filter. Permission: `thirdParty:listWebhooks`
844
-
845
- ```typescript
846
- createWebhook(payload: CreateWebhookRequest): Promise<Webhook>
847
- ```
848
- Create a new webhook. Requires admin approval before going live. Permission: `thirdParty:createWebhook`
849
-
850
- ```typescript
851
- getWebhook(payload: { id: number }): Promise<Webhook>
852
- ```
853
- Get webhook details by ID. Permission: `thirdParty:getWebhook`
854
-
855
- ```typescript
856
- updateWebhook(payload: { id: number; data: UpdateWebhookRequest }): Promise<Webhook>
857
- ```
858
- Update a webhook. Config changes require admin re-approval. Permission: `thirdParty:updateWebhook`
859
-
860
- ```typescript
861
- deleteWebhook(payload: { id: number }): Promise<void>
862
- ```
863
- Delete a webhook. Permission: `thirdParty:deleteWebhook`
864
-
865
- ```typescript
866
- rotateWebhookSigningKey(payload: { id: number }): Promise<RotateWebhookKeyResponse>
867
- ```
868
- Rotate webhook signing key. New public key returned in response. Permission: `thirdParty:rotateWebhookSigningKey`
869
-
870
- ### Third-Party Types
871
-
872
- ```typescript
873
- interface Developer {
874
- id: number;
875
- name: string;
876
- description: string;
877
- email: string;
878
- apiKey: string;
879
- createdAt: string;
880
- updatedAt: string;
881
- }
882
-
883
- interface UpdateDeveloperRequest {
884
- name?: string;
885
- description?: string;
886
- email?: string;
887
- }
888
-
889
- interface RotateKeyResponse {
890
- message: string;
891
- developer: Developer;
892
- }
893
-
894
- type AppStatus =
895
- | 'in_review'
896
- | 'accepted'
897
- | 'released'
898
- | 'rejected'
899
- | 'request_deactivation'
900
- | 'deactivated';
901
-
902
- type AppPermission = string;
903
-
904
- interface App {
905
- id: number;
906
- developer: number;
907
- icon: string | null;
908
- name: string;
909
- readableId: string;
910
- description: string;
911
- url: string;
912
- cnameEntry: string;
913
- txtEntry: string | null;
914
- permissions: AppPermission[];
915
- permissionDisclaimer: string;
916
- status: AppStatus;
917
- reviewNotes: string;
918
- createdAt: string;
919
- updatedAt: string;
920
- }
921
-
922
- interface CreateAppRequest {
923
- developer: number;
924
- url: string;
925
- cnameEntry: string;
926
- txtEntry?: string;
927
- permissions: AppPermission[];
928
- permissionDisclaimer: string;
929
- }
930
-
931
- interface UpdateAppRequest {
932
- developer?: number;
933
- url?: string;
934
- cnameEntry?: string;
935
- txtEntry?: string;
936
- permissions?: AppPermission[];
937
- permissionDisclaimer?: string;
938
- }
939
-
940
- type WebhookStatus = 'IN_REVIEW' | 'LIVE' | 'REJECTED';
941
- type WebhookEvent = string;
942
- type WebhookScope = Record<string, number[] | '*'>;
943
-
944
- interface WebhookConfig {
945
- events: WebhookEvent[];
946
- scope: WebhookScope;
947
- }
948
-
949
- interface Webhook {
950
- id: number;
951
- developer: number;
952
- name: string;
953
- description: string;
954
- targetUrl: string;
955
- config: WebhookConfig;
956
- signingPublicKey: string;
957
- status: WebhookStatus;
958
- reviewNotes: string;
959
- createdAt: string;
960
- updatedAt: string;
961
- }
962
-
963
- interface CreateWebhookRequest {
964
- developer: number;
965
- name: string;
966
- description: string;
967
- targetUrl: string;
968
- config: WebhookConfig;
969
- }
970
-
971
- interface UpdateWebhookRequest {
972
- developer?: number;
973
- name?: string;
974
- description?: string;
975
- targetUrl?: string;
976
- config?: WebhookConfig;
977
- }
978
-
979
- interface RotateWebhookKeyResponse {
980
- message: string;
981
- webhook: Webhook;
982
- }
983
-
984
- interface ListParams {
985
- limit?: number;
986
- offset?: number;
987
- }
988
-
989
- interface ListAppsParams extends ListParams {
990
- developerId?: number;
991
- }
992
-
993
- interface ListWebhooksParams extends ListParams {
994
- developerId?: number;
995
- }
996
- ```
997
-
998
- ---
999
-
1000
- ## 8. Communities Module
1001
-
1002
- Access via `sdk.getCommunities()`. Manage communities, internship passes, and member reassignment requests.
1003
-
1004
- Community listing is public. Internship passes require authentication, an active subscription, and community manager status. Reassign requests require authentication; creating requires managing the member's current community, accepting requires managing the target community. Superusers can access everything.
1005
-
1006
- ### Methods
1007
-
1008
- ```typescript
1009
- listCommunities(payload?: ListCommunitiesParams): Promise<PaginatedResponse<Community>>
1010
- ```
1011
- List all visible communities, paginated. Permission: `communities:listCommunities`
1012
-
1013
- ```typescript
1014
- getCommunity(payload: { idOrSlug: string | number }): Promise<Community>
1015
- ```
1016
- Get a community by numeric ID or slug string. Permission: `communities:getCommunity`
1017
-
1018
- ```typescript
1019
- createInternshipPass(payload: CreateInternshipPassRequest): Promise<InternshipPass>
1020
- ```
1021
- Create an internship pass. Auto-creates an inactive account if the user does not exist. Permission: `communities:createInternshipPass`
1022
-
1023
- ```typescript
1024
- listInternshipPasses(payload?: ListInternshipPassesParams): Promise<PaginatedResponse<InternshipPass>>
1025
- ```
1026
- List internship passes for managed communities. Active only by default; set `includeRevoked: true` to include revoked. Permission: `communities:listInternshipPasses`
1027
-
1028
- ```typescript
1029
- getInternshipPass(payload: { id: number }): Promise<InternshipPass>
1030
- ```
1031
- Get an internship pass by ID. Permission: `communities:getInternshipPass`
1032
-
1033
- ```typescript
1034
- revokeInternshipPass(payload: { id: number }): Promise<void>
1035
- ```
1036
- Revoke an internship pass. Cannot revoke an already-revoked pass. Permission: `communities:revokeInternshipPass`
1037
-
1038
- ```typescript
1039
- createReassignRequest(payload: CreateReassignRequestPayload): Promise<ReassignRequest>
1040
- ```
1041
- Request to move a member to a different community. Caller must manage the member's current community. Permission: `communities:createReassignRequest`
1042
-
1043
- ```typescript
1044
- listReassignRequests(payload?: ListReassignRequestsParams): Promise<PaginatedResponse<ReassignRequest>>
1045
- ```
1046
- List pending reassign requests visible to the caller. Permission: `communities:listReassignRequests`
1047
-
1048
- ```typescript
1049
- getReassignRequest(payload: { id: number }): Promise<ReassignRequest>
1050
- ```
1051
- Get a reassign request by ID. Permission: `communities:getReassignRequest`
1052
-
1053
- ```typescript
1054
- acceptReassignRequest(payload: { id: number }): Promise<ReassignRequest>
1055
- ```
1056
- Accept a reassign request. Moves the member to the target community. Only target community managers (or superusers) can accept. Permission: `communities:acceptReassignRequest`
1057
-
1058
- ```typescript
1059
- rejectReassignRequest(payload: { id: number }): Promise<void>
1060
- ```
1061
- Reject a reassign request. Only pending requests can be rejected. Permission: `communities:rejectReassignRequest`
1062
-
1063
- ### Communities Types
1064
-
1065
- ```typescript
1066
- interface Community {
1067
- id: number;
1068
- name: string;
1069
- description: string;
1070
- slug: string;
1071
- iconName: string;
1072
- splashVideo: string | null;
1073
- }
1074
-
1075
- interface ListCommunitiesParams {
1076
- limit?: number;
1077
- offset?: number;
1078
- }
1079
-
1080
- type InternshipPassStatus = 'active' | 'revoked';
1081
-
1082
- interface InternshipPass {
1083
- id: number;
1084
- email: string;
1085
- firstName: string;
1086
- lastName: string;
1087
- community: number;
1088
- communityName: string;
1089
- status: InternshipPassStatus;
1090
- createdAt: string;
1091
- revokedAt: string | null;
1092
- updatedAt: string;
1093
- }
1094
-
1095
- interface CreateInternshipPassRequest {
1096
- email: string;
1097
- firstName: string;
1098
- lastName: string;
1099
- community: number;
1100
- }
1101
-
1102
- interface ListInternshipPassesParams {
1103
- limit?: number;
1104
- offset?: number;
1105
- includeRevoked?: boolean;
1106
- }
1107
-
1108
- type ReassignRequestStatus = 'pending' | 'accepted' | 'rejected';
1109
-
1110
- interface ReassignRequest {
1111
- id: number;
1112
- requester: number;
1113
- requesterEmail: string;
1114
- member: number;
1115
- memberEmail: string;
1116
- targetCommunity: number;
1117
- targetCommunityName: string;
1118
- status: ReassignRequestStatus;
1119
- createdAt: string;
1120
- resolvedAt: string | null;
1121
- resolvedBy: number | null;
1122
- resolvedByEmail: string | null;
1123
- }
1124
-
1125
- interface CreateReassignRequestPayload {
1126
- memberEmail: string;
1127
- targetCommunity: number;
1128
- }
1129
-
1130
- interface ListReassignRequestsParams {
1131
- limit?: number;
1132
- offset?: number;
1133
- }
1134
- ```
1135
-
1136
- ---
1137
-
1138
- ## 9. Events Module
1139
-
1140
- Access via `sdk.getEvents()`. Manage events, locations (event spaces and rooms), and room bookings.
1141
-
1142
- ### Methods
1143
-
1144
- ```typescript
1145
- listEvents(payload?: ListEventsParams): Promise<PaginatedResponse<Event>>
1146
- ```
1147
- List active events with optional filters (search, type, location, date range). Permission: `events:listEvents`
1148
-
1149
- ```typescript
1150
- createEvent(payload: CreateEventRequest): Promise<Event>
1151
- ```
1152
- Create a new event. Permission: `events:createEvent`
1153
-
1154
- ```typescript
1155
- addEventHost(payload: { eventId: number; email: string }): Promise<Event>
1156
- ```
1157
- Add a co-host to an event. Only the primary host can add co-hosts, and only to upcoming events. Permission: `events:addEventHost`
1158
-
1159
- ```typescript
1160
- listLocations(payload?: ListLocationsParams): Promise<Location[]>
1161
- ```
1162
- List available locations. Returns an array (not paginated). Optional `locationType` filter. Permission: `events:listLocations`
1163
-
1164
- ```typescript
1165
- listRoomBookings(payload?: ListRoomBookingsParams): Promise<PaginatedResponse<RoomBooking>>
1166
- ```
1167
- List approved room bookings with optional filters. Permission: `events:listRoomBookings`
1168
-
1169
- ```typescript
1170
- createRoomBooking(payload: CreateRoomBookingRequest): Promise<RoomBooking>
1171
- ```
1172
- Create a room booking. Location must be of type `'room'`. Permission: `events:createRoomBooking`
1173
-
1174
- ### Events Types
1175
-
1176
- ```typescript
1177
- type EventType = 'public' | 'members_plus_one' | 'members_only' | 'community_only';
1178
- type EventService = 'luma' | 'private' | 'test';
1179
- type ReviewStatus = 'not_required' | 'approved' | 'rejected' | 'pending';
1180
- type EventStatus = 'active' | 'suspended' | 'archived';
1181
- type LocationType = 'event_space' | 'room';
1182
-
1183
- interface Event {
1184
- id: number;
1185
- name: string;
1186
- description: string;
1187
- eventType: EventType;
1188
- eventService: EventService;
1189
- host: string;
1190
- community: number | null;
1191
- startsAt: string;
1192
- endsAt: string;
1193
- coverImage: string | null;
1194
- eventId: string;
1195
- location: string;
1196
- locationName: string;
1197
- displayLocation: string;
1198
- url: string;
1199
- additionalHosts: string[];
1200
- color: string;
1201
- reviewStatus: ReviewStatus;
1202
- status: EventStatus;
1203
- }
1204
-
1205
- interface ListEventsParams {
1206
- search?: string;
1207
- eventType?: EventType;
1208
- locationType?: LocationType;
1209
- locationId?: string;
1210
- date?: string; // YYYY-MM-DD
1211
- startDate?: string; // YYYY-MM-DD
1212
- endDate?: string; // YYYY-MM-DD
1213
- page?: number;
1214
- }
1215
-
1216
- interface CreateEventRequest {
1217
- name: string;
1218
- eventType: EventType;
1219
- startsAt: string; // ISO 8601
1220
- endsAt: string; // ISO 8601
1221
- location: string; // readable_id slug
1222
- description?: string;
1223
- coverImage?: string; // Base64 data URI
1224
- additionalHosts?: string[];
1225
- color?: string; // Hex color code
1226
- }
1227
-
1228
- interface Location {
1229
- id: number;
1230
- owner: number | null;
1231
- readableId: string;
1232
- name: string;
1233
- maxCapacity: number;
1234
- description: string;
1235
- directions: string;
1236
- locationType: LocationType;
1237
- warmupBuffer: string; // e.g. "00:10:00"
1238
- cooldownBuffer: string; // e.g. "00:15:00"
1239
- openBooking: boolean;
1240
- floorLocation: string;
1241
- }
1242
-
1243
- interface ListLocationsParams {
1244
- locationType?: LocationType;
1245
- }
1246
-
1247
- interface RoomBooking {
1248
- id: number;
1249
- startsAt: string;
1250
- endsAt: string;
1251
- location: string;
1252
- }
1253
-
1254
- interface ListRoomBookingsParams {
1255
- locationId?: string;
1256
- date?: string; // YYYY-MM-DD
1257
- startDate?: string; // YYYY-MM-DD
1258
- endDate?: string; // YYYY-MM-DD
1259
- page?: number;
1260
- }
1261
-
1262
- interface CreateRoomBookingRequest {
1263
- startsAt: string; // ISO 8601
1264
- endsAt: string; // ISO 8601
1265
- location: string; // readable_id (must be room type)
1266
- }
1267
- ```
1268
-
1269
- ---
1270
-
1271
- ## 10. Offices Module
1272
-
1273
- Access via `sdk.getOffices()`. Manage office access passes for membership contracts.
1274
-
1275
- All endpoints require authentication, an active subscription, and manager status on the membership contract's organization (or superuser).
1276
-
1277
- ### Methods
1278
-
1279
- ```typescript
1280
- createAccessPass(payload: CreateAccessPassRequest): Promise<AccessPass>
1281
- ```
1282
- Create an access pass for a membership contract. Auto-creates an inactive account if the user does not exist. Each user can only have one active pass per contract. Permission: `offices:createAccessPass`
1283
-
1284
- ```typescript
1285
- listAccessPasses(payload?: ListAccessPassesParams): Promise<PaginatedResponse<AccessPass>>
1286
- ```
1287
- List access passes for contracts the user manages. Active only by default; set `includeRevoked: true` for all. Ordered newest first. Permission: `offices:listAccessPasses`
1288
-
1289
- ```typescript
1290
- getAccessPass(payload: { id: number }): Promise<AccessPass>
1291
- ```
1292
- Get an access pass by ID. Permission: `offices:getAccessPass`
1293
-
1294
- ```typescript
1295
- revokeAccessPass(payload: { id: number }): Promise<void>
1296
- ```
1297
- Revoke an access pass. Cannot revoke an already-revoked pass. Permission: `offices:revokeAccessPass`
1298
-
1299
- ### Offices Types
1300
-
1301
- ```typescript
1302
- type AccessPassStatus = 'active' | 'revoked';
1303
-
1304
- interface AccessPass {
1305
- id: number;
1306
- email: string;
1307
- firstName: string;
1308
- lastName: string;
1309
- status: AccessPassStatus;
1310
- membershipContract: number;
1311
- contractReference: string;
1312
- createdAt: string;
1313
- revokedAt: string | null;
1314
- updatedAt: string;
1315
- }
1316
-
1317
- interface CreateAccessPassRequest {
1318
- email: string;
1319
- firstName: string;
1320
- lastName: string;
1321
- membershipContract: number;
1322
- }
1323
-
1324
- interface ListAccessPassesParams {
1325
- limit?: number;
1326
- offset?: number;
1327
- includeRevoked?: boolean;
1328
- }
1329
- ```
1330
-
1331
- ---
1332
-
1333
- ## 11. Navigation Module
1334
-
1335
- Access via `sdk.getNavigation()`. App-to-app deep linking. Allows apps to navigate to other Frontier OS apps and receive incoming deep link data.
1336
-
1337
- ### Methods
1338
-
1339
- ```typescript
1340
- openApp(appId: string, options?: NavigationOpenAppOptions): Promise<void>
1341
- ```
1342
- Navigate the host to another app in the Frontier OS ecosystem. `appId` is the target app ID from the Frontier app registry. `options.path` provides an optional deep link path for the target app. `options.params` provides optional key-value params for the target app. Permission: `navigation:openApp`
1343
-
1344
- ```typescript
1345
- close(): Promise<void>
1346
- ```
1347
- Close the current app and return to the previous screen. Permission: `navigation:close`
1348
-
1349
- ```typescript
1350
- onDeepLink(callback: (data: DeepLinkData) => void): () => void
1351
- ```
1352
- Register a callback for incoming deep link data. Called when this app was opened via another app's `openApp()` call. Returns an unsubscribe function. No permission required (passive listener).
1353
-
1354
- ### Navigation Types
1355
-
1356
- ```typescript
1357
- interface NavigationOpenAppOptions {
1358
- path?: string;
1359
- params?: Record<string, string>;
1360
- }
1361
-
1362
- interface DeepLinkData {
1363
- path?: string;
1364
- params?: Record<string, string>;
1365
- }
1366
- ```
1367
-
1368
- ---
1369
-
1370
- ## 12. UI Utilities
1371
-
1372
- Import from `@frontiertower/frontier-sdk/ui-utils`.
1373
-
1374
- ### Detection
1375
-
1376
- ```typescript
1377
- function isInFrontierApp(): boolean
1378
- ```
1379
- Returns `true` if the window is embedded in an iframe (`window.self !== window.top`). Use to detect whether the app is running inside the Frontier Wallet host.
1380
-
1381
- ```typescript
1382
- function getParentOrigin(): string | null
1383
- ```
1384
- Returns the origin of the parent window (via `document.referrer` or `window.parent.location.origin`). Returns `null` if not in an iframe or origin cannot be determined.
1385
-
1386
- ### Standalone Fallback
1387
-
1388
- ```typescript
1389
- function renderStandaloneMessage(container: HTMLElement, appName?: string): void
1390
- ```
1391
- Renders a styled "Frontier Wallet Required" message into the given container element. Default `appName` is `'Frontier App'`. Directs users to `os.frontiertower.io` to install the app.
1392
-
1393
- ```typescript
1394
- function createStandaloneHTML(appName?: string): string
1395
- ```
1396
- Returns the same styled "Frontier Wallet Required" message as an HTML string (with gradient background). Default `appName` is `'Frontier App'`.
1397
-
1398
- ### Allowed Origins Constant
1399
-
1400
- ```typescript
1401
- const ALLOWED_ORIGINS: string[] = [
1402
- 'http://localhost:5173',
1403
- 'https://sandbox.os.frontiertower.io',
1404
- 'https://os.frontiertower.io',
1405
- ];
1406
- ```
1407
-
1408
- ---
1409
-
1410
- ## 13. Security
1411
-
1412
- ### Allowed Origins
1413
-
1414
- The SDK defines three allowed Frontier Wallet origins. Apps should only accept messages from these:
1415
-
1416
- | Environment | Origin |
1417
- |---|---|
1418
- | Development | `http://localhost:5173` |
1419
- | Sandbox | `https://sandbox.os.frontiertower.io` |
1420
- | Production | `https://os.frontiertower.io` |
1421
-
1422
- ### Access Controls Verification
1423
-
1424
- The `user:getVerifiedAccessControls` method provides a tamper-proof way to verify user access. The flow:
1425
-
1426
- 1. The PWA host relays a `SignedAccessControls` envelope from the Frontier API server.
1427
- 2. The SDK decodes the Base64 payload, computes its SHA-256 hash, and verifies the ECDSA secp256k1 signature against a hardcoded public key for the current environment stage.
1428
- 3. If the signature is valid, the decoded `AccessControlsPayload` is returned.
1429
- 4. If invalid, the method throws -- the app should deny access.
1430
-
1431
- Supported stages and their public keys (uncompressed secp256k1, hex):
1432
-
1433
- | Stage(s) | Key |
1434
- |---|---|
1435
- | `test` | `04aab6c393...` (test-only key) |
1436
- | `development`, `local`, `sandbox`, `staging` | `04dc3ab0e1...` (shared dev/sandbox key) |
1437
- | `production` | `045d1a0f9c...` (production key) |
1438
-
1439
- **Rule: Always use `getVerifiedAccessControls()` for access-gating decisions.** Do not trust unsigned user data from other SDK methods for gating features, content, or permissions.
1440
-
1441
- ### PostMessage Security
1442
-
1443
- - The SDK sends requests to `window.parent` with `'*'` as the target origin.
1444
- - The SDK only processes responses where `event.source === window.parent`.
1445
- - Requests auto-expire after 30 seconds.
1446
-
1447
- ---
1448
-
1449
- ## 14. Complete Permissions List (84 permissions across 10 modules)
1450
-
1451
- ### Wallet (22 permissions)
1452
-
1453
- | Permission | Description |
1454
- |---|---|
1455
- | `wallet:getBalance` | Access wallet balance (raw bigint) |
1456
- | `wallet:getBalanceFormatted` | Access formatted wallet balance (display strings) |
1457
- | `wallet:getAddress` | Access wallet address |
1458
- | `wallet:getSmartAccount` | Access smart account details |
1459
- | `wallet:transferERC20` | Transfer ERC20 tokens |
1460
- | `wallet:approveERC20` | Approve ERC20 token spending |
1461
- | `wallet:transferNative` | Transfer native currency (ETH) |
1462
- | `wallet:transferFrontierDollar` | Transfer FND (Frontier Network Dollar) |
1463
- | `wallet:transferInternalFrontierDollar` | Transfer iFND (Internal Frontier Network Dollar) |
1464
- | `wallet:transferOverallFrontierDollar` | Transfer using iFND first, fallback to FND |
1465
- | `wallet:executeCall` | Execute arbitrary contract call |
1466
- | `wallet:executeBatchCall` | Execute multiple contract calls atomically |
1467
- | `wallet:getSupportedTokens` | Get supported token symbols for swaps |
1468
- | `wallet:swap` | Execute token swap (same-chain or cross-chain) |
1469
- | `wallet:quoteSwap` | Get swap quote without executing |
1470
- | `wallet:getUsdDepositInstructions` | Get USD bank deposit instructions (on-ramp) |
1471
- | `wallet:getEurDepositInstructions` | Get EUR/SEPA deposit instructions (on-ramp) |
1472
- | `wallet:getLinkedBanks` | Get linked bank accounts (off-ramp) |
1473
- | `wallet:linkUsBankAccount` | Link US bank account for USD withdrawals |
1474
- | `wallet:linkEuroAccount` | Link EUR/IBAN bank account for EUR withdrawals |
1475
- | `wallet:deleteLinkedBank` | Delete a linked bank account |
1476
- | `wallet:getDeprecatedSmartAccounts` | Get deprecated smart accounts with active gas sponsorship |
1477
-
1478
- ### Storage (4 permissions)
1479
-
1480
- | Permission | Description |
1481
- |---|---|
1482
- | `storage:get` | Read from persistent storage |
1483
- | `storage:set` | Write to persistent storage |
1484
- | `storage:remove` | Remove key from persistent storage |
1485
- | `storage:clear` | Clear all persistent storage |
1486
-
1487
- ### Chain (5 permissions)
1488
-
1489
- | Permission | Description |
1490
- |---|---|
1491
- | `chain:getCurrentNetwork` | Get current network name |
1492
- | `chain:getAvailableNetworks` | Get list of available networks |
1493
- | `chain:switchNetwork` | Switch to a different network |
1494
- | `chain:getCurrentChainConfig` | Get full chain configuration |
1495
- | `chain:getContractAddresses` | Get FND, iFND, PaymentRouter, SubscriptionManager addresses |
1496
-
1497
- ### User (8 permissions)
1498
-
1499
- | Permission | Description |
1500
- |---|---|
1501
- | `user:getDetails` | Access current user details |
1502
- | `user:getProfile` | Access current user profile |
1503
- | `user:getReferralOverview` | Access referral statistics |
1504
- | `user:getReferralDetails` | Access detailed referral information |
1505
- | `user:addUserContact` | Add user contact information |
1506
- | `user:getOrCreateKyc` | Get or create KYC verification status |
1507
- | `user:createSignupRequest` | Submit membership signup request with crypto payment |
1508
- | `user:getVerifiedAccessControls` | Get cryptographically verified access controls |
1509
-
1510
- ### Partnerships (7 permissions)
1511
-
1512
- | Permission | Description |
1513
- |---|---|
1514
- | `partnerships:listSponsors` | List sponsors you manage (paginated) |
1515
- | `partnerships:getSponsor` | Retrieve a Sponsor by ID |
1516
- | `partnerships:createSponsorPass` | Create a SponsorPass |
1517
- | `partnerships:listActiveSponsorPasses` | List active SponsorPasses (paginated) |
1518
- | `partnerships:listAllSponsorPasses` | List all SponsorPasses (paginated) |
1519
- | `partnerships:getSponsorPass` | Retrieve a SponsorPass by ID |
1520
- | `partnerships:revokeSponsorPass` | Revoke a SponsorPass |
1521
-
1522
- ### Third-Party (15 permissions)
1523
-
1524
- | Permission | Description |
1525
- |---|---|
1526
- | `thirdParty:listDevelopers` | List developer accounts (paginated) |
1527
- | `thirdParty:getDeveloper` | Get developer details by ID |
1528
- | `thirdParty:updateDeveloper` | Update developer information |
1529
- | `thirdParty:rotateDeveloperApiKey` | Rotate developer API key |
1530
- | `thirdParty:listApps` | List registered apps (paginated) |
1531
- | `thirdParty:createApp` | Register a new app |
1532
- | `thirdParty:getApp` | Get app details by ID |
1533
- | `thirdParty:updateApp` | Update an app |
1534
- | `thirdParty:deleteApp` | Request app deactivation |
1535
- | `thirdParty:listWebhooks` | List webhooks (paginated) |
1536
- | `thirdParty:createWebhook` | Create a new webhook |
1537
- | `thirdParty:getWebhook` | Get webhook details by ID |
1538
- | `thirdParty:updateWebhook` | Update a webhook |
1539
- | `thirdParty:deleteWebhook` | Delete a webhook |
1540
- | `thirdParty:rotateWebhookSigningKey` | Rotate webhook signing key |
1541
-
1542
- ### Communities (11 permissions)
1543
-
1544
- | Permission | Description |
1545
- |---|---|
1546
- | `communities:listCommunities` | List all visible communities (paginated) |
1547
- | `communities:getCommunity` | Get a community by ID or slug |
1548
- | `communities:createInternshipPass` | Create an internship pass for a managed community |
1549
- | `communities:listInternshipPasses` | List internship passes for managed communities |
1550
- | `communities:getInternshipPass` | Retrieve an internship pass by ID |
1551
- | `communities:revokeInternshipPass` | Revoke an internship pass |
1552
- | `communities:createReassignRequest` | Create a member reassignment request |
1553
- | `communities:listReassignRequests` | List pending reassignment requests |
1554
- | `communities:getReassignRequest` | Retrieve a reassignment request by ID |
1555
- | `communities:acceptReassignRequest` | Accept a reassignment request (moves member) |
1556
- | `communities:rejectReassignRequest` | Reject a reassignment request |
1557
-
1558
- ### Events (6 permissions)
1559
-
1560
- | Permission | Description |
1561
- |---|---|
1562
- | `events:listEvents` | List events with optional filters (paginated) |
1563
- | `events:createEvent` | Create a new event |
1564
- | `events:addEventHost` | Add a co-host to an event |
1565
- | `events:listLocations` | List available locations (event spaces and rooms) |
1566
- | `events:listRoomBookings` | List room bookings (paginated) |
1567
- | `events:createRoomBooking` | Create a room booking |
1568
-
1569
- ### Offices (4 permissions)
1570
-
1571
- | Permission | Description |
1572
- |---|---|
1573
- | `offices:createAccessPass` | Create an access pass for a membership contract |
1574
- | `offices:listAccessPasses` | List access passes for managed contracts (paginated) |
1575
- | `offices:getAccessPass` | Retrieve an access pass by ID |
1576
- | `offices:revokeAccessPass` | Revoke an access pass |
1577
-
1578
- ### Navigation (2 permissions)
1579
-
1580
- | Permission | Description |
1581
- |---|---|
1582
- | `navigation:openApp` | Navigate to another app |
1583
- | `navigation:close` | Close current app |
1584
-
1585
- ### Wildcard Permissions
1586
-
1587
- Each module supports a wildcard permission that grants access to all methods in that module:
1588
-
1589
- | Wildcard | Grants |
1590
- |---|---|
1591
- | `wallet:*` | All wallet permissions |
1592
- | `storage:*` | All storage permissions |
1593
- | `chain:*` | All chain permissions |
1594
- | `user:*` | All user permissions |
1595
- | `partnerships:*` | All partnerships permissions |
1596
- | `thirdParty:*` | All third-party permissions |
1597
- | `communities:*` | All communities permissions |
1598
- | `events:*` | All events permissions |
1599
- | `offices:*` | All offices permissions |
1600
- | `navigation:*` | All navigation permissions |