@frak-labs/core-sdk 0.2.1-beta.d04602ec → 0.2.1-beta.eb3cff34

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 (45) hide show
  1. package/cdn/bundle.js +3 -55
  2. package/dist/actions-D4aBXbdp.cjs +1 -0
  3. package/dist/actions-Dq_uN-wn.js +1 -0
  4. package/dist/actions.cjs +1 -1
  5. package/dist/actions.d.cts +3 -3
  6. package/dist/actions.d.ts +3 -3
  7. package/dist/actions.js +1 -1
  8. package/dist/bundle.cjs +1 -1
  9. package/dist/bundle.d.cts +4 -4
  10. package/dist/bundle.d.ts +4 -4
  11. package/dist/bundle.js +1 -1
  12. package/dist/{computeLegacyProductId-fKvxbC4k.d.ts → index-BV5D9DsW.d.ts} +1 -1
  13. package/dist/{siweAuthenticate-Dc_Yg9Bg.d.cts → index-BphwTmKA.d.cts} +22 -2
  14. package/dist/{computeLegacyProductId-rYIvY4c3.d.cts → index-Dwmo109y.d.cts} +1 -1
  15. package/dist/{siweAuthenticate-Ddhl-o4N.d.ts → index-_f8EuN_1.d.ts} +22 -2
  16. package/dist/index.cjs +1 -1
  17. package/dist/index.d.cts +3 -3
  18. package/dist/index.d.ts +3 -3
  19. package/dist/index.js +1 -1
  20. package/dist/{openSso-CMZM06uR.d.ts → openSso-BwEK2M98.d.cts} +31 -4
  21. package/dist/{openSso-CebB8mFv.d.cts → openSso-C1Wzl5-i.d.ts} +31 -4
  22. package/dist/src-B3Dusips.cjs +13 -0
  23. package/dist/src-CnnhYPyK.js +13 -0
  24. package/dist/trackEvent-BqJqRZ-u.cjs +1 -0
  25. package/dist/trackEvent-Bqq4jd6R.js +1 -0
  26. package/package.json +9 -10
  27. package/src/actions/getMergeToken.ts +33 -0
  28. package/src/actions/index.ts +1 -0
  29. package/src/clients/createIFrameFrakClient.ts +3 -2
  30. package/src/clients/transports/iframeLifecycleManager.test.ts +14 -14
  31. package/src/clients/transports/iframeLifecycleManager.ts +35 -9
  32. package/src/stubs/rrweb.ts +9 -0
  33. package/src/types/lifecycle/iframe.ts +7 -0
  34. package/src/types/resolvedConfig.ts +6 -0
  35. package/src/types/rpc/displaySharingPage.ts +5 -0
  36. package/src/types/rpc/embedded/index.ts +1 -1
  37. package/src/types/rpc.ts +12 -0
  38. package/src/utils/cache/withCache.test.ts +6 -0
  39. package/src/utils/cache/withCache.ts +19 -0
  40. package/dist/setupClient-B_XMB52l.cjs +0 -13
  41. package/dist/setupClient-jYx-fbxB.js +0 -13
  42. package/dist/siweAuthenticate-CWcVvP-G.cjs +0 -1
  43. package/dist/siweAuthenticate-DQfdb5UQ.js +0 -1
  44. package/dist/trackEvent-Ce1XlsIE.js +0 -1
  45. package/dist/trackEvent-CvbJTTqA.cjs +0 -1
@@ -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,S=new v(1024);async function C(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=S.get(t);if(r&&Date.now()-r<1e3)throw Error(`Cache: ${t} recently failed, backing off`);let i=y.get(t);i||(i=e(),y.set(t,i));try{let e=await i;return b.set(t,{data:e,created:Date.now()}),S.delete(t),e}catch(e){throw S.set(t,Date.now()),e}finally{y.delete(t)}}function w(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 T(){y.clear(),b.clear(),S.clear()}function E(e){return(0,t.jsonDecode)(s(e))}function D(e){return`r`in e&&!(`v`in e)}function O(e){return`v`in e&&e.v===2}const k=`fCtx`;function A(t){if(t)try{return O(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 j(t){if(!(!t||t.length===0))try{let n=E(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 M({url:e}){if(!e)return null;let t=new URL(e).searchParams.get(k);return t?j(t):null}function N({url:e,context:t}){if(!e)return null;let n=A(t);if(!n)return null;let r=new URL(e);return r.searchParams.set(k,n),r.toString()}function P(e){let t=new URL(e);return t.searchParams.delete(k),t.toString()}function ee({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?P(n):N({url:n,context:t}),r&&window.history.replaceState(null,``,r.toString())}const F={compress:A,decompress:j,parse:M,update:N,remove:P,replaceUrl:ee},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(),T(),B)try{sessionStorage.removeItem(R)}catch{}},resolve(e,t,n){let r=Z(e);return r?C(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 te(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 O}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return w}}),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 D}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return C}}),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 E}}),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 T}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return te}}),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}});
@@ -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 te(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 _=`https://backend.frak.id`;function v(e){return e.includes(`localhost:3000`)||e.includes(`localhost:3010`)}function y(e){return v(e)?`https://localhost:3030`:e.includes(`wallet-dev.frak.id`)||e.includes(`wallet.gcp-dev.frak.id`)?`https://backend.gcp-dev.frak.id`:_}function b(e){if(e)return y(e);if(typeof window<`u`){let e=window.FrakSetup?.client?.config?.walletUrl;if(e)return y(e)}return _}var x=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 S=new x(1024),C=new x(1024),w=3e4,T=new x(1024);async function E(e,{cacheKey:t,cacheTime:n=w}){if(n>0){let e=C.get(t);if(e&&Date.now()-e.created<n)return e.data}let r=T.get(t);if(r&&Date.now()-r<1e3)throw Error(`Cache: ${t} recently failed, backing off`);let i=S.get(t);i||(i=e(),S.set(t,i));try{let e=await i;return C.set(t,{data:e,created:Date.now()}),T.delete(t),e}catch(e){throw T.set(t,Date.now()),e}finally{S.delete(t)}}function D(e){return{clear:()=>{S.delete(e),C.delete(e)},has:(t=w)=>{let n=C.get(e);return n?Date.now()-n.created<t:!1}}}function O(){S.clear(),C.clear(),T.clear()}function k(e){return a(f(e))}function ne(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 L({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 R={compress:M,decompress:N,parse:P,update:F,remove:I,replaceUrl:L},z=`__frakSdkConfig`,B=`frak-config-cache`,V=`frak-merchant-id`,H={key:B},U=typeof window<`u`;function W(){return{isResolved:!1,merchantId:``}}let G=null;function K(){if(!U)return null;try{let e=localStorage.getItem(H.key);if(!e)return null;let t=JSON.parse(e);return t.config?.isResolved?(G=t,t):null}catch{return null}}function q(){return(G??K())?.config}function J(){let e=G??K();return e?Date.now()-e.timestamp<3e4:!1}function Y(e){if(!(!U||!e.isResolved))try{let t={config:e,timestamp:Date.now()};localStorage.setItem(H.key,JSON.stringify(t)),G=t}catch{}}function X(){if(U){G=null;try{localStorage.removeItem(H.key)}catch{}}}function re(){U&&(window[z]||(window[z]=q()??W()))}re();function Z(){return U?window[z]??W():W()}function Q(e){U&&window.dispatchEvent(new CustomEvent(`frak:config`,{detail:e}))}function ie(e){return e??(U?window.location.hostname:``)}async function ae(e,t,n){try{let r=b(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(U)try{sessionStorage.setItem(V,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 J()},setCacheScope(e,t){H.key=`${B}:${`${e}:${t??``}`}`,G=null},setConfig(e){if(U&&(window[z]=e),Y(e),Q(e),U&&e.merchantId)try{sessionStorage.setItem(V,e.merchantId)}catch{}},reset(){let e=q()??W();U&&(window[z]=e),Q(e)},clearCache(){if(X(),O(),U)try{sessionStorage.removeItem(V)}catch{}},resolve(e,t,n){let r=ie(e);return r?E(async()=>{let e=await ae(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(U)try{return sessionStorage.getItem(V)??void 0}catch{}},async resolveMerchantId(e,t){return $.getMerchantId()||(await $.resolve(e,t))?.merchantId}};function oe(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,te as d,h as f,f as g,p as h,ne as i,E as l,m,$ as n,k as o,g as p,R as r,O as s,oe as t,b as u,u as v,l as y};
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.d04602ec",
14
+ "version": "0.2.1-beta.eb3cff34",
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.d04602ec",
94
+ "@frak-labs/frame-connector": "0.2.0-beta.eb3cff34",
95
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
101
  "@types/jsdom": "^28.0.0",
103
- "@types/node": "^24.10.13",
104
- "@vitest/coverage-v8": "^4.1.0",
105
- "@vitest/ui": "^4.1.0",
102
+ "@types/node": "^25.6.0",
103
+ "@vitest/coverage-v8": "^4.1.4",
104
+ "@vitest/ui": "^4.1.4",
106
105
  "jsdom": "^29.0.0",
107
- "tsdown": "^0.20.3",
108
- "typescript": "^5.9.3",
109
- "viem": "^2.39.0",
110
- "vitest": "^4.1.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
  }
@@ -0,0 +1,33 @@
1
+ import type { FrakClient } from "../types";
2
+ import { withCache } from "../utils/cache";
3
+
4
+ /**
5
+ * Fetch a merge token for the current anonymous identity.
6
+ *
7
+ * Used by in-app browser redirect flows to preserve identity
8
+ * when switching from a WebView to the system browser.
9
+ * The token is appended as `?fmt=` to the redirect URL.
10
+ *
11
+ * Results are cached in memory for 30 seconds by default. Concurrent calls
12
+ * while a request is in-flight are deduplicated automatically.
13
+ *
14
+ * @param client - The current Frak Client
15
+ * @param options - Optional cache configuration
16
+ * @param options.cacheTime - Time in ms to cache the result. Default: 30_000 (30s). Set to 0 to disable.
17
+ * @returns The merge token string, or null if unavailable
18
+ */
19
+ export async function getMergeToken(
20
+ client: FrakClient,
21
+ options?: { cacheTime?: number }
22
+ ): Promise<string | null> {
23
+ return withCache(
24
+ () =>
25
+ client.request({
26
+ method: "frak_getMergeToken",
27
+ }),
28
+ {
29
+ cacheKey: "frak_getMergeToken",
30
+ cacheTime: options?.cacheTime,
31
+ }
32
+ );
33
+ }
@@ -3,6 +3,7 @@ export { displayModal } from "./displayModal";
3
3
  export { displaySharingPage } from "./displaySharingPage";
4
4
  export { ensureIdentity } from "./ensureIdentity";
5
5
  export { getMerchantInformation } from "./getMerchantInformation";
6
+ export { getMergeToken } from "./getMergeToken";
6
7
  export { getUserReferralStatus } from "./getUserReferralStatus";
7
8
  export { openSso } from "./openSso";
8
9
  export { prepareSso } from "./prepareSso";
@@ -125,9 +125,9 @@ export function createIFrameFrakClient({
125
125
  ],
126
126
  // Add lifecycle handlers to process iframe lifecycle events
127
127
  lifecycleHandlers: {
128
- iframeLifecycle: async (event, _context) => {
128
+ iframeLifecycle: (event, _context) => {
129
129
  // Delegate to lifecycle manager (cast for type compatibility)
130
- await lifecycleManager.handleEvent(event);
130
+ lifecycleManager.handleEvent(event);
131
131
  },
132
132
  },
133
133
  });
@@ -318,6 +318,7 @@ async function postConnectionSetup({
318
318
  css: raw.css,
319
319
  translations: raw.translations,
320
320
  placements: raw.placements,
321
+ components: raw.components,
321
322
  }
322
323
  : {
323
324
  isResolved: true,
@@ -102,7 +102,7 @@ describe("createIFrameLifecycleManager", () => {
102
102
  iframeLifecycle: "connected" as const,
103
103
  };
104
104
 
105
- await manager.handleEvent(event);
105
+ manager.handleEvent(event);
106
106
 
107
107
  await expect(manager.isConnected).resolves.toBe(true);
108
108
  });
@@ -126,7 +126,7 @@ describe("createIFrameLifecycleManager", () => {
126
126
  data: { backup },
127
127
  };
128
128
 
129
- await manager.handleEvent(event);
129
+ manager.handleEvent(event);
130
130
 
131
131
  expect(localStorage.getItem("frak-backup-key")).toBe(backup);
132
132
  });
@@ -150,7 +150,7 @@ describe("createIFrameLifecycleManager", () => {
150
150
  data: {},
151
151
  };
152
152
 
153
- await manager.handleEvent(event);
153
+ manager.handleEvent(event);
154
154
 
155
155
  expect(localStorage.getItem("frak-backup-key")).toBeNull();
156
156
  });
@@ -173,7 +173,7 @@ describe("createIFrameLifecycleManager", () => {
173
173
  iframeLifecycle: "remove-backup" as const,
174
174
  };
175
175
 
176
- await manager.handleEvent(event);
176
+ manager.handleEvent(event);
177
177
 
178
178
  expect(localStorage.getItem("frak-backup-key")).toBeNull();
179
179
  });
@@ -198,7 +198,7 @@ describe("createIFrameLifecycleManager", () => {
198
198
  iframeLifecycle: "show" as const,
199
199
  };
200
200
 
201
- await manager.handleEvent(event);
201
+ manager.handleEvent(event);
202
202
 
203
203
  expect(changeIframeVisibility).toHaveBeenCalledWith({
204
204
  iframe: mockIframe,
@@ -224,7 +224,7 @@ describe("createIFrameLifecycleManager", () => {
224
224
  iframeLifecycle: "hide" as const,
225
225
  };
226
226
 
227
- await manager.handleEvent(event);
227
+ manager.handleEvent(event);
228
228
 
229
229
  expect(changeIframeVisibility).toHaveBeenCalledWith({
230
230
  iframe: mockIframe,
@@ -259,7 +259,7 @@ describe("createIFrameLifecycleManager", () => {
259
259
  },
260
260
  };
261
261
 
262
- await manager.handleEvent(event);
262
+ manager.handleEvent(event);
263
263
 
264
264
  expect(window.location.href).toBe(
265
265
  "https://redirect.com/?u=https%3A%2F%2Foriginal.com"
@@ -291,7 +291,7 @@ describe("createIFrameLifecycleManager", () => {
291
291
  },
292
292
  };
293
293
 
294
- await manager.handleEvent(event);
294
+ manager.handleEvent(event);
295
295
 
296
296
  expect(window.location.href).toBe("https://redirect.com/path");
297
297
  });
@@ -325,7 +325,7 @@ describe("createIFrameLifecycleManager", () => {
325
325
  },
326
326
  };
327
327
 
328
- await manager.handleEvent(event);
328
+ manager.handleEvent(event);
329
329
 
330
330
  expect(triggerDeepLinkWithFallback).toHaveBeenCalledWith(
331
331
  "frakwallet://wallet",
@@ -370,7 +370,7 @@ describe("createIFrameLifecycleManager", () => {
370
370
  },
371
371
  };
372
372
 
373
- await manager.handleEvent(event);
373
+ manager.handleEvent(event);
374
374
 
375
375
  // Extract the onFallback callback from the mock call
376
376
  const callArgs = (triggerDeepLinkWithFallback as any).mock.calls[0];
@@ -419,7 +419,7 @@ describe("createIFrameLifecycleManager", () => {
419
419
  },
420
420
  };
421
421
 
422
- await manager.handleEvent(event);
422
+ manager.handleEvent(event);
423
423
 
424
424
  // Should NOT call fallback detection
425
425
  expect(triggerDeepLinkWithFallback).not.toHaveBeenCalled();
@@ -445,7 +445,7 @@ describe("createIFrameLifecycleManager", () => {
445
445
  } as any;
446
446
 
447
447
  // Should not throw
448
- await expect(manager.handleEvent(event)).resolves.toBeUndefined();
448
+ expect(manager.handleEvent(event)).toBeUndefined();
449
449
  });
450
450
 
451
451
  test("should only process events with iframeLifecycle", async () => {
@@ -463,13 +463,13 @@ describe("createIFrameLifecycleManager", () => {
463
463
  });
464
464
 
465
465
  // Event without iframeLifecycle
466
- await manager.handleEvent({ randomEvent: "show" } as any);
466
+ manager.handleEvent({ randomEvent: "show" } as any);
467
467
 
468
468
  // changeIframeVisibility should not be called
469
469
  expect(changeIframeVisibility).not.toHaveBeenCalled();
470
470
 
471
471
  // Event with iframeLifecycle
472
- await manager.handleEvent({ iframeLifecycle: "show" as const });
472
+ manager.handleEvent({ iframeLifecycle: "show" as const });
473
473
 
474
474
  // Now it should be called
475
475
  expect(changeIframeVisibility).toHaveBeenCalled();
@@ -32,7 +32,7 @@ const isIOSInAppBrowser = (() => {
32
32
  /** @ignore */
33
33
  export type IframeLifecycleManager = {
34
34
  isConnected: Promise<boolean>;
35
- handleEvent: (messageEvent: FrakLifecycleEvent) => Promise<void>;
35
+ handleEvent: (messageEvent: FrakLifecycleEvent) => void;
36
36
  };
37
37
 
38
38
  /**
@@ -59,12 +59,12 @@ function computeRedirectUrl(
59
59
  return baseRedirectUrl;
60
60
  }
61
61
 
62
- redirectUrl.searchParams.delete("u");
63
- redirectUrl.searchParams.append("u", window.location.href);
62
+ // Append merge token to the page URL so it survives
63
+ // the backend /common/social redirect chain
64
+ const finalPageUrl = appendMergeToken(window.location.href, mergeToken);
64
65
 
65
- if (mergeToken) {
66
- redirectUrl.searchParams.append("fmt", mergeToken);
67
- }
66
+ redirectUrl.searchParams.delete("u");
67
+ redirectUrl.searchParams.append("u", finalPageUrl);
68
68
 
69
69
  return redirectUrl.toString();
70
70
  } catch {
@@ -93,6 +93,21 @@ function isSocialRedirect(url: string): boolean {
93
93
  return url.includes("/common/social");
94
94
  }
95
95
 
96
+ /**
97
+ * Append merge token to a URL as the `fmt` query parameter.
98
+ */
99
+ function appendMergeToken(urlString: string, mergeToken?: string): string {
100
+ if (!mergeToken) return urlString;
101
+ try {
102
+ const url = new URL(urlString);
103
+ url.searchParams.set("fmt", mergeToken);
104
+ return url.toString();
105
+ } catch {
106
+ const sep = urlString.includes("?") ? "&" : "?";
107
+ return `${urlString}${sep}fmt=${encodeURIComponent(mergeToken)}`;
108
+ }
109
+ }
110
+
96
111
  /**
97
112
  * Handle redirect with deep link fallback
98
113
  */
@@ -100,8 +115,18 @@ function handleRedirect(
100
115
  iframe: HTMLIFrameElement,
101
116
  baseRedirectUrl: string,
102
117
  targetOrigin: string,
103
- mergeToken?: string
118
+ mergeToken?: string,
119
+ openInNewTab?: boolean
104
120
  ): void {
121
+ // If requested, open in a new tab instead of navigating the current page.
122
+ // This preserves the merchant page while triggering universal links.
123
+ // Requires the iframe postMessage to include user activation delegation.
124
+ if (openInNewTab) {
125
+ const finalUrl = computeRedirectUrl(baseRedirectUrl, mergeToken);
126
+ window.open(finalUrl, "_blank");
127
+ return;
128
+ }
129
+
105
130
  if (isFrakDeepLink(baseRedirectUrl)) {
106
131
  const finalUrl = computeRedirectUrl(baseRedirectUrl, mergeToken);
107
132
  triggerDeepLinkWithFallback(finalUrl, {
@@ -143,7 +168,7 @@ export function createIFrameLifecycleManager({
143
168
  const isConnectedDeferred = new Deferred<boolean>();
144
169
 
145
170
  // Build the handler itself
146
- const handler = async (messageEvent: FrakLifecycleEvent) => {
171
+ const handler = (messageEvent: FrakLifecycleEvent) => {
147
172
  if (!("iframeLifecycle" in messageEvent)) return;
148
173
 
149
174
  const { iframeLifecycle: event, data } = messageEvent;
@@ -172,7 +197,8 @@ export function createIFrameLifecycleManager({
172
197
  iframe,
173
198
  data.baseRedirectUrl,
174
199
  targetOrigin,
175
- data.mergeToken
200
+ data.mergeToken,
201
+ data.openInNewTab
176
202
  );
177
203
  break;
178
204
  }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Stub for rrweb. The @openpanel/web package statically imports `record` from
3
+ * rrweb even when session replay is disabled. This stub replaces the module so
4
+ * that rrweb is not included in the bundle.
5
+ * @see https://github.com/Openpanel-dev/openpanel/issues/336
6
+ */
7
+ export function record() {
8
+ return () => {};
9
+ }
@@ -29,5 +29,12 @@ type RedirectRequestEvent = {
29
29
  * Used when redirecting out of social browsers to preserve identity across contexts
30
30
  */
31
31
  mergeToken?: string;
32
+ /**
33
+ * When true, open the URL in a new tab via window.open(_blank)
34
+ * instead of navigating the current page.
35
+ * Requires the postMessage to include user activation delegation
36
+ * (includeUserActivation: true) so Safari allows the popup.
37
+ */
38
+ openInNewTab?: boolean;
32
39
  };
33
40
  };
@@ -36,6 +36,7 @@ export type ResolvedPlacement = {
36
36
  css?: string;
37
37
  };
38
38
  postPurchase?: {
39
+ badgeText?: string;
39
40
  refereeText?: string;
40
41
  refereeNoRewardText?: string;
41
42
  referrerText?: string;
@@ -77,6 +78,8 @@ export type ResolvedSdkConfig = {
77
78
  css?: string;
78
79
  translations?: Record<string, string>;
79
80
  placements?: Record<string, ResolvedPlacement>;
81
+ /** Global component defaults (used when no placement override exists) */
82
+ components?: ResolvedPlacement["components"];
80
83
  };
81
84
 
82
85
  /**
@@ -119,4 +122,7 @@ export type SdkResolvedConfig = {
119
122
 
120
123
  /** Named placements (keyed by placement ID) */
121
124
  placements?: Record<string, ResolvedPlacement>;
125
+
126
+ /** Global component defaults (fallback for placement-level overrides) */
127
+ components?: ResolvedPlacement["components"];
122
128
  };
@@ -14,6 +14,11 @@ export type SharingPageProduct = {
14
14
  * Optional product image URL
15
15
  */
16
16
  imageUrl?: string;
17
+ /**
18
+ * Optional product-specific sharing link
19
+ * When provided and the product is selected, this link is used instead of the default sharing link
20
+ */
21
+ link?: string;
17
22
  };
18
23
 
19
24
  /**
@@ -9,10 +9,10 @@ import type {
9
9
  import type { LoggedOutEmbeddedView } from "./loggedOut";
10
10
 
11
11
  export type {
12
+ EmbeddedViewActionReferred,
12
13
  EmbeddedViewActionSharing,
13
14
  LoggedInEmbeddedView,
14
15
  LoggedOutEmbeddedView,
15
- EmbeddedViewActionReferred,
16
16
  };
17
17
 
18
18
  /**
package/src/types/rpc.ts CHANGED
@@ -184,4 +184,16 @@ export type IFrameRpcSchema = [
184
184
  ];
185
185
  ReturnType: DisplaySharingPageResultType;
186
186
  },
187
+ /**
188
+ * Method to get a merge token for the current anonymous identity.
189
+ * Used by in-app browser redirect flows to preserve identity
190
+ * when switching from a WebView to the system browser.
191
+ * Returns the merge token string, or null if unavailable.
192
+ * This is a one-shot request.
193
+ */
194
+ {
195
+ Method: "frak_getMergeToken";
196
+ Parameters?: undefined;
197
+ ReturnType: string | null;
198
+ },
187
199
  ];
@@ -129,6 +129,7 @@ describe("withCache", () => {
129
129
  });
130
130
 
131
131
  it("should not cache errors — subsequent call retries", async () => {
132
+ vi.useFakeTimers();
132
133
  const fn = vi
133
134
  .fn()
134
135
  .mockRejectedValueOnce(new Error("fail"))
@@ -138,9 +139,14 @@ describe("withCache", () => {
138
139
  withCache(fn, { cacheKey: "retry-key" })
139
140
  ).rejects.toThrow("fail");
140
141
 
142
+ // Advance past the negative cache backoff (1s)
143
+ vi.advanceTimersByTime(1_001);
144
+
141
145
  const result = await withCache(fn, { cacheKey: "retry-key" });
142
146
  expect(result).toBe("recovered");
143
147
  expect(fn).toHaveBeenCalledTimes(2);
148
+
149
+ vi.useRealTimers();
144
150
  });
145
151
  });
146
152
 
@@ -14,6 +14,12 @@ const responseCache = new LruMap<CacheEntry<unknown>>(1024);
14
14
  /** Default cache time: 30 seconds */
15
15
  export const DEFAULT_CACHE_TIME = 30_000;
16
16
 
17
+ /** Short negative cache to avoid flooding on transient failures */
18
+ const NEGATIVE_CACHE_TIME = 1_000;
19
+
20
+ /** Tracks recently failed keys to avoid request floods */
21
+ const failureCache = new LruMap<number>(1024);
22
+
17
23
  type WithCacheOptions = {
18
24
  /** The key to cache the data against */
19
25
  cacheKey: string;
@@ -52,6 +58,12 @@ export async function withCache<TData>(
52
58
  }
53
59
  }
54
60
 
61
+ // Check if this key recently failed — back off briefly
62
+ const lastFailure = failureCache.get(cacheKey);
63
+ if (lastFailure && Date.now() - lastFailure < NEGATIVE_CACHE_TIME) {
64
+ throw new Error(`Cache: ${cacheKey} recently failed, backing off`);
65
+ }
66
+
55
67
  // Check if there's already a pending promise (dedup concurrent calls)
56
68
  let promise = promiseCache.get(cacheKey) as Promise<TData> | undefined;
57
69
  if (!promise) {
@@ -63,7 +75,13 @@ export async function withCache<TData>(
63
75
  const data = await promise;
64
76
  // Store the response with a timestamp
65
77
  responseCache.set(cacheKey, { data, created: Date.now() });
78
+ // Clear any previous failure
79
+ failureCache.delete(cacheKey);
66
80
  return data;
81
+ } catch (error) {
82
+ // Record the failure timestamp
83
+ failureCache.set(cacheKey, Date.now());
84
+ throw error;
67
85
  } finally {
68
86
  // Clear the promise cache so subsequent calls can re-fetch after TTL
69
87
  promiseCache.delete(cacheKey);
@@ -102,4 +120,5 @@ export function getCache(cacheKey: string) {
102
120
  export function clearAllCache() {
103
121
  promiseCache.clear();
104
122
  responseCache.clear();
123
+ failureCache.clear();
105
124
  }
@@ -1,13 +0,0 @@
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: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 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);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 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,n,r){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 j({iframe:e,targetOrigin:n}){let i=new t.Deferred;return{handleEvent:async 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`:A(e,o.baseRedirectUrl,n,o.mergeToken);break}},isConnected:i.promise}}function M({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=j({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:async(e,t)=>{await u.handleEvent(e)}}}),m=N(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 _=P({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 N(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 P({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 F({config:e}){let t=I(e),n=await h({config:t});if(!n){console.error(`Failed to create iframe`);return}let r=M({config:t,iframe:n});if(await r.waitForSetup,!await r.waitForConnection){console.error(`Failed to connect to client`);return}return r}function I(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 M}}),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 F}}),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}});
@@ -1,13 +0,0 @@
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: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(),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);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 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,n,r){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 I({iframe:e,targetOrigin:t}){let n=new r;return{handleEvent:async 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`:F(e,a.baseRedirectUrl,t,a.mergeToken);break}},isConnected:n.promise}}function L({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=I({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:async(e,t)=>{await h.handleEvent(e)}}}),y=R(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=z({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 R(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 z({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 B({config:e}){let t=V(e),n=await b({config:t});if(!n){console.error(`Failed to create iframe`);return}let r=L({config:t,iframe:n});if(await r.waitForSetup,!await r.waitForConnection){console.error(`Failed to connect to client`);return}return r}function V(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,L as n,D as o,h as p,k as r,y as s,B as t,v as u,f as v,l as y};
@@ -1 +0,0 @@
1
- const e=require(`./trackEvent-CvbJTTqA.cjs`);let t=require(`viem`),n=require(`@frak-labs/frame-connector`),r=require(`viem/siwe`);async function i(e,t,n){return await e.request({method:`frak_displayEmbeddedWallet`,params:n?[t,e.config.metadata,n]:[t,e.config.metadata]})}async function a(e,{steps:t,metadata:n},r){return await e.request({method:`frak_displayModal`,params:r?[t,n,e.config.metadata,r]:[t,n,e.config.metadata]})}async function o(e,t,n){return await e.request({method:`frak_displaySharingPage`,params:n?[t,e.config.metadata,n]:[t,e.config.metadata]})}async function s(t){if(typeof window>`u`)return;let n=e.y();if(!n)return;let r=await e.n.resolveMerchantId();if(!r)return;let i=`frak-identity-ensured-${r}`;if(!window.sessionStorage.getItem(i))try{let a=e.u();(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 c(t,n){return e.l(()=>t.request({method:`frak_getMerchantInformation`}),{cacheKey:`frak_getMerchantInformation`,cacheTime:n?.cacheTime})}async function l(t,n){return e.l(()=>t.request({method:`frak_getUserReferralStatus`}),{cacheKey:`frak_getUserReferralStatus`,cacheTime:n?.cacheTime})}async function u(e,t){let{metadata:n,customizations:r}=e.config;return await e.request({method:`frak_prepareSso`,params:[t,n.name,r?.css]})}async function d(t,n){try{await t.request({method:`frak_sendInteraction`,params:[n,{clientId:e.y()}]})}catch{console.warn(`[Frak SDK] Failed to send interaction:`,n.type)}}function f(t,n,r){let i=typeof window<`u`?window.location.href:void 0;return e.a(n)?(e.t(t,`user_referred_started`,{properties:{referrerClientId:n.c,walletStatus:r?.key}}),d(t,{type:`arrival`,referrerClientId:n.c,referrerMerchantId:n.m,referralTimestamp:n.t,landingUrl:i}),!0):e.i(n)?(e.t(t,`user_referred_started`,{properties:{referrer:n.r,walletStatus:r?.key}}),d(t,{type:`arrival`,referrerWallet:n.r,landingUrl:i}),!0):!1}function p(t){let n=e.y();return n?{v:2,c:n,m:t,t:Math.floor(Date.now()/1e3)}:null}function m(n,r){return e.a(n)?e.y()===n.c:e.i(n)&&r?.wallet?(0,t.isAddressEqual)(n.r,r.wallet):!1}function h(t,{walletStatus:n,frakContext:r,options:i}){if(!r)return`no-referrer`;if(m(r,n))return`self-referral`;if(!f(t,r,n))return`no-referrer`;let a=e.a(r)?r.m:i?.merchantId,o=i?.alwaysAppendUrl&&a?p(a):null;return e.r.replaceUrl({url:window.location?.href,context:o}),e.t(t,`user_referred_completed`,{properties:{status:`success`}}),`success`}async function g(t,{options:n}={}){let r=e.r.parse({url:window.location.href}),i=await b(t);try{return h(t,{walletStatus:i,frakContext:r,options:n})}catch(e){console.warn(`Error processing referral`,{error:e})}}const _=`frak:referral-success`;async function v(e){try{await g(e)===`success`&&window.dispatchEvent(new Event(_))}catch(e){console.warn(`[Frak] Referral setup failed`,e)}}async function y(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.y();if(!n&&!r){console.warn(`[Frak] No identity found, skipping purchase check`);return}let i=t.merchantId??await e.n.resolveMerchantId();if(!i){console.warn(`[Frak] No merchant id found, skipping purchase check`);return}let a={Accept:`application/json`,"Content-Type":`application/json`};n&&(a[`x-wallet-sdk-auth`]=n),r&&(a[`x-frak-client-id`]=r);let o=e.u();await fetch(`${o}/user/track/purchase`,{method:`POST`,headers:a,body:JSON.stringify({customerId:t.customerId,orderId:t.orderId,token:t.token,merchantId:i})})}function b(e,t){if(!t)return e.request({method:`frak_listenToWalletStatus`}).then(t=>(x(e,t),t));let r=new n.Deferred,i=!1;return e.listenerRequest({method:`frak_listenToWalletStatus`},n=>{x(e,n),t(n),i||=(r.resolve(n),!0)}),r.promise}function x(e,t){typeof window>`u`||(e.openPanel?.setGlobalProperties({wallet:t.wallet??null}),t.interactionToken?(window.sessionStorage.setItem(`frak-wallet-interaction-token`,t.interactionToken),s(t.interactionToken)):window.sessionStorage.removeItem(`frak-wallet-interaction-token`))}function S(e,{metadata:t,login:n}){return C(e,{steps:{login:n??{}},metadata:t})}function C(e,t){function n(n){return C(e,{...t,steps:{...t.steps,sendTransaction:n}})}function r(n){return C(e,{...t,steps:{...t.steps,final:{...n,action:{key:`reward`}}}})}function i(n,r){return C(e,{...t,steps:{...t.steps,final:{...r,action:{key:`sharing`,options:n}}}})}async function o(n,r){return n&&(t.metadata=n(t.metadata??{})),await a(e,t,r)}return{params:t,sendTx:n,reward:r,sharing:i,display:o}}async function w(e,{tx:t,metadata:n}){return(await a(e,{metadata:n,steps:{login:{},sendTransaction:{tx:t}}})).sendTransaction}async function T(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,`_`,{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`g`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`h`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return w}}),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 S}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return v}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return d}});
@@ -1 +0,0 @@
1
- import{a as e,i as t,l as n,n as r,r as i,t as a,u as o,y as s}from"./trackEvent-Ce1XlsIE.js";import{isAddressEqual as c}from"viem";import{Deferred as l}from"@frak-labs/frame-connector";import{generateSiweNonce as u}from"viem/siwe";async function d(e,t,n){return await e.request({method:`frak_displayEmbeddedWallet`,params:n?[t,e.config.metadata,n]:[t,e.config.metadata]})}async function f(e,{steps:t,metadata:n},r){return await e.request({method:`frak_displayModal`,params:r?[t,n,e.config.metadata,r]:[t,n,e.config.metadata]})}async function p(e,t,n){return await e.request({method:`frak_displaySharingPage`,params:n?[t,e.config.metadata,n]:[t,e.config.metadata]})}async function m(e){if(typeof window>`u`)return;let t=s();if(!t)return;let n=await r.resolveMerchantId();if(!n)return;let i=`frak-identity-ensured-${n}`;if(!window.sessionStorage.getItem(i))try{let r=o();(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":t},body:JSON.stringify({merchantId:n})})).ok&&window.sessionStorage.setItem(i,`1`)}catch{}}async function h(e,t){return n(()=>e.request({method:`frak_getMerchantInformation`}),{cacheKey:`frak_getMerchantInformation`,cacheTime:t?.cacheTime})}async function g(e,t){return n(()=>e.request({method:`frak_getUserReferralStatus`}),{cacheKey:`frak_getUserReferralStatus`,cacheTime:t?.cacheTime})}async function _(e,t){let{metadata:n,customizations:r}=e.config;return await e.request({method:`frak_prepareSso`,params:[t,n.name,r?.css]})}async function v(e,t){try{await e.request({method:`frak_sendInteraction`,params:[t,{clientId:s()}]})}catch{console.warn(`[Frak SDK] Failed to send interaction:`,t.type)}}function y(n,r,i){let o=typeof window<`u`?window.location.href:void 0;return e(r)?(a(n,`user_referred_started`,{properties:{referrerClientId:r.c,walletStatus:i?.key}}),v(n,{type:`arrival`,referrerClientId:r.c,referrerMerchantId:r.m,referralTimestamp:r.t,landingUrl:o}),!0):t(r)?(a(n,`user_referred_started`,{properties:{referrer:r.r,walletStatus:i?.key}}),v(n,{type:`arrival`,referrerWallet:r.r,landingUrl:o}),!0):!1}function b(e){let t=s();return t?{v:2,c:t,m:e,t:Math.floor(Date.now()/1e3)}:null}function x(n,r){return e(n)?s()===n.c:t(n)&&r?.wallet?c(n.r,r.wallet):!1}function S(t,{walletStatus:n,frakContext:r,options:o}){if(!r)return`no-referrer`;if(x(r,n))return`self-referral`;if(!y(t,r,n))return`no-referrer`;let s=e(r)?r.m:o?.merchantId,c=o?.alwaysAppendUrl&&s?b(s):null;return i.replaceUrl({url:window.location?.href,context:c}),a(t,`user_referred_completed`,{properties:{status:`success`}}),`success`}async function C(e,{options:t}={}){let n=i.parse({url:window.location.href}),r=await D(e);try{return S(e,{walletStatus:r,frakContext:n,options:t})}catch(e){console.warn(`Error processing referral`,{error:e})}}const w=`frak:referral-success`;async function T(e){try{await C(e)===`success`&&window.dispatchEvent(new Event(w))}catch(e){console.warn(`[Frak] Referral setup failed`,e)}}async function E(e){if(typeof window>`u`){console.warn(`[Frak] No window found, can't track purchase`);return}let t=window.sessionStorage.getItem(`frak-wallet-interaction-token`),n=s();if(!t&&!n){console.warn(`[Frak] No identity found, skipping purchase check`);return}let i=e.merchantId??await r.resolveMerchantId();if(!i){console.warn(`[Frak] No merchant id found, skipping purchase check`);return}let a={Accept:`application/json`,"Content-Type":`application/json`};t&&(a[`x-wallet-sdk-auth`]=t),n&&(a[`x-frak-client-id`]=n);let c=o();await fetch(`${c}/user/track/purchase`,{method:`POST`,headers:a,body:JSON.stringify({customerId:e.customerId,orderId:e.orderId,token:e.token,merchantId:i})})}function D(e,t){if(!t)return e.request({method:`frak_listenToWalletStatus`}).then(t=>(O(e,t),t));let n=new l,r=!1;return e.listenerRequest({method:`frak_listenToWalletStatus`},i=>{O(e,i),t(i),r||=(n.resolve(i),!0)}),n.promise}function O(e,t){typeof window>`u`||(e.openPanel?.setGlobalProperties({wallet:t.wallet??null}),t.interactionToken?(window.sessionStorage.setItem(`frak-wallet-interaction-token`,t.interactionToken),m(t.interactionToken)):window.sessionStorage.removeItem(`frak-wallet-interaction-token`))}function k(e,{metadata:t,login:n}){return A(e,{steps:{login:n??{}},metadata:t})}function A(e,t){function n(n){return A(e,{...t,steps:{...t.steps,sendTransaction:n}})}function r(n){return A(e,{...t,steps:{...t.steps,final:{...n,action:{key:`reward`}}}})}function i(n,r){return A(e,{...t,steps:{...t.steps,final:{...r,action:{key:`sharing`,options:n}}}})}async function a(n,r){return n&&(t.metadata=n(t.metadata??{})),await f(e,t,r)}return{params:t,sendTx:n,reward:r,sharing:i,display:a}}async function j(e,{tx:t,metadata:n}){return(await f(e,{metadata:n,steps:{login:{},sendTransaction:{tx:t}}})).sendTransaction}async function M(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 f(e,{metadata:n,steps:{login:{},siweAuthenticate:{siwe:{...t,statement:i,nonce:t?.nonce??u(),uri:t?.uri??`https://${r}`,version:t?.version??`1`,domain:r}}}})).siweAuthenticate}export{d as _,E as a,C as c,_ as d,g as f,f as g,p as h,D as i,S as l,m,j as n,w as o,h as p,k as r,T as s,M as t,v as u};