@frak-labs/core-sdk 0.1.1 → 0.2.0-beta.514ef378

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.
Files changed (125) hide show
  1. package/README.md +58 -0
  2. package/cdn/bundle.js +14 -0
  3. package/dist/actions.cjs +1 -1
  4. package/dist/actions.d.cts +3 -3
  5. package/dist/actions.d.ts +3 -3
  6. package/dist/actions.js +1 -1
  7. package/dist/bundle.cjs +1 -1
  8. package/dist/bundle.d.cts +4 -6
  9. package/dist/bundle.d.ts +4 -6
  10. package/dist/bundle.js +1 -1
  11. package/dist/{index-CRsQWnTs.d.cts → computeLegacyProductId-BkyJ4rEY.d.ts} +197 -10
  12. package/dist/{index-Ck1hudEi.d.ts → computeLegacyProductId-Raks6FXg.d.cts} +197 -10
  13. package/dist/index.cjs +1 -1
  14. package/dist/index.d.cts +3 -4
  15. package/dist/index.d.ts +3 -4
  16. package/dist/index.js +1 -1
  17. package/dist/{openSso-D--Airj6.d.cts → openSso-BCJGchIb.d.cts} +135 -131
  18. package/dist/{openSso-DsKJ4y0j.d.ts → openSso-DG-_9CED.d.ts} +135 -131
  19. package/dist/setupClient-BEiAE56h.js +13 -0
  20. package/dist/setupClient-Ls3vKSlH.cjs +13 -0
  21. package/dist/{index-d8xS4ryI.d.ts → siweAuthenticate-BH7Dn7nZ.d.cts} +90 -65
  22. package/dist/siweAuthenticate-BJHbtty4.js +1 -0
  23. package/dist/{index-C6FxkWPC.d.cts → siweAuthenticate-Btem4QHs.d.ts} +90 -65
  24. package/dist/siweAuthenticate-Cwj3HP0m.cjs +1 -0
  25. package/dist/trackEvent-M2RLTQ2p.js +1 -0
  26. package/dist/trackEvent-T_R9ER2S.cjs +1 -0
  27. package/package.json +11 -22
  28. package/src/actions/displayEmbeddedWallet.ts +1 -0
  29. package/src/actions/displayModal.test.ts +12 -11
  30. package/src/actions/displayModal.ts +7 -18
  31. package/src/actions/ensureIdentity.ts +68 -0
  32. package/src/actions/{getProductInformation.test.ts → getMerchantInformation.test.ts} +33 -50
  33. package/src/actions/getMerchantInformation.ts +16 -0
  34. package/src/actions/index.ts +3 -2
  35. package/src/actions/openSso.ts +4 -2
  36. package/src/actions/referral/processReferral.test.ts +42 -151
  37. package/src/actions/referral/processReferral.ts +18 -42
  38. package/src/actions/referral/referralInteraction.test.ts +1 -7
  39. package/src/actions/referral/referralInteraction.ts +1 -6
  40. package/src/actions/sendInteraction.ts +46 -22
  41. package/src/actions/trackPurchaseStatus.test.ts +354 -141
  42. package/src/actions/trackPurchaseStatus.ts +48 -11
  43. package/src/actions/watchWalletStatus.ts +2 -3
  44. package/src/actions/wrapper/modalBuilder.test.ts +0 -14
  45. package/src/actions/wrapper/modalBuilder.ts +3 -12
  46. package/src/bundle.ts +0 -1
  47. package/src/clients/createIFrameFrakClient.ts +10 -5
  48. package/src/clients/transports/iframeLifecycleManager.test.ts +163 -4
  49. package/src/clients/transports/iframeLifecycleManager.ts +172 -33
  50. package/src/constants/interactionTypes.ts +12 -41
  51. package/src/index.ts +24 -16
  52. package/src/types/config.ts +6 -0
  53. package/src/types/index.ts +13 -10
  54. package/src/types/lifecycle/client.ts +24 -1
  55. package/src/types/lifecycle/iframe.ts +6 -0
  56. package/src/types/rpc/displayModal.ts +2 -4
  57. package/src/types/rpc/embedded/index.ts +2 -2
  58. package/src/types/rpc/interaction.ts +26 -39
  59. package/src/types/rpc/merchantInformation.ts +77 -0
  60. package/src/types/rpc/modal/index.ts +0 -4
  61. package/src/types/rpc/modal/login.ts +5 -1
  62. package/src/types/rpc/walletStatus.ts +1 -7
  63. package/src/types/rpc.ts +22 -30
  64. package/src/types/tracking.ts +60 -0
  65. package/src/utils/backendUrl.test.ts +83 -0
  66. package/src/utils/backendUrl.ts +62 -0
  67. package/src/utils/clientId.test.ts +41 -0
  68. package/src/utils/clientId.ts +43 -0
  69. package/src/utils/compression/compress.test.ts +1 -1
  70. package/src/utils/compression/compress.ts +2 -2
  71. package/src/utils/compression/decompress.test.ts +8 -4
  72. package/src/utils/compression/decompress.ts +2 -2
  73. package/src/utils/{computeProductId.ts → computeLegacyProductId.ts} +2 -2
  74. package/src/utils/constants.ts +5 -0
  75. package/src/utils/deepLinkWithFallback.test.ts +243 -0
  76. package/src/utils/deepLinkWithFallback.ts +103 -0
  77. package/src/utils/formatAmount.ts +6 -0
  78. package/src/utils/iframeHelper.test.ts +18 -5
  79. package/src/utils/iframeHelper.ts +10 -3
  80. package/src/utils/index.ts +16 -1
  81. package/src/utils/merchantId.test.ts +653 -0
  82. package/src/utils/merchantId.ts +143 -0
  83. package/src/utils/sso.ts +18 -11
  84. package/src/utils/trackEvent.test.ts +23 -5
  85. package/src/utils/trackEvent.ts +13 -0
  86. package/cdn/bundle.iife.js +0 -14
  87. package/dist/actions-B5j-i1p0.cjs +0 -1
  88. package/dist/actions-q090Z0oR.js +0 -1
  89. package/dist/index-7OZ39x1U.d.ts +0 -195
  90. package/dist/index-zDq-VlKx.d.cts +0 -195
  91. package/dist/interaction-DMJ3ZfaF.d.cts +0 -45
  92. package/dist/interaction-KX1h9a7V.d.ts +0 -45
  93. package/dist/interactions-DnfM3oe0.js +0 -1
  94. package/dist/interactions-EIXhNLf6.cjs +0 -1
  95. package/dist/interactions.cjs +0 -1
  96. package/dist/interactions.d.cts +0 -2
  97. package/dist/interactions.d.ts +0 -2
  98. package/dist/interactions.js +0 -1
  99. package/dist/productTypes-BUkXJKZ7.cjs +0 -1
  100. package/dist/productTypes-CGb1MmBF.js +0 -1
  101. package/dist/src-1LQ4eLq5.js +0 -13
  102. package/dist/src-hW71KjPN.cjs +0 -13
  103. package/dist/trackEvent-CHnYa85W.js +0 -1
  104. package/dist/trackEvent-GuQm_1Nm.cjs +0 -1
  105. package/src/actions/getProductInformation.ts +0 -14
  106. package/src/actions/openSso.test.ts +0 -407
  107. package/src/actions/sendInteraction.test.ts +0 -219
  108. package/src/constants/interactionTypes.test.ts +0 -128
  109. package/src/constants/productTypes.test.ts +0 -130
  110. package/src/constants/productTypes.ts +0 -33
  111. package/src/interactions/index.ts +0 -5
  112. package/src/interactions/pressEncoder.test.ts +0 -215
  113. package/src/interactions/pressEncoder.ts +0 -53
  114. package/src/interactions/purchaseEncoder.test.ts +0 -291
  115. package/src/interactions/purchaseEncoder.ts +0 -99
  116. package/src/interactions/referralEncoder.test.ts +0 -170
  117. package/src/interactions/referralEncoder.ts +0 -47
  118. package/src/interactions/retailEncoder.test.ts +0 -107
  119. package/src/interactions/retailEncoder.ts +0 -37
  120. package/src/interactions/webshopEncoder.test.ts +0 -56
  121. package/src/interactions/webshopEncoder.ts +0 -30
  122. package/src/types/rpc/modal/openSession.ts +0 -25
  123. package/src/types/rpc/productInformation.ts +0 -59
  124. package/src/utils/computeProductId.test.ts +0 -80
  125. 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
- if (data.backup) {
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.contentWindow?.postMessage(
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
- const redirectUrl = new URL(data.baseRedirectUrl);
72
-
73
- // If we got a u append the current location dynamicly
74
- if (redirectUrl.searchParams.has("u")) {
75
- redirectUrl.searchParams.delete("u");
76
- redirectUrl.searchParams.append("u", window.location.href);
77
- window.location.href = redirectUrl.toString();
78
- } else {
79
- window.location.href = data.baseRedirectUrl;
80
- }
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 final keys for each interaction types (e.g. `openArticle`) -> interaction type
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 InteractionTypesKey = {
6
- [K in keyof typeof interactionTypes]: keyof (typeof interactionTypes)[K];
7
- }[keyof typeof interactionTypes];
8
-
9
- /**
10
- * The keys for each interaction types (e.g. `press.openArticle`) -> category_type.interaction_type
11
- * @inline
12
- */
13
- export type FullInteractionTypesKey = {
14
- [Category in keyof typeof interactionTypes]: `${Category & string}.${keyof (typeof interactionTypes)[Category] & string}`;
15
- }[keyof typeof interactionTypes];
16
-
17
- /**
18
- * Each interactions types according to the product types
19
- */
20
- export const interactionTypes = {
21
- press: {
22
- openArticle: "0xc0a24ffb",
23
- readArticle: "0xd5bd0fbe",
24
- },
25
- dapp: {
26
- proofVerifiableStorageUpdate: "0x2ab2aeef",
27
- callableVerifiableStorageUpdate: "0xa07da986",
28
- },
29
- webshop: {
30
- open: "0xb311798f",
31
- },
32
- referral: {
33
- referred: "0x010cc3b9",
34
- createLink: "0xb2c0f17c",
35
- },
36
- purchase: {
37
- started: "0xd87e90c3",
38
- completed: "0x8403aeb4",
39
- unsafeCompleted: "0x4d5b14e0",
40
- },
41
- retail: {
42
- customerMeeting: "0x74489004",
43
- },
44
- } as const;
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
- export {
10
- type FullInteractionTypesKey,
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
- // Constants
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,6 +21,7 @@ export type {
29
21
  DisplayModalParamsType,
30
22
  EmbeddedViewActionReferred,
31
23
  EmbeddedViewActionSharing,
24
+ EstimatedReward,
32
25
  FinalActionType,
33
26
  FinalModalStepType,
34
27
  // Client
@@ -38,7 +31,7 @@ export type {
38
31
  FrakLifecycleEvent,
39
32
  // Config
40
33
  FrakWalletSdkConfig,
41
- GetProductInformationReturnType,
34
+ GetMerchantInformationReturnType,
42
35
  HashProtectedData,
43
36
  I18nConfig,
44
37
  IFrameLifecycleEvent,
@@ -59,15 +52,13 @@ export type {
59
52
  ModalStepMetadata,
60
53
  // RPC Modal generics
61
54
  ModalStepTypes,
62
- OpenInteractionSessionModalStepType,
63
- OpenInteractionSessionReturnType,
64
55
  OpenSsoParamsType,
65
56
  OpenSsoReturnType,
66
- PreparedInteraction,
67
57
  PrepareSsoParamsType,
68
58
  PrepareSsoReturnType,
59
+ RewardTier,
60
+ // RPC Interaction
69
61
  SendInteractionParamsType,
70
- SendInteractionReturnType,
71
62
  SendTransactionModalStepType,
72
63
  SendTransactionReturnType,
73
64
  SendTransactionTxType,
@@ -76,6 +67,10 @@ export type {
76
67
  SiweAuthenticationParams,
77
68
  SsoMetadata,
78
69
  TokenAmountType,
70
+ // Tracking
71
+ TrackArrivalParams,
72
+ TrackArrivalResult,
73
+ UtmParams,
79
74
  // Rpc
80
75
  WalletStatusReturnType,
81
76
  } from "./types";
@@ -86,16 +81,29 @@ export {
86
81
  base64urlEncode,
87
82
  baseIframeProps,
88
83
  type CompressedSsoData,
84
+ clearMerchantIdCache,
89
85
  compressJsonToB64,
90
86
  createIframe,
87
+ DEEP_LINK_SCHEME,
88
+ type DeepLinkFallbackOptions,
91
89
  decompressJsonFromB64,
92
90
  FrakContextManager,
91
+ type FrakEvent,
93
92
  type FullSsoParams,
93
+ fetchMerchantId,
94
94
  findIframeInOpener,
95
95
  formatAmount,
96
96
  generateSsoUrl,
97
+ getBackendUrl,
98
+ getClientId,
97
99
  getCurrencyAmountKey,
98
100
  getSupportedCurrency,
99
101
  getSupportedLocale,
102
+ isChromiumAndroid,
103
+ isFrakDeepLink,
104
+ resolveMerchantId,
105
+ toAndroidIntentUrl,
100
106
  trackEvent,
107
+ triggerDeepLinkWithFallback,
101
108
  } from "./utils";
109
+ export { computeLegacyProductId } from "./utils/computeLegacyProductId";
@@ -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
@@ -16,6 +16,7 @@ export type {
16
16
  } from "./config";
17
17
  // Utils
18
18
  export type { FrakContext } from "./context";
19
+
19
20
  export type {
20
21
  ClientLifecycleEvent,
21
22
  IFrameLifecycleEvent,
@@ -37,18 +38,18 @@ export type {
37
38
  LoggedInEmbeddedView,
38
39
  LoggedOutEmbeddedView,
39
40
  } from "./rpc/embedded";
41
+ export type { SendInteractionParamsType } from "./rpc/interaction";
40
42
  export type {
41
- PreparedInteraction,
42
- SendInteractionParamsType,
43
- SendInteractionReturnType,
44
- } from "./rpc/interaction";
43
+ EstimatedReward,
44
+ GetMerchantInformationReturnType,
45
+ RewardTier,
46
+ TokenAmountType,
47
+ } from "./rpc/merchantInformation";
45
48
  export type {
46
49
  FinalActionType,
47
50
  FinalModalStepType,
48
51
  LoginModalStepType,
49
52
  ModalStepMetadata,
50
- OpenInteractionSessionModalStepType,
51
- OpenInteractionSessionReturnType,
52
53
  SendTransactionModalStepType,
53
54
  SendTransactionReturnType,
54
55
  SendTransactionTxType,
@@ -56,10 +57,6 @@ export type {
56
57
  SiweAuthenticateReturnType,
57
58
  SiweAuthenticationParams,
58
59
  } from "./rpc/modal";
59
- export type {
60
- GetProductInformationReturnType,
61
- TokenAmountType,
62
- } from "./rpc/productInformation";
63
60
  export type {
64
61
  OpenSsoParamsType,
65
62
  OpenSsoReturnType,
@@ -68,4 +65,10 @@ export type {
68
65
  SsoMetadata,
69
66
  } from "./rpc/sso";
70
67
  export type { WalletStatusReturnType } from "./rpc/walletStatus";
68
+ // Tracking
69
+ export type {
70
+ TrackArrivalParams,
71
+ TrackArrivalResult,
72
+ UtmParams,
73
+ } from "./tracking";
71
74
  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 { FullInteractionTypesKey } from "../../constants/interactionTypes";
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?: FullInteractionTypesKey;
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 { FullInteractionTypesKey } from "../../../constants/interactionTypes";
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?: FullInteractionTypesKey;
49
+ targetInteraction?: InteractionTypeKey;
50
50
  /**
51
51
  * The position of the component
52
52
  */
@@ -1,43 +1,30 @@
1
- import type { Hex } from "viem";
1
+ import type { Address } from "viem";
2
2
 
3
3
  /**
4
- * Represent a prepared user interaction, ready to be sent on-chain via the wallet
5
- */
6
- export type PreparedInteraction = {
7
- handlerTypeDenominator: Hex;
8
- interactionData: Hex;
9
- };
10
-
11
- /**
12
- * Parameters that will be used to send an interaction to the blockchain
13
- * @inline
14
- */
15
- export type SendInteractionParamsType = {
16
- /**
17
- * The product id where this interaction has been made
18
- * @defaultValue keccak256(toHex(window.location.host))
19
- */
20
- productId?: Hex;
21
- /**
22
- * The prepared interaction, built from an Interaction Encoder
23
- */
24
- interaction: PreparedInteraction;
25
- /**
26
- * A pre-computed interaction signature
27
- * If none provided, the delegated interaction validator of your product will sign it (you can manage it in the business dashboard)
28
- *
29
- * @defaultValue undefined
30
- */
31
- validation?: Hex;
32
- };
33
-
34
- /**
35
- * Return type of the send interaction rpc request
4
+ * Parameters for sending interactions via RPC
5
+ *
6
+ * Note: merchantId and clientId come from WalletRpcContext
7
+ * and are NOT included in the params - they are resolved by the listener
8
+ *
36
9
  * @group RPC Schema
37
10
  */
38
- export type SendInteractionReturnType = {
39
- /**
40
- * The id of the interaction in the interaction pool
41
- */
42
- delegationId: string;
43
- };
11
+ export type SendInteractionParamsType =
12
+ | {
13
+ type: "arrival";
14
+ referrerWallet?: Address;
15
+ landingUrl?: string;
16
+ utmSource?: string;
17
+ utmMedium?: string;
18
+ utmCampaign?: string;
19
+ utmTerm?: string;
20
+ utmContent?: string;
21
+ }
22
+ | {
23
+ type: "sharing";
24
+ }
25
+ | {
26
+ type: "custom";
27
+ customType: string;
28
+ data?: Record<string, unknown>;
29
+ idempotencyKey?: string;
30
+ };