@frak-labs/core-sdk 0.2.1-beta.b38eef2e → 0.2.1-beta.bbbb3d22

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 (76) hide show
  1. package/README.md +1 -2
  2. package/cdn/bundle.js +55 -3
  3. package/dist/actions-CIb7OfPp.js +1 -0
  4. package/dist/actions-uSbbKcu2.cjs +1 -0
  5. package/dist/actions.cjs +1 -1
  6. package/dist/actions.d.cts +3 -3
  7. package/dist/actions.d.ts +3 -3
  8. package/dist/actions.js +1 -1
  9. package/dist/bundle.cjs +1 -1
  10. package/dist/bundle.d.cts +4 -4
  11. package/dist/bundle.d.ts +4 -4
  12. package/dist/bundle.js +1 -1
  13. package/dist/{computeLegacyProductId-CCAZvLa5.d.cts → index-BMGEHGK_.d.ts} +91 -37
  14. package/dist/{computeLegacyProductId-b5cUWdAm.d.ts → index-CZ6q9BCe.d.cts} +91 -37
  15. package/dist/{siweAuthenticate-CnCZ7mok.d.ts → index-D9j5kJQ_.d.cts} +122 -8
  16. package/dist/{siweAuthenticate-CVigMOxz.d.cts → index-r9cPHZJn.d.ts} +122 -8
  17. package/dist/index.cjs +1 -1
  18. package/dist/index.d.cts +3 -3
  19. package/dist/index.d.ts +3 -3
  20. package/dist/index.js +1 -1
  21. package/dist/{openSso-B0g7-807.d.cts → openSso-C6AZ6DHE.d.ts} +278 -46
  22. package/dist/{openSso-CMzwvaCa.d.ts → openSso-DDC7BA9w.d.cts} +278 -46
  23. package/dist/src-CeGtGFnJ.js +13 -0
  24. package/dist/src-PWfXcMJt.cjs +13 -0
  25. package/dist/trackEvent-Ce1XlsIE.js +1 -0
  26. package/dist/trackEvent-CvbJTTqA.cjs +1 -0
  27. package/package.json +12 -13
  28. package/src/actions/displayEmbeddedWallet.ts +6 -2
  29. package/src/actions/displayModal.ts +6 -2
  30. package/src/actions/displaySharingPage.ts +49 -0
  31. package/src/actions/ensureIdentity.ts +2 -2
  32. package/src/actions/getMerchantInformation.test.ts +13 -1
  33. package/src/actions/getMerchantInformation.ts +20 -5
  34. package/src/actions/getMergeToken.ts +33 -0
  35. package/src/actions/getUserReferralStatus.ts +42 -0
  36. package/src/actions/index.ts +8 -1
  37. package/src/actions/referral/setupReferral.test.ts +79 -0
  38. package/src/actions/referral/setupReferral.ts +32 -0
  39. package/src/actions/trackPurchaseStatus.test.ts +32 -20
  40. package/src/actions/trackPurchaseStatus.ts +3 -5
  41. package/src/actions/wrapper/modalBuilder.test.ts +4 -2
  42. package/src/actions/wrapper/modalBuilder.ts +6 -8
  43. package/src/clients/createIFrameFrakClient.ts +150 -27
  44. package/src/clients/transports/iframeLifecycleManager.test.ts +14 -94
  45. package/src/clients/transports/iframeLifecycleManager.ts +35 -53
  46. package/src/index.ts +17 -4
  47. package/src/types/config.ts +10 -3
  48. package/src/types/index.ts +13 -1
  49. package/src/types/lifecycle/client.ts +22 -27
  50. package/src/types/lifecycle/iframe.ts +7 -8
  51. package/src/types/resolvedConfig.ts +123 -0
  52. package/src/types/rpc/displaySharingPage.ts +77 -0
  53. package/src/types/rpc/embedded/index.ts +1 -1
  54. package/src/types/rpc/interaction.ts +4 -0
  55. package/src/types/rpc/userReferralStatus.ts +20 -0
  56. package/src/types/rpc.ts +54 -5
  57. package/src/utils/backendUrl.test.ts +2 -2
  58. package/src/utils/backendUrl.ts +1 -1
  59. package/src/utils/cache/index.ts +7 -0
  60. package/src/utils/cache/lruMap.test.ts +55 -0
  61. package/src/utils/cache/lruMap.ts +38 -0
  62. package/src/utils/cache/withCache.test.ts +162 -0
  63. package/src/utils/cache/withCache.ts +105 -0
  64. package/src/utils/inAppBrowser.ts +60 -0
  65. package/src/utils/index.ts +6 -4
  66. package/src/utils/sdkConfigStore.test.ts +405 -0
  67. package/src/utils/sdkConfigStore.ts +263 -0
  68. package/src/utils/sso.ts +3 -7
  69. package/dist/setupClient-CqTHGvVa.cjs +0 -13
  70. package/dist/setupClient-DTyvAPgh.js +0 -13
  71. package/dist/siweAuthenticate-BWmI2_TN.cjs +0 -1
  72. package/dist/siweAuthenticate-zczqxm0a.js +0 -1
  73. package/dist/trackEvent-CeLFVzZn.js +0 -1
  74. package/dist/trackEvent-Ew5r5zfI.cjs +0 -1
  75. package/src/utils/merchantId.test.ts +0 -653
  76. package/src/utils/merchantId.ts +0 -143
@@ -1,6 +1,6 @@
1
- import { Address, Hex } from "viem";
2
- import { LifecycleMessage, RpcClient } from "@frak-labs/frame-connector";
3
1
  import { OpenPanel } from "@openpanel/web";
2
+ import { LifecycleMessage, RpcClient } from "@frak-labs/frame-connector";
3
+ import { Address, Hex } from "viem";
4
4
  import { SiweMessage } from "viem/siwe";
5
5
 
6
6
  //#region src/types/config.d.ts
@@ -31,7 +31,7 @@ type FrakWalletSdkConfig = {
31
31
  /**
32
32
  * Your application name (will be displayed in a few modals and in SSO)
33
33
  */
34
- name: string;
34
+ name?: string;
35
35
  /**
36
36
  * Your merchant ID from the Frak dashboard (UUID format)
37
37
  * Used for referral tracking and analytics
@@ -75,6 +75,13 @@ type FrakWalletSdkConfig = {
75
75
  * @defaultValue window.location.host
76
76
  */
77
77
  domain?: string;
78
+ /**
79
+ * Wait for backend config before rendering components.
80
+ * When true (default), components show a spinner until backend config is resolved.
81
+ * When false, components render immediately with SDK static config / HTML attributes.
82
+ * @defaultValue true
83
+ */
84
+ waitForBackendConfig?: boolean;
78
85
  };
79
86
  /**
80
87
  * Custom i18n configuration for the modal
@@ -111,19 +118,116 @@ type FrakWalletSdkConfig = {
111
118
  */
112
119
  type I18nConfig = Record<Language, LocalizedI18nConfig> | LocalizedI18nConfig;
113
120
  /**
114
- * A localized i18n config
121
+ * A localized i18n config (inline objects only — URL-based i18n removed)
115
122
  * @category Config
116
123
  */
117
- type LocalizedI18nConfig = `${string}.css` | {
124
+ type LocalizedI18nConfig = {
118
125
  [key: string]: string;
119
126
  };
120
127
  //#endregion
128
+ //#region src/types/resolvedConfig.d.ts
129
+ /**
130
+ * Response from the merchant resolve endpoint
131
+ * @category Config
132
+ */
133
+ type MerchantConfigResponse = {
134
+ merchantId: string;
135
+ name: string;
136
+ domain: string;
137
+ allowedDomains: string[];
138
+ sdkConfig?: ResolvedSdkConfig;
139
+ };
140
+ /**
141
+ * Resolved placement config from backend
142
+ * Translations already flattened: default + lang-specific merged into one record
143
+ * @category Config
144
+ */
145
+ type ResolvedPlacement = {
146
+ /** Per-component configuration within this placement */components?: {
147
+ buttonShare?: {
148
+ text?: string;
149
+ noRewardText?: string;
150
+ clickAction?: "embedded-wallet" | "share-modal" | "sharing-page";
151
+ useReward?: boolean;
152
+ css?: string;
153
+ };
154
+ buttonWallet?: {
155
+ position?: "right" | "left";
156
+ css?: string;
157
+ };
158
+ openInApp?: {
159
+ text?: string;
160
+ css?: string;
161
+ };
162
+ postPurchase?: {
163
+ badgeText?: string;
164
+ refereeText?: string;
165
+ refereeNoRewardText?: string;
166
+ referrerText?: string;
167
+ referrerNoRewardText?: string;
168
+ ctaText?: string;
169
+ ctaNoRewardText?: string;
170
+ css?: string;
171
+ };
172
+ banner?: {
173
+ referralTitle?: string;
174
+ referralDescription?: string;
175
+ referralCta?: string;
176
+ inappTitle?: string;
177
+ inappDescription?: string;
178
+ inappCta?: string;
179
+ css?: string;
180
+ };
181
+ };
182
+ targetInteraction?: string; /** Already flattened: default + lang-specific merged into one record */
183
+ translations?: Record<string, string>; /** Global placement CSS (applied to modals/listener) */
184
+ css?: string;
185
+ };
186
+ /**
187
+ * Resolved SDK config from backend `/resolve` endpoint
188
+ * Language resolution and translation merging already applied
189
+ * @category Config
190
+ */
191
+ type ResolvedSdkConfig = {
192
+ name?: string;
193
+ logoUrl?: string;
194
+ homepageLink?: string;
195
+ currency?: Currency;
196
+ lang?: Language; /** When true, all SDK components should be hidden */
197
+ hidden?: boolean;
198
+ css?: string;
199
+ translations?: Record<string, string>;
200
+ placements?: Record<string, ResolvedPlacement>;
201
+ };
202
+ /**
203
+ * Internal SDK config store state
204
+ * Merged config: backend > SDK static > defaults
205
+ * Components subscribe to this reactively
206
+ * @category Config
207
+ */
208
+ type SdkResolvedConfig = {
209
+ /** Whether the backend config has been resolved */isResolved: boolean; /** Merchant ID from resolution */
210
+ merchantId: string; /** Domain returned by the resolve endpoint */
211
+ domain?: string; /** Domains allowed for this merchant (used by iframe trust check) */
212
+ allowedDomains?: string[]; /** Whether the resolve returned a backend sdkConfig object */
213
+ hasRawSdkConfig?: boolean; /** Merged metadata fields */
214
+ name?: string;
215
+ logoUrl?: string;
216
+ homepageLink?: string;
217
+ lang?: Language;
218
+ currency?: Currency; /** When true, all SDK components should be hidden */
219
+ hidden?: boolean; /** Global CSS from backend config (passed to iframe) */
220
+ css?: string; /** Global translations (for reference / component fallback) */
221
+ translations?: Record<string, string>; /** Named placements (keyed by placement ID) */
222
+ placements?: Record<string, ResolvedPlacement>;
223
+ };
224
+ //#endregion
121
225
  //#region src/types/lifecycle/client.d.ts
122
226
  /**
123
227
  * Event related to the iframe lifecycle
124
228
  * @ignore
125
229
  */
126
- type ClientLifecycleEvent = CustomCssEvent | CustomI18nEvent | RestoreBackupEvent | HearbeatEvent | HandshakeResponse | SsoRedirectCompleteEvent | DeepLinkFailedEvent;
230
+ type ClientLifecycleEvent = CustomCssEvent | CustomI18nEvent | RestoreBackupEvent | HearbeatEvent | SsoRedirectCompleteEvent | DeepLinkFailedEvent | ResolvedConfigEvent;
127
231
  type CustomCssEvent = {
128
232
  clientLifecycle: "modal-css";
129
233
  data: {
@@ -146,30 +250,6 @@ type HearbeatEvent = {
146
250
  clientLifecycle: "heartbeat";
147
251
  data?: never;
148
252
  };
149
- type HandshakeResponse = {
150
- clientLifecycle: "handshake-response";
151
- data: {
152
- token: string;
153
- currentUrl: string;
154
- /**
155
- * Pending merge token extracted from URL (?fmt= parameter)
156
- * When present, listener should execute identity merge in background
157
- * URL is cleaned after handshake response is sent
158
- */
159
- pendingMergeToken?: string;
160
- /**
161
- * Client ID for identity tracking (belt & suspenders fallback)
162
- * Primary delivery is via iframe URL query param; handshake is backup for SSR
163
- */
164
- clientId?: string;
165
- /**
166
- * Explicit domain from SDK config (FrakWalletSdkConfig.domain)
167
- * When present, listener should prefer this over URL-derived domain
168
- * for merchant resolution (handles proxied/tunneled environments)
169
- */
170
- configDomain?: string;
171
- };
172
- };
173
253
  type SsoRedirectCompleteEvent = {
174
254
  clientLifecycle: "sso-redirect-complete";
175
255
  data: {
@@ -182,6 +262,21 @@ type DeepLinkFailedEvent = {
182
262
  originalUrl: string;
183
263
  };
184
264
  };
265
+ type ResolvedConfigEvent = {
266
+ clientLifecycle: "resolved-config";
267
+ data: {
268
+ merchantId: string; /** The domain the backend resolved this config for */
269
+ domain: string; /** All domains registered for this merchant (for domain proof) */
270
+ allowedDomains: string[]; /** Full URL of the parent page (for interaction tracking) */
271
+ sourceUrl: string;
272
+ /**
273
+ * Pending merge token extracted from URL (?fmt= parameter).
274
+ * When present, listener should execute identity merge in background.
275
+ */
276
+ pendingMergeToken?: string;
277
+ sdkConfig?: ResolvedSdkConfig;
278
+ };
279
+ };
185
280
  //#endregion
186
281
  //#region src/types/lifecycle/iframe.d.ts
187
282
  /**
@@ -191,19 +286,13 @@ type DeepLinkFailedEvent = {
191
286
  type IFrameLifecycleEvent = {
192
287
  iframeLifecycle: "connected" | "show" | "hide" | "remove-backup";
193
288
  data?: never;
194
- } | DoBackupEvent | HandshakeRequestEvent | RedirectRequestEvent;
289
+ } | DoBackupEvent | RedirectRequestEvent;
195
290
  type DoBackupEvent = {
196
291
  iframeLifecycle: "do-backup";
197
292
  data: {
198
293
  backup?: string;
199
294
  };
200
295
  };
201
- type HandshakeRequestEvent = {
202
- iframeLifecycle: "handshake";
203
- data: {
204
- token: string;
205
- };
206
- };
207
296
  type RedirectRequestEvent = {
208
297
  iframeLifecycle: "redirect";
209
298
  data: {
@@ -218,6 +307,13 @@ type RedirectRequestEvent = {
218
307
  * Used when redirecting out of social browsers to preserve identity across contexts
219
308
  */
220
309
  mergeToken?: string;
310
+ /**
311
+ * When true, open the URL in a new tab via window.open(_blank)
312
+ * instead of navigating the current page.
313
+ * Requires the postMessage to include user activation delegation
314
+ * (includeUserActivation: true) so Safari allows the popup.
315
+ */
316
+ openInNewTab?: boolean;
221
317
  };
222
318
  };
223
319
  //#endregion
@@ -534,6 +630,80 @@ type DisplayModalParamsType<T extends ModalStepTypes[]> = {
534
630
  metadata?: ModalRpcMetadata;
535
631
  };
536
632
  //#endregion
633
+ //#region src/types/rpc/displaySharingPage.d.ts
634
+ /**
635
+ * Product information to display on the sharing page
636
+ * @group Sharing Page
637
+ */
638
+ type SharingPageProduct = {
639
+ /**
640
+ * The product title / name
641
+ */
642
+ title: string;
643
+ /**
644
+ * Optional product image URL
645
+ */
646
+ imageUrl?: string;
647
+ };
648
+ /**
649
+ * Parameters to display the sharing page
650
+ * @group Sharing Page
651
+ * @group RPC Schema
652
+ */
653
+ type DisplaySharingPageParamsType = {
654
+ /**
655
+ * Products to showcase on the sharing page
656
+ * If provided, they will be displayed in a product card section
657
+ */
658
+ products?: SharingPageProduct[];
659
+ /**
660
+ * Optional link override for sharing
661
+ * If not provided, the sharing link will be generated from the current page URL + merchant context
662
+ */
663
+ link?: string;
664
+ /**
665
+ * Optional metadata overrides for the sharing page
666
+ */
667
+ metadata?: {
668
+ /**
669
+ * Logo override for the sharing page header
670
+ */
671
+ logo?: string;
672
+ /**
673
+ * Link to the homepage of the calling website
674
+ */
675
+ homepageLink?: string;
676
+ /**
677
+ * The target interaction behind this sharing page
678
+ */
679
+ targetInteraction?: InteractionTypeKey;
680
+ /**
681
+ * i18n overrides for the sharing page
682
+ */
683
+ i18n?: I18nConfig;
684
+ };
685
+ };
686
+ /**
687
+ * Result of the sharing page display
688
+ * @group Sharing Page
689
+ * @group RPC Schema
690
+ */
691
+ type DisplaySharingPageResultType = {
692
+ /**
693
+ * The action the user took
694
+ * - "shared": User used the native share dialog
695
+ * - "copied": User copied the link to clipboard
696
+ * - "dismissed": User dismissed the sharing page without acting
697
+ */
698
+ action: "shared" | "copied" | "dismissed";
699
+ /**
700
+ * The install URL for the Frak app
701
+ * Can be used as a fallback to redirect the user to the install page
702
+ * from the merchant's top-level page (e.g. via `window.location.href`)
703
+ */
704
+ installUrl?: string;
705
+ };
706
+ //#endregion
537
707
  //#region src/types/rpc/embedded/loggedIn.d.ts
538
708
  /**
539
709
  * The different type of action we can have on the embedded view (once the user is logged in)
@@ -691,7 +861,9 @@ type SendInteractionParamsType = {
691
861
  utmTerm?: string;
692
862
  utmContent?: string;
693
863
  } | {
694
- type: "sharing";
864
+ type: "sharing"; /** Epoch seconds timestamp matching the V2 context `t` field embedded in the referral link URL, used for backend correlation */
865
+ sharingTimestamp?: number; /** Merchant order ID linking this sharing event to a purchase (stays server-side, never in URL) */
866
+ purchaseId?: string;
695
867
  } | {
696
868
  type: "custom";
697
869
  customType: string;
@@ -769,6 +941,28 @@ type GetMerchantInformationReturnType = {
769
941
  }[];
770
942
  };
771
943
  //#endregion
944
+ //#region src/types/rpc/userReferralStatus.d.ts
945
+ /**
946
+ * User referral status returned by `frak_getUserReferralStatus`.
947
+ *
948
+ * Generic referral context for the current user on a merchant.
949
+ * Used by components like `<frak-post-purchase>` and `<frak-referred-banner>`
950
+ * to adapt their display based on the user's referral relationship.
951
+ *
952
+ * Returns `null` when the user's identity cannot be resolved
953
+ * (e.g. no clientId and no wallet session).
954
+ *
955
+ * @group RPC Schema
956
+ */
957
+ type UserReferralStatusType = {
958
+ /**
959
+ * Whether the user was referred to this merchant by someone else.
960
+ *
961
+ * `true` means a referral link exists where this user is the referee.
962
+ */
963
+ isReferred: boolean;
964
+ };
965
+ //#endregion
772
966
  //#region src/types/rpc/walletStatus.d.ts
773
967
  /**
774
968
  * RPC Response for the method `frak_listenToWalletStatus`
@@ -815,7 +1009,7 @@ type WalletNotConnected = {
815
1009
  * - Response Type: stream (emits updates when wallet status changes)
816
1010
  *
817
1011
  * #### frak_displayModal
818
- * - Params: [requests: {@link ModalRpcStepsInput}, metadata?: {@link ModalRpcMetadata}, configMetadata: {@link FrakWalletSdkConfig}["metadata"]]
1012
+ * - Params: [requests: {@link ModalRpcStepsInput}, metadata?: {@link ModalRpcMetadata}, configMetadata: {@link FrakWalletSdkConfig}["metadata"], placement?: string]
819
1013
  * - Returns: {@link ModalRpcStepsResultType}
820
1014
  * - Response Type: promise (one-shot)
821
1015
  *
@@ -830,9 +1024,14 @@ type WalletNotConnected = {
830
1024
  * - Response Type: promise (one-shot)
831
1025
  *
832
1026
  * #### frak_displayEmbeddedWallet
833
- * - Params: [request: {@link DisplayEmbeddedWalletParamsType}, metadata: {@link FrakWalletSdkConfig}["metadata"]]
1027
+ * - Params: [request: {@link DisplayEmbeddedWalletParamsType}, metadata: {@link FrakWalletSdkConfig}["metadata"], placement?: string]
834
1028
  * - Returns: {@link DisplayEmbeddedWalletResultType}
835
1029
  * - Response Type: promise (one-shot)
1030
+ *
1031
+ * #### frak_displaySharingPage
1032
+ * - Params: [request: {@link DisplaySharingPageParamsType}, configMetadata: {@link FrakWalletSdkConfig}["metadata"], placement?: string]
1033
+ * - Returns: {@link DisplaySharingPageResultType}
1034
+ * - Response Type: promise (one-shot)
836
1035
  */
837
1036
  type IFrameRpcSchema = [
838
1037
  /**
@@ -850,7 +1049,7 @@ type IFrameRpcSchema = [
850
1049
  */
851
1050
  {
852
1051
  Method: "frak_displayModal";
853
- Parameters: [requests: ModalRpcStepsInput, metadata: ModalRpcMetadata | undefined, configMetadata: FrakWalletSdkConfig["metadata"]];
1052
+ Parameters: [requests: ModalRpcStepsInput, metadata: ModalRpcMetadata | undefined, configMetadata: FrakWalletSdkConfig["metadata"], placement?: string];
854
1053
  ReturnType: ModalRpcStepsResultType;
855
1054
  },
856
1055
  /**
@@ -860,7 +1059,7 @@ type IFrameRpcSchema = [
860
1059
  */
861
1060
  {
862
1061
  Method: "frak_prepareSso";
863
- Parameters: [params: PrepareSsoParamsType, name: string, customCss?: string];
1062
+ Parameters: [params: PrepareSsoParamsType, name?: string, customCss?: string];
864
1063
  ReturnType: PrepareSsoReturnType;
865
1064
  },
866
1065
  /**
@@ -871,7 +1070,7 @@ type IFrameRpcSchema = [
871
1070
  */
872
1071
  {
873
1072
  Method: "frak_openSso";
874
- Parameters: [params: OpenSsoParamsType, name: string, customCss?: string];
1073
+ Parameters: [params: OpenSsoParamsType, name?: string, customCss?: string];
875
1074
  ReturnType: OpenSsoReturnType;
876
1075
  },
877
1076
  /**
@@ -892,14 +1091,14 @@ type IFrameRpcSchema = [
892
1091
  */
893
1092
  {
894
1093
  Method: "frak_displayEmbeddedWallet";
895
- Parameters: [request: DisplayEmbeddedWalletParamsType, metadata: FrakWalletSdkConfig["metadata"]];
1094
+ Parameters: [request: DisplayEmbeddedWalletParamsType, metadata: FrakWalletSdkConfig["metadata"], placement?: string];
896
1095
  ReturnType: DisplayEmbeddedWalletResultType;
897
1096
  },
898
1097
  /**
899
1098
  * Method to send interactions (arrival, sharing, custom events)
900
1099
  * Fire-and-forget method - no return value expected
901
1100
  * merchantId is resolved from context
902
- * clientId is passed via metadata as safeguard against handshake race condition
1101
+ * clientId is passed via metadata as safeguard against race conditions
903
1102
  */
904
1103
  {
905
1104
  Method: "frak_sendInteraction";
@@ -907,6 +1106,39 @@ type IFrameRpcSchema = [
907
1106
  clientId?: string;
908
1107
  }];
909
1108
  ReturnType: undefined;
1109
+ },
1110
+ /**
1111
+ * Method to get the current user's referral status on this merchant.
1112
+ * Returns whether the user was referred (has a referral link as referee).
1113
+ * Returns null when the user's identity cannot be resolved.
1114
+ * This is a one-shot request.
1115
+ */
1116
+ {
1117
+ Method: "frak_getUserReferralStatus";
1118
+ Parameters?: undefined;
1119
+ ReturnType: UserReferralStatusType | null;
1120
+ },
1121
+ /**
1122
+ * Method to display a sharing page with product info and sharing buttons
1123
+ * Resolves on first user action (share/copy) but the page stays visible
1124
+ * This is a one-shot request
1125
+ */
1126
+ {
1127
+ Method: "frak_displaySharingPage";
1128
+ Parameters: [request: DisplaySharingPageParamsType, configMetadata: FrakWalletSdkConfig["metadata"], placement?: string];
1129
+ ReturnType: DisplaySharingPageResultType;
1130
+ },
1131
+ /**
1132
+ * Method to get a merge token for the current anonymous identity.
1133
+ * Used by in-app browser redirect flows to preserve identity
1134
+ * when switching from a WebView to the system browser.
1135
+ * Returns the merge token string, or null if unavailable.
1136
+ * This is a one-shot request.
1137
+ */
1138
+ {
1139
+ Method: "frak_getMergeToken";
1140
+ Parameters?: undefined;
1141
+ ReturnType: string | null;
910
1142
  }];
911
1143
  //#endregion
912
1144
  //#region src/types/transport.d.ts
@@ -1052,4 +1284,4 @@ declare const ssoPopupName = "frak-sso";
1052
1284
  */
1053
1285
  declare function openSso(client: FrakClient, args: OpenSsoParamsType): Promise<OpenSsoReturnType>;
1054
1286
  //#endregion
1055
- export { SendTransactionModalStepType as A, PrepareSsoReturnType as B, EmbeddedViewActionSharing as C, ModalRpcStepsInput as D, ModalRpcMetadata as E, SiweAuthenticationParams as F, InteractionTypeKey as G, FinalActionType as H, LoginModalStepType as I, Currency as J, IFrameLifecycleEvent as K, OpenSsoParamsType as L, SendTransactionTxType as M, SiweAuthenticateModalStepType as N, ModalRpcStepsResultType as O, SiweAuthenticateReturnType as P, LocalizedI18nConfig as Q, OpenSsoReturnType as R, EmbeddedViewActionReferred as S, DisplayModalParamsType as T, FinalModalStepType as U, SsoMetadata as V, ModalStepMetadata as W, I18nConfig as X, FrakWalletSdkConfig as Y, Language as Z, TokenAmountType as _, FrakContextV1 as a, DisplayEmbeddedWalletResultType as b, isV2Context as c, IFrameTransport as d, IFrameRpcSchema as f, RewardTier as g, GetMerchantInformationReturnType as h, FrakContext as i, SendTransactionReturnType as j, ModalStepTypes as k, FrakClient as l, EstimatedReward as m, ssoPopupFeatures as n, FrakContextV2 as o, WalletStatusReturnType as p, ClientLifecycleEvent as q, ssoPopupName as r, isV1Context as s, openSso as t, FrakLifecycleEvent as u, SendInteractionParamsType as v, LoggedInEmbeddedView as w, LoggedOutEmbeddedView as x, DisplayEmbeddedWalletParamsType as y, PrepareSsoParamsType as z };
1287
+ export { ResolvedPlacement as $, ModalRpcMetadata as A, LoginModalStepType as B, EmbeddedViewActionReferred as C, DisplaySharingPageResultType as D, DisplaySharingPageParamsType as E, SendTransactionReturnType as F, SsoMetadata as G, OpenSsoReturnType as H, SendTransactionTxType as I, ModalStepMetadata as J, FinalActionType as K, SiweAuthenticateModalStepType as L, ModalRpcStepsResultType as M, ModalStepTypes as N, SharingPageProduct as O, SendTransactionModalStepType as P, MerchantConfigResponse as Q, SiweAuthenticateReturnType as R, LoggedOutEmbeddedView as S, LoggedInEmbeddedView as T, PrepareSsoParamsType as U, OpenSsoParamsType as V, PrepareSsoReturnType as W, IFrameLifecycleEvent as X, InteractionTypeKey as Y, ClientLifecycleEvent as Z, RewardTier as _, FrakContextV1 as a, Language as at, DisplayEmbeddedWalletParamsType as b, isV2Context as c, IFrameTransport as d, ResolvedSdkConfig as et, IFrameRpcSchema as f, GetMerchantInformationReturnType as g, EstimatedReward as h, FrakContext as i, I18nConfig as it, ModalRpcStepsInput as j, DisplayModalParamsType as k, FrakClient as l, UserReferralStatusType as m, ssoPopupFeatures as n, Currency as nt, FrakContextV2 as o, LocalizedI18nConfig as ot, WalletStatusReturnType as p, FinalModalStepType as q, ssoPopupName as r, FrakWalletSdkConfig as rt, isV1Context as s, openSso as t, SdkResolvedConfig as tt, FrakLifecycleEvent as u, TokenAmountType as v, EmbeddedViewActionSharing as w, DisplayEmbeddedWalletResultType as x, SendInteractionParamsType as y, SiweAuthenticationParams as z };
@@ -0,0 +1,13 @@
1
+ import{n as e,s as t,y as n}from"./trackEvent-Ce1XlsIE.js";import{Deferred as r,FrakRpcError as i,RpcErrorCodes as a,createRpcClient as o}from"@frak-labs/frame-connector";import{OpenPanel as s}from"@openpanel/web";const c=`nexus-wallet-backup`,l=`frakwallet://`;function u(){let e=navigator.userAgent;return/Android/i.test(e)&&/Chrome\/\d+/i.test(e)}function d(e){return`intent://${e.slice(13)}#Intent;scheme=frakwallet;end`}function f(e,t){let n=t?.timeout??2500,r=!1,i=()=>{document.hidden&&(r=!0)};document.addEventListener(`visibilitychange`,i);let a=u()&&p(e)?d(e):e;window.location.href=a,setTimeout(()=>{document.removeEventListener(`visibilitychange`,i),r||t?.onFallback?.()},n)}function p(e){return e.startsWith(l)}const m={eur:`fr-FR`,usd:`en-US`,gbp:`en-GB`};function h(e){return e&&e in m?e:`eur`}function g(e){return e?m[e]??m.eur:m.eur}function _(e,t){let n=g(t),r=h(t);return e.toLocaleString(n,{style:`currency`,currency:r,minimumFractionDigits:0,maximumFractionDigits:2})}function v(e){return e?`${e}Amount`:`eurAmount`}const y={id:`frak-wallet`,name:`frak-wallet`,title:`Frak Wallet`,allow:`publickey-credentials-get *; clipboard-write; web-share *`,style:{width:`0`,height:`0`,border:`0`,position:`absolute`,zIndex:2000001,top:`-1000px`,left:`-1000px`,colorScheme:`auto`}};function b({walletBaseUrl:e,config:t}){let r=document.querySelector(`#frak-wallet`);r&&r.remove();let i=document.createElement(`iframe`);i.id=y.id,i.name=y.name,i.allow=y.allow,i.style.zIndex=y.style.zIndex.toString(),x({iframe:i,isVisible:!1});let a=t?.walletUrl??e??`https://wallet.frak.id`,o=n();return i.src=`${a}/listener?clientId=${encodeURIComponent(o)}`,new Promise(e=>{i.addEventListener(`load`,()=>e(i)),document.body.appendChild(i)})}function x({iframe:e,isVisible:t}){if(!t){e.style.width=`0`,e.style.height=`0`,e.style.border=`0`,e.style.position=`fixed`,e.style.top=`-1000px`,e.style.left=`-1000px`;return}e.style.position=`fixed`,e.style.top=`0`,e.style.left=`0`,e.style.width=`100%`,e.style.height=`100%`,e.style.pointerEvents=`auto`}function S(e=`/listener`){if(!window.opener)return null;let t=t=>{try{return t.location.origin===window.location.origin&&t.location.pathname===e}catch{return!1}};if(t(window.opener))return window.opener;try{let e=window.opener.frames;for(let n=0;n<e.length;n++)if(t(e[n]))return e[n];return null}catch(t){return console.error(`[findIframeInOpener] Error finding iframe with pathname ${e}:`,t),null}}function C(){if(typeof navigator>`u`)return!1;let e=navigator.userAgent;return!!(/iPhone|iPad|iPod/i.test(e)||/Macintosh/i.test(e)&&navigator.maxTouchPoints>1)}const w=C();function T(){if(typeof navigator>`u`)return!1;let e=navigator.userAgent.toLowerCase();return e.includes(`instagram`)||e.includes(`fban`)||e.includes(`fbav`)||e.includes(`facebook`)}const E=T();function D(e){w&&e.startsWith(`https://`)?window.location.href=`x-safari-https://${e.slice(8)}`:w&&e.startsWith(`http://`)?window.location.href=`x-safari-http://${e.slice(7)}`:window.location.href=`https://backend.frak.id/common/social?u=${encodeURIComponent(e)}`}function O(e,t){if(typeof window>`u`)return;let n=new URL(window.location.href),r=n.searchParams.get(`sso`);r&&(t.then(()=>{e.sendLifecycle({clientLifecycle:`sso-redirect-complete`,data:{compressed:r}}),console.log(`[SSO URL Listener] Forwarded compressed SSO data to iframe`)}).catch(e=>{console.error(`[SSO URL Listener] Failed to forward SSO data:`,e)}),n.searchParams.delete(`sso`),window.history.replaceState({},``,n.toString()),console.log(`[SSO URL Listener] SSO parameter detected and URL cleaned`))}var k=class e{config;iframe;isSetupDone=!1;lastResponse=null;lastRequest=null;constructor(e,t){this.config=e,this.iframe=t,this.lastRequest=null,this.lastResponse=null}setLastResponse(e,t){this.lastResponse={message:e,response:t,timestamp:Date.now()}}setLastRequest(e){this.lastRequest={event:e,timestamp:Date.now()}}updateSetupStatus(e){this.isSetupDone=e}base64Encode(e){try{return btoa(JSON.stringify(e))}catch(e){return console.warn(`Failed to encode debug data`,e),btoa(`Failed to encode data`)}}getIframeStatus(){return this.iframe?{loading:this.iframe.hasAttribute(`loading`),url:this.iframe.src,readyState:this.iframe.contentDocument?.readyState?+(this.iframe.contentDocument.readyState===`complete`):-1,contentWindow:!!this.iframe.contentWindow,isConnected:this.iframe.isConnected}:null}getNavigatorInfo(){return navigator?{userAgent:navigator.userAgent,language:navigator.language,onLine:navigator.onLine,screenWidth:window.screen.width,screenHeight:window.screen.height,pixelRatio:window.devicePixelRatio}:null}gatherDebugInfo(e){let t=this.getIframeStatus(),n=this.getNavigatorInfo(),r=`Unknown`;return e instanceof i?r=`FrakRpcError: ${e.code} '${e.message}'`:e instanceof Error?r=e.message:typeof e==`string`&&(r=e),{timestamp:new Date().toISOString(),encodedUrl:btoa(window.location.href),encodedConfig:this.config?this.base64Encode(this.config):`no-config`,navigatorInfo:n?this.base64Encode(n):`no-navigator`,iframeStatus:t?this.base64Encode(t):`not-iframe`,lastRequest:this.lastRequest?this.base64Encode(this.lastRequest):`No Frak request logged`,lastResponse:this.lastResponse?this.base64Encode(this.lastResponse):`No Frak response logged`,clientStatus:this.isSetupDone?`setup`:`not-setup`,error:r}}static empty(){return new e}formatDebugInfo(e){let t=this.gatherDebugInfo(e);return`
2
+ Debug Information:
3
+ -----------------
4
+ Timestamp: ${t.timestamp}
5
+ URL: ${t.encodedUrl}
6
+ Config: ${t.encodedConfig}
7
+ Navigator Info: ${t.navigatorInfo}
8
+ IFrame Status: ${t.iframeStatus}
9
+ Last Request: ${t.lastRequest}
10
+ Last Response: ${t.lastResponse}
11
+ Client Status: ${t.clientStatus}
12
+ Error: ${t.error}
13
+ `.trim()}};const A=(()=>{if(typeof navigator>`u`)return!1;let e=navigator.userAgent;if(!(/iPhone|iPad|iPod/i.test(e)||/Macintosh/i.test(e)&&navigator.maxTouchPoints>1))return!1;let t=e.toLowerCase();return t.includes(`instagram`)||t.includes(`fban`)||t.includes(`fbav`)||t.includes(`facebook`)})();function j(e){e?localStorage.setItem(c,e):localStorage.removeItem(c)}function M(e,t){try{let n=new URL(e);if(!n.searchParams.has(`u`))return e;let r=F(window.location.href,t);return n.searchParams.delete(`u`),n.searchParams.append(`u`,r),n.toString()}catch{return e}}function N(e){let t=new URL(window.location.href);e&&t.searchParams.set(`fmt`,e);let n=t.protocol===`http:`?`x-safari-http`:`x-safari-https`;window.location.href=`${n}://${t.host}${t.pathname}${t.search}${t.hash}`}function P(e){return e.includes(`/common/social`)}function F(e,t){if(!t)return e;try{let n=new URL(e);return n.searchParams.set(`fmt`,t),n.toString()}catch{return`${e}${e.includes(`?`)?`&`:`?`}fmt=${encodeURIComponent(t)}`}}function I(e,t,n,r,i){if(i){let e=M(t,r);window.open(e,`_blank`);return}if(p(t)){let i=M(t,r);f(i,{onFallback:()=>{e.contentWindow?.postMessage({clientLifecycle:`deep-link-failed`,data:{originalUrl:i}},n)}})}else if(A&&P(t))N(r);else{let e=M(t,r);window.location.href=e}}function L({iframe:e,targetOrigin:t}){let n=new r;return{handleEvent:r=>{if(!(`iframeLifecycle`in r))return;let{iframeLifecycle:i,data:a}=r;switch(i){case`connected`:n.resolve(!0);break;case`do-backup`:j(a.backup);break;case`remove-backup`:localStorage.removeItem(c);break;case`show`:case`hide`:x({iframe:e,isVisible:i===`show`});break;case`redirect`:I(e,a.baseRedirectUrl,t,a.mergeToken,a.openInNewTab);break}},isConnected:n.promise}}function R({config:c,iframe:l}){let u=c?.walletUrl??`https://wallet.frak.id`,d=typeof navigator<`u`?navigator.language?.split(`-`)[0]:void 0,f=c.metadata.lang??(d===`en`||d===`fr`?d:void 0),p=c.domain??(typeof window<`u`?window.location.hostname:``);e.setCacheScope(p,f),e.reset();let m=e.isCacheFresh?void 0:e.resolve(c.domain,c.walletUrl,f),h=L({iframe:l,targetOrigin:u}),g=new r,_=new k(c,l);if(!l.contentWindow)throw new i(a.configError,`The iframe does not have a content window`);let v=o({emittingTransport:l.contentWindow,listeningTransport:window,targetOrigin:u,middleware:[{async onRequest(e,t){if(!await h.isConnected)throw new i(a.clientNotConnected,`The iframe provider isn't connected yet`);return await g.promise,t}},{onRequest(e,t){return _.setLastRequest(e),t},onResponse(e,t){return _.setLastResponse(e,t),t}}],lifecycleHandlers:{iframeLifecycle:(e,t)=>{h.handleEvent(e)}}}),y=z(v,h),b=async()=>{y(),v.cleanup(),l.remove(),t(),e.clearCache(),e.reset()},x;console.log(`[Frak SDK] Initializing OpenPanel`),x=new s({apiUrl:`https://op-api.gcp.frak.id`,clientId:`6eacc8d7-49ac-4936-95e9-81ef29449570`,trackScreenViews:!0,trackOutgoingLinks:!0,trackAttributes:!1,filter:({type:e,payload:t})=>(e!==`track`||!t?.properties||`sdkVersion`in t.properties||(t.properties={...t.properties,sdkVersion:`0.2.1`,userAnonymousClientId:n()}),!0)}),x.setGlobalProperties({sdkVersion:`0.2.1`,userAnonymousClientId:n()}),x.init();let S=B({config:c,rpcClient:v,lifecycleManager:h,configPromise:m,contextSent:g}).then(()=>_.updateSetupStatus(!0)).catch(e=>{throw g.reject(e),e});return{config:c,debugInfo:_,waitForConnection:h.isConnected,waitForSetup:S,request:v.request,listenerRequest:v.listen,destroy:b,openPanel:x}}function z(e,t){let n,r,i=()=>e.sendLifecycle({clientLifecycle:`heartbeat`});async function a(){i(),n=setInterval(i,1e3),r=setTimeout(()=>{o(),console.log(`Heartbeat timeout: connection failed`)},3e4),await t.isConnected,o()}function o(){n&&clearInterval(n),r&&clearTimeout(r)}return a(),o}async function B({config:t,rpcClient:n,lifecycleManager:r,configPromise:i,contextSent:a}){await r.isConnected,O(n,r.isConnected);let o=new URL(window.location.href),s=o.searchParams.get(`fmt`)??void 0;s&&(o.searchParams.delete(`fmt`),window.history.replaceState({},``,o.toString()));let l=n=>{let r=n?.merchantId??t.metadata.merchantId??``,i=n?.domain??``,a=n?.allowedDomains??[],o=n?.sdkConfig;e.setConfig(o?{isResolved:!0,merchantId:r,domain:i,allowedDomains:a,hasRawSdkConfig:!0,name:o.name??t.metadata.name,logoUrl:o.logoUrl??t.metadata.logoUrl,homepageLink:o.homepageLink??t.metadata.homepageLink,lang:o.lang??t.metadata.lang,currency:o.currency??t.metadata.currency,hidden:o.hidden,css:o.css,translations:o.translations,placements:o.placements}:{isResolved:!0,merchantId:r,domain:i,allowedDomains:a,name:t.metadata.name,logoUrl:t.metadata.logoUrl,homepageLink:t.metadata.homepageLink,lang:t.metadata.lang,currency:t.metadata.currency})},u=!1,d=e=>{let t=u?void 0:s;u=!0;let r=e.hasRawSdkConfig?{name:e.name,logoUrl:e.logoUrl,homepageLink:e.homepageLink,lang:e.lang,currency:e.currency,hidden:e.hidden,css:e.css,translations:e.translations,placements:e.placements}:void 0;n.sendLifecycle({clientLifecycle:`resolved-config`,data:{merchantId:e.merchantId,domain:e.domain??``,allowedDomains:e.allowedDomains??[],sourceUrl:window.location.href,...t&&{pendingMergeToken:t},...r&&{sdkConfig:r}}})};e.isResolved&&(d(e.getConfig()),a.resolve()),i&&(l(await i),d(e.getConfig()),a.resolve());async function f(){let e=t.customizations?.css;e&&n.sendLifecycle({clientLifecycle:`modal-css`,data:{cssLink:e}})}async function p(){let e=t.customizations?.i18n;e&&n.sendLifecycle({clientLifecycle:`modal-i18n`,data:{i18n:e}})}async function m(){if(typeof window>`u`)return;let e=window.localStorage.getItem(c);e&&n.sendLifecycle({clientLifecycle:`restore-backup`,data:{backup:e}})}await Promise.allSettled([f(),p(),m()])}async function V({config:e}){let t=H(e),n=await b({config:t});if(!n){console.error(`Failed to create iframe`);return}let r=R({config:t,iframe:n});if(await r.waitForSetup,!await r.waitForConnection){console.error(`Failed to connect to client`);return}return r}function H(e){let t=h(e.metadata?.currency);return{...e,metadata:{...e.metadata,currency:t}}}export{d as _,E as a,b as c,_ as d,g as f,p as g,u as h,w as i,S as l,m,R as n,D as o,h as p,k as r,y as s,V as t,v as u,f as v,l as y};
@@ -0,0 +1,13 @@
1
+ const e=require(`./trackEvent-CvbJTTqA.cjs`);let t=require(`@frak-labs/frame-connector`),n=require(`@openpanel/web`);const r=`nexus-wallet-backup`,i=`frakwallet://`;function a(){let e=navigator.userAgent;return/Android/i.test(e)&&/Chrome\/\d+/i.test(e)}function o(e){return`intent://${e.slice(13)}#Intent;scheme=frakwallet;end`}function s(e,t){let n=t?.timeout??2500,r=!1,i=()=>{document.hidden&&(r=!0)};document.addEventListener(`visibilitychange`,i);let s=a()&&c(e)?o(e):e;window.location.href=s,setTimeout(()=>{document.removeEventListener(`visibilitychange`,i),r||t?.onFallback?.()},n)}function c(e){return e.startsWith(i)}const l={eur:`fr-FR`,usd:`en-US`,gbp:`en-GB`};function u(e){return e&&e in l?e:`eur`}function d(e){return e?l[e]??l.eur:l.eur}function f(e,t){let n=d(t),r=u(t);return e.toLocaleString(n,{style:`currency`,currency:r,minimumFractionDigits:0,maximumFractionDigits:2})}function p(e){return e?`${e}Amount`:`eurAmount`}const m={id:`frak-wallet`,name:`frak-wallet`,title:`Frak Wallet`,allow:`publickey-credentials-get *; clipboard-write; web-share *`,style:{width:`0`,height:`0`,border:`0`,position:`absolute`,zIndex:2000001,top:`-1000px`,left:`-1000px`,colorScheme:`auto`}};function h({walletBaseUrl:t,config:n}){let r=document.querySelector(`#frak-wallet`);r&&r.remove();let i=document.createElement(`iframe`);i.id=m.id,i.name=m.name,i.allow=m.allow,i.style.zIndex=m.style.zIndex.toString(),g({iframe:i,isVisible:!1});let a=n?.walletUrl??t??`https://wallet.frak.id`,o=e.y();return i.src=`${a}/listener?clientId=${encodeURIComponent(o)}`,new Promise(e=>{i.addEventListener(`load`,()=>e(i)),document.body.appendChild(i)})}function g({iframe:e,isVisible:t}){if(!t){e.style.width=`0`,e.style.height=`0`,e.style.border=`0`,e.style.position=`fixed`,e.style.top=`-1000px`,e.style.left=`-1000px`;return}e.style.position=`fixed`,e.style.top=`0`,e.style.left=`0`,e.style.width=`100%`,e.style.height=`100%`,e.style.pointerEvents=`auto`}function _(e=`/listener`){if(!window.opener)return null;let t=t=>{try{return t.location.origin===window.location.origin&&t.location.pathname===e}catch{return!1}};if(t(window.opener))return window.opener;try{let e=window.opener.frames;for(let n=0;n<e.length;n++)if(t(e[n]))return e[n];return null}catch(t){return console.error(`[findIframeInOpener] Error finding iframe with pathname ${e}:`,t),null}}function v(){if(typeof navigator>`u`)return!1;let e=navigator.userAgent;return!!(/iPhone|iPad|iPod/i.test(e)||/Macintosh/i.test(e)&&navigator.maxTouchPoints>1)}const y=v();function b(){if(typeof navigator>`u`)return!1;let e=navigator.userAgent.toLowerCase();return e.includes(`instagram`)||e.includes(`fban`)||e.includes(`fbav`)||e.includes(`facebook`)}const x=b();function S(e){y&&e.startsWith(`https://`)?window.location.href=`x-safari-https://${e.slice(8)}`:y&&e.startsWith(`http://`)?window.location.href=`x-safari-http://${e.slice(7)}`:window.location.href=`https://backend.frak.id/common/social?u=${encodeURIComponent(e)}`}function C(e,t){if(typeof window>`u`)return;let n=new URL(window.location.href),r=n.searchParams.get(`sso`);r&&(t.then(()=>{e.sendLifecycle({clientLifecycle:`sso-redirect-complete`,data:{compressed:r}}),console.log(`[SSO URL Listener] Forwarded compressed SSO data to iframe`)}).catch(e=>{console.error(`[SSO URL Listener] Failed to forward SSO data:`,e)}),n.searchParams.delete(`sso`),window.history.replaceState({},``,n.toString()),console.log(`[SSO URL Listener] SSO parameter detected and URL cleaned`))}var w=class e{config;iframe;isSetupDone=!1;lastResponse=null;lastRequest=null;constructor(e,t){this.config=e,this.iframe=t,this.lastRequest=null,this.lastResponse=null}setLastResponse(e,t){this.lastResponse={message:e,response:t,timestamp:Date.now()}}setLastRequest(e){this.lastRequest={event:e,timestamp:Date.now()}}updateSetupStatus(e){this.isSetupDone=e}base64Encode(e){try{return btoa(JSON.stringify(e))}catch(e){return console.warn(`Failed to encode debug data`,e),btoa(`Failed to encode data`)}}getIframeStatus(){return this.iframe?{loading:this.iframe.hasAttribute(`loading`),url:this.iframe.src,readyState:this.iframe.contentDocument?.readyState?+(this.iframe.contentDocument.readyState===`complete`):-1,contentWindow:!!this.iframe.contentWindow,isConnected:this.iframe.isConnected}:null}getNavigatorInfo(){return navigator?{userAgent:navigator.userAgent,language:navigator.language,onLine:navigator.onLine,screenWidth:window.screen.width,screenHeight:window.screen.height,pixelRatio:window.devicePixelRatio}:null}gatherDebugInfo(e){let n=this.getIframeStatus(),r=this.getNavigatorInfo(),i=`Unknown`;return e instanceof t.FrakRpcError?i=`FrakRpcError: ${e.code} '${e.message}'`:e instanceof Error?i=e.message:typeof e==`string`&&(i=e),{timestamp:new Date().toISOString(),encodedUrl:btoa(window.location.href),encodedConfig:this.config?this.base64Encode(this.config):`no-config`,navigatorInfo:r?this.base64Encode(r):`no-navigator`,iframeStatus:n?this.base64Encode(n):`not-iframe`,lastRequest:this.lastRequest?this.base64Encode(this.lastRequest):`No Frak request logged`,lastResponse:this.lastResponse?this.base64Encode(this.lastResponse):`No Frak response logged`,clientStatus:this.isSetupDone?`setup`:`not-setup`,error:i}}static empty(){return new e}formatDebugInfo(e){let t=this.gatherDebugInfo(e);return`
2
+ Debug Information:
3
+ -----------------
4
+ Timestamp: ${t.timestamp}
5
+ URL: ${t.encodedUrl}
6
+ Config: ${t.encodedConfig}
7
+ Navigator Info: ${t.navigatorInfo}
8
+ IFrame Status: ${t.iframeStatus}
9
+ Last Request: ${t.lastRequest}
10
+ Last Response: ${t.lastResponse}
11
+ Client Status: ${t.clientStatus}
12
+ Error: ${t.error}
13
+ `.trim()}};const T=(()=>{if(typeof navigator>`u`)return!1;let e=navigator.userAgent;if(!(/iPhone|iPad|iPod/i.test(e)||/Macintosh/i.test(e)&&navigator.maxTouchPoints>1))return!1;let t=e.toLowerCase();return t.includes(`instagram`)||t.includes(`fban`)||t.includes(`fbav`)||t.includes(`facebook`)})();function E(e){e?localStorage.setItem(r,e):localStorage.removeItem(r)}function D(e,t){try{let n=new URL(e);if(!n.searchParams.has(`u`))return e;let r=A(window.location.href,t);return n.searchParams.delete(`u`),n.searchParams.append(`u`,r),n.toString()}catch{return e}}function O(e){let t=new URL(window.location.href);e&&t.searchParams.set(`fmt`,e);let n=t.protocol===`http:`?`x-safari-http`:`x-safari-https`;window.location.href=`${n}://${t.host}${t.pathname}${t.search}${t.hash}`}function k(e){return e.includes(`/common/social`)}function A(e,t){if(!t)return e;try{let n=new URL(e);return n.searchParams.set(`fmt`,t),n.toString()}catch{return`${e}${e.includes(`?`)?`&`:`?`}fmt=${encodeURIComponent(t)}`}}function j(e,t,n,r,i){if(i){let e=D(t,r);window.open(e,`_blank`);return}if(c(t)){let i=D(t,r);s(i,{onFallback:()=>{e.contentWindow?.postMessage({clientLifecycle:`deep-link-failed`,data:{originalUrl:i}},n)}})}else if(T&&k(t))O(r);else{let e=D(t,r);window.location.href=e}}function M({iframe:e,targetOrigin:n}){let i=new t.Deferred;return{handleEvent:t=>{if(!(`iframeLifecycle`in t))return;let{iframeLifecycle:a,data:o}=t;switch(a){case`connected`:i.resolve(!0);break;case`do-backup`:E(o.backup);break;case`remove-backup`:localStorage.removeItem(r);break;case`show`:case`hide`:g({iframe:e,isVisible:a===`show`});break;case`redirect`:j(e,o.baseRedirectUrl,n,o.mergeToken,o.openInNewTab);break}},isConnected:i.promise}}function N({config:r,iframe:i}){let a=r?.walletUrl??`https://wallet.frak.id`,o=typeof navigator<`u`?navigator.language?.split(`-`)[0]:void 0,s=r.metadata.lang??(o===`en`||o===`fr`?o:void 0),c=r.domain??(typeof window<`u`?window.location.hostname:``);e.n.setCacheScope(c,s),e.n.reset();let l=e.n.isCacheFresh?void 0:e.n.resolve(r.domain,r.walletUrl,s),u=M({iframe:i,targetOrigin:a}),d=new t.Deferred,f=new w(r,i);if(!i.contentWindow)throw new t.FrakRpcError(t.RpcErrorCodes.configError,`The iframe does not have a content window`);let p=(0,t.createRpcClient)({emittingTransport:i.contentWindow,listeningTransport:window,targetOrigin:a,middleware:[{async onRequest(e,n){if(!await u.isConnected)throw new t.FrakRpcError(t.RpcErrorCodes.clientNotConnected,`The iframe provider isn't connected yet`);return await d.promise,n}},{onRequest(e,t){return f.setLastRequest(e),t},onResponse(e,t){return f.setLastResponse(e,t),t}}],lifecycleHandlers:{iframeLifecycle:(e,t)=>{u.handleEvent(e)}}}),m=P(p,u),h=async()=>{m(),p.cleanup(),i.remove(),e.s(),e.n.clearCache(),e.n.reset()},g;console.log(`[Frak SDK] Initializing OpenPanel`),g=new n.OpenPanel({apiUrl:`https://op-api.gcp.frak.id`,clientId:`6eacc8d7-49ac-4936-95e9-81ef29449570`,trackScreenViews:!0,trackOutgoingLinks:!0,trackAttributes:!1,filter:({type:t,payload:n})=>(t!==`track`||!n?.properties||`sdkVersion`in n.properties||(n.properties={...n.properties,sdkVersion:`0.2.1`,userAnonymousClientId:e.y()}),!0)}),g.setGlobalProperties({sdkVersion:`0.2.1`,userAnonymousClientId:e.y()}),g.init();let _=F({config:r,rpcClient:p,lifecycleManager:u,configPromise:l,contextSent:d}).then(()=>f.updateSetupStatus(!0)).catch(e=>{throw d.reject(e),e});return{config:r,debugInfo:f,waitForConnection:u.isConnected,waitForSetup:_,request:p.request,listenerRequest:p.listen,destroy:h,openPanel:g}}function P(e,t){let n,r,i=()=>e.sendLifecycle({clientLifecycle:`heartbeat`});async function a(){i(),n=setInterval(i,1e3),r=setTimeout(()=>{o(),console.log(`Heartbeat timeout: connection failed`)},3e4),await t.isConnected,o()}function o(){n&&clearInterval(n),r&&clearTimeout(r)}return a(),o}async function F({config:t,rpcClient:n,lifecycleManager:i,configPromise:a,contextSent:o}){await i.isConnected,C(n,i.isConnected);let s=new URL(window.location.href),c=s.searchParams.get(`fmt`)??void 0;c&&(s.searchParams.delete(`fmt`),window.history.replaceState({},``,s.toString()));let l=n=>{let r=n?.merchantId??t.metadata.merchantId??``,i=n?.domain??``,a=n?.allowedDomains??[],o=n?.sdkConfig;e.n.setConfig(o?{isResolved:!0,merchantId:r,domain:i,allowedDomains:a,hasRawSdkConfig:!0,name:o.name??t.metadata.name,logoUrl:o.logoUrl??t.metadata.logoUrl,homepageLink:o.homepageLink??t.metadata.homepageLink,lang:o.lang??t.metadata.lang,currency:o.currency??t.metadata.currency,hidden:o.hidden,css:o.css,translations:o.translations,placements:o.placements}:{isResolved:!0,merchantId:r,domain:i,allowedDomains:a,name:t.metadata.name,logoUrl:t.metadata.logoUrl,homepageLink:t.metadata.homepageLink,lang:t.metadata.lang,currency:t.metadata.currency})},u=!1,d=e=>{let t=u?void 0:c;u=!0;let r=e.hasRawSdkConfig?{name:e.name,logoUrl:e.logoUrl,homepageLink:e.homepageLink,lang:e.lang,currency:e.currency,hidden:e.hidden,css:e.css,translations:e.translations,placements:e.placements}:void 0;n.sendLifecycle({clientLifecycle:`resolved-config`,data:{merchantId:e.merchantId,domain:e.domain??``,allowedDomains:e.allowedDomains??[],sourceUrl:window.location.href,...t&&{pendingMergeToken:t},...r&&{sdkConfig:r}}})};e.n.isResolved&&(d(e.n.getConfig()),o.resolve()),a&&(l(await a),d(e.n.getConfig()),o.resolve());async function f(){let e=t.customizations?.css;e&&n.sendLifecycle({clientLifecycle:`modal-css`,data:{cssLink:e}})}async function p(){let e=t.customizations?.i18n;e&&n.sendLifecycle({clientLifecycle:`modal-i18n`,data:{i18n:e}})}async function m(){if(typeof window>`u`)return;let e=window.localStorage.getItem(r);e&&n.sendLifecycle({clientLifecycle:`restore-backup`,data:{backup:e}})}await Promise.allSettled([f(),p(),m()])}async function I({config:e}){let t=L(e),n=await h({config:t});if(!n){console.error(`Failed to create iframe`);return}let r=N({config:t,iframe:n});if(await r.waitForSetup,!await r.waitForConnection){console.error(`Failed to connect to client`);return}return r}function L(e){let t=u(e.metadata?.currency);return{...e,metadata:{...e.metadata,currency:t}}}Object.defineProperty(exports,`_`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`g`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`h`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return N}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return I}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`v`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`y`,{enumerable:!0,get:function(){return i}});
@@ -0,0 +1 @@
1
+ import{bytesToHex as e,hexToBytes as t,isAddress as n,keccak256 as r,toHex as i}from"viem";import{jsonDecode as a,jsonEncode as o}from"@frak-labs/frame-connector";const s=`frak-client-id`;function c(){return typeof crypto<`u`&&crypto.randomUUID?crypto.randomUUID():`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e===`x`?t:t&3|8).toString(16)})}function l(){if(typeof window>`u`||!window.localStorage)return console.warn(`[Frak SDK] No Window / localStorage available to save the clientId`),c();let e=localStorage.getItem(s);return e||(e=c(),localStorage.setItem(s,e)),e}function u({domain:e}={}){return r(i((e??window.location.host).replace(`www.`,``)))}function d(e){return btoa(Array.from(e,e=>String.fromCharCode(e)).join(``)).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function f(e){let t=e.length%4;return Uint8Array.from(atob(e.replace(/-/g,`+`).replace(/_/g,`/`).padEnd(e.length+(t===0?0:4-t),`=`)),e=>e.charCodeAt(0))}function p(e){return d(o(e))}function m(e,t,n,r,i,a){let o=p(ee({redirectUrl:t.redirectUrl,directExit:t.directExit,lang:t.lang,merchantId:n,metadata:{name:r,css:a,logoUrl:t.metadata?.logoUrl,homepageLink:t.metadata?.homepageLink},clientId:i})),s=new URL(e);return s.pathname=`/sso`,s.searchParams.set(`p`,o),s.toString()}function ee(e){return{r:e.redirectUrl,cId:e.clientId,d:e.directExit,l:e.lang,m:e.merchantId,md:{n:e.metadata?.name,css:e.metadata?.css,l:e.metadata?.logoUrl,h:e.metadata?.homepageLink}}}const h=`menubar=no,status=no,scrollbars=no,fullscreen=no,width=500, height=800`,g=`frak-sso`;async function _(e,t){let{metadata:n,customizations:r,walletUrl:i}=e.config;if(t.openInSameWindow??!!t.redirectUrl)return await e.request({method:`frak_openSso`,params:[t,n.name,r?.css]});let a=t.ssoPopupUrl??m(i??`https://wallet.frak.id`,t,u(),n.name,l(),r?.css),o=window.open(a,g,h);if(!o)throw Error(`Popup was blocked. Please allow popups for this site.`);return o.focus(),await e.request({method:`frak_openSso`,params:[t,n.name,r?.css]})??{}}const v=`https://backend.frak.id`;function y(e){return e.includes(`localhost:3000`)||e.includes(`localhost:3010`)}function b(e){return y(e)?`https://localhost:3030`:e.includes(`wallet-dev.frak.id`)||e.includes(`wallet.gcp-dev.frak.id`)?`https://backend.gcp-dev.frak.id`:v}function x(e){if(e)return b(e);if(typeof window<`u`){let e=window.FrakSetup?.client?.config?.walletUrl;if(e)return b(e)}return v}var S=class extends Map{maxSize;constructor(e){super(),this.maxSize=e}get(e){let t=super.get(e);return super.has(e)&&(super.delete(e),super.set(e,t)),t}set(e,t){if(super.has(e)&&super.delete(e),super.set(e,t),this.maxSize&&this.size>this.maxSize){let e=super.keys().next().value;e!==void 0&&super.delete(e)}return this}};const C=new S(1024),w=new S(1024),T=3e4;async function E(e,{cacheKey:t,cacheTime:n=T}){if(n>0){let e=w.get(t);if(e&&Date.now()-e.created<n)return e.data}let r=C.get(t);r||(r=e(),C.set(t,r));try{let e=await r;return w.set(t,{data:e,created:Date.now()}),e}finally{C.delete(t)}}function D(e){return{clear:()=>{C.delete(e),w.delete(e)},has:(t=T)=>{let n=w.get(e);return n?Date.now()-n.created<t:!1}}}function O(){C.clear(),w.clear()}function k(e){return a(f(e))}function te(e){return`r`in e&&!(`v`in e)}function A(e){return`v`in e&&e.v===2}const j=`fCtx`;function M(e){if(e)try{return A(e)?!e.c||!e.m||!e.t?void 0:p({v:2,c:e.c,m:e.m,t:e.t}):d(t(e.r))}catch(t){console.error(`Error compressing Frak context`,{e:t,context:e})}}function N(t){if(!(!t||t.length===0))try{let r=k(t);if(r&&typeof r==`object`&&r.v===2)return r.c&&r.m&&r.t?{v:2,c:r.c,m:r.m,t:r.t}:void 0;let i=e(f(t),{size:20});if(n(i))return{r:i}}catch(e){console.error(`Error decompressing Frak context`,{e,context:t})}}function P({url:e}){if(!e)return null;let t=new URL(e).searchParams.get(j);return t?N(t):null}function F({url:e,context:t}){if(!e)return null;let n=M(t);if(!n)return null;let r=new URL(e);return r.searchParams.set(j,n),r.toString()}function I(e){let t=new URL(e);return t.searchParams.delete(j),t.toString()}function ne({url:e,context:t}){if(!window.location?.href||typeof window>`u`){console.error(`No window found, can't update context`);return}let n=e??window.location.href,r;r=t===null?I(n):F({url:n,context:t}),r&&window.history.replaceState(null,``,r.toString())}const L={compress:M,decompress:N,parse:P,update:F,remove:I,replaceUrl:ne},R=`__frakSdkConfig`,z=`frak-config-cache`,B=`frak-merchant-id`,V={key:z},H=typeof window<`u`;function U(){return{isResolved:!1,merchantId:``}}let W=null;function G(){if(!H)return null;try{let e=localStorage.getItem(V.key);if(!e)return null;let t=JSON.parse(e);return t.config?.isResolved?(W=t,t):null}catch{return null}}function K(){return(W??G())?.config}function q(){let e=W??G();return e?Date.now()-e.timestamp<3e4:!1}function J(e){if(!(!H||!e.isResolved))try{let t={config:e,timestamp:Date.now()};localStorage.setItem(V.key,JSON.stringify(t)),W=t}catch{}}function Y(){if(H){W=null;try{localStorage.removeItem(V.key)}catch{}}}function X(){H&&(window[R]||(window[R]=K()??U()))}X();function Z(){return H?window[R]??U():U()}function Q(e){H&&window.dispatchEvent(new CustomEvent(`frak:config`,{detail:e}))}function re(e){return e??(H?window.location.hostname:``)}async function ie(e,t,n){try{let r=x(t),i=n?`&lang=${encodeURIComponent(n)}`:``,a=await fetch(`${r}/user/merchant/resolve?domain=${encodeURIComponent(e)}${i}`);if(!a.ok){console.warn(`[Frak SDK] Merchant lookup failed for domain ${e}: ${a.status}`);return}let o=await a.json();if(H)try{sessionStorage.setItem(B,o.merchantId)}catch{}return o}catch(e){console.warn(`[Frak SDK] Failed to fetch merchant config:`,e);return}}const $={getConfig:Z,get isResolved(){return Z().isResolved},get isCacheFresh(){return q()},setCacheScope(e,t){V.key=`${z}:${`${e}:${t??``}`}`,W=null},setConfig(e){if(H&&(window[R]=e),J(e),Q(e),H&&e.merchantId)try{sessionStorage.setItem(B,e.merchantId)}catch{}},reset(){let e=K()??U();H&&(window[R]=e),Q(e)},clearCache(){if(Y(),O(),H)try{sessionStorage.removeItem(B)}catch{}},resolve(e,t,n){let r=re(e);return r?E(async()=>{let e=await ie(r,t,n);if(!e)throw Error(`Config resolution returned empty`);return e},{cacheKey:`sdkConfig:${r}:${n??``}`,cacheTime:1/0}).catch(()=>void 0):Promise.resolve(void 0)},getMerchantId(){let e=Z();if(e.isResolved&&e.merchantId)return e.merchantId;if(H)try{return sessionStorage.getItem(B)??void 0}catch{}},async resolveMerchantId(e,t){return $.getMerchantId()||(await $.resolve(e,t))?.merchantId}};function ae(e,t,n={}){if(!e){console.debug(`[Frak] No client provided, skipping event tracking`);return}try{e.openPanel?.track(t,n)}catch(e){console.debug(`[Frak] Failed to track event:`,t,e)}}export{d as _,A as a,D as c,_ as d,h as f,f as g,p as h,te as i,E as l,m,$ as n,k as o,g as p,L as r,O as s,ae as t,x as u,u as v,l as y};
@@ -0,0 +1 @@
1
+ let e=require(`viem`),t=require(`@frak-labs/frame-connector`);const n=`frak-client-id`;function r(){return typeof crypto<`u`&&crypto.randomUUID?crypto.randomUUID():`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e===`x`?t:t&3|8).toString(16)})}function i(){if(typeof window>`u`||!window.localStorage)return console.warn(`[Frak SDK] No Window / localStorage available to save the clientId`),r();let e=localStorage.getItem(n);return e||(e=r(),localStorage.setItem(n,e)),e}function a({domain:t}={}){return(0,e.keccak256)((0,e.toHex)((t??window.location.host).replace(`www.`,``)))}function o(e){return btoa(Array.from(e,e=>String.fromCharCode(e)).join(``)).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function s(e){let t=e.length%4;return Uint8Array.from(atob(e.replace(/-/g,`+`).replace(/_/g,`/`).padEnd(e.length+(t===0?0:4-t),`=`)),e=>e.charCodeAt(0))}function c(e){return o((0,t.jsonEncode)(e))}function l(e,t,n,r,i,a){let o=c(u({redirectUrl:t.redirectUrl,directExit:t.directExit,lang:t.lang,merchantId:n,metadata:{name:r,css:a,logoUrl:t.metadata?.logoUrl,homepageLink:t.metadata?.homepageLink},clientId:i})),s=new URL(e);return s.pathname=`/sso`,s.searchParams.set(`p`,o),s.toString()}function u(e){return{r:e.redirectUrl,cId:e.clientId,d:e.directExit,l:e.lang,m:e.merchantId,md:{n:e.metadata?.name,css:e.metadata?.css,l:e.metadata?.logoUrl,h:e.metadata?.homepageLink}}}const d=`menubar=no,status=no,scrollbars=no,fullscreen=no,width=500, height=800`,f=`frak-sso`;async function p(e,t){let{metadata:n,customizations:r,walletUrl:o}=e.config;if(t.openInSameWindow??!!t.redirectUrl)return await e.request({method:`frak_openSso`,params:[t,n.name,r?.css]});let s=t.ssoPopupUrl??l(o??`https://wallet.frak.id`,t,a(),n.name,i(),r?.css),c=window.open(s,f,d);if(!c)throw Error(`Popup was blocked. Please allow popups for this site.`);return c.focus(),await e.request({method:`frak_openSso`,params:[t,n.name,r?.css]})??{}}const m=`https://backend.frak.id`;function h(e){return e.includes(`localhost:3000`)||e.includes(`localhost:3010`)}function g(e){return h(e)?`https://localhost:3030`:e.includes(`wallet-dev.frak.id`)||e.includes(`wallet.gcp-dev.frak.id`)?`https://backend.gcp-dev.frak.id`:m}function _(e){if(e)return g(e);if(typeof window<`u`){let e=window.FrakSetup?.client?.config?.walletUrl;if(e)return g(e)}return m}var v=class extends Map{maxSize;constructor(e){super(),this.maxSize=e}get(e){let t=super.get(e);return super.has(e)&&(super.delete(e),super.set(e,t)),t}set(e,t){if(super.has(e)&&super.delete(e),super.set(e,t),this.maxSize&&this.size>this.maxSize){let e=super.keys().next().value;e!==void 0&&super.delete(e)}return this}};const y=new v(1024),b=new v(1024),x=3e4;async function S(e,{cacheKey:t,cacheTime:n=x}){if(n>0){let e=b.get(t);if(e&&Date.now()-e.created<n)return e.data}let r=y.get(t);r||(r=e(),y.set(t,r));try{let e=await r;return b.set(t,{data:e,created:Date.now()}),e}finally{y.delete(t)}}function C(e){return{clear:()=>{y.delete(e),b.delete(e)},has:(t=x)=>{let n=b.get(e);return n?Date.now()-n.created<t:!1}}}function w(){y.clear(),b.clear()}function T(e){return(0,t.jsonDecode)(s(e))}function E(e){return`r`in e&&!(`v`in e)}function D(e){return`v`in e&&e.v===2}const O=`fCtx`;function k(t){if(t)try{return D(t)?!t.c||!t.m||!t.t?void 0:c({v:2,c:t.c,m:t.m,t:t.t}):o((0,e.hexToBytes)(t.r))}catch(e){console.error(`Error compressing Frak context`,{e,context:t})}}function A(t){if(!(!t||t.length===0))try{let n=T(t);if(n&&typeof n==`object`&&n.v===2)return n.c&&n.m&&n.t?{v:2,c:n.c,m:n.m,t:n.t}:void 0;let r=(0,e.bytesToHex)(s(t),{size:20});if((0,e.isAddress)(r))return{r}}catch(e){console.error(`Error decompressing Frak context`,{e,context:t})}}function j({url:e}){if(!e)return null;let t=new URL(e).searchParams.get(O);return t?A(t):null}function M({url:e,context:t}){if(!e)return null;let n=k(t);if(!n)return null;let r=new URL(e);return r.searchParams.set(O,n),r.toString()}function N(e){let t=new URL(e);return t.searchParams.delete(O),t.toString()}function P({url:e,context:t}){if(!window.location?.href||typeof window>`u`){console.error(`No window found, can't update context`);return}let n=e??window.location.href,r;r=t===null?N(n):M({url:n,context:t}),r&&window.history.replaceState(null,``,r.toString())}const F={compress:k,decompress:A,parse:j,update:M,remove:N,replaceUrl:P},I=`__frakSdkConfig`,L=`frak-config-cache`,R=`frak-merchant-id`,z={key:L},B=typeof window<`u`;function V(){return{isResolved:!1,merchantId:``}}let H=null;function U(){if(!B)return null;try{let e=localStorage.getItem(z.key);if(!e)return null;let t=JSON.parse(e);return t.config?.isResolved?(H=t,t):null}catch{return null}}function W(){return(H??U())?.config}function G(){let e=H??U();return e?Date.now()-e.timestamp<3e4:!1}function K(e){if(!(!B||!e.isResolved))try{let t={config:e,timestamp:Date.now()};localStorage.setItem(z.key,JSON.stringify(t)),H=t}catch{}}function q(){if(B){H=null;try{localStorage.removeItem(z.key)}catch{}}}function J(){B&&(window[I]||(window[I]=W()??V()))}J();function Y(){return B?window[I]??V():V()}function X(e){B&&window.dispatchEvent(new CustomEvent(`frak:config`,{detail:e}))}function Z(e){return e??(B?window.location.hostname:``)}async function Q(e,t,n){try{let r=_(t),i=n?`&lang=${encodeURIComponent(n)}`:``,a=await fetch(`${r}/user/merchant/resolve?domain=${encodeURIComponent(e)}${i}`);if(!a.ok){console.warn(`[Frak SDK] Merchant lookup failed for domain ${e}: ${a.status}`);return}let o=await a.json();if(B)try{sessionStorage.setItem(R,o.merchantId)}catch{}return o}catch(e){console.warn(`[Frak SDK] Failed to fetch merchant config:`,e);return}}const $={getConfig:Y,get isResolved(){return Y().isResolved},get isCacheFresh(){return G()},setCacheScope(e,t){z.key=`${L}:${`${e}:${t??``}`}`,H=null},setConfig(e){if(B&&(window[I]=e),K(e),X(e),B&&e.merchantId)try{sessionStorage.setItem(R,e.merchantId)}catch{}},reset(){let e=W()??V();B&&(window[I]=e),X(e)},clearCache(){if(q(),w(),B)try{sessionStorage.removeItem(R)}catch{}},resolve(e,t,n){let r=Z(e);return r?S(async()=>{let e=await Q(r,t,n);if(!e)throw Error(`Config resolution returned empty`);return e},{cacheKey:`sdkConfig:${r}:${n??``}`,cacheTime:1/0}).catch(()=>void 0):Promise.resolve(void 0)},getMerchantId(){let e=Y();if(e.isResolved&&e.merchantId)return e.merchantId;if(B)try{return sessionStorage.getItem(R)??void 0}catch{}},async resolveMerchantId(e,t){return $.getMerchantId()||(await $.resolve(e,t))?.merchantId}};function ee(e,t,n={}){if(!e){console.debug(`[Frak] No client provided, skipping event tracking`);return}try{e.openPanel?.track(t,n)}catch(e){console.debug(`[Frak] Failed to track event:`,t,e)}}Object.defineProperty(exports,`_`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return D}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`g`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`h`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return $}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return F}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return ee}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`v`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`y`,{enumerable:!0,get:function(){return i}});
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "url": "https://twitter.com/QNivelais"
12
12
  }
13
13
  ],
14
- "version": "0.2.1-beta.b38eef2e",
14
+ "version": "0.2.1-beta.bbbb3d22",
15
15
  "description": "Core SDK of the Frak wallet, low level library to interact directly with the frak ecosystem.",
16
16
  "repository": {
17
17
  "url": "https://github.com/frak-id/wallet",
@@ -91,22 +91,21 @@
91
91
  "viem": "^2.x"
92
92
  },
93
93
  "dependencies": {
94
- "@frak-labs/frame-connector": "0.2.0-beta.b38eef2e",
95
- "@openpanel/web": "^1.0.7"
94
+ "@frak-labs/frame-connector": "0.2.0-beta.bbbb3d22",
95
+ "@openpanel/web": "^1.2.0"
96
96
  },
97
97
  "devDependencies": {
98
98
  "@arethetypeswrong/cli": "^0.18.2",
99
- "@frak-labs/dev-tooling": "0.0.0",
100
99
  "@frak-labs/test-foundation": "0.1.0",
101
100
  "@rolldown/plugin-node-polyfills": "^1.0.3",
102
- "@types/jsdom": "^27.0.0",
103
- "@types/node": "^24.10.13",
104
- "@vitest/coverage-v8": "^4.0.18",
105
- "@vitest/ui": "^4.0.18",
106
- "jsdom": "^28.0.0",
107
- "tsdown": "^0.20.3",
108
- "typescript": "^5.9.3",
109
- "viem": "^2.39.0",
110
- "vitest": "^4.0.18"
101
+ "@types/jsdom": "^28.0.0",
102
+ "@types/node": "^25.6.0",
103
+ "@vitest/coverage-v8": "^4.1.4",
104
+ "@vitest/ui": "^4.1.4",
105
+ "jsdom": "^29.0.0",
106
+ "tsdown": "^0.21.8",
107
+ "typescript": "^6.0.2",
108
+ "viem": "^2.47.16",
109
+ "vitest": "^4.1.4"
111
110
  }
112
111
  }
@@ -8,14 +8,18 @@ import type {
8
8
  * Function used to display the Frak embedded wallet popup
9
9
  * @param client - The current Frak Client
10
10
  * @param params - The parameter used to customise the embedded wallet
11
+ * @param placement - Optional placement ID to associate with this display request
11
12
  * @returns The embedded wallet display result
12
13
  */
13
14
  export async function displayEmbeddedWallet(
14
15
  client: FrakClient,
15
- params: DisplayEmbeddedWalletParamsType
16
+ params: DisplayEmbeddedWalletParamsType,
17
+ placement?: string
16
18
  ): Promise<DisplayEmbeddedWalletResultType> {
17
19
  return await client.request({
18
20
  method: "frak_displayEmbeddedWallet",
19
- params: [params, client.config.metadata],
21
+ params: placement
22
+ ? [params, client.config.metadata, placement]
23
+ : [params, client.config.metadata],
20
24
  });
21
25
  }