@frak-labs/core-sdk 0.1.1 → 0.2.0-beta.7898df5b
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 +58 -0
- package/cdn/bundle.js +14 -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 -6
- package/dist/bundle.d.ts +4 -6
- package/dist/bundle.js +1 -1
- package/dist/computeLegacyProductId-CCAZvLa5.d.cts +537 -0
- package/dist/computeLegacyProductId-b5cUWdAm.d.ts +537 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +3 -4
- package/dist/index.d.ts +3 -4
- package/dist/index.js +1 -1
- package/dist/{openSso-D--Airj6.d.cts → openSso-B0g7-807.d.cts} +173 -136
- package/dist/{openSso-DsKJ4y0j.d.ts → openSso-CMzwvaCa.d.ts} +173 -136
- package/dist/setupClient-BICl5fdX.js +13 -0
- package/dist/setupClient-nl8Dhh4V.cjs +13 -0
- package/dist/siweAuthenticate-BWmI2_TN.cjs +1 -0
- package/dist/{index-d8xS4ryI.d.ts → siweAuthenticate-CVigMOxz.d.cts} +113 -92
- package/dist/{index-C6FxkWPC.d.cts → siweAuthenticate-CnCZ7mok.d.ts} +113 -92
- package/dist/siweAuthenticate-zczqxm0a.js +1 -0
- package/dist/trackEvent-CeLFVzZn.js +1 -0
- package/dist/trackEvent-Ew5r5zfI.cjs +1 -0
- package/package.json +11 -22
- package/src/actions/displayEmbeddedWallet.ts +1 -0
- package/src/actions/displayModal.test.ts +12 -11
- package/src/actions/displayModal.ts +7 -18
- package/src/actions/ensureIdentity.ts +68 -0
- package/src/actions/{getProductInformation.test.ts → getMerchantInformation.test.ts} +33 -50
- package/src/actions/getMerchantInformation.ts +16 -0
- package/src/actions/index.ts +3 -2
- package/src/actions/openSso.ts +4 -2
- package/src/actions/referral/processReferral.test.ts +117 -242
- package/src/actions/referral/processReferral.ts +134 -204
- package/src/actions/referral/referralInteraction.test.ts +4 -12
- package/src/actions/referral/referralInteraction.ts +3 -13
- package/src/actions/sendInteraction.ts +46 -22
- package/src/actions/trackPurchaseStatus.test.ts +354 -141
- package/src/actions/trackPurchaseStatus.ts +48 -11
- package/src/actions/watchWalletStatus.ts +2 -3
- package/src/actions/wrapper/modalBuilder.test.ts +0 -14
- package/src/actions/wrapper/modalBuilder.ts +3 -12
- package/src/bundle.ts +0 -1
- package/src/clients/createIFrameFrakClient.ts +10 -5
- package/src/clients/transports/iframeLifecycleManager.test.ts +163 -4
- package/src/clients/transports/iframeLifecycleManager.ts +172 -33
- package/src/constants/interactionTypes.ts +12 -41
- package/src/index.ts +27 -16
- package/src/types/config.ts +6 -0
- package/src/types/context.ts +48 -6
- package/src/types/index.ts +15 -11
- package/src/types/lifecycle/client.ts +24 -1
- package/src/types/lifecycle/iframe.ts +6 -0
- package/src/types/rpc/displayModal.ts +2 -4
- package/src/types/rpc/embedded/index.ts +2 -2
- package/src/types/rpc/interaction.ts +31 -39
- package/src/types/rpc/merchantInformation.ts +77 -0
- package/src/types/rpc/modal/index.ts +0 -4
- package/src/types/rpc/modal/login.ts +5 -1
- package/src/types/rpc/walletStatus.ts +1 -7
- package/src/types/rpc.ts +22 -30
- package/src/types/tracking.ts +31 -0
- package/src/utils/FrakContext.test.ts +270 -186
- package/src/utils/FrakContext.ts +78 -56
- package/src/utils/backendUrl.test.ts +83 -0
- package/src/utils/backendUrl.ts +62 -0
- package/src/utils/clientId.test.ts +41 -0
- package/src/utils/clientId.ts +43 -0
- package/src/utils/compression/compress.test.ts +1 -1
- package/src/utils/compression/compress.ts +2 -2
- package/src/utils/compression/decompress.test.ts +8 -4
- package/src/utils/compression/decompress.ts +2 -2
- package/src/utils/{computeProductId.ts → computeLegacyProductId.ts} +2 -2
- package/src/utils/constants.ts +5 -0
- package/src/utils/deepLinkWithFallback.test.ts +243 -0
- package/src/utils/deepLinkWithFallback.ts +103 -0
- package/src/utils/formatAmount.ts +6 -0
- package/src/utils/iframeHelper.test.ts +18 -5
- package/src/utils/iframeHelper.ts +10 -3
- package/src/utils/index.ts +16 -1
- package/src/utils/merchantId.test.ts +653 -0
- package/src/utils/merchantId.ts +143 -0
- package/src/utils/sso.ts +18 -11
- package/src/utils/trackEvent.test.ts +23 -5
- package/src/utils/trackEvent.ts +13 -0
- package/cdn/bundle.iife.js +0 -14
- package/dist/actions-B5j-i1p0.cjs +0 -1
- package/dist/actions-q090Z0oR.js +0 -1
- package/dist/index-7OZ39x1U.d.ts +0 -195
- package/dist/index-CRsQWnTs.d.cts +0 -351
- package/dist/index-Ck1hudEi.d.ts +0 -351
- package/dist/index-zDq-VlKx.d.cts +0 -195
- package/dist/interaction-DMJ3ZfaF.d.cts +0 -45
- package/dist/interaction-KX1h9a7V.d.ts +0 -45
- package/dist/interactions-DnfM3oe0.js +0 -1
- package/dist/interactions-EIXhNLf6.cjs +0 -1
- package/dist/interactions.cjs +0 -1
- package/dist/interactions.d.cts +0 -2
- package/dist/interactions.d.ts +0 -2
- package/dist/interactions.js +0 -1
- package/dist/productTypes-BUkXJKZ7.cjs +0 -1
- package/dist/productTypes-CGb1MmBF.js +0 -1
- package/dist/src-1LQ4eLq5.js +0 -13
- package/dist/src-hW71KjPN.cjs +0 -13
- package/dist/trackEvent-CHnYa85W.js +0 -1
- package/dist/trackEvent-GuQm_1Nm.cjs +0 -1
- package/src/actions/getProductInformation.ts +0 -14
- package/src/actions/openSso.test.ts +0 -407
- package/src/actions/sendInteraction.test.ts +0 -219
- package/src/constants/interactionTypes.test.ts +0 -128
- package/src/constants/productTypes.test.ts +0 -130
- package/src/constants/productTypes.ts +0 -33
- package/src/interactions/index.ts +0 -5
- package/src/interactions/pressEncoder.test.ts +0 -215
- package/src/interactions/pressEncoder.ts +0 -53
- package/src/interactions/purchaseEncoder.test.ts +0 -291
- package/src/interactions/purchaseEncoder.ts +0 -99
- package/src/interactions/referralEncoder.test.ts +0 -170
- package/src/interactions/referralEncoder.ts +0 -47
- package/src/interactions/retailEncoder.test.ts +0 -107
- package/src/interactions/retailEncoder.ts +0 -37
- package/src/interactions/webshopEncoder.test.ts +0 -56
- package/src/interactions/webshopEncoder.ts +0 -30
- package/src/types/rpc/modal/openSession.ts +0 -25
- package/src/types/rpc/productInformation.ts +0 -59
- package/src/utils/computeProductId.test.ts +0 -80
- package/src/utils/sso.test.ts +0 -361
|
@@ -1,22 +1,183 @@
|
|
|
1
1
|
import { Deferred } from "@frak-labs/frame-connector";
|
|
2
2
|
import type { FrakLifecycleEvent } from "../../types";
|
|
3
|
+
import { getClientId } from "../../utils/clientId";
|
|
3
4
|
import { BACKUP_KEY } from "../../utils/constants";
|
|
5
|
+
import {
|
|
6
|
+
isFrakDeepLink,
|
|
7
|
+
triggerDeepLinkWithFallback,
|
|
8
|
+
} from "../../utils/deepLinkWithFallback";
|
|
4
9
|
import { changeIframeVisibility } from "../../utils/iframeHelper";
|
|
5
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Detect iOS in-app browsers (Instagram, Facebook) where server-side
|
|
13
|
+
* 302 redirects to custom URL schemes (x-safari-https://) are silently
|
|
14
|
+
* swallowed by WKWebView. Direct window.location.href assignment works.
|
|
15
|
+
*/
|
|
16
|
+
const isIOSInAppBrowser = (() => {
|
|
17
|
+
if (typeof navigator === "undefined") return false;
|
|
18
|
+
const ua = navigator.userAgent;
|
|
19
|
+
// Standard iOS or iPadOS 13+ (reports as Macintosh with touch)
|
|
20
|
+
const isIOS =
|
|
21
|
+
/iPhone|iPad|iPod/i.test(ua) ||
|
|
22
|
+
(/Macintosh/i.test(ua) && navigator.maxTouchPoints > 1);
|
|
23
|
+
if (!isIOS) return false;
|
|
24
|
+
const lower = ua.toLowerCase();
|
|
25
|
+
return (
|
|
26
|
+
lower.includes("instagram") ||
|
|
27
|
+
lower.includes("fban") ||
|
|
28
|
+
lower.includes("fbav") ||
|
|
29
|
+
lower.includes("facebook")
|
|
30
|
+
);
|
|
31
|
+
})();
|
|
32
|
+
|
|
6
33
|
/** @ignore */
|
|
7
34
|
export type IframeLifecycleManager = {
|
|
8
35
|
isConnected: Promise<boolean>;
|
|
9
36
|
handleEvent: (messageEvent: FrakLifecycleEvent) => Promise<void>;
|
|
10
37
|
};
|
|
11
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Handle backup storage
|
|
41
|
+
*/
|
|
42
|
+
function handleBackup(backup: string | undefined): void {
|
|
43
|
+
if (backup) {
|
|
44
|
+
localStorage.setItem(BACKUP_KEY, backup);
|
|
45
|
+
} else {
|
|
46
|
+
localStorage.removeItem(BACKUP_KEY);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
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
|
+
/**
|
|
87
|
+
* Compute final redirect URL with parameter substitution
|
|
88
|
+
*/
|
|
89
|
+
function computeRedirectUrl(
|
|
90
|
+
baseRedirectUrl: string,
|
|
91
|
+
mergeToken?: string
|
|
92
|
+
): string {
|
|
93
|
+
try {
|
|
94
|
+
const redirectUrl = new URL(baseRedirectUrl);
|
|
95
|
+
if (!redirectUrl.searchParams.has("u")) {
|
|
96
|
+
return baseRedirectUrl;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
redirectUrl.searchParams.delete("u");
|
|
100
|
+
redirectUrl.searchParams.append("u", window.location.href);
|
|
101
|
+
|
|
102
|
+
if (mergeToken) {
|
|
103
|
+
redirectUrl.searchParams.append("fmt", mergeToken);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return redirectUrl.toString();
|
|
107
|
+
} catch {
|
|
108
|
+
return baseRedirectUrl;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Redirect current page to Safari via x-safari-https:// scheme.
|
|
114
|
+
* Used on iOS in-app browsers where backend 302 → custom scheme fails.
|
|
115
|
+
*/
|
|
116
|
+
function redirectToSafari(mergeToken?: string) {
|
|
117
|
+
const url = new URL(window.location.href);
|
|
118
|
+
if (mergeToken) {
|
|
119
|
+
url.searchParams.set("fmt", mergeToken);
|
|
120
|
+
}
|
|
121
|
+
const scheme =
|
|
122
|
+
url.protocol === "http:" ? "x-safari-http" : "x-safari-https";
|
|
123
|
+
window.location.href = `${scheme}://${url.host}${url.pathname}${url.search}${url.hash}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Check if this is a social/in-app-browser escape redirect (contains /common/social)
|
|
128
|
+
*/
|
|
129
|
+
function isSocialRedirect(url: string): boolean {
|
|
130
|
+
return url.includes("/common/social");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Handle redirect with deep link fallback
|
|
135
|
+
*/
|
|
136
|
+
function handleRedirect(
|
|
137
|
+
iframe: HTMLIFrameElement,
|
|
138
|
+
baseRedirectUrl: string,
|
|
139
|
+
targetOrigin: string,
|
|
140
|
+
mergeToken?: string
|
|
141
|
+
): void {
|
|
142
|
+
if (isFrakDeepLink(baseRedirectUrl)) {
|
|
143
|
+
const finalUrl = computeRedirectUrl(baseRedirectUrl, mergeToken);
|
|
144
|
+
triggerDeepLinkWithFallback(finalUrl, {
|
|
145
|
+
onFallback: () => {
|
|
146
|
+
iframe.contentWindow?.postMessage(
|
|
147
|
+
{
|
|
148
|
+
clientLifecycle: "deep-link-failed",
|
|
149
|
+
data: { originalUrl: finalUrl },
|
|
150
|
+
},
|
|
151
|
+
targetOrigin
|
|
152
|
+
);
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
} else if (isIOSInAppBrowser && isSocialRedirect(baseRedirectUrl)) {
|
|
156
|
+
// iOS WKWebView silently swallows 302 redirects to custom URL
|
|
157
|
+
// schemes — bypass the server redirect entirely
|
|
158
|
+
redirectToSafari(mergeToken);
|
|
159
|
+
} else {
|
|
160
|
+
const finalUrl = computeRedirectUrl(baseRedirectUrl, mergeToken);
|
|
161
|
+
window.location.href = finalUrl;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
12
165
|
/**
|
|
13
166
|
* Create a new iframe lifecycle handler
|
|
167
|
+
* @param args
|
|
168
|
+
* @param args.iframe - The iframe element used for wallet communication
|
|
169
|
+
* @param args.targetOrigin - The wallet URL origin for postMessage security
|
|
170
|
+
* @param args.configDomain - Optional domain override forwarded during handshake for tunneled/proxied environments
|
|
14
171
|
* @ignore
|
|
15
172
|
*/
|
|
16
173
|
export function createIFrameLifecycleManager({
|
|
17
174
|
iframe,
|
|
175
|
+
targetOrigin,
|
|
176
|
+
configDomain,
|
|
18
177
|
}: {
|
|
19
178
|
iframe: HTMLIFrameElement;
|
|
179
|
+
targetOrigin: string;
|
|
180
|
+
configDomain?: string;
|
|
20
181
|
}): IframeLifecycleManager {
|
|
21
182
|
// Create the isConnected listener
|
|
22
183
|
const isConnectedDeferred = new Deferred<boolean>();
|
|
@@ -34,11 +195,7 @@ export function createIFrameLifecycleManager({
|
|
|
34
195
|
break;
|
|
35
196
|
// Perform a frak backup
|
|
36
197
|
case "do-backup":
|
|
37
|
-
|
|
38
|
-
localStorage.setItem(BACKUP_KEY, data.backup);
|
|
39
|
-
} else {
|
|
40
|
-
localStorage.removeItem(BACKUP_KEY);
|
|
41
|
-
}
|
|
198
|
+
handleBackup(data.backup);
|
|
42
199
|
break;
|
|
43
200
|
// Remove frak backup
|
|
44
201
|
case "remove-backup":
|
|
@@ -47,39 +204,21 @@ export function createIFrameLifecycleManager({
|
|
|
47
204
|
// Change iframe visibility
|
|
48
205
|
case "show":
|
|
49
206
|
case "hide":
|
|
50
|
-
changeIframeVisibility({
|
|
51
|
-
iframe,
|
|
52
|
-
isVisible: event === "show",
|
|
53
|
-
});
|
|
207
|
+
changeIframeVisibility({ iframe, isVisible: event === "show" });
|
|
54
208
|
break;
|
|
55
209
|
// Handshake handling
|
|
56
|
-
case "handshake":
|
|
57
|
-
iframe.
|
|
58
|
-
{
|
|
59
|
-
clientLifecycle: "handshake-response",
|
|
60
|
-
data: {
|
|
61
|
-
token: data.token,
|
|
62
|
-
currentUrl: window.location.href,
|
|
63
|
-
},
|
|
64
|
-
},
|
|
65
|
-
"*"
|
|
66
|
-
);
|
|
210
|
+
case "handshake":
|
|
211
|
+
handleHandshake(iframe, data.token, targetOrigin, configDomain);
|
|
67
212
|
break;
|
|
68
|
-
}
|
|
69
213
|
// Redirect handling
|
|
70
|
-
case "redirect":
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
window.location.href = redirectUrl.toString();
|
|
78
|
-
} else {
|
|
79
|
-
window.location.href = data.baseRedirectUrl;
|
|
80
|
-
}
|
|
214
|
+
case "redirect":
|
|
215
|
+
handleRedirect(
|
|
216
|
+
iframe,
|
|
217
|
+
data.baseRedirectUrl,
|
|
218
|
+
targetOrigin,
|
|
219
|
+
data.mergeToken
|
|
220
|
+
);
|
|
81
221
|
break;
|
|
82
|
-
}
|
|
83
222
|
}
|
|
84
223
|
};
|
|
85
224
|
|
|
@@ -1,44 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The supported interaction type keys
|
|
3
|
+
*
|
|
4
|
+
* - `referral` - User arrived via a referral link
|
|
5
|
+
* - `create_referral_link` - User created/shared a referral link
|
|
6
|
+
* - `purchase` - User completed a purchase
|
|
7
|
+
* - `custom.${string}` - Custom interaction type defined per campaign
|
|
8
|
+
*
|
|
3
9
|
* @inline
|
|
4
10
|
*/
|
|
5
|
-
export type
|
|
6
|
-
|
|
7
|
-
|
|
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;
|
|
11
|
+
export type InteractionTypeKey =
|
|
12
|
+
| "referral"
|
|
13
|
+
| "create_referral_link"
|
|
14
|
+
| "purchase"
|
|
15
|
+
| `custom.${string}`;
|
package/src/index.ts
CHANGED
|
@@ -6,18 +6,10 @@ export {
|
|
|
6
6
|
DebugInfoGatherer,
|
|
7
7
|
setupClient,
|
|
8
8
|
} from "./clients";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
type InteractionTypesKey,
|
|
12
|
-
interactionTypes,
|
|
13
|
-
} from "./constants/interactionTypes";
|
|
9
|
+
|
|
10
|
+
export type { InteractionTypeKey } from "./constants/interactionTypes";
|
|
14
11
|
export { type LocalesKey, locales } from "./constants/locales";
|
|
15
|
-
|
|
16
|
-
export {
|
|
17
|
-
type ProductTypesKey,
|
|
18
|
-
productTypes,
|
|
19
|
-
productTypesMask,
|
|
20
|
-
} from "./constants/productTypes";
|
|
12
|
+
|
|
21
13
|
// Types
|
|
22
14
|
export type {
|
|
23
15
|
ClientLifecycleEvent,
|
|
@@ -29,16 +21,19 @@ export type {
|
|
|
29
21
|
DisplayModalParamsType,
|
|
30
22
|
EmbeddedViewActionReferred,
|
|
31
23
|
EmbeddedViewActionSharing,
|
|
24
|
+
EstimatedReward,
|
|
32
25
|
FinalActionType,
|
|
33
26
|
FinalModalStepType,
|
|
34
27
|
// Client
|
|
35
28
|
FrakClient,
|
|
36
29
|
// Utils
|
|
37
30
|
FrakContext,
|
|
31
|
+
FrakContextV1,
|
|
32
|
+
FrakContextV2,
|
|
38
33
|
FrakLifecycleEvent,
|
|
39
34
|
// Config
|
|
40
35
|
FrakWalletSdkConfig,
|
|
41
|
-
|
|
36
|
+
GetMerchantInformationReturnType,
|
|
42
37
|
HashProtectedData,
|
|
43
38
|
I18nConfig,
|
|
44
39
|
IFrameLifecycleEvent,
|
|
@@ -59,15 +54,13 @@ export type {
|
|
|
59
54
|
ModalStepMetadata,
|
|
60
55
|
// RPC Modal generics
|
|
61
56
|
ModalStepTypes,
|
|
62
|
-
OpenInteractionSessionModalStepType,
|
|
63
|
-
OpenInteractionSessionReturnType,
|
|
64
57
|
OpenSsoParamsType,
|
|
65
58
|
OpenSsoReturnType,
|
|
66
|
-
PreparedInteraction,
|
|
67
59
|
PrepareSsoParamsType,
|
|
68
60
|
PrepareSsoReturnType,
|
|
61
|
+
RewardTier,
|
|
62
|
+
// RPC Interaction
|
|
69
63
|
SendInteractionParamsType,
|
|
70
|
-
SendInteractionReturnType,
|
|
71
64
|
SendTransactionModalStepType,
|
|
72
65
|
SendTransactionReturnType,
|
|
73
66
|
SendTransactionTxType,
|
|
@@ -76,9 +69,14 @@ export type {
|
|
|
76
69
|
SiweAuthenticationParams,
|
|
77
70
|
SsoMetadata,
|
|
78
71
|
TokenAmountType,
|
|
72
|
+
// Tracking
|
|
73
|
+
TrackArrivalParams,
|
|
74
|
+
TrackArrivalResult,
|
|
75
|
+
UtmParams,
|
|
79
76
|
// Rpc
|
|
80
77
|
WalletStatusReturnType,
|
|
81
78
|
} from "./types";
|
|
79
|
+
export { isV1Context, isV2Context } from "./types";
|
|
82
80
|
// Utils
|
|
83
81
|
export {
|
|
84
82
|
type AppSpecificSsoMetadata,
|
|
@@ -86,16 +84,29 @@ export {
|
|
|
86
84
|
base64urlEncode,
|
|
87
85
|
baseIframeProps,
|
|
88
86
|
type CompressedSsoData,
|
|
87
|
+
clearMerchantIdCache,
|
|
89
88
|
compressJsonToB64,
|
|
90
89
|
createIframe,
|
|
90
|
+
DEEP_LINK_SCHEME,
|
|
91
|
+
type DeepLinkFallbackOptions,
|
|
91
92
|
decompressJsonFromB64,
|
|
92
93
|
FrakContextManager,
|
|
94
|
+
type FrakEvent,
|
|
93
95
|
type FullSsoParams,
|
|
96
|
+
fetchMerchantId,
|
|
94
97
|
findIframeInOpener,
|
|
95
98
|
formatAmount,
|
|
96
99
|
generateSsoUrl,
|
|
100
|
+
getBackendUrl,
|
|
101
|
+
getClientId,
|
|
97
102
|
getCurrencyAmountKey,
|
|
98
103
|
getSupportedCurrency,
|
|
99
104
|
getSupportedLocale,
|
|
105
|
+
isChromiumAndroid,
|
|
106
|
+
isFrakDeepLink,
|
|
107
|
+
resolveMerchantId,
|
|
108
|
+
toAndroidIntentUrl,
|
|
100
109
|
trackEvent,
|
|
110
|
+
triggerDeepLinkWithFallback,
|
|
101
111
|
} from "./utils";
|
|
112
|
+
export { computeLegacyProductId } from "./utils/computeLegacyProductId";
|
package/src/types/config.ts
CHANGED
|
@@ -28,6 +28,12 @@ export type FrakWalletSdkConfig = {
|
|
|
28
28
|
* Your application name (will be displayed in a few modals and in SSO)
|
|
29
29
|
*/
|
|
30
30
|
name: string;
|
|
31
|
+
/**
|
|
32
|
+
* Your merchant ID from the Frak dashboard (UUID format)
|
|
33
|
+
* Used for referral tracking and analytics
|
|
34
|
+
* If not provided, will be auto-fetched from the backend using your domain
|
|
35
|
+
*/
|
|
36
|
+
merchantId?: string;
|
|
31
37
|
/**
|
|
32
38
|
* Language to display in the modal
|
|
33
39
|
* If undefined, will default to the browser language
|
package/src/types/context.ts
CHANGED
|
@@ -1,13 +1,55 @@
|
|
|
1
1
|
import type { Address } from "viem";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* For now, only contain a referrer address.
|
|
7
|
-
*
|
|
4
|
+
* V1 (legacy) Frak Context — contains only the referrer wallet address.
|
|
5
|
+
* Used for backward compatibility with old sharing links.
|
|
8
6
|
* @ignore
|
|
9
7
|
*/
|
|
10
|
-
export type
|
|
11
|
-
|
|
8
|
+
export type FrakContextV1 = {
|
|
9
|
+
/** Referrer wallet address */
|
|
12
10
|
r: Address;
|
|
13
11
|
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* V2 Frak Context — anonymous-first referral context.
|
|
15
|
+
* Contains the sharer's clientId, merchantId, and link creation timestamp.
|
|
16
|
+
* @ignore
|
|
17
|
+
*/
|
|
18
|
+
export type FrakContextV2 = {
|
|
19
|
+
/** Version discriminator */
|
|
20
|
+
v: 2;
|
|
21
|
+
/** Sharer's anonymous clientId (UUID from localStorage) */
|
|
22
|
+
c: string;
|
|
23
|
+
/** Merchant ID (UUID) */
|
|
24
|
+
m: string;
|
|
25
|
+
/** Link creation timestamp (epoch seconds) */
|
|
26
|
+
t: number;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The current Frak Context — union of all versions.
|
|
31
|
+
*
|
|
32
|
+
* - No `v` field → V1 (legacy wallet address)
|
|
33
|
+
* - `v: 2` → V2 (anonymous clientId-based)
|
|
34
|
+
*
|
|
35
|
+
* @ignore
|
|
36
|
+
*/
|
|
37
|
+
export type FrakContext = FrakContextV1 | FrakContextV2;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Type guard: check if a context is V1 (legacy wallet address).
|
|
41
|
+
* @param ctx - The Frak context to check
|
|
42
|
+
* @returns True if the context is a V1 context
|
|
43
|
+
*/
|
|
44
|
+
export function isV1Context(ctx: FrakContext): ctx is FrakContextV1 {
|
|
45
|
+
return "r" in ctx && !("v" in ctx);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Type guard: check if a context is V2 (anonymous clientId-based).
|
|
50
|
+
* @param ctx - The Frak context to check
|
|
51
|
+
* @returns True if the context is a V2 context
|
|
52
|
+
*/
|
|
53
|
+
export function isV2Context(ctx: FrakContext): ctx is FrakContextV2 {
|
|
54
|
+
return "v" in ctx && ctx.v === 2;
|
|
55
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -15,7 +15,9 @@ export type {
|
|
|
15
15
|
LocalizedI18nConfig,
|
|
16
16
|
} from "./config";
|
|
17
17
|
// Utils
|
|
18
|
-
export type { FrakContext } from "./context";
|
|
18
|
+
export type { FrakContext, FrakContextV1, FrakContextV2 } from "./context";
|
|
19
|
+
export { isV1Context, isV2Context } from "./context";
|
|
20
|
+
|
|
19
21
|
export type {
|
|
20
22
|
ClientLifecycleEvent,
|
|
21
23
|
IFrameLifecycleEvent,
|
|
@@ -37,18 +39,18 @@ export type {
|
|
|
37
39
|
LoggedInEmbeddedView,
|
|
38
40
|
LoggedOutEmbeddedView,
|
|
39
41
|
} from "./rpc/embedded";
|
|
42
|
+
export type { SendInteractionParamsType } from "./rpc/interaction";
|
|
40
43
|
export type {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
EstimatedReward,
|
|
45
|
+
GetMerchantInformationReturnType,
|
|
46
|
+
RewardTier,
|
|
47
|
+
TokenAmountType,
|
|
48
|
+
} from "./rpc/merchantInformation";
|
|
45
49
|
export type {
|
|
46
50
|
FinalActionType,
|
|
47
51
|
FinalModalStepType,
|
|
48
52
|
LoginModalStepType,
|
|
49
53
|
ModalStepMetadata,
|
|
50
|
-
OpenInteractionSessionModalStepType,
|
|
51
|
-
OpenInteractionSessionReturnType,
|
|
52
54
|
SendTransactionModalStepType,
|
|
53
55
|
SendTransactionReturnType,
|
|
54
56
|
SendTransactionTxType,
|
|
@@ -56,10 +58,6 @@ export type {
|
|
|
56
58
|
SiweAuthenticateReturnType,
|
|
57
59
|
SiweAuthenticationParams,
|
|
58
60
|
} from "./rpc/modal";
|
|
59
|
-
export type {
|
|
60
|
-
GetProductInformationReturnType,
|
|
61
|
-
TokenAmountType,
|
|
62
|
-
} from "./rpc/productInformation";
|
|
63
61
|
export type {
|
|
64
62
|
OpenSsoParamsType,
|
|
65
63
|
OpenSsoReturnType,
|
|
@@ -68,4 +66,10 @@ export type {
|
|
|
68
66
|
SsoMetadata,
|
|
69
67
|
} from "./rpc/sso";
|
|
70
68
|
export type { WalletStatusReturnType } from "./rpc/walletStatus";
|
|
69
|
+
// Tracking
|
|
70
|
+
export type {
|
|
71
|
+
TrackArrivalParams,
|
|
72
|
+
TrackArrivalResult,
|
|
73
|
+
UtmParams,
|
|
74
|
+
} from "./tracking";
|
|
71
75
|
export type { FrakLifecycleEvent, IFrameTransport } from "./transport";
|
|
@@ -10,7 +10,8 @@ export type ClientLifecycleEvent =
|
|
|
10
10
|
| RestoreBackupEvent
|
|
11
11
|
| HearbeatEvent
|
|
12
12
|
| HandshakeResponse
|
|
13
|
-
| SsoRedirectCompleteEvent
|
|
13
|
+
| SsoRedirectCompleteEvent
|
|
14
|
+
| DeepLinkFailedEvent;
|
|
14
15
|
|
|
15
16
|
type CustomCssEvent = {
|
|
16
17
|
clientLifecycle: "modal-css";
|
|
@@ -37,6 +38,23 @@ type HandshakeResponse = {
|
|
|
37
38
|
data: {
|
|
38
39
|
token: string;
|
|
39
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;
|
|
40
58
|
};
|
|
41
59
|
};
|
|
42
60
|
|
|
@@ -44,3 +62,8 @@ type SsoRedirectCompleteEvent = {
|
|
|
44
62
|
clientLifecycle: "sso-redirect-complete";
|
|
45
63
|
data: { compressed: string };
|
|
46
64
|
};
|
|
65
|
+
|
|
66
|
+
type DeepLinkFailedEvent = {
|
|
67
|
+
clientLifecycle: "deep-link-failed";
|
|
68
|
+
data: { originalUrl: string };
|
|
69
|
+
};
|
|
@@ -31,5 +31,11 @@ type RedirectRequestEvent = {
|
|
|
31
31
|
* If it contain a query param `u`, the client need will suffix the current url to the base url
|
|
32
32
|
*/
|
|
33
33
|
baseRedirectUrl: string;
|
|
34
|
+
/**
|
|
35
|
+
* Optional merge token for anonymous identity merging
|
|
36
|
+
* When provided, appended as ?fmt= query parameter to the final redirect URL
|
|
37
|
+
* Used when redirecting out of social browsers to preserve identity across contexts
|
|
38
|
+
*/
|
|
39
|
+
mergeToken?: string;
|
|
34
40
|
};
|
|
35
41
|
};
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { InteractionTypeKey } from "../../constants/interactionTypes";
|
|
2
2
|
import type { I18nConfig } from "../config";
|
|
3
3
|
import type {
|
|
4
4
|
FinalModalStepType,
|
|
5
5
|
LoginModalStepType,
|
|
6
|
-
OpenInteractionSessionModalStepType,
|
|
7
6
|
SendTransactionModalStepType,
|
|
8
7
|
SiweAuthenticateModalStepType,
|
|
9
8
|
} from "./modal";
|
|
@@ -16,7 +15,6 @@ export type ModalStepTypes =
|
|
|
16
15
|
| LoginModalStepType
|
|
17
16
|
| SiweAuthenticateModalStepType
|
|
18
17
|
| SendTransactionModalStepType
|
|
19
|
-
| OpenInteractionSessionModalStepType
|
|
20
18
|
| FinalModalStepType;
|
|
21
19
|
|
|
22
20
|
/**
|
|
@@ -54,7 +52,7 @@ export type ModalRpcMetadata = {
|
|
|
54
52
|
title?: string;
|
|
55
53
|
icon?: string;
|
|
56
54
|
};
|
|
57
|
-
targetInteraction?:
|
|
55
|
+
targetInteraction?: InteractionTypeKey;
|
|
58
56
|
/**
|
|
59
57
|
* Some i18n override for the displayed modal (i.e. update the displayed text only for this modal)
|
|
60
58
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Address } from "viem";
|
|
2
|
-
import type {
|
|
2
|
+
import type { InteractionTypeKey } from "../../../constants/interactionTypes";
|
|
3
3
|
import type { I18nConfig } from "../../config";
|
|
4
4
|
import type {
|
|
5
5
|
EmbeddedViewActionReferred,
|
|
@@ -46,7 +46,7 @@ export type DisplayEmbeddedWalletParamsType = {
|
|
|
46
46
|
/**
|
|
47
47
|
* The target interaction behind this modal
|
|
48
48
|
*/
|
|
49
|
-
targetInteraction?:
|
|
49
|
+
targetInteraction?: InteractionTypeKey;
|
|
50
50
|
/**
|
|
51
51
|
* The position of the component
|
|
52
52
|
*/
|