Skip to content

Conversation

yosriady
Copy link
Contributor

@yosriady yosriady commented Sep 16, 2025

Still testing

Design should be modular and easy to install

@yosriady yosriady requested a review from Copilot September 16, 2025 08:13
@yosriady
Copy link
Contributor Author

bugbot run

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a comprehensive Wagmi integration for Formo Analytics, enabling automatic wallet event tracking with minimal setup for Web3 applications. The integration provides multiple approaches including drop-in replacement hooks and a unified provider system to accommodate different developer needs and migration strategies.

Key Changes

  • Unified WagmiFormoProvider that combines Formo Analytics and Wagmi integration in a single provider
  • Drop-in replacement hooks (useSignMessage, useSendTransaction) with identical APIs to Wagmi but automatic event tracking
  • Dynamic Wagmi imports for graceful degradation when Wagmi is not installed

Reviewed Changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
src/integrations/wagmi/index.ts Main entry point exporting provider, hooks, and types for the Wagmi integration
src/integrations/wagmi/drop-in-hooks.ts Drop-in replacement hooks that wrap Wagmi hooks with automatic Formo event tracking
src/integrations/wagmi/WagmiFormoProvider.tsx Unified provider component that combines Formo Analytics with automatic Wagmi detection
src/integrations/index.ts Integration module entry point exporting all available integrations
src/index.ts Updated main entry to include integrations export
package.json Added optional peer dependencies for wagmi and viem
examples/wagmi-enhanced/, examples/wagmi-drop-in/, examples/wagmi-basic/ Complete example applications demonstrating different integration approaches
docs/WAGMI_INTEGRATION.md Comprehensive documentation for the Wagmi integration
README.md Updated main README with Wagmi integration overview

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 23 to 25
type UseSignMessageParameters = any;
type UseSendTransactionParameters = any;

Copy link

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using any types defeats the purpose of TypeScript and makes the code harder to maintain. Consider importing actual types conditionally or creating proper type definitions that match Wagmi's interfaces.

Suggested change
type UseSignMessageParameters = any;
type UseSendTransactionParameters = any;
import type { UseSignMessageParameters as WagmiUseSignMessageParameters, UseSendTransactionParameters as WagmiUseSendTransactionParameters } from "wagmi";
// Fallback types in case wagmi is not installed (for type checking only)
// You may want to refine these to match Wagmi's actual interfaces if needed.
type UseSignMessageParameters = WagmiUseSignMessageParameters;
type UseSendTransactionParameters = WagmiUseSendTransactionParameters;

Copilot uses AI. Check for mistakes.

Comment on lines 23 to 30
type UseSignMessageParameters = any;
type UseSendTransactionParameters = any;

// Dynamic imports for wagmi hooks - these will be undefined if wagmi is not installed
let useWagmiSignMessage: any;
let useWagmiSendTransaction: any;
let useWagmiAccount: any;
let useWagmiChainId: any;
Copy link

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using any types for the imported hooks removes type safety. Consider using proper type annotations or conditional typing to maintain type safety while allowing graceful degradation.

Suggested change
type UseSignMessageParameters = any;
type UseSendTransactionParameters = any;
// Dynamic imports for wagmi hooks - these will be undefined if wagmi is not installed
let useWagmiSignMessage: any;
let useWagmiSendTransaction: any;
let useWagmiAccount: any;
let useWagmiChainId: any;
import type { useSignMessage as UseSignMessageType, useSendTransaction as UseSendTransactionType, useAccount as UseAccountType, useChainId as UseChainIdType } from "wagmi";
type UseSignMessageParameters = Parameters<UseSignMessageType>[0];
type UseSendTransactionParameters = Parameters<UseSendTransactionType>[0];
// Dynamic imports for wagmi hooks - these will be undefined if wagmi is not installed
let useWagmiSignMessage: typeof UseSignMessageType | undefined;
let useWagmiSendTransaction: typeof UseSendTransactionType | undefined;
let useWagmiAccount: typeof UseAccountType | undefined;
let useWagmiChainId: typeof UseChainIdType | undefined;

Copilot uses AI. Check for mistakes.

Comment on lines 32 to 40
try {
const wagmi = require("wagmi");
useWagmiSignMessage = wagmi.useSignMessage;
useWagmiSendTransaction = wagmi.useSendTransaction;
useWagmiAccount = wagmi.useAccount;
useWagmiChainId = wagmi.useChainId;
} catch (error) {
// Wagmi is not installed - hooks will throw helpful errors
}
Copy link

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using require() in a TypeScript/ES6 module is inconsistent with modern module patterns. Consider using dynamic import() with proper error handling instead.

Copilot uses AI. Check for mistakes.

Comment on lines +8 to +11
let useAccount: any;
let useChainId: any;
let useConnectorClient: any;
let useConfig: any;
Copy link

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using any types removes type safety. Consider using proper type annotations or conditional typing to maintain type safety while allowing optional dependencies.

Suggested change
let useAccount: any;
let useChainId: any;
let useConnectorClient: any;
let useConfig: any;
let useAccount: ((...args: any[]) => any) | undefined;
let useChainId: ((...args: any[]) => any) | undefined;
let useConnectorClient: ((...args: any[]) => any) | undefined;
let useConfig: ((...args: any[]) => any) | undefined;

Copilot uses AI. Check for mistakes.

Comment on lines +13 to +21
try {
const wagmi = require("wagmi");
useAccount = wagmi.useAccount;
useChainId = wagmi.useChainId;
useConnectorClient = wagmi.useConnectorClient;
useConfig = wagmi.useConfig;
} catch (error) {
// Wagmi is not installed - will fall back to regular FormoAnalyticsProvider
}
Copy link

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using require() in a TypeScript/ES6 module is inconsistent with modern module patterns. Consider using dynamic import() with proper error handling instead.

Copilot uses AI. Check for mistakes.

});

// Debounce timer
const debounceTimer = useRef<NodeJS.Timeout>();
Copy link

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using NodeJS.Timeout assumes a Node.js environment, but this code may run in browsers. Consider using number type for better cross-platform compatibility, as setTimeout returns number in browsers.

Suggested change
const debounceTimer = useRef<NodeJS.Timeout>();
const debounceTimer = useRef<number | undefined>();

Copilot uses AI. Check for mistakes.

<div className="feature-grid">
<div className="feature-item">
<h4>🎯 Single Provider</h4>
<p>Replaces both FormoAnalyticsProvider + WagmiFormoProvider</p>
Copy link

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is inconsistent with the actual implementation. The enhanced provider is WagmiFormoProvider which replaces FormoAnalyticsProvider + WagmiFormoProvider, but the text suggests it replaces something else. The documentation should be clarified.

Suggested change
<p>Replaces both FormoAnalyticsProvider + WagmiFormoProvider</p>
<p>Replaces the combination of FormoAnalyticsProvider and WagmiFormoProvider</p>

Copilot uses AI. Check for mistakes.

```tsx
// Layout 1: Wagmi outside (recommended)
<WagmiProvider>
<FormoAnalyticsProviderWithWagmi>
Copy link

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The component name FormoAnalyticsProviderWithWagmi used in documentation doesn't match the actual exported component name WagmiFormoProvider. This inconsistency could confuse developers following the examples.

Copilot uses AI. Check for mistakes.


Edit `App.tsx` and replace `"your-formo-write-key"`:
```tsx
<FormoAnalyticsProviderWithWagmi writeKey="your-actual-write-key">
Copy link

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The component name FormoAnalyticsProviderWithWagmi used in documentation doesn't match the actual exported component name WagmiFormoProvider. This inconsistency could confuse developers following the examples.

Copilot uses AI. Check for mistakes.

cursor[bot]

This comment was marked as outdated.

@yosriady yosriady requested a review from Copilot September 17, 2025 14:11
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 23 to 24
type UseSignMessageParameters = any;
type UseSendTransactionParameters = any;
Copy link

Copilot AI Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using any type defeats the purpose of TypeScript type safety. Consider importing proper types from Wagmi or defining more specific interfaces to maintain type safety.

Suggested change
type UseSignMessageParameters = any;
type UseSendTransactionParameters = any;
import type { UseSignMessageParameters, UseSendTransactionParameters } from "wagmi";

Copilot uses AI. Check for mistakes.

<li>✅ <strong>Single Provider</strong> - No need for separate WagmiFormoProvider</li>
<li>✅ <strong>Automatic Detection</strong> - Detects Wagmi context automatically</li>
<li>✅ <strong>Flexible Layout</strong> - Works with Wagmi outside Formo provider</li>
<li>✅ <strong>Zero Config</strong> - Just wrap with FormoAnalyticsProviderWithWagmi</li>
Copy link

Copilot AI Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment mentions 'FormoAnalyticsProviderWithWagmi' but this provider name doesn't match what's actually used in the code (WagmiFormoProvider). This inconsistency could confuse developers.

Suggested change
<li><strong>Zero Config</strong> - Just wrap with FormoAnalyticsProviderWithWagmi</li>
<li><strong>Zero Config</strong> - Just wrap with WagmiFormoProvider</li>

Copilot uses AI. Check for mistakes.

Comment on lines 30 to 34
<FormoAnalyticsProviderWithWagmi>
<WagmiProvider>
<App />
</WagmiProvider>
</FormoAnalyticsProviderWithWagmi>
Copy link

Copilot AI Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

References to 'FormoAnalyticsProviderWithWagmi' throughout the documentation are inconsistent with the actual component name 'WagmiFormoProvider' used in the implementation.

Copilot uses AI. Check for mistakes.


Edit `App.tsx` and replace `"your-formo-write-key"`:
```tsx
<FormoAnalyticsProviderWithWagmi writeKey="your-actual-write-key">
Copy link

Copilot AI Sep 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

References to 'FormoAnalyticsProviderWithWagmi' are inconsistent with the actual component name 'WagmiFormoProvider' used in the implementation.

Copilot uses AI. Check for mistakes.

const formo = useFormo();
const { address } = useWagmiAccount();
const chainId = useWagmiChainId();

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Wagmi Hooks Fail to Detect Installation

The if (!useWagmiX) checks in useSignMessage, useSendTransaction, and useFormoWallet are ineffective. The useWagmiX variables are always assigned a function (either the real Wagmi hook or an error-throwing fallback) in the try-catch block, making them truthy. This means if Wagmi isn't installed, calls to useWagmiAccount() and useWagmiChainId() within these hooks will throw generic errors instead of the intended descriptive "wagmi is not installed" message.

Additional Locations (2)

Fix in Cursor Fix in Web

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 5 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +75 to +81
try {
const wagmi = require("wagmi");
useWagmiSignMessage = wagmi.useSignMessage;
useWagmiSendTransaction = wagmi.useSendTransaction;
useWagmiAccount = wagmi.useAccount;
useWagmiChainId = wagmi.useChainId;
} catch (error) {
Copy link

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using require() in TypeScript modules is not recommended. Consider using dynamic imports with import() which are more TypeScript-friendly and provide better type safety.

Copilot uses AI. Check for mistakes.

Comment on lines +118 to +120
if (!useWagmiSignMessage) {
throw new Error("useSignMessage requires wagmi to be installed. Please install wagmi: npm install wagmi");
}
Copy link

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conditional check !useWagmiSignMessage will always be false after line 76 assignment. The function will be assigned either the wagmi hook or an error-throwing function, never undefined. This check should be removed since the error is already handled in the catch block.

Suggested change
if (!useWagmiSignMessage) {
throw new Error("useSignMessage requires wagmi to be installed. Please install wagmi: npm install wagmi");
}

Copilot uses AI. Check for mistakes.

Comment on lines +225 to +227
if (!useWagmiSendTransaction) {
throw new Error("useSendTransaction requires wagmi to be installed. Please install wagmi: npm install wagmi");
}
Copy link

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conditional check !useWagmiSendTransaction will always be false after line 78 assignment. The function will be assigned either the wagmi hook or an error-throwing function, never undefined. This check should be removed since the error is already handled in the catch block.

Suggested change
if (!useWagmiSendTransaction) {
throw new Error("useSendTransaction requires wagmi to be installed. Please install wagmi: npm install wagmi");
}

Copilot uses AI. Check for mistakes.

Comment on lines +320 to +322
if (!useWagmiAccount) {
throw new Error("useFormoWallet requires wagmi to be installed. Please install wagmi: npm install wagmi");
}
Copy link

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conditional check !useWagmiAccount will always be false after line 79 assignment. The function will be assigned either the wagmi hook or an error-throwing function, never undefined. This check should be removed since the error is already handled in the catch block.

Suggested change
if (!useWagmiAccount) {
throw new Error("useFormoWallet requires wagmi to be installed. Please install wagmi: npm install wagmi");
}

Copilot uses AI. Check for mistakes.

Comment on lines +332 to +333
if (!formo || !address || !chainId) return;

Copy link

Copilot AI Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The early return condition combines multiple unrelated checks. Consider separating these into individual checks with specific error handling or logging for each missing dependency to improve debuggability.

Suggested change
if (!formo || !address || !chainId) return;
if (!formo) {
logger.error("connectWithTracking: Missing Formo Analytics instance (formo is undefined)");
return;
}
if (!address) {
logger.error("connectWithTracking: Missing wallet address (address is undefined)");
return;
}
if (!chainId) {
logger.error("connectWithTracking: Missing chain ID (chainId is undefined)");
return;
}

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant