@frak-labs/core-sdk 0.2.1 → 1.0.0-beta.61e6fb99
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/README.md +1 -2
- package/cdn/bundle.js +3 -3
- package/dist/actions-Di4welXI.cjs +1 -0
- package/dist/actions-DyMkUe65.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-CCAZvLa5.d.cts → index-B_Uj-puh.d.ts} +249 -73
- package/dist/{computeLegacyProductId-b5cUWdAm.d.ts → index-ByVpu25D.d.cts} +249 -73
- package/dist/{siweAuthenticate-CnCZ7mok.d.ts → index-CGyEOo9J.d.cts} +122 -8
- package/dist/{siweAuthenticate-CVigMOxz.d.cts → index-Cdf5j2_W.d.ts} +122 -8
- 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-B0g7-807.d.cts → openSso-B6pD2oA6.d.ts} +380 -46
- package/dist/{openSso-CMzwvaCa.d.ts → openSso-qjaccFd0.d.cts} +379 -45
- package/dist/sdkConfigStore-DvwFc6Ym.cjs +1 -0
- package/dist/sdkConfigStore-M37skmM8.js +1 -0
- package/dist/src-BqpqVHCq.cjs +13 -0
- package/dist/src-BxRYON49.js +13 -0
- package/package.json +12 -13
- package/src/actions/displayEmbeddedWallet.ts +6 -2
- package/src/actions/displayModal.ts +6 -2
- package/src/actions/displaySharingPage.ts +49 -0
- package/src/actions/ensureIdentity.ts +2 -2
- 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/processReferral.test.ts +4 -8
- package/src/actions/referral/processReferral.ts +5 -11
- package/src/actions/referral/setupReferral.test.ts +79 -0
- package/src/actions/referral/setupReferral.ts +32 -0
- package/src/actions/trackPurchaseStatus.test.ts +32 -20
- package/src/actions/trackPurchaseStatus.ts +3 -5
- package/src/actions/wrapper/modalBuilder.test.ts +4 -2
- package/src/actions/wrapper/modalBuilder.ts +6 -8
- package/src/clients/createIFrameFrakClient.ts +233 -28
- package/src/clients/transports/iframeLifecycleManager.test.ts +14 -94
- package/src/clients/transports/iframeLifecycleManager.ts +35 -53
- package/src/index.ts +25 -5
- package/src/stubs/rrweb.ts +9 -0
- package/src/types/config.ts +19 -3
- package/src/types/index.ts +15 -1
- package/src/types/lifecycle/client.ts +29 -27
- package/src/types/lifecycle/iframe.ts +7 -8
- package/src/types/resolvedConfig.ts +138 -0
- package/src/types/rpc/displaySharingPage.ts +100 -0
- package/src/types/rpc/embedded/index.ts +1 -1
- package/src/types/rpc/interaction.ts +4 -0
- package/src/types/rpc/userReferralStatus.ts +20 -0
- package/src/types/rpc.ts +54 -5
- package/src/types/tracking.ts +36 -0
- package/src/utils/FrakContext.test.ts +151 -0
- package/src/utils/FrakContext.ts +67 -1
- package/src/utils/analytics/events/component.ts +58 -0
- package/src/utils/analytics/events/index.ts +20 -0
- package/src/utils/analytics/events/lifecycle.ts +26 -0
- package/src/utils/analytics/events/referral.ts +10 -0
- package/src/utils/analytics/index.ts +8 -0
- package/src/utils/{trackEvent.test.ts → analytics/trackEvent.test.ts} +22 -30
- package/src/utils/analytics/trackEvent.ts +34 -0
- package/src/utils/backendUrl.test.ts +2 -2
- package/src/utils/backendUrl.ts +1 -1
- 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 +11 -5
- package/src/utils/mergeAttribution.test.ts +153 -0
- package/src/utils/mergeAttribution.ts +75 -0
- package/src/utils/sdkConfigStore.test.ts +405 -0
- package/src/utils/sdkConfigStore.ts +263 -0
- package/src/utils/sso.ts +3 -7
- package/dist/setupClient-BduY6Sym.cjs +0 -13
- package/dist/setupClient-ftmdQ-I8.js +0 -13
- package/dist/siweAuthenticate-BWmI2_TN.cjs +0 -1
- package/dist/siweAuthenticate-zczqxm0a.js +0 -1
- package/dist/trackEvent-CeLFVzZn.js +0 -1
- package/dist/trackEvent-Ew5r5zfI.cjs +0 -1
- package/src/utils/merchantId.test.ts +0 -653
- package/src/utils/merchantId.ts +0 -143
- package/src/utils/trackEvent.ts +0 -41
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Deferred } from "@frak-labs/frame-connector";
|
|
2
2
|
import type { FrakLifecycleEvent } from "../../types";
|
|
3
|
-
import { getClientId } from "../../utils/clientId";
|
|
4
3
|
import { BACKUP_KEY } from "../../utils/constants";
|
|
5
4
|
import {
|
|
6
5
|
isFrakDeepLink,
|
|
@@ -33,7 +32,7 @@ const isIOSInAppBrowser = (() => {
|
|
|
33
32
|
/** @ignore */
|
|
34
33
|
export type IframeLifecycleManager = {
|
|
35
34
|
isConnected: Promise<boolean>;
|
|
36
|
-
handleEvent: (messageEvent: FrakLifecycleEvent) =>
|
|
35
|
+
handleEvent: (messageEvent: FrakLifecycleEvent) => void;
|
|
37
36
|
};
|
|
38
37
|
|
|
39
38
|
/**
|
|
@@ -47,42 +46,6 @@ function handleBackup(backup: string | undefined): void {
|
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
/**
|
|
51
|
-
* Handle handshake with iframe — sends client metadata so the listener can resolve the correct merchant
|
|
52
|
-
* @param iframe - The iframe element to post the handshake response to
|
|
53
|
-
* @param token - The handshake token received from the iframe
|
|
54
|
-
* @param targetOrigin - The target origin for postMessage security
|
|
55
|
-
* @param configDomain - Optional override domain for merchant resolution in tunneled/proxied environments
|
|
56
|
-
*/
|
|
57
|
-
function handleHandshake(
|
|
58
|
-
iframe: HTMLIFrameElement,
|
|
59
|
-
token: string,
|
|
60
|
-
targetOrigin: string,
|
|
61
|
-
configDomain?: string
|
|
62
|
-
): void {
|
|
63
|
-
const url = new URL(window.location.href);
|
|
64
|
-
const pendingMergeToken = url.searchParams.get("fmt") ?? undefined;
|
|
65
|
-
|
|
66
|
-
iframe.contentWindow?.postMessage(
|
|
67
|
-
{
|
|
68
|
-
clientLifecycle: "handshake-response",
|
|
69
|
-
data: {
|
|
70
|
-
token,
|
|
71
|
-
currentUrl: window.location.href,
|
|
72
|
-
pendingMergeToken,
|
|
73
|
-
configDomain,
|
|
74
|
-
clientId: getClientId(),
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
targetOrigin
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
if (pendingMergeToken) {
|
|
81
|
-
url.searchParams.delete("fmt");
|
|
82
|
-
window.history.replaceState({}, "", url.toString());
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
49
|
/**
|
|
87
50
|
* Compute final redirect URL with parameter substitution
|
|
88
51
|
*/
|
|
@@ -96,12 +59,12 @@ function computeRedirectUrl(
|
|
|
96
59
|
return baseRedirectUrl;
|
|
97
60
|
}
|
|
98
61
|
|
|
99
|
-
|
|
100
|
-
|
|
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);
|
|
101
65
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
66
|
+
redirectUrl.searchParams.delete("u");
|
|
67
|
+
redirectUrl.searchParams.append("u", finalPageUrl);
|
|
105
68
|
|
|
106
69
|
return redirectUrl.toString();
|
|
107
70
|
} catch {
|
|
@@ -130,6 +93,21 @@ function isSocialRedirect(url: string): boolean {
|
|
|
130
93
|
return url.includes("/common/social");
|
|
131
94
|
}
|
|
132
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
|
+
|
|
133
111
|
/**
|
|
134
112
|
* Handle redirect with deep link fallback
|
|
135
113
|
*/
|
|
@@ -137,8 +115,18 @@ function handleRedirect(
|
|
|
137
115
|
iframe: HTMLIFrameElement,
|
|
138
116
|
baseRedirectUrl: string,
|
|
139
117
|
targetOrigin: string,
|
|
140
|
-
mergeToken?: string
|
|
118
|
+
mergeToken?: string,
|
|
119
|
+
openInNewTab?: boolean
|
|
141
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
|
+
|
|
142
130
|
if (isFrakDeepLink(baseRedirectUrl)) {
|
|
143
131
|
const finalUrl = computeRedirectUrl(baseRedirectUrl, mergeToken);
|
|
144
132
|
triggerDeepLinkWithFallback(finalUrl, {
|
|
@@ -167,23 +155,20 @@ function handleRedirect(
|
|
|
167
155
|
* @param args
|
|
168
156
|
* @param args.iframe - The iframe element used for wallet communication
|
|
169
157
|
* @param args.targetOrigin - The wallet URL origin for postMessage security
|
|
170
|
-
* @param args.configDomain - Optional domain override forwarded during handshake for tunneled/proxied environments
|
|
171
158
|
* @ignore
|
|
172
159
|
*/
|
|
173
160
|
export function createIFrameLifecycleManager({
|
|
174
161
|
iframe,
|
|
175
162
|
targetOrigin,
|
|
176
|
-
configDomain,
|
|
177
163
|
}: {
|
|
178
164
|
iframe: HTMLIFrameElement;
|
|
179
165
|
targetOrigin: string;
|
|
180
|
-
configDomain?: string;
|
|
181
166
|
}): IframeLifecycleManager {
|
|
182
167
|
// Create the isConnected listener
|
|
183
168
|
const isConnectedDeferred = new Deferred<boolean>();
|
|
184
169
|
|
|
185
170
|
// Build the handler itself
|
|
186
|
-
const handler =
|
|
171
|
+
const handler = (messageEvent: FrakLifecycleEvent) => {
|
|
187
172
|
if (!("iframeLifecycle" in messageEvent)) return;
|
|
188
173
|
|
|
189
174
|
const { iframeLifecycle: event, data } = messageEvent;
|
|
@@ -206,17 +191,14 @@ export function createIFrameLifecycleManager({
|
|
|
206
191
|
case "hide":
|
|
207
192
|
changeIframeVisibility({ iframe, isVisible: event === "show" });
|
|
208
193
|
break;
|
|
209
|
-
// Handshake handling
|
|
210
|
-
case "handshake":
|
|
211
|
-
handleHandshake(iframe, data.token, targetOrigin, configDomain);
|
|
212
|
-
break;
|
|
213
194
|
// Redirect handling
|
|
214
195
|
case "redirect":
|
|
215
196
|
handleRedirect(
|
|
216
197
|
iframe,
|
|
217
198
|
data.baseRedirectUrl,
|
|
218
199
|
targetOrigin,
|
|
219
|
-
data.mergeToken
|
|
200
|
+
data.mergeToken,
|
|
201
|
+
data.openInNewTab
|
|
220
202
|
);
|
|
221
203
|
break;
|
|
222
204
|
}
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,8 @@ export { type LocalesKey, locales } from "./constants/locales";
|
|
|
12
12
|
|
|
13
13
|
// Types
|
|
14
14
|
export type {
|
|
15
|
+
AttributionDefaults,
|
|
16
|
+
AttributionParams,
|
|
15
17
|
ClientLifecycleEvent,
|
|
16
18
|
CompressedData,
|
|
17
19
|
Currency,
|
|
@@ -19,6 +21,9 @@ export type {
|
|
|
19
21
|
DisplayEmbeddedWalletParamsType,
|
|
20
22
|
DisplayEmbeddedWalletResultType,
|
|
21
23
|
DisplayModalParamsType,
|
|
24
|
+
// RPC Sharing page
|
|
25
|
+
DisplaySharingPageParamsType,
|
|
26
|
+
DisplaySharingPageResultType,
|
|
22
27
|
EmbeddedViewActionReferred,
|
|
23
28
|
EmbeddedViewActionSharing,
|
|
24
29
|
EstimatedReward,
|
|
@@ -47,6 +52,7 @@ export type {
|
|
|
47
52
|
LoggedInEmbeddedView,
|
|
48
53
|
LoggedOutEmbeddedView,
|
|
49
54
|
LoginModalStepType,
|
|
55
|
+
MerchantConfigResponse,
|
|
50
56
|
ModalRpcMetadata,
|
|
51
57
|
ModalRpcStepsInput,
|
|
52
58
|
ModalRpcStepsResultType,
|
|
@@ -58,12 +64,16 @@ export type {
|
|
|
58
64
|
OpenSsoReturnType,
|
|
59
65
|
PrepareSsoParamsType,
|
|
60
66
|
PrepareSsoReturnType,
|
|
67
|
+
ResolvedPlacement,
|
|
68
|
+
ResolvedSdkConfig,
|
|
61
69
|
RewardTier,
|
|
70
|
+
SdkResolvedConfig,
|
|
62
71
|
// RPC Interaction
|
|
63
72
|
SendInteractionParamsType,
|
|
64
73
|
SendTransactionModalStepType,
|
|
65
74
|
SendTransactionReturnType,
|
|
66
75
|
SendTransactionTxType,
|
|
76
|
+
SharingPageProduct,
|
|
67
77
|
SiweAuthenticateModalStepType,
|
|
68
78
|
SiweAuthenticateReturnType,
|
|
69
79
|
SiweAuthenticationParams,
|
|
@@ -72,8 +82,9 @@ export type {
|
|
|
72
82
|
// Tracking
|
|
73
83
|
TrackArrivalParams,
|
|
74
84
|
TrackArrivalResult,
|
|
75
|
-
UtmParams,
|
|
76
85
|
// Rpc
|
|
86
|
+
UserReferralStatusType,
|
|
87
|
+
UtmParams,
|
|
77
88
|
WalletStatusReturnType,
|
|
78
89
|
} from "./types";
|
|
79
90
|
export { isV1Context, isV2Context } from "./types";
|
|
@@ -84,29 +95,38 @@ export {
|
|
|
84
95
|
base64urlEncode,
|
|
85
96
|
baseIframeProps,
|
|
86
97
|
type CompressedSsoData,
|
|
87
|
-
|
|
98
|
+
clearAllCache,
|
|
88
99
|
compressJsonToB64,
|
|
89
100
|
createIframe,
|
|
90
101
|
DEEP_LINK_SCHEME,
|
|
91
102
|
type DeepLinkFallbackOptions,
|
|
92
103
|
decompressJsonFromB64,
|
|
93
104
|
FrakContextManager,
|
|
94
|
-
type FrakEvent,
|
|
95
105
|
type FullSsoParams,
|
|
96
|
-
fetchMerchantId,
|
|
97
106
|
findIframeInOpener,
|
|
98
107
|
formatAmount,
|
|
99
108
|
generateSsoUrl,
|
|
100
109
|
getBackendUrl,
|
|
110
|
+
getCache,
|
|
101
111
|
getClientId,
|
|
102
112
|
getCurrencyAmountKey,
|
|
103
113
|
getSupportedCurrency,
|
|
104
114
|
getSupportedLocale,
|
|
105
115
|
isChromiumAndroid,
|
|
106
116
|
isFrakDeepLink,
|
|
107
|
-
|
|
117
|
+
isInAppBrowser,
|
|
118
|
+
isIOS,
|
|
119
|
+
type MergeAttributionInput,
|
|
120
|
+
mergeAttribution,
|
|
121
|
+
redirectToExternalBrowser,
|
|
122
|
+
sdkConfigStore,
|
|
108
123
|
toAndroidIntentUrl,
|
|
109
124
|
trackEvent,
|
|
110
125
|
triggerDeepLinkWithFallback,
|
|
126
|
+
withCache,
|
|
111
127
|
} from "./utils";
|
|
128
|
+
export type {
|
|
129
|
+
SdkEventMap,
|
|
130
|
+
SdkHandshakeFailureReason,
|
|
131
|
+
} from "./utils/analytics";
|
|
112
132
|
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/config.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { AttributionDefaults } from "./tracking";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* All the currencies available
|
|
3
5
|
* @category Config
|
|
@@ -27,7 +29,7 @@ export type FrakWalletSdkConfig = {
|
|
|
27
29
|
/**
|
|
28
30
|
* Your application name (will be displayed in a few modals and in SSO)
|
|
29
31
|
*/
|
|
30
|
-
name
|
|
32
|
+
name?: string;
|
|
31
33
|
/**
|
|
32
34
|
* Your merchant ID from the Frak dashboard (UUID format)
|
|
33
35
|
* Used for referral tracking and analytics
|
|
@@ -71,6 +73,20 @@ export type FrakWalletSdkConfig = {
|
|
|
71
73
|
* @defaultValue window.location.host
|
|
72
74
|
*/
|
|
73
75
|
domain?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Wait for backend config before rendering components.
|
|
78
|
+
* When true (default), components show a spinner until backend config is resolved.
|
|
79
|
+
* When false, components render immediately with SDK static config / HTML attributes.
|
|
80
|
+
* @defaultValue true
|
|
81
|
+
*/
|
|
82
|
+
waitForBackendConfig?: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Default attribution params (UTM / via / ref) appended to outbound
|
|
85
|
+
* sharing URLs. Per-call `displaySharingPage` overrides win, then backend
|
|
86
|
+
* config, then this SDK-level default. `utm_content` is intentionally
|
|
87
|
+
* excluded — it is per-content/per-product, never a merchant-wide default.
|
|
88
|
+
*/
|
|
89
|
+
attribution?: AttributionDefaults;
|
|
74
90
|
};
|
|
75
91
|
|
|
76
92
|
/**
|
|
@@ -111,7 +127,7 @@ export type I18nConfig =
|
|
|
111
127
|
| LocalizedI18nConfig;
|
|
112
128
|
|
|
113
129
|
/**
|
|
114
|
-
* A localized i18n config
|
|
130
|
+
* A localized i18n config (inline objects only — URL-based i18n removed)
|
|
115
131
|
* @category Config
|
|
116
132
|
*/
|
|
117
|
-
export type LocalizedI18nConfig =
|
|
133
|
+
export type LocalizedI18nConfig = { [key: string]: string };
|
package/src/types/index.ts
CHANGED
|
@@ -17,11 +17,16 @@ export type {
|
|
|
17
17
|
// Utils
|
|
18
18
|
export type { FrakContext, FrakContextV1, FrakContextV2 } from "./context";
|
|
19
19
|
export { isV1Context, isV2Context } from "./context";
|
|
20
|
-
|
|
21
20
|
export type {
|
|
22
21
|
ClientLifecycleEvent,
|
|
23
22
|
IFrameLifecycleEvent,
|
|
24
23
|
} from "./lifecycle";
|
|
24
|
+
export type {
|
|
25
|
+
MerchantConfigResponse,
|
|
26
|
+
ResolvedPlacement,
|
|
27
|
+
ResolvedSdkConfig,
|
|
28
|
+
SdkResolvedConfig,
|
|
29
|
+
} from "./resolvedConfig";
|
|
25
30
|
export type { IFrameRpcSchema } from "./rpc";
|
|
26
31
|
// Modal related
|
|
27
32
|
export type {
|
|
@@ -31,6 +36,12 @@ export type {
|
|
|
31
36
|
ModalRpcStepsResultType,
|
|
32
37
|
ModalStepTypes,
|
|
33
38
|
} from "./rpc/displayModal";
|
|
39
|
+
// Sharing page related
|
|
40
|
+
export type {
|
|
41
|
+
DisplaySharingPageParamsType,
|
|
42
|
+
DisplaySharingPageResultType,
|
|
43
|
+
SharingPageProduct,
|
|
44
|
+
} from "./rpc/displaySharingPage";
|
|
34
45
|
export type {
|
|
35
46
|
DisplayEmbeddedWalletParamsType,
|
|
36
47
|
DisplayEmbeddedWalletResultType,
|
|
@@ -65,9 +76,12 @@ export type {
|
|
|
65
76
|
PrepareSsoReturnType,
|
|
66
77
|
SsoMetadata,
|
|
67
78
|
} from "./rpc/sso";
|
|
79
|
+
export type { UserReferralStatusType } from "./rpc/userReferralStatus";
|
|
68
80
|
export type { WalletStatusReturnType } from "./rpc/walletStatus";
|
|
69
81
|
// Tracking
|
|
70
82
|
export type {
|
|
83
|
+
AttributionDefaults,
|
|
84
|
+
AttributionParams,
|
|
71
85
|
TrackArrivalParams,
|
|
72
86
|
TrackArrivalResult,
|
|
73
87
|
UtmParams,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { I18nConfig } from "../config";
|
|
2
|
+
import type { ResolvedSdkConfig } from "../resolvedConfig";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Event related to the iframe lifecycle
|
|
@@ -9,9 +10,9 @@ export type ClientLifecycleEvent =
|
|
|
9
10
|
| CustomI18nEvent
|
|
10
11
|
| RestoreBackupEvent
|
|
11
12
|
| HearbeatEvent
|
|
12
|
-
| HandshakeResponse
|
|
13
13
|
| SsoRedirectCompleteEvent
|
|
14
|
-
| DeepLinkFailedEvent
|
|
14
|
+
| DeepLinkFailedEvent
|
|
15
|
+
| ResolvedConfigEvent;
|
|
15
16
|
|
|
16
17
|
type CustomCssEvent = {
|
|
17
18
|
clientLifecycle: "modal-css";
|
|
@@ -33,31 +34,6 @@ type HearbeatEvent = {
|
|
|
33
34
|
data?: never;
|
|
34
35
|
};
|
|
35
36
|
|
|
36
|
-
type HandshakeResponse = {
|
|
37
|
-
clientLifecycle: "handshake-response";
|
|
38
|
-
data: {
|
|
39
|
-
token: string;
|
|
40
|
-
currentUrl: string;
|
|
41
|
-
/**
|
|
42
|
-
* Pending merge token extracted from URL (?fmt= parameter)
|
|
43
|
-
* When present, listener should execute identity merge in background
|
|
44
|
-
* URL is cleaned after handshake response is sent
|
|
45
|
-
*/
|
|
46
|
-
pendingMergeToken?: string;
|
|
47
|
-
/**
|
|
48
|
-
* Client ID for identity tracking (belt & suspenders fallback)
|
|
49
|
-
* Primary delivery is via iframe URL query param; handshake is backup for SSR
|
|
50
|
-
*/
|
|
51
|
-
clientId?: string;
|
|
52
|
-
/**
|
|
53
|
-
* Explicit domain from SDK config (FrakWalletSdkConfig.domain)
|
|
54
|
-
* When present, listener should prefer this over URL-derived domain
|
|
55
|
-
* for merchant resolution (handles proxied/tunneled environments)
|
|
56
|
-
*/
|
|
57
|
-
configDomain?: string;
|
|
58
|
-
};
|
|
59
|
-
};
|
|
60
|
-
|
|
61
37
|
type SsoRedirectCompleteEvent = {
|
|
62
38
|
clientLifecycle: "sso-redirect-complete";
|
|
63
39
|
data: { compressed: string };
|
|
@@ -67,3 +43,29 @@ type DeepLinkFailedEvent = {
|
|
|
67
43
|
clientLifecycle: "deep-link-failed";
|
|
68
44
|
data: { originalUrl: string };
|
|
69
45
|
};
|
|
46
|
+
|
|
47
|
+
type ResolvedConfigEvent = {
|
|
48
|
+
clientLifecycle: "resolved-config";
|
|
49
|
+
data: {
|
|
50
|
+
merchantId: string;
|
|
51
|
+
/** The domain the backend resolved this config for */
|
|
52
|
+
domain: string;
|
|
53
|
+
/** All domains registered for this merchant (for domain proof) */
|
|
54
|
+
allowedDomains: string[];
|
|
55
|
+
/** Full URL of the parent page (for interaction tracking) */
|
|
56
|
+
sourceUrl: string;
|
|
57
|
+
/**
|
|
58
|
+
* Pending merge token extracted from URL (?fmt= parameter).
|
|
59
|
+
* When present, listener should execute identity merge in background.
|
|
60
|
+
*/
|
|
61
|
+
pendingMergeToken?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Persistent per-origin anonymous id generated on the partner site
|
|
64
|
+
* (SDK-side localStorage). Propagated here so the listener can
|
|
65
|
+
* set it as an OpenPanel global property and stitch SDK events
|
|
66
|
+
* with listener events in the same funnel.
|
|
67
|
+
*/
|
|
68
|
+
sdkAnonymousId?: string;
|
|
69
|
+
sdkConfig?: ResolvedSdkConfig;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
@@ -8,7 +8,6 @@ export type IFrameLifecycleEvent =
|
|
|
8
8
|
data?: never;
|
|
9
9
|
}
|
|
10
10
|
| DoBackupEvent
|
|
11
|
-
| HandshakeRequestEvent
|
|
12
11
|
| RedirectRequestEvent;
|
|
13
12
|
|
|
14
13
|
type DoBackupEvent = {
|
|
@@ -16,13 +15,6 @@ type DoBackupEvent = {
|
|
|
16
15
|
data: { backup?: string };
|
|
17
16
|
};
|
|
18
17
|
|
|
19
|
-
type HandshakeRequestEvent = {
|
|
20
|
-
iframeLifecycle: "handshake";
|
|
21
|
-
data: {
|
|
22
|
-
token: string;
|
|
23
|
-
};
|
|
24
|
-
};
|
|
25
|
-
|
|
26
18
|
type RedirectRequestEvent = {
|
|
27
19
|
iframeLifecycle: "redirect";
|
|
28
20
|
data: {
|
|
@@ -37,5 +29,12 @@ type RedirectRequestEvent = {
|
|
|
37
29
|
* Used when redirecting out of social browsers to preserve identity across contexts
|
|
38
30
|
*/
|
|
39
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;
|
|
40
39
|
};
|
|
41
40
|
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { Currency, Language } from "./config";
|
|
2
|
+
import type { AttributionDefaults } from "./tracking";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Response from the merchant resolve endpoint
|
|
6
|
+
* @category Config
|
|
7
|
+
*/
|
|
8
|
+
export type MerchantConfigResponse = {
|
|
9
|
+
merchantId: string;
|
|
10
|
+
name: string;
|
|
11
|
+
domain: string;
|
|
12
|
+
allowedDomains: string[];
|
|
13
|
+
sdkConfig?: ResolvedSdkConfig;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Resolved placement config from backend
|
|
18
|
+
* Translations already flattened: default + lang-specific merged into one record
|
|
19
|
+
* @category Config
|
|
20
|
+
*/
|
|
21
|
+
export type ResolvedPlacement = {
|
|
22
|
+
/** Per-component configuration within this placement */
|
|
23
|
+
components?: {
|
|
24
|
+
buttonShare?: {
|
|
25
|
+
text?: string;
|
|
26
|
+
noRewardText?: string;
|
|
27
|
+
clickAction?: "embedded-wallet" | "share-modal" | "sharing-page";
|
|
28
|
+
useReward?: boolean;
|
|
29
|
+
css?: string;
|
|
30
|
+
};
|
|
31
|
+
buttonWallet?: {
|
|
32
|
+
position?: "right" | "left";
|
|
33
|
+
css?: string;
|
|
34
|
+
};
|
|
35
|
+
openInApp?: {
|
|
36
|
+
text?: string;
|
|
37
|
+
css?: string;
|
|
38
|
+
};
|
|
39
|
+
postPurchase?: {
|
|
40
|
+
badgeText?: string;
|
|
41
|
+
refereeText?: string;
|
|
42
|
+
refereeNoRewardText?: string;
|
|
43
|
+
referrerText?: string;
|
|
44
|
+
referrerNoRewardText?: string;
|
|
45
|
+
ctaText?: string;
|
|
46
|
+
ctaNoRewardText?: string;
|
|
47
|
+
css?: string;
|
|
48
|
+
};
|
|
49
|
+
banner?: {
|
|
50
|
+
referralTitle?: string;
|
|
51
|
+
referralDescription?: string;
|
|
52
|
+
referralCta?: string;
|
|
53
|
+
inappTitle?: string;
|
|
54
|
+
inappDescription?: string;
|
|
55
|
+
inappCta?: string;
|
|
56
|
+
css?: string;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
targetInteraction?: string;
|
|
60
|
+
/** Already flattened: default + lang-specific merged into one record */
|
|
61
|
+
translations?: Record<string, string>;
|
|
62
|
+
/** Global placement CSS (applied to modals/listener) */
|
|
63
|
+
css?: string;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Resolved SDK config from backend `/resolve` endpoint
|
|
68
|
+
* Language resolution and translation merging already applied
|
|
69
|
+
* @category Config
|
|
70
|
+
*/
|
|
71
|
+
export type ResolvedSdkConfig = {
|
|
72
|
+
name?: string;
|
|
73
|
+
logoUrl?: string;
|
|
74
|
+
homepageLink?: string;
|
|
75
|
+
currency?: Currency;
|
|
76
|
+
lang?: Language;
|
|
77
|
+
/** When true, all SDK components should be hidden */
|
|
78
|
+
hidden?: boolean;
|
|
79
|
+
css?: string;
|
|
80
|
+
translations?: Record<string, string>;
|
|
81
|
+
placements?: Record<string, ResolvedPlacement>;
|
|
82
|
+
/** Global component defaults (used when no placement override exists) */
|
|
83
|
+
components?: ResolvedPlacement["components"];
|
|
84
|
+
/**
|
|
85
|
+
* Default attribution params applied when building outbound sharing URLs.
|
|
86
|
+
* Per-call overrides win over these backend defaults; `utm_content` is
|
|
87
|
+
* intentionally excluded (per-content/per-product, never a merchant default).
|
|
88
|
+
*/
|
|
89
|
+
attribution?: AttributionDefaults;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Internal SDK config store state
|
|
94
|
+
* Merged config: backend > SDK static > defaults
|
|
95
|
+
* Components subscribe to this reactively
|
|
96
|
+
* @category Config
|
|
97
|
+
*/
|
|
98
|
+
export type SdkResolvedConfig = {
|
|
99
|
+
/** Whether the backend config has been resolved */
|
|
100
|
+
isResolved: boolean;
|
|
101
|
+
|
|
102
|
+
/** Merchant ID from resolution */
|
|
103
|
+
merchantId: string;
|
|
104
|
+
|
|
105
|
+
/** Domain returned by the resolve endpoint */
|
|
106
|
+
domain?: string;
|
|
107
|
+
|
|
108
|
+
/** Domains allowed for this merchant (used by iframe trust check) */
|
|
109
|
+
allowedDomains?: string[];
|
|
110
|
+
|
|
111
|
+
/** Whether the resolve returned a backend sdkConfig object */
|
|
112
|
+
hasRawSdkConfig?: boolean;
|
|
113
|
+
|
|
114
|
+
/** Merged metadata fields */
|
|
115
|
+
name?: string;
|
|
116
|
+
logoUrl?: string;
|
|
117
|
+
homepageLink?: string;
|
|
118
|
+
lang?: Language;
|
|
119
|
+
currency?: Currency;
|
|
120
|
+
|
|
121
|
+
/** When true, all SDK components should be hidden */
|
|
122
|
+
hidden?: boolean;
|
|
123
|
+
|
|
124
|
+
/** Global CSS from backend config (passed to iframe) */
|
|
125
|
+
css?: string;
|
|
126
|
+
|
|
127
|
+
/** Global translations (for reference / component fallback) */
|
|
128
|
+
translations?: Record<string, string>;
|
|
129
|
+
|
|
130
|
+
/** Named placements (keyed by placement ID) */
|
|
131
|
+
placements?: Record<string, ResolvedPlacement>;
|
|
132
|
+
|
|
133
|
+
/** Global component defaults (fallback for placement-level overrides) */
|
|
134
|
+
components?: ResolvedPlacement["components"];
|
|
135
|
+
|
|
136
|
+
/** Merged attribution defaults: backend > SDK static config */
|
|
137
|
+
attribution?: AttributionDefaults;
|
|
138
|
+
};
|