@formo/analytics 1.27.0 → 1.28.0

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 (74) hide show
  1. package/dist/cjs/src/FormoAnalytics.d.ts +69 -12
  2. package/dist/cjs/src/FormoAnalytics.js +273 -147
  3. package/dist/cjs/src/event/EventFactory.d.ts +10 -2
  4. package/dist/cjs/src/event/EventFactory.js +32 -21
  5. package/dist/cjs/src/index.d.ts +4 -0
  6. package/dist/cjs/src/index.js +6 -0
  7. package/dist/cjs/src/privy/index.d.ts +9 -0
  8. package/dist/cjs/src/privy/index.js +12 -0
  9. package/dist/cjs/src/privy/types.d.ts +175 -0
  10. package/dist/cjs/src/privy/types.js +12 -0
  11. package/dist/cjs/src/privy/utils.d.ts +32 -0
  12. package/dist/cjs/src/privy/utils.js +188 -0
  13. package/dist/cjs/src/session/index.js +2 -1
  14. package/dist/cjs/src/solana/SolanaAdapter.d.ts +211 -0
  15. package/dist/cjs/src/solana/SolanaAdapter.js +975 -0
  16. package/dist/cjs/src/solana/SolanaManager.d.ts +24 -0
  17. package/dist/cjs/src/solana/SolanaManager.js +80 -0
  18. package/dist/cjs/src/solana/address.d.ts +72 -0
  19. package/dist/cjs/src/solana/address.js +176 -0
  20. package/dist/cjs/src/solana/index.d.ts +13 -0
  21. package/dist/cjs/src/solana/index.js +32 -0
  22. package/dist/cjs/src/solana/types.d.ts +206 -0
  23. package/dist/cjs/src/solana/types.js +80 -0
  24. package/dist/cjs/src/types/base.d.ts +17 -0
  25. package/dist/cjs/src/types/events.d.ts +4 -3
  26. package/dist/cjs/src/utils/address.d.ts +21 -0
  27. package/dist/cjs/src/utils/address.js +48 -1
  28. package/dist/cjs/src/utils/builderCode.d.ts +30 -0
  29. package/dist/cjs/src/utils/builderCode.js +143 -0
  30. package/dist/cjs/src/utils/index.d.ts +1 -0
  31. package/dist/cjs/src/utils/index.js +1 -0
  32. package/dist/cjs/src/version.d.ts +1 -1
  33. package/dist/cjs/src/version.js +1 -1
  34. package/dist/cjs/src/wagmi/WagmiEventHandler.js +13 -15
  35. package/dist/cjs/src/wagmi/utils.d.ts +5 -0
  36. package/dist/cjs/src/wagmi/utils.js +20 -0
  37. package/dist/esm/src/FormoAnalytics.d.ts +69 -12
  38. package/dist/esm/src/FormoAnalytics.js +274 -148
  39. package/dist/esm/src/event/EventFactory.d.ts +10 -2
  40. package/dist/esm/src/event/EventFactory.js +34 -23
  41. package/dist/esm/src/index.d.ts +4 -0
  42. package/dist/esm/src/index.js +3 -0
  43. package/dist/esm/src/privy/index.d.ts +9 -0
  44. package/dist/esm/src/privy/index.js +8 -0
  45. package/dist/esm/src/privy/types.d.ts +175 -0
  46. package/dist/esm/src/privy/types.js +11 -0
  47. package/dist/esm/src/privy/utils.d.ts +32 -0
  48. package/dist/esm/src/privy/utils.js +185 -0
  49. package/dist/esm/src/session/index.js +2 -1
  50. package/dist/esm/src/solana/SolanaAdapter.d.ts +211 -0
  51. package/dist/esm/src/solana/SolanaAdapter.js +972 -0
  52. package/dist/esm/src/solana/SolanaManager.d.ts +24 -0
  53. package/dist/esm/src/solana/SolanaManager.js +77 -0
  54. package/dist/esm/src/solana/address.d.ts +72 -0
  55. package/dist/esm/src/solana/address.js +167 -0
  56. package/dist/esm/src/solana/index.d.ts +13 -0
  57. package/dist/esm/src/solana/index.js +13 -0
  58. package/dist/esm/src/solana/types.d.ts +206 -0
  59. package/dist/esm/src/solana/types.js +74 -0
  60. package/dist/esm/src/types/base.d.ts +17 -0
  61. package/dist/esm/src/types/events.d.ts +4 -3
  62. package/dist/esm/src/utils/address.d.ts +21 -0
  63. package/dist/esm/src/utils/address.js +45 -0
  64. package/dist/esm/src/utils/builderCode.d.ts +30 -0
  65. package/dist/esm/src/utils/builderCode.js +140 -0
  66. package/dist/esm/src/utils/index.d.ts +1 -0
  67. package/dist/esm/src/utils/index.js +1 -0
  68. package/dist/esm/src/version.d.ts +1 -1
  69. package/dist/esm/src/version.js +1 -1
  70. package/dist/esm/src/wagmi/WagmiEventHandler.js +14 -16
  71. package/dist/esm/src/wagmi/utils.d.ts +5 -0
  72. package/dist/esm/src/wagmi/utils.js +19 -0
  73. package/dist/index.umd.min.js +1 -1
  74. package/package.json +15 -3
@@ -4,6 +4,14 @@ declare class EventFactory implements IEventFactory {
4
4
  private options?;
5
5
  private compiledPathPattern?;
6
6
  constructor(options?: Options);
7
+ /**
8
+ * Validate an address for both EVM and Solana chains.
9
+ * Uses chainId for strict validation when available.
10
+ * @param address The address to validate
11
+ * @param chainId Optional chain ID for strict chain-specific validation
12
+ * @returns The validated address or null if invalid
13
+ */
14
+ private validateEventAddress;
7
15
  private getTimezone;
8
16
  private getLocation;
9
17
  private getLanguage;
@@ -22,12 +30,12 @@ declare class EventFactory implements IEventFactory {
22
30
  private getEnrichedEvent;
23
31
  generatePageEvent(category?: string, name?: string, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
24
32
  generateDetectWalletEvent(providerName: string, rdns: string, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
25
- generateIdentifyEvent(providerName: string, rdns: string, address: Nullable<Address>, userId?: Nullable<string>, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
33
+ generateIdentifyEvent(providerName?: string, rdns?: string, address?: Nullable<Address>, userId?: Nullable<string>, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
26
34
  generateConnectEvent(chainId: ChainID, address: Address, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
27
35
  generateDisconnectEvent(chainId?: ChainID, address?: Address, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
28
36
  generateChainChangedEvent(chainId: ChainID, address: Address, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
29
37
  generateSignatureEvent(status: SignatureStatus, chainId: ChainID, address: Address, message: string, signatureHash?: string, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
30
- generateTransactionEvent(status: TransactionStatus, chainId: ChainID, address: Address, data?: string, to?: string, value?: string, transactionHash?: string, function_name?: string, function_args?: Record<string, unknown>, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
38
+ generateTransactionEvent(status: TransactionStatus, chainId: ChainID, address: Address, data?: string, to?: string, value?: string, transactionHash?: string, function_name?: string, function_args?: Record<string, unknown>, builder_codes?: string, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
31
39
  generateTrackEvent(event: string, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
32
40
  create(event: APIEvent, address?: Address, userId?: string): Promise<IFormoEvent>;
33
41
  }
@@ -198,6 +198,19 @@ var EventFactory = /** @class */ (function () {
198
198
  }
199
199
  }
200
200
  }
201
+ /**
202
+ * Validate an address for both EVM and Solana chains.
203
+ * Uses chainId for strict validation when available.
204
+ * @param address The address to validate
205
+ * @param chainId Optional chain ID for strict chain-specific validation
206
+ * @returns The validated address or null if invalid
207
+ */
208
+ EventFactory.prototype.validateEventAddress = function (address, chainId) {
209
+ if (!address) {
210
+ return null;
211
+ }
212
+ return (0, address_1.validateAddress)(address, chainId) || null;
213
+ };
201
214
  EventFactory.prototype.getTimezone = function () {
202
215
  try {
203
216
  return Intl.DateTimeFormat().resolvedOptions().timeZone;
@@ -280,15 +293,16 @@ var EventFactory = /** @class */ (function () {
280
293
  };
281
294
  EventFactory.prototype.getEnrichedEvent = function (formoEvent, context) {
282
295
  return __awaiter(this, void 0, void 0, function () {
283
- var commonEventData, validAddress, processedEvent;
296
+ var commonEventData, eventChainId, validAddress, processedEvent;
284
297
  var _a;
285
- return __generator(this, function (_b) {
286
- switch (_b.label) {
298
+ var _b;
299
+ return __generator(this, function (_c) {
300
+ switch (_c.label) {
287
301
  case 0:
288
302
  _a = {};
289
303
  return [4 /*yield*/, this.generateContext(context)];
290
304
  case 1:
291
- commonEventData = (_a.context = _b.sent(),
305
+ commonEventData = (_a.context = _c.sent(),
292
306
  _a.original_timestamp = (0, timestamp_1.getCurrentTimeFormatted)(),
293
307
  _a.user_id = formoEvent.user_id,
294
308
  _a.type = formoEvent.type,
@@ -296,13 +310,9 @@ var EventFactory = /** @class */ (function () {
296
310
  _a.version = constants_2.VERSION,
297
311
  _a);
298
312
  commonEventData.anonymous_id = (0, utils_2.generateAnonymousId)(constants_1.LOCAL_ANONYMOUS_ID_KEY);
299
- validAddress = (0, address_1.getValidAddress)(formoEvent.address);
300
- if (validAddress) {
301
- commonEventData.address = (0, utils_1.toChecksumAddress)(validAddress);
302
- }
303
- else {
304
- commonEventData.address = null;
305
- }
313
+ eventChainId = (_b = formoEvent.properties) === null || _b === void 0 ? void 0 : _b.chainId;
314
+ validAddress = this.validateEventAddress(formoEvent.address, eventChainId);
315
+ commonEventData.address = validAddress;
306
316
  processedEvent = (0, mergeDeepRight_1.default)(formoEvent, commonEventData);
307
317
  if (processedEvent.event === undefined) {
308
318
  processedEvent.event = null;
@@ -348,7 +358,7 @@ var EventFactory = /** @class */ (function () {
348
358
  var identifyEvent;
349
359
  return __generator(this, function (_a) {
350
360
  identifyEvent = {
351
- properties: __assign({ providerName: providerName, rdns: rdns }, properties),
361
+ properties: __assign(__assign(__assign({}, (providerName !== undefined && { providerName: providerName })), (rdns !== undefined && { rdns: rdns })), properties),
352
362
  user_id: userId,
353
363
  address: address,
354
364
  type: "identify",
@@ -409,12 +419,12 @@ var EventFactory = /** @class */ (function () {
409
419
  });
410
420
  });
411
421
  };
412
- EventFactory.prototype.generateTransactionEvent = function (status, chainId, address, data, to, value, transactionHash, function_name, function_args, properties, context) {
422
+ EventFactory.prototype.generateTransactionEvent = function (status, chainId, address, data, to, value, transactionHash, function_name, function_args, builder_codes, properties, context) {
413
423
  return __awaiter(this, void 0, void 0, function () {
414
424
  var transactionEvent;
415
425
  return __generator(this, function (_a) {
416
426
  transactionEvent = {
417
- properties: __assign(__assign(__assign(__assign(__assign(__assign(__assign({ status: status, chainId: chainId }, (data && { data: data })), (to && { to: to })), (value && { value: value })), (transactionHash && { transactionHash: transactionHash })), (function_name && { function_name: function_name })), (function_args && { function_args: function_args })), properties),
427
+ properties: __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({ status: status, chainId: chainId }, (data && { data: data })), (to && { to: to })), (value && { value: value })), (transactionHash && { transactionHash: transactionHash })), (function_name && { function_name: function_name })), (function_args && { function_args: function_args })), (builder_codes && { builder_codes: builder_codes })), properties),
418
428
  address: address,
419
429
  type: "transaction",
420
430
  };
@@ -447,7 +457,7 @@ var EventFactory = /** @class */ (function () {
447
457
  // Returns an event with type, context, properties, and common properties
448
458
  EventFactory.prototype.create = function (event, address, userId) {
449
459
  return __awaiter(this, void 0, void 0, function () {
450
- var formoEvent, _a, validAddress;
460
+ var formoEvent, _a, chainId;
451
461
  return __generator(this, function (_b) {
452
462
  switch (_b.label) {
453
463
  case 0:
@@ -493,7 +503,7 @@ var EventFactory = /** @class */ (function () {
493
503
  case 14:
494
504
  formoEvent = _b.sent();
495
505
  return [3 /*break*/, 19];
496
- case 15: return [4 /*yield*/, this.generateTransactionEvent(event.status, event.chainId, event.address, event.data, event.to, event.value, event.transactionHash, event.function_name, event.function_args, event.properties, event.context)];
506
+ case 15: return [4 /*yield*/, this.generateTransactionEvent(event.status, event.chainId, event.address, event.data, event.to, event.value, event.transactionHash, event.function_name, event.function_args, event.builder_codes, event.properties, event.context)];
497
507
  case 16:
498
508
  formoEvent = _b.sent();
499
509
  return [3 /*break*/, 19];
@@ -503,11 +513,12 @@ var EventFactory = /** @class */ (function () {
503
513
  return [3 /*break*/, 19];
504
514
  case 19:
505
515
  // Set address if not already set by the specific event generator
506
- if (formoEvent.address === undefined || formoEvent.address === null) {
507
- validAddress = (0, address_1.getValidAddress)(address);
508
- formoEvent.address = validAddress
509
- ? (0, utils_1.toChecksumAddress)(validAddress)
510
- : null;
516
+ // Uses chainId for strict chain-specific validation
517
+ // Skip backfill for identify events to prevent stale address being used
518
+ if ((formoEvent.address === undefined || formoEvent.address === null) &&
519
+ event.type !== "identify") {
520
+ chainId = 'chainId' in event ? event.chainId : undefined;
521
+ formoEvent.address = this.validateEventAddress(address, chainId);
511
522
  }
512
523
  formoEvent.user_id = userId || null;
513
524
  return [2 /*return*/, formoEvent];
@@ -1,4 +1,8 @@
1
1
  export * from "./FormoAnalyticsProvider";
2
2
  export * from "./FormoAnalytics";
3
3
  export * from "./types";
4
+ export { parsePrivyProperties } from "./privy";
5
+ export type { PrivyUser, PrivyLinkedAccount, PrivyAccountType, PrivyProfileProperties, PrivyWalletInfo } from "./privy";
6
+ export { SolanaManager } from "./solana";
7
+ export type { SolanaOptions, SolanaCluster, ISolanaAdapter, SolanaWalletContext, SolanaPublicKey, SolanaConnection, } from "./solana";
4
8
  //# sourceMappingURL=index.d.ts.map
@@ -14,10 +14,16 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.SolanaManager = exports.parsePrivyProperties = void 0;
17
18
  var initialization_1 = require("./initialization");
18
19
  __exportStar(require("./FormoAnalyticsProvider"), exports);
19
20
  __exportStar(require("./FormoAnalytics"), exports);
20
21
  __exportStar(require("./types"), exports);
22
+ var privy_1 = require("./privy");
23
+ Object.defineProperty(exports, "parsePrivyProperties", { enumerable: true, get: function () { return privy_1.parsePrivyProperties; } });
24
+ // Solana integration exports
25
+ var solana_1 = require("./solana");
26
+ Object.defineProperty(exports, "SolanaManager", { enumerable: true, get: function () { return solana_1.SolanaManager; } });
21
27
  if (typeof window !== "undefined")
22
28
  window.formofy = initialization_1.formofy;
23
29
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Privy integration module
3
+ *
4
+ * Provides utilities for enriching wallet profiles with Privy user data.
5
+ * This module exports the property extraction utility and related types.
6
+ */
7
+ export { parsePrivyProperties } from "./utils";
8
+ export type { PrivyUser, PrivyLinkedAccount, PrivyAccountType, PrivyProfileProperties, PrivyWalletInfo, } from "./types";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ /**
3
+ * Privy integration module
4
+ *
5
+ * Provides utilities for enriching wallet profiles with Privy user data.
6
+ * This module exports the property extraction utility and related types.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.parsePrivyProperties = void 0;
10
+ var utils_1 = require("./utils");
11
+ Object.defineProperty(exports, "parsePrivyProperties", { enumerable: true, get: function () { return utils_1.parsePrivyProperties; } });
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Privy-specific type definitions for user profile enrichment
3
+ *
4
+ * These types provide TypeScript interfaces for Privy user objects
5
+ * from the Privy React SDK (`usePrivy()` hook).
6
+ *
7
+ * Based on the Privy user object structure:
8
+ * https://docs.privy.io/user-management/users/the-user-object
9
+ */
10
+ /**
11
+ * Valid Privy linked account type strings.
12
+ */
13
+ export type PrivyAccountType = "email" | "phone" | "wallet" | "farcaster" | "telegram" | "apple_oauth" | "discord_oauth" | "github_oauth" | "google_oauth" | "instagram_oauth" | "linkedin_oauth" | "spotify_oauth" | "tiktok_oauth" | "twitter_oauth" | "line" | "custom_auth" | "passkey" | "cross_app" | string;
14
+ /**
15
+ * A linked account entry from the Privy user object.
16
+ * Each linked account has a `type` discriminator and type-specific fields.
17
+ */
18
+ export interface PrivyLinkedAccount {
19
+ type: PrivyAccountType;
20
+ address?: string;
21
+ number?: string;
22
+ username?: string;
23
+ name?: string;
24
+ displayName?: string;
25
+ subject?: string;
26
+ email?: string;
27
+ chainType?: string;
28
+ walletClient?: string;
29
+ walletClientType?: string;
30
+ connectorType?: string;
31
+ delegated?: boolean;
32
+ fid?: number;
33
+ ownerAddress?: string;
34
+ bio?: string;
35
+ pfp?: string;
36
+ url?: string;
37
+ signerPublicKey?: string;
38
+ telegramUserId?: string;
39
+ firstName?: string;
40
+ lastName?: string;
41
+ firstVerifiedAt?: number | null;
42
+ latestVerifiedAt?: number | null;
43
+ verifiedAt?: number | null;
44
+ }
45
+ /**
46
+ * Privy user object as returned by the Privy React SDK.
47
+ *
48
+ * Convenience accessors: user.email, user.phone, user.wallet, user.discord,
49
+ * user.twitter, user.farcaster, user.github, user.google, user.linkedin,
50
+ * user.apple, user.instagram, user.spotify, user.tiktok, user.telegram, user.line
51
+ */
52
+ export interface PrivyUser {
53
+ /** Privy user ID in DID format (e.g., "did:privy:cm3np...") */
54
+ id: string;
55
+ /** Account creation timestamp */
56
+ createdAt?: number;
57
+ /** All linked accounts */
58
+ linkedAccounts?: PrivyLinkedAccount[];
59
+ /** Optional custom metadata */
60
+ customMetadata?: Record<string, unknown>;
61
+ email?: {
62
+ address: string;
63
+ };
64
+ phone?: {
65
+ number: string;
66
+ };
67
+ wallet?: {
68
+ address: string;
69
+ chainType?: string;
70
+ walletClient?: string;
71
+ walletClientType?: string;
72
+ connectorType?: string;
73
+ };
74
+ google?: {
75
+ email?: string;
76
+ name?: string;
77
+ subject?: string;
78
+ };
79
+ discord?: {
80
+ username?: string;
81
+ subject?: string;
82
+ email?: string;
83
+ };
84
+ twitter?: {
85
+ username?: string;
86
+ name?: string;
87
+ subject?: string;
88
+ profilePictureUrl?: string;
89
+ };
90
+ farcaster?: {
91
+ fid?: number;
92
+ username?: string;
93
+ displayName?: string;
94
+ ownerAddress?: string;
95
+ bio?: string;
96
+ pfp?: string;
97
+ };
98
+ github?: {
99
+ username?: string;
100
+ name?: string;
101
+ subject?: string;
102
+ };
103
+ linkedin?: {
104
+ email?: string;
105
+ name?: string;
106
+ subject?: string;
107
+ };
108
+ apple?: {
109
+ email?: string;
110
+ subject?: string;
111
+ };
112
+ instagram?: {
113
+ username?: string;
114
+ subject?: string;
115
+ };
116
+ spotify?: {
117
+ email?: string;
118
+ name?: string;
119
+ subject?: string;
120
+ };
121
+ tiktok?: {
122
+ username?: string;
123
+ name?: string;
124
+ subject?: string;
125
+ };
126
+ line?: {
127
+ email?: string;
128
+ name?: string;
129
+ subject?: string;
130
+ };
131
+ telegram?: {
132
+ telegramUserId?: string;
133
+ username?: string;
134
+ firstName?: string;
135
+ lastName?: string;
136
+ };
137
+ /** MFA methods */
138
+ mfaMethods?: Array<string>;
139
+ /** Whether the user has accepted terms */
140
+ hasAcceptedTerms?: boolean;
141
+ /** Whether this is a guest user */
142
+ isGuest?: boolean;
143
+ }
144
+ /**
145
+ * Extracted profile properties from a Privy user.
146
+ * These are the properties that get sent as event properties via `identify()`.
147
+ */
148
+ export interface PrivyProfileProperties {
149
+ privyDid: string;
150
+ privyCreatedAt?: number;
151
+ email?: string;
152
+ apple?: string;
153
+ discord?: string;
154
+ twitter?: string;
155
+ farcaster?: string;
156
+ github?: string;
157
+ google?: string;
158
+ linkedin?: string;
159
+ line?: string;
160
+ spotify?: string;
161
+ telegram?: string;
162
+ tiktok?: string;
163
+ instagram?: string;
164
+ [key: string]: unknown;
165
+ }
166
+ /**
167
+ * Wallet info extracted from Privy linked accounts.
168
+ */
169
+ export interface PrivyWalletInfo {
170
+ address: string;
171
+ walletClient?: string;
172
+ chainType?: string;
173
+ isEmbedded: boolean;
174
+ }
175
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ /**
3
+ * Privy-specific type definitions for user profile enrichment
4
+ *
5
+ * These types provide TypeScript interfaces for Privy user objects
6
+ * from the Privy React SDK (`usePrivy()` hook).
7
+ *
8
+ * Based on the Privy user object structure:
9
+ * https://docs.privy.io/user-management/users/the-user-object
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Utility functions for extracting profile properties from Privy user objects.
3
+ */
4
+ import { PrivyProfileProperties, PrivyUser, PrivyWalletInfo } from "./types";
5
+ /**
6
+ * Extract profile properties and wallet addresses from a Privy user object.
7
+ *
8
+ * Parses the Privy user's linked accounts into a flat properties object
9
+ * (email, social accounts, etc.) and extracts all linked wallet addresses.
10
+ *
11
+ * @param user - The Privy user object from `usePrivy()`
12
+ * @returns An object with `properties` and `wallets`
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import { parsePrivyProperties } from '@formo/analytics';
17
+ *
18
+ * const { user } = usePrivy();
19
+ * if (user) {
20
+ * const { properties, wallets } = parsePrivyProperties(user);
21
+ *
22
+ * for (const wallet of wallets) {
23
+ * formo.identify({ address: wallet.address, userId: user.id }, properties);
24
+ * }
25
+ * }
26
+ * ```
27
+ */
28
+ export declare function parsePrivyProperties(user: PrivyUser): {
29
+ properties: PrivyProfileProperties;
30
+ wallets: PrivyWalletInfo[];
31
+ };
32
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1,188 @@
1
+ "use strict";
2
+ /**
3
+ * Utility functions for extracting profile properties from Privy user objects.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parsePrivyProperties = parsePrivyProperties;
7
+ /**
8
+ * Extract profile properties and wallet addresses from a Privy user object.
9
+ *
10
+ * Parses the Privy user's linked accounts into a flat properties object
11
+ * (email, social accounts, etc.) and extracts all linked wallet addresses.
12
+ *
13
+ * @param user - The Privy user object from `usePrivy()`
14
+ * @returns An object with `properties` and `wallets`
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * import { parsePrivyProperties } from '@formo/analytics';
19
+ *
20
+ * const { user } = usePrivy();
21
+ * if (user) {
22
+ * const { properties, wallets } = parsePrivyProperties(user);
23
+ *
24
+ * for (const wallet of wallets) {
25
+ * formo.identify({ address: wallet.address, userId: user.id }, properties);
26
+ * }
27
+ * }
28
+ * ```
29
+ */
30
+ function parsePrivyProperties(user) {
31
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
32
+ var accounts = user.linkedAccounts || [];
33
+ // Extract profile properties
34
+ var properties = {
35
+ privyDid: user.id,
36
+ privyCreatedAt: user.createdAt,
37
+ };
38
+ // Email
39
+ if ((_a = user.email) === null || _a === void 0 ? void 0 : _a.address) {
40
+ properties.email = user.email.address;
41
+ }
42
+ // Social accounts - extract usernames/identifiers
43
+ if ((_b = user.apple) === null || _b === void 0 ? void 0 : _b.email) {
44
+ properties.apple = user.apple.email;
45
+ }
46
+ if ((_c = user.discord) === null || _c === void 0 ? void 0 : _c.username) {
47
+ properties.discord = user.discord.username;
48
+ }
49
+ if ((_d = user.farcaster) === null || _d === void 0 ? void 0 : _d.username) {
50
+ properties.farcaster = user.farcaster.username;
51
+ }
52
+ if ((_e = user.github) === null || _e === void 0 ? void 0 : _e.username) {
53
+ properties.github = user.github.username;
54
+ }
55
+ if ((_f = user.google) === null || _f === void 0 ? void 0 : _f.email) {
56
+ properties.google = user.google.email;
57
+ }
58
+ if ((_g = user.instagram) === null || _g === void 0 ? void 0 : _g.username) {
59
+ properties.instagram = user.instagram.username;
60
+ }
61
+ if ((_h = user.line) === null || _h === void 0 ? void 0 : _h.email) {
62
+ properties.line = user.line.email;
63
+ }
64
+ if ((_j = user.linkedin) === null || _j === void 0 ? void 0 : _j.email) {
65
+ properties.linkedin = user.linkedin.email;
66
+ }
67
+ if ((_k = user.spotify) === null || _k === void 0 ? void 0 : _k.email) {
68
+ properties.spotify = user.spotify.email;
69
+ }
70
+ if ((_l = user.telegram) === null || _l === void 0 ? void 0 : _l.username) {
71
+ properties.telegram = user.telegram.username;
72
+ }
73
+ if ((_m = user.tiktok) === null || _m === void 0 ? void 0 : _m.username) {
74
+ properties.tiktok = user.tiktok.username;
75
+ }
76
+ if ((_o = user.twitter) === null || _o === void 0 ? void 0 : _o.username) {
77
+ properties.twitter = user.twitter.username;
78
+ }
79
+ // Fallback to linkedAccounts if convenience accessors are not populated
80
+ if (!properties.email) {
81
+ var emailAccount = accounts.find(function (account) { return account.type === "email"; });
82
+ if (emailAccount === null || emailAccount === void 0 ? void 0 : emailAccount.address) {
83
+ properties.email = emailAccount.address;
84
+ }
85
+ }
86
+ if (!properties.apple) {
87
+ var appleAccount = accounts.find(function (a) { return a.type === "apple_oauth"; });
88
+ if (appleAccount === null || appleAccount === void 0 ? void 0 : appleAccount.email) {
89
+ properties.apple = appleAccount.email;
90
+ }
91
+ }
92
+ if (!properties.discord) {
93
+ var discordAccount = accounts.find(function (a) { return a.type === "discord_oauth"; });
94
+ if (discordAccount === null || discordAccount === void 0 ? void 0 : discordAccount.username) {
95
+ properties.discord = discordAccount.username;
96
+ }
97
+ }
98
+ if (!properties.farcaster) {
99
+ var farcasterAccount = accounts.find(function (a) { return a.type === "farcaster"; });
100
+ if (farcasterAccount === null || farcasterAccount === void 0 ? void 0 : farcasterAccount.username) {
101
+ properties.farcaster = farcasterAccount.username;
102
+ }
103
+ else if (farcasterAccount === null || farcasterAccount === void 0 ? void 0 : farcasterAccount.displayName) {
104
+ properties.farcaster = farcasterAccount.displayName;
105
+ }
106
+ }
107
+ if (!properties.github) {
108
+ var githubAccount = accounts.find(function (a) { return a.type === "github_oauth"; });
109
+ if (githubAccount === null || githubAccount === void 0 ? void 0 : githubAccount.username) {
110
+ properties.github = githubAccount.username;
111
+ }
112
+ }
113
+ if (!properties.google) {
114
+ var googleAccount = accounts.find(function (a) { return a.type === "google_oauth"; });
115
+ if (googleAccount === null || googleAccount === void 0 ? void 0 : googleAccount.email) {
116
+ properties.google = googleAccount.email;
117
+ }
118
+ }
119
+ if (!properties.instagram) {
120
+ var instagramAccount = accounts.find(function (a) { return a.type === "instagram_oauth"; });
121
+ if (instagramAccount === null || instagramAccount === void 0 ? void 0 : instagramAccount.username) {
122
+ properties.instagram = instagramAccount.username;
123
+ }
124
+ }
125
+ if (!properties.line) {
126
+ var lineAccount = accounts.find(function (a) { return a.type === "line"; });
127
+ if (lineAccount === null || lineAccount === void 0 ? void 0 : lineAccount.email) {
128
+ properties.line = lineAccount.email;
129
+ }
130
+ }
131
+ if (!properties.linkedin) {
132
+ var linkedinAccount = accounts.find(function (a) { return a.type === "linkedin_oauth"; });
133
+ if (linkedinAccount === null || linkedinAccount === void 0 ? void 0 : linkedinAccount.email) {
134
+ properties.linkedin = linkedinAccount.email;
135
+ }
136
+ }
137
+ if (!properties.spotify) {
138
+ var spotifyAccount = accounts.find(function (a) { return a.type === "spotify_oauth"; });
139
+ if (spotifyAccount === null || spotifyAccount === void 0 ? void 0 : spotifyAccount.email) {
140
+ properties.spotify = spotifyAccount.email;
141
+ }
142
+ }
143
+ if (!properties.telegram) {
144
+ var telegramAccount = accounts.find(function (a) { return a.type === "telegram"; });
145
+ if (telegramAccount === null || telegramAccount === void 0 ? void 0 : telegramAccount.username) {
146
+ properties.telegram = telegramAccount.username;
147
+ }
148
+ else if (telegramAccount === null || telegramAccount === void 0 ? void 0 : telegramAccount.telegramUserId) {
149
+ properties.telegram = telegramAccount.telegramUserId;
150
+ }
151
+ }
152
+ if (!properties.tiktok) {
153
+ var tiktokAccount = accounts.find(function (a) { return a.type === "tiktok_oauth"; });
154
+ if (tiktokAccount === null || tiktokAccount === void 0 ? void 0 : tiktokAccount.username) {
155
+ properties.tiktok = tiktokAccount.username;
156
+ }
157
+ }
158
+ if (!properties.twitter) {
159
+ var twitterAccount = accounts.find(function (a) { return a.type === "twitter_oauth"; });
160
+ if (twitterAccount === null || twitterAccount === void 0 ? void 0 : twitterAccount.username) {
161
+ properties.twitter = twitterAccount.username;
162
+ }
163
+ }
164
+ // Use OAuth emails as fallback for email if still blank
165
+ // Priority: email -> google -> apple -> linkedin
166
+ if (!properties.email) {
167
+ if (properties.google) {
168
+ properties.email = properties.google;
169
+ }
170
+ else if (properties.apple) {
171
+ properties.email = properties.apple;
172
+ }
173
+ else if (properties.linkedin) {
174
+ properties.email = properties.linkedin;
175
+ }
176
+ }
177
+ // Extract wallet addresses
178
+ var wallets = accounts
179
+ .filter(function (a) { return a.type === "wallet" && a.address; })
180
+ .map(function (a) { return ({
181
+ address: a.address,
182
+ walletClient: a.walletClientType || a.walletClient,
183
+ chainType: a.chainType,
184
+ isEmbedded: a.walletClientType === "privy" || a.walletClient === "privy",
185
+ }); });
186
+ return { properties: properties, wallets: wallets };
187
+ }
188
+ //# sourceMappingURL=utils.js.map
@@ -99,7 +99,8 @@ var FormoAnalyticsSession = /** @class */ (function () {
99
99
  var _a;
100
100
  var identifiedKey = this.generateIdentificationKey(address, rdns);
101
101
  var identifiedWallets = ((_a = (0, storage_1.cookie)().get(exports.SESSION_WALLET_IDENTIFIED_KEY)) === null || _a === void 0 ? void 0 : _a.split(",")) || [];
102
- if (!identifiedWallets.includes(identifiedKey)) {
102
+ var alreadyExists = identifiedWallets.includes(identifiedKey);
103
+ if (!alreadyExists) {
103
104
  identifiedWallets.push(identifiedKey);
104
105
  var newValue = identifiedWallets.join(",");
105
106
  (0, storage_1.cookie)().set(exports.SESSION_WALLET_IDENTIFIED_KEY, newValue, {