@frak-labs/core-sdk 0.2.1-beta.d2556d47 → 0.2.1-beta.eb3cff34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cdn/bundle.js +3 -55
- package/dist/actions-D4aBXbdp.cjs +1 -0
- package/dist/actions-Dq_uN-wn.js +1 -0
- package/dist/actions.cjs +1 -1
- package/dist/actions.d.cts +3 -3
- package/dist/actions.d.ts +3 -3
- package/dist/actions.js +1 -1
- package/dist/bundle.cjs +1 -1
- package/dist/bundle.d.cts +4 -4
- package/dist/bundle.d.ts +4 -4
- package/dist/bundle.js +1 -1
- package/dist/{computeLegacyProductId-BP-ciVsp.d.cts → index-BV5D9DsW.d.ts} +71 -3
- package/dist/{siweAuthenticate-yITE-iKh.d.cts → index-BphwTmKA.d.cts} +115 -4
- package/dist/{computeLegacyProductId-DiJd7RNo.d.ts → index-Dwmo109y.d.cts} +71 -3
- package/dist/{siweAuthenticate-CDCsp8EJ.d.ts → index-_f8EuN_1.d.ts} +115 -4
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/{openSso-B8v3Vtnh.d.ts → openSso-BwEK2M98.d.cts} +174 -7
- package/dist/{openSso-n_B4LSuW.d.cts → openSso-C1Wzl5-i.d.ts} +174 -7
- package/dist/src-B3Dusips.cjs +13 -0
- package/dist/src-CnnhYPyK.js +13 -0
- package/dist/trackEvent-BqJqRZ-u.cjs +1 -0
- package/dist/trackEvent-Bqq4jd6R.js +1 -0
- package/package.json +9 -10
- package/src/actions/displaySharingPage.ts +49 -0
- package/src/actions/getMerchantInformation.test.ts +13 -1
- package/src/actions/getMerchantInformation.ts +20 -5
- package/src/actions/getMergeToken.ts +33 -0
- package/src/actions/getUserReferralStatus.ts +42 -0
- package/src/actions/index.ts +8 -1
- package/src/actions/referral/setupReferral.test.ts +79 -0
- package/src/actions/referral/setupReferral.ts +32 -0
- package/src/clients/createIFrameFrakClient.ts +5 -2
- package/src/clients/transports/iframeLifecycleManager.test.ts +14 -14
- package/src/clients/transports/iframeLifecycleManager.ts +35 -9
- package/src/index.ts +12 -1
- package/src/stubs/rrweb.ts +9 -0
- package/src/types/index.ts +7 -0
- package/src/types/lifecycle/iframe.ts +7 -0
- package/src/types/resolvedConfig.ts +26 -2
- package/src/types/rpc/displaySharingPage.ts +82 -0
- package/src/types/rpc/embedded/index.ts +1 -1
- package/src/types/rpc/userReferralStatus.ts +20 -0
- package/src/types/rpc.ts +47 -0
- package/src/utils/cache/index.ts +7 -0
- package/src/utils/cache/lruMap.test.ts +55 -0
- package/src/utils/cache/lruMap.ts +38 -0
- package/src/utils/cache/withCache.test.ts +168 -0
- package/src/utils/cache/withCache.ts +124 -0
- package/src/utils/inAppBrowser.ts +60 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/sdkConfigStore.ts +21 -35
- package/dist/setupClient-Dr_UYfTD.cjs +0 -13
- package/dist/setupClient-TuhDjVJx.js +0 -13
- package/dist/siweAuthenticate-0UPcUqI1.js +0 -1
- package/dist/siweAuthenticate-CfQibjZR.cjs +0 -1
- package/dist/trackEvent-5j5kkOCj.js +0 -1
- package/dist/trackEvent-B2uom25e.cjs +0 -1
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { REFERRAL_SUCCESS_EVENT, setupReferral } from "./setupReferral";
|
|
3
|
+
|
|
4
|
+
vi.mock("./referralInteraction", () => ({
|
|
5
|
+
referralInteraction: vi.fn(),
|
|
6
|
+
}));
|
|
7
|
+
|
|
8
|
+
import { referralInteraction } from "./referralInteraction";
|
|
9
|
+
|
|
10
|
+
describe("setupReferral", () => {
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
vi.clearAllMocks();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
vi.restoreAllMocks();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("should dispatch referral success event on successful referral", async () => {
|
|
20
|
+
vi.mocked(referralInteraction).mockResolvedValue("success");
|
|
21
|
+
const listener = vi.fn();
|
|
22
|
+
window.addEventListener(REFERRAL_SUCCESS_EVENT, listener);
|
|
23
|
+
|
|
24
|
+
await setupReferral({ config: {} } as any);
|
|
25
|
+
|
|
26
|
+
expect(listener).toHaveBeenCalledTimes(1);
|
|
27
|
+
expect(listener).toHaveBeenCalledWith(expect.any(Event));
|
|
28
|
+
|
|
29
|
+
window.removeEventListener(REFERRAL_SUCCESS_EVENT, listener);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("should not dispatch event when referral state is not success", async () => {
|
|
33
|
+
vi.mocked(referralInteraction).mockResolvedValue("no-referrer");
|
|
34
|
+
const listener = vi.fn();
|
|
35
|
+
window.addEventListener(REFERRAL_SUCCESS_EVENT, listener);
|
|
36
|
+
|
|
37
|
+
await setupReferral({ config: {} } as any);
|
|
38
|
+
|
|
39
|
+
expect(listener).not.toHaveBeenCalled();
|
|
40
|
+
|
|
41
|
+
window.removeEventListener(REFERRAL_SUCCESS_EVENT, listener);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should not dispatch event when referral returns undefined", async () => {
|
|
45
|
+
vi.mocked(referralInteraction).mockResolvedValue(undefined);
|
|
46
|
+
const listener = vi.fn();
|
|
47
|
+
window.addEventListener(REFERRAL_SUCCESS_EVENT, listener);
|
|
48
|
+
|
|
49
|
+
await setupReferral({ config: {} } as any);
|
|
50
|
+
|
|
51
|
+
expect(listener).not.toHaveBeenCalled();
|
|
52
|
+
|
|
53
|
+
window.removeEventListener(REFERRAL_SUCCESS_EVENT, listener);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("should silently catch errors and log warning", async () => {
|
|
57
|
+
vi.mocked(referralInteraction).mockRejectedValue(
|
|
58
|
+
new Error("network failure")
|
|
59
|
+
);
|
|
60
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
61
|
+
const listener = vi.fn();
|
|
62
|
+
window.addEventListener(REFERRAL_SUCCESS_EVENT, listener);
|
|
63
|
+
|
|
64
|
+
await setupReferral({ config: {} } as any);
|
|
65
|
+
|
|
66
|
+
expect(listener).not.toHaveBeenCalled();
|
|
67
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
68
|
+
"[Frak] Referral setup failed",
|
|
69
|
+
expect.any(Error)
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
window.removeEventListener(REFERRAL_SUCCESS_EVENT, listener);
|
|
73
|
+
warnSpy.mockRestore();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("should export the correct event name constant", () => {
|
|
77
|
+
expect(REFERRAL_SUCCESS_EVENT).toBe("frak:referral-success");
|
|
78
|
+
});
|
|
79
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { FrakClient } from "../../types";
|
|
2
|
+
import { referralInteraction } from "./referralInteraction";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Custom event name dispatched on successful referral processing.
|
|
6
|
+
*
|
|
7
|
+
* Fired once per page load when a valid referral context is found in the URL
|
|
8
|
+
* and successfully tracked. Consumers (e.g. `<frak-banner>`) listen for this
|
|
9
|
+
* to display a referral success message.
|
|
10
|
+
*/
|
|
11
|
+
export const REFERRAL_SUCCESS_EVENT = "frak:referral-success";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Process referral context and emit a DOM event on success.
|
|
15
|
+
*
|
|
16
|
+
* - Calls {@link referralInteraction} to detect and track any referral in the URL
|
|
17
|
+
* - On `"success"`, dispatches a bare {@link REFERRAL_SUCCESS_EVENT} on `window`
|
|
18
|
+
* - Silently swallows errors (fire-and-forget during SDK init)
|
|
19
|
+
*
|
|
20
|
+
* @param client - The initialized Frak client
|
|
21
|
+
*/
|
|
22
|
+
export async function setupReferral(client: FrakClient): Promise<void> {
|
|
23
|
+
try {
|
|
24
|
+
const state = await referralInteraction(client);
|
|
25
|
+
|
|
26
|
+
if (state === "success") {
|
|
27
|
+
window.dispatchEvent(new Event(REFERRAL_SUCCESS_EVENT));
|
|
28
|
+
}
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.warn("[Frak] Referral setup failed", error);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -12,6 +12,7 @@ import type { FrakWalletSdkConfig } from "../types/config";
|
|
|
12
12
|
import type { SdkResolvedConfig } from "../types/resolvedConfig";
|
|
13
13
|
import type { IFrameRpcSchema } from "../types/rpc";
|
|
14
14
|
import { getClientId } from "../utils";
|
|
15
|
+
import { clearAllCache } from "../utils/cache";
|
|
15
16
|
import { BACKUP_KEY } from "../utils/constants";
|
|
16
17
|
import { sdkConfigStore } from "../utils/sdkConfigStore";
|
|
17
18
|
import { setupSsoUrlListener } from "../utils/ssoUrlListener";
|
|
@@ -124,9 +125,9 @@ export function createIFrameFrakClient({
|
|
|
124
125
|
],
|
|
125
126
|
// Add lifecycle handlers to process iframe lifecycle events
|
|
126
127
|
lifecycleHandlers: {
|
|
127
|
-
iframeLifecycle:
|
|
128
|
+
iframeLifecycle: (event, _context) => {
|
|
128
129
|
// Delegate to lifecycle manager (cast for type compatibility)
|
|
129
|
-
|
|
130
|
+
lifecycleManager.handleEvent(event);
|
|
130
131
|
},
|
|
131
132
|
},
|
|
132
133
|
});
|
|
@@ -138,6 +139,7 @@ export function createIFrameFrakClient({
|
|
|
138
139
|
stopHeartbeat();
|
|
139
140
|
rpcClient.cleanup();
|
|
140
141
|
iframe.remove();
|
|
142
|
+
clearAllCache();
|
|
141
143
|
sdkConfigStore.clearCache();
|
|
142
144
|
sdkConfigStore.reset();
|
|
143
145
|
};
|
|
@@ -316,6 +318,7 @@ async function postConnectionSetup({
|
|
|
316
318
|
css: raw.css,
|
|
317
319
|
translations: raw.translations,
|
|
318
320
|
placements: raw.placements,
|
|
321
|
+
components: raw.components,
|
|
319
322
|
}
|
|
320
323
|
: {
|
|
321
324
|
isResolved: true,
|
|
@@ -102,7 +102,7 @@ describe("createIFrameLifecycleManager", () => {
|
|
|
102
102
|
iframeLifecycle: "connected" as const,
|
|
103
103
|
};
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
manager.handleEvent(event);
|
|
106
106
|
|
|
107
107
|
await expect(manager.isConnected).resolves.toBe(true);
|
|
108
108
|
});
|
|
@@ -126,7 +126,7 @@ describe("createIFrameLifecycleManager", () => {
|
|
|
126
126
|
data: { backup },
|
|
127
127
|
};
|
|
128
128
|
|
|
129
|
-
|
|
129
|
+
manager.handleEvent(event);
|
|
130
130
|
|
|
131
131
|
expect(localStorage.getItem("frak-backup-key")).toBe(backup);
|
|
132
132
|
});
|
|
@@ -150,7 +150,7 @@ describe("createIFrameLifecycleManager", () => {
|
|
|
150
150
|
data: {},
|
|
151
151
|
};
|
|
152
152
|
|
|
153
|
-
|
|
153
|
+
manager.handleEvent(event);
|
|
154
154
|
|
|
155
155
|
expect(localStorage.getItem("frak-backup-key")).toBeNull();
|
|
156
156
|
});
|
|
@@ -173,7 +173,7 @@ describe("createIFrameLifecycleManager", () => {
|
|
|
173
173
|
iframeLifecycle: "remove-backup" as const,
|
|
174
174
|
};
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
manager.handleEvent(event);
|
|
177
177
|
|
|
178
178
|
expect(localStorage.getItem("frak-backup-key")).toBeNull();
|
|
179
179
|
});
|
|
@@ -198,7 +198,7 @@ describe("createIFrameLifecycleManager", () => {
|
|
|
198
198
|
iframeLifecycle: "show" as const,
|
|
199
199
|
};
|
|
200
200
|
|
|
201
|
-
|
|
201
|
+
manager.handleEvent(event);
|
|
202
202
|
|
|
203
203
|
expect(changeIframeVisibility).toHaveBeenCalledWith({
|
|
204
204
|
iframe: mockIframe,
|
|
@@ -224,7 +224,7 @@ describe("createIFrameLifecycleManager", () => {
|
|
|
224
224
|
iframeLifecycle: "hide" as const,
|
|
225
225
|
};
|
|
226
226
|
|
|
227
|
-
|
|
227
|
+
manager.handleEvent(event);
|
|
228
228
|
|
|
229
229
|
expect(changeIframeVisibility).toHaveBeenCalledWith({
|
|
230
230
|
iframe: mockIframe,
|
|
@@ -259,7 +259,7 @@ describe("createIFrameLifecycleManager", () => {
|
|
|
259
259
|
},
|
|
260
260
|
};
|
|
261
261
|
|
|
262
|
-
|
|
262
|
+
manager.handleEvent(event);
|
|
263
263
|
|
|
264
264
|
expect(window.location.href).toBe(
|
|
265
265
|
"https://redirect.com/?u=https%3A%2F%2Foriginal.com"
|
|
@@ -291,7 +291,7 @@ describe("createIFrameLifecycleManager", () => {
|
|
|
291
291
|
},
|
|
292
292
|
};
|
|
293
293
|
|
|
294
|
-
|
|
294
|
+
manager.handleEvent(event);
|
|
295
295
|
|
|
296
296
|
expect(window.location.href).toBe("https://redirect.com/path");
|
|
297
297
|
});
|
|
@@ -325,7 +325,7 @@ describe("createIFrameLifecycleManager", () => {
|
|
|
325
325
|
},
|
|
326
326
|
};
|
|
327
327
|
|
|
328
|
-
|
|
328
|
+
manager.handleEvent(event);
|
|
329
329
|
|
|
330
330
|
expect(triggerDeepLinkWithFallback).toHaveBeenCalledWith(
|
|
331
331
|
"frakwallet://wallet",
|
|
@@ -370,7 +370,7 @@ describe("createIFrameLifecycleManager", () => {
|
|
|
370
370
|
},
|
|
371
371
|
};
|
|
372
372
|
|
|
373
|
-
|
|
373
|
+
manager.handleEvent(event);
|
|
374
374
|
|
|
375
375
|
// Extract the onFallback callback from the mock call
|
|
376
376
|
const callArgs = (triggerDeepLinkWithFallback as any).mock.calls[0];
|
|
@@ -419,7 +419,7 @@ describe("createIFrameLifecycleManager", () => {
|
|
|
419
419
|
},
|
|
420
420
|
};
|
|
421
421
|
|
|
422
|
-
|
|
422
|
+
manager.handleEvent(event);
|
|
423
423
|
|
|
424
424
|
// Should NOT call fallback detection
|
|
425
425
|
expect(triggerDeepLinkWithFallback).not.toHaveBeenCalled();
|
|
@@ -445,7 +445,7 @@ describe("createIFrameLifecycleManager", () => {
|
|
|
445
445
|
} as any;
|
|
446
446
|
|
|
447
447
|
// Should not throw
|
|
448
|
-
|
|
448
|
+
expect(manager.handleEvent(event)).toBeUndefined();
|
|
449
449
|
});
|
|
450
450
|
|
|
451
451
|
test("should only process events with iframeLifecycle", async () => {
|
|
@@ -463,13 +463,13 @@ describe("createIFrameLifecycleManager", () => {
|
|
|
463
463
|
});
|
|
464
464
|
|
|
465
465
|
// Event without iframeLifecycle
|
|
466
|
-
|
|
466
|
+
manager.handleEvent({ randomEvent: "show" } as any);
|
|
467
467
|
|
|
468
468
|
// changeIframeVisibility should not be called
|
|
469
469
|
expect(changeIframeVisibility).not.toHaveBeenCalled();
|
|
470
470
|
|
|
471
471
|
// Event with iframeLifecycle
|
|
472
|
-
|
|
472
|
+
manager.handleEvent({ iframeLifecycle: "show" as const });
|
|
473
473
|
|
|
474
474
|
// Now it should be called
|
|
475
475
|
expect(changeIframeVisibility).toHaveBeenCalled();
|
|
@@ -32,7 +32,7 @@ const isIOSInAppBrowser = (() => {
|
|
|
32
32
|
/** @ignore */
|
|
33
33
|
export type IframeLifecycleManager = {
|
|
34
34
|
isConnected: Promise<boolean>;
|
|
35
|
-
handleEvent: (messageEvent: FrakLifecycleEvent) =>
|
|
35
|
+
handleEvent: (messageEvent: FrakLifecycleEvent) => void;
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
/**
|
|
@@ -59,12 +59,12 @@ function computeRedirectUrl(
|
|
|
59
59
|
return baseRedirectUrl;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
// Append merge token to the page URL so it survives
|
|
63
|
+
// the backend /common/social redirect chain
|
|
64
|
+
const finalPageUrl = appendMergeToken(window.location.href, mergeToken);
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
66
|
+
redirectUrl.searchParams.delete("u");
|
|
67
|
+
redirectUrl.searchParams.append("u", finalPageUrl);
|
|
68
68
|
|
|
69
69
|
return redirectUrl.toString();
|
|
70
70
|
} catch {
|
|
@@ -93,6 +93,21 @@ function isSocialRedirect(url: string): boolean {
|
|
|
93
93
|
return url.includes("/common/social");
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Append merge token to a URL as the `fmt` query parameter.
|
|
98
|
+
*/
|
|
99
|
+
function appendMergeToken(urlString: string, mergeToken?: string): string {
|
|
100
|
+
if (!mergeToken) return urlString;
|
|
101
|
+
try {
|
|
102
|
+
const url = new URL(urlString);
|
|
103
|
+
url.searchParams.set("fmt", mergeToken);
|
|
104
|
+
return url.toString();
|
|
105
|
+
} catch {
|
|
106
|
+
const sep = urlString.includes("?") ? "&" : "?";
|
|
107
|
+
return `${urlString}${sep}fmt=${encodeURIComponent(mergeToken)}`;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
96
111
|
/**
|
|
97
112
|
* Handle redirect with deep link fallback
|
|
98
113
|
*/
|
|
@@ -100,8 +115,18 @@ function handleRedirect(
|
|
|
100
115
|
iframe: HTMLIFrameElement,
|
|
101
116
|
baseRedirectUrl: string,
|
|
102
117
|
targetOrigin: string,
|
|
103
|
-
mergeToken?: string
|
|
118
|
+
mergeToken?: string,
|
|
119
|
+
openInNewTab?: boolean
|
|
104
120
|
): void {
|
|
121
|
+
// If requested, open in a new tab instead of navigating the current page.
|
|
122
|
+
// This preserves the merchant page while triggering universal links.
|
|
123
|
+
// Requires the iframe postMessage to include user activation delegation.
|
|
124
|
+
if (openInNewTab) {
|
|
125
|
+
const finalUrl = computeRedirectUrl(baseRedirectUrl, mergeToken);
|
|
126
|
+
window.open(finalUrl, "_blank");
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
105
130
|
if (isFrakDeepLink(baseRedirectUrl)) {
|
|
106
131
|
const finalUrl = computeRedirectUrl(baseRedirectUrl, mergeToken);
|
|
107
132
|
triggerDeepLinkWithFallback(finalUrl, {
|
|
@@ -143,7 +168,7 @@ export function createIFrameLifecycleManager({
|
|
|
143
168
|
const isConnectedDeferred = new Deferred<boolean>();
|
|
144
169
|
|
|
145
170
|
// Build the handler itself
|
|
146
|
-
const handler =
|
|
171
|
+
const handler = (messageEvent: FrakLifecycleEvent) => {
|
|
147
172
|
if (!("iframeLifecycle" in messageEvent)) return;
|
|
148
173
|
|
|
149
174
|
const { iframeLifecycle: event, data } = messageEvent;
|
|
@@ -172,7 +197,8 @@ export function createIFrameLifecycleManager({
|
|
|
172
197
|
iframe,
|
|
173
198
|
data.baseRedirectUrl,
|
|
174
199
|
targetOrigin,
|
|
175
|
-
data.mergeToken
|
|
200
|
+
data.mergeToken,
|
|
201
|
+
data.openInNewTab
|
|
176
202
|
);
|
|
177
203
|
break;
|
|
178
204
|
}
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,9 @@ export type {
|
|
|
19
19
|
DisplayEmbeddedWalletParamsType,
|
|
20
20
|
DisplayEmbeddedWalletResultType,
|
|
21
21
|
DisplayModalParamsType,
|
|
22
|
+
// RPC Sharing page
|
|
23
|
+
DisplaySharingPageParamsType,
|
|
24
|
+
DisplaySharingPageResultType,
|
|
22
25
|
EmbeddedViewActionReferred,
|
|
23
26
|
EmbeddedViewActionSharing,
|
|
24
27
|
EstimatedReward,
|
|
@@ -68,6 +71,7 @@ export type {
|
|
|
68
71
|
SendTransactionModalStepType,
|
|
69
72
|
SendTransactionReturnType,
|
|
70
73
|
SendTransactionTxType,
|
|
74
|
+
SharingPageProduct,
|
|
71
75
|
SiweAuthenticateModalStepType,
|
|
72
76
|
SiweAuthenticateReturnType,
|
|
73
77
|
SiweAuthenticationParams,
|
|
@@ -76,8 +80,9 @@ export type {
|
|
|
76
80
|
// Tracking
|
|
77
81
|
TrackArrivalParams,
|
|
78
82
|
TrackArrivalResult,
|
|
79
|
-
UtmParams,
|
|
80
83
|
// Rpc
|
|
84
|
+
UserReferralStatusType,
|
|
85
|
+
UtmParams,
|
|
81
86
|
WalletStatusReturnType,
|
|
82
87
|
} from "./types";
|
|
83
88
|
export { isV1Context, isV2Context } from "./types";
|
|
@@ -88,6 +93,7 @@ export {
|
|
|
88
93
|
base64urlEncode,
|
|
89
94
|
baseIframeProps,
|
|
90
95
|
type CompressedSsoData,
|
|
96
|
+
clearAllCache,
|
|
91
97
|
compressJsonToB64,
|
|
92
98
|
createIframe,
|
|
93
99
|
DEEP_LINK_SCHEME,
|
|
@@ -100,15 +106,20 @@ export {
|
|
|
100
106
|
formatAmount,
|
|
101
107
|
generateSsoUrl,
|
|
102
108
|
getBackendUrl,
|
|
109
|
+
getCache,
|
|
103
110
|
getClientId,
|
|
104
111
|
getCurrencyAmountKey,
|
|
105
112
|
getSupportedCurrency,
|
|
106
113
|
getSupportedLocale,
|
|
107
114
|
isChromiumAndroid,
|
|
108
115
|
isFrakDeepLink,
|
|
116
|
+
isInAppBrowser,
|
|
117
|
+
isIOS,
|
|
118
|
+
redirectToExternalBrowser,
|
|
109
119
|
sdkConfigStore,
|
|
110
120
|
toAndroidIntentUrl,
|
|
111
121
|
trackEvent,
|
|
112
122
|
triggerDeepLinkWithFallback,
|
|
123
|
+
withCache,
|
|
113
124
|
} from "./utils";
|
|
114
125
|
export { computeLegacyProductId } from "./utils/computeLegacyProductId";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stub for rrweb. The @openpanel/web package statically imports `record` from
|
|
3
|
+
* rrweb even when session replay is disabled. This stub replaces the module so
|
|
4
|
+
* that rrweb is not included in the bundle.
|
|
5
|
+
* @see https://github.com/Openpanel-dev/openpanel/issues/336
|
|
6
|
+
*/
|
|
7
|
+
export function record() {
|
|
8
|
+
return () => {};
|
|
9
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -36,6 +36,12 @@ export type {
|
|
|
36
36
|
ModalRpcStepsResultType,
|
|
37
37
|
ModalStepTypes,
|
|
38
38
|
} from "./rpc/displayModal";
|
|
39
|
+
// Sharing page related
|
|
40
|
+
export type {
|
|
41
|
+
DisplaySharingPageParamsType,
|
|
42
|
+
DisplaySharingPageResultType,
|
|
43
|
+
SharingPageProduct,
|
|
44
|
+
} from "./rpc/displaySharingPage";
|
|
39
45
|
export type {
|
|
40
46
|
DisplayEmbeddedWalletParamsType,
|
|
41
47
|
DisplayEmbeddedWalletResultType,
|
|
@@ -70,6 +76,7 @@ export type {
|
|
|
70
76
|
PrepareSsoReturnType,
|
|
71
77
|
SsoMetadata,
|
|
72
78
|
} from "./rpc/sso";
|
|
79
|
+
export type { UserReferralStatusType } from "./rpc/userReferralStatus";
|
|
73
80
|
export type { WalletStatusReturnType } from "./rpc/walletStatus";
|
|
74
81
|
// Tracking
|
|
75
82
|
export type {
|
|
@@ -29,5 +29,12 @@ type RedirectRequestEvent = {
|
|
|
29
29
|
* Used when redirecting out of social browsers to preserve identity across contexts
|
|
30
30
|
*/
|
|
31
31
|
mergeToken?: string;
|
|
32
|
+
/**
|
|
33
|
+
* When true, open the URL in a new tab via window.open(_blank)
|
|
34
|
+
* instead of navigating the current page.
|
|
35
|
+
* Requires the postMessage to include user activation delegation
|
|
36
|
+
* (includeUserActivation: true) so Safari allows the popup.
|
|
37
|
+
*/
|
|
38
|
+
openInNewTab?: boolean;
|
|
32
39
|
};
|
|
33
40
|
};
|
|
@@ -23,18 +23,37 @@ export type ResolvedPlacement = {
|
|
|
23
23
|
buttonShare?: {
|
|
24
24
|
text?: string;
|
|
25
25
|
noRewardText?: string;
|
|
26
|
-
clickAction?: "embedded-wallet" | "share-modal";
|
|
26
|
+
clickAction?: "embedded-wallet" | "share-modal" | "sharing-page";
|
|
27
27
|
useReward?: boolean;
|
|
28
28
|
css?: string;
|
|
29
29
|
};
|
|
30
30
|
buttonWallet?: {
|
|
31
|
-
position?: "
|
|
31
|
+
position?: "right" | "left";
|
|
32
32
|
css?: string;
|
|
33
33
|
};
|
|
34
34
|
openInApp?: {
|
|
35
35
|
text?: string;
|
|
36
36
|
css?: string;
|
|
37
37
|
};
|
|
38
|
+
postPurchase?: {
|
|
39
|
+
badgeText?: string;
|
|
40
|
+
refereeText?: string;
|
|
41
|
+
refereeNoRewardText?: string;
|
|
42
|
+
referrerText?: string;
|
|
43
|
+
referrerNoRewardText?: string;
|
|
44
|
+
ctaText?: string;
|
|
45
|
+
ctaNoRewardText?: string;
|
|
46
|
+
css?: string;
|
|
47
|
+
};
|
|
48
|
+
banner?: {
|
|
49
|
+
referralTitle?: string;
|
|
50
|
+
referralDescription?: string;
|
|
51
|
+
referralCta?: string;
|
|
52
|
+
inappTitle?: string;
|
|
53
|
+
inappDescription?: string;
|
|
54
|
+
inappCta?: string;
|
|
55
|
+
css?: string;
|
|
56
|
+
};
|
|
38
57
|
};
|
|
39
58
|
targetInteraction?: string;
|
|
40
59
|
/** Already flattened: default + lang-specific merged into one record */
|
|
@@ -59,6 +78,8 @@ export type ResolvedSdkConfig = {
|
|
|
59
78
|
css?: string;
|
|
60
79
|
translations?: Record<string, string>;
|
|
61
80
|
placements?: Record<string, ResolvedPlacement>;
|
|
81
|
+
/** Global component defaults (used when no placement override exists) */
|
|
82
|
+
components?: ResolvedPlacement["components"];
|
|
62
83
|
};
|
|
63
84
|
|
|
64
85
|
/**
|
|
@@ -101,4 +122,7 @@ export type SdkResolvedConfig = {
|
|
|
101
122
|
|
|
102
123
|
/** Named placements (keyed by placement ID) */
|
|
103
124
|
placements?: Record<string, ResolvedPlacement>;
|
|
125
|
+
|
|
126
|
+
/** Global component defaults (fallback for placement-level overrides) */
|
|
127
|
+
components?: ResolvedPlacement["components"];
|
|
104
128
|
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { InteractionTypeKey } from "../../constants/interactionTypes";
|
|
2
|
+
import type { I18nConfig } from "../config";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Product information to display on the sharing page
|
|
6
|
+
* @group Sharing Page
|
|
7
|
+
*/
|
|
8
|
+
export type SharingPageProduct = {
|
|
9
|
+
/**
|
|
10
|
+
* The product title / name
|
|
11
|
+
*/
|
|
12
|
+
title: string;
|
|
13
|
+
/**
|
|
14
|
+
* Optional product image URL
|
|
15
|
+
*/
|
|
16
|
+
imageUrl?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Optional product-specific sharing link
|
|
19
|
+
* When provided and the product is selected, this link is used instead of the default sharing link
|
|
20
|
+
*/
|
|
21
|
+
link?: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Parameters to display the sharing page
|
|
26
|
+
* @group Sharing Page
|
|
27
|
+
* @group RPC Schema
|
|
28
|
+
*/
|
|
29
|
+
export type DisplaySharingPageParamsType = {
|
|
30
|
+
/**
|
|
31
|
+
* Products to showcase on the sharing page
|
|
32
|
+
* If provided, they will be displayed in a product card section
|
|
33
|
+
*/
|
|
34
|
+
products?: SharingPageProduct[];
|
|
35
|
+
/**
|
|
36
|
+
* Optional link override for sharing
|
|
37
|
+
* If not provided, the sharing link will be generated from the current page URL + merchant context
|
|
38
|
+
*/
|
|
39
|
+
link?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Optional metadata overrides for the sharing page
|
|
42
|
+
*/
|
|
43
|
+
metadata?: {
|
|
44
|
+
/**
|
|
45
|
+
* Logo override for the sharing page header
|
|
46
|
+
*/
|
|
47
|
+
logo?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Link to the homepage of the calling website
|
|
50
|
+
*/
|
|
51
|
+
homepageLink?: string;
|
|
52
|
+
/**
|
|
53
|
+
* The target interaction behind this sharing page
|
|
54
|
+
*/
|
|
55
|
+
targetInteraction?: InteractionTypeKey;
|
|
56
|
+
/**
|
|
57
|
+
* i18n overrides for the sharing page
|
|
58
|
+
*/
|
|
59
|
+
i18n?: I18nConfig;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Result of the sharing page display
|
|
65
|
+
* @group Sharing Page
|
|
66
|
+
* @group RPC Schema
|
|
67
|
+
*/
|
|
68
|
+
export type DisplaySharingPageResultType = {
|
|
69
|
+
/**
|
|
70
|
+
* The action the user took
|
|
71
|
+
* - "shared": User used the native share dialog
|
|
72
|
+
* - "copied": User copied the link to clipboard
|
|
73
|
+
* - "dismissed": User dismissed the sharing page without acting
|
|
74
|
+
*/
|
|
75
|
+
action: "shared" | "copied" | "dismissed";
|
|
76
|
+
/**
|
|
77
|
+
* The install URL for the Frak app
|
|
78
|
+
* Can be used as a fallback to redirect the user to the install page
|
|
79
|
+
* from the merchant's top-level page (e.g. via `window.location.href`)
|
|
80
|
+
*/
|
|
81
|
+
installUrl?: string;
|
|
82
|
+
};
|
|
@@ -9,10 +9,10 @@ import type {
|
|
|
9
9
|
import type { LoggedOutEmbeddedView } from "./loggedOut";
|
|
10
10
|
|
|
11
11
|
export type {
|
|
12
|
+
EmbeddedViewActionReferred,
|
|
12
13
|
EmbeddedViewActionSharing,
|
|
13
14
|
LoggedInEmbeddedView,
|
|
14
15
|
LoggedOutEmbeddedView,
|
|
15
|
-
EmbeddedViewActionReferred,
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
/**
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User referral status returned by `frak_getUserReferralStatus`.
|
|
3
|
+
*
|
|
4
|
+
* Generic referral context for the current user on a merchant.
|
|
5
|
+
* Used by components like `<frak-post-purchase>` and `<frak-referred-banner>`
|
|
6
|
+
* to adapt their display based on the user's referral relationship.
|
|
7
|
+
*
|
|
8
|
+
* Returns `null` when the user's identity cannot be resolved
|
|
9
|
+
* (e.g. no clientId and no wallet session).
|
|
10
|
+
*
|
|
11
|
+
* @group RPC Schema
|
|
12
|
+
*/
|
|
13
|
+
export type UserReferralStatusType = {
|
|
14
|
+
/**
|
|
15
|
+
* Whether the user was referred to this merchant by someone else.
|
|
16
|
+
*
|
|
17
|
+
* `true` means a referral link exists where this user is the referee.
|
|
18
|
+
*/
|
|
19
|
+
isReferred: boolean;
|
|
20
|
+
};
|