Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: tx evm #1188

Merged
merged 8 commits into from
Jan 15, 2025
Merged

feat: tx evm #1188

merged 8 commits into from
Jan 15, 2025

Conversation

songwongtp
Copy link
Collaborator

@songwongtp songwongtp commented Jan 13, 2025

Summary by CodeRabbit

Based on the comprehensive pull request summary, here are the updated release notes:

  • New Features

    • Added support for EVM (Ethereum Virtual Machine) transactions.
    • Implemented EVM transaction simulation and fee estimation.
    • Enhanced transaction handling for EVM-based interactions.
    • Introduced new hooks for signing and broadcasting EVM transactions.
    • Added a new component for rendering estimated EVM transaction fees.
  • Improvements

    • Updated dependencies to latest versions.
    • Refined error handling across multiple components.
    • Improved type safety and code consistency.
    • Enhanced JSON-RPC parameter handling for EVM transactions.
  • Bug Fixes

    • Addressed various linting and type-related issues.
    • Streamlined JSON parsing and error management.
  • Chores

    • Reorganized code structure.
    • Updated ESLint configuration for stricter code standards.

Copy link

vercel bot commented Jan 13, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
celatone-frontend-staging ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jan 15, 2025 6:48am
6 Skipped Deployments
Name Status Preview Comments Updated (UTC)
celatone-frontend-main ⬜️ Ignored (Inspect) Visit Preview Jan 15, 2025 6:48am
initia-celatone-frontend ⬜️ Ignored (Inspect) Visit Preview Jan 15, 2025 6:48am
neutron-celatone-frontend ⬜️ Ignored (Inspect) Visit Preview Jan 15, 2025 6:48am
osmosis-celatone-frontend ⬜️ Ignored (Inspect) Visit Preview Jan 15, 2025 6:48am
sei-celatone-frontend ⬜️ Ignored (Inspect) Visit Preview Jan 15, 2025 6:48am
terra-celatone-frontend ⬜️ Ignored (Inspect) Visit Preview Jan 15, 2025 6:48am

Copy link

coderabbitai bot commented Jan 13, 2025

Walkthrough

This pull request introduces comprehensive changes across multiple files, focusing on enhancing EVM (Ethereum Virtual Machine) transaction handling, improving type safety, and refining linting configurations. The modifications span various aspects of the codebase, including transaction simulation, fee estimation, JSON-RPC interactions, and ESLint rule configurations. Key additions include new hooks for EVM transactions, expanded type definitions, and utility functions for EVM-related operations.

Changes

File Change Summary
.eslintrc.json Added and modified ESLint rules, including stricter error handling and code style configurations.
CHANGELOG.md Added new feature entry for EVM transaction request and simulation; reorganized existing entries.
package.json Updated dependency versions, added ethers package.
src/lib/app-provider/hooks/useSignAndBroadcastEvm.ts Introduced new hook for signing and broadcasting EVM transactions.
src/lib/app-provider/tx/evm/requestEvm.ts Introduced new hook for requesting EVM transactions.
src/lib/services/tx/simulateFeeEvm.ts Introduced new hook for simulating EVM transaction fees.
src/lib/services/evm/jsonRpc.ts Added new function for simulating EVM fees and modified existing JSON-RPC functions.
src/lib/utils/evm.ts Added utility functions for EVM-related operations.
src/lib/app-fns/tx/common/postEvm.tsx Introduced new function for posting EVM transactions.
src/lib/components/EstimatedFeeEvmRender.tsx Added new component to render estimated fees for EVM transactions.
Multiple utility files Simplified error handling and type transformations.

Possibly related PRs

Suggested reviewers

  • evilpeach

🐰 In the land of code where the rabbits play,
New hooks and features hop in every day!
With EVM magic and fees to estimate,
Our code's getting better, oh isn't it great?
So let’s celebrate with a joyful cheer,
For every new change, we hold dear! 🎉


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (4)
src/lib/app-provider/hooks/useSignAndBroadcastEvm.ts (1)

6-19: Consider enhancing error handling and input validation.

While the implementation is functional, consider these improvements:

  1. Add input validation for the transaction request
  2. Handle potential errors from requestEthereumTx
  3. Return loading/error states for better UX

Example enhancement:

 export const useSignAndBroadcastEvm = () => {
   const { walletProvider, chainId } = useCurrentChain();
+  const [isLoading, setIsLoading] = useState(false);
+  const [error, setError] = useState<Error | null>(null);
 
   return useCallback(
     async (request: TransactionRequest): Promise<string> => {
+      setIsLoading(true);
+      setError(null);
+      
+      // Validate request
+      if (!request.to) {
+        throw new Error("Transaction must specify 'to' address");
+      }
+      
       try {
         if (walletProvider.type === "initia-widget") {
           const { requestEthereumTx } = walletProvider.context;
           return requestEthereumTx(request, { chainId });
         }
         throw new Error("Unsupported wallet provider");
+      } catch (err) {
+        setError(err instanceof Error ? err : new Error('Unknown error'));
+        throw err;
+      } finally {
+        setIsLoading(false);
       }
     },
     [chainId, walletProvider.context, walletProvider.type]
   );
 };
src/lib/app-provider/hooks/useSimulateFeeEvm.ts (2)

15-16: Remove redundant comment.

The comment "If the user has connected with Initia Widget" is redundant with the if condition below it.

-      // If the user has connected with Initia Widget
       if (walletProvider.type === "initia-widget") {

10-25: Consider enhancing error handling and input validation.

Similar to useSignAndBroadcastEvm, consider adding:

  1. Input validation for the transaction request
  2. Better error handling with specific error types
  3. Loading states for better UX

Example enhancement:

+import { useState } from "react";
 import { useCallback } from "react";
 
 export const useSimulateFeeEvm = () => {
   const { chainId, walletProvider } = useCurrentChain();
+  const [isLoading, setIsLoading] = useState(false);
+  const [error, setError] = useState<Error | null>(null);
 
   return useCallback(
     async (request: TransactionRequest): Promise<Gas<Big>> => {
+      setIsLoading(true);
+      setError(null);
+      
+      // Validate request
+      if (!request.to) {
+        throw new Error("Transaction must specify 'to' address");
+      }
+      
       try {
         if (walletProvider.type === "initia-widget") {
           const { estimateEthereumTx } = walletProvider.context;
           return estimateEthereumTx(request, chainId).then(zGas(zBig).parse);
         }
         throw new Error("Unsupported wallet provider");
+      } catch (err) {
+        const error = err instanceof Error ? err : new Error('Unknown error');
+        setError(error);
+        throw error;
+      } finally {
+        setIsLoading(false);
       }
     },
     [chainId, walletProvider.context, walletProvider.type]
   );
 };
src/lib/services/tx/simulateFeeEvm.ts (1)

19-45: Consider enhancing the query configuration.

The hook implementation follows React Query best practices, but consider these improvements:

  1. Add retry configuration for specific error types.
  2. Configure staleTime to prevent unnecessary refetches.
  3. Add JSDoc documentation for the hook's purpose and usage.

Example implementation:

+/**
+ * Hook to simulate EVM transaction fees.
+ * @param params - Query parameters including the transaction request
+ * @returns Query result containing the simulated gas fees
+ */
 export const useSimulateFeeEvmQuery = ({
   enabled,
   request,
   retry = 2,
   extraQueryKey = [],
   onSuccess,
   onError,
 }: SimulateQueryEvmParams) => {
   const { address } = useCurrentChain();
   const simulateFeeEvm = useSimulateFeeEvm();
 
   return useQuery({
     queryKey: [
       CELATONE_QUERY_KEYS.SIMULATE_FEE_EVM,
       request,
       address,
       ...extraQueryKey,
     ],
     queryFn: () => simulateFeeEvm(request),
     enabled,
-    retry,
+    retry: (failureCount, error) => {
+      // Retry only for network errors
+      if (error instanceof NetworkError) return failureCount < retry;
+      return false;
+    },
     refetchOnReconnect: false,
     refetchOnWindowFocus: false,
+    staleTime: 30 * 1000, // Consider data fresh for 30 seconds
     onSuccess,
     onError,
   });
 };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2c9d9a4 and 2a606d5.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (23)
  • .eslintrc.json (1 hunks)
  • CHANGELOG.md (1 hunks)
  • package.json (3 hunks)
  • src/lib/amplitude/Amplitude.ts (1 hunks)
  • src/lib/app-provider/env.ts (1 hunks)
  • src/lib/app-provider/hooks/useSignAndBroadcastEvm.ts (1 hunks)
  • src/lib/app-provider/hooks/useSimulateFeeEvm.ts (1 hunks)
  • src/lib/components/json-schema/UploadTemplate.tsx (1 hunks)
  • src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx (2 hunks)
  • src/lib/components/json-schema/form/templates/button-templates/icon-buttons/ChakraIconButton.tsx (1 hunks)
  • src/lib/pages/account-details/components/AccountTitle.tsx (1 hunks)
  • src/lib/pages/interact-contract/components/execute-area/schema-execute/index.tsx (1 hunks)
  • src/lib/pages/interact-contract/components/query-area/schema-query/index.tsx (1 hunks)
  • src/lib/pages/publish-module/index.tsx (1 hunks)
  • src/lib/services/tx/simulateFee.ts (3 hunks)
  • src/lib/services/tx/simulateFeeEvm.ts (1 hunks)
  • src/lib/types/contractState.ts (1 hunks)
  • src/lib/types/move/abi.ts (2 hunks)
  • src/lib/utils/abi.ts (2 hunks)
  • src/lib/utils/formatter/token.ts (1 hunks)
  • src/lib/utils/json.ts (1 hunks)
  • src/lib/utils/mergeRefs.ts (1 hunks)
  • src/lib/utils/validate.ts (1 hunks)
✅ Files skipped from review due to trivial changes (5)
  • src/lib/utils/formatter/token.ts
  • src/lib/amplitude/Amplitude.ts
  • src/lib/pages/interact-contract/components/query-area/schema-query/index.tsx
  • src/lib/utils/abi.ts
  • src/lib/components/json-schema/form/templates/button-templates/icon-buttons/ChakraIconButton.tsx
🔇 Additional comments (15)
src/lib/types/contractState.ts (1)

Line range hint 16-20: LGTM! Good schema design.

The exported schema provides proper type validation for contract state with well-structured fields.

src/lib/utils/mergeRefs.ts (1)

13-13: LGTM! Improved type safety.

Good change to use strict equality check (!==) instead of loose equality (!=). This prevents potential type coercion issues.

src/lib/types/move/abi.ts (1)

6-8: LGTM! Well-structured type definitions.

The interfaces are well-defined with clear property types and relationships. The ModuleAbi interface provides a comprehensive structure for module information, while GenericTypeParam and Field interfaces are appropriately used within ExposedFunction and Struct interfaces.

Also applies to: 10-12, 33-38

src/lib/pages/publish-module/index.tsx (1)

11-14: LGTM! Better organization of type definitions.

Moving the PublishCompleteState interface above its usage in DEFAULT_STATE follows TypeScript best practices.

src/lib/services/tx/simulateFeeEvm.ts (1)

10-17: LGTM! Well-structured query parameters interface.

The SimulateQueryEvmParams interface provides a comprehensive set of options for controlling the query behavior.

src/lib/utils/json.ts (1)

33-33: LGTM! Simplified error handling.

Removing the unused error parameter in the catch block follows ESLint best practices without affecting functionality.

src/lib/pages/account-details/components/AccountTitle.tsx (1)

9-11: LGTM! Well-defined interface for Initia username data.

The interface is properly typed and follows TypeScript best practices.

src/lib/services/tx/simulateFee.ts (1)

34-34: LGTM! Improved query key stability.

Using chainId instead of rpcEndpoint in query keys is a better practice as it provides a more stable identifier for caching.

Also applies to: 48-48

src/lib/app-provider/env.ts (1)

6-6: LGTM! The new query key follows conventions.

The addition of SIMULATE_FEE_EVM is well-placed in the SIMULATE section and follows the established naming pattern for EVM-related keys.

.eslintrc.json (1)

13-27: Consider the impact of strict ESLint rules.

The new rules will enforce better code quality, but some might be too restrictive:

  1. no-console as error might hinder debugging
  2. no-param-reassign with props: true might be too strict for reducers
  3. eqeqeq as error is good for type safety

Let's check the impact of these rules:

✅ Verification successful

ESLint rules are well-suited for the codebase with minor adjustments

The analysis shows:

  • no-console as error is appropriate since current console usage is intentional and properly handled with eslint-disable comments for error logging
  • no-param-reassign with props: true is suitable as reducer patterns follow best practices
  • eqeqeq as error is good for enforcing type safety

Recommendations:

  • Consider allowing console.error by modifying the rule: "no-console": ["error", { "allow": ["error"] }]
  • Keep other rules as they currently enforce good practices
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for console usage and parameter reassignment
echo "Checking for console usage..."
rg "console\." -l

echo "Checking for parameter reassignment..."
rg "\b(\w+)\s*=\s*" --type ts --type tsx

Length of output: 783


Script:

#!/bin/bash
# Check console usage context
echo "Console usage context:"
rg "console\." -A 2 -B 2

# Fix parameter reassignment check for TS files
echo -e "\nParameter reassignment in TS files:"
rg "\b(\w+)\s*=\s*" --type ts

# Look for reducer patterns
echo -e "\nReducer patterns:"
rg "reduce\(" -A 3 -B 1

Length of output: 72485


Script:

#!/bin/bash
# Check for reducer patterns and parameter reassignment
echo "Checking reducer patterns and accumulator usage:"
rg "\.reduce\(" -A 5 -B 2

echo -e "\nChecking parameter reassignment in TS/TSX files:"
rg "(\w+)\s*=\s*" --type-add "typescript:*.{ts,tsx}" --type typescript

Length of output: 69311

src/lib/utils/validate.ts (1)

22-24: LGTM! Simplified error handling.

Removing unused error parameters from catch blocks improves code cleanliness while maintaining the same functionality.

package.json (2)

75-77: Verify compatibility with updated @initia packages.

The updates to @initia packages might have breaking changes:

  • @initia/initia.js: 0.2.24 → 0.2.26
  • @initia/react-wallet-widget: ^0.191.0 → 0.193.0

106-106: Verify ethers integration.

The addition of ethers v6.13.5 is appropriate for EVM functionality. However, ensure it's properly integrated with existing code.

Let's check the usage:

✅ Verification successful

ethers integration verified successfully

The ethers v6.13.5 package is properly integrated, being used exclusively for TypeScript type definitions (TransactionRequest) in EVM-related functionality across hooks and services.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check ethers import usage
echo "Checking ethers usage..."
rg "from ['\"]ethers['\"]" --type ts --type tsx

Length of output: 140


Script:

#!/bin/bash
# Comprehensive check for ethers usage
echo "Checking for ethers imports and usage..."
rg "(?i)(?:import.*from.*['\"]ethers['\"]|require.*['\"]ethers['\"]|import.*['\"]ethers['\"]|from\s+['\"]ethers['\"])"

echo -e "\nChecking for ethers. usage..."
rg "ethers\." -A 2

echo -e "\nChecking for ethers configuration..."
rg "ethers" package.json

Length of output: 736


Script:

#!/bin/bash
# Check implementation of files using TransactionRequest
echo "Checking useSimulateFeeEvm.ts implementation..."
cat src/lib/app-provider/hooks/useSimulateFeeEvm.ts

echo -e "\nChecking useSignAndBroadcastEvm.ts implementation..."
cat src/lib/app-provider/hooks/useSignAndBroadcastEvm.ts

echo -e "\nChecking simulateFeeEvm.ts implementation..."
cat src/lib/services/tx/simulateFeeEvm.ts

Length of output: 3130

src/lib/components/json-schema/form/templates/BaseInputTemplate.tsx (1)

154-154: LGTM! Good improvement in type safety.

The change from == to === for null comparison is a good practice as it prevents potential type coercion issues and makes the code more predictable.

CHANGELOG.md (1)

42-42: LGTM! Well-formatted changelog entry.

The new entry follows the changelog guidelines with proper PR reference and clear description.

Comment on lines +74 to 76
} catch {
//
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling in catch block.

Empty catch blocks are an anti-pattern as they silently swallow errors, making debugging difficult. Consider logging the error or showing a user-friendly message.

Apply this diff to improve error handling:

-      } catch {
-        //
+      } catch (error) {
+        console.error('Failed to parse initial message:', error);
+        // Optionally show a user-friendly message
       }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch {
//
}
} catch (error) {
console.error('Failed to parse initial message:', error);
// Optionally show a user-friendly message
}

Comment on lines +132 to 134
} catch {
//
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for file reading failures.

Empty catch blocks hide file reading errors from users, providing no feedback when uploads fail. Consider showing an error message to help users understand and resolve the issue.

Apply this diff to improve error handling:

-            } catch {
-              //
+            } catch (error) {
+              console.error('Failed to read file:', error);
+              dispatch({
+                type: ActionType.SET_ERROR,
+                method,
+                error: 'Failed to read file. Please try again.',
+              });
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch {
//
}
} catch (error) {
console.error('Failed to read file:', error);
dispatch({
type: ActionType.SET_ERROR,
method,
error: 'Failed to read file. Please try again.',
});
}

export interface InitiaUsernameDataResponse {
username: string | null;
}

Copy link
Collaborator

@Poafs1 Poafs1 Jan 13, 2025

Choose a reason for hiding this comment

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

Nullable<string>

Copy link
Collaborator

@Poafs1 Poafs1 left a comment

Choose a reason for hiding this comment

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

:)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2a606d5 and 2514c1b.

📒 Files selected for processing (6)
  • src/lib/app-provider/hooks/index.ts (1 hunks)
  • src/lib/app-provider/hooks/useSignAndBroadcastEvm.ts (1 hunks)
  • src/lib/app-provider/hooks/useSimulateFeeEvm.ts (1 hunks)
  • src/lib/pages/account-details/components/AccountTitle.tsx (1 hunks)
  • src/lib/services/tx/simulateFeeEvm.ts (1 hunks)
  • src/lib/types/big.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/services/tx/simulateFeeEvm.ts
🔇 Additional comments (4)
src/lib/types/big.ts (1)

8-8: LGTM! Good addition of bigint support.

The addition of z.bigint() with string transformation is a good practice for handling EVM transaction values which commonly use bigint. The transformation ensures type safety while maintaining compatibility with Big.js.

src/lib/app-provider/hooks/index.ts (1)

22-24: LGTM! Exports are properly organized.

The new EVM-related hook exports maintain the established pattern and ordering.

src/lib/pages/account-details/components/AccountTitle.tsx (2)

7-7: LGTM! Clean import statement update.

The addition of the Nullable type import is consistent with its usage in the new interface.


9-11: Well-structured interface definition!

The InitiaUsernameDataResponse interface is well-defined and properly integrated with the component's logic. The use of Nullable<string> is handled correctly throughout the component with appropriate null checks.

Comment on lines 18 to 20
} catch {
return "";
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve error handling.

Returning an empty string on error silently masks issues. Consider:

  1. Propagating the error with meaningful context
  2. Logging the error for debugging
  3. Returning a Result/Either type to handle success/failure cases explicitly

Comment on lines 12 to 16
if (walletProvider.type === "initia-widget") {
const { requestEthereumTx } = walletProvider.context;
const result = await requestEthereumTx(request, { chainId });
return result;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add type narrowing for wallet provider context.

The code assumes requestEthereumTx exists on the context without type checking. Consider adding a type guard:

 if (walletProvider.type === "initia-widget") {
+  if (!('requestEthereumTx' in walletProvider.context)) {
+    throw new Error("Wallet provider context missing requestEthereumTx");
+  }
   const { requestEthereumTx } = walletProvider.context;
   const result = await requestEthereumTx(request, { chainId });
   return result;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (walletProvider.type === "initia-widget") {
const { requestEthereumTx } = walletProvider.context;
const result = await requestEthereumTx(request, { chainId });
return result;
}
if (walletProvider.type === "initia-widget") {
if (!('requestEthereumTx' in walletProvider.context)) {
throw new Error("Wallet provider context missing requestEthereumTx");
}
const { requestEthereumTx } = walletProvider.context;
const result = await requestEthereumTx(request, { chainId });
return result;
}

Comment on lines 25 to 27
} catch {
return zGas(zBig).parse(0);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Improve error handling for gas estimation.

Returning 0 for gas on error is dangerous as it could lead to failed transactions. Consider:

  1. Propagating the error with context
  2. Implementing a fallback estimation strategy
  3. Using a Result/Either type to handle success/failure explicitly

src/lib/app-provider/hooks/useSimulateFeeEvm.ts Outdated Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (12)
src/lib/components/table/evm-transactions/EvmTransactionsTable.tsx (1)

54-55: Consider adding type safety for evmDenom.

The evmDenom prop is passed as an optional value (evmParams?.params.feeDenom). Consider adding runtime validation or TypeScript type guards to handle cases where evmDenom might be undefined.

+ const evmDenom = evmParams?.params.feeDenom;
+ if (!evmDenom) {
+   console.warn('EVM denom is not available');
+   return <Loading />;
+ }

Also applies to: 71-72

src/lib/services/types/evm/params.ts (1)

4-14: Add JSDoc comments to document the schema fields.

While the schema is well-structured, adding documentation for each field would improve maintainability and help other developers understand the purpose of each parameter.

Example documentation:

/**
 * Zod schema for EVM parameters
 * @property params.extra_eips - List of additional EIPs to enable
 * @property params.allowed_publishers - List of authorized publishing addresses
 * @property params.allow_custom_erc20 - Flag to enable custom ERC20 tokens
 * @property params.allowed_custom_erc20s - List of allowed custom ERC20 token addresses
 * @property params.fee_denom - Denomination for transaction fees
 */
export const zEvmParams = z
  .object({
    // ... rest of the code
  })
src/lib/app-provider/tx/evm/requestEvm.ts (2)

28-28: Add type narrowing for estimatedFee check.

The current check if (!estimatedFee) could be improved with explicit type narrowing.

-      if (!estimatedFee) return null;
+      if (estimatedFee === undefined) return null;

35-38: Consider adding error tracking.

Success tracking is implemented, but error tracking is missing. Consider adding trackTxFailed for consistency.

         onTxSucceed: () => {
           trackTxSucceed();
           onTxSucceed?.();
         },
-        onTxFailed,
+        onTxFailed: () => {
+          trackTxFailed();
+          onTxFailed?.();
+        },
src/lib/components/EstimatedEvmFeeRender.tsx (3)

8-16: Define explicit interface for component props.

Extract props into a named interface for better maintainability and documentation.

+interface EstimatedEvmFeeRenderProps {
+  effectiveGasPrice: Big;
+  gasUsed: Big;
+  loading: boolean;
+}
+
-export const EstimatedEvmFeeRender = ({
-  effectiveGasPrice,
-  gasUsed,
-  loading,
-}: {
-  effectiveGasPrice: Big;
-  gasUsed: Big;
-  loading: boolean;
-}) => {
+export const EstimatedEvmFeeRender = ({
+  effectiveGasPrice,
+  gasUsed,
+  loading,
+}: EstimatedEvmFeeRenderProps) => {

22-29: Extract loading states into a reusable component.

Consider consolidating the loading indicators into a separate component for better reusability and consistency.

+const LoadingIndicator = ({ text }: { text?: string }) => (
+  <>
+    <Spinner size="sm" mx={1} />
+    {text}
+  </>
+);
+
 if (isAssetInfoLoading || isEvmParamsLoading)
-  return <Spinner size="sm" mx={1} />;
+  return <LoadingIndicator />;
 if (loading)
-  return (
-    <>
-      <Spinner size="sm" mx={1} /> Estimating ...
-    </>
-  );
+  return <LoadingIndicator text="Estimating ..." />;

34-40: Consider wrapping calculations in error boundary.

The fee calculations could potentially throw errors (e.g., from Big.js operations). Consider adding error handling.

+  try {
     const feeAmount = effectiveGasPrice.mul(gasUsed);
     const feeToken = coinToTokenWithValue(
       feeDenom,
       feeAmount.toFixed(),
       assetInfos
     );
     return <>{formatTokenWithValue(feeToken)}</>;
+  } catch (error) {
+    console.error('Error calculating fee:', error);
+    return <>Error calculating fee</>;
+  }
src/lib/app-fns/tx/common/postEvm.tsx (1)

32-32: Address the TODO comment about event/rawlog attribute picker.

The TODO comment suggests missing functionality for event/rawlog attribute selection.

Would you like me to help implement the event/rawlog attribute picker or create a GitHub issue to track this task?

src/lib/app-fns/tx/common/post.tsx (1)

21-23: Consider adding JSDoc documentation.

Adding documentation would help explain the purpose and usage of the generic type parameter.

+/**
+ * Creates a transaction posting function that handles DeliverTxResponse results.
+ * @template T Type extending DeliverTxResponse
+ * @param postFn Function that posts the transaction and returns a Promise<T>
+ * @returns Function that processes and formats the transaction result
+ */
 export const postTx = <T extends DeliverTxResponse>({
   postFn,
 }: PostTxParams<T>) => {
src/lib/services/tx/jsonRpc.ts (1)

88-93: Add input validation and documentation.

The getEthCall function would benefit from input validation and JSDoc documentation.

+/**
+ * Makes an eth_call JSON-RPC request.
+ * @param endpoint The JSON-RPC endpoint URL
+ * @param from The sender address (optional)
+ * @param to The target contract address
+ * @param data The call data
+ * @returns Promise resolving to the call result
+ */
 export const getEthCall = (
   endpoint: string,
   from: Nullable<HexAddr>,
   to: HexAddr,
   data: string
-) => requestJsonRpc(endpoint, "eth_call", [{ from, to, data }, "latest"]);
+) => {
+  if (!endpoint) throw new Error("Endpoint is required");
+  if (!to) throw new Error("Target address is required");
+  if (!data) throw new Error("Call data is required");
+  return requestJsonRpc(endpoint, "eth_call", [{ from, to, data }, "latest"]);
+};
src/lib/app-fns/tx/evm/requestEvm.tsx (1)

24-78: Consider adding transaction timeout handling.

The function effectively handles transaction success and error cases. However, it might benefit from having a timeout mechanism for long-running transactions.

Consider adding a timeout parameter and implementing timeout handling:

 interface RequestEvmTxParams {
   to: HexAddr;
   data: string;
   fee: StdFee;
   signAndBroadcastEvm: SignAndBroadcastEvm;
   onTxSucceed?: () => void;
   onTxFailed?: () => void;
+  timeoutMs?: number;
 }

 export const requestEvmTx = ({
   to,
   data,
   fee,
   signAndBroadcastEvm,
   onTxSucceed,
   onTxFailed,
+  timeoutMs = 30000,
 }: RequestEvmTxParams): Observable<TxResultRendering> => {
   return pipe(
     sendingTx(fee),
     postEvmTx<TxReceiptJsonRpc>({
       postFn: () => signAndBroadcastEvm({ to, data }),
+      timeoutMs,
     }),
src/lib/app-provider/hooks/useSignAndBroadcastEvm.ts (1)

10-50: Consider making timeout values configurable.

The timeout values are hardcoded. Consider making them configurable through parameters or environment variables for flexibility.

+interface EvmTxResponseConfig {
+  timeoutMs?: number;
+  pollIntervalMs?: number;
+}
+
-const getEvmTxResponse = async (jsonRpcEndpoint: string, txHash: string) => {
+const getEvmTxResponse = async (
+  jsonRpcEndpoint: string,
+  txHash: string,
+  config?: EvmTxResponseConfig
+) => {
-  const TIME_OUT_MS = 3000;
-  const POLL_INTERVAL_MS = 1000;
+  const TIME_OUT_MS = config?.timeoutMs ?? 3000;
+  const POLL_INTERVAL_MS = config?.pollIntervalMs ?? 1000;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2514c1b and dc0b0cf.

📒 Files selected for processing (16)
  • src/lib/app-fns/tx/common/index.ts (1 hunks)
  • src/lib/app-fns/tx/common/post.tsx (3 hunks)
  • src/lib/app-fns/tx/common/postEvm.tsx (1 hunks)
  • src/lib/app-fns/tx/evm/requestEvm.tsx (1 hunks)
  • src/lib/app-provider/env.ts (2 hunks)
  • src/lib/app-provider/hooks/useSignAndBroadcastEvm.ts (1 hunks)
  • src/lib/app-provider/tx/evm/requestEvm.ts (1 hunks)
  • src/lib/components/EstimatedEvmFeeRender.tsx (1 hunks)
  • src/lib/components/table/evm-transactions/EvmTransactionsTable.tsx (2 hunks)
  • src/lib/pages/evm-tx-details/data.ts (1 hunks)
  • src/lib/services/evm/jsonRpc.ts (1 hunks)
  • src/lib/services/tx/index.ts (3 hunks)
  • src/lib/services/tx/jsonRpc.ts (2 hunks)
  • src/lib/services/types/evm/params.ts (1 hunks)
  • src/lib/services/types/tx.ts (1 hunks)
  • src/lib/utils/evm.ts (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/lib/pages/evm-tx-details/data.ts
🔇 Additional comments (14)
src/lib/components/table/evm-transactions/EvmTransactionsTable.tsx (1)

54-54: LGTM! Property naming convention update.

The change from fee_denom to feeDenom aligns with JavaScript/TypeScript camelCase naming conventions.

Also applies to: 71-71

src/lib/app-fns/tx/common/index.ts (1)

3-3: LGTM!

The new export follows the established pattern and maintains consistency with other exports.

src/lib/app-fns/tx/common/postEvm.tsx (1)

7-9: LGTM! Well-structured interface definition.

The PostEvmTxParams interface with generic type constraint is well-defined and provides good type safety.

src/lib/services/evm/jsonRpc.ts (1)

8-8: LGTM! Type expansion improves flexibility.

Adding object to JsonRpcParams type is appropriate for EVM transactions that require structured parameters.

Let's verify that the expanded type is used correctly:

✅ Verification successful

Type expansion is correctly used throughout the codebase

The expanded JsonRpcParams type accommodates all current usage patterns, including string parameters for cosmos transactions and object parameters for ETH calls.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for JsonRpcParams usage to ensure compatibility
rg -l "JsonRpcParams" | xargs rg "JsonRpcParams.*=.*" -A 2

Length of output: 242


Script:

#!/bin/bash
# Get complete implementation context
ast-grep --pattern 'export const requestJsonRpc = ($$$) {
  $$$
}'

# Find all usages of requestJsonRpc
rg "requestJsonRpc\(" -A 2

Length of output: 954

src/lib/app-fns/tx/common/post.tsx (1)

10-12: LGTM! Type constraint simplification.

Simplifying to DeliverTxResponse makes the code more focused and maintainable.

src/lib/app-fns/tx/evm/requestEvm.tsx (1)

15-22: LGTM! Well-structured interface definition.

The interface clearly defines the required parameters and optional callbacks for transaction handling.

src/lib/services/types/tx.ts (1)

469-469: LGTM! Clean type export.

The type is correctly inferred from the Zod schema and properly exported.

src/lib/services/tx/index.ts (1)

783-808: LGTM! Well-implemented hook with proper error handling and caching.

The hook effectively:

  • Handles EVM configuration
  • Includes proper error handling
  • Uses appropriate query caching
  • Maintains type safety
src/lib/app-provider/hooks/useSignAndBroadcastEvm.ts (2)

52-54: LGTM! Clean type definition.

The type is well-defined and properly exported.


56-82: Add type narrowing for wallet provider context.

The code assumes requestEthereumTx exists on the context without type checking.

 if (evm.enabled && walletProvider.type === "initia-widget") {
+  if (!('requestEthereumTx' in walletProvider.context)) {
+    throw new Error("Wallet provider context missing requestEthereumTx");
+  }
   const { requestEthereumTx } = walletProvider.context;
   const txHash = await requestEthereumTx(request, { chainId });
   return getEvmTxResponse(evm.jsonRpc, txHash);
 }
src/lib/app-provider/env.ts (2)

6-6: LGTM! Well-organized simulation key addition.

The new SIMULATE_FEE_EVM key follows the existing naming pattern and is correctly placed in the simulation section.


147-147: LGTM! Properly placed EVM query key.

The new EVM_ETH_CALL key is logically placed in the EVM section and follows the established naming convention.

src/lib/utils/evm.ts (2)

7-7: LGTM!

The import statement follows the existing pattern and imports the necessary types from the ethers library.


95-101: Verify integration with EVM transaction hooks.

Let's verify the usage of this function in the codebase:

✅ Verification successful

Proper integration with EVM transaction flow verified

The encodeFunctionData utility is correctly integrated into the EVM transaction flow:

  • Used by requestEvmTx for transaction preparation
  • Properly interfaces with ethers.js for ABI encoding
  • Follows the standard EVM transaction pattern
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of encodeFunctionData
echo "Searching for encodeFunctionData usage..."
rg "encodeFunctionData" --type ts

# Check the implementation of related hooks
echo -e "\nChecking related hook implementations..."
rg "useSignAndBroadcastEvm|useSimulateFeeEvm" --type ts

# Look for similar encoding patterns
echo -e "\nChecking for similar encoding patterns..."
ast-grep --pattern 'new Interface($$$)'

Length of output: 1713


Script:

#!/bin/bash
# Check hook implementations
echo "Content of useSignAndBroadcastEvm.ts:"
cat src/lib/app-provider/hooks/useSignAndBroadcastEvm.ts

echo -e "\nContent of useSimulateFeeEvm.ts:"
cat src/lib/app-provider/hooks/useSimulateFeeEvm.ts

# Look for transaction preparation functions
echo -e "\nSearching for transaction preparation patterns:"
rg "prepareTx|prepareTransaction" --type ts -A 5

Length of output: 3932


Script:

#!/bin/bash
# Check where hooks are used and how transactions are prepared
echo "Searching for TransactionRequest usage:"
rg "TransactionRequest" --type ts -B 2 -A 2

echo -e "\nChecking files that use the hooks:"
rg "useSignAndBroadcastEvm|useSimulateFeeEvm" --type ts -B 2 -A 2

echo -e "\nLooking for transaction creation patterns:"
ast-grep --pattern 'const $_ = {
  to: $_,
  data: $_
}'

Length of output: 7182


Script:

#!/bin/bash
# Check transaction preparation implementation
echo "Content of requestEvmTx implementation:"
cat src/lib/app-fns/tx/evm/requestEvm.ts

# Look for any other files that might be preparing transactions
echo -e "\nSearching for files with 'evm' and 'tx' in path:"
fd -t f -p ".*evm.*tx.*" -x cat {}

Length of output: 54308


Script:

#!/bin/bash
# Search for files in app-fns directory
echo "Checking app-fns directory:"
fd -t f . src/lib/app-fns -x cat {}

# Search for transaction preparation patterns
echo -e "\nSearching for transaction preparation and encoding patterns:"
rg "prepareTx|prepareTransaction|encodeFunctionData" --type ts -B 2 -A 5

Length of output: 37101

Comment on lines 11 to 48
export const postEvmTx = <T extends TxReceiptJsonRpc>({
postFn,
}: PostEvmTxParams<T>) => {
return () =>
postFn().then((txResult) => {
return {
value: txResult,
phase: TxStreamPhase.BROADCAST,
receipts: [
{
title: "Tx Hash",
html: (
<ExplorerLink
type="tx_hash"
value={txResult.transactionHash}
openNewTab
/>
),
},
{
title: "Tx Fee",
// TODO: Implement event/rawlog attribute picker
html: (
<EstimatedEvmFeeRender
effectiveGasPrice={txResult.effectiveGasPrice}
gasUsed={txResult.gasUsed}
loading={false}
/>
),
},
],
receiptInfo: {
header: "Sending Transaction",
},
actionVariant: "sending",
} as TxResultRendering<T>;
});
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding error handling for failed transactions.

The current implementation doesn't handle transaction failures explicitly. Consider adding error handling similar to how postTx handles isDeliverTxFailure.

Here's a suggested implementation:

 export const postEvmTx = <T extends TxReceiptJsonRpc>({
   postFn,
 }: PostEvmTxParams<T>) => {
   return () =>
     postFn().then((txResult) => {
+      // Check for transaction failure
+      if (txResult.status === '0x0') {
+        throw new Error(`Transaction failed: ${txResult.transactionHash}`);
+      }
       return {
         value: txResult,
         phase: TxStreamPhase.BROADCAST,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const postEvmTx = <T extends TxReceiptJsonRpc>({
postFn,
}: PostEvmTxParams<T>) => {
return () =>
postFn().then((txResult) => {
return {
value: txResult,
phase: TxStreamPhase.BROADCAST,
receipts: [
{
title: "Tx Hash",
html: (
<ExplorerLink
type="tx_hash"
value={txResult.transactionHash}
openNewTab
/>
),
},
{
title: "Tx Fee",
// TODO: Implement event/rawlog attribute picker
html: (
<EstimatedEvmFeeRender
effectiveGasPrice={txResult.effectiveGasPrice}
gasUsed={txResult.gasUsed}
loading={false}
/>
),
},
],
receiptInfo: {
header: "Sending Transaction",
},
actionVariant: "sending",
} as TxResultRendering<T>;
});
};
export const postEvmTx = <T extends TxReceiptJsonRpc>({
postFn,
}: PostEvmTxParams<T>) => {
return () =>
postFn().then((txResult) => {
// Check for transaction failure
if (txResult.status === '0x0') {
throw new Error(`Transaction failed: ${txResult.transactionHash}`);
}
return {
value: txResult,
phase: TxStreamPhase.BROADCAST,
receipts: [
{
title: "Tx Hash",
html: (
<ExplorerLink
type="tx_hash"
value={txResult.transactionHash}
openNewTab
/>
),
},
{
title: "Tx Fee",
// TODO: Implement event/rawlog attribute picker
html: (
<EstimatedEvmFeeRender
effectiveGasPrice={txResult.effectiveGasPrice}
gasUsed={txResult.gasUsed}
loading={false}
/>
),
},
],
receiptInfo: {
header: "Sending Transaction",
},
actionVariant: "sending",
} as TxResultRendering<T>;
});
};

Comment on lines 95 to 101
export const encodeFunctionData = (
abiSection: JsonFragment,
values: unknown[]
) => {
const iface = new Interface([abiSection]);
return iface.encodeFunctionData(abiSection.name ?? "", values);
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add type safety, error handling, and documentation.

The function implementation could be improved in several areas:

+/**
+ * Encodes function data using ethers Interface for EVM transactions
+ * @param abiSection - The ABI fragment containing function details
+ * @param values - Array of parameter values matching the function signature
+ * @returns Encoded function data as a hex string
+ * @throws {Error} If ABI is invalid or encoding fails
+ */
 export const encodeFunctionData = (
   abiSection: JsonFragment,
-  values: unknown[]
+  values: Array<string | number | boolean>
 ) => {
+  if (!abiSection.name || !abiSection.type || abiSection.type !== "function") {
+    throw new Error("Invalid ABI: missing function name or type");
+  }
+
+  try {
     const iface = new Interface([abiSection]);
-    return iface.encodeFunctionData(abiSection.name ?? "", values);
+    return iface.encodeFunctionData(abiSection.name, values);
+  } catch (error) {
+    throw new Error(`Failed to encode function data: ${(error as Error).message}`);
+  }
 };

Changes:

  1. Added JSDoc documentation
  2. Improved type safety by replacing unknown[] with specific types
  3. Added validation for required ABI properties
  4. Added error handling with descriptive messages
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const encodeFunctionData = (
abiSection: JsonFragment,
values: unknown[]
) => {
const iface = new Interface([abiSection]);
return iface.encodeFunctionData(abiSection.name ?? "", values);
};
/**
* Encodes function data using ethers Interface for EVM transactions
* @param abiSection - The ABI fragment containing function details
* @param values - Array of parameter values matching the function signature
* @returns Encoded function data as a hex string
* @throws {Error} If ABI is invalid or encoding fails
*/
export const encodeFunctionData = (
abiSection: JsonFragment,
values: Array<string | number | boolean>
) => {
if (!abiSection.name || !abiSection.type || abiSection.type !== "function") {
throw new Error("Invalid ABI: missing function name or type");
}
try {
const iface = new Interface([abiSection]);
return iface.encodeFunctionData(abiSection.name, values);
} catch (error) {
throw new Error(`Failed to encode function data: ${(error as Error).message}`);
}
};

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (2)
src/lib/app-fns/tx/common/postEvm.tsx (1)

14-47: ⚠️ Potential issue

Add error handling for failed transactions.

The current implementation doesn't handle transaction failures.

   return () =>
     postFn().then((txResult) => {
+      if (txResult.status === '0x0') {
+        throw new Error(`Transaction failed: ${txResult.transactionHash}`);
+      }
       return {
         value: txResult,
         phase: TxStreamPhase.BROADCAST,
src/lib/app-provider/hooks/useSignAndBroadcastEvm.ts (1)

70-83: ⚠️ Potential issue

Add type narrowing for wallet provider context.

The code assumes requestEthereumTx exists on the context without type checking.

   if (evm.enabled && walletProvider.type === "initia-widget") {
+    if (!('requestEthereumTx' in walletProvider.context) || !('ethereum' in walletProvider.context)) {
+      throw new Error("Wallet provider context missing required methods");
+    }
     const { requestEthereumTx, ethereum } = walletProvider.context;
🧹 Nitpick comments (3)
src/lib/app-fns/tx/common/sendingEvm.tsx (2)

12-13: Remove unnecessary eslint-disable comment and improve type safety.

The eslint-disable comment and void parameter can be removed since they're not needed.

-  // eslint-disable-next-line @typescript-eslint/no-unused-vars
-  return (_: void) => {
+  return () => {
🧰 Tools
🪛 Biome (1.9.4)

[error] 13-13: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)


8-36: Consider memoizing the return function.

Since this function returns another function that creates an object with React components, consider memoizing it to prevent unnecessary re-renders.

+import { useMemo } from "react";

-export const sendingEvmTx = ({
+export const sendingEvmTx = useMemo(({ 
   gasPrice,
   simulatedGasUsed,
 }: SimulatedFeeEvm) => {
   return () => {
     return {
       // ... existing implementation
     } as TxResultRendering;
   };
-};
+}, [gasPrice, simulatedGasUsed]);
🧰 Tools
🪛 Biome (1.9.4)

[error] 13-13: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)

src/lib/components/EstimatedFeeEvmRender.tsx (1)

8-41: Optimize component performance with useMemo.

The component performs calculations on every render. Consider memoizing the fee calculation.

+import { useMemo } from "react";

 export const EstimatedFeeEvmRender = ({
   gasPrice,
   gasUsed,
   loading,
 }: {
   gasPrice: Big;
   gasUsed: Big;
   loading: boolean;
 }) => {
   const { data: assetInfos, isLoading: isAssetInfoLoading } = useAssetInfos({
     withPrices: false,
   });
   const { data: evmParams, isLoading: isEvmParamsLoading } = useEvmParams();

+  const feeToken = useMemo(() => {
+    if (!evmParams?.params.feeDenom || !assetInfos) return null;
+    try {
+      const feeAmount = gasPrice.mul(gasUsed);
+      return coinToTokenWithValue(
+        evmParams.params.feeDenom,
+        feeAmount.toFixed(),
+        assetInfos
+      );
+    } catch (error) {
+      console.error('Error calculating fee:', error);
+      return null;
+    }
+  }, [gasPrice, gasUsed, evmParams?.params.feeDenom, assetInfos]);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dc0b0cf and 2d6c2da.

📒 Files selected for processing (15)
  • src/lib/app-fns/tx/common/postEvm.tsx (1 hunks)
  • src/lib/app-fns/tx/common/sendingEvm.tsx (1 hunks)
  • src/lib/app-fns/tx/evm/requestEvm.tsx (1 hunks)
  • src/lib/app-provider/hooks/index.ts (1 hunks)
  • src/lib/app-provider/hooks/useSignAndBroadcastEvm.ts (1 hunks)
  • src/lib/app-provider/tx/evm/requestEvm.ts (1 hunks)
  • src/lib/components/EstimatedFeeEvmRender.tsx (1 hunks)
  • src/lib/components/token/TokenImageWithAmount.tsx (2 hunks)
  • src/lib/services/evm/index.ts (2 hunks)
  • src/lib/services/evm/jsonRpc.ts (3 hunks)
  • src/lib/services/tx/index.ts (2 hunks)
  • src/lib/services/tx/jsonRpc.ts (2 hunks)
  • src/lib/services/tx/simulateFeeEvm.ts (1 hunks)
  • src/lib/services/types/tx.ts (4 hunks)
  • src/lib/utils/evm.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/lib/app-provider/hooks/index.ts
  • src/lib/services/tx/index.ts
  • src/lib/services/types/tx.ts
  • src/lib/app-fns/tx/evm/requestEvm.tsx
  • src/lib/services/tx/simulateFeeEvm.ts
  • src/lib/services/tx/jsonRpc.ts
  • src/lib/app-provider/tx/evm/requestEvm.ts
🧰 Additional context used
🪛 Biome (1.9.4)
src/lib/app-fns/tx/common/sendingEvm.tsx

[error] 13-13: void is confusing outside a return type or a type parameter.

Unsafe fix: Use undefined instead.

(lint/suspicious/noConfusingVoidType)

🔇 Additional comments (8)
src/lib/components/token/TokenImageWithAmount.tsx (2)

4-4: LGTM!

The import statement is correctly placed and properly aligned with the component's dependencies.


20-20: Verify the token formatting behavior across the codebase.

The refactoring from using two separate functions to a single formatTokenWithValue function looks good and simplifies the implementation. However, let's verify that this change maintains consistent behavior across all token formatting use cases.

Let's check other usages of token formatting in the codebase:

✅ Verification successful

Token formatting behavior is consistent across the codebase

The refactoring maintains backward compatibility while providing a more convenient combined function. The implementation is well-tested and shows consistent usage patterns across components.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining usages of the old formatting functions and verify consistent usage of the new function

# Check for any remaining usage of old functions
echo "Checking for remaining usage of formatUTokenWithPrecision..."
rg "formatUTokenWithPrecision"

echo "Checking for remaining usage of getTokenLabel..."
rg "getTokenLabel"

# Check usage patterns of new function
echo "Checking usage patterns of formatTokenWithValue..."
rg "formatTokenWithValue" -A 2

Length of output: 27914

src/lib/app-fns/tx/common/postEvm.tsx (1)

32-32: Address TODO comment about event/rawlog attribute picker.

The TODO comment indicates missing functionality for event/rawlog attribute picking.

Would you like me to help implement the event/rawlog attribute picker or create a GitHub issue to track this task?

src/lib/utils/evm.ts (2)

105-111: Previous review comments still apply.

The suggested improvements from the previous review for type safety, error handling, and documentation have not been addressed.


113-119: 🛠️ Refactor suggestion

Add type safety, error handling, and documentation.

The function implementation needs improvements:

+/**
+ * Decodes function result data using ethers Interface for EVM transactions
+ * @param abiSection - The ABI fragment containing function details
+ * @param data - The hex string data to decode
+ * @returns Decoded function result
+ * @throws {Error} If ABI is invalid or decoding fails
+ */
 export const decodeEvmFunctionResult = (
   abiSection: JsonFragment,
   data: string
-) => {
-  const iface = new Interface([abiSection]);
-  return iface.decodeFunctionResult(abiSection.name ?? "", data);
+): unknown => {
+  if (!abiSection.name || !abiSection.type || abiSection.type !== "function") {
+    throw new Error("Invalid ABI: missing function name or type");
+  }
+
+  try {
+    const iface = new Interface([abiSection]);
+    return iface.decodeFunctionResult(abiSection.name, data);
+  } catch (error) {
+    throw new Error(`Failed to decode function result: ${(error as Error).message}`);
+  }
 };

Likely invalid or redundant comment.

src/lib/services/evm/jsonRpc.ts (2)

37-37: Ensure changing the return value of requestJsonRpc does not introduce breaking changes

By returning parsed.result instead of the entire parsed object, this change may affect functions that rely on the previous return structure of requestJsonRpc. Please verify that all consumers of this function handle the new return value correctly.


76-84: getEthCall function implementation is correct

The getEthCall function correctly constructs an eth_call JSON-RPC request and properly parses the response using parseWithError(zHex, result).

src/lib/services/evm/index.ts (1)

74-100: useEthCall hook is properly implemented

The useEthCall hook appropriately sets up a query for making Ethereum calls, handling EVM configuration and user address conversion correctly.

Comment on lines +34 to +39
const feeAmount = gasPrice.mul(gasUsed);
const feeToken = coinToTokenWithValue(
feeDenom,
feeAmount.toFixed(),
assetInfos
);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for invalid fee calculations.

The multiplication of gasPrice and gasUsed could throw if the values are invalid. Consider adding try-catch.

-  const feeAmount = gasPrice.mul(gasUsed);
-  const feeToken = coinToTokenWithValue(
-    feeDenom,
-    feeAmount.toFixed(),
-    assetInfos
-  );
+  try {
+    const feeAmount = gasPrice.mul(gasUsed);
+    const feeToken = coinToTokenWithValue(
+      feeDenom,
+      feeAmount.toFixed(),
+      assetInfos
+    );
+    return <>{formatTokenWithValue(feeToken, undefined, false)}</>;
+  } catch (error) {
+    console.error('Error calculating fee:', error);
+    return <>Error calculating fee</>;
+  }
-  return <>{formatTokenWithValue(feeToken, undefined, false)}</>;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const feeAmount = gasPrice.mul(gasUsed);
const feeToken = coinToTokenWithValue(
feeDenom,
feeAmount.toFixed(),
assetInfos
);
try {
const feeAmount = gasPrice.mul(gasUsed);
const feeToken = coinToTokenWithValue(
feeDenom,
feeAmount.toFixed(),
assetInfos
);
return <>{formatTokenWithValue(feeToken, undefined, false)}</>;
} catch (error) {
console.error('Error calculating fee:', error);
return <>Error calculating fee</>;
}

Comment on lines +14 to +54
const getEvmTxResponse = async (jsonRpcEndpoint: string, txHash: string) => {
const TIME_OUT_MS = 3000;
const POLL_INTERVAL_MS = 1000;

let timedOut = false;
const txPollTimeout = setTimeout(() => {
timedOut = true;
}, TIME_OUT_MS);

const pollForEvmTx = async (_txHash: string): Promise<TxReceiptJsonRpc> => {
if (timedOut) {
throw new Error(
`Transaction with hash ${_txHash} was submitted but was not yet found on the chain. You might want to check later. There was a wait of ${
TIME_OUT_MS / 1000
} seconds.`
);
}
await sleep(POLL_INTERVAL_MS);
const result = await requestJsonRpc(
jsonRpcEndpoint,
"eth_getTransactionReceipt",
[txHash]
)
.then((result) => parseWithError(zTxReceiptJsonRpc, result))
.catch(() => undefined);
return result ? result : pollForEvmTx(_txHash);
};

return new Promise<TxReceiptJsonRpc>((resolve, reject) => {
pollForEvmTx(txHash).then(
(value) => {
clearTimeout(txPollTimeout);
resolve(value);
},
(error) => {
clearTimeout(txPollTimeout);
reject(error);
}
);
});
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Extract timeout constants and improve error handling in polling mechanism.

The timeout and polling interval values should be configurable constants, and error handling could be improved.

+const EVM_TX_TIMEOUT_MS = 3000;
+const EVM_TX_POLL_INTERVAL_MS = 1000;
+
 const getEvmTxResponse = async (jsonRpcEndpoint: string, txHash: string) => {
-  const TIME_OUT_MS = 3000;
-  const POLL_INTERVAL_MS = 1000;
+  const timeoutMessage = (hash: string, timeout: number) =>
+    `Transaction ${hash} was not found on chain after ${timeout / 1000}s`;

   let timedOut = false;
   const txPollTimeout = setTimeout(() => {
     timedOut = true;
-  }, TIME_OUT_MS);
+  }, EVM_TX_TIMEOUT_MS);

   const pollForEvmTx = async (_txHash: string): Promise<TxReceiptJsonRpc> => {
     if (timedOut) {
-      throw new Error(
-        `Transaction with hash ${_txHash} was submitted but was not yet found on the chain. You might want to check later. There was a wait of ${
-          TIME_OUT_MS / 1000
-        } seconds.`
-      );
+      throw new Error(timeoutMessage(_txHash, EVM_TX_TIMEOUT_MS));
     }
-    await sleep(POLL_INTERVAL_MS);
+    await sleep(EVM_TX_POLL_INTERVAL_MS);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const getEvmTxResponse = async (jsonRpcEndpoint: string, txHash: string) => {
const TIME_OUT_MS = 3000;
const POLL_INTERVAL_MS = 1000;
let timedOut = false;
const txPollTimeout = setTimeout(() => {
timedOut = true;
}, TIME_OUT_MS);
const pollForEvmTx = async (_txHash: string): Promise<TxReceiptJsonRpc> => {
if (timedOut) {
throw new Error(
`Transaction with hash ${_txHash} was submitted but was not yet found on the chain. You might want to check later. There was a wait of ${
TIME_OUT_MS / 1000
} seconds.`
);
}
await sleep(POLL_INTERVAL_MS);
const result = await requestJsonRpc(
jsonRpcEndpoint,
"eth_getTransactionReceipt",
[txHash]
)
.then((result) => parseWithError(zTxReceiptJsonRpc, result))
.catch(() => undefined);
return result ? result : pollForEvmTx(_txHash);
};
return new Promise<TxReceiptJsonRpc>((resolve, reject) => {
pollForEvmTx(txHash).then(
(value) => {
clearTimeout(txPollTimeout);
resolve(value);
},
(error) => {
clearTimeout(txPollTimeout);
reject(error);
}
);
});
};
const EVM_TX_TIMEOUT_MS = 3000;
const EVM_TX_POLL_INTERVAL_MS = 1000;
const getEvmTxResponse = async (jsonRpcEndpoint: string, txHash: string) => {
const timeoutMessage = (hash: string, timeout: number) =>
`Transaction ${hash} was not found on chain after ${timeout / 1000}s`;
let timedOut = false;
const txPollTimeout = setTimeout(() => {
timedOut = true;
}, EVM_TX_TIMEOUT_MS);
const pollForEvmTx = async (_txHash: string): Promise<TxReceiptJsonRpc> => {
if (timedOut) {
throw new Error(timeoutMessage(_txHash, EVM_TX_TIMEOUT_MS));
}
await sleep(EVM_TX_POLL_INTERVAL_MS);
const result = await requestJsonRpc(
jsonRpcEndpoint,
"eth_getTransactionReceipt",
[txHash]
)
.then((result) => parseWithError(zTxReceiptJsonRpc, result))
.catch(() => undefined);
return result ? result : pollForEvmTx(_txHash);
};
return new Promise<TxReceiptJsonRpc>((resolve, reject) => {
pollForEvmTx(txHash).then(
(value) => {
clearTimeout(txPollTimeout);
resolve(value);
},
(error) => {
clearTimeout(txPollTimeout);
reject(error);
}
);
});
};

Comment on lines +96 to +103
export const convertCosmosChainIdToEvmChainId = (chainId: string) => {
// metamask max
const METAMASK_MAX = "4503599627370476";

const hash = keccak256(Buffer.from(chainId));
const rawEvmChainId = Buffer.from(hash).readBigUInt64BE();
return big(rawEvmChainId.toString()).mod(METAMASK_MAX).toFixed();
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add documentation, input validation, and error handling.

The chain ID conversion function needs improvements in several areas:

+/**
+ * Converts a Cosmos chain ID to an EVM-compatible chain ID
+ * @param chainId - The Cosmos chain ID string
+ * @returns A string representing the EVM chain ID, compatible with MetaMask's maximum value
+ * @throws {Error} If the chain ID is invalid or conversion fails
+ */
 export const convertCosmosChainIdToEvmChainId = (chainId: string) => {
+  if (!chainId) {
+    throw new Error("Chain ID is required");
+  }
+
   // MetaMask's maximum safe chain ID (2^52 - 1)
   const METAMASK_MAX = "4503599627370476";
 
-  const hash = keccak256(Buffer.from(chainId));
-  const rawEvmChainId = Buffer.from(hash).readBigUInt64BE();
-  return big(rawEvmChainId.toString()).mod(METAMASK_MAX).toFixed();
+  try {
+    const hash = keccak256(Buffer.from(chainId));
+    const rawEvmChainId = Buffer.from(hash).readBigUInt64BE();
+    return big(rawEvmChainId.toString()).mod(METAMASK_MAX).toFixed();
+  } catch (error) {
+    throw new Error(`Failed to convert chain ID: ${(error as Error).message}`);
+  }
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const convertCosmosChainIdToEvmChainId = (chainId: string) => {
// metamask max
const METAMASK_MAX = "4503599627370476";
const hash = keccak256(Buffer.from(chainId));
const rawEvmChainId = Buffer.from(hash).readBigUInt64BE();
return big(rawEvmChainId.toString()).mod(METAMASK_MAX).toFixed();
};
/**
* Converts a Cosmos chain ID to an EVM-compatible chain ID
* @param chainId - The Cosmos chain ID string
* @returns A string representing the EVM chain ID, compatible with MetaMask's maximum value
* @throws {Error} If the chain ID is invalid or conversion fails
*/
export const convertCosmosChainIdToEvmChainId = (chainId: string) => {
if (!chainId) {
throw new Error("Chain ID is required");
}
// MetaMask's maximum safe chain ID (2^52 - 1)
const METAMASK_MAX = "4503599627370476";
try {
const hash = keccak256(Buffer.from(chainId));
const rawEvmChainId = Buffer.from(hash).readBigUInt64BE();
return big(rawEvmChainId.toString()).mod(METAMASK_MAX).toFixed();
} catch (error) {
throw new Error(`Failed to convert chain ID: ${(error as Error).message}`);
}
};

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
CHANGELOG.md (2)

42-42: Add release dates for version entries.

Each version section should include its release date to help track when changes were made available.

-## v1.9.3
+## v1.9.3 - 2024-01-10

Line range hint 42-1124: Consider standardizing entry descriptions.

While most entries are clear, some could be more descriptive. Consider standardizing the format to always:

  1. Start with a verb (Add, Fix, Update, etc.)
  2. Clearly state what was changed
  3. Include the impact or reason when relevant

Example of improving an entry:

-[#1188](https://github.com/alleslabs/celatone-frontend/pull/1188) Add request and simulate evm tx
+[#1188](https://github.com/alleslabs/celatone-frontend/pull/1188) Add request and simulate EVM transaction functionality to support Ethereum-compatible transactions
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8434703 and 80f4d3f.

📒 Files selected for processing (2)
  • CHANGELOG.md (1 hunks)
  • src/lib/utils/validate.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/utils/validate.ts
🔇 Additional comments (2)
CHANGELOG.md (2)

Line range hint 1-24: LGTM! Well-structured changelog header.

The header section properly explains the guiding principles and usage instructions for maintaining the changelog.


Line range hint 26-40: LGTM! Follows Keep a Changelog format.

The file structure correctly follows the Keep a Changelog format and clearly states adherence to Semantic Versioning.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🔭 Outside diff range comments (1)
src/lib/pages/evm-contract-verify/components/ConstructorArgs.tsx (1)

Line range hint 24-26: Add validation for constructor arguments format.

The placeholder suggests a specific hex format, but there's no validation to ensure the input matches this format. Consider adding validation to prevent invalid submissions.

// Add this validation function
const isValidConstructorArgs = (value: string) => /^(0x)?[0-9a-fA-F]+$/.test(value);

// Add validation to the onChange handler
onChange={(e) => {
  const value = e.target.value;
  if (value === '' || isValidConstructorArgs(value)) {
    field.onChange(value);
  }
}}
🧹 Nitpick comments (2)
src/lib/pages/evm-contract-verify/components/ConstructorArgs.tsx (2)

Line range hint 28-33: Improve accessibility for the constructor arguments input.

The textarea lacks proper ARIA attributes and error handling for better accessibility.

 <Textarea
   visibility={field.value === undefined ? "hidden" : "visible"}
   placeholder="ex.000000000000000000000000c005dc82818d67af737725bd4bf75435d065d239"
   value={field.value}
   onChange={(e) => field.onChange(e.target.value)}
+  aria-label="Constructor Arguments"
+  aria-describedby="constructor-args-help"
 />
+<Text id="constructor-args-help" fontSize="sm" color="text.dark">
+  Enter the constructor arguments in hexadecimal format
+</Text>

4-6: Consider using a more specific type for the form control.

The EvmContractVerifyForm type might be too broad. Consider creating a more specific type for the constructor arguments field.

interface ConstructorArgsField {
  verifyForm: {
    form: {
      constructorArgs?: string;
    };
  };
}

interface ConstructorArgsProps {
  control: Control<ConstructorArgsField>;
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 80f4d3f and bfd550e.

📒 Files selected for processing (2)
  • src/lib/components/forms/SelectInput.tsx (1 hunks)
  • src/lib/pages/evm-contract-verify/components/ConstructorArgs.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/lib/components/forms/SelectInput.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (javascript)

@songwongtp songwongtp merged commit ae6fab7 into develop Jan 15, 2025
13 checks passed
@songwongtp songwongtp deleted the feat/tx-evm branch January 15, 2025 07:03
@coderabbitai coderabbitai bot mentioned this pull request Jan 20, 2025
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.

3 participants