@frak-labs/core-sdk 0.2.1-beta.b38eef2e → 0.2.1-beta.d04602ec
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 +55 -3
- 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 → computeLegacyProductId-fKvxbC4k.d.ts} +91 -37
- package/dist/{computeLegacyProductId-b5cUWdAm.d.ts → computeLegacyProductId-rYIvY4c3.d.cts} +91 -37
- 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-CMZM06uR.d.ts} +258 -46
- package/dist/{openSso-CMzwvaCa.d.ts → openSso-CebB8mFv.d.cts} +258 -46
- package/dist/setupClient-B_XMB52l.cjs +13 -0
- package/dist/setupClient-jYx-fbxB.js +13 -0
- package/dist/siweAuthenticate-CWcVvP-G.cjs +1 -0
- package/dist/siweAuthenticate-DQfdb5UQ.js +1 -0
- package/dist/{siweAuthenticate-CnCZ7mok.d.ts → siweAuthenticate-Dc_Yg9Bg.d.cts} +102 -8
- package/dist/{siweAuthenticate-CVigMOxz.d.cts → siweAuthenticate-Ddhl-o4N.d.ts} +102 -8
- package/dist/trackEvent-Ce1XlsIE.js +1 -0
- package/dist/trackEvent-CvbJTTqA.cjs +1 -0
- package/package.json +8 -8
- 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/getUserReferralStatus.ts +42 -0
- package/src/actions/index.ts +7 -1
- 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 +148 -25
- package/src/clients/transports/iframeLifecycleManager.test.ts +0 -80
- package/src/clients/transports/iframeLifecycleManager.ts +0 -44
- package/src/index.ts +17 -4
- package/src/types/config.ts +10 -3
- package/src/types/index.ts +13 -1
- package/src/types/lifecycle/client.ts +22 -27
- package/src/types/lifecycle/iframe.ts +0 -8
- package/src/types/resolvedConfig.ts +122 -0
- package/src/types/rpc/displaySharingPage.ts +77 -0
- package/src/types/rpc/interaction.ts +4 -0
- package/src/types/rpc/userReferralStatus.ts +20 -0
- package/src/types/rpc.ts +42 -5
- 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 +162 -0
- package/src/utils/cache/withCache.ts +105 -0
- package/src/utils/inAppBrowser.ts +60 -0
- package/src/utils/index.ts +6 -4
- 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-CqTHGvVa.cjs +0 -13
- package/dist/setupClient-DTyvAPgh.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
|
@@ -233,86 +233,6 @@ describe("createIFrameLifecycleManager", () => {
|
|
|
233
233
|
});
|
|
234
234
|
});
|
|
235
235
|
|
|
236
|
-
describe("handshake event", () => {
|
|
237
|
-
test("should post handshake-response with token to iframe origin", async () => {
|
|
238
|
-
const { createIFrameLifecycleManager } = await import(
|
|
239
|
-
"./iframeLifecycleManager"
|
|
240
|
-
);
|
|
241
|
-
|
|
242
|
-
const mockPostMessage = vi.fn();
|
|
243
|
-
const mockIframe = {
|
|
244
|
-
src: "https://wallet.frak.id/listener",
|
|
245
|
-
contentWindow: {
|
|
246
|
-
postMessage: mockPostMessage,
|
|
247
|
-
},
|
|
248
|
-
} as any;
|
|
249
|
-
|
|
250
|
-
const manager = createIFrameLifecycleManager({
|
|
251
|
-
iframe: mockIframe,
|
|
252
|
-
targetOrigin: WALLET_ORIGIN,
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
const event = {
|
|
256
|
-
iframeLifecycle: "handshake" as const,
|
|
257
|
-
data: { token: "handshake-token-123" },
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
await manager.handleEvent(event);
|
|
261
|
-
|
|
262
|
-
expect(mockPostMessage).toHaveBeenCalledWith(
|
|
263
|
-
{
|
|
264
|
-
clientLifecycle: "handshake-response",
|
|
265
|
-
data: {
|
|
266
|
-
token: "handshake-token-123",
|
|
267
|
-
currentUrl: "https://test.com",
|
|
268
|
-
clientId: "mock-client-id",
|
|
269
|
-
},
|
|
270
|
-
},
|
|
271
|
-
"https://wallet.frak.id"
|
|
272
|
-
);
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
test("should include current URL in handshake response", async () => {
|
|
276
|
-
const { createIFrameLifecycleManager } = await import(
|
|
277
|
-
"./iframeLifecycleManager"
|
|
278
|
-
);
|
|
279
|
-
|
|
280
|
-
Object.defineProperty(window, "location", {
|
|
281
|
-
value: { href: "https://example.com/page?param=value" },
|
|
282
|
-
writable: true,
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
const mockPostMessage = vi.fn();
|
|
286
|
-
const mockIframe = {
|
|
287
|
-
src: "https://wallet.frak.id/listener",
|
|
288
|
-
contentWindow: {
|
|
289
|
-
postMessage: mockPostMessage,
|
|
290
|
-
},
|
|
291
|
-
} as any;
|
|
292
|
-
|
|
293
|
-
const manager = createIFrameLifecycleManager({
|
|
294
|
-
iframe: mockIframe,
|
|
295
|
-
targetOrigin: WALLET_ORIGIN,
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
const event = {
|
|
299
|
-
iframeLifecycle: "handshake" as const,
|
|
300
|
-
data: { token: "token" },
|
|
301
|
-
};
|
|
302
|
-
|
|
303
|
-
await manager.handleEvent(event);
|
|
304
|
-
|
|
305
|
-
expect(mockPostMessage).toHaveBeenCalledWith(
|
|
306
|
-
expect.objectContaining({
|
|
307
|
-
data: expect.objectContaining({
|
|
308
|
-
currentUrl: "https://example.com/page?param=value",
|
|
309
|
-
}),
|
|
310
|
-
}),
|
|
311
|
-
"https://wallet.frak.id"
|
|
312
|
-
);
|
|
313
|
-
});
|
|
314
|
-
});
|
|
315
|
-
|
|
316
236
|
describe("redirect event", () => {
|
|
317
237
|
test("should redirect with appended current URL for HTTP URLs", async () => {
|
|
318
238
|
const { createIFrameLifecycleManager } = await import(
|
|
@@ -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,
|
|
@@ -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
|
*/
|
|
@@ -167,17 +130,14 @@ function handleRedirect(
|
|
|
167
130
|
* @param args
|
|
168
131
|
* @param args.iframe - The iframe element used for wallet communication
|
|
169
132
|
* @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
133
|
* @ignore
|
|
172
134
|
*/
|
|
173
135
|
export function createIFrameLifecycleManager({
|
|
174
136
|
iframe,
|
|
175
137
|
targetOrigin,
|
|
176
|
-
configDomain,
|
|
177
138
|
}: {
|
|
178
139
|
iframe: HTMLIFrameElement;
|
|
179
140
|
targetOrigin: string;
|
|
180
|
-
configDomain?: string;
|
|
181
141
|
}): IframeLifecycleManager {
|
|
182
142
|
// Create the isConnected listener
|
|
183
143
|
const isConnectedDeferred = new Deferred<boolean>();
|
|
@@ -206,10 +166,6 @@ export function createIFrameLifecycleManager({
|
|
|
206
166
|
case "hide":
|
|
207
167
|
changeIframeVisibility({ iframe, isVisible: event === "show" });
|
|
208
168
|
break;
|
|
209
|
-
// Handshake handling
|
|
210
|
-
case "handshake":
|
|
211
|
-
handleHandshake(iframe, data.token, targetOrigin, configDomain);
|
|
212
|
-
break;
|
|
213
169
|
// Redirect handling
|
|
214
170
|
case "redirect":
|
|
215
171
|
handleRedirect(
|
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,
|
|
@@ -47,6 +50,7 @@ export type {
|
|
|
47
50
|
LoggedInEmbeddedView,
|
|
48
51
|
LoggedOutEmbeddedView,
|
|
49
52
|
LoginModalStepType,
|
|
53
|
+
MerchantConfigResponse,
|
|
50
54
|
ModalRpcMetadata,
|
|
51
55
|
ModalRpcStepsInput,
|
|
52
56
|
ModalRpcStepsResultType,
|
|
@@ -58,12 +62,16 @@ export type {
|
|
|
58
62
|
OpenSsoReturnType,
|
|
59
63
|
PrepareSsoParamsType,
|
|
60
64
|
PrepareSsoReturnType,
|
|
65
|
+
ResolvedPlacement,
|
|
66
|
+
ResolvedSdkConfig,
|
|
61
67
|
RewardTier,
|
|
68
|
+
SdkResolvedConfig,
|
|
62
69
|
// RPC Interaction
|
|
63
70
|
SendInteractionParamsType,
|
|
64
71
|
SendTransactionModalStepType,
|
|
65
72
|
SendTransactionReturnType,
|
|
66
73
|
SendTransactionTxType,
|
|
74
|
+
SharingPageProduct,
|
|
67
75
|
SiweAuthenticateModalStepType,
|
|
68
76
|
SiweAuthenticateReturnType,
|
|
69
77
|
SiweAuthenticationParams,
|
|
@@ -72,8 +80,9 @@ export type {
|
|
|
72
80
|
// Tracking
|
|
73
81
|
TrackArrivalParams,
|
|
74
82
|
TrackArrivalResult,
|
|
75
|
-
UtmParams,
|
|
76
83
|
// Rpc
|
|
84
|
+
UserReferralStatusType,
|
|
85
|
+
UtmParams,
|
|
77
86
|
WalletStatusReturnType,
|
|
78
87
|
} from "./types";
|
|
79
88
|
export { isV1Context, isV2Context } from "./types";
|
|
@@ -84,7 +93,7 @@ export {
|
|
|
84
93
|
base64urlEncode,
|
|
85
94
|
baseIframeProps,
|
|
86
95
|
type CompressedSsoData,
|
|
87
|
-
|
|
96
|
+
clearAllCache,
|
|
88
97
|
compressJsonToB64,
|
|
89
98
|
createIframe,
|
|
90
99
|
DEEP_LINK_SCHEME,
|
|
@@ -93,20 +102,24 @@ export {
|
|
|
93
102
|
FrakContextManager,
|
|
94
103
|
type FrakEvent,
|
|
95
104
|
type FullSsoParams,
|
|
96
|
-
fetchMerchantId,
|
|
97
105
|
findIframeInOpener,
|
|
98
106
|
formatAmount,
|
|
99
107
|
generateSsoUrl,
|
|
100
108
|
getBackendUrl,
|
|
109
|
+
getCache,
|
|
101
110
|
getClientId,
|
|
102
111
|
getCurrencyAmountKey,
|
|
103
112
|
getSupportedCurrency,
|
|
104
113
|
getSupportedLocale,
|
|
105
114
|
isChromiumAndroid,
|
|
106
115
|
isFrakDeepLink,
|
|
107
|
-
|
|
116
|
+
isInAppBrowser,
|
|
117
|
+
isIOS,
|
|
118
|
+
redirectToExternalBrowser,
|
|
119
|
+
sdkConfigStore,
|
|
108
120
|
toAndroidIntentUrl,
|
|
109
121
|
trackEvent,
|
|
110
122
|
triggerDeepLinkWithFallback,
|
|
123
|
+
withCache,
|
|
111
124
|
} from "./utils";
|
|
112
125
|
export { computeLegacyProductId } from "./utils/computeLegacyProductId";
|
package/src/types/config.ts
CHANGED
|
@@ -27,7 +27,7 @@ export type FrakWalletSdkConfig = {
|
|
|
27
27
|
/**
|
|
28
28
|
* Your application name (will be displayed in a few modals and in SSO)
|
|
29
29
|
*/
|
|
30
|
-
name
|
|
30
|
+
name?: string;
|
|
31
31
|
/**
|
|
32
32
|
* Your merchant ID from the Frak dashboard (UUID format)
|
|
33
33
|
* Used for referral tracking and analytics
|
|
@@ -71,6 +71,13 @@ export type FrakWalletSdkConfig = {
|
|
|
71
71
|
* @defaultValue window.location.host
|
|
72
72
|
*/
|
|
73
73
|
domain?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Wait for backend config before rendering components.
|
|
76
|
+
* When true (default), components show a spinner until backend config is resolved.
|
|
77
|
+
* When false, components render immediately with SDK static config / HTML attributes.
|
|
78
|
+
* @defaultValue true
|
|
79
|
+
*/
|
|
80
|
+
waitForBackendConfig?: boolean;
|
|
74
81
|
};
|
|
75
82
|
|
|
76
83
|
/**
|
|
@@ -111,7 +118,7 @@ export type I18nConfig =
|
|
|
111
118
|
| LocalizedI18nConfig;
|
|
112
119
|
|
|
113
120
|
/**
|
|
114
|
-
* A localized i18n config
|
|
121
|
+
* A localized i18n config (inline objects only — URL-based i18n removed)
|
|
115
122
|
* @category Config
|
|
116
123
|
*/
|
|
117
|
-
export type LocalizedI18nConfig =
|
|
124
|
+
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,6 +76,7 @@ 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 {
|
|
@@ -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,22 @@ 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
|
+
sdkConfig?: ResolvedSdkConfig;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
@@ -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: {
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { Currency, Language } from "./config";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Response from the merchant resolve endpoint
|
|
5
|
+
* @category Config
|
|
6
|
+
*/
|
|
7
|
+
export type MerchantConfigResponse = {
|
|
8
|
+
merchantId: string;
|
|
9
|
+
name: string;
|
|
10
|
+
domain: string;
|
|
11
|
+
allowedDomains: string[];
|
|
12
|
+
sdkConfig?: ResolvedSdkConfig;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Resolved placement config from backend
|
|
17
|
+
* Translations already flattened: default + lang-specific merged into one record
|
|
18
|
+
* @category Config
|
|
19
|
+
*/
|
|
20
|
+
export type ResolvedPlacement = {
|
|
21
|
+
/** Per-component configuration within this placement */
|
|
22
|
+
components?: {
|
|
23
|
+
buttonShare?: {
|
|
24
|
+
text?: string;
|
|
25
|
+
noRewardText?: string;
|
|
26
|
+
clickAction?: "embedded-wallet" | "share-modal" | "sharing-page";
|
|
27
|
+
useReward?: boolean;
|
|
28
|
+
css?: string;
|
|
29
|
+
};
|
|
30
|
+
buttonWallet?: {
|
|
31
|
+
position?: "right" | "left";
|
|
32
|
+
css?: string;
|
|
33
|
+
};
|
|
34
|
+
openInApp?: {
|
|
35
|
+
text?: string;
|
|
36
|
+
css?: string;
|
|
37
|
+
};
|
|
38
|
+
postPurchase?: {
|
|
39
|
+
refereeText?: string;
|
|
40
|
+
refereeNoRewardText?: string;
|
|
41
|
+
referrerText?: string;
|
|
42
|
+
referrerNoRewardText?: string;
|
|
43
|
+
ctaText?: string;
|
|
44
|
+
ctaNoRewardText?: string;
|
|
45
|
+
css?: string;
|
|
46
|
+
};
|
|
47
|
+
banner?: {
|
|
48
|
+
referralTitle?: string;
|
|
49
|
+
referralDescription?: string;
|
|
50
|
+
referralCta?: string;
|
|
51
|
+
inappTitle?: string;
|
|
52
|
+
inappDescription?: string;
|
|
53
|
+
inappCta?: string;
|
|
54
|
+
css?: string;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
targetInteraction?: string;
|
|
58
|
+
/** Already flattened: default + lang-specific merged into one record */
|
|
59
|
+
translations?: Record<string, string>;
|
|
60
|
+
/** Global placement CSS (applied to modals/listener) */
|
|
61
|
+
css?: string;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Resolved SDK config from backend `/resolve` endpoint
|
|
66
|
+
* Language resolution and translation merging already applied
|
|
67
|
+
* @category Config
|
|
68
|
+
*/
|
|
69
|
+
export type ResolvedSdkConfig = {
|
|
70
|
+
name?: string;
|
|
71
|
+
logoUrl?: string;
|
|
72
|
+
homepageLink?: string;
|
|
73
|
+
currency?: Currency;
|
|
74
|
+
lang?: Language;
|
|
75
|
+
/** When true, all SDK components should be hidden */
|
|
76
|
+
hidden?: boolean;
|
|
77
|
+
css?: string;
|
|
78
|
+
translations?: Record<string, string>;
|
|
79
|
+
placements?: Record<string, ResolvedPlacement>;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Internal SDK config store state
|
|
84
|
+
* Merged config: backend > SDK static > defaults
|
|
85
|
+
* Components subscribe to this reactively
|
|
86
|
+
* @category Config
|
|
87
|
+
*/
|
|
88
|
+
export type SdkResolvedConfig = {
|
|
89
|
+
/** Whether the backend config has been resolved */
|
|
90
|
+
isResolved: boolean;
|
|
91
|
+
|
|
92
|
+
/** Merchant ID from resolution */
|
|
93
|
+
merchantId: string;
|
|
94
|
+
|
|
95
|
+
/** Domain returned by the resolve endpoint */
|
|
96
|
+
domain?: string;
|
|
97
|
+
|
|
98
|
+
/** Domains allowed for this merchant (used by iframe trust check) */
|
|
99
|
+
allowedDomains?: string[];
|
|
100
|
+
|
|
101
|
+
/** Whether the resolve returned a backend sdkConfig object */
|
|
102
|
+
hasRawSdkConfig?: boolean;
|
|
103
|
+
|
|
104
|
+
/** Merged metadata fields */
|
|
105
|
+
name?: string;
|
|
106
|
+
logoUrl?: string;
|
|
107
|
+
homepageLink?: string;
|
|
108
|
+
lang?: Language;
|
|
109
|
+
currency?: Currency;
|
|
110
|
+
|
|
111
|
+
/** When true, all SDK components should be hidden */
|
|
112
|
+
hidden?: boolean;
|
|
113
|
+
|
|
114
|
+
/** Global CSS from backend config (passed to iframe) */
|
|
115
|
+
css?: string;
|
|
116
|
+
|
|
117
|
+
/** Global translations (for reference / component fallback) */
|
|
118
|
+
translations?: Record<string, string>;
|
|
119
|
+
|
|
120
|
+
/** Named placements (keyed by placement ID) */
|
|
121
|
+
placements?: Record<string, ResolvedPlacement>;
|
|
122
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Parameters to display the sharing page
|
|
21
|
+
* @group Sharing Page
|
|
22
|
+
* @group RPC Schema
|
|
23
|
+
*/
|
|
24
|
+
export type DisplaySharingPageParamsType = {
|
|
25
|
+
/**
|
|
26
|
+
* Products to showcase on the sharing page
|
|
27
|
+
* If provided, they will be displayed in a product card section
|
|
28
|
+
*/
|
|
29
|
+
products?: SharingPageProduct[];
|
|
30
|
+
/**
|
|
31
|
+
* Optional link override for sharing
|
|
32
|
+
* If not provided, the sharing link will be generated from the current page URL + merchant context
|
|
33
|
+
*/
|
|
34
|
+
link?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Optional metadata overrides for the sharing page
|
|
37
|
+
*/
|
|
38
|
+
metadata?: {
|
|
39
|
+
/**
|
|
40
|
+
* Logo override for the sharing page header
|
|
41
|
+
*/
|
|
42
|
+
logo?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Link to the homepage of the calling website
|
|
45
|
+
*/
|
|
46
|
+
homepageLink?: string;
|
|
47
|
+
/**
|
|
48
|
+
* The target interaction behind this sharing page
|
|
49
|
+
*/
|
|
50
|
+
targetInteraction?: InteractionTypeKey;
|
|
51
|
+
/**
|
|
52
|
+
* i18n overrides for the sharing page
|
|
53
|
+
*/
|
|
54
|
+
i18n?: I18nConfig;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Result of the sharing page display
|
|
60
|
+
* @group Sharing Page
|
|
61
|
+
* @group RPC Schema
|
|
62
|
+
*/
|
|
63
|
+
export type DisplaySharingPageResultType = {
|
|
64
|
+
/**
|
|
65
|
+
* The action the user took
|
|
66
|
+
* - "shared": User used the native share dialog
|
|
67
|
+
* - "copied": User copied the link to clipboard
|
|
68
|
+
* - "dismissed": User dismissed the sharing page without acting
|
|
69
|
+
*/
|
|
70
|
+
action: "shared" | "copied" | "dismissed";
|
|
71
|
+
/**
|
|
72
|
+
* The install URL for the Frak app
|
|
73
|
+
* Can be used as a fallback to redirect the user to the install page
|
|
74
|
+
* from the merchant's top-level page (e.g. via `window.location.href`)
|
|
75
|
+
*/
|
|
76
|
+
installUrl?: string;
|
|
77
|
+
};
|
|
@@ -26,6 +26,10 @@ export type SendInteractionParamsType =
|
|
|
26
26
|
}
|
|
27
27
|
| {
|
|
28
28
|
type: "sharing";
|
|
29
|
+
/** Epoch seconds timestamp matching the V2 context `t` field embedded in the referral link URL, used for backend correlation */
|
|
30
|
+
sharingTimestamp?: number;
|
|
31
|
+
/** Merchant order ID linking this sharing event to a purchase (stays server-side, never in URL) */
|
|
32
|
+
purchaseId?: string;
|
|
29
33
|
}
|
|
30
34
|
| {
|
|
31
35
|
type: "custom";
|
|
@@ -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
|
+
};
|