@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.
- package/cdn/bundle.js +17 -31
- package/cdn/bundle.js.LICENSE.txt +10 -0
- package/dist/actions.cjs +1 -0
- package/dist/actions.d.cts +1285 -0
- package/dist/actions.d.ts +1285 -0
- package/dist/actions.js +1 -0
- package/dist/index.cjs +11 -487
- package/dist/index.d.cts +1152 -255
- package/dist/index.d.ts +1152 -255
- package/dist/index.js +11 -428
- package/dist/interactions.cjs +1 -0
- package/dist/{interactions/index.d.ts → interactions.d.cts} +182 -174
- package/dist/{interactions/index.d.cts → interactions.d.ts} +182 -174
- package/dist/interactions.js +1 -0
- package/package.json +15 -15
- package/dist/actions/index.cjs +0 -350
- package/dist/actions/index.d.cts +0 -501
- package/dist/actions/index.d.ts +0 -501
- package/dist/actions/index.js +0 -337
- package/dist/chunk-665P7NO4.cjs +0 -81
- package/dist/chunk-7YDJDVXY.cjs +0 -833
- package/dist/chunk-GTBCSNLF.js +0 -819
- package/dist/chunk-PHVGCFDX.cjs +0 -155
- package/dist/chunk-U2NTN5QZ.js +0 -75
- package/dist/chunk-VE6URIIJ.js +0 -149
- package/dist/context-D7aZDKLT.d.cts +0 -813
- package/dist/context-rDsQbSgB.d.ts +0 -813
- package/dist/interaction-CTQ5-kqe.d.cts +0 -43
- package/dist/interaction-CTQ5-kqe.d.ts +0 -43
- package/dist/interactions/index.cjs +0 -26
- package/dist/interactions/index.js +0 -1
package/dist/index.js
CHANGED
|
@@ -1,430 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { ClientNotFound, Deferred, FrakContextManager, FrakRpcError, RpcErrorCodes, baseIframeProps, compressJson, createIframe, decompressDataAndCheckHash, decompressJson, hashAndCompressData } from './chunk-GTBCSNLF.js';
|
|
3
|
-
export { interactionTypes, productTypes, productTypesMask } from './chunk-U2NTN5QZ.js';
|
|
4
|
-
|
|
5
|
-
// src/utils/constants.ts
|
|
6
|
-
var BACKUP_KEY = "nexus-wallet-backup";
|
|
7
|
-
|
|
8
|
-
// src/clients/DebugInfo.ts
|
|
9
|
-
var DebugInfoGatherer = class _DebugInfoGatherer {
|
|
10
|
-
config;
|
|
11
|
-
iframe;
|
|
12
|
-
isSetupDone = false;
|
|
13
|
-
lastResponse = null;
|
|
14
|
-
lastRequest = null;
|
|
15
|
-
constructor(config, iframe) {
|
|
16
|
-
this.config = config;
|
|
17
|
-
this.iframe = iframe;
|
|
18
|
-
this.lastRequest = null;
|
|
19
|
-
this.lastResponse = null;
|
|
20
|
-
}
|
|
21
|
-
// Update communication logs
|
|
22
|
-
setLastResponse(event) {
|
|
23
|
-
this.lastResponse = {
|
|
24
|
-
event: event.data,
|
|
25
|
-
origin: event.origin,
|
|
26
|
-
timestamp: Date.now()
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
setLastRequest(event, target) {
|
|
30
|
-
this.lastRequest = { event, target, timestamp: Date.now() };
|
|
31
|
-
}
|
|
32
|
-
// Update connection status
|
|
33
|
-
updateSetupStatus(status) {
|
|
34
|
-
this.isSetupDone = status;
|
|
35
|
-
}
|
|
36
|
-
base64Encode(data) {
|
|
37
|
-
try {
|
|
38
|
-
return btoa(JSON.stringify(data));
|
|
39
|
-
} catch (err) {
|
|
40
|
-
console.warn("Failed to encode debug data", err);
|
|
41
|
-
return btoa("Failed to encode data");
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Extract information from the iframe status
|
|
46
|
-
*/
|
|
47
|
-
getIframeStatus() {
|
|
48
|
-
if (!this.iframe) {
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
return {
|
|
52
|
-
loading: this.iframe.hasAttribute("loading"),
|
|
53
|
-
url: this.iframe.src,
|
|
54
|
-
readyState: this.iframe.contentDocument?.readyState ? this.iframe.contentDocument.readyState === "complete" ? 1 : 0 : -1,
|
|
55
|
-
contentWindow: !!this.iframe.contentWindow,
|
|
56
|
-
isConnected: this.iframe.isConnected
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
getNavigatorInfo() {
|
|
60
|
-
if (!navigator) {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
return {
|
|
64
|
-
userAgent: navigator.userAgent,
|
|
65
|
-
language: navigator.language,
|
|
66
|
-
onLine: navigator.onLine,
|
|
67
|
-
screenWidth: window.screen.width,
|
|
68
|
-
screenHeight: window.screen.height,
|
|
69
|
-
pixelRatio: window.devicePixelRatio
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
gatherDebugInfo(error) {
|
|
73
|
-
const iframeStatus = this.getIframeStatus();
|
|
74
|
-
const navigatorInfo = this.getNavigatorInfo();
|
|
75
|
-
let formattedError = "Unknown";
|
|
76
|
-
if (error instanceof FrakRpcError) {
|
|
77
|
-
formattedError = `FrakRpcError: ${error.code} '${error.message}'`;
|
|
78
|
-
} else if (error instanceof Error) {
|
|
79
|
-
formattedError = error.message;
|
|
80
|
-
} else if (typeof error === "string") {
|
|
81
|
-
formattedError = error;
|
|
82
|
-
}
|
|
83
|
-
const debugInfo = {
|
|
84
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
85
|
-
encodedUrl: btoa(window.location.href),
|
|
86
|
-
encodedConfig: this.config ? this.base64Encode(this.config) : "no-config",
|
|
87
|
-
navigatorInfo: navigatorInfo ? this.base64Encode(navigatorInfo) : "no-navigator",
|
|
88
|
-
iframeStatus: iframeStatus ? this.base64Encode(iframeStatus) : "not-iframe",
|
|
89
|
-
lastRequest: this.lastRequest ? this.base64Encode(this.lastRequest) : "No Frak request logged",
|
|
90
|
-
lastResponse: this.lastResponse ? this.base64Encode(this.lastResponse) : "No Frak response logged",
|
|
91
|
-
clientStatus: this.isSetupDone ? "setup" : "not-setup",
|
|
92
|
-
error: formattedError
|
|
93
|
-
};
|
|
94
|
-
return debugInfo;
|
|
95
|
-
}
|
|
96
|
-
static empty() {
|
|
97
|
-
return new _DebugInfoGatherer();
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Format Frak debug information
|
|
101
|
-
*/
|
|
102
|
-
formatDebugInfo(error) {
|
|
103
|
-
const debugInfo = this.gatherDebugInfo(error);
|
|
104
|
-
return `
|
|
1
|
+
import*as e from"async-lz-string";import*as t from"js-sha256";import*as n from"viem";class r extends Error{code;data;constructor(e,t,n){super(t),this.code=e,this.data=n}}class a extends r{constructor(e){super(s.internalError,e)}}class o extends r{constructor(){super(s.clientNotConnected,"Client not found")}}let s={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 i{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(),n=this.getNavigatorInfo(),a="Unknown";return e instanceof r?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: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:a}}static empty(){return new i}formatDebugInfo(e){let t=this.gatherDebugInfo(e);return`
|
|
105
2
|
Debug Information:
|
|
106
3
|
-----------------
|
|
107
|
-
Timestamp: ${
|
|
108
|
-
URL: ${
|
|
109
|
-
Config: ${
|
|
110
|
-
Navigator Info: ${
|
|
111
|
-
IFrame Status: ${
|
|
112
|
-
Last Request: ${
|
|
113
|
-
Last Response: ${
|
|
114
|
-
Client Status: ${
|
|
115
|
-
Error: ${
|
|
116
|
-
`.trim();
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
// src/clients/transports/iframeChannelManager.ts
|
|
121
|
-
function createIFrameChannelManager() {
|
|
122
|
-
const channels = /* @__PURE__ */ new Map();
|
|
123
|
-
return {
|
|
124
|
-
// TODO: Better id system?? uid stuff?
|
|
125
|
-
createChannel: (resolver) => {
|
|
126
|
-
const id = Math.random().toString(36).substring(7);
|
|
127
|
-
channels.set(id, resolver);
|
|
128
|
-
return id;
|
|
129
|
-
},
|
|
130
|
-
getRpcResolver: (id) => channels.get(id),
|
|
131
|
-
removeChannel: (id) => channels.delete(id),
|
|
132
|
-
destroy: () => channels.clear()
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// src/clients/transports/iframeLifecycleManager.ts
|
|
137
|
-
function createIFrameLifecycleManager({
|
|
138
|
-
iframe
|
|
139
|
-
}) {
|
|
140
|
-
const isConnectedDeferred = new Deferred();
|
|
141
|
-
const handler = async (messageEvent) => {
|
|
142
|
-
switch (messageEvent.iframeLifecycle) {
|
|
143
|
-
// Resolve the isConnected promise
|
|
144
|
-
case "connected":
|
|
145
|
-
isConnectedDeferred.resolve(true);
|
|
146
|
-
break;
|
|
147
|
-
// Perform a nexus backup
|
|
148
|
-
case "do-backup":
|
|
149
|
-
if (messageEvent.data.backup) {
|
|
150
|
-
localStorage.setItem(BACKUP_KEY, messageEvent.data.backup);
|
|
151
|
-
} else {
|
|
152
|
-
localStorage.removeItem(BACKUP_KEY);
|
|
153
|
-
}
|
|
154
|
-
break;
|
|
155
|
-
// Remove nexus backup
|
|
156
|
-
case "remove-backup":
|
|
157
|
-
localStorage.removeItem(BACKUP_KEY);
|
|
158
|
-
break;
|
|
159
|
-
// Change iframe visibility
|
|
160
|
-
case "show":
|
|
161
|
-
case "hide":
|
|
162
|
-
changeIframeVisibility({
|
|
163
|
-
iframe,
|
|
164
|
-
isVisible: messageEvent.iframeLifecycle === "show"
|
|
165
|
-
});
|
|
166
|
-
break;
|
|
167
|
-
// Handshake handling
|
|
168
|
-
case "handshake": {
|
|
169
|
-
iframe.contentWindow?.postMessage(
|
|
170
|
-
{
|
|
171
|
-
clientLifecycle: "handshake-response",
|
|
172
|
-
data: {
|
|
173
|
-
token: messageEvent.data.token,
|
|
174
|
-
currentUrl: window.location.href
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
"*"
|
|
178
|
-
);
|
|
179
|
-
break;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
};
|
|
183
|
-
return {
|
|
184
|
-
handleEvent: handler,
|
|
185
|
-
isConnected: isConnectedDeferred.promise
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// src/clients/transports/iframeMessageHandler.ts
|
|
190
|
-
function createIFrameMessageHandler({
|
|
191
|
-
frakWalletUrl,
|
|
192
|
-
iframe,
|
|
193
|
-
channelManager,
|
|
194
|
-
iframeLifecycleManager,
|
|
195
|
-
debugInfo
|
|
196
|
-
}) {
|
|
197
|
-
if (typeof window === "undefined") {
|
|
198
|
-
throw new FrakRpcError(
|
|
199
|
-
RpcErrorCodes.configError,
|
|
200
|
-
"iframe client should be used in the browser"
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
if (!iframe.contentWindow) {
|
|
204
|
-
throw new FrakRpcError(
|
|
205
|
-
RpcErrorCodes.configError,
|
|
206
|
-
"The iframe does not have a product window"
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
const contentWindow = iframe.contentWindow;
|
|
210
|
-
async function msgHandler(event) {
|
|
211
|
-
if (!event.origin) {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
try {
|
|
215
|
-
if (new URL(event.origin).origin.toLowerCase() !== new URL(frakWalletUrl).origin.toLowerCase()) {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
} catch (e) {
|
|
219
|
-
console.log("Unable to check frak msg origin", e);
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
if (typeof event.data !== "object") {
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
debugInfo.setLastResponse(event);
|
|
226
|
-
if ("iframeLifecycle" in event.data) {
|
|
227
|
-
await iframeLifecycleManager.handleEvent(event.data);
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
if ("clientLifecycle" in event.data) {
|
|
231
|
-
console.error(
|
|
232
|
-
"Client lifecycle event received on the client side, dismissing it"
|
|
233
|
-
);
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
const channel = event.data.id;
|
|
237
|
-
const resolver = channelManager.getRpcResolver(channel);
|
|
238
|
-
if (!resolver) {
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
await resolver(event.data);
|
|
242
|
-
}
|
|
243
|
-
window.addEventListener("message", msgHandler);
|
|
244
|
-
function sendEvent(message) {
|
|
245
|
-
contentWindow.postMessage(message, {
|
|
246
|
-
targetOrigin: frakWalletUrl
|
|
247
|
-
});
|
|
248
|
-
debugInfo.setLastRequest(message, frakWalletUrl);
|
|
249
|
-
}
|
|
250
|
-
function cleanup() {
|
|
251
|
-
window.removeEventListener("message", msgHandler);
|
|
252
|
-
}
|
|
253
|
-
return {
|
|
254
|
-
sendEvent,
|
|
255
|
-
cleanup
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// src/clients/createIFrameFrakClient.ts
|
|
260
|
-
function createIFrameFrakClient({
|
|
261
|
-
config,
|
|
262
|
-
iframe
|
|
263
|
-
}) {
|
|
264
|
-
const channelManager = createIFrameChannelManager();
|
|
265
|
-
const lifecycleManager = createIFrameLifecycleManager({ iframe });
|
|
266
|
-
const debugInfo = new DebugInfoGatherer(config, iframe);
|
|
267
|
-
const messageHandler = createIFrameMessageHandler({
|
|
268
|
-
frakWalletUrl: config?.walletUrl ?? "https://wallet.frak.id",
|
|
269
|
-
iframe,
|
|
270
|
-
channelManager,
|
|
271
|
-
iframeLifecycleManager: lifecycleManager,
|
|
272
|
-
debugInfo
|
|
273
|
-
});
|
|
274
|
-
const request = async (args) => {
|
|
275
|
-
const isConnected = await lifecycleManager.isConnected;
|
|
276
|
-
if (!isConnected) {
|
|
277
|
-
throw new FrakRpcError(
|
|
278
|
-
RpcErrorCodes.clientNotConnected,
|
|
279
|
-
"The iframe provider isn't connected yet"
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
const result = new Deferred();
|
|
283
|
-
const channelId = channelManager.createChannel(async (message) => {
|
|
284
|
-
const decompressed = await decompressDataAndCheckHash(message.data);
|
|
285
|
-
if (decompressed.error) {
|
|
286
|
-
result.reject(
|
|
287
|
-
new FrakRpcError(
|
|
288
|
-
decompressed.error.code,
|
|
289
|
-
decompressed.error.message,
|
|
290
|
-
decompressed.error?.data
|
|
291
|
-
)
|
|
292
|
-
);
|
|
293
|
-
} else {
|
|
294
|
-
result.resolve(decompressed.result);
|
|
295
|
-
}
|
|
296
|
-
channelManager.removeChannel(channelId);
|
|
297
|
-
});
|
|
298
|
-
const compressedMessage = await hashAndCompressData(args);
|
|
299
|
-
messageHandler.sendEvent({
|
|
300
|
-
id: channelId,
|
|
301
|
-
topic: args.method,
|
|
302
|
-
data: compressedMessage
|
|
303
|
-
});
|
|
304
|
-
return result.promise;
|
|
305
|
-
};
|
|
306
|
-
const listenerRequest = async (args, callback) => {
|
|
307
|
-
const isConnected = await lifecycleManager.isConnected;
|
|
308
|
-
if (!isConnected) {
|
|
309
|
-
throw new FrakRpcError(
|
|
310
|
-
RpcErrorCodes.clientNotConnected,
|
|
311
|
-
"The iframe provider isn't connected yet"
|
|
312
|
-
);
|
|
313
|
-
}
|
|
314
|
-
const channelId = channelManager.createChannel(async (message) => {
|
|
315
|
-
const decompressed = await decompressDataAndCheckHash(message.data);
|
|
316
|
-
if (decompressed.result) {
|
|
317
|
-
callback(decompressed.result);
|
|
318
|
-
} else {
|
|
319
|
-
throw new InternalError("No valid result in the response");
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
const compressedMessage = await hashAndCompressData(args);
|
|
323
|
-
messageHandler.sendEvent({
|
|
324
|
-
id: channelId,
|
|
325
|
-
topic: args.method,
|
|
326
|
-
data: compressedMessage
|
|
327
|
-
});
|
|
328
|
-
};
|
|
329
|
-
const stopHeartbeat = setupHeartbeat(messageHandler, lifecycleManager);
|
|
330
|
-
const destroy = async () => {
|
|
331
|
-
stopHeartbeat();
|
|
332
|
-
channelManager.destroy();
|
|
333
|
-
messageHandler.cleanup();
|
|
334
|
-
iframe.remove();
|
|
335
|
-
};
|
|
336
|
-
const waitForSetup = postConnectionSetup({
|
|
337
|
-
config,
|
|
338
|
-
messageHandler,
|
|
339
|
-
lifecycleManager
|
|
340
|
-
}).then(() => debugInfo.updateSetupStatus(true));
|
|
341
|
-
return {
|
|
342
|
-
config,
|
|
343
|
-
debugInfo,
|
|
344
|
-
waitForConnection: lifecycleManager.isConnected,
|
|
345
|
-
waitForSetup,
|
|
346
|
-
request,
|
|
347
|
-
listenerRequest,
|
|
348
|
-
destroy
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
|
-
function setupHeartbeat(messageHandler, lifecycleManager) {
|
|
352
|
-
const HEARTBEAT_INTERVAL = 100;
|
|
353
|
-
const HEARTBEAT_TIMEOUT = 3e4;
|
|
354
|
-
let heartbeatInterval;
|
|
355
|
-
let timeoutId;
|
|
356
|
-
const sendHeartbeat = () => messageHandler.sendEvent({
|
|
357
|
-
clientLifecycle: "heartbeat"
|
|
358
|
-
});
|
|
359
|
-
async function startHeartbeat() {
|
|
360
|
-
sendHeartbeat();
|
|
361
|
-
heartbeatInterval = setInterval(sendHeartbeat, HEARTBEAT_INTERVAL);
|
|
362
|
-
timeoutId = setTimeout(() => {
|
|
363
|
-
stopHeartbeat();
|
|
364
|
-
console.log("Heartbeat timeout: connection failed");
|
|
365
|
-
}, HEARTBEAT_TIMEOUT);
|
|
366
|
-
await lifecycleManager.isConnected;
|
|
367
|
-
stopHeartbeat();
|
|
368
|
-
}
|
|
369
|
-
function stopHeartbeat() {
|
|
370
|
-
if (heartbeatInterval) {
|
|
371
|
-
clearInterval(heartbeatInterval);
|
|
372
|
-
}
|
|
373
|
-
if (timeoutId) {
|
|
374
|
-
clearTimeout(timeoutId);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
startHeartbeat();
|
|
378
|
-
return stopHeartbeat;
|
|
379
|
-
}
|
|
380
|
-
async function postConnectionSetup({
|
|
381
|
-
config,
|
|
382
|
-
messageHandler,
|
|
383
|
-
lifecycleManager
|
|
384
|
-
}) {
|
|
385
|
-
await lifecycleManager.isConnected;
|
|
386
|
-
const pushCss = async () => {
|
|
387
|
-
const cssLink = config.metadata.css;
|
|
388
|
-
if (!cssLink) return;
|
|
389
|
-
messageHandler.sendEvent({
|
|
390
|
-
clientLifecycle: "modal-css",
|
|
391
|
-
data: { cssLink }
|
|
392
|
-
});
|
|
393
|
-
};
|
|
394
|
-
const pushBackup = async () => {
|
|
395
|
-
if (typeof window === "undefined") return;
|
|
396
|
-
const backup = window.localStorage.getItem(BACKUP_KEY);
|
|
397
|
-
if (!backup) return;
|
|
398
|
-
messageHandler.sendEvent({
|
|
399
|
-
clientLifecycle: "restore-backup",
|
|
400
|
-
data: { backup }
|
|
401
|
-
});
|
|
402
|
-
};
|
|
403
|
-
await Promise.all([pushCss(), pushBackup()]);
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
// src/clients/setupClient.ts
|
|
407
|
-
async function setupClient({
|
|
408
|
-
config
|
|
409
|
-
}) {
|
|
410
|
-
const iframe = await createIframe({
|
|
411
|
-
config
|
|
412
|
-
});
|
|
413
|
-
if (!iframe) {
|
|
414
|
-
console.error("Failed to create iframe");
|
|
415
|
-
return;
|
|
416
|
-
}
|
|
417
|
-
const client = createIFrameFrakClient({
|
|
418
|
-
config,
|
|
419
|
-
iframe
|
|
420
|
-
});
|
|
421
|
-
await client.waitForSetup;
|
|
422
|
-
const waitForConnection = await client.waitForConnection;
|
|
423
|
-
if (!waitForConnection) {
|
|
424
|
-
console.error("Failed to connect to client");
|
|
425
|
-
return;
|
|
426
|
-
}
|
|
427
|
-
return client;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
export { DebugInfoGatherer, createIFrameFrakClient, 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()}}class c{_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)}}async function l(e){if(!(e?.compressed&&e?.compressedHash))throw new r(s.corruptedResponse,"Missing compressed data");let n=await d(e.compressed);if(!n)throw new r(s.corruptedResponse,"Invalid compressed data");if(!n?.validationHash)throw new r(s.corruptedResponse,"Missing validation hash");if((0,t.sha256)(e.compressed)!==e.compressedHash)throw new r(s.corruptedResponse,"Invalid compressed hash");let{validationHash:a,...o}=n;if((0,t.sha256)(JSON.stringify(o))!==n.validationHash)throw new r(s.corruptedResponse,"Invalid data validation hash");return n}async function d(t){let n=await (0,e.decompressFromBase64)(t);try{return JSON.parse(n)}catch(e){return console.error("Invalid compressed data",{e,decompressed:n}),null}}async function u(e){let n=(0,t.sha256)(JSON.stringify(e)),r={...e,validationHash:n},a=await f(r),o=(0,t.sha256)(a);return{compressed:a,compressedHash:o}}async function f(t){return(0,e.compressToBase64)(JSON.stringify(t))}let p="nexus-wallet-backup",h={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 m({walletBaseUrl:e,config:t}){let n=document.querySelector("#nexus-wallet");n&&n.remove();let r=document.createElement("iframe");return r.id=h.id,r.name=h.name,r.allow=h.allow,r.style.zIndex=h.style.zIndex.toString(),w({iframe:r,isVisible:!1}),document.body.appendChild(r),new Promise(n=>{r?.addEventListener("load",()=>n(r)),r.src=`${t?.walletUrl??e??"https://wallet.frak.id"}/listener`})}function w({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 g({config:e,iframe:t}){let n=function(){let e=new Map;return{createChannel:t=>{let n=Math.random().toString(36).substring(7);return e.set(n,t),n},getRpcResolver:t=>e.get(t),removeChannel:t=>e.delete(t),destroy:()=>e.clear()}}(),o=function({iframe:e}){let t=new c;return{handleEvent:async n=>{switch(n.iframeLifecycle){case"connected":t.resolve(!0);break;case"do-backup":n.data.backup?localStorage.setItem(p,n.data.backup):localStorage.removeItem(p);break;case"remove-backup":localStorage.removeItem(p);break;case"show":case"hide":w({iframe:e,isVisible:"show"===n.iframeLifecycle});break;case"handshake":e.contentWindow?.postMessage({clientLifecycle:"handshake-response",data:{token:n.data.token,currentUrl:window.location.href}},"*")}},isConnected:t.promise}}({iframe:t}),d=new i(e,t),f=function({frakWalletUrl:e,iframe:t,channelManager:n,iframeLifecycleManager:a,debugInfo:o}){if("undefined"==typeof window)throw new r(s.configError,"iframe client should be used in the browser");if(!t.contentWindow)throw new r(s.configError,"The iframe does not have a product window");let i=t.contentWindow;async function c(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(o.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 r=t.data.id,s=n.getRpcResolver(r);s&&await s(t.data)}return window.addEventListener("message",c),{sendEvent:function(t){i.postMessage(t,{targetOrigin:e}),o.setLastRequest(t,e)},cleanup:function(){window.removeEventListener("message",c)}}}({frakWalletUrl:e?.walletUrl??"https://wallet.frak.id",iframe:t,channelManager:n,iframeLifecycleManager:o,debugInfo:d}),h=async e=>{if(!await o.isConnected)throw new r(s.clientNotConnected,"The iframe provider isn't connected yet");let t=new c,a=n.createChannel(async e=>{let o=await l(e.data);o.error?t.reject(new r(o.error.code,o.error.message,o.error?.data)):t.resolve(o.result),n.removeChannel(a)}),i=await u(e);return f.sendEvent({id:a,topic:e.method,data:i}),t.promise},m=async(e,t)=>{if(!await o.isConnected)throw new r(s.clientNotConnected,"The iframe provider isn't connected yet");let i=n.createChannel(async e=>{let n=await l(e.data);if(n.result)t(n.result);else throw new a("No valid result in the response")}),c=await u(e);f.sendEvent({id:i,topic:e.method,data:c})},g=function(e,t){let n,r;let a=()=>e.sendEvent({clientLifecycle:"heartbeat"});function o(){n&&clearInterval(n),r&&clearTimeout(r)}return async function(){a(),n=setInterval(a,100),r=setTimeout(()=>{o(),console.log("Heartbeat timeout: connection failed")},3e4),await t.isConnected,o()}(),o}(f,o),v=async()=>{g(),n.destroy(),f.cleanup(),t.remove()},b=y({config:e,messageHandler:f,lifecycleManager:o}).then(()=>d.updateSetupStatus(!0));return{config:e,debugInfo:d,waitForConnection:o.isConnected,waitForSetup:b,request:h,listenerRequest:m,destroy:v}}async function y({config:e,messageHandler:t,lifecycleManager:n}){await n.isConnected;let r=async()=>{let n=e.metadata.css;n&&t.sendEvent({clientLifecycle:"modal-css",data:{cssLink:n}})},a=async()=>{if("undefined"==typeof window)return;let e=window.localStorage.getItem(p);e&&t.sendEvent({clientLifecycle:"restore-backup",data:{backup:e}})};await Promise.all([r(),a()])}async function v({config:e}){let t=await m({config:e});if(!t){console.error("Failed to create iframe");return}let n=g({config:e,iframe:t});if(await n.waitForSetup,!await n.waitForConnection){console.error("Failed to connect to client");return}return n}let b="fCtx";function R(e){if(e?.r)try{var t;return t=(0,n.hexToBytes)(e.r),btoa(Array.from(t,e=>String.fromCharCode(e)).join("")).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}catch(t){console.error("Error compressing Frak context",{e:t,context:e})}}function C(e){if(e&&0!==e.length)try{let t=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))}(e);return{r:(0,n.bytesToHex)(t,{size:20})}}catch(t){console.error("Error decompressing Frak context",{e:t,context:e})}}function S({url:e}){if(!e)return null;let t=new URL(e).searchParams.get(b);return t?C(t):null}function x({url:e,context:t}){if(!e)return null;let n=S({url:e}),r=n?{...n,...t}:t;if(!r.r)return null;let a=R(r);if(!a)return null;let o=new URL(e);return o.searchParams.set(b,a),o.toString()}function E(e){let t=new URL(e);return t.searchParams.delete(b),t.toString()}let I={compress:R,decompress:C,parse:S,update:x,remove:E,replaceUrl:function({url:e,context:t}){let n;if(!window.location?.href||"undefined"==typeof window){console.error("No window found, can't update context");return}let r=e??window.location.href;(n=null!==t?x({url:r,context:t}):E(r))&&window.history.replaceState(null,"",n.toString())}},k={dapp:1,press:2,webshop:3,retail:4,referral:30,purchase:31},L=Object.entries(k).reduce((e,[t,n])=>(e[t]=BigInt(1)<<BigInt(n),e),{}),F={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"}};export{o as ClientNotFound,i as DebugInfoGatherer,c as Deferred,I as FrakContextManager,r as FrakRpcError,s as RpcErrorCodes,h as baseIframeProps,f as compressJson,g as createIFrameFrakClient,m as createIframe,l as decompressDataAndCheckHash,d as decompressJson,u as hashAndCompressData,F as interactionTypes,k as productTypes,L as productTypesMask,v as setupClient};
|
|
@@ -0,0 +1 @@
|
|
|
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,r){for(var t in r)__webpack_require__.o(r,t)&&!__webpack_require__.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},__webpack_require__.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},__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__,{RetailInteractionEncoder:()=>RetailInteractionEncoder,PressInteractionEncoder:()=>PressInteractionEncoder,WebShopInteractionEncoder:()=>WebShopInteractionEncoder,PurchaseInteractionEncoder:()=>PurchaseInteractionEncoder,ReferralInteractionEncoder:()=>ReferralInteractionEncoder});let external_viem_namespaceObject=require("viem"),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"}},productTypes={dapp:1,press:2,webshop:3,retail:4,referral:30,purchase:31},productTypesMask=Object.entries(productTypes).reduce((e,[r,t])=>(e[r]=BigInt(1)<<BigInt(t),e),{}),PressInteractionEncoder={openArticle({articleId:e}){let r=(0,external_viem_namespaceObject.concatHex)([interactionTypes.press.openArticle,(0,external_viem_namespaceObject.pad)(e,{size:32})]);return{handlerTypeDenominator:(0,external_viem_namespaceObject.toHex)(productTypes.press),interactionData:r}},readArticle({articleId:e}){let r=(0,external_viem_namespaceObject.concatHex)([interactionTypes.press.readArticle,(0,external_viem_namespaceObject.pad)(e,{size:32})]);return{handlerTypeDenominator:(0,external_viem_namespaceObject.toHex)(productTypes.press),interactionData:r}}},ReferralInteractionEncoder={createLink:()=>({handlerTypeDenominator:(0,external_viem_namespaceObject.toHex)(productTypes.referral),interactionData:interactionTypes.referral.createLink}),referred({referrer:e}){let r=(0,external_viem_namespaceObject.concatHex)([interactionTypes.referral.referred,(0,external_viem_namespaceObject.pad)(e,{size:32})]);return{handlerTypeDenominator:(0,external_viem_namespaceObject.toHex)(productTypes.referral),interactionData:r}}},PurchaseInteractionEncoder={startPurchase({purchaseId:e}){let r=(0,external_viem_namespaceObject.concatHex)([interactionTypes.purchase.started,(0,external_viem_namespaceObject.pad)(e,{size:32})]);return{handlerTypeDenominator:(0,external_viem_namespaceObject.toHex)(productTypes.purchase),interactionData:r}},completedPurchase({purchaseId:e,proof:r}){let t=(0,external_viem_namespaceObject.encodeAbiParameters)([{type:"uint256"},{type:"bytes32[]"}],[BigInt(e),r]),a=(0,external_viem_namespaceObject.concatHex)([interactionTypes.purchase.completed,t]);return{handlerTypeDenominator:(0,external_viem_namespaceObject.toHex)(productTypes.purchase),interactionData:a}},unsafeCompletedPurchase({purchaseId:e}){let r=(0,external_viem_namespaceObject.concatHex)([interactionTypes.purchase.unsafeCompleted,(0,external_viem_namespaceObject.pad)(e,{size:32})]);return{handlerTypeDenominator:(0,external_viem_namespaceObject.toHex)(productTypes.purchase),interactionData:r}}},WebShopInteractionEncoder={open:()=>({handlerTypeDenominator:(0,external_viem_namespaceObject.toHex)(productTypes.webshop),interactionData:interactionTypes.webshop.open})},RetailInteractionEncoder={customerMeeting({agencyId:e}){let r=(0,external_viem_namespaceObject.concatHex)([interactionTypes.retail.customerMeeting,(0,external_viem_namespaceObject.pad)(e,{size:32})]);return{handlerTypeDenominator:(0,external_viem_namespaceObject.toHex)(productTypes.retail),interactionData:r}}};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});
|