@frak-labs/core-sdk 0.0.6 → 0.0.8

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.
@@ -0,0 +1 @@
1
+ import*as e from"viem";import*as t from"viem/siwe";class n{_promise;_resolve;_reject;constructor(){this._promise=new Promise((e,t)=>{this._resolve=e,this._reject=t})}get promise(){return this._promise}resolve=e=>{this._resolve?.(e)};reject=e=>{this._reject?.(e)}}function r(e,t){if(!t)return e.request({method:"frak_listenToWalletStatus"}).then(e=>(a(e.interactionToken),e));let r=new n,o=!1;return e.listenerRequest({method:"frak_listenToWalletStatus"},e=>{t(e),a(e.interactionToken),o||(r.resolve(e),o=!0)}).then(()=>r.promise)}function a(e){"undefined"!=typeof window&&(e?window.sessionStorage.setItem("frak-wallet-interaction-token",e):window.sessionStorage.removeItem("frak.interaction-token"))}async function o(t,{productId:n,interaction:r,validation:a}){let o=n??function({domain:t}){let n=t??window.location.host;return(0,e.keccak256)((0,e.toHex)(n))}(t.config);return await t.request({method:"frak_sendInteraction",params:[o,r,a]})}async function i(e,{steps:t,metadata:n}){return await e.request({method:"frak_displayModal",params:[t,e.config.metadata.name,n]})}async function s(e,t){await e.request({method:"frak_displayEmbededWallet",params:[t,e.config.metadata.name]})}async function c(e,t){let{metadata:n}=e.config;await e.request({method:"frak_sso",params:[t,n.name,n.css]})}async function l(e){return await e.request({method:"frak_getProductInformation"})}async function u(e){if("undefined"==typeof window){console.warn("[Frak] No window found, can't track purchase");return}let t=window.sessionStorage.getItem("frak-wallet-interaction-token");if(!t){console.warn("[Frak] No frak session found, skipping purchase check");return}await fetch("https://backend.frak.id/interactions/listenForPurchase",{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json","x-wallet-sdk-auth":t},body:JSON.stringify(e)})}async function f(e,{siwe:n,metadata:r}){let a=e.config?.domain??window.location.host,o=n?.statement??`I confirm that I want to use my Frak wallet on: ${e.config.metadata.name}`,s={...n,statement:o,nonce:n?.nonce??(0,t.generateSiweNonce)(),uri:n?.uri??`https://${a}`,version:n?.version??"1",domain:a};return(await i(e,{metadata:r,steps:{login:{},siweAuthenticate:{siwe:s}}})).siweAuthenticate}async function d(e,{tx:t,metadata:n}){return(await i(e,{metadata:n,steps:{login:{},sendTransaction:{tx:t}}})).sendTransaction}function w(e,{metadata:t,login:n,openSession:r}){return function e(t,n){async function r(e){return e&&(n.metadata=e(n.metadata??{})),await i(t,n)}return{params:n,sendTx:function(r){return e(t,{...n,steps:{...n.steps,sendTransaction:r}})},reward:function(r){return e(t,{...n,steps:{...n.steps,final:{...r,action:{key:"reward"}}}})},sharing:function(r,a){return e(t,{...n,steps:{...n.steps,final:{...a,action:{key:"sharing",options:r}}}})},display:r}}(e,{steps:{login:n??{},openSession:r??{}},metadata:t})}let p="fCtx";function h({url:t}){if(!t)return null;let n=new URL(t).searchParams.get(p);return n?function(t){if(t&&0!==t.length)try{let n=function(e){let t=e.length%4;return Uint8Array.from(atob(e.replace(/-/g,"+").replace(/_/g,"/").padEnd(e.length+(0===t?0:4-t),"=")),e=>e.charCodeAt(0))}(t);return{r:(0,e.bytesToHex)(n,{size:20})}}catch(e){console.error("Error decompressing Frak context",{e,context:t})}}(n):null}let m={parse:h,replaceUrl:function({url:t,context:n}){let r;if(!window.location?.href||"undefined"==typeof window){console.error("No window found, can't update context");return}let a=t??window.location.href;(r=null!==n?function({url:t,context:n}){if(!t)return null;let r=h({url:t}),a=r?{...r,...n}:n;if(!a.r)return null;let o=function(t){if(t?.r)try{var n;return n=(0,e.hexToBytes)(t.r),btoa(Array.from(n,e=>String.fromCharCode(e)).join("")).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}catch(e){console.error("Error compressing Frak context",{e,context:t})}}(a);if(!o)return null;let i=new URL(t);return i.searchParams.set(p,o),i.toString()}({url:a,context:n}):function(e){let t=new URL(e);return t.searchParams.delete(p),t.toString()}(a))&&window.history.replaceState(null,"",r.toString())}},g="0x010cc3b9",y="0xb2c0f17c",k={dapp:1,press:2,webshop:3,retail:4,referral:30,purchase:31};Object.entries(k).reduce((e,[t,n])=>(e[t]=BigInt(1)<<BigInt(n),e),{});let S={createLink:()=>({handlerTypeDenominator:(0,e.toHex)(k.referral),interactionData:y}),referred({referrer:t}){let n=(0,e.concatHex)([g,(0,e.pad)(t,{size:32})]);return{handlerTypeDenominator:(0,e.toHex)(k.referral),interactionData:n}}};class x extends Error{code;data;constructor(e,t,n){super(t),this.code=e,this.data=n}}let _={walletNotConnected:-32005,serverErrorForInteractionDelegation:-32006};async function v(e,{walletStatus:t,frakContext:n,modalConfig:r,productId:a,options:i}){let s=!1;async function c(){if(!s)return s=!0,I(e,{modalConfig:r,walletStatus:t})}async function l(t){let n=S.referred({referrer:t});await o(e,{productId:a,interaction:n})}try{let{status:e,currentWallet:r}=await T({initialWalletStatus:t,getFreshWalletStatus:c,pushReferralInteraction:l,frakContext:n});return m.replaceUrl({url:window.location?.href,context:i?.alwaysAppendUrl?{r:r}:null}),e}catch(e){return console.log("Error processing referral",{error:e}),m.replaceUrl({url:window.location?.href,context:i?.alwaysAppendUrl?{r:t?.wallet}:null}),function(e){if(e instanceof x)switch(e.code){case _.walletNotConnected:return"no-wallet";case _.serverErrorForInteractionDelegation:return"no-session"}return"error"}(e)}}async function T({initialWalletStatus:t,getFreshWalletStatus:n,pushReferralInteraction:r,frakContext:a}){let o=t?.wallet;return a?.r?(o||(o=await n()),o&&(0,e.isAddressEqual)(a.r,o))?{status:"self-referral",currentWallet:o}:(t?.interactionSession||(o=await n()),await r(a.r),{status:"success",currentWallet:o}):{status:"no-referrer",currentWallet:o}}async function I(e,{modalConfig:t,walletStatus:n}){if(!n?.interactionSession){if(!t)return;let n=await i(e,t);return n?.login?.wallet??void 0}return n.wallet??void 0}async function b(e,{productId:t,modalConfig:n,options:a}={}){let o=m.parse({url:window.location.href}),i=await r(e);try{return await v(e,{walletStatus:i,frakContext:o,modalConfig:n,productId:t,options:a})}catch(e){console.warn("Error processing referral",{error:e})}}export{s as displayEmbededWallet,i as displayModal,l as getProductInformation,w as modalBuilder,c as openSso,v as processReferral,b as referralInteraction,o as sendInteraction,d as sendTransaction,f as siweAuthenticate,u as trackPurchaseStatus,r as watchWalletStatus};
package/dist/index.cjs CHANGED
@@ -1,489 +1,13 @@
1
- 'use strict';
2
-
3
- var chunk7YDJDVXY_cjs = require('./chunk-7YDJDVXY.cjs');
4
- var chunk665P7NO4_cjs = require('./chunk-665P7NO4.cjs');
5
-
6
- // src/utils/constants.ts
7
- var BACKUP_KEY = "nexus-wallet-backup";
8
-
9
- // src/clients/DebugInfo.ts
10
- var DebugInfoGatherer = class _DebugInfoGatherer {
11
- config;
12
- iframe;
13
- isSetupDone = false;
14
- lastResponse = null;
15
- lastRequest = null;
16
- constructor(config, iframe) {
17
- this.config = config;
18
- this.iframe = iframe;
19
- this.lastRequest = null;
20
- this.lastResponse = null;
21
- }
22
- // Update communication logs
23
- setLastResponse(event) {
24
- this.lastResponse = {
25
- event: event.data,
26
- origin: event.origin,
27
- timestamp: Date.now()
28
- };
29
- }
30
- setLastRequest(event, target) {
31
- this.lastRequest = { event, target, timestamp: Date.now() };
32
- }
33
- // Update connection status
34
- updateSetupStatus(status) {
35
- this.isSetupDone = status;
36
- }
37
- base64Encode(data) {
38
- try {
39
- return btoa(JSON.stringify(data));
40
- } catch (err) {
41
- console.warn("Failed to encode debug data", err);
42
- return btoa("Failed to encode data");
43
- }
44
- }
45
- /**
46
- * Extract information from the iframe status
47
- */
48
- getIframeStatus() {
49
- if (!this.iframe) {
50
- return null;
51
- }
52
- return {
53
- loading: this.iframe.hasAttribute("loading"),
54
- url: this.iframe.src,
55
- readyState: this.iframe.contentDocument?.readyState ? this.iframe.contentDocument.readyState === "complete" ? 1 : 0 : -1,
56
- contentWindow: !!this.iframe.contentWindow,
57
- isConnected: this.iframe.isConnected
58
- };
59
- }
60
- getNavigatorInfo() {
61
- if (!navigator) {
62
- return null;
63
- }
64
- return {
65
- userAgent: navigator.userAgent,
66
- language: navigator.language,
67
- onLine: navigator.onLine,
68
- screenWidth: window.screen.width,
69
- screenHeight: window.screen.height,
70
- pixelRatio: window.devicePixelRatio
71
- };
72
- }
73
- gatherDebugInfo(error) {
74
- const iframeStatus = this.getIframeStatus();
75
- const navigatorInfo = this.getNavigatorInfo();
76
- let formattedError = "Unknown";
77
- if (error instanceof chunk7YDJDVXY_cjs.FrakRpcError) {
78
- formattedError = `FrakRpcError: ${error.code} '${error.message}'`;
79
- } else if (error instanceof Error) {
80
- formattedError = error.message;
81
- } else if (typeof error === "string") {
82
- formattedError = error;
83
- }
84
- const debugInfo = {
85
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
86
- encodedUrl: btoa(window.location.href),
87
- encodedConfig: this.config ? this.base64Encode(this.config) : "no-config",
88
- navigatorInfo: navigatorInfo ? this.base64Encode(navigatorInfo) : "no-navigator",
89
- iframeStatus: iframeStatus ? this.base64Encode(iframeStatus) : "not-iframe",
90
- lastRequest: this.lastRequest ? this.base64Encode(this.lastRequest) : "No Frak request logged",
91
- lastResponse: this.lastResponse ? this.base64Encode(this.lastResponse) : "No Frak response logged",
92
- clientStatus: this.isSetupDone ? "setup" : "not-setup",
93
- error: formattedError
94
- };
95
- return debugInfo;
96
- }
97
- static empty() {
98
- return new _DebugInfoGatherer();
99
- }
100
- /**
101
- * Format Frak debug information
102
- */
103
- formatDebugInfo(error) {
104
- const debugInfo = this.gatherDebugInfo(error);
105
- return `
1
+ "use strict";let __rslib_import_meta_url__="undefined"==typeof document?new(require("url".replace("",""))).URL("file:"+__filename).href:document.currentScript&&document.currentScript.src||new URL("main.js",document.baseURI).href;var __webpack_require__={};__webpack_require__.d=function(e,t){for(var r in t)__webpack_require__.o(t,r)&&!__webpack_require__.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},__webpack_require__.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},__webpack_require__.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__={};__webpack_require__.r(__webpack_exports__),__webpack_require__.d(__webpack_exports__,{DebugInfoGatherer:()=>DebugInfoGatherer,decompressJson:()=>decompressJson,productTypesMask:()=>productTypesMask,Deferred:()=>Deferred,ClientNotFound:()=>ClientNotFound,compressJson:()=>compressJson,FrakContextManager:()=>FrakContextManager,createIFrameFrakClient:()=>createIFrameFrakClient,baseIframeProps:()=>baseIframeProps,RpcErrorCodes:()=>RpcErrorCodes,productTypes:()=>productTypes,setupClient:()=>setupClient,interactionTypes:()=>interactionTypes,createIframe:()=>createIframe,decompressDataAndCheckHash:()=>decompressDataAndCheckHash,FrakRpcError:()=>FrakRpcError,hashAndCompressData:()=>hashAndCompressData});class FrakRpcError extends Error{code;data;constructor(e,t,r){super(t),this.code=e,this.data=r}}class MethodNotFoundError extends FrakRpcError{constructor(e,t){super(RpcErrorCodes.methodNotFound,e,{method:t})}}class InternalError extends FrakRpcError{constructor(e){super(RpcErrorCodes.internalError,e)}}class ClientNotFound extends FrakRpcError{constructor(){super(RpcErrorCodes.clientNotConnected,"Client not found")}}let RpcErrorCodes={parseError:-32700,invalidRequest:-32600,methodNotFound:-32601,invalidParams:-32602,internalError:-32603,serverError:-32e3,clientNotConnected:-32001,configError:-32002,corruptedResponse:-32003,clientAborted:-32004,walletNotConnected:-32005,serverErrorForInteractionDelegation:-32006};class Deferred{_promise;_resolve;_reject;constructor(){this._promise=new Promise((e,t)=>{this._resolve=e,this._reject=t})}get promise(){return this._promise}resolve=e=>{this._resolve?.(e)};reject=e=>{this._reject?.(e)}}let external_async_lz_string_namespaceObject=require("async-lz-string"),external_js_sha256_namespaceObject=require("js-sha256");async function decompressDataAndCheckHash(e){if(!(e?.compressed&&e?.compressedHash))throw new FrakRpcError(RpcErrorCodes.corruptedResponse,"Missing compressed data");let t=await decompressJson(e.compressed);if(!t)throw new FrakRpcError(RpcErrorCodes.corruptedResponse,"Invalid compressed data");if(!t?.validationHash)throw new FrakRpcError(RpcErrorCodes.corruptedResponse,"Missing validation hash");if((0,external_js_sha256_namespaceObject.sha256)(e.compressed)!==e.compressedHash)throw new FrakRpcError(RpcErrorCodes.corruptedResponse,"Invalid compressed hash");let{validationHash:r,...a}=t;if((0,external_js_sha256_namespaceObject.sha256)(JSON.stringify(a))!==t.validationHash)throw new FrakRpcError(RpcErrorCodes.corruptedResponse,"Invalid data validation hash");return t}async function decompressJson(e){let t=await (0,external_async_lz_string_namespaceObject.decompressFromBase64)(e);try{return JSON.parse(t)}catch(e){return console.error("Invalid compressed data",{e,decompressed:t}),null}}async function hashAndCompressData(e){let t=(0,external_js_sha256_namespaceObject.sha256)(JSON.stringify(e)),r={...e,validationHash:t},a=await compressJson(r),n=(0,external_js_sha256_namespaceObject.sha256)(a);return{compressed:a,compressedHash:n}}async function compressJson(e){return(0,external_async_lz_string_namespaceObject.compressToBase64)(JSON.stringify(e))}let BACKUP_KEY="nexus-wallet-backup";class DebugInfoGatherer{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){this.lastResponse={event:e.data,origin:e.origin,timestamp:Date.now()}}setLastRequest(e,t){this.lastRequest={event:e,target:t,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?+("complete"===this.iframe.contentDocument.readyState):-1,contentWindow:!!this.iframe.contentWindow,isConnected:this.iframe.isConnected}:null}getNavigatorInfo(){return navigator?{userAgent:navigator.userAgent,language:navigator.language,onLine:navigator.onLine,screenWidth:window.screen.width,screenHeight:window.screen.height,pixelRatio:window.devicePixelRatio}:null}gatherDebugInfo(e){let t=this.getIframeStatus(),r=this.getNavigatorInfo(),a="Unknown";return e instanceof FrakRpcError?a=`FrakRpcError: ${e.code} '${e.message}'`:e instanceof Error?a=e.message:"string"==typeof e&&(a=e),{timestamp:new Date().toISOString(),encodedUrl:btoa(window.location.href),encodedConfig:this.config?this.base64Encode(this.config):"no-config",navigatorInfo:r?this.base64Encode(r):"no-navigator",iframeStatus:t?this.base64Encode(t):"not-iframe",lastRequest:this.lastRequest?this.base64Encode(this.lastRequest):"No Frak request logged",lastResponse:this.lastResponse?this.base64Encode(this.lastResponse):"No Frak response logged",clientStatus:this.isSetupDone?"setup":"not-setup",error:a}}static empty(){return new DebugInfoGatherer}formatDebugInfo(e){let t=this.gatherDebugInfo(e);return`
106
2
  Debug Information:
107
3
  -----------------
108
- Timestamp: ${debugInfo.timestamp}
109
- URL: ${debugInfo.encodedUrl}
110
- Config: ${debugInfo.encodedConfig}
111
- Navigator Info: ${debugInfo.navigatorInfo}
112
- IFrame Status: ${debugInfo.iframeStatus}
113
- Last Request: ${debugInfo.lastRequest}
114
- Last Response: ${debugInfo.lastResponse}
115
- Client Status: ${debugInfo.clientStatus}
116
- Error: ${debugInfo.error}
117
- `.trim();
118
- }
119
- };
120
-
121
- // src/clients/transports/iframeChannelManager.ts
122
- function createIFrameChannelManager() {
123
- const channels = /* @__PURE__ */ new Map();
124
- return {
125
- // TODO: Better id system?? uid stuff?
126
- createChannel: (resolver) => {
127
- const id = Math.random().toString(36).substring(7);
128
- channels.set(id, resolver);
129
- return id;
130
- },
131
- getRpcResolver: (id) => channels.get(id),
132
- removeChannel: (id) => channels.delete(id),
133
- destroy: () => channels.clear()
134
- };
135
- }
136
-
137
- // src/clients/transports/iframeLifecycleManager.ts
138
- function createIFrameLifecycleManager({
139
- iframe
140
- }) {
141
- const isConnectedDeferred = new chunk7YDJDVXY_cjs.Deferred();
142
- const handler = async (messageEvent) => {
143
- switch (messageEvent.iframeLifecycle) {
144
- // Resolve the isConnected promise
145
- case "connected":
146
- isConnectedDeferred.resolve(true);
147
- break;
148
- // Perform a nexus backup
149
- case "do-backup":
150
- if (messageEvent.data.backup) {
151
- localStorage.setItem(BACKUP_KEY, messageEvent.data.backup);
152
- } else {
153
- localStorage.removeItem(BACKUP_KEY);
154
- }
155
- break;
156
- // Remove nexus backup
157
- case "remove-backup":
158
- localStorage.removeItem(BACKUP_KEY);
159
- break;
160
- // Change iframe visibility
161
- case "show":
162
- case "hide":
163
- chunk7YDJDVXY_cjs.changeIframeVisibility({
164
- iframe,
165
- isVisible: messageEvent.iframeLifecycle === "show"
166
- });
167
- break;
168
- // Handshake handling
169
- case "handshake": {
170
- iframe.contentWindow?.postMessage(
171
- {
172
- clientLifecycle: "handshake-response",
173
- data: {
174
- token: messageEvent.data.token,
175
- currentUrl: window.location.href
176
- }
177
- },
178
- "*"
179
- );
180
- break;
181
- }
182
- }
183
- };
184
- return {
185
- handleEvent: handler,
186
- isConnected: isConnectedDeferred.promise
187
- };
188
- }
189
-
190
- // src/clients/transports/iframeMessageHandler.ts
191
- function createIFrameMessageHandler({
192
- frakWalletUrl,
193
- iframe,
194
- channelManager,
195
- iframeLifecycleManager,
196
- debugInfo
197
- }) {
198
- if (typeof window === "undefined") {
199
- throw new chunk7YDJDVXY_cjs.FrakRpcError(
200
- chunk7YDJDVXY_cjs.RpcErrorCodes.configError,
201
- "iframe client should be used in the browser"
202
- );
203
- }
204
- if (!iframe.contentWindow) {
205
- throw new chunk7YDJDVXY_cjs.FrakRpcError(
206
- chunk7YDJDVXY_cjs.RpcErrorCodes.configError,
207
- "The iframe does not have a product window"
208
- );
209
- }
210
- const contentWindow = iframe.contentWindow;
211
- async function msgHandler(event) {
212
- if (!event.origin) {
213
- return;
214
- }
215
- try {
216
- if (new URL(event.origin).origin.toLowerCase() !== new URL(frakWalletUrl).origin.toLowerCase()) {
217
- return;
218
- }
219
- } catch (e) {
220
- console.log("Unable to check frak msg origin", e);
221
- return;
222
- }
223
- if (typeof event.data !== "object") {
224
- return;
225
- }
226
- debugInfo.setLastResponse(event);
227
- if ("iframeLifecycle" in event.data) {
228
- await iframeLifecycleManager.handleEvent(event.data);
229
- return;
230
- }
231
- if ("clientLifecycle" in event.data) {
232
- console.error(
233
- "Client lifecycle event received on the client side, dismissing it"
234
- );
235
- return;
236
- }
237
- const channel = event.data.id;
238
- const resolver = channelManager.getRpcResolver(channel);
239
- if (!resolver) {
240
- return;
241
- }
242
- await resolver(event.data);
243
- }
244
- window.addEventListener("message", msgHandler);
245
- function sendEvent(message) {
246
- contentWindow.postMessage(message, {
247
- targetOrigin: frakWalletUrl
248
- });
249
- debugInfo.setLastRequest(message, frakWalletUrl);
250
- }
251
- function cleanup() {
252
- window.removeEventListener("message", msgHandler);
253
- }
254
- return {
255
- sendEvent,
256
- cleanup
257
- };
258
- }
259
-
260
- // src/clients/createIFrameFrakClient.ts
261
- function createIFrameFrakClient({
262
- config,
263
- iframe
264
- }) {
265
- const channelManager = createIFrameChannelManager();
266
- const lifecycleManager = createIFrameLifecycleManager({ iframe });
267
- const debugInfo = new DebugInfoGatherer(config, iframe);
268
- const messageHandler = createIFrameMessageHandler({
269
- frakWalletUrl: config?.walletUrl ?? "https://wallet.frak.id",
270
- iframe,
271
- channelManager,
272
- iframeLifecycleManager: lifecycleManager,
273
- debugInfo
274
- });
275
- const request = async (args) => {
276
- const isConnected = await lifecycleManager.isConnected;
277
- if (!isConnected) {
278
- throw new chunk7YDJDVXY_cjs.FrakRpcError(
279
- chunk7YDJDVXY_cjs.RpcErrorCodes.clientNotConnected,
280
- "The iframe provider isn't connected yet"
281
- );
282
- }
283
- const result = new chunk7YDJDVXY_cjs.Deferred();
284
- const channelId = channelManager.createChannel(async (message) => {
285
- const decompressed = await chunk7YDJDVXY_cjs.decompressDataAndCheckHash(message.data);
286
- if (decompressed.error) {
287
- result.reject(
288
- new chunk7YDJDVXY_cjs.FrakRpcError(
289
- decompressed.error.code,
290
- decompressed.error.message,
291
- decompressed.error?.data
292
- )
293
- );
294
- } else {
295
- result.resolve(decompressed.result);
296
- }
297
- channelManager.removeChannel(channelId);
298
- });
299
- const compressedMessage = await chunk7YDJDVXY_cjs.hashAndCompressData(args);
300
- messageHandler.sendEvent({
301
- id: channelId,
302
- topic: args.method,
303
- data: compressedMessage
304
- });
305
- return result.promise;
306
- };
307
- const listenerRequest = async (args, callback) => {
308
- const isConnected = await lifecycleManager.isConnected;
309
- if (!isConnected) {
310
- throw new chunk7YDJDVXY_cjs.FrakRpcError(
311
- chunk7YDJDVXY_cjs.RpcErrorCodes.clientNotConnected,
312
- "The iframe provider isn't connected yet"
313
- );
314
- }
315
- const channelId = channelManager.createChannel(async (message) => {
316
- const decompressed = await chunk7YDJDVXY_cjs.decompressDataAndCheckHash(message.data);
317
- if (decompressed.result) {
318
- callback(decompressed.result);
319
- } else {
320
- throw new chunk7YDJDVXY_cjs.InternalError("No valid result in the response");
321
- }
322
- });
323
- const compressedMessage = await chunk7YDJDVXY_cjs.hashAndCompressData(args);
324
- messageHandler.sendEvent({
325
- id: channelId,
326
- topic: args.method,
327
- data: compressedMessage
328
- });
329
- };
330
- const stopHeartbeat = setupHeartbeat(messageHandler, lifecycleManager);
331
- const destroy = async () => {
332
- stopHeartbeat();
333
- channelManager.destroy();
334
- messageHandler.cleanup();
335
- iframe.remove();
336
- };
337
- const waitForSetup = postConnectionSetup({
338
- config,
339
- messageHandler,
340
- lifecycleManager
341
- }).then(() => debugInfo.updateSetupStatus(true));
342
- return {
343
- config,
344
- debugInfo,
345
- waitForConnection: lifecycleManager.isConnected,
346
- waitForSetup,
347
- request,
348
- listenerRequest,
349
- destroy
350
- };
351
- }
352
- function setupHeartbeat(messageHandler, lifecycleManager) {
353
- const HEARTBEAT_INTERVAL = 100;
354
- const HEARTBEAT_TIMEOUT = 3e4;
355
- let heartbeatInterval;
356
- let timeoutId;
357
- const sendHeartbeat = () => messageHandler.sendEvent({
358
- clientLifecycle: "heartbeat"
359
- });
360
- async function startHeartbeat() {
361
- sendHeartbeat();
362
- heartbeatInterval = setInterval(sendHeartbeat, HEARTBEAT_INTERVAL);
363
- timeoutId = setTimeout(() => {
364
- stopHeartbeat();
365
- console.log("Heartbeat timeout: connection failed");
366
- }, HEARTBEAT_TIMEOUT);
367
- await lifecycleManager.isConnected;
368
- stopHeartbeat();
369
- }
370
- function stopHeartbeat() {
371
- if (heartbeatInterval) {
372
- clearInterval(heartbeatInterval);
373
- }
374
- if (timeoutId) {
375
- clearTimeout(timeoutId);
376
- }
377
- }
378
- startHeartbeat();
379
- return stopHeartbeat;
380
- }
381
- async function postConnectionSetup({
382
- config,
383
- messageHandler,
384
- lifecycleManager
385
- }) {
386
- await lifecycleManager.isConnected;
387
- const pushCss = async () => {
388
- const cssLink = config.metadata.css;
389
- if (!cssLink) return;
390
- messageHandler.sendEvent({
391
- clientLifecycle: "modal-css",
392
- data: { cssLink }
393
- });
394
- };
395
- const pushBackup = async () => {
396
- if (typeof window === "undefined") return;
397
- const backup = window.localStorage.getItem(BACKUP_KEY);
398
- if (!backup) return;
399
- messageHandler.sendEvent({
400
- clientLifecycle: "restore-backup",
401
- data: { backup }
402
- });
403
- };
404
- await Promise.all([pushCss(), pushBackup()]);
405
- }
406
-
407
- // src/clients/setupClient.ts
408
- async function setupClient({
409
- config
410
- }) {
411
- const iframe = await chunk7YDJDVXY_cjs.createIframe({
412
- config
413
- });
414
- if (!iframe) {
415
- console.error("Failed to create iframe");
416
- return;
417
- }
418
- const client = createIFrameFrakClient({
419
- config,
420
- iframe
421
- });
422
- await client.waitForSetup;
423
- const waitForConnection = await client.waitForConnection;
424
- if (!waitForConnection) {
425
- console.error("Failed to connect to client");
426
- return;
427
- }
428
- return client;
429
- }
430
-
431
- Object.defineProperty(exports, "ClientNotFound", {
432
- enumerable: true,
433
- get: function () { return chunk7YDJDVXY_cjs.ClientNotFound; }
434
- });
435
- Object.defineProperty(exports, "Deferred", {
436
- enumerable: true,
437
- get: function () { return chunk7YDJDVXY_cjs.Deferred; }
438
- });
439
- Object.defineProperty(exports, "FrakContextManager", {
440
- enumerable: true,
441
- get: function () { return chunk7YDJDVXY_cjs.FrakContextManager; }
442
- });
443
- Object.defineProperty(exports, "FrakRpcError", {
444
- enumerable: true,
445
- get: function () { return chunk7YDJDVXY_cjs.FrakRpcError; }
446
- });
447
- Object.defineProperty(exports, "RpcErrorCodes", {
448
- enumerable: true,
449
- get: function () { return chunk7YDJDVXY_cjs.RpcErrorCodes; }
450
- });
451
- Object.defineProperty(exports, "baseIframeProps", {
452
- enumerable: true,
453
- get: function () { return chunk7YDJDVXY_cjs.baseIframeProps; }
454
- });
455
- Object.defineProperty(exports, "compressJson", {
456
- enumerable: true,
457
- get: function () { return chunk7YDJDVXY_cjs.compressJson; }
458
- });
459
- Object.defineProperty(exports, "createIframe", {
460
- enumerable: true,
461
- get: function () { return chunk7YDJDVXY_cjs.createIframe; }
462
- });
463
- Object.defineProperty(exports, "decompressDataAndCheckHash", {
464
- enumerable: true,
465
- get: function () { return chunk7YDJDVXY_cjs.decompressDataAndCheckHash; }
466
- });
467
- Object.defineProperty(exports, "decompressJson", {
468
- enumerable: true,
469
- get: function () { return chunk7YDJDVXY_cjs.decompressJson; }
470
- });
471
- Object.defineProperty(exports, "hashAndCompressData", {
472
- enumerable: true,
473
- get: function () { return chunk7YDJDVXY_cjs.hashAndCompressData; }
474
- });
475
- Object.defineProperty(exports, "interactionTypes", {
476
- enumerable: true,
477
- get: function () { return chunk665P7NO4_cjs.interactionTypes; }
478
- });
479
- Object.defineProperty(exports, "productTypes", {
480
- enumerable: true,
481
- get: function () { return chunk665P7NO4_cjs.productTypes; }
482
- });
483
- Object.defineProperty(exports, "productTypesMask", {
484
- enumerable: true,
485
- get: function () { return chunk665P7NO4_cjs.productTypesMask; }
486
- });
487
- exports.DebugInfoGatherer = DebugInfoGatherer;
488
- exports.createIFrameFrakClient = createIFrameFrakClient;
489
- exports.setupClient = setupClient;
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()}}function createIFrameChannelManager(){let e=new Map;return{createChannel:t=>{let r=Math.random().toString(36).substring(7);return e.set(r,t),r},getRpcResolver:t=>e.get(t),removeChannel:t=>e.delete(t),destroy:()=>e.clear()}}let baseIframeProps={id:"nexus-wallet",name:"nexus-wallet",allow:"publickey-credentials-get *; clipboard-write; web-share *",style:{width:"0",height:"0",border:"0",position:"absolute",zIndex:2000001,top:"-1000px",left:"-1000px"}};function createIframe({walletBaseUrl:e,config:t}){let r=document.querySelector("#nexus-wallet");r&&r.remove();let a=document.createElement("iframe");return a.id=baseIframeProps.id,a.name=baseIframeProps.name,a.allow=baseIframeProps.allow,a.style.zIndex=baseIframeProps.style.zIndex.toString(),changeIframeVisibility({iframe:a,isVisible:!1}),document.body.appendChild(a),new Promise(r=>{a?.addEventListener("load",()=>r(a)),a.src=`${t?.walletUrl??e??"https://wallet.frak.id"}/listener`})}function changeIframeVisibility({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 createIFrameLifecycleManager({iframe:e}){let t=new Deferred;return{handleEvent:async r=>{switch(r.iframeLifecycle){case"connected":t.resolve(!0);break;case"do-backup":r.data.backup?localStorage.setItem(BACKUP_KEY,r.data.backup):localStorage.removeItem(BACKUP_KEY);break;case"remove-backup":localStorage.removeItem(BACKUP_KEY);break;case"show":case"hide":changeIframeVisibility({iframe:e,isVisible:"show"===r.iframeLifecycle});break;case"handshake":e.contentWindow?.postMessage({clientLifecycle:"handshake-response",data:{token:r.data.token,currentUrl:window.location.href}},"*")}},isConnected:t.promise}}function createIFrameMessageHandler({frakWalletUrl:e,iframe:t,channelManager:r,iframeLifecycleManager:a,debugInfo:n}){if("undefined"==typeof window)throw new FrakRpcError(RpcErrorCodes.configError,"iframe client should be used in the browser");if(!t.contentWindow)throw new FrakRpcError(RpcErrorCodes.configError,"The iframe does not have a product window");let o=t.contentWindow;async function s(t){if(!t.origin)return;try{if(new URL(t.origin).origin.toLowerCase()!==new URL(e).origin.toLowerCase())return}catch(e){console.log("Unable to check frak msg origin",e);return}if("object"!=typeof t.data)return;if(n.setLastResponse(t),"iframeLifecycle"in t.data){await a.handleEvent(t.data);return}if("clientLifecycle"in t.data){console.error("Client lifecycle event received on the client side, dismissing it");return}let o=t.data.id,s=r.getRpcResolver(o);s&&await s(t.data)}return window.addEventListener("message",s),{sendEvent:function(t){o.postMessage(t,{targetOrigin:e}),n.setLastRequest(t,e)},cleanup:function(){window.removeEventListener("message",s)}}}function createIFrameFrakClient({config:e,iframe:t}){let r=createIFrameChannelManager(),a=createIFrameLifecycleManager({iframe:t}),n=new DebugInfoGatherer(e,t),o=createIFrameMessageHandler({frakWalletUrl:e?.walletUrl??"https://wallet.frak.id",iframe:t,channelManager:r,iframeLifecycleManager:a,debugInfo:n}),s=async e=>{if(!await a.isConnected)throw new FrakRpcError(RpcErrorCodes.clientNotConnected,"The iframe provider isn't connected yet");let t=new Deferred,n=r.createChannel(async e=>{let a=await decompressDataAndCheckHash(e.data);a.error?t.reject(new FrakRpcError(a.error.code,a.error.message,a.error?.data)):t.resolve(a.result),r.removeChannel(n)}),s=await hashAndCompressData(e);return o.sendEvent({id:n,topic:e.method,data:s}),t.promise},i=async(e,t)=>{if(!await a.isConnected)throw new FrakRpcError(RpcErrorCodes.clientNotConnected,"The iframe provider isn't connected yet");let n=r.createChannel(async e=>{let r=await decompressDataAndCheckHash(e.data);if(r.result)t(r.result);else throw new InternalError("No valid result in the response")}),s=await hashAndCompressData(e);o.sendEvent({id:n,topic:e.method,data:s})},c=setupHeartbeat(o,a),l=async()=>{c(),r.destroy(),o.cleanup(),t.remove()},d=postConnectionSetup({config:e,messageHandler:o,lifecycleManager:a}).then(()=>n.updateSetupStatus(!0));return{config:e,debugInfo:n,waitForConnection:a.isConnected,waitForSetup:d,request:s,listenerRequest:i,destroy:l}}function setupHeartbeat(e,t){let r,a;let n=()=>e.sendEvent({clientLifecycle:"heartbeat"});function o(){r&&clearInterval(r),a&&clearTimeout(a)}return async function(){n(),r=setInterval(n,100),a=setTimeout(()=>{o(),console.log("Heartbeat timeout: connection failed")},3e4),await t.isConnected,o()}(),o}async function postConnectionSetup({config:e,messageHandler:t,lifecycleManager:r}){await r.isConnected;let a=async()=>{let r=e.metadata.css;r&&t.sendEvent({clientLifecycle:"modal-css",data:{cssLink:r}})},n=async()=>{if("undefined"==typeof window)return;let e=window.localStorage.getItem(BACKUP_KEY);e&&t.sendEvent({clientLifecycle:"restore-backup",data:{backup:e}})};await Promise.all([a(),n()])}async function setupClient({config:e}){let t=await createIframe({config:e});if(!t){console.error("Failed to create iframe");return}let r=createIFrameFrakClient({config:e,iframe:t});if(await r.waitForSetup,!await r.waitForConnection){console.error("Failed to connect to client");return}return r}let external_viem_namespaceObject=require("viem"),contextKey="fCtx";function base64url_encode(e){return btoa(Array.from(e,e=>String.fromCharCode(e)).join("")).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function base64url_decode(e){let t=e.length%4;return Uint8Array.from(atob(e.replace(/-/g,"+").replace(/_/g,"/").padEnd(e.length+(0===t?0:4-t),"=")),e=>e.charCodeAt(0))}function compress(e){if(e?.r)try{let t=(0,external_viem_namespaceObject.hexToBytes)(e.r);return base64url_encode(t)}catch(t){console.error("Error compressing Frak context",{e:t,context:e})}}function decompress(e){if(e&&0!==e.length)try{let t=base64url_decode(e);return{r:(0,external_viem_namespaceObject.bytesToHex)(t,{size:20})}}catch(t){console.error("Error decompressing Frak context",{e:t,context:e})}}function parse({url:e}){if(!e)return null;let t=new URL(e).searchParams.get(contextKey);return t?decompress(t):null}function update({url:e,context:t}){if(!e)return null;let r=parse({url:e}),a=r?{...r,...t}:t;if(!a.r)return null;let n=compress(a);if(!n)return null;let o=new URL(e);return o.searchParams.set(contextKey,n),o.toString()}function remove(e){let t=new URL(e);return t.searchParams.delete(contextKey),t.toString()}function replaceUrl({url:e,context:t}){let r;if(!window.location?.href||"undefined"==typeof window){console.error("No window found, can't update context");return}let a=e??window.location.href;(r=null!==t?update({url:a,context:t}):remove(a))&&window.history.replaceState(null,"",r.toString())}let FrakContextManager={compress,decompress,parse,update,remove,replaceUrl},productTypes={dapp:1,press:2,webshop:3,retail:4,referral:30,purchase:31},productTypesMask=Object.entries(productTypes).reduce((e,[t,r])=>(e[t]=BigInt(1)<<BigInt(r),e),{}),interactionTypes={press:{openArticle:"0xc0a24ffb",readArticle:"0xd5bd0fbe"},dapp:{proofVerifiableStorageUpdate:"0x2ab2aeef",callableVerifiableStorageUpdate:"0xa07da986"},webshop:{open:"0xb311798f"},referral:{referred:"0x010cc3b9",createLink:"0xb2c0f17c"},purchase:{started:"0xd87e90c3",completed:"0x8403aeb4",unsafeCompleted:"0x4d5b14e0"},retail:{customerMeeting:"0x74489004"}};var __webpack_export_target__=exports;for(var __webpack_i__ in __webpack_exports__)__webpack_export_target__[__webpack_i__]=__webpack_exports__[__webpack_i__];__webpack_exports__.__esModule&&Object.defineProperty(__webpack_export_target__,"__esModule",{value:!0});