@formo/analytics 1.13.0-alpha.1 → 1.13.3-alpha.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 (70) hide show
  1. package/CONTRIBUTING.md +3 -3
  2. package/dist/cjs/src/FormoAnalytics.d.ts +115 -24
  3. package/dist/cjs/src/FormoAnalytics.d.ts.map +1 -1
  4. package/dist/cjs/src/FormoAnalytics.js +442 -65
  5. package/dist/cjs/src/FormoAnalytics.js.map +1 -1
  6. package/dist/cjs/src/constants/config.d.ts +522 -522
  7. package/dist/cjs/src/constants/config.d.ts.map +1 -1
  8. package/dist/cjs/src/constants/config.js +557 -557
  9. package/dist/cjs/src/constants/config.js.map +1 -1
  10. package/dist/cjs/src/constants/events.d.ts +1 -1
  11. package/dist/cjs/src/constants/events.d.ts.map +1 -1
  12. package/dist/cjs/src/constants/events.js +1 -1
  13. package/dist/cjs/src/constants/events.js.map +1 -1
  14. package/dist/cjs/src/types/base.d.ts +1 -1
  15. package/dist/cjs/src/types/base.d.ts.map +1 -1
  16. package/dist/cjs/src/types/events.d.ts +11 -0
  17. package/dist/cjs/src/types/events.d.ts.map +1 -0
  18. package/dist/cjs/src/types/events.js +16 -0
  19. package/dist/cjs/src/types/events.js.map +1 -0
  20. package/dist/cjs/src/types/index.d.ts +2 -1
  21. package/dist/cjs/src/types/index.d.ts.map +1 -1
  22. package/dist/cjs/src/types/index.js +2 -1
  23. package/dist/cjs/src/types/index.js.map +1 -1
  24. package/dist/cjs/src/types/{wallet.d.ts → provider.d.ts} +5 -1
  25. package/dist/cjs/src/types/provider.d.ts.map +1 -0
  26. package/dist/cjs/src/types/{wallet.js → provider.js} +1 -1
  27. package/dist/cjs/src/types/provider.js.map +1 -0
  28. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  29. package/dist/esm/src/FormoAnalytics.d.ts +115 -24
  30. package/dist/esm/src/FormoAnalytics.d.ts.map +1 -1
  31. package/dist/esm/src/FormoAnalytics.js +443 -66
  32. package/dist/esm/src/FormoAnalytics.js.map +1 -1
  33. package/dist/esm/src/constants/config.d.ts +522 -522
  34. package/dist/esm/src/constants/config.d.ts.map +1 -1
  35. package/dist/esm/src/constants/config.js +556 -556
  36. package/dist/esm/src/constants/config.js.map +1 -1
  37. package/dist/esm/src/constants/events.d.ts +1 -1
  38. package/dist/esm/src/constants/events.d.ts.map +1 -1
  39. package/dist/esm/src/constants/events.js +1 -1
  40. package/dist/esm/src/constants/events.js.map +1 -1
  41. package/dist/esm/src/types/base.d.ts +1 -1
  42. package/dist/esm/src/types/base.d.ts.map +1 -1
  43. package/dist/esm/src/types/events.d.ts +11 -0
  44. package/dist/esm/src/types/events.d.ts.map +1 -0
  45. package/dist/esm/src/types/events.js +13 -0
  46. package/dist/esm/src/types/events.js.map +1 -0
  47. package/dist/esm/src/types/index.d.ts +2 -1
  48. package/dist/esm/src/types/index.d.ts.map +1 -1
  49. package/dist/esm/src/types/index.js +2 -1
  50. package/dist/esm/src/types/index.js.map +1 -1
  51. package/dist/esm/src/types/{wallet.d.ts → provider.d.ts} +5 -1
  52. package/dist/esm/src/types/provider.d.ts.map +1 -0
  53. package/dist/esm/src/types/provider.js +2 -0
  54. package/dist/esm/src/types/provider.js.map +1 -0
  55. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  56. package/dist/index.umd.min.js +1 -1
  57. package/dist/index.umd.min.js.map +1 -1
  58. package/package.json +3 -3
  59. package/src/FormoAnalytics.ts +474 -82
  60. package/src/constants/config.ts +556 -556
  61. package/src/constants/events.ts +1 -1
  62. package/src/types/base.ts +1 -1
  63. package/src/types/events.ts +11 -0
  64. package/src/types/index.ts +2 -1
  65. package/src/types/{wallet.ts → provider.ts} +5 -0
  66. package/dist/cjs/src/types/wallet.d.ts.map +0 -1
  67. package/dist/cjs/src/types/wallet.js.map +0 -1
  68. package/dist/esm/src/types/wallet.d.ts.map +0 -1
  69. package/dist/esm/src/types/wallet.js +0 -2
  70. package/dist/esm/src/types/wallet.js.map +0 -1
@@ -45,36 +45,81 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
45
45
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
46
  }
47
47
  };
48
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
49
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
50
+ if (ar || !(i in from)) {
51
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
52
+ ar[i] = from[i];
53
+ }
54
+ }
55
+ return to.concat(ar || Array.prototype.slice.call(from));
56
+ };
48
57
  import axios from "axios";
49
- import { COUNTRY_LIST, EVENTS_API_URL, Event, } from "./constants";
58
+ import { createStore } from 'mipd';
59
+ import { COUNTRY_LIST, CURRENT_URL_KEY, EVENTS_API_URL, Event, } from "./constants";
50
60
  import { H } from "highlight.run";
61
+ import { SignatureStatus, TransactionStatus, } from "./types";
51
62
  var FormoAnalytics = /** @class */ (function () {
52
63
  function FormoAnalytics(apiKey, options) {
53
64
  if (options === void 0) { options = {}; }
54
- var _a;
55
65
  this.apiKey = apiKey;
56
66
  this.options = options;
57
67
  this._providerListeners = {};
58
68
  this.config = {
59
69
  apiKey: apiKey,
60
70
  };
61
- var provider = (window === null || window === void 0 ? void 0 : window.ethereum) || ((_a = window.web3) === null || _a === void 0 ? void 0 : _a.currentProvider) || (options === null || options === void 0 ? void 0 : options.provider);
71
+ // TODO: replace with eip6963
72
+ var provider = options.provider || (window === null || window === void 0 ? void 0 : window.ethereum);
62
73
  if (provider) {
63
74
  this.trackProvider(provider);
64
75
  }
76
+ this.trackFirstPageVisit();
77
+ this.trackPagesChange();
65
78
  }
66
79
  FormoAnalytics.init = function (apiKey, options) {
67
80
  return __awaiter(this, void 0, void 0, function () {
81
+ var analytics, providers;
68
82
  return __generator(this, function (_a) {
69
- // May be needed for delayed loading
70
- // https://github.com/segmentio/analytics-next/tree/master/packages/browser#lazy--delayed-loading
71
- return [2 /*return*/, new FormoAnalytics(apiKey, options)];
83
+ switch (_a.label) {
84
+ case 0:
85
+ analytics = new FormoAnalytics(apiKey, options);
86
+ return [4 /*yield*/, analytics.getProviders()];
87
+ case 1:
88
+ providers = _a.sent();
89
+ return [4 /*yield*/, analytics.identifyAll(providers)];
90
+ case 2:
91
+ _a.sent();
92
+ return [2 /*return*/, analytics];
93
+ }
72
94
  });
73
95
  });
74
96
  };
75
97
  /*
76
98
  Public SDK functions
77
99
  */
100
+ /**
101
+ * Emits a page visit event with the current URL information, fire on page change.
102
+ * @returns {Promise<void>}
103
+ */
104
+ FormoAnalytics.prototype.page = function () {
105
+ return __awaiter(this, void 0, void 0, function () {
106
+ return __generator(this, function (_a) {
107
+ switch (_a.label) {
108
+ case 0: return [4 /*yield*/, this.trackPageHit()];
109
+ case 1:
110
+ _a.sent();
111
+ return [2 /*return*/];
112
+ }
113
+ });
114
+ });
115
+ };
116
+ /**
117
+ * Emits a wallet connect event.
118
+ * @param {ChainID} params.chainId
119
+ * @param {Address} params.address
120
+ * @throws {Error} If chainId or address is empty
121
+ * @returns {Promise<void>}
122
+ */
78
123
  FormoAnalytics.prototype.connect = function (_a) {
79
124
  return __awaiter(this, arguments, void 0, function (_b) {
80
125
  var chainId = _b.chainId, address = _b.address;
@@ -100,6 +145,12 @@ var FormoAnalytics = /** @class */ (function () {
100
145
  });
101
146
  });
102
147
  };
148
+ /**
149
+ * Emits a wallet disconnect event.
150
+ * @param {ChainID} params.chainId
151
+ * @param {Address} params.address
152
+ * @returns {Promise<void>}
153
+ */
103
154
  FormoAnalytics.prototype.disconnect = function (params) {
104
155
  return __awaiter(this, void 0, void 0, function () {
105
156
  var address, chainId;
@@ -116,6 +167,14 @@ var FormoAnalytics = /** @class */ (function () {
116
167
  });
117
168
  });
118
169
  };
170
+ /**
171
+ * Emits a chain network change event.
172
+ * @param {ChainID} params.chainId
173
+ * @param {Address} params.address
174
+ * @throws {Error} If chainId is empty, zero, or not a valid number
175
+ * @throws {Error} If no address is provided and no previous address is recorded
176
+ * @returns {Promise<void>}
177
+ */
119
178
  FormoAnalytics.prototype.chain = function (_a) {
120
179
  return __awaiter(this, arguments, void 0, function (_b) {
121
180
  var chainId = _b.chainId, address = _b.address;
@@ -125,12 +184,12 @@ var FormoAnalytics = /** @class */ (function () {
125
184
  if (!chainId || Number(chainId) === 0) {
126
185
  throw new Error("FormoAnalytics::chain: chainId cannot be empty or 0");
127
186
  }
128
- if (!address && !this.currentConnectedAddress) {
129
- throw new Error("FormoAnalytics::chain: address was empty and no previous address has been recorded. You can either pass an address or call connect() first");
130
- }
131
187
  if (isNaN(Number(chainId))) {
132
188
  throw new Error("FormoAnalytics::chain: chainId must be a valid decimal number");
133
189
  }
190
+ if (!address && !this.currentConnectedAddress) {
191
+ throw new Error("FormoAnalytics::chain: address was empty and no previous address has been recorded");
192
+ }
134
193
  this.currentChainId = chainId;
135
194
  return [4 /*yield*/, this.trackEvent(Event.CHAIN_CHANGED, {
136
195
  chain_id: chainId,
@@ -143,24 +202,88 @@ var FormoAnalytics = /** @class */ (function () {
143
202
  });
144
203
  });
145
204
  };
146
- // TODO: allow custom url as input
147
- FormoAnalytics.prototype.page = function () {
148
- return __awaiter(this, void 0, void 0, function () {
149
- return __generator(this, function (_a) {
150
- switch (_a.label) {
151
- case 0: return [4 /*yield*/, this.trackPageHit()];
205
+ /**
206
+ * Emits a signature event.
207
+ * @param {SignatureStatus} params.status - requested, confirmed, rejected
208
+ * @param {ChainID} params.chainId
209
+ * @param {Address} params.address
210
+ * @param {string} params.message
211
+ * @param {string} params.signatureHash - only provided if status is confirmed
212
+ * @returns {Promise<void>}
213
+ */
214
+ FormoAnalytics.prototype.signature = function (_a) {
215
+ return __awaiter(this, arguments, void 0, function (_b) {
216
+ var status = _b.status, chainId = _b.chainId, address = _b.address, message = _b.message, signatureHash = _b.signatureHash;
217
+ return __generator(this, function (_c) {
218
+ switch (_c.label) {
219
+ case 0: return [4 /*yield*/, this.trackEvent(Event.SIGNATURE, __assign({ status: status, chainId: chainId, address: address, message: message }, (signatureHash && { signatureHash: signatureHash })))];
152
220
  case 1:
153
- _a.sent();
221
+ _c.sent();
222
+ return [2 /*return*/];
223
+ }
224
+ });
225
+ });
226
+ };
227
+ /**
228
+ * Emits a transaction event.
229
+ * @param {TransactionStatus} params.status - started, broadcasted, rejected
230
+ * @param {ChainID} params.chainId
231
+ * @param {Address} params.address
232
+ * @param {string} params.data
233
+ * @param {string} params.to
234
+ * @param {string} params.value
235
+ * @param {string} params.transactionHash - only provided if status is broadcasted
236
+ * @returns {Promise<void>}
237
+ */
238
+ FormoAnalytics.prototype.transaction = function (_a) {
239
+ return __awaiter(this, arguments, void 0, function (_b) {
240
+ var status = _b.status, chainId = _b.chainId, address = _b.address, data = _b.data, to = _b.to, value = _b.value, transactionHash = _b.transactionHash;
241
+ return __generator(this, function (_c) {
242
+ switch (_c.label) {
243
+ case 0: return [4 /*yield*/, this.trackEvent(Event.TRANSACTION, __assign({ status: status, chainId: chainId, address: address, data: data, to: to, value: value }, (transactionHash && { transactionHash: transactionHash })))];
244
+ case 1:
245
+ _c.sent();
154
246
  return [2 /*return*/];
155
247
  }
156
248
  });
157
249
  });
158
250
  };
159
- FormoAnalytics.prototype.track = function (eventName, eventData) {
251
+ /**
252
+ * Emits a identify event with current wallet address.
253
+ * @param {Address} params.address
254
+ * @returns {Promise<void>}
255
+ */
256
+ FormoAnalytics.prototype.identify = function (_a) {
257
+ return __awaiter(this, arguments, void 0, function (_b) {
258
+ var address = _b.address, providerName = _b.providerName, rdns = _b.rdns;
259
+ return __generator(this, function (_c) {
260
+ switch (_c.label) {
261
+ case 0:
262
+ if (!address) return [3 /*break*/, 2];
263
+ return [4 /*yield*/, this.trackEvent(Event.IDENTIFY, {
264
+ address: address,
265
+ name: providerName,
266
+ rdns: rdns,
267
+ })];
268
+ case 1:
269
+ _c.sent();
270
+ _c.label = 2;
271
+ case 2: return [2 /*return*/];
272
+ }
273
+ });
274
+ });
275
+ };
276
+ /**
277
+ * Emits a custom event with custom data.
278
+ * @param {string} action
279
+ * @param {Record<string, any>} payload
280
+ * @returns {Promise<void>}
281
+ */
282
+ FormoAnalytics.prototype.track = function (action, payload) {
160
283
  return __awaiter(this, void 0, void 0, function () {
161
284
  return __generator(this, function (_a) {
162
285
  switch (_a.label) {
163
- case 0: return [4 /*yield*/, this.trackEvent(eventName, eventData)];
286
+ case 0: return [4 /*yield*/, this.trackEvent(action, payload)];
164
287
  case 1:
165
288
  _a.sent();
166
289
  return [2 /*return*/];
@@ -179,20 +302,19 @@ var FormoAnalytics = /** @class */ (function () {
179
302
  this.currentChainId = undefined;
180
303
  this.currentConnectedAddress = undefined;
181
304
  if (this._provider) {
182
- var eventNames = Object.keys(this._providerListeners);
183
- for (var _i = 0, eventNames_1 = eventNames; _i < eventNames_1.length; _i++) {
184
- var eventName = eventNames_1[_i];
185
- this._provider.removeListener(eventName, this._providerListeners[eventName]);
186
- delete this._providerListeners[eventName];
305
+ var actions = Object.keys(this._providerListeners);
306
+ for (var _i = 0, actions_1 = actions; _i < actions_1.length; _i++) {
307
+ var action = actions_1[_i];
308
+ this._provider.removeListener(action, this._providerListeners[action]);
309
+ delete this._providerListeners[action];
187
310
  }
188
311
  }
189
- console.log("Tracking new provider:", provider);
190
312
  this._provider = provider;
191
- this.getAddress();
313
+ // Register listeners for web3 provider events
192
314
  this.registerAddressChangedListener();
193
315
  this.registerChainChangedListener();
194
- // TODO: track signing and transactions
195
- // https://linear.app/getformo/issue/P-607/sdk-support-signature-and-transaction-events
316
+ this.registerSignatureListener();
317
+ this.registerTransactionListener();
196
318
  };
197
319
  FormoAnalytics.prototype.registerAddressChangedListener = function () {
198
320
  var _this = this;
@@ -223,6 +345,105 @@ var FormoAnalytics = /** @class */ (function () {
223
345
  (_a = this.provider) === null || _a === void 0 ? void 0 : _a.on("chainChanged", listener);
224
346
  this._providerListeners["chainChanged"] = listener;
225
347
  };
348
+ FormoAnalytics.prototype.registerSignatureListener = function () {
349
+ var _this = this;
350
+ var _a;
351
+ if (!this.provider) {
352
+ console.error("_trackSigning: provider not found");
353
+ return;
354
+ }
355
+ if (((_a = Object.getOwnPropertyDescriptor(this.provider, "request")) === null || _a === void 0 ? void 0 : _a.writable) ===
356
+ false) {
357
+ console.warn("_trackSigning: provider.request is not writable");
358
+ return;
359
+ }
360
+ var request = this.provider.request.bind(this.provider);
361
+ this.provider.request = function (_a) { return __awaiter(_this, [_a], void 0, function (_b) {
362
+ var response, error_1, rpcError;
363
+ var method = _b.method, params = _b.params;
364
+ return __generator(this, function (_c) {
365
+ switch (_c.label) {
366
+ case 0:
367
+ if (!(Array.isArray(params) &&
368
+ ["eth_signTypedData_v4", "personal_sign"].includes(method))) return [3 /*break*/, 4];
369
+ // Emit signature request event
370
+ this.signature(__assign({ status: SignatureStatus.REQUESTED }, this.buildSignatureEventPayload(method, params)));
371
+ _c.label = 1;
372
+ case 1:
373
+ _c.trys.push([1, 3, , 4]);
374
+ return [4 /*yield*/, request({ method: method, params: params })];
375
+ case 2:
376
+ response = (_c.sent());
377
+ if (response) {
378
+ // Emit signature confirmed event
379
+ this.signature(__assign({ status: SignatureStatus.CONFIRMED }, this.buildSignatureEventPayload(method, params, response)));
380
+ }
381
+ return [2 /*return*/, response];
382
+ case 3:
383
+ error_1 = _c.sent();
384
+ rpcError = error_1;
385
+ if (rpcError && (rpcError === null || rpcError === void 0 ? void 0 : rpcError.code) === 4001) {
386
+ // Emit signature rejected event
387
+ this.signature(__assign({ status: SignatureStatus.REJECTED }, this.buildSignatureEventPayload(method, params)));
388
+ }
389
+ throw error_1;
390
+ case 4: return [2 /*return*/, request({ method: method, params: params })];
391
+ }
392
+ });
393
+ }); };
394
+ return;
395
+ };
396
+ FormoAnalytics.prototype.registerTransactionListener = function () {
397
+ var _this = this;
398
+ var _a;
399
+ if (!this.provider) {
400
+ console.error("_trackTransactions: provider not found");
401
+ return;
402
+ }
403
+ if (((_a = Object.getOwnPropertyDescriptor(this.provider, "request")) === null || _a === void 0 ? void 0 : _a.writable) ===
404
+ false) {
405
+ console.warn("_trackTransactions: provider.request is not writable");
406
+ return;
407
+ }
408
+ var request = this.provider.request.bind(this.provider);
409
+ this.provider.request = function (_a) { return __awaiter(_this, [_a], void 0, function (_b) {
410
+ var payload, transactionHash, error_2, rpcError;
411
+ var method = _b.method, params = _b.params;
412
+ return __generator(this, function (_c) {
413
+ switch (_c.label) {
414
+ case 0:
415
+ if (!(Array.isArray(params) &&
416
+ method === "eth_sendTransaction" &&
417
+ params[0])) return [3 /*break*/, 5];
418
+ return [4 /*yield*/, this.buildTransactionEventPayload(params)];
419
+ case 1:
420
+ payload = _c.sent();
421
+ this.transaction(__assign({ status: TransactionStatus.STARTED }, payload));
422
+ _c.label = 2;
423
+ case 2:
424
+ _c.trys.push([2, 4, , 5]);
425
+ return [4 /*yield*/, request({ method: method, params: params })];
426
+ case 3:
427
+ transactionHash = (_c.sent());
428
+ // Track transaction broadcast
429
+ this.transaction(__assign(__assign({ status: TransactionStatus.BROADCASTED }, payload), { transactionHash: transactionHash }));
430
+ return [2 /*return*/];
431
+ case 4:
432
+ error_2 = _c.sent();
433
+ console.log("transaction listener catch");
434
+ console.log(error_2);
435
+ rpcError = error_2;
436
+ if (rpcError && (rpcError === null || rpcError === void 0 ? void 0 : rpcError.code) === 4001) {
437
+ // Emit transaction rejected event
438
+ this.transaction(__assign({ status: TransactionStatus.REJECTED }, payload));
439
+ }
440
+ throw error_2;
441
+ case 5: return [2 /*return*/, request({ method: method, params: params })];
442
+ }
443
+ });
444
+ }); };
445
+ return;
446
+ };
226
447
  FormoAnalytics.prototype.onAddressChanged = function (addresses) {
227
448
  return __awaiter(this, void 0, void 0, function () {
228
449
  return __generator(this, function (_a) {
@@ -310,7 +531,7 @@ var FormoAnalytics = /** @class */ (function () {
310
531
  console.log("FormoAnalytics::onChainChanged: Unable to fetch or store connected address");
311
532
  return [2 /*return*/, Promise.resolve()];
312
533
  }
313
- this.currentConnectedAddress = address[0];
534
+ this.currentConnectedAddress = address;
314
535
  _a.label = 2;
315
536
  case 2:
316
537
  // Proceed only if the address exists
@@ -328,28 +549,83 @@ var FormoAnalytics = /** @class */ (function () {
328
549
  });
329
550
  });
330
551
  };
331
- // TOFIX: support multiple page hit events
552
+ FormoAnalytics.prototype.trackFirstPageVisit = function () {
553
+ return __awaiter(this, void 0, void 0, function () {
554
+ return __generator(this, function (_a) {
555
+ if (sessionStorage.getItem(CURRENT_URL_KEY) === null) {
556
+ sessionStorage.setItem(CURRENT_URL_KEY, window.location.href);
557
+ }
558
+ return [2 /*return*/, this.trackPageHit()];
559
+ });
560
+ });
561
+ };
562
+ FormoAnalytics.prototype.trackPagesChange = function () {
563
+ return __awaiter(this, void 0, void 0, function () {
564
+ var oldPushState, oldReplaceState;
565
+ var _this = this;
566
+ return __generator(this, function (_a) {
567
+ oldPushState = history.pushState;
568
+ history.pushState = function pushState() {
569
+ var args = [];
570
+ for (var _i = 0; _i < arguments.length; _i++) {
571
+ args[_i] = arguments[_i];
572
+ }
573
+ var ret = oldPushState.apply(this, args);
574
+ window.dispatchEvent(new window.Event("locationchange"));
575
+ return ret;
576
+ };
577
+ oldReplaceState = history.replaceState;
578
+ history.replaceState = function replaceState() {
579
+ var args = [];
580
+ for (var _i = 0; _i < arguments.length; _i++) {
581
+ args[_i] = arguments[_i];
582
+ }
583
+ var ret = oldReplaceState.apply(this, args);
584
+ window.dispatchEvent(new window.Event("locationchange"));
585
+ return ret;
586
+ };
587
+ window.addEventListener("popstate", function () { return _this.onLocationChange(); });
588
+ window.addEventListener("locationchange", function () { return _this.onLocationChange(); });
589
+ return [2 /*return*/];
590
+ });
591
+ });
592
+ };
593
+ FormoAnalytics.prototype.onLocationChange = function () {
594
+ return __awaiter(this, void 0, void 0, function () {
595
+ var currentUrl;
596
+ return __generator(this, function (_a) {
597
+ currentUrl = sessionStorage.getItem(CURRENT_URL_KEY);
598
+ if (currentUrl !== window.location.href) {
599
+ sessionStorage.setItem(CURRENT_URL_KEY, window.location.href);
600
+ this.trackPageHit();
601
+ }
602
+ return [2 /*return*/];
603
+ });
604
+ });
605
+ };
332
606
  // TODO: Add event listener and support for SPA and hash-based navigation
333
607
  // https://linear.app/getformo/issue/P-800/sdk-support-spa-and-hash-based-routing
334
608
  FormoAnalytics.prototype.trackPageHit = function () {
335
609
  var _this = this;
336
610
  var pathname = window.location.pathname;
337
611
  var href = window.location.href;
612
+ var hash = window.location.hash;
338
613
  setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
339
614
  return __generator(this, function (_a) {
340
615
  this.trackEvent(Event.PAGE, {
341
616
  pathname: pathname,
342
617
  href: href,
618
+ hash: hash,
343
619
  });
344
620
  return [2 /*return*/];
345
621
  });
346
622
  }); }, 300);
347
623
  };
348
- // TODO: refactor this with event queue and flushing
624
+ // TODO: refactor this with event queue and flushing
349
625
  // https://linear.app/getformo/issue/P-835/sdk-refactor-retries-with-event-queue-and-batching
350
626
  FormoAnalytics.prototype.trackEvent = function (action, payload) {
351
627
  return __awaiter(this, void 0, void 0, function () {
352
- var address, requestData, response, error_1;
628
+ var address, requestData, response, error_3;
353
629
  var _a;
354
630
  return __generator(this, function (_b) {
355
631
  switch (_b.label) {
@@ -378,26 +654,84 @@ var FormoAnalytics = /** @class */ (function () {
378
654
  case 4:
379
655
  response = _b.sent();
380
656
  if (response.status >= 200 && response.status < 300) {
381
- console.log("Event sent successfully:", action);
657
+ console.log("Event sent successfully: ".concat(this.getActionDescriptor(action, payload)));
382
658
  }
383
659
  else {
384
660
  throw new Error("Failed with status: ".concat(response.status));
385
661
  }
386
662
  return [3 /*break*/, 6];
387
663
  case 5:
388
- error_1 = _b.sent();
389
- H.consumeError(error_1, "Request data: ".concat(JSON.stringify(requestData)));
390
- console.error("Event \"".concat(action, "\" failed. Error: ").concat(error_1));
664
+ error_3 = _b.sent();
665
+ H.consumeError(error_3, "Request data: ".concat(JSON.stringify(requestData)));
666
+ console.error("Event \"".concat(action, "\" failed. Error: ").concat(error_3));
391
667
  return [3 /*break*/, 6];
392
668
  case 6: return [2 /*return*/];
393
669
  }
394
670
  });
395
671
  });
396
672
  };
673
+ /*
674
+ Utility functions
675
+ */
676
+ FormoAnalytics.prototype.getProviders = function () {
677
+ return __awaiter(this, void 0, void 0, function () {
678
+ var store, providers;
679
+ return __generator(this, function (_a) {
680
+ store = createStore();
681
+ providers = __spreadArray([], store.getProviders(), true);
682
+ // TODO: consider using store.subscribe to detect changes to providers list
683
+ // store.subscribe(providers => (state.providers = providers))
684
+ // Fallback to injected provider if no providers are found
685
+ if (providers.length === 0) {
686
+ return [2 /*return*/, [window === null || window === void 0 ? void 0 : window.ethereum]];
687
+ }
688
+ return [2 /*return*/, providers];
689
+ });
690
+ });
691
+ };
692
+ FormoAnalytics.prototype.identifyAll = function (providers) {
693
+ return __awaiter(this, void 0, void 0, function () {
694
+ var _i, providers_1, _a, provider, info, accounts, _b, accounts_1, address, err_1;
695
+ return __generator(this, function (_c) {
696
+ switch (_c.label) {
697
+ case 0:
698
+ _i = 0, providers_1 = providers;
699
+ _c.label = 1;
700
+ case 1:
701
+ if (!(_i < providers_1.length)) return [3 /*break*/, 10];
702
+ _a = providers_1[_i], provider = _a.provider, info = _a.info;
703
+ _c.label = 2;
704
+ case 2:
705
+ _c.trys.push([2, 8, , 9]);
706
+ return [4 /*yield*/, this.getAccounts(provider)];
707
+ case 3:
708
+ accounts = _c.sent();
709
+ if (!(accounts && accounts.length > 0)) return [3 /*break*/, 7];
710
+ _b = 0, accounts_1 = accounts;
711
+ _c.label = 4;
712
+ case 4:
713
+ if (!(_b < accounts_1.length)) return [3 /*break*/, 7];
714
+ address = accounts_1[_b];
715
+ return [4 /*yield*/, this.identify({ address: address, providerName: info.name, rdns: info.rdns })];
716
+ case 5:
717
+ _c.sent();
718
+ _c.label = 6;
719
+ case 6:
720
+ _b++;
721
+ return [3 /*break*/, 4];
722
+ case 7: return [3 /*break*/, 9];
723
+ case 8:
724
+ err_1 = _c.sent();
725
+ return [3 /*break*/, 9];
726
+ case 9:
727
+ _i++;
728
+ return [3 /*break*/, 1];
729
+ case 10: return [2 /*return*/];
730
+ }
731
+ });
732
+ });
733
+ };
397
734
  Object.defineProperty(FormoAnalytics.prototype, "provider", {
398
- /*
399
- Utility functions
400
- */
401
735
  get: function () {
402
736
  return this._provider;
403
737
  },
@@ -406,10 +740,12 @@ var FormoAnalytics = /** @class */ (function () {
406
740
  });
407
741
  FormoAnalytics.prototype.getAddress = function () {
408
742
  return __awaiter(this, void 0, void 0, function () {
409
- var accounts, address, err_1;
743
+ var accounts, err_2;
410
744
  return __generator(this, function (_a) {
411
745
  switch (_a.label) {
412
746
  case 0:
747
+ if (this.currentConnectedAddress)
748
+ return [2 /*return*/, this.currentConnectedAddress];
413
749
  if (!this.provider) {
414
750
  console.log("FormoAnalytics::getAddress: the provider is not set");
415
751
  return [2 /*return*/, null];
@@ -421,54 +757,52 @@ var FormoAnalytics = /** @class */ (function () {
421
757
  case 2:
422
758
  accounts = _a.sent();
423
759
  if (accounts && accounts.length > 0) {
424
- address = accounts[0];
760
+ return [2 /*return*/, accounts[0]];
425
761
  // TODO: how to handle multiple addresses? Should we emit a connect event here? Since the user has not manually connected
426
762
  // https://linear.app/getformo/issue/P-691/sdk-detect-multiple-wallets-using-eip6963
427
- this.onAddressConnected(address);
428
- return [2 /*return*/, address];
429
763
  }
430
764
  return [3 /*break*/, 4];
431
765
  case 3:
432
- err_1 = _a.sent();
433
- console.log("Failed to fetch accounts from provider:", err_1);
766
+ err_2 = _a.sent();
767
+ console.log("Failed to fetch accounts from provider:", err_2);
434
768
  return [2 /*return*/, null];
435
769
  case 4: return [2 /*return*/, null];
436
770
  }
437
771
  });
438
772
  });
439
773
  };
440
- FormoAnalytics.prototype.getAccounts = function () {
774
+ FormoAnalytics.prototype.getAccounts = function (provider) {
441
775
  return __awaiter(this, void 0, void 0, function () {
442
- var res, err_2;
443
- var _a;
444
- return __generator(this, function (_b) {
445
- switch (_b.label) {
776
+ var p, res, err_3;
777
+ return __generator(this, function (_a) {
778
+ switch (_a.label) {
446
779
  case 0:
447
- _b.trys.push([0, 2, , 3]);
448
- return [4 /*yield*/, ((_a = this.provider) === null || _a === void 0 ? void 0 : _a.request({
780
+ p = provider || this.provider;
781
+ _a.label = 1;
782
+ case 1:
783
+ _a.trys.push([1, 3, , 4]);
784
+ return [4 /*yield*/, (p === null || p === void 0 ? void 0 : p.request({
449
785
  method: "eth_accounts",
450
786
  }))];
451
- case 1:
452
- res = _b.sent();
453
- if (!res || res.length === 0) {
454
- console.log("FormoAnalytics::getAccounts: unable to get account. eth_accounts returned empty");
787
+ case 2:
788
+ res = _a.sent();
789
+ if (!res || res.length === 0)
455
790
  return [2 /*return*/, null];
456
- }
457
791
  return [2 /*return*/, res];
458
- case 2:
459
- err_2 = _b.sent();
460
- if (err_2.code !== 4001) {
461
- console.log("FormoAnalytics::getAccounts: eth_accounts threw an error", err_2);
792
+ case 3:
793
+ err_3 = _a.sent();
794
+ if (err_3.code !== 4001) {
795
+ console.log("FormoAnalytics::getAccounts: eth_accounts threw an error", err_3);
462
796
  }
463
797
  return [2 /*return*/, null];
464
- case 3: return [2 /*return*/];
798
+ case 4: return [2 /*return*/];
465
799
  }
466
800
  });
467
801
  });
468
802
  };
469
803
  FormoAnalytics.prototype.getCurrentChainId = function () {
470
804
  return __awaiter(this, void 0, void 0, function () {
471
- var chainIdHex, err_3;
805
+ var chainIdHex, err_4;
472
806
  var _a;
473
807
  return __generator(this, function (_b) {
474
808
  switch (_b.label) {
@@ -490,8 +824,8 @@ var FormoAnalytics = /** @class */ (function () {
490
824
  }
491
825
  return [2 /*return*/, parseInt(chainIdHex, 16)];
492
826
  case 3:
493
- err_3 = _b.sent();
494
- console.log("FormoAnalytics::fetchChainId: eth_chainId threw an error", err_3);
827
+ err_4 = _b.sent();
828
+ console.log("FormoAnalytics::fetchChainId: eth_chainId threw an error", err_4);
495
829
  return [2 /*return*/, 0];
496
830
  case 4: return [2 /*return*/];
497
831
  }
@@ -501,11 +835,13 @@ var FormoAnalytics = /** @class */ (function () {
501
835
  FormoAnalytics.prototype.getLocation = function () {
502
836
  try {
503
837
  var timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
504
- return COUNTRY_LIST[timezone];
838
+ if (timezone in COUNTRY_LIST)
839
+ return COUNTRY_LIST[timezone];
840
+ return timezone;
505
841
  }
506
842
  catch (error) {
507
843
  console.error("Error resolving timezone:", error);
508
- return undefined;
844
+ return "";
509
845
  }
510
846
  };
511
847
  FormoAnalytics.prototype.getLanguage = function () {
@@ -540,6 +876,47 @@ var FormoAnalytics = /** @class */ (function () {
540
876
  });
541
877
  });
542
878
  };
879
+ FormoAnalytics.prototype.buildSignatureEventPayload = function (method, params, response) {
880
+ var basePayload = {
881
+ chainId: this.currentChainId,
882
+ address: method === "personal_sign"
883
+ ? params[1]
884
+ : params[0],
885
+ };
886
+ if (method === "personal_sign") {
887
+ var message = Buffer.from(params[0].slice(2), "hex").toString("utf8");
888
+ return __assign(__assign(__assign({}, basePayload), { message: message }), (response ? { signatureHash: response } : {}));
889
+ }
890
+ return __assign(__assign(__assign({}, basePayload), { message: params[1] }), (response ? { signatureHash: response } : {}));
891
+ };
892
+ FormoAnalytics.prototype.buildTransactionEventPayload = function (params) {
893
+ return __awaiter(this, void 0, void 0, function () {
894
+ var _a, data, from, to, value, _b;
895
+ var _c;
896
+ return __generator(this, function (_d) {
897
+ switch (_d.label) {
898
+ case 0:
899
+ _a = params[0], data = _a.data, from = _a.from, to = _a.to, value = _a.value;
900
+ _c = {};
901
+ _b = this.currentChainId;
902
+ if (_b) return [3 /*break*/, 2];
903
+ return [4 /*yield*/, this.getCurrentChainId()];
904
+ case 1:
905
+ _b = (_d.sent());
906
+ _d.label = 2;
907
+ case 2: return [2 /*return*/, (_c.chainId = _b,
908
+ _c.data = data,
909
+ _c.address = from,
910
+ _c.to = to,
911
+ _c.value = value,
912
+ _c)];
913
+ }
914
+ });
915
+ });
916
+ };
917
+ FormoAnalytics.prototype.getActionDescriptor = function (action, payload) {
918
+ return "".concat(action).concat(payload.status ? " ".concat(payload.status) : "");
919
+ };
543
920
  return FormoAnalytics;
544
921
  }());
545
922
  export { FormoAnalytics };