@formo/analytics 1.37.0 → 1.38.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.
Files changed (42) hide show
  1. package/dist/cjs/src/FormoAnalytics.d.ts +66 -0
  2. package/dist/cjs/src/FormoAnalytics.js +176 -5
  3. package/dist/cjs/src/FormoAnalyticsProvider.d.ts +8 -0
  4. package/dist/cjs/src/FormoAnalyticsProvider.js +42 -32
  5. package/dist/cjs/src/evm/EvmEventTracker.d.ts +38 -10
  6. package/dist/cjs/src/evm/EvmEventTracker.js +182 -0
  7. package/dist/cjs/src/evm/EvmProviderRegistry.js +26 -4
  8. package/dist/cjs/src/evm/EvmRequestTracker.d.ts +40 -10
  9. package/dist/cjs/src/evm/EvmRequestTracker.js +219 -59
  10. package/dist/cjs/src/provider/detection.d.ts +30 -0
  11. package/dist/cjs/src/provider/detection.js +62 -0
  12. package/dist/cjs/src/provider/index.d.ts +1 -1
  13. package/dist/cjs/src/provider/index.js +3 -1
  14. package/dist/cjs/src/types/base.d.ts +23 -0
  15. package/dist/cjs/src/types/provider.d.ts +16 -0
  16. package/dist/cjs/src/types/provider.js +17 -1
  17. package/dist/cjs/src/version.d.ts +1 -1
  18. package/dist/cjs/src/version.js +1 -1
  19. package/dist/cjs/src/wagmi/WagmiEventHandler.d.ts +81 -0
  20. package/dist/cjs/src/wagmi/WagmiEventHandler.js +478 -38
  21. package/dist/esm/src/FormoAnalytics.d.ts +66 -0
  22. package/dist/esm/src/FormoAnalytics.js +176 -5
  23. package/dist/esm/src/FormoAnalyticsProvider.d.ts +8 -0
  24. package/dist/esm/src/FormoAnalyticsProvider.js +40 -31
  25. package/dist/esm/src/evm/EvmEventTracker.d.ts +38 -10
  26. package/dist/esm/src/evm/EvmEventTracker.js +183 -1
  27. package/dist/esm/src/evm/EvmProviderRegistry.js +27 -5
  28. package/dist/esm/src/evm/EvmRequestTracker.d.ts +40 -10
  29. package/dist/esm/src/evm/EvmRequestTracker.js +218 -58
  30. package/dist/esm/src/provider/detection.d.ts +30 -0
  31. package/dist/esm/src/provider/detection.js +60 -0
  32. package/dist/esm/src/provider/index.d.ts +1 -1
  33. package/dist/esm/src/provider/index.js +1 -1
  34. package/dist/esm/src/types/base.d.ts +23 -0
  35. package/dist/esm/src/types/provider.d.ts +16 -0
  36. package/dist/esm/src/types/provider.js +16 -0
  37. package/dist/esm/src/version.d.ts +1 -1
  38. package/dist/esm/src/version.js +1 -1
  39. package/dist/esm/src/wagmi/WagmiEventHandler.d.ts +81 -0
  40. package/dist/esm/src/wagmi/WagmiEventHandler.js +478 -38
  41. package/dist/index.umd.min.js +1 -1
  42. package/package.json +2 -2
@@ -19,6 +19,17 @@ export interface IFormoAnalytics {
19
19
  page(category?: string, name?: string, properties?: IFormoEventProperties, context?: IFormoEventContext, callback?: (...args: unknown[]) => void): Promise<void>;
20
20
  reset(): void;
21
21
  cleanup(): void;
22
+ /**
23
+ * Track a constructed (non-injected) EIP-1193 provider, such as a
24
+ * WalletConnect or Ledger provider the app built itself. Returns true when
25
+ * the provider is tracked, false when refused (wagmi mode, EVM disabled,
26
+ * or not a valid provider).
27
+ */
28
+ registerProvider(provider: EIP1193Provider, info?: {
29
+ name?: string;
30
+ rdns?: string;
31
+ icon?: `data:image/${string}`;
32
+ }): boolean;
22
33
  detect(params: {
23
34
  rdns: string;
24
35
  providerName: string;
@@ -171,6 +182,18 @@ export interface ReferralOptions {
171
182
  * Allows the SDK to hook into Wagmi v2 wallet events instead of wrapping EIP-1193 providers
172
183
  */
173
184
  export interface WagmiOptions {
185
+ /**
186
+ * OPT-IN: fall back to the EIP-1193 request wrapper for wallet calls the
187
+ * wagmi caches cannot see - imperative viem calls
188
+ * (walletClient.sendTransaction, .signMessage, .writeContract, raw
189
+ * request) that create no mutation. The active connector's provider gets
190
+ * the same wrapper the SDK's default mode uses. Off by default: wagmi
191
+ * mode's baseline contract is observing wagmi state and caches without
192
+ * touching the signing transport, and enabling this is an explicit,
193
+ * auditable decision. Hook-driven calls are never double-counted (a
194
+ * pending wagmi mutation stands the wrapper down).
195
+ */
196
+ eip1193Fallback?: boolean;
174
197
  /**
175
198
  * Wagmi config instance from createConfig()
176
199
  * The SDK will subscribe to this config's state changes to track wallet events
@@ -20,6 +20,22 @@ export type WrappedRequestFunction = (<T>(args: RequestArguments) => Promise<T |
20
20
  [WRAPPED_REQUEST_SYMBOL]?: boolean;
21
21
  };
22
22
  export declare const WRAPPED_REQUEST_REF_SYMBOL: unique symbol;
23
+ /**
24
+ * The SDK instance a provider's installed wrapper currently reports to.
25
+ *
26
+ * The wrapper survives an SDK rebuild (nothing restores `provider.request`),
27
+ * and its closure holds the instance that installed it - whose event queue
28
+ * is CLOSED after cleanup. Without this slot, a rebuilt instance saw
29
+ * "already wrapped", reported success, and every request-derived event
30
+ * silently died in the old instance's queue. The slot holds the LIST of
31
+ * instances that registered this provider, in registration order; the
32
+ * wrapper routes each call to the newest one still live. A list rather
33
+ * than a single ref for two reasons: with several live instances (multi
34
+ * write-key pages) a cleanup degrades to newest-live-wins instead of
35
+ * dead-instance-wins, and the list is attached at install time, so
36
+ * rebinding mutates it and works even on a provider frozen AFTER wrapping.
37
+ */
38
+ export declare const WRAPPED_REQUEST_OWNER_SYMBOL: unique symbol;
23
39
  export interface WrappedEIP1193Provider extends EIP1193Provider {
24
40
  [WRAPPED_REQUEST_REF_SYMBOL]?: WrappedRequestFunction;
25
41
  }
@@ -1,3 +1,19 @@
1
1
  export var WRAPPED_REQUEST_SYMBOL = Symbol("formoWrappedRequest");
2
2
  export var WRAPPED_REQUEST_REF_SYMBOL = Symbol("formoWrappedRequestRef");
3
+ /**
4
+ * The SDK instance a provider's installed wrapper currently reports to.
5
+ *
6
+ * The wrapper survives an SDK rebuild (nothing restores `provider.request`),
7
+ * and its closure holds the instance that installed it - whose event queue
8
+ * is CLOSED after cleanup. Without this slot, a rebuilt instance saw
9
+ * "already wrapped", reported success, and every request-derived event
10
+ * silently died in the old instance's queue. The slot holds the LIST of
11
+ * instances that registered this provider, in registration order; the
12
+ * wrapper routes each call to the newest one still live. A list rather
13
+ * than a single ref for two reasons: with several live instances (multi
14
+ * write-key pages) a cleanup degrades to newest-live-wins instead of
15
+ * dead-instance-wins, and the list is attached at install time, so
16
+ * rebinding mutates it and works even on a provider frozen AFTER wrapping.
17
+ */
18
+ export var WRAPPED_REQUEST_OWNER_SYMBOL = Symbol("formoWrappedRequestOwner");
3
19
  //# sourceMappingURL=provider.js.map
@@ -1,2 +1,2 @@
1
- export declare const version = "1.37.0";
1
+ export declare const version = "1.38.1";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1,4 +1,4 @@
1
1
  // This file is auto-generated by scripts/update-version.js during npm version
2
2
  // Do not edit manually - it will be overwritten
3
- export var version = '1.37.0';
3
+ export var version = '1.38.1';
4
4
  //# sourceMappingURL=version.js.map
@@ -204,6 +204,7 @@ export declare class WagmiEventHandler {
204
204
  * already recorded the new address synchronously by the time this runs. The
205
205
  * `lastAddress` check below is what makes the two paths mutually exclusive.
206
206
  */
207
+ private handleActiveAddressChangeEntryKick;
207
208
  private handleActiveAddressChange;
208
209
  /**
209
210
  * Record and emit a chain move for the wallet already being tracked.
@@ -266,6 +267,26 @@ export declare class WagmiEventHandler {
266
267
  /**
267
268
  * Handle signature mutations (signMessage, signTypedData)
268
269
  */
270
+ /**
271
+ * Is a PENDING wagmi mutation already covering this wallet request?
272
+ *
273
+ * The hybrid-capture dedup. TanStack dispatches `pending` BEFORE the
274
+ * mutationFn issues the wallet call (verified against query-core), so a
275
+ * hook-driven request always finds its mutation here and the request
276
+ * wrapper stands down; an imperative viem call never does, and the
277
+ * wrapper captures it. Matching is by mutation type, refined with cheap
278
+ * parameter checks where the shapes allow, and errs toward NOT skipping:
279
+ * a duplicate is visible and diagnosable, a silent loss is neither.
280
+ */
281
+ hasMatchingPendingMutation(method: string, params: unknown[]): boolean;
282
+ /**
283
+ * Wallet attribution for mutation- and query-derived events.
284
+ *
285
+ * Mid-session events (signatures, transactions) fire after the peer
286
+ * lookup has resolved, so a WalletConnect connector names its actual
287
+ * signer here - the first observable consumer of the peer cache.
288
+ */
289
+ private mutationAttribution;
269
290
  private handleSignatureMutation;
270
291
  /**
271
292
  * Handle transaction mutations (sendTransaction, writeContract)
@@ -320,6 +341,66 @@ export declare class WagmiEventHandler {
320
341
  * Get the connector name from Wagmi state
321
342
  */
322
343
  private getConnectorName;
344
+ /**
345
+ * Start resolving the wallet behind a WalletConnect connection.
346
+ *
347
+ * Fire-and-forget on purpose: emission paths are synchronous by design
348
+ * and must never wait (see the connect marker comment). Called at the
349
+ * START of the status/address flows rather than only at read time - the
350
+ * lookup is one microtask for an initialised connector, and the emission
351
+ * sits behind several awaits, so kicking early usually means even the
352
+ * FIRST connect names the real wallet. When the race is lost the event
353
+ * honestly says "WalletConnect" and every later event names the peer.
354
+ */
355
+ /**
356
+ * Install the request wrapper on the active connector's provider.
357
+ *
358
+ * This is what lets wagmi mode capture IMPERATIVE viem calls
359
+ * (walletClient.sendTransaction / .signMessage / .writeContract / raw
360
+ * request), which create no mutation and were silently lost. Hook-driven
361
+ * calls stay owned by the mutation handlers via the pending-mutation
362
+ * dedup. Fire-and-forget per connection; a provider that cannot be
363
+ * produced simply keeps mutation-only capture.
364
+ */
365
+ /**
366
+ * Connections THIS instance has wrapped. Deliberately per-instance, not
367
+ * module-level: a module-level guard let a rebuilt SDK instance skip
368
+ * re-wrapping, so ownership stayed with the torn-down instance and every
369
+ * capture died in its closed queue - and it also stopped a second
370
+ * write-key instance from ever registering. Re-wrapping is safe and
371
+ * cheap: the request tracker rebinds ownership of an intact wrapper.
372
+ */
373
+ /**
374
+ * Latest wrap attempt per connector. Every kick re-resolves
375
+ * getProvider() - a connector can hand out a REPLACEMENT provider after
376
+ * a reconnect, so a once-only guard would leave the new session's
377
+ * provider unwrapped forever. Re-wrapping is idempotent: the request
378
+ * tracker rebinds ownership of an intact wrapper. The epoch lets a slow
379
+ * resolution from a superseded kick (an earlier session, an earlier
380
+ * chain) be discarded instead of overwriting fresher state.
381
+ */
382
+ private wrapEpochs;
383
+ /** Consecutive automatic wrap retries per connector; see below. */
384
+ private wrapRetryCounts;
385
+ /** Pending retry timers, cancelled by cleanup(). */
386
+ private wrapRetryTimers;
387
+ /**
388
+ * Bumped on every observed disconnect. Every wrap attempt captures it
389
+ * at kick time and its resolution stands down on a mismatch, so a
390
+ * disconnect invalidates ALL pending wraps at once - including ones
391
+ * whose getProvider() had not resolved yet, which no per-connector
392
+ * bookkeeping can reach because nothing has been recorded for them.
393
+ */
394
+ private wrapSessionGeneration;
395
+ /** The active connector this instance wrapped, and its provider, for
396
+ * chain updates. Kept as a pair so a chain report is only ever applied
397
+ * to the provider of the connector it describes. Keyed by connector,
398
+ * not by connection record: wagmi REPLACES the connection object on
399
+ * every account or chain update, so record identity is not stable. */
400
+ private fallbackConnector?;
401
+ private fallbackProvider?;
402
+ private wrapActiveConnectorProvider;
403
+ private kickWalletConnectPeerLookup;
323
404
  /**
324
405
  * Clean up all subscriptions
325
406
  */