@frak-labs/core-sdk 0.1.0-beta.afa252b0 → 0.1.0-beta.b0bd1f8a
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.iife.js +14 -0
- package/dist/actions-CEEObPYc.js +1 -0
- package/dist/actions-DbQhWYx8.cjs +1 -0
- package/dist/actions.cjs +1 -1
- package/dist/actions.d.cts +3 -1481
- package/dist/actions.d.ts +3 -1481
- package/dist/actions.js +1 -1
- package/dist/bundle.cjs +1 -13
- package/dist/bundle.d.cts +6 -2087
- package/dist/bundle.d.ts +6 -2087
- package/dist/bundle.js +1 -13
- package/dist/index-7OZ39x1U.d.ts +195 -0
- package/dist/index-C6FxkWPC.d.cts +511 -0
- package/dist/index-UFX7xCg3.d.ts +351 -0
- package/dist/index-d8xS4ryI.d.ts +511 -0
- package/dist/index-p4FqSp8z.d.cts +351 -0
- package/dist/index-zDq-VlKx.d.cts +195 -0
- package/dist/index.cjs +1 -13
- package/dist/index.d.cts +4 -1387
- package/dist/index.d.ts +4 -1387
- package/dist/index.js +1 -13
- package/dist/interaction-DMJ3ZfaF.d.cts +45 -0
- package/dist/interaction-KX1h9a7V.d.ts +45 -0
- package/dist/interactions-DnfM3oe0.js +1 -0
- package/dist/interactions-EIXhNLf6.cjs +1 -0
- package/dist/interactions.cjs +1 -1
- package/dist/interactions.d.cts +2 -182
- package/dist/interactions.d.ts +2 -182
- package/dist/interactions.js +1 -1
- package/dist/openSso-D--Airj6.d.cts +1018 -0
- package/dist/openSso-DsKJ4y0j.d.ts +1018 -0
- package/dist/productTypes-BUkXJKZ7.cjs +1 -0
- package/dist/productTypes-CGb1MmBF.js +1 -0
- package/dist/src-B_xO0AR6.cjs +13 -0
- package/dist/src-D2d52OZa.js +13 -0
- package/dist/trackEvent-CHnYa85W.js +1 -0
- package/dist/trackEvent-GuQm_1Nm.cjs +1 -0
- package/package.json +23 -18
- package/src/actions/displayEmbeddedWallet.test.ts +194 -0
- package/src/actions/displayEmbeddedWallet.ts +20 -0
- package/src/actions/displayModal.test.ts +387 -0
- package/src/actions/displayModal.ts +131 -0
- package/src/actions/getProductInformation.test.ts +133 -0
- package/src/actions/getProductInformation.ts +14 -0
- package/src/actions/index.ts +29 -0
- package/src/actions/openSso.test.ts +407 -0
- package/src/actions/openSso.ts +116 -0
- package/src/actions/prepareSso.test.ts +223 -0
- package/src/actions/prepareSso.ts +48 -0
- package/src/actions/referral/processReferral.ts +230 -0
- package/src/actions/referral/referralInteraction.ts +57 -0
- package/src/actions/sendInteraction.test.ts +219 -0
- package/src/actions/sendInteraction.ts +32 -0
- package/src/actions/trackPurchaseStatus.test.ts +287 -0
- package/src/actions/trackPurchaseStatus.ts +53 -0
- package/src/actions/watchWalletStatus.test.ts +372 -0
- package/src/actions/watchWalletStatus.ts +94 -0
- package/src/actions/wrapper/modalBuilder.ts +212 -0
- package/src/actions/wrapper/sendTransaction.ts +62 -0
- package/src/actions/wrapper/siweAuthenticate.ts +94 -0
- package/src/bundle.ts +3 -0
- package/src/clients/DebugInfo.ts +182 -0
- package/src/clients/createIFrameFrakClient.ts +287 -0
- package/src/clients/index.ts +3 -0
- package/src/clients/setupClient.test.ts +343 -0
- package/src/clients/setupClient.ts +73 -0
- package/src/clients/transports/iframeLifecycleManager.test.ts +399 -0
- package/src/clients/transports/iframeLifecycleManager.ts +90 -0
- package/src/constants/interactionTypes.ts +44 -0
- package/src/constants/locales.ts +14 -0
- package/src/constants/productTypes.ts +33 -0
- package/src/index.ts +101 -0
- package/src/interactions/index.ts +5 -0
- package/src/interactions/pressEncoder.test.ts +215 -0
- package/src/interactions/pressEncoder.ts +53 -0
- package/src/interactions/purchaseEncoder.test.ts +291 -0
- package/src/interactions/purchaseEncoder.ts +99 -0
- package/src/interactions/referralEncoder.test.ts +170 -0
- package/src/interactions/referralEncoder.ts +47 -0
- package/src/interactions/retailEncoder.test.ts +107 -0
- package/src/interactions/retailEncoder.ts +37 -0
- package/src/interactions/webshopEncoder.test.ts +56 -0
- package/src/interactions/webshopEncoder.ts +30 -0
- package/src/types/client.ts +14 -0
- package/src/types/compression.ts +22 -0
- package/src/types/config.ts +111 -0
- package/src/types/context.ts +13 -0
- package/src/types/index.ts +71 -0
- package/src/types/lifecycle/client.ts +46 -0
- package/src/types/lifecycle/iframe.ts +35 -0
- package/src/types/lifecycle/index.ts +2 -0
- package/src/types/rpc/displayModal.ts +84 -0
- package/src/types/rpc/embedded/index.ts +68 -0
- package/src/types/rpc/embedded/loggedIn.ts +55 -0
- package/src/types/rpc/embedded/loggedOut.ts +28 -0
- package/src/types/rpc/interaction.ts +43 -0
- package/src/types/rpc/modal/final.ts +46 -0
- package/src/types/rpc/modal/generic.ts +46 -0
- package/src/types/rpc/modal/index.ts +20 -0
- package/src/types/rpc/modal/login.ts +32 -0
- package/src/types/rpc/modal/openSession.ts +25 -0
- package/src/types/rpc/modal/siweAuthenticate.ts +37 -0
- package/src/types/rpc/modal/transaction.ts +33 -0
- package/src/types/rpc/productInformation.ts +59 -0
- package/src/types/rpc/sso.ts +80 -0
- package/src/types/rpc/walletStatus.ts +35 -0
- package/src/types/rpc.ts +158 -0
- package/src/types/transport.ts +34 -0
- package/src/utils/FrakContext.test.ts +407 -0
- package/src/utils/FrakContext.ts +158 -0
- package/src/utils/compression/b64.test.ts +181 -0
- package/src/utils/compression/b64.ts +29 -0
- package/src/utils/compression/compress.test.ts +123 -0
- package/src/utils/compression/compress.ts +11 -0
- package/src/utils/compression/decompress.test.ts +145 -0
- package/src/utils/compression/decompress.ts +11 -0
- package/src/utils/compression/index.ts +3 -0
- package/src/utils/computeProductId.test.ts +80 -0
- package/src/utils/computeProductId.ts +11 -0
- package/src/utils/constants.test.ts +23 -0
- package/src/utils/constants.ts +4 -0
- package/src/utils/formatAmount.test.ts +113 -0
- package/src/utils/formatAmount.ts +18 -0
- package/src/utils/getCurrencyAmountKey.test.ts +44 -0
- package/src/utils/getCurrencyAmountKey.ts +15 -0
- package/src/utils/getSupportedCurrency.test.ts +51 -0
- package/src/utils/getSupportedCurrency.ts +14 -0
- package/src/utils/getSupportedLocale.test.ts +64 -0
- package/src/utils/getSupportedLocale.ts +16 -0
- package/src/utils/iframeHelper.test.ts +450 -0
- package/src/utils/iframeHelper.ts +143 -0
- package/src/utils/index.ts +21 -0
- package/src/utils/sso.test.ts +361 -0
- package/src/utils/sso.ts +119 -0
- package/src/utils/ssoUrlListener.ts +60 -0
- package/src/utils/trackEvent.test.ts +162 -0
- package/src/utils/trackEvent.ts +26 -0
- package/cdn/bundle.js +0 -19
- package/cdn/bundle.js.LICENSE.txt +0 -10
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, test, vi } from "vitest";
|
|
2
|
+
|
|
3
|
+
// Mock dependencies
|
|
4
|
+
vi.mock("@frak-labs/frame-connector", () => ({
|
|
5
|
+
Deferred: class {
|
|
6
|
+
promise: Promise<any>;
|
|
7
|
+
resolve!: (value: any) => void;
|
|
8
|
+
reject!: (error: any) => void;
|
|
9
|
+
|
|
10
|
+
constructor() {
|
|
11
|
+
this.promise = new Promise((resolve, reject) => {
|
|
12
|
+
this.resolve = resolve;
|
|
13
|
+
this.reject = reject;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
vi.mock("../../utils/constants", () => ({
|
|
20
|
+
BACKUP_KEY: "frak-backup-key",
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
vi.mock("../../utils/iframeHelper", () => ({
|
|
24
|
+
changeIframeVisibility: vi.fn(),
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
describe("createIFrameLifecycleManager", () => {
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
vi.clearAllMocks();
|
|
30
|
+
// Reset localStorage
|
|
31
|
+
localStorage.clear();
|
|
32
|
+
// Mock window.location
|
|
33
|
+
Object.defineProperty(window, "location", {
|
|
34
|
+
value: { href: "https://test.com" },
|
|
35
|
+
writable: true,
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe("manager initialization", () => {
|
|
40
|
+
test("should create manager with correct properties", async () => {
|
|
41
|
+
const { createIFrameLifecycleManager } = await import(
|
|
42
|
+
"./iframeLifecycleManager"
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const mockIframe = document.createElement("iframe");
|
|
46
|
+
const manager = createIFrameLifecycleManager({
|
|
47
|
+
iframe: mockIframe,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect(manager).toBeDefined();
|
|
51
|
+
expect(manager.isConnected).toBeInstanceOf(Promise);
|
|
52
|
+
expect(manager.handleEvent).toBeInstanceOf(Function);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("should start with unresolved isConnected promise", async () => {
|
|
56
|
+
const { createIFrameLifecycleManager } = await import(
|
|
57
|
+
"./iframeLifecycleManager"
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const mockIframe = document.createElement("iframe");
|
|
61
|
+
const manager = createIFrameLifecycleManager({
|
|
62
|
+
iframe: mockIframe,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
let resolved = false;
|
|
66
|
+
manager.isConnected.then(() => {
|
|
67
|
+
resolved = true;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Wait a tick
|
|
71
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
72
|
+
expect(resolved).toBe(false);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe("connected event", () => {
|
|
77
|
+
test("should resolve isConnected on connected event", async () => {
|
|
78
|
+
const { createIFrameLifecycleManager } = await import(
|
|
79
|
+
"./iframeLifecycleManager"
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const mockIframe = document.createElement("iframe");
|
|
83
|
+
const manager = createIFrameLifecycleManager({
|
|
84
|
+
iframe: mockIframe,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const event = {
|
|
88
|
+
iframeLifecycle: "connected" as const,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
await manager.handleEvent(event);
|
|
92
|
+
|
|
93
|
+
await expect(manager.isConnected).resolves.toBe(true);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe("backup events", () => {
|
|
98
|
+
test("should save backup to localStorage on do-backup", async () => {
|
|
99
|
+
const { createIFrameLifecycleManager } = await import(
|
|
100
|
+
"./iframeLifecycleManager"
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const mockIframe = document.createElement("iframe");
|
|
104
|
+
const manager = createIFrameLifecycleManager({
|
|
105
|
+
iframe: mockIframe,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const backup = "encrypted-backup-data";
|
|
109
|
+
const event = {
|
|
110
|
+
iframeLifecycle: "do-backup" as const,
|
|
111
|
+
data: { backup },
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
await manager.handleEvent(event);
|
|
115
|
+
|
|
116
|
+
expect(localStorage.getItem("frak-backup-key")).toBe(backup);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("should remove backup when data.backup is undefined", async () => {
|
|
120
|
+
const { createIFrameLifecycleManager } = await import(
|
|
121
|
+
"./iframeLifecycleManager"
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const mockIframe = document.createElement("iframe");
|
|
125
|
+
const manager = createIFrameLifecycleManager({
|
|
126
|
+
iframe: mockIframe,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// First set a backup
|
|
130
|
+
localStorage.setItem("frak-backup-key", "old-backup");
|
|
131
|
+
|
|
132
|
+
const event = {
|
|
133
|
+
iframeLifecycle: "do-backup" as const,
|
|
134
|
+
data: {},
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
await manager.handleEvent(event);
|
|
138
|
+
|
|
139
|
+
expect(localStorage.getItem("frak-backup-key")).toBeNull();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("should remove backup on remove-backup event", async () => {
|
|
143
|
+
const { createIFrameLifecycleManager } = await import(
|
|
144
|
+
"./iframeLifecycleManager"
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const mockIframe = document.createElement("iframe");
|
|
148
|
+
const manager = createIFrameLifecycleManager({
|
|
149
|
+
iframe: mockIframe,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// First set a backup
|
|
153
|
+
localStorage.setItem("frak-backup-key", "backup-to-remove");
|
|
154
|
+
|
|
155
|
+
const event = {
|
|
156
|
+
iframeLifecycle: "remove-backup" as const,
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
await manager.handleEvent(event);
|
|
160
|
+
|
|
161
|
+
expect(localStorage.getItem("frak-backup-key")).toBeNull();
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
describe("visibility events", () => {
|
|
166
|
+
test("should show iframe on show event", async () => {
|
|
167
|
+
const { createIFrameLifecycleManager } = await import(
|
|
168
|
+
"./iframeLifecycleManager"
|
|
169
|
+
);
|
|
170
|
+
const { changeIframeVisibility } = await import(
|
|
171
|
+
"../../utils/iframeHelper"
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
const mockIframe = document.createElement("iframe");
|
|
175
|
+
const manager = createIFrameLifecycleManager({
|
|
176
|
+
iframe: mockIframe,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
const event = {
|
|
180
|
+
iframeLifecycle: "show" as const,
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
await manager.handleEvent(event);
|
|
184
|
+
|
|
185
|
+
expect(changeIframeVisibility).toHaveBeenCalledWith({
|
|
186
|
+
iframe: mockIframe,
|
|
187
|
+
isVisible: true,
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test("should hide iframe on hide event", async () => {
|
|
192
|
+
const { createIFrameLifecycleManager } = await import(
|
|
193
|
+
"./iframeLifecycleManager"
|
|
194
|
+
);
|
|
195
|
+
const { changeIframeVisibility } = await import(
|
|
196
|
+
"../../utils/iframeHelper"
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
const mockIframe = document.createElement("iframe");
|
|
200
|
+
const manager = createIFrameLifecycleManager({
|
|
201
|
+
iframe: mockIframe,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const event = {
|
|
205
|
+
iframeLifecycle: "hide" as const,
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
await manager.handleEvent(event);
|
|
209
|
+
|
|
210
|
+
expect(changeIframeVisibility).toHaveBeenCalledWith({
|
|
211
|
+
iframe: mockIframe,
|
|
212
|
+
isVisible: false,
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe("handshake event", () => {
|
|
218
|
+
test("should post handshake-response with token", async () => {
|
|
219
|
+
const { createIFrameLifecycleManager } = await import(
|
|
220
|
+
"./iframeLifecycleManager"
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
const mockPostMessage = vi.fn();
|
|
224
|
+
const mockIframe = {
|
|
225
|
+
contentWindow: {
|
|
226
|
+
postMessage: mockPostMessage,
|
|
227
|
+
},
|
|
228
|
+
} as any;
|
|
229
|
+
|
|
230
|
+
const manager = createIFrameLifecycleManager({
|
|
231
|
+
iframe: mockIframe,
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
const event = {
|
|
235
|
+
iframeLifecycle: "handshake" as const,
|
|
236
|
+
data: { token: "handshake-token-123" },
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
await manager.handleEvent(event);
|
|
240
|
+
|
|
241
|
+
expect(mockPostMessage).toHaveBeenCalledWith(
|
|
242
|
+
{
|
|
243
|
+
clientLifecycle: "handshake-response",
|
|
244
|
+
data: {
|
|
245
|
+
token: "handshake-token-123",
|
|
246
|
+
currentUrl: "https://test.com",
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
"*"
|
|
250
|
+
);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
test("should include current URL in handshake response", async () => {
|
|
254
|
+
const { createIFrameLifecycleManager } = await import(
|
|
255
|
+
"./iframeLifecycleManager"
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
Object.defineProperty(window, "location", {
|
|
259
|
+
value: { href: "https://example.com/page?param=value" },
|
|
260
|
+
writable: true,
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
const mockPostMessage = vi.fn();
|
|
264
|
+
const mockIframe = {
|
|
265
|
+
contentWindow: {
|
|
266
|
+
postMessage: mockPostMessage,
|
|
267
|
+
},
|
|
268
|
+
} as any;
|
|
269
|
+
|
|
270
|
+
const manager = createIFrameLifecycleManager({
|
|
271
|
+
iframe: mockIframe,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const event = {
|
|
275
|
+
iframeLifecycle: "handshake" as const,
|
|
276
|
+
data: { token: "token" },
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
await manager.handleEvent(event);
|
|
280
|
+
|
|
281
|
+
expect(mockPostMessage).toHaveBeenCalledWith(
|
|
282
|
+
expect.objectContaining({
|
|
283
|
+
data: expect.objectContaining({
|
|
284
|
+
currentUrl: "https://example.com/page?param=value",
|
|
285
|
+
}),
|
|
286
|
+
}),
|
|
287
|
+
"*"
|
|
288
|
+
);
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
describe("redirect event", () => {
|
|
293
|
+
test("should redirect with appended current URL", async () => {
|
|
294
|
+
const { createIFrameLifecycleManager } = await import(
|
|
295
|
+
"./iframeLifecycleManager"
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
Object.defineProperty(window, "location", {
|
|
299
|
+
value: {
|
|
300
|
+
href: "https://original.com",
|
|
301
|
+
},
|
|
302
|
+
writable: true,
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
const mockIframe = document.createElement("iframe");
|
|
306
|
+
const manager = createIFrameLifecycleManager({
|
|
307
|
+
iframe: mockIframe,
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
const event = {
|
|
311
|
+
iframeLifecycle: "redirect" as const,
|
|
312
|
+
data: {
|
|
313
|
+
baseRedirectUrl: "https://redirect.com?u=placeholder",
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
await manager.handleEvent(event);
|
|
318
|
+
|
|
319
|
+
expect(window.location.href).toBe(
|
|
320
|
+
"https://redirect.com/?u=https%3A%2F%2Foriginal.com"
|
|
321
|
+
);
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
test("should redirect without modification if no u parameter", async () => {
|
|
325
|
+
const { createIFrameLifecycleManager } = await import(
|
|
326
|
+
"./iframeLifecycleManager"
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
Object.defineProperty(window, "location", {
|
|
330
|
+
value: {
|
|
331
|
+
href: "https://original.com",
|
|
332
|
+
},
|
|
333
|
+
writable: true,
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
const mockIframe = document.createElement("iframe");
|
|
337
|
+
const manager = createIFrameLifecycleManager({
|
|
338
|
+
iframe: mockIframe,
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
const event = {
|
|
342
|
+
iframeLifecycle: "redirect" as const,
|
|
343
|
+
data: {
|
|
344
|
+
baseRedirectUrl: "https://redirect.com/path",
|
|
345
|
+
},
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
await manager.handleEvent(event);
|
|
349
|
+
|
|
350
|
+
expect(window.location.href).toBe("https://redirect.com/path");
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
describe("event filtering", () => {
|
|
355
|
+
test("should ignore events without iframeLifecycle property", async () => {
|
|
356
|
+
const { createIFrameLifecycleManager } = await import(
|
|
357
|
+
"./iframeLifecycleManager"
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
const mockIframe = document.createElement("iframe");
|
|
361
|
+
const manager = createIFrameLifecycleManager({
|
|
362
|
+
iframe: mockIframe,
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
const event = {
|
|
366
|
+
someOtherEvent: "value",
|
|
367
|
+
} as any;
|
|
368
|
+
|
|
369
|
+
// Should not throw
|
|
370
|
+
await expect(manager.handleEvent(event)).resolves.toBeUndefined();
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
test("should only process events with iframeLifecycle", async () => {
|
|
374
|
+
const { createIFrameLifecycleManager } = await import(
|
|
375
|
+
"./iframeLifecycleManager"
|
|
376
|
+
);
|
|
377
|
+
const { changeIframeVisibility } = await import(
|
|
378
|
+
"../../utils/iframeHelper"
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
const mockIframe = document.createElement("iframe");
|
|
382
|
+
const manager = createIFrameLifecycleManager({
|
|
383
|
+
iframe: mockIframe,
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
// Event without iframeLifecycle
|
|
387
|
+
await manager.handleEvent({ randomEvent: "show" } as any);
|
|
388
|
+
|
|
389
|
+
// changeIframeVisibility should not be called
|
|
390
|
+
expect(changeIframeVisibility).not.toHaveBeenCalled();
|
|
391
|
+
|
|
392
|
+
// Event with iframeLifecycle
|
|
393
|
+
await manager.handleEvent({ iframeLifecycle: "show" as const });
|
|
394
|
+
|
|
395
|
+
// Now it should be called
|
|
396
|
+
expect(changeIframeVisibility).toHaveBeenCalled();
|
|
397
|
+
});
|
|
398
|
+
});
|
|
399
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Deferred } from "@frak-labs/frame-connector";
|
|
2
|
+
import type { FrakLifecycleEvent } from "../../types";
|
|
3
|
+
import { BACKUP_KEY } from "../../utils/constants";
|
|
4
|
+
import { changeIframeVisibility } from "../../utils/iframeHelper";
|
|
5
|
+
|
|
6
|
+
/** @ignore */
|
|
7
|
+
export type IframeLifecycleManager = {
|
|
8
|
+
isConnected: Promise<boolean>;
|
|
9
|
+
handleEvent: (messageEvent: FrakLifecycleEvent) => Promise<void>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Create a new iframe lifecycle handler
|
|
14
|
+
* @ignore
|
|
15
|
+
*/
|
|
16
|
+
export function createIFrameLifecycleManager({
|
|
17
|
+
iframe,
|
|
18
|
+
}: {
|
|
19
|
+
iframe: HTMLIFrameElement;
|
|
20
|
+
}): IframeLifecycleManager {
|
|
21
|
+
// Create the isConnected listener
|
|
22
|
+
const isConnectedDeferred = new Deferred<boolean>();
|
|
23
|
+
|
|
24
|
+
// Build the handler itself
|
|
25
|
+
const handler = async (messageEvent: FrakLifecycleEvent) => {
|
|
26
|
+
if (!("iframeLifecycle" in messageEvent)) return;
|
|
27
|
+
|
|
28
|
+
const { iframeLifecycle: event, data } = messageEvent;
|
|
29
|
+
|
|
30
|
+
switch (event) {
|
|
31
|
+
// Resolve the isConnected promise
|
|
32
|
+
case "connected":
|
|
33
|
+
isConnectedDeferred.resolve(true);
|
|
34
|
+
break;
|
|
35
|
+
// Perform a frak backup
|
|
36
|
+
case "do-backup":
|
|
37
|
+
if (data.backup) {
|
|
38
|
+
localStorage.setItem(BACKUP_KEY, data.backup);
|
|
39
|
+
} else {
|
|
40
|
+
localStorage.removeItem(BACKUP_KEY);
|
|
41
|
+
}
|
|
42
|
+
break;
|
|
43
|
+
// Remove frak backup
|
|
44
|
+
case "remove-backup":
|
|
45
|
+
localStorage.removeItem(BACKUP_KEY);
|
|
46
|
+
break;
|
|
47
|
+
// Change iframe visibility
|
|
48
|
+
case "show":
|
|
49
|
+
case "hide":
|
|
50
|
+
changeIframeVisibility({
|
|
51
|
+
iframe,
|
|
52
|
+
isVisible: event === "show",
|
|
53
|
+
});
|
|
54
|
+
break;
|
|
55
|
+
// Handshake handling
|
|
56
|
+
case "handshake": {
|
|
57
|
+
iframe.contentWindow?.postMessage(
|
|
58
|
+
{
|
|
59
|
+
clientLifecycle: "handshake-response",
|
|
60
|
+
data: {
|
|
61
|
+
token: data.token,
|
|
62
|
+
currentUrl: window.location.href,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
"*"
|
|
66
|
+
);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
// Redirect handling
|
|
70
|
+
case "redirect": {
|
|
71
|
+
const redirectUrl = new URL(data.baseRedirectUrl);
|
|
72
|
+
|
|
73
|
+
// If we got a u append the current location dynamicly
|
|
74
|
+
if (redirectUrl.searchParams.has("u")) {
|
|
75
|
+
redirectUrl.searchParams.delete("u");
|
|
76
|
+
redirectUrl.searchParams.append("u", window.location.href);
|
|
77
|
+
window.location.href = redirectUrl.toString();
|
|
78
|
+
} else {
|
|
79
|
+
window.location.href = data.baseRedirectUrl;
|
|
80
|
+
}
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
handleEvent: handler,
|
|
88
|
+
isConnected: isConnectedDeferred.promise,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The final keys for each interaction types (e.g. `openArticle`) -> interaction type
|
|
3
|
+
* @inline
|
|
4
|
+
*/
|
|
5
|
+
export type InteractionTypesKey = {
|
|
6
|
+
[K in keyof typeof interactionTypes]: keyof (typeof interactionTypes)[K];
|
|
7
|
+
}[keyof typeof interactionTypes];
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The keys for each interaction types (e.g. `press.openArticle`) -> category_type.interaction_type
|
|
11
|
+
* @inline
|
|
12
|
+
*/
|
|
13
|
+
export type FullInteractionTypesKey = {
|
|
14
|
+
[Category in keyof typeof interactionTypes]: `${Category & string}.${keyof (typeof interactionTypes)[Category] & string}`;
|
|
15
|
+
}[keyof typeof interactionTypes];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Each interactions types according to the product types
|
|
19
|
+
*/
|
|
20
|
+
export const interactionTypes = {
|
|
21
|
+
press: {
|
|
22
|
+
openArticle: "0xc0a24ffb",
|
|
23
|
+
readArticle: "0xd5bd0fbe",
|
|
24
|
+
},
|
|
25
|
+
dapp: {
|
|
26
|
+
proofVerifiableStorageUpdate: "0x2ab2aeef",
|
|
27
|
+
callableVerifiableStorageUpdate: "0xa07da986",
|
|
28
|
+
},
|
|
29
|
+
webshop: {
|
|
30
|
+
open: "0xb311798f",
|
|
31
|
+
},
|
|
32
|
+
referral: {
|
|
33
|
+
referred: "0x010cc3b9",
|
|
34
|
+
createLink: "0xb2c0f17c",
|
|
35
|
+
},
|
|
36
|
+
purchase: {
|
|
37
|
+
started: "0xd87e90c3",
|
|
38
|
+
completed: "0x8403aeb4",
|
|
39
|
+
unsafeCompleted: "0x4d5b14e0",
|
|
40
|
+
},
|
|
41
|
+
retail: {
|
|
42
|
+
customerMeeting: "0x74489004",
|
|
43
|
+
},
|
|
44
|
+
} as const;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The keys for each product types
|
|
3
|
+
* @inline
|
|
4
|
+
*/
|
|
5
|
+
export type ProductTypesKey = keyof typeof productTypes;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* List of the product types per denominator
|
|
9
|
+
*/
|
|
10
|
+
export const productTypes = {
|
|
11
|
+
// content type
|
|
12
|
+
dapp: 1,
|
|
13
|
+
press: 2,
|
|
14
|
+
webshop: 3,
|
|
15
|
+
retail: 4,
|
|
16
|
+
|
|
17
|
+
// feature type
|
|
18
|
+
referral: 30,
|
|
19
|
+
purchase: 31,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Bitmask for each product types
|
|
24
|
+
*/
|
|
25
|
+
export const productTypesMask: Record<ProductTypesKey, bigint> = Object.entries(
|
|
26
|
+
productTypes
|
|
27
|
+
).reduce(
|
|
28
|
+
(acc, [key, value]) => {
|
|
29
|
+
acc[key as ProductTypesKey] = BigInt(1) << BigInt(value);
|
|
30
|
+
return acc;
|
|
31
|
+
},
|
|
32
|
+
{} as Record<ProductTypesKey, bigint>
|
|
33
|
+
);
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// Clients
|
|
2
|
+
|
|
3
|
+
export { ssoPopupFeatures, ssoPopupName } from "./actions/openSso";
|
|
4
|
+
export {
|
|
5
|
+
createIFrameFrakClient,
|
|
6
|
+
DebugInfoGatherer,
|
|
7
|
+
setupClient,
|
|
8
|
+
} from "./clients";
|
|
9
|
+
export {
|
|
10
|
+
type FullInteractionTypesKey,
|
|
11
|
+
type InteractionTypesKey,
|
|
12
|
+
interactionTypes,
|
|
13
|
+
} from "./constants/interactionTypes";
|
|
14
|
+
export { type LocalesKey, locales } from "./constants/locales";
|
|
15
|
+
// Constants
|
|
16
|
+
export {
|
|
17
|
+
type ProductTypesKey,
|
|
18
|
+
productTypes,
|
|
19
|
+
productTypesMask,
|
|
20
|
+
} from "./constants/productTypes";
|
|
21
|
+
// Types
|
|
22
|
+
export type {
|
|
23
|
+
ClientLifecycleEvent,
|
|
24
|
+
CompressedData,
|
|
25
|
+
Currency,
|
|
26
|
+
// RPC Embedded wallet
|
|
27
|
+
DisplayEmbeddedWalletParamsType,
|
|
28
|
+
DisplayEmbeddedWalletResultType,
|
|
29
|
+
DisplayModalParamsType,
|
|
30
|
+
EmbeddedViewActionReferred,
|
|
31
|
+
EmbeddedViewActionSharing,
|
|
32
|
+
FinalActionType,
|
|
33
|
+
FinalModalStepType,
|
|
34
|
+
// Client
|
|
35
|
+
FrakClient,
|
|
36
|
+
// Utils
|
|
37
|
+
FrakContext,
|
|
38
|
+
FrakLifecycleEvent,
|
|
39
|
+
// Config
|
|
40
|
+
FrakWalletSdkConfig,
|
|
41
|
+
GetProductInformationReturnType,
|
|
42
|
+
HashProtectedData,
|
|
43
|
+
I18nConfig,
|
|
44
|
+
IFrameLifecycleEvent,
|
|
45
|
+
IFrameRpcSchema,
|
|
46
|
+
// Transport
|
|
47
|
+
IFrameTransport,
|
|
48
|
+
// Compression
|
|
49
|
+
KeyProvider,
|
|
50
|
+
Language,
|
|
51
|
+
LocalizedI18nConfig,
|
|
52
|
+
LoggedInEmbeddedView,
|
|
53
|
+
LoggedOutEmbeddedView,
|
|
54
|
+
LoginModalStepType,
|
|
55
|
+
ModalRpcMetadata,
|
|
56
|
+
ModalRpcStepsInput,
|
|
57
|
+
ModalRpcStepsResultType,
|
|
58
|
+
// RPC Modal types
|
|
59
|
+
ModalStepMetadata,
|
|
60
|
+
// RPC Modal generics
|
|
61
|
+
ModalStepTypes,
|
|
62
|
+
OpenInteractionSessionModalStepType,
|
|
63
|
+
OpenInteractionSessionReturnType,
|
|
64
|
+
OpenSsoParamsType,
|
|
65
|
+
OpenSsoReturnType,
|
|
66
|
+
PreparedInteraction,
|
|
67
|
+
PrepareSsoParamsType,
|
|
68
|
+
PrepareSsoReturnType,
|
|
69
|
+
SendInteractionParamsType,
|
|
70
|
+
SendInteractionReturnType,
|
|
71
|
+
SendTransactionModalStepType,
|
|
72
|
+
SendTransactionReturnType,
|
|
73
|
+
SendTransactionTxType,
|
|
74
|
+
SiweAuthenticateModalStepType,
|
|
75
|
+
SiweAuthenticateReturnType,
|
|
76
|
+
SiweAuthenticationParams,
|
|
77
|
+
SsoMetadata,
|
|
78
|
+
TokenAmountType,
|
|
79
|
+
// Rpc
|
|
80
|
+
WalletStatusReturnType,
|
|
81
|
+
} from "./types";
|
|
82
|
+
// Utils
|
|
83
|
+
export {
|
|
84
|
+
type AppSpecificSsoMetadata,
|
|
85
|
+
base64urlDecode,
|
|
86
|
+
base64urlEncode,
|
|
87
|
+
baseIframeProps,
|
|
88
|
+
type CompressedSsoData,
|
|
89
|
+
compressJsonToB64,
|
|
90
|
+
createIframe,
|
|
91
|
+
decompressJsonFromB64,
|
|
92
|
+
FrakContextManager,
|
|
93
|
+
type FullSsoParams,
|
|
94
|
+
findIframeInOpener,
|
|
95
|
+
formatAmount,
|
|
96
|
+
generateSsoUrl,
|
|
97
|
+
getCurrencyAmountKey,
|
|
98
|
+
getSupportedCurrency,
|
|
99
|
+
getSupportedLocale,
|
|
100
|
+
trackEvent,
|
|
101
|
+
} from "./utils";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { PressInteractionEncoder } from "./pressEncoder";
|
|
2
|
+
export { PurchaseInteractionEncoder } from "./purchaseEncoder";
|
|
3
|
+
export { ReferralInteractionEncoder } from "./referralEncoder";
|
|
4
|
+
export { RetailInteractionEncoder } from "./retailEncoder";
|
|
5
|
+
export { WebShopInteractionEncoder } from "./webshopEncoder";
|