@frak-labs/core-sdk 0.2.1 → 1.0.0-beta.61e6fb99

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 (92) hide show
  1. package/README.md +1 -2
  2. package/cdn/bundle.js +3 -3
  3. package/dist/actions-Di4welXI.cjs +1 -0
  4. package/dist/actions-DyMkUe65.js +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-B_Uj-puh.d.ts} +249 -73
  14. package/dist/{computeLegacyProductId-b5cUWdAm.d.ts → index-ByVpu25D.d.cts} +249 -73
  15. package/dist/{siweAuthenticate-CnCZ7mok.d.ts → index-CGyEOo9J.d.cts} +122 -8
  16. package/dist/{siweAuthenticate-CVigMOxz.d.cts → index-Cdf5j2_W.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-B6pD2oA6.d.ts} +380 -46
  22. package/dist/{openSso-CMzwvaCa.d.ts → openSso-qjaccFd0.d.cts} +379 -45
  23. package/dist/sdkConfigStore-DvwFc6Ym.cjs +1 -0
  24. package/dist/sdkConfigStore-M37skmM8.js +1 -0
  25. package/dist/src-BqpqVHCq.cjs +13 -0
  26. package/dist/src-BxRYON49.js +13 -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/processReferral.test.ts +4 -8
  38. package/src/actions/referral/processReferral.ts +5 -11
  39. package/src/actions/referral/setupReferral.test.ts +79 -0
  40. package/src/actions/referral/setupReferral.ts +32 -0
  41. package/src/actions/trackPurchaseStatus.test.ts +32 -20
  42. package/src/actions/trackPurchaseStatus.ts +3 -5
  43. package/src/actions/wrapper/modalBuilder.test.ts +4 -2
  44. package/src/actions/wrapper/modalBuilder.ts +6 -8
  45. package/src/clients/createIFrameFrakClient.ts +233 -28
  46. package/src/clients/transports/iframeLifecycleManager.test.ts +14 -94
  47. package/src/clients/transports/iframeLifecycleManager.ts +35 -53
  48. package/src/index.ts +25 -5
  49. package/src/stubs/rrweb.ts +9 -0
  50. package/src/types/config.ts +19 -3
  51. package/src/types/index.ts +15 -1
  52. package/src/types/lifecycle/client.ts +29 -27
  53. package/src/types/lifecycle/iframe.ts +7 -8
  54. package/src/types/resolvedConfig.ts +138 -0
  55. package/src/types/rpc/displaySharingPage.ts +100 -0
  56. package/src/types/rpc/embedded/index.ts +1 -1
  57. package/src/types/rpc/interaction.ts +4 -0
  58. package/src/types/rpc/userReferralStatus.ts +20 -0
  59. package/src/types/rpc.ts +54 -5
  60. package/src/types/tracking.ts +36 -0
  61. package/src/utils/FrakContext.test.ts +151 -0
  62. package/src/utils/FrakContext.ts +67 -1
  63. package/src/utils/analytics/events/component.ts +58 -0
  64. package/src/utils/analytics/events/index.ts +20 -0
  65. package/src/utils/analytics/events/lifecycle.ts +26 -0
  66. package/src/utils/analytics/events/referral.ts +10 -0
  67. package/src/utils/analytics/index.ts +8 -0
  68. package/src/utils/{trackEvent.test.ts → analytics/trackEvent.test.ts} +22 -30
  69. package/src/utils/analytics/trackEvent.ts +34 -0
  70. package/src/utils/backendUrl.test.ts +2 -2
  71. package/src/utils/backendUrl.ts +1 -1
  72. package/src/utils/cache/index.ts +7 -0
  73. package/src/utils/cache/lruMap.test.ts +55 -0
  74. package/src/utils/cache/lruMap.ts +38 -0
  75. package/src/utils/cache/withCache.test.ts +168 -0
  76. package/src/utils/cache/withCache.ts +124 -0
  77. package/src/utils/inAppBrowser.ts +60 -0
  78. package/src/utils/index.ts +11 -5
  79. package/src/utils/mergeAttribution.test.ts +153 -0
  80. package/src/utils/mergeAttribution.ts +75 -0
  81. package/src/utils/sdkConfigStore.test.ts +405 -0
  82. package/src/utils/sdkConfigStore.ts +263 -0
  83. package/src/utils/sso.ts +3 -7
  84. package/dist/setupClient-BduY6Sym.cjs +0 -13
  85. package/dist/setupClient-ftmdQ-I8.js +0 -13
  86. package/dist/siweAuthenticate-BWmI2_TN.cjs +0 -1
  87. package/dist/siweAuthenticate-zczqxm0a.js +0 -1
  88. package/dist/trackEvent-CeLFVzZn.js +0 -1
  89. package/dist/trackEvent-Ew5r5zfI.cjs +0 -1
  90. package/src/utils/merchantId.test.ts +0 -653
  91. package/src/utils/merchantId.ts +0 -143
  92. package/src/utils/trackEvent.ts +0 -41
@@ -0,0 +1,263 @@
1
+ /**
2
+ * SDK config store — reactive singleton for the resolved merchant config.
3
+ *
4
+ * State lives directly on `window.__frakSdkConfig`.
5
+ * Reactivity is handled via the `frak:config` CustomEvent on `window`.
6
+ * Resolved configs are cached in localStorage (30 s TTL, stale-while-revalidate).
7
+ *
8
+ * Backend fetch responses are cached and deduplicated via `withCache`.
9
+ * Also owns the `frak-merchant-id` sessionStorage compatibility key.
10
+ */
11
+
12
+ import type { Language } from "../types/config";
13
+ import type {
14
+ MerchantConfigResponse,
15
+ SdkResolvedConfig,
16
+ } from "../types/resolvedConfig";
17
+ import { getBackendUrl } from "./backendUrl";
18
+ import { clearAllCache, withCache } from "./cache";
19
+
20
+ const GLOBAL_KEY = "__frakSdkConfig";
21
+ const CACHE_TTL = 30_000; // 30 seconds
22
+ const DEFAULT_CACHE_KEY = "frak-config-cache";
23
+ const MERCHANT_ID_KEY = "frak-merchant-id";
24
+
25
+ const cacheState = { key: DEFAULT_CACHE_KEY };
26
+
27
+ const isBrowser = typeof window !== "undefined";
28
+
29
+ type CacheEntry = { config: SdkResolvedConfig; timestamp: number };
30
+
31
+ declare global {
32
+ interface Window {
33
+ [GLOBAL_KEY]?: SdkResolvedConfig;
34
+ }
35
+ interface WindowEventMap {
36
+ "frak:config": CustomEvent<SdkResolvedConfig>;
37
+ }
38
+ }
39
+
40
+ function freshEmptyConfig(): SdkResolvedConfig {
41
+ return { isResolved: false, merchantId: "" };
42
+ }
43
+
44
+ // ---------------------------------------------------------------------------
45
+ // localStorage cache (with in-memory parsed copy)
46
+ // ---------------------------------------------------------------------------
47
+
48
+ let memoryEntry: CacheEntry | null = null;
49
+
50
+ function loadCacheEntry(): CacheEntry | null {
51
+ if (!isBrowser) return null;
52
+ try {
53
+ const raw = localStorage.getItem(cacheState.key);
54
+ if (!raw) return null;
55
+ const entry: CacheEntry = JSON.parse(raw);
56
+ if (!entry.config?.isResolved) return null;
57
+ memoryEntry = entry;
58
+ return entry;
59
+ } catch {
60
+ return null;
61
+ }
62
+ }
63
+
64
+ function readCache(): SdkResolvedConfig | undefined {
65
+ return (memoryEntry ?? loadCacheEntry())?.config;
66
+ }
67
+
68
+ function isCacheFresh(): boolean {
69
+ const entry = memoryEntry ?? loadCacheEntry();
70
+ if (!entry) return false;
71
+ return Date.now() - entry.timestamp < CACHE_TTL;
72
+ }
73
+
74
+ function writeCache(config: SdkResolvedConfig): void {
75
+ if (!isBrowser || !config.isResolved) return;
76
+ try {
77
+ const entry: CacheEntry = { config, timestamp: Date.now() };
78
+ localStorage.setItem(cacheState.key, JSON.stringify(entry));
79
+ memoryEntry = entry;
80
+ } catch {}
81
+ }
82
+
83
+ function removeCache(): void {
84
+ if (!isBrowser) return;
85
+ memoryEntry = null;
86
+ try {
87
+ localStorage.removeItem(cacheState.key);
88
+ } catch {}
89
+ }
90
+
91
+ // ---------------------------------------------------------------------------
92
+ // Initialise window-backed config (once per bundle boundary)
93
+ // ---------------------------------------------------------------------------
94
+
95
+ function initConfig(): void {
96
+ if (!isBrowser) return;
97
+ if (window[GLOBAL_KEY]) return;
98
+ window[GLOBAL_KEY] = readCache() ?? freshEmptyConfig();
99
+ }
100
+
101
+ initConfig();
102
+
103
+ // ---------------------------------------------------------------------------
104
+ // Helpers
105
+ // ---------------------------------------------------------------------------
106
+
107
+ function getConfig(): SdkResolvedConfig {
108
+ if (!isBrowser) return freshEmptyConfig();
109
+ return window[GLOBAL_KEY] ?? freshEmptyConfig();
110
+ }
111
+
112
+ function dispatch(config: SdkResolvedConfig): void {
113
+ if (!isBrowser) return;
114
+ window.dispatchEvent(new CustomEvent("frak:config", { detail: config }));
115
+ }
116
+
117
+ function getTargetDomain(domain?: string): string {
118
+ return domain ?? (isBrowser ? window.location.hostname : "");
119
+ }
120
+
121
+ // ---------------------------------------------------------------------------
122
+ // Merchant config fetching (resolve)
123
+ // ---------------------------------------------------------------------------
124
+
125
+ async function fetchFromBackend(
126
+ targetDomain: string,
127
+ walletUrl?: string,
128
+ lang?: Language
129
+ ): Promise<MerchantConfigResponse | undefined> {
130
+ try {
131
+ const backendUrl = getBackendUrl(walletUrl);
132
+ const langParam = lang ? `&lang=${encodeURIComponent(lang)}` : "";
133
+ const response = await fetch(
134
+ `${backendUrl}/user/merchant/resolve?domain=${encodeURIComponent(targetDomain)}${langParam}`
135
+ );
136
+
137
+ if (!response.ok) {
138
+ console.warn(
139
+ `[Frak SDK] Merchant lookup failed for domain ${targetDomain}: ${response.status}`
140
+ );
141
+ return undefined;
142
+ }
143
+
144
+ const data = (await response.json()) as MerchantConfigResponse;
145
+
146
+ // Write compatibility sessionStorage key
147
+ if (isBrowser) {
148
+ try {
149
+ sessionStorage.setItem(MERCHANT_ID_KEY, data.merchantId);
150
+ } catch {}
151
+ }
152
+
153
+ return data;
154
+ } catch (error) {
155
+ console.warn("[Frak SDK] Failed to fetch merchant config:", error);
156
+ return undefined;
157
+ }
158
+ }
159
+
160
+ // ---------------------------------------------------------------------------
161
+ // Public API
162
+ // ---------------------------------------------------------------------------
163
+
164
+ export const sdkConfigStore = {
165
+ getConfig,
166
+
167
+ get isResolved(): boolean {
168
+ return getConfig().isResolved;
169
+ },
170
+
171
+ get isCacheFresh(): boolean {
172
+ return isCacheFresh();
173
+ },
174
+
175
+ setCacheScope(domain: string, lang?: string): void {
176
+ const suffix = `${domain}:${lang ?? ""}`;
177
+ cacheState.key = `${DEFAULT_CACHE_KEY}:${suffix}`;
178
+ memoryEntry = null;
179
+ },
180
+
181
+ setConfig(config: SdkResolvedConfig): void {
182
+ if (isBrowser) window[GLOBAL_KEY] = config;
183
+ writeCache(config);
184
+ dispatch(config);
185
+
186
+ // Keep sessionStorage merchantId in sync
187
+ if (isBrowser && config.merchantId) {
188
+ try {
189
+ sessionStorage.setItem(MERCHANT_ID_KEY, config.merchantId);
190
+ } catch {}
191
+ }
192
+ },
193
+
194
+ reset(): void {
195
+ const next = readCache() ?? freshEmptyConfig();
196
+ if (isBrowser) window[GLOBAL_KEY] = next;
197
+ dispatch(next);
198
+ },
199
+
200
+ clearCache(): void {
201
+ removeCache();
202
+ clearAllCache();
203
+ if (isBrowser) {
204
+ try {
205
+ sessionStorage.removeItem(MERCHANT_ID_KEY);
206
+ } catch {}
207
+ }
208
+ },
209
+
210
+ resolve(
211
+ domain?: string,
212
+ walletUrl?: string,
213
+ lang?: Language
214
+ ): Promise<MerchantConfigResponse | undefined> {
215
+ const targetDomain = getTargetDomain(domain);
216
+ if (!targetDomain) {
217
+ return Promise.resolve(undefined);
218
+ }
219
+
220
+ const cacheKey = `sdkConfig:${targetDomain}:${lang ?? ""}`;
221
+
222
+ return withCache(
223
+ async () => {
224
+ const result = await fetchFromBackend(
225
+ targetDomain,
226
+ walletUrl,
227
+ lang
228
+ );
229
+ // Throw on failure so withCache doesn't cache undefined
230
+ if (!result) {
231
+ throw new Error("Config resolution returned empty");
232
+ }
233
+ return result;
234
+ },
235
+ { cacheKey, cacheTime: Number.POSITIVE_INFINITY }
236
+ ).catch(() => undefined);
237
+ },
238
+
239
+ getMerchantId(): string | undefined {
240
+ const config = getConfig();
241
+ if (config.isResolved && config.merchantId) {
242
+ return config.merchantId;
243
+ }
244
+
245
+ if (isBrowser) {
246
+ try {
247
+ return sessionStorage.getItem(MERCHANT_ID_KEY) ?? undefined;
248
+ } catch {}
249
+ }
250
+ return undefined;
251
+ },
252
+
253
+ async resolveMerchantId(
254
+ domain?: string,
255
+ walletUrl?: string
256
+ ): Promise<string | undefined> {
257
+ const fast = sdkConfigStore.getMerchantId();
258
+ if (fast) return fast;
259
+
260
+ const config = await sdkConfigStore.resolve(domain, walletUrl);
261
+ return config?.merchantId;
262
+ },
263
+ };
package/src/utils/sso.ts CHANGED
@@ -3,7 +3,7 @@ import type { PrepareSsoParamsType, SsoMetadata } from "../types";
3
3
  import { compressJsonToB64 } from "./compression/compress";
4
4
 
5
5
  export type AppSpecificSsoMetadata = SsoMetadata & {
6
- name: string;
6
+ name?: string;
7
7
  css?: string;
8
8
  };
9
9
 
@@ -43,7 +43,7 @@ export function generateSsoUrl(
43
43
  walletUrl: string,
44
44
  params: PrepareSsoParamsType,
45
45
  merchantId: string,
46
- name: string,
46
+ name: string | undefined,
47
47
  clientId: string,
48
48
  css?: string
49
49
  ): string {
@@ -114,13 +114,9 @@ export type CompressedSsoData = {
114
114
  m: string;
115
115
  // metadata
116
116
  md: {
117
- // merchant name
118
- n: string;
119
- // custom css
117
+ n?: string;
120
118
  css?: string;
121
- // logo
122
119
  l?: string;
123
- // home page link
124
120
  h?: string;
125
121
  };
126
122
  };
@@ -1,13 +0,0 @@
1
- const e=require(`./trackEvent-Ew5r5zfI.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.v();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(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 y=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:0:-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 b=(()=>{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 x(e){e?localStorage.setItem(r,e):localStorage.removeItem(r)}function S(t,n,r,i){let a=new URL(window.location.href),o=a.searchParams.get(`fmt`)??void 0;t.contentWindow?.postMessage({clientLifecycle:`handshake-response`,data:{token:n,currentUrl:window.location.href,pendingMergeToken:o,configDomain:i,clientId:e.v()}},r),o&&(a.searchParams.delete(`fmt`),window.history.replaceState({},``,a.toString()))}function C(e,t){try{let n=new URL(e);return n.searchParams.has(`u`)?(n.searchParams.delete(`u`),n.searchParams.append(`u`,window.location.href),t&&n.searchParams.append(`fmt`,t),n.toString()):e}catch{return e}}function w(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 T(e){return e.includes(`/common/social`)}function E(e,t,n,r){if(c(t)){let i=C(t,r);s(i,{onFallback:()=>{e.contentWindow?.postMessage({clientLifecycle:`deep-link-failed`,data:{originalUrl:i}},n)}})}else if(b&&T(t))w(r);else{let e=C(t,r);window.location.href=e}}function D({iframe:e,targetOrigin:n,configDomain:i}){let a=new t.Deferred;return{handleEvent:async t=>{if(!(`iframeLifecycle`in t))return;let{iframeLifecycle:o,data:s}=t;switch(o){case`connected`:a.resolve(!0);break;case`do-backup`:x(s.backup);break;case`remove-backup`:localStorage.removeItem(r);break;case`show`:case`hide`:g({iframe:e,isVisible:o===`show`});break;case`handshake`:S(e,s.token,n,i);break;case`redirect`:E(e,s.baseRedirectUrl,n,s.mergeToken);break}},isConnected:a.promise}}function O({config:r,iframe:i}){let a=r?.walletUrl??`https://wallet.frak.id`,o=D({iframe:i,targetOrigin:a,configDomain:r.domain}),s=new y(r,i);if(!i.contentWindow)throw new t.FrakRpcError(t.RpcErrorCodes.configError,`The iframe does not have a content window`);let c=(0,t.createRpcClient)({emittingTransport:i.contentWindow,listeningTransport:window,targetOrigin:a,middleware:[{async onRequest(e,n){if(!await o.isConnected)throw new t.FrakRpcError(t.RpcErrorCodes.clientNotConnected,`The iframe provider isn't connected yet`);return n}},{onRequest(e,t){return s.setLastRequest(e),t},onResponse(e,t){return s.setLastResponse(e,t),t}}],lifecycleHandlers:{iframeLifecycle:async(e,t)=>{await o.handleEvent(e)}}}),l=k(c,o),u=async()=>{l(),c.cleanup(),i.remove()},d;console.log(`[Frak SDK] Initializing OpenPanel`),d=new n.OpenPanel({apiUrl:`https://op-api.gcp.frak.id`,clientId:`f305d11d-b93b-487c-80d4-92deb7903e98`,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.v()}),!0)}),d.setGlobalProperties({sdkVersion:`0.2.1`,userAnonymousClientId:e.v()}),d.init();let f=A({config:r,rpcClient:c,lifecycleManager:o}).then(()=>s.updateSetupStatus(!0));return{config:r,debugInfo:s,waitForConnection:o.isConnected,waitForSetup:f,request:c.request,listenerRequest:c.listen,destroy:u,openPanel:d}}function k(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 A({config:e,rpcClient:t,lifecycleManager:n}){await n.isConnected,v(t,n.isConnected);async function i(){let n=e.customizations?.css;if(!n)return;let r={clientLifecycle:`modal-css`,data:{cssLink:n}};t.sendLifecycle(r)}async function a(){let n=e.customizations?.i18n;if(!n)return;let r={clientLifecycle:`modal-i18n`,data:{i18n:n}};t.sendLifecycle(r)}async function o(){if(typeof window>`u`)return;let e=window.localStorage.getItem(r);if(!e)return;let n={clientLifecycle:`restore-backup`,data:{backup:e}};t.sendLifecycle(n)}await Promise.allSettled([i(),a(),o()])}async function j({config:e}){let t=M(e),n=await h({config:t});if(!n){console.error(`Failed to create iframe`);return}let r=O({config:t,iframe:n});if(await r.waitForSetup,!await r.waitForConnection){console.error(`Failed to connect to client`);return}return r}function M(e){let t=u(e.metadata?.currency);return{...e,metadata:{...e.metadata,currency:t}}}Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`g`,{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,`h`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return O}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return j}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return u}});
@@ -1,13 +0,0 @@
1
- import{v as e}from"./trackEvent-CeLFVzZn.js";import{Deferred as t,FrakRpcError as n,RpcErrorCodes as r,createRpcClient as i}from"@frak-labs/frame-connector";import{OpenPanel as a}from"@openpanel/web";const o=`nexus-wallet-backup`,s=`frakwallet://`;function c(){let e=navigator.userAgent;return/Android/i.test(e)&&/Chrome\/\d+/i.test(e)}function l(e){return`intent://${e.slice(13)}#Intent;scheme=frakwallet;end`}function u(e,t){let n=t?.timeout??2500,r=!1,i=()=>{document.hidden&&(r=!0)};document.addEventListener(`visibilitychange`,i);let a=c()&&d(e)?l(e):e;window.location.href=a,setTimeout(()=>{document.removeEventListener(`visibilitychange`,i),r||t?.onFallback?.()},n)}function d(e){return e.startsWith(s)}const f={eur:`fr-FR`,usd:`en-US`,gbp:`en-GB`};function p(e){return e&&e in f?e:`eur`}function m(e){return e?f[e]??f.eur:f.eur}function h(e,t){let n=m(t),r=p(t);return e.toLocaleString(n,{style:`currency`,currency:r,minimumFractionDigits:0,maximumFractionDigits:2})}function g(e){return e?`${e}Amount`:`eurAmount`}const _={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 v({walletBaseUrl:t,config:n}){let r=document.querySelector(`#frak-wallet`);r&&r.remove();let i=document.createElement(`iframe`);i.id=_.id,i.name=_.name,i.allow=_.allow,i.style.zIndex=_.style.zIndex.toString(),y({iframe:i,isVisible:!1});let a=n?.walletUrl??t??`https://wallet.frak.id`,o=e();return i.src=`${a}/listener?clientId=${encodeURIComponent(o)}`,new Promise(e=>{i.addEventListener(`load`,()=>e(i)),document.body.appendChild(i)})}function y({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 b(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 x(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 S=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:0:-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(),r=this.getNavigatorInfo(),i=`Unknown`;return e instanceof n?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: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: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 C=(()=>{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 w(e){e?localStorage.setItem(o,e):localStorage.removeItem(o)}function T(t,n,r,i){let a=new URL(window.location.href),o=a.searchParams.get(`fmt`)??void 0;t.contentWindow?.postMessage({clientLifecycle:`handshake-response`,data:{token:n,currentUrl:window.location.href,pendingMergeToken:o,configDomain:i,clientId:e()}},r),o&&(a.searchParams.delete(`fmt`),window.history.replaceState({},``,a.toString()))}function E(e,t){try{let n=new URL(e);return n.searchParams.has(`u`)?(n.searchParams.delete(`u`),n.searchParams.append(`u`,window.location.href),t&&n.searchParams.append(`fmt`,t),n.toString()):e}catch{return e}}function D(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 O(e){return e.includes(`/common/social`)}function k(e,t,n,r){if(d(t)){let i=E(t,r);u(i,{onFallback:()=>{e.contentWindow?.postMessage({clientLifecycle:`deep-link-failed`,data:{originalUrl:i}},n)}})}else if(C&&O(t))D(r);else{let e=E(t,r);window.location.href=e}}function A({iframe:e,targetOrigin:n,configDomain:r}){let i=new t;return{handleEvent:async t=>{if(!(`iframeLifecycle`in t))return;let{iframeLifecycle:a,data:s}=t;switch(a){case`connected`:i.resolve(!0);break;case`do-backup`:w(s.backup);break;case`remove-backup`:localStorage.removeItem(o);break;case`show`:case`hide`:y({iframe:e,isVisible:a===`show`});break;case`handshake`:T(e,s.token,n,r);break;case`redirect`:k(e,s.baseRedirectUrl,n,s.mergeToken);break}},isConnected:i.promise}}function j({config:t,iframe:o}){let s=t?.walletUrl??`https://wallet.frak.id`,c=A({iframe:o,targetOrigin:s,configDomain:t.domain}),l=new S(t,o);if(!o.contentWindow)throw new n(r.configError,`The iframe does not have a content window`);let u=i({emittingTransport:o.contentWindow,listeningTransport:window,targetOrigin:s,middleware:[{async onRequest(e,t){if(!await c.isConnected)throw new n(r.clientNotConnected,`The iframe provider isn't connected yet`);return t}},{onRequest(e,t){return l.setLastRequest(e),t},onResponse(e,t){return l.setLastResponse(e,t),t}}],lifecycleHandlers:{iframeLifecycle:async(e,t)=>{await c.handleEvent(e)}}}),d=M(u,c),f=async()=>{d(),u.cleanup(),o.remove()},p;console.log(`[Frak SDK] Initializing OpenPanel`),p=new a({apiUrl:`https://op-api.gcp.frak.id`,clientId:`f305d11d-b93b-487c-80d4-92deb7903e98`,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()}),!0)}),p.setGlobalProperties({sdkVersion:`0.2.1`,userAnonymousClientId:e()}),p.init();let m=N({config:t,rpcClient:u,lifecycleManager:c}).then(()=>l.updateSetupStatus(!0));return{config:t,debugInfo:l,waitForConnection:c.isConnected,waitForSetup:m,request:u.request,listenerRequest:u.listen,destroy:f,openPanel:p}}function M(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 N({config:e,rpcClient:t,lifecycleManager:n}){await n.isConnected,x(t,n.isConnected);async function r(){let n=e.customizations?.css;if(!n)return;let r={clientLifecycle:`modal-css`,data:{cssLink:n}};t.sendLifecycle(r)}async function i(){let n=e.customizations?.i18n;if(!n)return;let r={clientLifecycle:`modal-i18n`,data:{i18n:n}};t.sendLifecycle(r)}async function a(){if(typeof window>`u`)return;let e=window.localStorage.getItem(o);if(!e)return;let n={clientLifecycle:`restore-backup`,data:{backup:e}};t.sendLifecycle(n)}await Promise.allSettled([r(),i(),a()])}async function P({config:e}){let t=F(e),n=await v({config:t});if(!n){console.error(`Failed to create iframe`);return}let r=j({config:t,iframe:n});if(await r.waitForSetup,!await r.waitForConnection){console.error(`Failed to connect to client`);return}return r}function F(e){let t=p(e.metadata?.currency);return{...e,metadata:{...e.metadata,currency:t}}}export{v as a,h as c,f as d,c as f,s as g,u as h,_ as i,m as l,l as m,j as n,b as o,d as p,S as r,g as s,P as t,p as u};
@@ -1 +0,0 @@
1
- const e=require(`./trackEvent-Ew5r5zfI.cjs`);let t=require(`viem`),n=require(`@frak-labs/frame-connector`),r=require(`viem/siwe`);async function i(e,t){return await e.request({method:`frak_displayEmbeddedWallet`,params:[t,e.config.metadata]})}async function a(e,{steps:t,metadata:n}){return await e.request({method:`frak_displayModal`,params:[t,n,e.config.metadata]})}async function o(t){if(typeof window>`u`)return;let n=e.v();if(!n)return;let r=await e.r();if(!r)return;let i=`frak-identity-ensured-${r}`;if(!window.sessionStorage.getItem(i))try{let a=e.l();(await fetch(`${a}/user/identity/ensure`,{method:`POST`,headers:{Accept:`application/json`,"Content-Type":`application/json`,"x-wallet-sdk-auth":t,"x-frak-client-id":n},body:JSON.stringify({merchantId:r})})).ok&&window.sessionStorage.setItem(i,`1`)}catch{}}async function s(e){return await e.request({method:`frak_getMerchantInformation`})}async function c(e,t){let{metadata:n,customizations:r}=e.config;return await e.request({method:`frak_prepareSso`,params:[t,n.name,r?.css]})}async function l(t,n){try{await t.request({method:`frak_sendInteraction`,params:[n,{clientId:e.v()}]})}catch{console.warn(`[Frak SDK] Failed to send interaction:`,n.type)}}function u(t,n,r){let i=typeof window<`u`?window.location.href:void 0;return e.s(n)?(e.t(t,`user_referred_started`,{properties:{referrerClientId:n.c,walletStatus:r?.key}}),l(t,{type:`arrival`,referrerClientId:n.c,referrerMerchantId:n.m,referralTimestamp:n.t,landingUrl:i}),!0):e.o(n)?(e.t(t,`user_referred_started`,{properties:{referrer:n.r,walletStatus:r?.key}}),l(t,{type:`arrival`,referrerWallet:n.r,landingUrl:i}),!0):!1}function d(t){let n=e.v();return n?{v:2,c:n,m:t,t:Math.floor(Date.now()/1e3)}:null}function f(n,r){return e.s(n)?e.v()===n.c:e.o(n)&&r?.wallet?(0,t.isAddressEqual)(n.r,r.wallet):!1}function p(t,{walletStatus:n,frakContext:r,options:i}){if(!r)return`no-referrer`;if(f(r,n))return`self-referral`;if(!u(t,r,n))return`no-referrer`;let a=e.s(r)?r.m:i?.merchantId,o=i?.alwaysAppendUrl&&a?d(a):null;return e.a.replaceUrl({url:window.location?.href,context:o}),e.t(t,`user_referred_completed`,{properties:{status:`success`}}),`success`}async function m(t,{options:n}={}){let r=e.a.parse({url:window.location.href}),i=await g(t);try{return p(t,{walletStatus:i,frakContext:r,options:n})}catch(e){console.warn(`Error processing referral`,{error:e})}}async function h(t){if(typeof window>`u`){console.warn(`[Frak] No window found, can't track purchase`);return}let n=window.sessionStorage.getItem(`frak-wallet-interaction-token`),r=e.v();if(!n&&!r){console.warn(`[Frak] No identity found, skipping purchase check`);return}let i=window.sessionStorage.getItem(`frak-merchant-id`),a=t.merchantId??i??await e.r();if(!a){console.warn(`[Frak] No merchant id found, skipping purchase check`);return}let o={Accept:`application/json`,"Content-Type":`application/json`};n&&(o[`x-wallet-sdk-auth`]=n),r&&(o[`x-frak-client-id`]=r);let s=e.l();await fetch(`${s}/user/track/purchase`,{method:`POST`,headers:o,body:JSON.stringify({customerId:t.customerId,orderId:t.orderId,token:t.token,merchantId:a})})}function g(e,t){if(!t)return e.request({method:`frak_listenToWalletStatus`}).then(t=>(_(e,t),t));let r=new n.Deferred,i=!1;return e.listenerRequest({method:`frak_listenToWalletStatus`},n=>{_(e,n),t(n),i||=(r.resolve(n),!0)}),r.promise}function _(e,t){typeof window>`u`||(e.openPanel?.setGlobalProperties({wallet:t.wallet??null}),t.interactionToken?(window.sessionStorage.setItem(`frak-wallet-interaction-token`,t.interactionToken),o(t.interactionToken)):window.sessionStorage.removeItem(`frak-wallet-interaction-token`))}function v(e,{metadata:t,login:n}){return y(e,{steps:{login:n??{}},metadata:t})}function y(e,t){function n(n){return y(e,{...t,steps:{...t.steps,sendTransaction:n}})}function r(n){return y(e,{...t,steps:{...t.steps,final:{...n,action:{key:`reward`}}}})}function i(n,r){return y(e,{...t,steps:{...t.steps,final:{...r,action:{key:`sharing`,options:n}}}})}async function o(n){return n&&(t.metadata=n(t.metadata??{})),await a(e,t)}return{params:t,sendTx:n,reward:r,sharing:i,display:o}}async function b(e,{tx:t,metadata:n}){return(await a(e,{metadata:n,steps:{login:{},sendTransaction:{tx:t}}})).sendTransaction}async function x(e,{siwe:t,metadata:n}){let i=e.config?.domain??window.location.host,o=t?.statement??`I confirm that I want to use my Frak wallet on: ${e.config.metadata.name}`;return(await a(e,{metadata:n,steps:{login:{},siweAuthenticate:{siwe:{...t,statement:o,nonce:t?.nonce??(0,r.generateSiweNonce)(),uri:t?.uri??`https://${i}`,version:t?.version??`1`,domain:i}}}})).siweAuthenticate}Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return x}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return s}});
@@ -1 +0,0 @@
1
- import{a as e,l as t,o as n,r,s as i,t as a,v as o}from"./trackEvent-CeLFVzZn.js";import{isAddressEqual as s}from"viem";import{Deferred as c}from"@frak-labs/frame-connector";import{generateSiweNonce as l}from"viem/siwe";async function u(e,t){return await e.request({method:`frak_displayEmbeddedWallet`,params:[t,e.config.metadata]})}async function d(e,{steps:t,metadata:n}){return await e.request({method:`frak_displayModal`,params:[t,n,e.config.metadata]})}async function f(e){if(typeof window>`u`)return;let n=o();if(!n)return;let i=await r();if(!i)return;let a=`frak-identity-ensured-${i}`;if(!window.sessionStorage.getItem(a))try{let r=t();(await fetch(`${r}/user/identity/ensure`,{method:`POST`,headers:{Accept:`application/json`,"Content-Type":`application/json`,"x-wallet-sdk-auth":e,"x-frak-client-id":n},body:JSON.stringify({merchantId:i})})).ok&&window.sessionStorage.setItem(a,`1`)}catch{}}async function p(e){return await e.request({method:`frak_getMerchantInformation`})}async function m(e,t){let{metadata:n,customizations:r}=e.config;return await e.request({method:`frak_prepareSso`,params:[t,n.name,r?.css]})}async function h(e,t){try{await e.request({method:`frak_sendInteraction`,params:[t,{clientId:o()}]})}catch{console.warn(`[Frak SDK] Failed to send interaction:`,t.type)}}function g(e,t,r){let o=typeof window<`u`?window.location.href:void 0;return i(t)?(a(e,`user_referred_started`,{properties:{referrerClientId:t.c,walletStatus:r?.key}}),h(e,{type:`arrival`,referrerClientId:t.c,referrerMerchantId:t.m,referralTimestamp:t.t,landingUrl:o}),!0):n(t)?(a(e,`user_referred_started`,{properties:{referrer:t.r,walletStatus:r?.key}}),h(e,{type:`arrival`,referrerWallet:t.r,landingUrl:o}),!0):!1}function _(e){let t=o();return t?{v:2,c:t,m:e,t:Math.floor(Date.now()/1e3)}:null}function v(e,t){return i(e)?o()===e.c:n(e)&&t?.wallet?s(e.r,t.wallet):!1}function y(t,{walletStatus:n,frakContext:r,options:o}){if(!r)return`no-referrer`;if(v(r,n))return`self-referral`;if(!g(t,r,n))return`no-referrer`;let s=i(r)?r.m:o?.merchantId,c=o?.alwaysAppendUrl&&s?_(s):null;return e.replaceUrl({url:window.location?.href,context:c}),a(t,`user_referred_completed`,{properties:{status:`success`}}),`success`}async function b(t,{options:n}={}){let r=e.parse({url:window.location.href}),i=await S(t);try{return y(t,{walletStatus:i,frakContext:r,options:n})}catch(e){console.warn(`Error processing referral`,{error:e})}}async function x(e){if(typeof window>`u`){console.warn(`[Frak] No window found, can't track purchase`);return}let n=window.sessionStorage.getItem(`frak-wallet-interaction-token`),i=o();if(!n&&!i){console.warn(`[Frak] No identity found, skipping purchase check`);return}let a=window.sessionStorage.getItem(`frak-merchant-id`),s=e.merchantId??a??await r();if(!s){console.warn(`[Frak] No merchant id found, skipping purchase check`);return}let c={Accept:`application/json`,"Content-Type":`application/json`};n&&(c[`x-wallet-sdk-auth`]=n),i&&(c[`x-frak-client-id`]=i);let l=t();await fetch(`${l}/user/track/purchase`,{method:`POST`,headers:c,body:JSON.stringify({customerId:e.customerId,orderId:e.orderId,token:e.token,merchantId:s})})}function S(e,t){if(!t)return e.request({method:`frak_listenToWalletStatus`}).then(t=>(C(e,t),t));let n=new c,r=!1;return e.listenerRequest({method:`frak_listenToWalletStatus`},i=>{C(e,i),t(i),r||=(n.resolve(i),!0)}),n.promise}function C(e,t){typeof window>`u`||(e.openPanel?.setGlobalProperties({wallet:t.wallet??null}),t.interactionToken?(window.sessionStorage.setItem(`frak-wallet-interaction-token`,t.interactionToken),f(t.interactionToken)):window.sessionStorage.removeItem(`frak-wallet-interaction-token`))}function w(e,{metadata:t,login:n}){return T(e,{steps:{login:n??{}},metadata:t})}function T(e,t){function n(n){return T(e,{...t,steps:{...t.steps,sendTransaction:n}})}function r(n){return T(e,{...t,steps:{...t.steps,final:{...n,action:{key:`reward`}}}})}function i(n,r){return T(e,{...t,steps:{...t.steps,final:{...r,action:{key:`sharing`,options:n}}}})}async function a(n){return n&&(t.metadata=n(t.metadata??{})),await d(e,t)}return{params:t,sendTx:n,reward:r,sharing:i,display:a}}async function E(e,{tx:t,metadata:n}){return(await d(e,{metadata:n,steps:{login:{},sendTransaction:{tx:t}}})).sendTransaction}async function D(e,{siwe:t,metadata:n}){let r=e.config?.domain??window.location.host,i=t?.statement??`I confirm that I want to use my Frak wallet on: ${e.config.metadata.name}`;return(await d(e,{metadata:n,steps:{login:{},siweAuthenticate:{siwe:{...t,statement:i,nonce:t?.nonce??l(),uri:t?.uri??`https://${r}`,version:t?.version??`1`,domain:r}}}})).siweAuthenticate}export{x as a,h as c,f as d,d as f,S as i,m as l,E as n,b as o,u as p,w as r,y as s,D as t,p as u};
@@ -1 +0,0 @@
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(h({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 h(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 g=`menubar=no,status=no,scrollbars=no,fullscreen=no,width=500, height=800`,_=`frak-sso`;async function v(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);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 y=`https://backend.frak.id`;function b(e){return e.includes(`localhost:3000`)||e.includes(`localhost:3010`)}function x(e){return b(e)?`http://localhost:3030`:e.includes(`wallet-dev.frak.id`)||e.includes(`wallet.gcp-dev.frak.id`)?`https://backend.gcp-dev.frak.id`:y}function S(e){if(e)return x(e);if(typeof window<`u`){let e=window.FrakSetup?.client?.config?.walletUrl;if(e)return x(e)}return y}function C(e){return a(f(e))}function w(e){return`r`in e&&!(`v`in e)}function T(e){return`v`in e&&e.v===2}const E=`fCtx`;function D(e){if(e)try{return T(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 O(t){if(!(!t||t.length===0))try{let r=C(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 k({url:e}){if(!e)return null;let t=new URL(e).searchParams.get(E);return t?O(t):null}function A({url:e,context:t}){if(!e)return null;let n=D(t);if(!n)return null;let r=new URL(e);return r.searchParams.set(E,n),r.toString()}function j(e){let t=new URL(e);return t.searchParams.delete(E),t.toString()}function M({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?j(n):A({url:n,context:t}),r&&window.history.replaceState(null,``,r.toString())}const N={compress:D,decompress:O,parse:k,update:A,remove:j,replaceUrl:M},P=`frak-merchant-id`;let F,I;async function L(e,t){if(F)return F;if(typeof window<`u`){let e=window.sessionStorage.getItem(P);if(e)return F=e,e}if(I)return I;I=R(e,t);let n=await I;return I=void 0,n}async function R(e,t){let n=e??(typeof window<`u`?window.location.hostname:``);if(n)try{let e=S(t),r=await fetch(`${e}/user/merchant/resolve?domain=${encodeURIComponent(n)}`);if(!r.ok){console.warn(`[Frak SDK] Merchant lookup failed for domain ${n}: ${r.status}`);return}let i=await r.json();return F=i.merchantId,typeof window<`u`&&window.sessionStorage.setItem(P,i.merchantId),F}catch(e){console.warn(`[Frak SDK] Failed to fetch merchantId:`,e);return}}function z(){F=void 0,I=void 0,typeof window<`u`&&window.sessionStorage.removeItem(P)}async function B(e,t){return e.metadata?.merchantId?e.metadata.merchantId:L(void 0,t)}function V(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{u as _,N as a,C as c,g as d,_ as f,d as g,f as h,B as i,S as l,p as m,z as n,w as o,m as p,L as r,T as s,V as t,v as u,l as v};
@@ -1 +0,0 @@
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)?`http://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}function v(e){return(0,t.jsonDecode)(s(e))}function y(e){return`r`in e&&!(`v`in e)}function b(e){return`v`in e&&e.v===2}const x=`fCtx`;function S(t){if(t)try{return b(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 C(t){if(!(!t||t.length===0))try{let n=v(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 w({url:e}){if(!e)return null;let t=new URL(e).searchParams.get(x);return t?C(t):null}function T({url:e,context:t}){if(!e)return null;let n=S(t);if(!n)return null;let r=new URL(e);return r.searchParams.set(x,n),r.toString()}function E(e){let t=new URL(e);return t.searchParams.delete(x),t.toString()}function D({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?E(n):T({url:n,context:t}),r&&window.history.replaceState(null,``,r.toString())}const O={compress:S,decompress:C,parse:w,update:T,remove:E,replaceUrl:D},k=`frak-merchant-id`;let A,j;async function M(e,t){if(A)return A;if(typeof window<`u`){let e=window.sessionStorage.getItem(k);if(e)return A=e,e}if(j)return j;j=N(e,t);let n=await j;return j=void 0,n}async function N(e,t){let n=e??(typeof window<`u`?window.location.hostname:``);if(n)try{let e=_(t),r=await fetch(`${e}/user/merchant/resolve?domain=${encodeURIComponent(n)}`);if(!r.ok){console.warn(`[Frak SDK] Merchant lookup failed for domain ${n}: ${r.status}`);return}let i=await r.json();return A=i.merchantId,typeof window<`u`&&window.sessionStorage.setItem(k,i.merchantId),A}catch(e){console.warn(`[Frak SDK] Failed to fetch merchantId:`,e);return}}function P(){A=void 0,j=void 0,typeof window<`u`&&window.sessionStorage.removeItem(k)}async function F(e,t){return e.metadata?.merchantId?e.metadata.merchantId:M(void 0,t)}function I(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 a}}),Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return O}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`g`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`h`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return F}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return P}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return M}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return b}}),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 i}});