@frak-labs/core-sdk 0.2.0 → 0.2.1
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/cdn/bundle.js +3 -3
- package/dist/actions.cjs +1 -1
- package/dist/actions.d.cts +2 -2
- package/dist/actions.d.ts +2 -2
- 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-Raks6FXg.d.cts → computeLegacyProductId-CCAZvLa5.d.cts} +45 -46
- package/dist/{computeLegacyProductId-BkyJ4rEY.d.ts → computeLegacyProductId-b5cUWdAm.d.ts} +45 -46
- 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-BCJGchIb.d.cts → openSso-B0g7-807.d.cts} +40 -7
- package/dist/{openSso-DG-_9CED.d.ts → openSso-CMzwvaCa.d.ts} +40 -7
- package/dist/setupClient-BduY6Sym.cjs +13 -0
- package/dist/setupClient-ftmdQ-I8.js +13 -0
- package/dist/siweAuthenticate-BWmI2_TN.cjs +1 -0
- package/dist/{siweAuthenticate-Btem4QHs.d.ts → siweAuthenticate-CVigMOxz.d.cts} +28 -32
- package/dist/{siweAuthenticate-BH7Dn7nZ.d.cts → siweAuthenticate-CnCZ7mok.d.ts} +28 -32
- package/dist/siweAuthenticate-zczqxm0a.js +1 -0
- package/dist/trackEvent-CeLFVzZn.js +1 -0
- package/dist/trackEvent-Ew5r5zfI.cjs +1 -0
- package/package.json +1 -1
- package/src/actions/referral/processReferral.test.ts +109 -125
- package/src/actions/referral/processReferral.ts +134 -180
- package/src/actions/referral/referralInteraction.test.ts +3 -5
- package/src/actions/referral/referralInteraction.ts +2 -7
- package/src/index.ts +3 -0
- package/src/types/context.ts +48 -6
- package/src/types/index.ts +2 -1
- package/src/types/rpc/interaction.ts +5 -0
- package/src/types/tracking.ts +5 -34
- package/src/utils/FrakContext.test.ts +270 -186
- package/src/utils/FrakContext.ts +78 -56
- package/dist/setupClient-CQrMDGyZ.js +0 -13
- package/dist/setupClient-Ccv3XxwL.cjs +0 -13
- package/dist/siweAuthenticate-BJHbtty4.js +0 -1
- package/dist/siweAuthenticate-Cwj3HP0m.cjs +0 -1
- package/dist/trackEvent-M2RLTQ2p.js +0 -1
- package/dist/trackEvent-T_R9ER2S.cjs +0 -1
|
@@ -1,232 +1,186 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type Address, isAddressEqual } from "viem";
|
|
1
|
+
import { isAddressEqual } from "viem";
|
|
3
2
|
import type {
|
|
4
|
-
DisplayEmbeddedWalletParamsType,
|
|
5
3
|
FrakClient,
|
|
6
4
|
FrakContext,
|
|
5
|
+
FrakContextV2,
|
|
7
6
|
WalletStatusReturnType,
|
|
8
7
|
} from "../../types";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
8
|
+
import { isV1Context, isV2Context } from "../../types";
|
|
9
|
+
import { FrakContextManager, getClientId, trackEvent } from "../../utils";
|
|
11
10
|
import { sendInteraction } from "../sendInteraction";
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
|
-
*
|
|
13
|
+
* Options for the referral auto-interaction process.
|
|
14
|
+
*/
|
|
15
|
+
export type ProcessReferralOptions = {
|
|
16
|
+
/**
|
|
17
|
+
* If true, always replace the URL with the current user's referral context
|
|
18
|
+
* so the next visitor gets referred by this user.
|
|
19
|
+
* @defaultValue false
|
|
20
|
+
*/
|
|
21
|
+
alwaysAppendUrl?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Merchant ID for building the current user's referral context.
|
|
24
|
+
* Required when `alwaysAppendUrl` is true and the incoming context is V1.
|
|
25
|
+
* For V2 contexts, the merchantId is already embedded in the context.
|
|
26
|
+
*/
|
|
27
|
+
merchantId?: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The different states of the referral process.
|
|
15
32
|
* @inline
|
|
16
33
|
*/
|
|
17
34
|
type ReferralState =
|
|
18
35
|
| "idle"
|
|
19
36
|
| "processing"
|
|
20
37
|
| "success"
|
|
21
|
-
| "no-wallet"
|
|
22
|
-
| "error"
|
|
23
38
|
| "no-referrer"
|
|
24
39
|
| "self-referral";
|
|
25
40
|
|
|
26
41
|
/**
|
|
27
|
-
*
|
|
28
|
-
|
|
29
|
-
export type ProcessReferralOptions = {
|
|
30
|
-
/**
|
|
31
|
-
* If we want to always append the url with the frak context or not
|
|
32
|
-
* @defaultValue false
|
|
33
|
-
*/
|
|
34
|
-
alwaysAppendUrl?: boolean;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* This function handle all the heavy lifting of the referral interaction process
|
|
39
|
-
* 1. Check if the user has been referred or not (if not, early exit)
|
|
40
|
-
* 2. Then check if the user is logged in or not
|
|
41
|
-
* 2.1 If not logged in, try a soft login, if it fail, display a modal for the user to login
|
|
42
|
-
* 3. Check if that's not a self-referral (if yes, early exit)
|
|
43
|
-
* 4. Track the referral event
|
|
44
|
-
* 5. Update the current url with the right data
|
|
45
|
-
* 6. Return the resulting referral state
|
|
46
|
-
*
|
|
47
|
-
* If any error occurs during the process, the function will catch it and return an error state
|
|
42
|
+
* Track an arrival event if the context version is recognized.
|
|
43
|
+
* Sends both tracking analytics and the arrival interaction RPC.
|
|
48
44
|
*
|
|
49
|
-
* @
|
|
50
|
-
* @param args
|
|
51
|
-
* @param args.walletStatus - The current user wallet status
|
|
52
|
-
* @param args.frakContext - The current frak context
|
|
53
|
-
* @param args.modalConfig - The modal configuration to display if the user is not logged in
|
|
54
|
-
* @param args.options - Some options for the referral interaction
|
|
55
|
-
* @returns A promise with the resulting referral state
|
|
56
|
-
*
|
|
57
|
-
* @see {@link displayModal} for more details about the displayed modal
|
|
58
|
-
* @see {@link @frak-labs/core-sdk!ModalStepTypes} for more details on each modal steps types
|
|
45
|
+
* @returns true if the context was valid and tracked, false otherwise
|
|
59
46
|
*/
|
|
60
|
-
|
|
47
|
+
function trackArrivalIfValid(
|
|
61
48
|
client: FrakClient,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
) {
|
|
74
|
-
// Early exit if we don't have any referral informations
|
|
75
|
-
if (!frakContext?.r) {
|
|
76
|
-
return "no-referrer";
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// If we got a context, log an event
|
|
80
|
-
trackEvent(client, "user_referred_started", {
|
|
81
|
-
properties: {
|
|
82
|
-
referrer: frakContext?.r,
|
|
83
|
-
walletStatus: walletStatus?.key,
|
|
84
|
-
},
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
sendInteraction(client, {
|
|
88
|
-
type: "arrival",
|
|
89
|
-
referrerWallet: frakContext.r,
|
|
90
|
-
landingUrl:
|
|
91
|
-
typeof window !== "undefined" ? window.location.href : undefined,
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// Helper to fetch a fresh wallet status
|
|
95
|
-
let walletRequest = false;
|
|
96
|
-
async function getFreshWalletStatus() {
|
|
97
|
-
if (walletRequest) {
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
walletRequest = true;
|
|
101
|
-
return ensureWalletConnected(client, {
|
|
102
|
-
modalConfig: {
|
|
103
|
-
...modalConfig,
|
|
104
|
-
loggedIn: {
|
|
105
|
-
action: {
|
|
106
|
-
key: "referred",
|
|
107
|
-
},
|
|
108
|
-
},
|
|
49
|
+
frakContext: FrakContext,
|
|
50
|
+
walletStatus?: WalletStatusReturnType
|
|
51
|
+
): boolean {
|
|
52
|
+
const landingUrl =
|
|
53
|
+
typeof window !== "undefined" ? window.location.href : undefined;
|
|
54
|
+
|
|
55
|
+
if (isV2Context(frakContext)) {
|
|
56
|
+
trackEvent(client, "user_referred_started", {
|
|
57
|
+
properties: {
|
|
58
|
+
referrerClientId: frakContext.c,
|
|
59
|
+
walletStatus: walletStatus?.key,
|
|
109
60
|
},
|
|
110
|
-
walletStatus,
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
try {
|
|
115
|
-
// Do the core processing logic
|
|
116
|
-
const { status, currentWallet } = await processReferralLogic({
|
|
117
|
-
initialWalletStatus: walletStatus,
|
|
118
|
-
getFreshWalletStatus,
|
|
119
|
-
// We can enforce this type cause of the condition at the start
|
|
120
|
-
frakContext: frakContext as Pick<FrakContext, "r">,
|
|
121
61
|
});
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
62
|
+
sendInteraction(client, {
|
|
63
|
+
type: "arrival",
|
|
64
|
+
referrerClientId: frakContext.c,
|
|
65
|
+
referrerMerchantId: frakContext.m,
|
|
66
|
+
referralTimestamp: frakContext.t,
|
|
67
|
+
landingUrl,
|
|
127
68
|
});
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
128
71
|
|
|
129
|
-
|
|
130
|
-
trackEvent(client, "
|
|
72
|
+
if (isV1Context(frakContext)) {
|
|
73
|
+
trackEvent(client, "user_referred_started", {
|
|
131
74
|
properties: {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
wallet: currentWallet,
|
|
75
|
+
referrer: frakContext.r,
|
|
76
|
+
walletStatus: walletStatus?.key,
|
|
135
77
|
},
|
|
136
78
|
});
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
// Track the error event
|
|
143
|
-
trackEvent(client, "user_referred_error", {
|
|
144
|
-
properties: {
|
|
145
|
-
referrer: frakContext?.r,
|
|
146
|
-
error:
|
|
147
|
-
error instanceof FrakRpcError
|
|
148
|
-
? `[${error.code}] ${error.name} - ${error.message}`
|
|
149
|
-
: error instanceof Error
|
|
150
|
-
? error.message
|
|
151
|
-
: "undefined",
|
|
152
|
-
},
|
|
79
|
+
sendInteraction(client, {
|
|
80
|
+
type: "arrival",
|
|
81
|
+
referrerWallet: frakContext.r,
|
|
82
|
+
landingUrl,
|
|
153
83
|
});
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
154
86
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
url: window.location?.href,
|
|
158
|
-
context: options?.alwaysAppendUrl
|
|
159
|
-
? { r: walletStatus?.wallet }
|
|
160
|
-
: null,
|
|
161
|
-
});
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
162
89
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Build a V2 context representing the current user for URL replacement.
|
|
92
|
+
* @returns A V2 context, or null if clientId or merchantId is unavailable
|
|
93
|
+
*/
|
|
94
|
+
function buildCurrentUserContext(merchantId: string): FrakContextV2 | null {
|
|
95
|
+
const clientId = getClientId();
|
|
96
|
+
if (!clientId) return null;
|
|
97
|
+
return {
|
|
98
|
+
v: 2,
|
|
99
|
+
c: clientId,
|
|
100
|
+
m: merchantId,
|
|
101
|
+
t: Math.floor(Date.now() / 1000),
|
|
102
|
+
};
|
|
166
103
|
}
|
|
167
104
|
|
|
168
105
|
/**
|
|
169
|
-
*
|
|
106
|
+
* Client-side self-referral preflight check.
|
|
107
|
+
* Prevents unnecessary backend round-trips for obvious self-referrals.
|
|
170
108
|
*/
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
getFreshWalletStatus: () => Promise<Address | undefined>;
|
|
178
|
-
frakContext: Pick<FrakContext, "r">;
|
|
179
|
-
}) {
|
|
180
|
-
// Get the current wallet, without auto displaying the modal
|
|
181
|
-
let currentWallet = initialWalletStatus?.wallet;
|
|
182
|
-
|
|
183
|
-
// If we don't have a current wallet, display the modal to log in
|
|
184
|
-
if (!currentWallet) {
|
|
185
|
-
currentWallet = await getFreshWalletStatus();
|
|
109
|
+
function isSelfReferral(
|
|
110
|
+
frakContext: FrakContext,
|
|
111
|
+
walletStatus?: WalletStatusReturnType
|
|
112
|
+
): boolean {
|
|
113
|
+
if (isV2Context(frakContext)) {
|
|
114
|
+
return getClientId() === frakContext.c;
|
|
186
115
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (currentWallet && isAddressEqual(frakContext.r, currentWallet)) {
|
|
190
|
-
return { status: "self-referral", currentWallet } as const;
|
|
116
|
+
if (isV1Context(frakContext) && walletStatus?.wallet) {
|
|
117
|
+
return isAddressEqual(frakContext.r, walletStatus.wallet);
|
|
191
118
|
}
|
|
192
|
-
|
|
193
|
-
return { status: "success", currentWallet } as const;
|
|
119
|
+
return false;
|
|
194
120
|
}
|
|
195
121
|
|
|
196
122
|
/**
|
|
197
|
-
*
|
|
123
|
+
* Handle the full referral interaction flow:
|
|
124
|
+
*
|
|
125
|
+
* 1. Check if the user has been referred (if not, early exit)
|
|
126
|
+
* 2. Preflight self-referral check (if yes, early exit)
|
|
127
|
+
* 3. Track the arrival event
|
|
128
|
+
* 4. Replace the current URL with the user's own referral context
|
|
129
|
+
* 5. Return the resulting referral state
|
|
130
|
+
*
|
|
131
|
+
* @param client - The current Frak Client
|
|
132
|
+
* @param args
|
|
133
|
+
* @param args.walletStatus - The current user wallet status
|
|
134
|
+
* @param args.frakContext - The referral context parsed from the URL
|
|
135
|
+
* @param args.options - Options for URL replacement and merchant context
|
|
136
|
+
* @returns The referral state
|
|
137
|
+
*
|
|
138
|
+
* @see {@link @frak-labs/core-sdk!ModalStepTypes} for modal step types
|
|
198
139
|
*/
|
|
199
|
-
|
|
140
|
+
export function processReferral(
|
|
200
141
|
client: FrakClient,
|
|
201
142
|
{
|
|
202
|
-
modalConfig,
|
|
203
143
|
walletStatus,
|
|
144
|
+
frakContext,
|
|
145
|
+
options,
|
|
204
146
|
}: {
|
|
205
|
-
modalConfig?: DisplayEmbeddedWalletParamsType;
|
|
206
147
|
walletStatus?: WalletStatusReturnType;
|
|
148
|
+
frakContext?: FrakContext | null;
|
|
149
|
+
options?: ProcessReferralOptions;
|
|
207
150
|
}
|
|
208
|
-
) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const result = await displayEmbeddedWallet(client, modalConfig ?? {});
|
|
212
|
-
return result?.wallet ?? undefined;
|
|
151
|
+
): ReferralState {
|
|
152
|
+
if (!frakContext) {
|
|
153
|
+
return "no-referrer";
|
|
213
154
|
}
|
|
214
155
|
|
|
215
|
-
|
|
216
|
-
|
|
156
|
+
if (isSelfReferral(frakContext, walletStatus)) {
|
|
157
|
+
return "self-referral";
|
|
158
|
+
}
|
|
217
159
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
* @param error
|
|
221
|
-
*/
|
|
222
|
-
function mapErrorToState(error: unknown): ReferralState {
|
|
223
|
-
if (error instanceof FrakRpcError) {
|
|
224
|
-
switch (error.code) {
|
|
225
|
-
case RpcErrorCodes.walletNotConnected:
|
|
226
|
-
return "no-wallet";
|
|
227
|
-
default:
|
|
228
|
-
return "error";
|
|
229
|
-
}
|
|
160
|
+
if (!trackArrivalIfValid(client, frakContext, walletStatus)) {
|
|
161
|
+
return "no-referrer";
|
|
230
162
|
}
|
|
231
|
-
|
|
163
|
+
|
|
164
|
+
// V2 context embeds merchantId; V1 falls back to options
|
|
165
|
+
const contextMerchantId = isV2Context(frakContext)
|
|
166
|
+
? frakContext.m
|
|
167
|
+
: options?.merchantId;
|
|
168
|
+
|
|
169
|
+
const replaceContext =
|
|
170
|
+
options?.alwaysAppendUrl && contextMerchantId
|
|
171
|
+
? buildCurrentUserContext(contextMerchantId)
|
|
172
|
+
: null;
|
|
173
|
+
|
|
174
|
+
FrakContextManager.replaceUrl({
|
|
175
|
+
url: window.location?.href,
|
|
176
|
+
context: replaceContext,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
trackEvent(client, "user_referred_completed", {
|
|
180
|
+
properties: {
|
|
181
|
+
status: "success",
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
return "success";
|
|
232
186
|
}
|
|
@@ -69,7 +69,6 @@ describe("referralInteraction", () => {
|
|
|
69
69
|
|
|
70
70
|
const mockContext = { r: "0xreferrer" as Hex };
|
|
71
71
|
const mockWalletStatus = { wallet: "0x123" as Hex };
|
|
72
|
-
const mockModalConfig = { type: "login" };
|
|
73
72
|
const mockOptions = { alwaysAppendUrl: true };
|
|
74
73
|
|
|
75
74
|
vi.mocked(FrakContextManager.parse).mockReturnValue(mockContext as any);
|
|
@@ -77,14 +76,12 @@ describe("referralInteraction", () => {
|
|
|
77
76
|
vi.mocked(processReferral).mockResolvedValue("success");
|
|
78
77
|
|
|
79
78
|
await referralInteraction(mockClient, {
|
|
80
|
-
modalConfig: mockModalConfig as any,
|
|
81
79
|
options: mockOptions,
|
|
82
80
|
});
|
|
83
81
|
|
|
84
82
|
expect(processReferral).toHaveBeenCalledWith(mockClient, {
|
|
85
83
|
walletStatus: mockWalletStatus,
|
|
86
84
|
frakContext: mockContext,
|
|
87
|
-
modalConfig: mockModalConfig,
|
|
88
85
|
options: mockOptions,
|
|
89
86
|
});
|
|
90
87
|
});
|
|
@@ -110,7 +107,9 @@ describe("referralInteraction", () => {
|
|
|
110
107
|
|
|
111
108
|
vi.mocked(FrakContextManager.parse).mockReturnValue({} as any);
|
|
112
109
|
vi.mocked(watchWalletStatus).mockResolvedValue(null as any);
|
|
113
|
-
vi.mocked(processReferral).
|
|
110
|
+
vi.mocked(processReferral).mockImplementation(() => {
|
|
111
|
+
throw new Error("Test error");
|
|
112
|
+
});
|
|
114
113
|
|
|
115
114
|
const consoleSpy = vi
|
|
116
115
|
.spyOn(console, "warn")
|
|
@@ -139,7 +138,6 @@ describe("referralInteraction", () => {
|
|
|
139
138
|
expect(processReferral).toHaveBeenCalledWith(
|
|
140
139
|
mockClient,
|
|
141
140
|
expect.objectContaining({
|
|
142
|
-
modalConfig: undefined,
|
|
143
141
|
options: undefined,
|
|
144
142
|
})
|
|
145
143
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FrakClient } from "../../types";
|
|
2
2
|
import { FrakContextManager } from "../../utils";
|
|
3
3
|
import { watchWalletStatus } from "../index";
|
|
4
4
|
import {
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
* Function used to handle referral interactions
|
|
11
11
|
* @param client - The current Frak Client
|
|
12
12
|
* @param args
|
|
13
|
-
* @param args.modalConfig - The modal configuration to display if the user is not logged in
|
|
14
13
|
* @param args.options - Some options for the referral interaction
|
|
15
14
|
*
|
|
16
15
|
* @returns A promise with the resulting referral state, or undefined in case of an error
|
|
@@ -18,15 +17,12 @@ import {
|
|
|
18
17
|
* @description This function will automatically handle the referral interaction process
|
|
19
18
|
*
|
|
20
19
|
* @see {@link processReferral} for more details on the automatic referral handling process
|
|
21
|
-
* @see {@link @frak-labs/core-sdk!ModalStepTypes} for more details on each modal steps types
|
|
22
20
|
*/
|
|
23
21
|
export async function referralInteraction(
|
|
24
22
|
client: FrakClient,
|
|
25
23
|
{
|
|
26
|
-
modalConfig,
|
|
27
24
|
options,
|
|
28
25
|
}: {
|
|
29
|
-
modalConfig?: DisplayEmbeddedWalletParamsType;
|
|
30
26
|
options?: ProcessReferralOptions;
|
|
31
27
|
} = {}
|
|
32
28
|
) {
|
|
@@ -39,10 +35,9 @@ export async function referralInteraction(
|
|
|
39
35
|
const currentWalletStatus = await watchWalletStatus(client);
|
|
40
36
|
|
|
41
37
|
try {
|
|
42
|
-
return
|
|
38
|
+
return processReferral(client, {
|
|
43
39
|
walletStatus: currentWalletStatus,
|
|
44
40
|
frakContext,
|
|
45
|
-
modalConfig,
|
|
46
41
|
options,
|
|
47
42
|
});
|
|
48
43
|
} catch (error) {
|
package/src/index.ts
CHANGED
|
@@ -28,6 +28,8 @@ export type {
|
|
|
28
28
|
FrakClient,
|
|
29
29
|
// Utils
|
|
30
30
|
FrakContext,
|
|
31
|
+
FrakContextV1,
|
|
32
|
+
FrakContextV2,
|
|
31
33
|
FrakLifecycleEvent,
|
|
32
34
|
// Config
|
|
33
35
|
FrakWalletSdkConfig,
|
|
@@ -74,6 +76,7 @@ export type {
|
|
|
74
76
|
// Rpc
|
|
75
77
|
WalletStatusReturnType,
|
|
76
78
|
} from "./types";
|
|
79
|
+
export { isV1Context, isV2Context } from "./types";
|
|
77
80
|
// Utils
|
|
78
81
|
export {
|
|
79
82
|
type AppSpecificSsoMetadata,
|
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,8 @@ 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";
|
|
19
20
|
|
|
20
21
|
export type {
|
|
21
22
|
ClientLifecycleEvent,
|
|
@@ -11,7 +11,12 @@ import type { Address } from "viem";
|
|
|
11
11
|
export type SendInteractionParamsType =
|
|
12
12
|
| {
|
|
13
13
|
type: "arrival";
|
|
14
|
+
/** @deprecated V1 legacy — use referrerClientId for v2 */
|
|
14
15
|
referrerWallet?: Address;
|
|
16
|
+
referrerClientId?: string;
|
|
17
|
+
referrerMerchantId?: string;
|
|
18
|
+
/** Epoch seconds timestamp from the referral link creation */
|
|
19
|
+
referralTimestamp?: number;
|
|
15
20
|
landingUrl?: string;
|
|
16
21
|
utmSource?: string;
|
|
17
22
|
utmMedium?: string;
|
package/src/types/tracking.ts
CHANGED
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Types for arrival tracking and referral attribution
|
|
3
|
-
* @category Tracking
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
1
|
import type { Address } from "viem";
|
|
7
2
|
|
|
8
|
-
/**
|
|
9
|
-
* UTM parameters for marketing attribution
|
|
10
|
-
* @category Tracking
|
|
11
|
-
*/
|
|
12
3
|
export type UtmParams = {
|
|
13
4
|
source?: string;
|
|
14
5
|
medium?: string;
|
|
@@ -17,29 +8,17 @@ export type UtmParams = {
|
|
|
17
8
|
content?: string;
|
|
18
9
|
};
|
|
19
10
|
|
|
20
|
-
/**
|
|
21
|
-
* Parameters for tracking an arrival event
|
|
22
|
-
* @category Tracking
|
|
23
|
-
*/
|
|
24
11
|
export type TrackArrivalParams = {
|
|
25
|
-
/**
|
|
26
|
-
* The referrer wallet address (from fCtx URL param)
|
|
27
|
-
*/
|
|
12
|
+
/** @deprecated V1 legacy — use referrerClientId for v2 contexts */
|
|
28
13
|
referrerWallet?: Address;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
14
|
+
referrerClientId?: string;
|
|
15
|
+
referrerMerchantId?: string;
|
|
16
|
+
/** Epoch seconds timestamp from the referral link creation */
|
|
17
|
+
referralTimestamp?: number;
|
|
32
18
|
landingUrl?: string;
|
|
33
|
-
/**
|
|
34
|
-
* UTM parameters for marketing attribution
|
|
35
|
-
*/
|
|
36
19
|
utmParams?: UtmParams;
|
|
37
20
|
};
|
|
38
21
|
|
|
39
|
-
/**
|
|
40
|
-
* Result from tracking an arrival event
|
|
41
|
-
* @category Tracking
|
|
42
|
-
*/
|
|
43
22
|
export type TrackArrivalResult = {
|
|
44
23
|
success: boolean;
|
|
45
24
|
identityGroupId?: string;
|
|
@@ -47,14 +26,6 @@ export type TrackArrivalResult = {
|
|
|
47
26
|
error?: string;
|
|
48
27
|
};
|
|
49
28
|
|
|
50
|
-
/**
|
|
51
|
-
* Internal params passed to the trackArrival action
|
|
52
|
-
* Includes merchantId resolved from config or fetch
|
|
53
|
-
* @internal
|
|
54
|
-
*/
|
|
55
29
|
export type TrackArrivalInternalParams = TrackArrivalParams & {
|
|
56
|
-
/**
|
|
57
|
-
* The merchant ID (UUID from dashboard)
|
|
58
|
-
*/
|
|
59
30
|
merchantId: string;
|
|
60
31
|
};
|