@frak-labs/core-sdk 1.0.2-beta.64c76510 → 1.0.2-beta.75bb63ae

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 (88) hide show
  1. package/README.md +0 -1
  2. package/package.json +4 -4
  3. package/src/actions/ensureIdentity.ts +3 -3
  4. package/src/actions/openSso.ts +4 -4
  5. package/src/actions/referral/processReferral.test.ts +38 -22
  6. package/src/actions/referral/processReferral.ts +6 -4
  7. package/src/actions/referral/referralInteraction.test.ts +7 -7
  8. package/src/actions/referral/referralInteraction.ts +1 -1
  9. package/src/actions/sendInteraction.ts +1 -1
  10. package/src/actions/trackPurchaseStatus.test.ts +4 -4
  11. package/src/actions/trackPurchaseStatus.ts +3 -3
  12. package/src/actions/wrapper/siweAuthenticate.test.ts +1 -5
  13. package/src/actions/wrapper/siweAuthenticate.ts +25 -1
  14. package/src/clients/createIFrameFrakClient.ts +5 -21
  15. package/src/clients/index.ts +0 -1
  16. package/src/clients/transports/iframeLifecycleManager.test.ts +10 -10
  17. package/src/clients/transports/iframeLifecycleManager.ts +3 -3
  18. package/src/config/index.ts +3 -0
  19. package/src/{utils → config}/sdkConfigStore.ts +1 -1
  20. package/src/{utils/constants.test.ts → constants.test.ts} +1 -6
  21. package/src/context/address.ts +76 -0
  22. package/src/{utils/FrakContext.test.ts → context/frakContext.test.ts} +4 -2
  23. package/src/{utils/FrakContext.ts → context/frakContext.ts} +4 -4
  24. package/src/{utils → context}/frakContextV2Codec.test.ts +1 -1
  25. package/src/{utils → context}/frakContextV2Codec.ts +6 -6
  26. package/src/context/index.ts +6 -0
  27. package/src/index.ts +17 -22
  28. package/src/stubs/rrweb.ts +8 -4
  29. package/src/types/client.ts +0 -3
  30. package/src/types/config.ts +11 -0
  31. package/src/types/index.ts +1 -0
  32. package/src/utils/{deepLinkWithFallback.ts → browser/deepLinkWithFallback.ts} +1 -1
  33. package/src/utils/{inAppBrowser.ts → browser/inAppBrowser.ts} +13 -0
  34. package/src/utils/browser/index.ts +13 -0
  35. package/src/utils/{formatAmount.test.ts → format/formatAmount.test.ts} +1 -1
  36. package/src/utils/{formatAmount.ts → format/formatAmount.ts} +1 -1
  37. package/src/utils/{getCurrencyAmountKey.test.ts → format/getCurrencyAmountKey.test.ts} +2 -2
  38. package/src/utils/{getCurrencyAmountKey.ts → format/getCurrencyAmountKey.ts} +1 -1
  39. package/src/utils/{getSupportedCurrency.test.ts → format/getSupportedCurrency.test.ts} +2 -2
  40. package/src/utils/{getSupportedCurrency.ts → format/getSupportedCurrency.ts} +2 -2
  41. package/src/utils/{getSupportedLocale.test.ts → format/getSupportedLocale.test.ts} +3 -3
  42. package/src/utils/{getSupportedLocale.ts → format/getSupportedLocale.ts} +2 -2
  43. package/src/utils/format/index.ts +4 -0
  44. package/src/utils/{iframeHelper.test.ts → iframe/iframeHelper.test.ts} +3 -3
  45. package/src/utils/{iframeHelper.ts → iframe/iframeHelper.ts} +3 -3
  46. package/src/utils/iframe/index.ts +6 -0
  47. package/src/utils/index.ts +31 -24
  48. package/src/utils/sso/index.ts +6 -0
  49. package/src/utils/{sso.ts → sso/sso.ts} +2 -2
  50. package/cdn/bundle.js +0 -14
  51. package/dist/actions-DihYM-OG.js +0 -1
  52. package/dist/actions-cYbmqewX.cjs +0 -1
  53. package/dist/actions.cjs +0 -1
  54. package/dist/actions.d.cts +0 -3
  55. package/dist/actions.d.ts +0 -3
  56. package/dist/actions.js +0 -1
  57. package/dist/bundle.cjs +0 -1
  58. package/dist/bundle.d.cts +0 -4
  59. package/dist/bundle.d.ts +0 -4
  60. package/dist/bundle.js +0 -1
  61. package/dist/index-BhBuaCRl.d.cts +0 -707
  62. package/dist/index-BsBbSMxk.d.cts +0 -646
  63. package/dist/index-CeX1Tl7W.d.ts +0 -707
  64. package/dist/index-quaxtKRh.d.ts +0 -646
  65. package/dist/index.cjs +0 -1
  66. package/dist/index.d.cts +0 -3
  67. package/dist/index.d.ts +0 -3
  68. package/dist/index.js +0 -1
  69. package/dist/openSso-DyUQew2K.d.ts +0 -1392
  70. package/dist/openSso-rQhLhPbq.d.cts +0 -1392
  71. package/dist/sdkConfigStore-BXzz5PlK.js +0 -1
  72. package/dist/sdkConfigStore-DDL_fjYX.cjs +0 -1
  73. package/dist/src-CMaRNkkJ.cjs +0 -13
  74. package/dist/src-DMFOQMm6.js +0 -13
  75. package/src/clients/DebugInfo.test.ts +0 -418
  76. package/src/clients/DebugInfo.ts +0 -182
  77. package/src/utils/computeLegacyProductId.ts +0 -11
  78. /package/src/{utils → clients}/ssoUrlListener.test.ts +0 -0
  79. /package/src/{utils → clients}/ssoUrlListener.ts +0 -0
  80. /package/src/{utils → config}/backendUrl.test.ts +0 -0
  81. /package/src/{utils → config}/backendUrl.ts +0 -0
  82. /package/src/{utils → config}/clientId.test.ts +0 -0
  83. /package/src/{utils → config}/clientId.ts +0 -0
  84. /package/src/{utils → config}/sdkConfigStore.test.ts +0 -0
  85. /package/src/{utils/constants.ts → constants.ts} +0 -0
  86. /package/src/{utils → context}/mergeAttribution.test.ts +0 -0
  87. /package/src/{utils → context}/mergeAttribution.ts +0 -0
  88. /package/src/utils/{deepLinkWithFallback.test.ts → browser/deepLinkWithFallback.test.ts} +0 -0
@@ -1 +0,0 @@
1
- import{bytesToHex as e,hexToBytes as t,isAddress as n,keccak256 as r,toHex as i}from"viem";import{jsonEncode as a}from"@frak-labs/frame-connector";const o=`frak-client-id`;function s(){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 c(){if(typeof window>`u`||!window.localStorage)return console.warn(`[Frak SDK] No Window / localStorage available to save the clientId`),s();let e=localStorage.getItem(o);return e||(e=s(),localStorage.setItem(o,e)),e}function l({domain:e}={}){return r(i((e??window.location.host).replace(`www.`,``)))}function u(e){return btoa(Array.from(e,e=>String.fromCharCode(e)).join(``)).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function d(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 f(e){return u(a(e))}function p(e,t,n,r,i,a){let o=f(m({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 m(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 ee(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??p(i??`https://wallet.frak.id`,t,l(),n.name,c(),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]})??{}}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)}}const _=`https://backend.frak.id`;function ne(e){return e.includes(`localhost:3000`)||e.includes(`localhost:3010`)}function v(e){return ne(e)?`https://localhost:3030`:e.includes(`wallet-dev.frak.id`)||e.includes(`wallet.gcp-dev.frak.id`)?`https://backend.gcp-dev.frak.id`:_}function y(e){if(e)return v(e);if(typeof window<`u`){let e=window.FrakSetup?.client?.config?.walletUrl;if(e)return v(e)}return _}var b=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 x=new b(1024),S=new b(1024),C=3e4,w=new b(1024);async function T(e,{cacheKey:t,cacheTime:n=C}){if(n>0){let e=S.get(t);if(e&&Date.now()-e.created<n)return e.data}let r=w.get(t);if(r&&Date.now()-r<1e3)throw Error(`Cache: ${t} recently failed, backing off`);let i=x.get(t);i||(i=e(),x.set(t,i));try{let e=await i;return S.set(t,{data:e,created:Date.now()}),w.delete(t),e}catch(e){throw w.set(t,Date.now()),e}finally{x.delete(t)}}function E(e){return{clear:()=>{x.delete(e),S.delete(e)},has:(t=C)=>{let n=S.get(e);return n?Date.now()-n.created<t:!1}}}function D(){x.clear(),S.clear(),w.clear()}function re(e){return`r`in e&&!(`v`in e)}function O(e){return`v`in e&&e.v===2}const k=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function A(e){return typeof e==`string`&&k.test(e)}function j(e){let t=e.replace(/-/g,``),n=new Uint8Array(16);for(let e=0;e<16;e++)n[e]=Number.parseInt(t.substring(e*2,e*2+2),16);return n}function M(e){let t=``;for(let n=0;n<16;n++)t+=e[n].toString(16).padStart(2,`0`);return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20,32)}`}function ie(e){if(!A(e.m)||!Number.isInteger(e.t)||e.t<0||e.t>4294967295)return null;let r=typeof e.c==`string`&&e.c.length>0,i=typeof e.w==`string`&&n(e.w);if(!r&&!i||r&&!A(e.c))return null;let a=new Uint8Array(21+(r?16:0)+(i?20:0)),o=new DataView(a.buffer,a.byteOffset,a.byteLength),s=0;return a[s++]=2|(r?16:0)|(i?32:0),a.set(j(e.m),s),s+=16,o.setUint32(s,e.t,!1),s+=4,r&&(a.set(j(e.c),s),s+=16),i&&(a.set(t(e.w),s),s+=20),a}function ae(t){if(t.length<21)return null;let r=t[0];if((r&15)!=2||r&192)return null;let i=(r&16)!=0,a=(r&32)!=0;if(!i&&!a)return null;let o=21+(i?16:0)+(a?20:0);if(t.length!==o)return null;let s=1,c=M(t.subarray(s,s+16));s+=16;let l=new DataView(t.buffer,t.byteOffset,t.byteLength).getUint32(s,!1);s+=4;let u={v:2,m:c,t:l};if(i&&(u.c=M(t.subarray(s,s+16)),s+=16),a){let r=e(t.subarray(s,s+20),{size:20});if(!n(r))return null;u.w=r,s+=20}return u}const N=`fCtx`;function P(e){if(e)try{if(O(e)){let t=ie(e);return t?u(t):void 0}return u(t(e.r))}catch(t){console.error(`Error compressing Frak context`,{e:t,context:e})}}function F(t){if(!(!t||t.length===0))try{let r=d(t);if(r.length!==20)return ae(r)||void 0;let i=e(r,{size:20});if(n(i))return{r:i}}catch(e){console.error(`Error decompressing Frak context`,{e,context:t})}}function I({url:e}){if(!e)return null;let t=new URL(e).searchParams.get(N);return t?F(t):null}const L=`frak`;function oe(e,t){let n=O(e);return{utm_source:t.utmSource??L,utm_medium:t.utmMedium??`referral`,utm_campaign:t.utmCampaign??(n?e.m:void 0),utm_content:t.utmContent,utm_term:t.utmTerm,via:t.via??L,ref:t.ref??(n?e.c:void 0)}}function se(e,t,n){let r=oe(t,n??{});for(let[t,n]of Object.entries(r))n===void 0||n===``||e.searchParams.has(t)||e.searchParams.set(t,n)}function R({url:e,context:t,attribution:n}){if(!e)return null;let r=P(t);if(!r)return null;let i=new URL(e);return i.searchParams.set(N,r),se(i,t,n),i.toString()}function z(e){let t=new URL(e);return t.searchParams.delete(N),t.toString()}function ce({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?z(n):R({url:n,context:t}),r&&window.history.replaceState(null,``,r.toString())}const B={compress:P,decompress:F,parse:I,update:R,remove:z,replaceUrl:ce},V=`__frakSdkConfig`,H=`frak-config-cache`,U=`frak-merchant-id`,W={key:H},G=typeof window<`u`;function K(){return{isResolved:!1,merchantId:``}}let q=null;function J(){if(!G)return null;try{let e=localStorage.getItem(W.key);if(!e)return null;let t=JSON.parse(e);return t.config?.isResolved?(q=t,t):null}catch{return null}}function Y(){return(q??J())?.config}function le(){let e=q??J();return e?Date.now()-e.timestamp<3e4:!1}function ue(e){if(!(!G||!e.isResolved))try{let t={config:e,timestamp:Date.now()};localStorage.setItem(W.key,JSON.stringify(t)),q=t}catch{}}function X(){if(G){q=null;try{localStorage.removeItem(W.key)}catch{}}}function de(){G&&(window[V]||(window[V]=Y()??K()))}de();function Z(){return G?window[V]??K():K()}function Q(e){G&&window.dispatchEvent(new CustomEvent(`frak:config`,{detail:e}))}function fe(e){return e??(G?window.location.hostname:``)}async function pe(e,t,n){try{let r=y(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(G)try{sessionStorage.setItem(U,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 le()},setCacheScope(e,t){W.key=`${H}:${`${e}:${t??``}`}`,q=null},setConfig(e){if(G&&(window[V]=e),ue(e),Q(e),G&&e.merchantId)try{sessionStorage.setItem(U,e.merchantId)}catch{}},reset(){let e=Y()??K();G&&(window[V]=e),Q(e)},clearCache(){if(X(),D(),G)try{sessionStorage.removeItem(U)}catch{}},resolve(e,t,n){let r=fe(e);return r?T(async()=>{let e=await pe(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(G)try{return sessionStorage.getItem(U)??void 0}catch{}},async resolveMerchantId(e,t){return $.getMerchantId()||(await $.resolve(e,t))?.merchantId}};export{l as _,D as a,y as c,h as d,g as f,u as g,d as h,O as i,te as l,f as m,B as n,E as o,p,re as r,T as s,$ as t,ee as u,c 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 ee(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]})??{}}function p(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)}}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 te(e){return`r`in e&&!(`v`in e)}function E(e){return`v`in e&&e.v===2}const D=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function O(e){return typeof e==`string`&&D.test(e)}function k(e){let t=e.replace(/-/g,``),n=new Uint8Array(16);for(let e=0;e<16;e++)n[e]=Number.parseInt(t.substring(e*2,e*2+2),16);return n}function A(e){let t=``;for(let n=0;n<16;n++)t+=e[n].toString(16).padStart(2,`0`);return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20,32)}`}function j(t){if(!O(t.m)||!Number.isInteger(t.t)||t.t<0||t.t>4294967295)return null;let n=typeof t.c==`string`&&t.c.length>0,r=typeof t.w==`string`&&(0,e.isAddress)(t.w);if(!n&&!r||n&&!O(t.c))return null;let i=new Uint8Array(21+(n?16:0)+(r?20:0)),a=new DataView(i.buffer,i.byteOffset,i.byteLength),o=0;return i[o++]=2|(n?16:0)|(r?32:0),i.set(k(t.m),o),o+=16,a.setUint32(o,t.t,!1),o+=4,n&&(i.set(k(t.c),o),o+=16),r&&(i.set((0,e.hexToBytes)(t.w),o),o+=20),i}function ne(t){if(t.length<21)return null;let n=t[0];if((n&15)!=2||n&192)return null;let r=(n&16)!=0,i=(n&32)!=0;if(!r&&!i)return null;let a=21+(r?16:0)+(i?20:0);if(t.length!==a)return null;let o=1,s=A(t.subarray(o,o+16));o+=16;let c=new DataView(t.buffer,t.byteOffset,t.byteLength).getUint32(o,!1);o+=4;let l={v:2,m:s,t:c};if(r&&(l.c=A(t.subarray(o,o+16)),o+=16),i){let n=(0,e.bytesToHex)(t.subarray(o,o+20),{size:20});if(!(0,e.isAddress)(n))return null;l.w=n,o+=20}return l}const M=`fCtx`;function N(t){if(t)try{if(E(t)){let e=j(t);return e?o(e):void 0}return o((0,e.hexToBytes)(t.r))}catch(e){console.error(`Error compressing Frak context`,{e,context:t})}}function P(t){if(!(!t||t.length===0))try{let n=s(t);if(n.length!==20)return ne(n)||void 0;let r=(0,e.bytesToHex)(n,{size:20});if((0,e.isAddress)(r))return{r}}catch(e){console.error(`Error decompressing Frak context`,{e,context:t})}}function F({url:e}){if(!e)return null;let t=new URL(e).searchParams.get(M);return t?P(t):null}const I=`frak`;function L(e,t){let n=E(e);return{utm_source:t.utmSource??I,utm_medium:t.utmMedium??`referral`,utm_campaign:t.utmCampaign??(n?e.m:void 0),utm_content:t.utmContent,utm_term:t.utmTerm,via:t.via??I,ref:t.ref??(n?e.c:void 0)}}function R(e,t,n){let r=L(t,n??{});for(let[t,n]of Object.entries(r))n===void 0||n===``||e.searchParams.has(t)||e.searchParams.set(t,n)}function z({url:e,context:t,attribution:n}){if(!e)return null;let r=N(t);if(!r)return null;let i=new URL(e);return i.searchParams.set(M,r),R(i,t,n),i.toString()}function B(e){let t=new URL(e);return t.searchParams.delete(M),t.toString()}function re({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?B(n):z({url:n,context:t}),r&&window.history.replaceState(null,``,r.toString())}const V={compress:N,decompress:P,parse:F,update:z,remove:B,replaceUrl:re},H=`__frakSdkConfig`,U=`frak-config-cache`,W=`frak-merchant-id`,G={key:U},K=typeof window<`u`;function q(){return{isResolved:!1,merchantId:``}}let J=null;function Y(){if(!K)return null;try{let e=localStorage.getItem(G.key);if(!e)return null;let t=JSON.parse(e);return t.config?.isResolved?(J=t,t):null}catch{return null}}function X(){return(J??Y())?.config}function ie(){let e=J??Y();return e?Date.now()-e.timestamp<3e4:!1}function ae(e){if(!(!K||!e.isResolved))try{let t={config:e,timestamp:Date.now()};localStorage.setItem(G.key,JSON.stringify(t)),J=t}catch{}}function oe(){if(K){J=null;try{localStorage.removeItem(G.key)}catch{}}}function se(){K&&(window[H]||(window[H]=X()??q()))}se();function Z(){return K?window[H]??q():q()}function Q(e){K&&window.dispatchEvent(new CustomEvent(`frak:config`,{detail:e}))}function ce(e){return e??(K?window.location.hostname:``)}async function le(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(K)try{sessionStorage.setItem(W,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 ie()},setCacheScope(e,t){G.key=`${U}:${`${e}:${t??``}`}`,J=null},setConfig(e){if(K&&(window[H]=e),ae(e),Q(e),K&&e.merchantId)try{sessionStorage.setItem(W,e.merchantId)}catch{}},reset(){let e=X()??q();K&&(window[H]=e),Q(e)},clearCache(){if(oe(),T(),K)try{sessionStorage.removeItem(W)}catch{}},resolve(e,t,n){let r=ce(e);return r?C(async()=>{let e=await le(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(K)try{return sessionStorage.getItem(W)??void 0}catch{}},async resolveMerchantId(e,t){return $.getMerchantId()||(await $.resolve(e,t))?.merchantId}};Object.defineProperty(exports,`_`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return _}}),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 E}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return V}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return te}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return C}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return $}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return ee}}),Object.defineProperty(exports,`v`,{enumerable:!0,get:function(){return i}});
@@ -1,13 +0,0 @@
1
- const e=require(`./sdkConfigStore-DDL_fjYX.cjs`);let t=require(`@frak-labs/frame-connector`),n=require(`@openpanel/web`);function r(n){return(0,t.jsonDecode)(e.h(n))}const i=`nexus-wallet-backup`,a=`frakwallet://`;function o(){let e=navigator.userAgent;return/Android/i.test(e)&&/Chrome\/\d+/i.test(e)}const s=a.replace(`://`,``);function c(e){return`intent://${e.slice(13)}#Intent;scheme=${s};end`}function l(e,t){let n=t?.timeout??2500,r=!1,i=()=>{document.hidden&&(r=!0)};document.addEventListener(`visibilitychange`,i);let a=o()&&u(e)?c(e):e;window.location.href=a,setTimeout(()=>{document.removeEventListener(`visibilitychange`,i),r||t?.onFallback?.()},n)}function u(e){return e.startsWith(a)}const d={eur:`fr-FR`,usd:`en-US`,gbp:`en-GB`};function f(e){return e&&e in d?e:`eur`}function p(e){return e?d[e]??d.eur:d.eur}function m(e,t){let n=p(t),r=f(t);return e.toLocaleString(n,{style:`currency`,currency:r,minimumFractionDigits:0,maximumFractionDigits:2})}function h(e){return e?`${e}Amount`:`eurAmount`}const g={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 _({walletBaseUrl:t,config:n}){let r=document.querySelector(`#frak-wallet`);r&&r.remove();let i=document.createElement(`iframe`);i.id=g.id,i.name=g.name,i.allow=g.allow,i.style.zIndex=g.style.zIndex.toString(),v({iframe:i,isVisible:!1});let a=n?.walletUrl??t??`https://wallet.frak.id`,o=e.v();return b(a),b(e.c(a)),i.src=`${a}/listener?clientId=${encodeURIComponent(o)}`,new Promise(e=>{i.addEventListener(`load`,()=>e(i)),document.body.appendChild(i)})}function v({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 y(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 b(e){if(!(typeof document>`u`))try{let t=new URL(e).origin,n=`link[rel="preconnect"][data-frak-preconnect="${t}"]`;if(document.head.querySelector(n))return;let r=document.createElement(`link`);r.rel=`preconnect`,r.href=t,r.crossOrigin=``,r.dataset.frakPreconnect=t,document.head.appendChild(r)}catch{}}function x(){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 S=x();function C(){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 w=C();function T(e){S&&e.startsWith(`https://`)?window.location.href=`x-safari-https://${e.slice(8)}`:S&&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 E({perCall:e,defaults:t,productUtmContent:n}){if(e===null)return;let r=e!==void 0,i=t!==void 0&&Object.keys(t).length>0;if(!r&&!i&&!(n!==void 0&&n!==``))return;let a={...t,...e??{}},o=n??e?.utmContent;return o!==void 0&&o!==``?a.utmContent=o:delete a.utmContent,a}function D(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 O=class e{config;iframe;isSetupDone=!1;lastResponse=null;lastRequest=null;constructor(e,t){this.config=e,this.iframe=t,this.lastRequest=null,this.lastResponse=null}setLastResponse(e,t){this.lastResponse={message:e,response:t,timestamp:Date.now()}}setLastRequest(e){this.lastRequest={event:e,timestamp:Date.now()}}updateSetupStatus(e){this.isSetupDone=e}base64Encode(e){try{return btoa(JSON.stringify(e))}catch(e){return console.warn(`Failed to encode debug data`,e),btoa(`Failed to encode data`)}}getIframeStatus(){return this.iframe?{loading:this.iframe.hasAttribute(`loading`),url:this.iframe.src,readyState:this.iframe.contentDocument?.readyState?+(this.iframe.contentDocument.readyState===`complete`):-1,contentWindow:!!this.iframe.contentWindow,isConnected:this.iframe.isConnected}:null}getNavigatorInfo(){return navigator?{userAgent:navigator.userAgent,language:navigator.language,onLine:navigator.onLine,screenWidth:window.screen.width,screenHeight:window.screen.height,pixelRatio:window.devicePixelRatio}:null}gatherDebugInfo(e){let n=this.getIframeStatus(),r=this.getNavigatorInfo(),i=`Unknown`;return e instanceof t.FrakRpcError?i=`FrakRpcError: ${e.code} '${e.message}'`:e instanceof Error?i=e.message:typeof e==`string`&&(i=e),{timestamp:new Date().toISOString(),encodedUrl:btoa(window.location.href),encodedConfig:this.config?this.base64Encode(this.config):`no-config`,navigatorInfo:r?this.base64Encode(r):`no-navigator`,iframeStatus:n?this.base64Encode(n):`not-iframe`,lastRequest:this.lastRequest?this.base64Encode(this.lastRequest):`No Frak request logged`,lastResponse:this.lastResponse?this.base64Encode(this.lastResponse):`No Frak response logged`,clientStatus:this.isSetupDone?`setup`:`not-setup`,error:i}}static empty(){return new e}formatDebugInfo(e){let t=this.gatherDebugInfo(e);return`
2
- Debug Information:
3
- -----------------
4
- Timestamp: ${t.timestamp}
5
- URL: ${t.encodedUrl}
6
- Config: ${t.encodedConfig}
7
- Navigator Info: ${t.navigatorInfo}
8
- IFrame Status: ${t.iframeStatus}
9
- Last Request: ${t.lastRequest}
10
- Last Response: ${t.lastResponse}
11
- Client Status: ${t.clientStatus}
12
- Error: ${t.error}
13
- `.trim()}};const k=(()=>{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 A(e){e?localStorage.setItem(i,e):localStorage.removeItem(i)}function j(e,t){try{let n=new URL(e);if(!n.searchParams.has(`u`))return e;let r=P(window.location.href,t);return n.searchParams.delete(`u`),n.searchParams.append(`u`,r),n.toString()}catch{return e}}function M(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 N(e){return e.includes(`/common/social`)}function P(e,t){if(!t)return e;try{let n=new URL(e);return n.searchParams.set(`fmt`,t),n.toString()}catch{return`${e}${e.includes(`?`)?`&`:`?`}fmt=${encodeURIComponent(t)}`}}function F(e,t,n,r,i){if(i){let e=j(t,r);window.open(e,`_blank`);return}if(u(t)){let i=j(t,r);l(i,{onFallback:()=>{e.contentWindow?.postMessage({clientLifecycle:`deep-link-failed`,data:{originalUrl:i}},n)}})}else if(k&&N(t))M(r);else{let e=j(t,r);window.location.href=e}}function I({iframe:e,targetOrigin:n}){let r=new t.Deferred;return{handleEvent:t=>{if(!(`iframeLifecycle`in t))return;let{iframeLifecycle:a,data:o}=t;switch(a){case`connected`:r.resolve(!0);break;case`do-backup`:A(o.backup);break;case`remove-backup`:localStorage.removeItem(i);break;case`show`:case`hide`:v({iframe:e,isVisible:a===`show`});break;case`redirect`:F(e,o.baseRedirectUrl,n,o.mergeToken,o.openInNewTab);break}},isConnected:r.promise}}function L({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.t.setCacheScope(c,s),e.t.reset();let l=e.t.isCacheFresh?void 0:e.t.resolve(r.domain,r.walletUrl,s),u=I({iframe:i,targetOrigin:a}),d=new t.Deferred,f=Date.now(),p=new O(r,i);if(!i.contentWindow)throw new t.FrakRpcError(t.RpcErrorCodes.configError,`The iframe does not have a content window`);let m=(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 p.setLastRequest(e),t},onResponse(e,t){return p.setLastResponse(e,t),t}}],lifecycleHandlers:{iframeLifecycle:(e,t)=>{u.handleEvent(e)}}}),h=R(m,u),g=async()=>{h(),m.cleanup(),i.remove(),e.a(),e.t.clearCache(),e.t.reset()},_;{console.log(`[Frak SDK] Initializing OpenPanel`),_=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:`1.0.2`,userAnonymousClientId:e.v()}),!0)}),_.setGlobalProperties({sdkVersion:`1.0.2`,userAnonymousClientId:e.v()}),_.init(),_.track(`sdk_initialized`,{sdkVersion:`1.0.2`});let t=!1,r=setTimeout(()=>{t||(t=!0,_?.track(`sdk_iframe_handshake_failed`,{reason:`timeout`}))},3e4);u.isConnected.then(()=>{t||(t=!0,clearTimeout(r),_?.track(`sdk_iframe_connected`,{handshake_duration_ms:Date.now()-f}))}).catch(()=>{t||(t=!0,clearTimeout(r),_?.track(`sdk_iframe_handshake_failed`,{reason:`unknown`}))})}let v=z({config:r,rpcClient:m,lifecycleManager:u,configPromise:l,contextSent:d,openPanel:_}).then(()=>p.updateSetupStatus(!0)).catch(e=>{throw d.reject(e),e});return{config:r,debugInfo:p,waitForConnection:u.isConnected,waitForSetup:v,request:m.request,listenerRequest:m.listen,destroy:g,openPanel:_}}function R(e,t){let n,r,i=()=>e.sendLifecycle({clientLifecycle:`heartbeat`});async function a(){i(),n=setInterval(i,250),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:a,contextSent:o,openPanel:s}){await r.isConnected,D(n,r.isConnected);let c=new URL(window.location.href),l=c.searchParams.get(`fmt`)??void 0;l&&(c.searchParams.delete(`fmt`),window.history.replaceState({},``,c.toString()));let u=n=>{let r=n?.merchantId??t.metadata.merchantId??``,i=n?.domain??``,a=n?.allowedDomains??[],o=n?.sdkConfig,s=o?.attribution||t.attribution?{...t.attribution,...o?.attribution}:void 0;e.t.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,components:o.components,attribution:s}:{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,attribution:s})},d=!1,f=t=>{let r=d?void 0:l;d=!0;let i=t.hasRawSdkConfig?{name:t.name,logoUrl:t.logoUrl,homepageLink:t.homepageLink,lang:t.lang,currency:t.currency,hidden:t.hidden,css:t.css,translations:t.translations,placements:t.placements,attribution:t.attribution}:t.attribution?{attribution:t.attribution}:void 0,a=e.v();if(s){let e=s.global??{};s.setGlobalProperties({...e,merchantId:t.merchantId,domain:t.domain??``})}n.sendLifecycle({clientLifecycle:`resolved-config`,data:{merchantId:t.merchantId,domain:t.domain??``,allowedDomains:t.allowedDomains??[],sourceUrl:window.location.href,...a&&{sdkAnonymousId:a},...r&&{pendingMergeToken:r},...i&&{sdkConfig:i}}})};e.t.isResolved&&(f(e.t.getConfig()),o.resolve()),a&&(u(await a),f(e.t.getConfig()),o.resolve());async function p(){let e=t.customizations?.css;e&&n.sendLifecycle({clientLifecycle:`modal-css`,data:{cssLink:e}})}async function m(){let e=t.customizations?.i18n;e&&n.sendLifecycle({clientLifecycle:`modal-i18n`,data:{i18n:e}})}async function h(){if(typeof window>`u`)return;let e=window.localStorage.getItem(i);e&&n.sendLifecycle({clientLifecycle:`restore-backup`,data:{backup:e}})}(await Promise.allSettled([p(),m(),h()])).some(e=>e.status===`rejected`)&&s?.track(`sdk_iframe_handshake_failed`,{reason:`asset_push`})}async function B({config:e}){let t=V(e),n=await _({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=f(e.metadata?.currency);return{...e,metadata:{...e.metadata,currency:t}}}Object.defineProperty(exports,`_`,{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return S}}),Object.defineProperty(exports,`b`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return g}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,`f`,{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,`g`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`h`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return E}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return _}}),Object.defineProperty(exports,`m`,{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return L}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return w}}),Object.defineProperty(exports,`p`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return O}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return B}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return y}}),Object.defineProperty(exports,`v`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`x`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`y`,{enumerable:!0,get:function(){return l}});
@@ -1,13 +0,0 @@
1
- import{a as e,c as t,h as n,t as r,v as i}from"./sdkConfigStore-BXzz5PlK.js";import{Deferred as a,FrakRpcError as o,RpcErrorCodes as s,createRpcClient as c,jsonDecode as l}from"@frak-labs/frame-connector";import{OpenPanel as u}from"@openpanel/web";function d(e){return l(n(e))}const f=`nexus-wallet-backup`,p=`frakwallet://`;function m(){let e=navigator.userAgent;return/Android/i.test(e)&&/Chrome\/\d+/i.test(e)}const h=p.replace(`://`,``);function g(e){return`intent://${e.slice(13)}#Intent;scheme=${h};end`}function _(e,t){let n=t?.timeout??2500,r=!1,i=()=>{document.hidden&&(r=!0)};document.addEventListener(`visibilitychange`,i);let a=m()&&v(e)?g(e):e;window.location.href=a,setTimeout(()=>{document.removeEventListener(`visibilitychange`,i),r||t?.onFallback?.()},n)}function v(e){return e.startsWith(p)}const y={eur:`fr-FR`,usd:`en-US`,gbp:`en-GB`};function b(e){return e&&e in y?e:`eur`}function x(e){return e?y[e]??y.eur:y.eur}function S(e,t){let n=x(t),r=b(t);return e.toLocaleString(n,{style:`currency`,currency:r,minimumFractionDigits:0,maximumFractionDigits:2})}function C(e){return e?`${e}Amount`:`eurAmount`}const w={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 T({walletBaseUrl:e,config:n}){let r=document.querySelector(`#frak-wallet`);r&&r.remove();let a=document.createElement(`iframe`);a.id=w.id,a.name=w.name,a.allow=w.allow,a.style.zIndex=w.style.zIndex.toString(),E({iframe:a,isVisible:!1});let o=n?.walletUrl??e??`https://wallet.frak.id`,s=i();return O(o),O(t(o)),a.src=`${o}/listener?clientId=${encodeURIComponent(s)}`,new Promise(e=>{a.addEventListener(`load`,()=>e(a)),document.body.appendChild(a)})}function E({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 D(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 O(e){if(!(typeof document>`u`))try{let t=new URL(e).origin,n=`link[rel="preconnect"][data-frak-preconnect="${t}"]`;if(document.head.querySelector(n))return;let r=document.createElement(`link`);r.rel=`preconnect`,r.href=t,r.crossOrigin=``,r.dataset.frakPreconnect=t,document.head.appendChild(r)}catch{}}function k(){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 A=k();function j(){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 M=j();function N(e){A&&e.startsWith(`https://`)?window.location.href=`x-safari-https://${e.slice(8)}`:A&&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 P({perCall:e,defaults:t,productUtmContent:n}){if(e===null)return;let r=e!==void 0,i=t!==void 0&&Object.keys(t).length>0;if(!r&&!i&&!(n!==void 0&&n!==``))return;let a={...t,...e??{}},o=n??e?.utmContent;return o!==void 0&&o!==``?a.utmContent=o:delete a.utmContent,a}function F(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 I=class e{config;iframe;isSetupDone=!1;lastResponse=null;lastRequest=null;constructor(e,t){this.config=e,this.iframe=t,this.lastRequest=null,this.lastResponse=null}setLastResponse(e,t){this.lastResponse={message:e,response:t,timestamp:Date.now()}}setLastRequest(e){this.lastRequest={event:e,timestamp:Date.now()}}updateSetupStatus(e){this.isSetupDone=e}base64Encode(e){try{return btoa(JSON.stringify(e))}catch(e){return console.warn(`Failed to encode debug data`,e),btoa(`Failed to encode data`)}}getIframeStatus(){return this.iframe?{loading:this.iframe.hasAttribute(`loading`),url:this.iframe.src,readyState:this.iframe.contentDocument?.readyState?+(this.iframe.contentDocument.readyState===`complete`):-1,contentWindow:!!this.iframe.contentWindow,isConnected:this.iframe.isConnected}:null}getNavigatorInfo(){return navigator?{userAgent:navigator.userAgent,language:navigator.language,onLine:navigator.onLine,screenWidth:window.screen.width,screenHeight:window.screen.height,pixelRatio:window.devicePixelRatio}:null}gatherDebugInfo(e){let t=this.getIframeStatus(),n=this.getNavigatorInfo(),r=`Unknown`;return e instanceof o?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 L=(()=>{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 R(e){e?localStorage.setItem(f,e):localStorage.removeItem(f)}function z(e,t){try{let n=new URL(e);if(!n.searchParams.has(`u`))return e;let r=H(window.location.href,t);return n.searchParams.delete(`u`),n.searchParams.append(`u`,r),n.toString()}catch{return e}}function B(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 V(e){return e.includes(`/common/social`)}function H(e,t){if(!t)return e;try{let n=new URL(e);return n.searchParams.set(`fmt`,t),n.toString()}catch{return`${e}${e.includes(`?`)?`&`:`?`}fmt=${encodeURIComponent(t)}`}}function U(e,t,n,r,i){if(i){let e=z(t,r);window.open(e,`_blank`);return}if(v(t)){let i=z(t,r);_(i,{onFallback:()=>{e.contentWindow?.postMessage({clientLifecycle:`deep-link-failed`,data:{originalUrl:i}},n)}})}else if(L&&V(t))B(r);else{let e=z(t,r);window.location.href=e}}function W({iframe:e,targetOrigin:t}){let n=new a;return{handleEvent:r=>{if(!(`iframeLifecycle`in r))return;let{iframeLifecycle:i,data:a}=r;switch(i){case`connected`:n.resolve(!0);break;case`do-backup`:R(a.backup);break;case`remove-backup`:localStorage.removeItem(f);break;case`show`:case`hide`:E({iframe:e,isVisible:i===`show`});break;case`redirect`:U(e,a.baseRedirectUrl,t,a.mergeToken,a.openInNewTab);break}},isConnected:n.promise}}function G({config:t,iframe:n}){let l=t?.walletUrl??`https://wallet.frak.id`,d=typeof navigator<`u`?navigator.language?.split(`-`)[0]:void 0,f=t.metadata.lang??(d===`en`||d===`fr`?d:void 0),p=t.domain??(typeof window<`u`?window.location.hostname:``);r.setCacheScope(p,f),r.reset();let m=r.isCacheFresh?void 0:r.resolve(t.domain,t.walletUrl,f),h=W({iframe:n,targetOrigin:l}),g=new a,_=Date.now(),v=new I(t,n);if(!n.contentWindow)throw new o(s.configError,`The iframe does not have a content window`);let y=c({emittingTransport:n.contentWindow,listeningTransport:window,targetOrigin:l,middleware:[{async onRequest(e,t){if(!await h.isConnected)throw new o(s.clientNotConnected,`The iframe provider isn't connected yet`);return await g.promise,t}},{onRequest(e,t){return v.setLastRequest(e),t},onResponse(e,t){return v.setLastResponse(e,t),t}}],lifecycleHandlers:{iframeLifecycle:(e,t)=>{h.handleEvent(e)}}}),b=K(y,h),x=async()=>{b(),y.cleanup(),n.remove(),e(),r.clearCache(),r.reset()},S;{console.log(`[Frak SDK] Initializing OpenPanel`),S=new u({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:`1.0.2`,userAnonymousClientId:i()}),!0)}),S.setGlobalProperties({sdkVersion:`1.0.2`,userAnonymousClientId:i()}),S.init(),S.track(`sdk_initialized`,{sdkVersion:`1.0.2`});let e=!1,t=setTimeout(()=>{e||(e=!0,S?.track(`sdk_iframe_handshake_failed`,{reason:`timeout`}))},3e4);h.isConnected.then(()=>{e||(e=!0,clearTimeout(t),S?.track(`sdk_iframe_connected`,{handshake_duration_ms:Date.now()-_}))}).catch(()=>{e||(e=!0,clearTimeout(t),S?.track(`sdk_iframe_handshake_failed`,{reason:`unknown`}))})}let C=q({config:t,rpcClient:y,lifecycleManager:h,configPromise:m,contextSent:g,openPanel:S}).then(()=>v.updateSetupStatus(!0)).catch(e=>{throw g.reject(e),e});return{config:t,debugInfo:v,waitForConnection:h.isConnected,waitForSetup:C,request:y.request,listenerRequest:y.listen,destroy:x,openPanel:S}}function K(e,t){let n,r,i=()=>e.sendLifecycle({clientLifecycle:`heartbeat`});async function a(){i(),n=setInterval(i,250),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 q({config:e,rpcClient:t,lifecycleManager:n,configPromise:a,contextSent:o,openPanel:s}){await n.isConnected,F(t,n.isConnected);let c=new URL(window.location.href),l=c.searchParams.get(`fmt`)??void 0;l&&(c.searchParams.delete(`fmt`),window.history.replaceState({},``,c.toString()));let u=t=>{let n=t?.merchantId??e.metadata.merchantId??``,i=t?.domain??``,a=t?.allowedDomains??[],o=t?.sdkConfig,s=o?.attribution||e.attribution?{...e.attribution,...o?.attribution}:void 0;r.setConfig(o?{isResolved:!0,merchantId:n,domain:i,allowedDomains:a,hasRawSdkConfig:!0,name:o.name??e.metadata.name,logoUrl:o.logoUrl??e.metadata.logoUrl,homepageLink:o.homepageLink??e.metadata.homepageLink,lang:o.lang??e.metadata.lang,currency:o.currency??e.metadata.currency,hidden:o.hidden,css:o.css,translations:o.translations,placements:o.placements,components:o.components,attribution:s}:{isResolved:!0,merchantId:n,domain:i,allowedDomains:a,name:e.metadata.name,logoUrl:e.metadata.logoUrl,homepageLink:e.metadata.homepageLink,lang:e.metadata.lang,currency:e.metadata.currency,attribution:s})},d=!1,p=e=>{let n=d?void 0:l;d=!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,attribution:e.attribution}:e.attribution?{attribution:e.attribution}:void 0,a=i();if(s){let t=s.global??{};s.setGlobalProperties({...t,merchantId:e.merchantId,domain:e.domain??``})}t.sendLifecycle({clientLifecycle:`resolved-config`,data:{merchantId:e.merchantId,domain:e.domain??``,allowedDomains:e.allowedDomains??[],sourceUrl:window.location.href,...a&&{sdkAnonymousId:a},...n&&{pendingMergeToken:n},...r&&{sdkConfig:r}}})};r.isResolved&&(p(r.getConfig()),o.resolve()),a&&(u(await a),p(r.getConfig()),o.resolve());async function m(){let n=e.customizations?.css;n&&t.sendLifecycle({clientLifecycle:`modal-css`,data:{cssLink:n}})}async function h(){let n=e.customizations?.i18n;n&&t.sendLifecycle({clientLifecycle:`modal-i18n`,data:{i18n:n}})}async function g(){if(typeof window>`u`)return;let e=window.localStorage.getItem(f);e&&t.sendLifecycle({clientLifecycle:`restore-backup`,data:{backup:e}})}(await Promise.allSettled([m(),h(),g()])).some(e=>e.status===`rejected`)&&s?.track(`sdk_iframe_handshake_failed`,{reason:`asset_push`})}async function J({config:e}){let t=Y(e),n=await T({config:t});if(!n){console.error(`Failed to create iframe`);return}let r=G({config:t,iframe:n});if(await r.waitForSetup,!await r.waitForConnection){console.error(`Failed to connect to client`);return}return r}function Y(e){let t=b(e.metadata?.currency);return{...e,metadata:{...e.metadata,currency:t}}}export{v as _,A as a,p as b,w as c,C as d,S as f,m as g,y as h,P as i,T as l,b as m,G as n,M as o,x as p,I as r,N as s,J as t,D as u,g as v,d as x,_ as y};
@@ -1,418 +0,0 @@
1
- /**
2
- * Tests for DebugInfoGatherer class
3
- * Tests debug information gathering and formatting for error reporting
4
- */
5
-
6
- import { FrakRpcError, RpcErrorCodes } from "@frak-labs/frame-connector";
7
- import {
8
- afterEach,
9
- beforeEach,
10
- describe,
11
- expect,
12
- it,
13
- vi,
14
- } from "../../tests/vitest-fixtures";
15
- import type { FrakWalletSdkConfig } from "../types";
16
- import { DebugInfoGatherer } from "./DebugInfo";
17
-
18
- describe("DebugInfoGatherer", () => {
19
- let mockConfig: FrakWalletSdkConfig;
20
- let mockIframe: HTMLIFrameElement;
21
- let consoleWarnSpy: ReturnType<typeof vi.spyOn>;
22
-
23
- beforeEach(() => {
24
- // Create mock config
25
- mockConfig = {
26
- metadata: {
27
- name: "Test App",
28
- },
29
- };
30
-
31
- // Create mock iframe
32
- mockIframe = document.createElement("iframe");
33
- mockIframe.src = "https://wallet.frak.id";
34
- mockIframe.setAttribute("loading", "lazy");
35
- document.body.appendChild(mockIframe);
36
-
37
- // Mock iframe contentDocument
38
- Object.defineProperty(mockIframe, "contentDocument", {
39
- value: {
40
- readyState: "complete",
41
- },
42
- writable: true,
43
- });
44
-
45
- // Mock iframe contentWindow
46
- Object.defineProperty(mockIframe, "contentWindow", {
47
- value: {},
48
- writable: true,
49
- });
50
-
51
- // Spy on console.warn
52
- consoleWarnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
53
- });
54
-
55
- afterEach(() => {
56
- consoleWarnSpy.mockRestore();
57
- document.body.removeChild(mockIframe);
58
- vi.clearAllMocks();
59
- });
60
-
61
- describe("constructor", () => {
62
- it("should create instance with config and iframe", () => {
63
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
64
-
65
- expect(gatherer).toBeInstanceOf(DebugInfoGatherer);
66
- });
67
-
68
- it("should create instance without config and iframe", () => {
69
- const gatherer = new DebugInfoGatherer();
70
-
71
- expect(gatherer).toBeInstanceOf(DebugInfoGatherer);
72
- });
73
-
74
- it("should initialize with null lastRequest and lastResponse", () => {
75
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
76
-
77
- // Access private properties through formatDebugInfo output
78
- const debugInfo = gatherer.formatDebugInfo("test error");
79
- expect(debugInfo).toContain("No Frak request logged");
80
- expect(debugInfo).toContain("No Frak response logged");
81
- });
82
- });
83
-
84
- describe("static empty()", () => {
85
- it("should create empty instance", () => {
86
- const gatherer = DebugInfoGatherer.empty();
87
-
88
- expect(gatherer).toBeInstanceOf(DebugInfoGatherer);
89
- });
90
-
91
- it("should create instance without config or iframe", () => {
92
- const gatherer = DebugInfoGatherer.empty();
93
- const debugInfo = gatherer.formatDebugInfo("test error");
94
-
95
- expect(debugInfo).toContain("no-config");
96
- expect(debugInfo).toContain("not-iframe");
97
- });
98
- });
99
-
100
- describe("setLastRequest", () => {
101
- it("should set last request with timestamp", () => {
102
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
103
- const mockMessage = {
104
- id: 1,
105
- method: "test_method",
106
- params: [],
107
- } as any;
108
-
109
- gatherer.setLastRequest(mockMessage);
110
-
111
- const debugInfo = gatherer.formatDebugInfo("test error");
112
- expect(debugInfo).toContain("Last Request:");
113
- expect(debugInfo).not.toContain("No Frak request logged");
114
- });
115
- });
116
-
117
- describe("setLastResponse", () => {
118
- it("should set last response with timestamp", () => {
119
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
120
- const mockMessage = {
121
- id: 1,
122
- method: "test_method",
123
- } as any;
124
- const mockResponse = {
125
- id: 1,
126
- result: "success",
127
- } as any;
128
-
129
- gatherer.setLastResponse(mockMessage, mockResponse);
130
-
131
- const debugInfo = gatherer.formatDebugInfo("test error");
132
- expect(debugInfo).toContain("Last Response:");
133
- expect(debugInfo).not.toContain("No Frak response logged");
134
- });
135
- });
136
-
137
- describe("updateSetupStatus", () => {
138
- it("should update setup status to true", () => {
139
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
140
-
141
- gatherer.updateSetupStatus(true);
142
-
143
- const debugInfo = gatherer.formatDebugInfo("test error");
144
- expect(debugInfo).toContain("Client Status: setup");
145
- });
146
-
147
- it("should update setup status to false", () => {
148
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
149
-
150
- gatherer.updateSetupStatus(false);
151
-
152
- const debugInfo = gatherer.formatDebugInfo("test error");
153
- expect(debugInfo).toContain("Client Status: not-setup");
154
- });
155
- });
156
-
157
- describe("formatDebugInfo", () => {
158
- it("should format debug info with all fields", () => {
159
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
160
-
161
- const debugInfo = gatherer.formatDebugInfo("test error");
162
-
163
- expect(debugInfo).toContain("Debug Information:");
164
- expect(debugInfo).toContain("Timestamp:");
165
- expect(debugInfo).toContain("URL:");
166
- expect(debugInfo).toContain("Config:");
167
- expect(debugInfo).toContain("Navigator Info:");
168
- expect(debugInfo).toContain("IFrame Status:");
169
- expect(debugInfo).toContain("Last Request:");
170
- expect(debugInfo).toContain("Last Response:");
171
- expect(debugInfo).toContain("Client Status:");
172
- expect(debugInfo).toContain("Error:");
173
- });
174
-
175
- it("should format FrakRpcError correctly", () => {
176
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
177
- const error = new FrakRpcError(
178
- RpcErrorCodes.walletNotConnected,
179
- "Wallet not connected"
180
- );
181
-
182
- const debugInfo = gatherer.formatDebugInfo(error);
183
-
184
- expect(debugInfo).toContain(
185
- `FrakRpcError: ${RpcErrorCodes.walletNotConnected} 'Wallet not connected'`
186
- );
187
- });
188
-
189
- it("should format regular Error correctly", () => {
190
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
191
- const error = new Error("Network timeout");
192
-
193
- const debugInfo = gatherer.formatDebugInfo(error);
194
-
195
- expect(debugInfo).toContain("Network timeout");
196
- });
197
-
198
- it("should format string error correctly", () => {
199
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
200
-
201
- const debugInfo = gatherer.formatDebugInfo("String error message");
202
-
203
- expect(debugInfo).toContain("String error message");
204
- });
205
-
206
- it("should format unknown error as 'Unknown'", () => {
207
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
208
-
209
- const debugInfo = gatherer.formatDebugInfo(null);
210
-
211
- expect(debugInfo).toContain("Error: Unknown");
212
- });
213
-
214
- it("should include encoded URL", () => {
215
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
216
-
217
- const debugInfo = gatherer.formatDebugInfo("test error");
218
-
219
- // URL should be base64 encoded
220
- expect(debugInfo).toContain("URL:");
221
- const urlMatch = debugInfo.match(/URL: (.+)/);
222
- expect(urlMatch).toBeTruthy();
223
- if (urlMatch) {
224
- // Should be base64 encoded (alphanumeric + =)
225
- expect(urlMatch[1]).toMatch(/^[A-Za-z0-9+/=]+$/);
226
- }
227
- });
228
-
229
- it("should include encoded config when config is provided", () => {
230
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
231
-
232
- const debugInfo = gatherer.formatDebugInfo("test error");
233
-
234
- expect(debugInfo).toContain("Config:");
235
- expect(debugInfo).not.toContain("no-config");
236
- });
237
-
238
- it("should show 'no-config' when config is not provided", () => {
239
- const gatherer = new DebugInfoGatherer(undefined, mockIframe);
240
-
241
- const debugInfo = gatherer.formatDebugInfo("test error");
242
-
243
- expect(debugInfo).toContain("Config: no-config");
244
- });
245
-
246
- it("should include iframe status when iframe is provided", () => {
247
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
248
-
249
- const debugInfo = gatherer.formatDebugInfo("test error");
250
-
251
- expect(debugInfo).toContain("IFrame Status:");
252
- expect(debugInfo).not.toContain("not-iframe");
253
- });
254
-
255
- it("should show 'not-iframe' when iframe is not provided", () => {
256
- const gatherer = new DebugInfoGatherer(mockConfig, undefined);
257
-
258
- const debugInfo = gatherer.formatDebugInfo("test error");
259
-
260
- expect(debugInfo).toContain("IFrame Status: not-iframe");
261
- });
262
-
263
- it("should include navigator info", () => {
264
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
265
-
266
- const debugInfo = gatherer.formatDebugInfo("test error");
267
-
268
- expect(debugInfo).toContain("Navigator Info:");
269
- expect(debugInfo).not.toContain("no-navigator");
270
- });
271
-
272
- it("should handle iframe without contentDocument", () => {
273
- const iframeWithoutDoc = document.createElement("iframe");
274
- Object.defineProperty(iframeWithoutDoc, "contentDocument", {
275
- value: null,
276
- writable: true,
277
- });
278
- Object.defineProperty(iframeWithoutDoc, "contentWindow", {
279
- value: {},
280
- writable: true,
281
- });
282
-
283
- const gatherer = new DebugInfoGatherer(
284
- mockConfig,
285
- iframeWithoutDoc
286
- );
287
-
288
- const debugInfo = gatherer.formatDebugInfo("test error");
289
-
290
- expect(debugInfo).toContain("IFrame Status:");
291
- });
292
-
293
- it("should handle iframe with incomplete readyState", () => {
294
- const iframeIncomplete = document.createElement("iframe");
295
- Object.defineProperty(iframeIncomplete, "contentDocument", {
296
- value: {
297
- readyState: "loading",
298
- },
299
- writable: true,
300
- });
301
- Object.defineProperty(iframeIncomplete, "contentWindow", {
302
- value: {},
303
- writable: true,
304
- });
305
-
306
- const gatherer = new DebugInfoGatherer(
307
- mockConfig,
308
- iframeIncomplete
309
- );
310
-
311
- const debugInfo = gatherer.formatDebugInfo("test error");
312
-
313
- expect(debugInfo).toContain("IFrame Status:");
314
- });
315
-
316
- it("should include last request when set", () => {
317
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
318
- const mockMessage = {
319
- id: 1,
320
- method: "test_method",
321
- params: [],
322
- } as any;
323
-
324
- gatherer.setLastRequest(mockMessage);
325
- const debugInfo = gatherer.formatDebugInfo("test error");
326
-
327
- expect(debugInfo).toContain("Last Request:");
328
- expect(debugInfo).not.toContain("No Frak request logged");
329
- });
330
-
331
- it("should include last response when set", () => {
332
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
333
- const mockMessage = {
334
- id: 1,
335
- method: "test_method",
336
- } as any;
337
- const mockResponse = {
338
- id: 1,
339
- result: "success",
340
- } as any;
341
-
342
- gatherer.setLastResponse(mockMessage, mockResponse);
343
- const debugInfo = gatherer.formatDebugInfo("test error");
344
-
345
- expect(debugInfo).toContain("Last Response:");
346
- expect(debugInfo).not.toContain("No Frak response logged");
347
- });
348
-
349
- it("should show 'No Frak request logged' when no request is set", () => {
350
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
351
-
352
- const debugInfo = gatherer.formatDebugInfo("test error");
353
-
354
- expect(debugInfo).toContain("No Frak request logged");
355
- });
356
-
357
- it("should show 'No Frak response logged' when no response is set", () => {
358
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
359
-
360
- const debugInfo = gatherer.formatDebugInfo("test error");
361
-
362
- expect(debugInfo).toContain("No Frak response logged");
363
- });
364
- });
365
-
366
- describe("base64 encoding error handling", () => {
367
- it("should handle encoding errors gracefully", () => {
368
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
369
-
370
- // Create a circular reference that can't be JSON stringified
371
- const circularObj: any = { prop: "value" };
372
- circularObj.self = circularObj;
373
-
374
- // Mock base64Encode to throw an error
375
- // We can't directly test the private method, but we can test
376
- // that formatDebugInfo doesn't throw when encoding fails
377
- // by checking that it still produces output
378
-
379
- const debugInfo = gatherer.formatDebugInfo("test error");
380
-
381
- // Should still produce debug info even if encoding fails
382
- expect(debugInfo).toContain("Debug Information:");
383
- });
384
- });
385
-
386
- describe("integration", () => {
387
- it("should format complete debug info with all data set", () => {
388
- const gatherer = new DebugInfoGatherer(mockConfig, mockIframe);
389
- const mockRequest = {
390
- id: 1,
391
- method: "frak_sendInteraction",
392
- params: [],
393
- } as any;
394
- const mockResponse = {
395
- id: 1,
396
- result: { delegationId: "123" },
397
- } as any;
398
- const error = new FrakRpcError(
399
- RpcErrorCodes.serverError,
400
- "Server error"
401
- );
402
-
403
- gatherer.setLastRequest(mockRequest);
404
- gatherer.setLastResponse(mockRequest, mockResponse);
405
- gatherer.updateSetupStatus(true);
406
-
407
- const debugInfo = gatherer.formatDebugInfo(error);
408
-
409
- expect(debugInfo).toContain("Debug Information:");
410
- expect(debugInfo).toContain("Client Status: setup");
411
- expect(debugInfo).toContain(
412
- `FrakRpcError: ${RpcErrorCodes.serverError} 'Server error'`
413
- );
414
- expect(debugInfo).not.toContain("No Frak request logged");
415
- expect(debugInfo).not.toContain("No Frak response logged");
416
- });
417
- });
418
- });