@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.
Files changed (130) 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/computeLegacyProductId-CCAZvLa5.d.cts +537 -0
  12. package/dist/computeLegacyProductId-b5cUWdAm.d.ts +537 -0
  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-B0g7-807.d.cts} +173 -136
  18. package/dist/{openSso-DsKJ4y0j.d.ts → openSso-CMzwvaCa.d.ts} +173 -136
  19. package/dist/setupClient-BICl5fdX.js +13 -0
  20. package/dist/setupClient-nl8Dhh4V.cjs +13 -0
  21. package/dist/siweAuthenticate-BWmI2_TN.cjs +1 -0
  22. package/dist/{index-d8xS4ryI.d.ts → siweAuthenticate-CVigMOxz.d.cts} +113 -92
  23. package/dist/{index-C6FxkWPC.d.cts → siweAuthenticate-CnCZ7mok.d.ts} +113 -92
  24. package/dist/siweAuthenticate-zczqxm0a.js +1 -0
  25. package/dist/trackEvent-CeLFVzZn.js +1 -0
  26. package/dist/trackEvent-Ew5r5zfI.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 +117 -242
  37. package/src/actions/referral/processReferral.ts +134 -204
  38. package/src/actions/referral/referralInteraction.test.ts +4 -12
  39. package/src/actions/referral/referralInteraction.ts +3 -13
  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 +27 -16
  52. package/src/types/config.ts +6 -0
  53. package/src/types/context.ts +48 -6
  54. package/src/types/index.ts +15 -11
  55. package/src/types/lifecycle/client.ts +24 -1
  56. package/src/types/lifecycle/iframe.ts +6 -0
  57. package/src/types/rpc/displayModal.ts +2 -4
  58. package/src/types/rpc/embedded/index.ts +2 -2
  59. package/src/types/rpc/interaction.ts +31 -39
  60. package/src/types/rpc/merchantInformation.ts +77 -0
  61. package/src/types/rpc/modal/index.ts +0 -4
  62. package/src/types/rpc/modal/login.ts +5 -1
  63. package/src/types/rpc/walletStatus.ts +1 -7
  64. package/src/types/rpc.ts +22 -30
  65. package/src/types/tracking.ts +31 -0
  66. package/src/utils/FrakContext.test.ts +270 -186
  67. package/src/utils/FrakContext.ts +78 -56
  68. package/src/utils/backendUrl.test.ts +83 -0
  69. package/src/utils/backendUrl.ts +62 -0
  70. package/src/utils/clientId.test.ts +41 -0
  71. package/src/utils/clientId.ts +43 -0
  72. package/src/utils/compression/compress.test.ts +1 -1
  73. package/src/utils/compression/compress.ts +2 -2
  74. package/src/utils/compression/decompress.test.ts +8 -4
  75. package/src/utils/compression/decompress.ts +2 -2
  76. package/src/utils/{computeProductId.ts → computeLegacyProductId.ts} +2 -2
  77. package/src/utils/constants.ts +5 -0
  78. package/src/utils/deepLinkWithFallback.test.ts +243 -0
  79. package/src/utils/deepLinkWithFallback.ts +103 -0
  80. package/src/utils/formatAmount.ts +6 -0
  81. package/src/utils/iframeHelper.test.ts +18 -5
  82. package/src/utils/iframeHelper.ts +10 -3
  83. package/src/utils/index.ts +16 -1
  84. package/src/utils/merchantId.test.ts +653 -0
  85. package/src/utils/merchantId.ts +143 -0
  86. package/src/utils/sso.ts +18 -11
  87. package/src/utils/trackEvent.test.ts +23 -5
  88. package/src/utils/trackEvent.ts +13 -0
  89. package/cdn/bundle.iife.js +0 -14
  90. package/dist/actions-B5j-i1p0.cjs +0 -1
  91. package/dist/actions-q090Z0oR.js +0 -1
  92. package/dist/index-7OZ39x1U.d.ts +0 -195
  93. package/dist/index-CRsQWnTs.d.cts +0 -351
  94. package/dist/index-Ck1hudEi.d.ts +0 -351
  95. package/dist/index-zDq-VlKx.d.cts +0 -195
  96. package/dist/interaction-DMJ3ZfaF.d.cts +0 -45
  97. package/dist/interaction-KX1h9a7V.d.ts +0 -45
  98. package/dist/interactions-DnfM3oe0.js +0 -1
  99. package/dist/interactions-EIXhNLf6.cjs +0 -1
  100. package/dist/interactions.cjs +0 -1
  101. package/dist/interactions.d.cts +0 -2
  102. package/dist/interactions.d.ts +0 -2
  103. package/dist/interactions.js +0 -1
  104. package/dist/productTypes-BUkXJKZ7.cjs +0 -1
  105. package/dist/productTypes-CGb1MmBF.js +0 -1
  106. package/dist/src-1LQ4eLq5.js +0 -13
  107. package/dist/src-hW71KjPN.cjs +0 -13
  108. package/dist/trackEvent-CHnYa85W.js +0 -1
  109. package/dist/trackEvent-GuQm_1Nm.cjs +0 -1
  110. package/src/actions/getProductInformation.ts +0 -14
  111. package/src/actions/openSso.test.ts +0 -407
  112. package/src/actions/sendInteraction.test.ts +0 -219
  113. package/src/constants/interactionTypes.test.ts +0 -128
  114. package/src/constants/productTypes.test.ts +0 -130
  115. package/src/constants/productTypes.ts +0 -33
  116. package/src/interactions/index.ts +0 -5
  117. package/src/interactions/pressEncoder.test.ts +0 -215
  118. package/src/interactions/pressEncoder.ts +0 -53
  119. package/src/interactions/purchaseEncoder.test.ts +0 -291
  120. package/src/interactions/purchaseEncoder.ts +0 -99
  121. package/src/interactions/referralEncoder.test.ts +0 -170
  122. package/src/interactions/referralEncoder.ts +0 -47
  123. package/src/interactions/retailEncoder.test.ts +0 -107
  124. package/src/interactions/retailEncoder.ts +0 -37
  125. package/src/interactions/webshopEncoder.test.ts +0 -56
  126. package/src/interactions/webshopEncoder.ts +0 -30
  127. package/src/types/rpc/modal/openSession.ts +0 -25
  128. package/src/types/rpc/productInformation.ts +0 -59
  129. package/src/utils/computeProductId.test.ts +0 -80
  130. package/src/utils/sso.test.ts +0 -361
@@ -0,0 +1,68 @@
1
+ import { getBackendUrl } from "../utils/backendUrl";
2
+ import { getClientId } from "../utils/clientId";
3
+ import { fetchMerchantId } from "../utils/merchantId";
4
+
5
+ const ENSURE_STORAGE_PREFIX = "frak-identity-ensured-";
6
+
7
+ /**
8
+ * Ensure the current wallet ↔ clientId link exists on the backend.
9
+ *
10
+ * Called automatically by {@link watchWalletStatus} when a connected wallet
11
+ * status is received. Acts as a failsafe: if the primary merge (SSO, pairing,
12
+ * login/register) missed or silently failed, this ensures the link is
13
+ * eventually established.
14
+ *
15
+ * The call is:
16
+ * - **Idempotent** — if already linked, backend returns immediately
17
+ * - **Deduplicated** — only fires once per browser session per merchant
18
+ * - **Fire-and-forget** — errors are logged but never thrown
19
+ *
20
+ * @param interactionToken - The SDK JWT from wallet status (x-wallet-sdk-auth)
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * // Usually called automatically via watchWalletStatus side effect.
25
+ * // Can also be called manually if needed:
26
+ * await ensureIdentity("eyJhbGciOi...");
27
+ * ```
28
+ */
29
+ export async function ensureIdentity(interactionToken: string): Promise<void> {
30
+ if (typeof window === "undefined") {
31
+ return;
32
+ }
33
+
34
+ const clientId = getClientId();
35
+ if (!clientId) {
36
+ return;
37
+ }
38
+
39
+ const merchantId = await fetchMerchantId();
40
+ if (!merchantId) {
41
+ return;
42
+ }
43
+
44
+ const storageKey = `${ENSURE_STORAGE_PREFIX}${merchantId}`;
45
+ if (window.sessionStorage.getItem(storageKey)) {
46
+ return;
47
+ }
48
+
49
+ try {
50
+ const backendUrl = getBackendUrl();
51
+ const response = await fetch(`${backendUrl}/user/identity/ensure`, {
52
+ method: "POST",
53
+ headers: {
54
+ Accept: "application/json",
55
+ "Content-Type": "application/json",
56
+ "x-wallet-sdk-auth": interactionToken,
57
+ "x-frak-client-id": clientId,
58
+ },
59
+ body: JSON.stringify({ merchantId }),
60
+ });
61
+
62
+ if (response.ok) {
63
+ window.sessionStorage.setItem(storageKey, "1");
64
+ }
65
+ } catch {
66
+ // Fire-and-forget — retry on next session
67
+ }
68
+ }
@@ -1,22 +1,16 @@
1
- /**
2
- * Tests for getProductInformation action
3
- * Tests fetching product information via RPC
4
- */
5
-
6
1
  import type { Address, Hex } from "viem";
7
2
  import { describe, expect, it, vi } from "../../tests/vitest-fixtures";
8
- import type { FrakClient, GetProductInformationReturnType } from "../types";
9
- import { getProductInformation } from "./getProductInformation";
3
+ import type { FrakClient, GetMerchantInformationReturnType } from "../types";
4
+ import { getMerchantInformation } from "./getMerchantInformation";
10
5
 
11
- describe("getProductInformation", () => {
6
+ describe("getMerchantInformation", () => {
12
7
  describe("success cases", () => {
13
8
  it("should call client.request with correct method", async () => {
14
- const mockResponse: GetProductInformationReturnType = {
9
+ const mockResponse: GetMerchantInformationReturnType = {
15
10
  id: "0x1234567890123456789012345678901234567890123456789012345678901234" as Hex,
16
11
  onChainMetadata: {
17
- name: "Test Product",
12
+ name: "Test Merchant",
18
13
  domain: "example.com",
19
- productTypes: ["press"],
20
14
  },
21
15
  rewards: [],
22
16
  };
@@ -25,20 +19,19 @@ describe("getProductInformation", () => {
25
19
  request: vi.fn().mockResolvedValue(mockResponse),
26
20
  } as unknown as FrakClient;
27
21
 
28
- await getProductInformation(mockClient);
22
+ await getMerchantInformation(mockClient);
29
23
 
30
24
  expect(mockClient.request).toHaveBeenCalledWith({
31
- method: "frak_getProductInformation",
25
+ method: "frak_getMerchantInformation",
32
26
  });
33
27
  });
34
28
 
35
- it("should return product information", async () => {
36
- const mockResponse: GetProductInformationReturnType = {
29
+ it("should return merchant information", async () => {
30
+ const mockResponse: GetMerchantInformationReturnType = {
37
31
  id: "0x1234567890123456789012345678901234567890123456789012345678901234" as Hex,
38
32
  onChainMetadata: {
39
- name: "Test Product",
33
+ name: "Test Merchant",
40
34
  domain: "example.com",
41
- productTypes: ["press"],
42
35
  },
43
36
  rewards: [],
44
37
  };
@@ -47,48 +40,40 @@ describe("getProductInformation", () => {
47
40
  request: vi.fn().mockResolvedValue(mockResponse),
48
41
  } as unknown as FrakClient;
49
42
 
50
- const result = await getProductInformation(mockClient);
43
+ const result = await getMerchantInformation(mockClient);
51
44
 
52
45
  expect(result).toEqual(mockResponse);
53
46
  });
54
47
 
55
- it("should return product information with rewards", async () => {
56
- const mockResponse: GetProductInformationReturnType = {
48
+ it("should return merchant information with rewards", async () => {
49
+ const mockResponse: GetMerchantInformationReturnType = {
57
50
  id: "0x1234567890123456789012345678901234567890123456789012345678901234" as Hex,
58
51
  onChainMetadata: {
59
- name: "Test Product",
52
+ name: "Test Merchant",
60
53
  domain: "example.com",
61
- productTypes: ["press", "purchase"],
62
- },
63
- maxReferrer: {
64
- amount: 100,
65
- eurAmount: 10,
66
- usdAmount: 12,
67
- gbpAmount: 9,
68
- },
69
- maxReferee: {
70
- amount: 50,
71
- eurAmount: 5,
72
- usdAmount: 6,
73
- gbpAmount: 4.5,
74
54
  },
75
55
  rewards: [
76
56
  {
77
57
  token: "0x1234567890123456789012345678901234567890" as Address,
78
- campaign:
79
- "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd" as Address,
80
- interactionTypeKey: "press.readArticle",
58
+ campaignId: "campaign-1",
59
+ interactionTypeKey: "referral",
81
60
  referrer: {
82
- amount: 10,
83
- eurAmount: 1,
84
- usdAmount: 1.2,
85
- gbpAmount: 0.9,
61
+ payoutType: "fixed",
62
+ amount: {
63
+ amount: 10,
64
+ eurAmount: 1,
65
+ usdAmount: 1.2,
66
+ gbpAmount: 0.9,
67
+ },
86
68
  },
87
69
  referee: {
88
- amount: 5,
89
- eurAmount: 0.5,
90
- usdAmount: 0.6,
91
- gbpAmount: 0.45,
70
+ payoutType: "fixed",
71
+ amount: {
72
+ amount: 5,
73
+ eurAmount: 0.5,
74
+ usdAmount: 0.6,
75
+ gbpAmount: 0.45,
76
+ },
92
77
  },
93
78
  },
94
79
  ],
@@ -98,12 +83,10 @@ describe("getProductInformation", () => {
98
83
  request: vi.fn().mockResolvedValue(mockResponse),
99
84
  } as unknown as FrakClient;
100
85
 
101
- const result = await getProductInformation(mockClient);
86
+ const result = await getMerchantInformation(mockClient);
102
87
 
103
88
  expect(result).toEqual(mockResponse);
104
89
  expect(result.rewards).toHaveLength(1);
105
- expect(result.maxReferrer).toBeDefined();
106
- expect(result.maxReferee).toBeDefined();
107
90
  });
108
91
  });
109
92
 
@@ -114,7 +97,7 @@ describe("getProductInformation", () => {
114
97
  request: vi.fn().mockRejectedValue(error),
115
98
  } as unknown as FrakClient;
116
99
 
117
- await expect(getProductInformation(mockClient)).rejects.toThrow(
100
+ await expect(getMerchantInformation(mockClient)).rejects.toThrow(
118
101
  "RPC request failed"
119
102
  );
120
103
  });
@@ -125,7 +108,7 @@ describe("getProductInformation", () => {
125
108
  request: vi.fn().mockRejectedValue(error),
126
109
  } as unknown as FrakClient;
127
110
 
128
- await expect(getProductInformation(mockClient)).rejects.toThrow(
111
+ await expect(getMerchantInformation(mockClient)).rejects.toThrow(
129
112
  "Request timeout"
130
113
  );
131
114
  });
@@ -0,0 +1,16 @@
1
+ import type { FrakClient, GetMerchantInformationReturnType } from "../types";
2
+
3
+ /**
4
+ * Fetch the current merchant information (name, rewards, tiers) from the wallet iframe
5
+ * @param client - The current Frak Client
6
+ * @returns The merchant information including available reward tiers
7
+ *
8
+ * @see {@link @frak-labs/core-sdk!index.GetMerchantInformationReturnType | `GetMerchantInformationReturnType`} for the return type shape
9
+ */
10
+ export async function getMerchantInformation(
11
+ client: FrakClient
12
+ ): Promise<GetMerchantInformationReturnType> {
13
+ return await client.request({
14
+ method: "frak_getMerchantInformation",
15
+ });
16
+ }
@@ -1,6 +1,7 @@
1
1
  export { displayEmbeddedWallet } from "./displayEmbeddedWallet";
2
2
  export { displayModal } from "./displayModal";
3
- export { getProductInformation } from "./getProductInformation";
3
+ export { ensureIdentity } from "./ensureIdentity";
4
+ export { getMerchantInformation } from "./getMerchantInformation";
4
5
  export { openSso } from "./openSso";
5
6
  export { prepareSso } from "./prepareSso";
6
7
  export {
@@ -13,6 +14,7 @@ export { sendInteraction } from "./sendInteraction";
13
14
  // Helper to track the purchase status
14
15
  export { trackPurchaseStatus } from "./trackPurchaseStatus";
15
16
  export { watchWalletStatus } from "./watchWalletStatus";
17
+ // Modal wrappers
16
18
  export {
17
19
  type ModalBuilder,
18
20
  type ModalStepBuilder,
@@ -22,7 +24,6 @@ export {
22
24
  type SendTransactionParams,
23
25
  sendTransaction,
24
26
  } from "./wrapper/sendTransaction";
25
- // Modal wrappers
26
27
  export {
27
28
  type SiweAuthenticateModalParams,
28
29
  siweAuthenticate,
@@ -3,7 +3,8 @@ import type {
3
3
  OpenSsoParamsType,
4
4
  OpenSsoReturnType,
5
5
  } from "../types";
6
- import { computeProductId } from "../utils/computeProductId";
6
+ import { getClientId } from "../utils/clientId";
7
+ import { computeLegacyProductId } from "../utils/computeLegacyProductId";
7
8
  import { generateSsoUrl } from "../utils/sso";
8
9
 
9
10
  // SSO popup configuration
@@ -91,8 +92,9 @@ export async function openSso(
91
92
  generateSsoUrl(
92
93
  walletUrl ?? "https://wallet.frak.id",
93
94
  args,
94
- computeProductId(),
95
+ computeLegacyProductId(),
95
96
  metadata.name,
97
+ getClientId(),
96
98
  customizations?.css
97
99
  );
98
100