Skip to content

Conversation

@li-jianli
Copy link
Contributor

@li-jianli li-jianli commented Dec 10, 2025

[中文版模板 / Chinese template]

💡 Background and solution

Swap Token Component
image

🔗 Related issue link

Summary by CodeRabbit

  • 新功能
    • 新增完整 SwapToken 组件及子组件(CryptoInput、TokenSelector、PrimaryButton)、并提供演示(basic、quota、fee-control)。
  • 工具
    • 增加金额/格式化与单位转换等实用函数,改善数值显示与转换。
  • 类型与兼容性
    • 补充 PNG 导入声明、代币/配置/资金流向类型与常量导出。
  • 文档
    • 完善中/英文组件文档与示例。
  • 样式
    • 添加 SwapToken 与 PrimaryButton 主题样式与样式钩子。
  • 测试
    • 新增基础单元测试用例。

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Dec 10, 2025

⚠️ No Changeset found

Latest commit: 7c90fcb

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Dec 10, 2025

Someone is attempting to deploy a commit to the pro-components Team on Vercel.

A member of the Team first needs to authorize it.

@dosubot dosubot bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Dec 10, 2025
@github-actions
Copy link

github-actions bot commented Dec 10, 2025

Preview is ready

@gemini-code-assist
Copy link

Summary of Changes

Hello @li-jianli, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request delivers a new SwapToken component to the @ant-design/web3 library, significantly enhancing its capabilities for decentralized applications. The component offers a user-friendly interface for token exchanges, encompassing input and output fields for token amounts, dynamic token selection, and robust validation against user balances, maximum input limits, and global quotas. It also integrates fee calculation and provides clear visual feedback for various states, making it a versatile tool for developers building Web3 applications that require token swap functionalities.

Highlights

  • New SwapToken Component: Introduces a comprehensive UI component for token swapping, designed for DApps and cross-chain scenarios, integrating input fields, token selection, and action handling.
  • CryptoInput & TokenSelector: Adds specialized input fields for cryptocurrency amounts with features like balance display, max input functionality, quota checks, and token selection dropdowns.
  • Fee and Quota Management: Implements features for displaying estimated fees, handling global quotas, and validating input amounts against these limits, providing clear visual feedback.
  • Styling and Theming: Includes dedicated styling for the new components, ensuring a consistent look and feel within the Ant Design Web3 ecosystem, with a custom primary button.
  • Extensive API and Documentation: Provides a rich API for customization and detailed documentation in both English and Chinese, along with multiple usage demos covering basic usage, fee control, and quota management.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link

coderabbitai bot commented Dec 10, 2025

Warning

Rate limit exceeded

@li-jianli has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 1 minutes and 24 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between ec95705 and 7c90fcb.

📒 Files selected for processing (1)
  • packages/web3/src/swap-token/CryptoInput.tsx (1 hunks)

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

新增完整的 SwapToken 套件:包含泛型 SwapToken 主组件及子组件(CryptoInput、TokenSelector、PrimaryButton)、样式与 useStyle 钩子、类型定义、格式化工具、演示、测试,并在全局声明中加入对 .png 导入的支持。

Changes

内聚体 / 文件(s) 更改摘要
全局声明
packages/web3/global.d.ts
新增 PNG 模块声明:declare module '*.png' { const url: string; export default url; }
包导出
packages/web3/src/index.ts
新增对 SwapToken 及其类型的公开 re-exports(SwapTokenSwapInputPropsSwapInputRefSwapTokenConfigSwapTokenTokenFundFlowDirection
主组件 & 类型
packages/web3/src/swap-token/index.tsx, packages/web3/src/swap-token/type.ts
新增泛型 forwardRef SwapToken 组件与相关导出类型(SwapInputPropsSwapInputRefSwapTokenComponentSwapTokenToken/SwapTokenConfigFundFlowDirection
子组件
packages/web3/src/swap-token/CryptoInput.tsx, packages/web3/src/swap-token/TokenSelector.tsx, packages/web3/src/swap-token/PrimaryButton/index.tsx
新增泛型 CryptoInput<T>(输入校验、配额、Max、状态回调)、TokenSelector<T>(token 选单/标签渲染)与封装按钮 PrimaryButton 组件
样式钩子
packages/web3/src/swap-token/PrimaryButton/style/index.tsx, packages/web3/src/swap-token/style/index.tsx
新增样式生成器与 useStyle 钩子(PrimaryButtonTokengenPrimaryButtonStyleSwapTokenTokengenSwapTokenStyleuseStyle
常量
packages/web3/src/swap-token/constant.ts
新增常量:TOKEN_DECIMALS_DEFAULT = 18AMOUNT_IN_DECIMALS = 6CUSTOMIZE_PREFIX_CLS = 'ant-web3-swap-token'
格式化工具
packages/web3/src/swap-token/utils/format.ts
新增工具函数:formatBalanceformatBalanceWithoutFixedformatValueformatAmountdecimalToBigInt(依赖 decimal.js 与 viem.parseUnits,含容错回退)
测试
packages/web3/src/swap-token/__tests__/basic.test.tsx
新增基础测试,覆盖提交、方向切换、额外渲染与未连接钱包按钮禁用场景
演示 与 模拟数据
packages/web3/src/swap-token/demos/*, packages/web3/src/swap-token/demos/mockData.tsx
新增三个演示(basicfee-controlquota)与 mockTokenPairs(含 TokenBadge
文档
packages/web3/src/swap-token/index.md, packages/web3/src/swap-token/index.zh-CN.md
新增中英文文档,包含组件概览、API、类型说明与演示引用

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SwapToken
  participant CryptoInput
  participant TokenSelector
  participant FeeCalc as onCalculateFee
  participant ButtonHandler as onButtonClick

  User->>SwapToken: 输入值 / 切换代币 / 点击 Max
  SwapToken->>CryptoInput: 设置/验证 valueIn 并传递状态
  SwapToken->>TokenSelector: 渲染或切换 token
  alt 需要估算费用
    SwapToken->>FeeCalc: 调用 onCalculateFee(valueIn, tokenPair)
    FeeCalc-->>SwapToken: 返回 estFee / estFeeRate
    SwapToken->>CryptoInput: 更新 valueOut(或基于 calculateValueOut)
  end
  User->>SwapToken: 点击 Swap 按钮
  SwapToken->>ButtonHandler: 调用 onButtonClick({ tokenPair, valueIn, valueOut })
  ButtonHandler-->>SwapToken: 异步返回结果
  SwapToken-->>User: 更新加载 / 成功 / 错误 状态
Loading

Estimated code review effort

🎯 4 (复杂) | ⏱️ ~60 分钟

需要重点关注:

  • packages/web3/src/swap-token/index.tsx(主组件状态流、calculateValueIn/Out、费用计算与错误路径)
  • packages/web3/src/swap-token/CryptoInput.tsx(输入解析/格式化、decimals 与配额边界、onStatusChange 行为)
  • packages/web3/src/swap-token/type.ts(泛型与条件类型的正确性)
  • packages/web3/src/swap-token/utils/format.tsdecimalToBigInt 的降级策略与精度处理)
  • 样式钩子在不同前缀/主题下的作用域与选择器准确性

Poem

🐰 我在代码丛林里蹦跳忙,
新的 SwapToken 闪亮又欢畅,
输入校验稳又准,配额算得慌,
代币选择随心浪漫飞翔,
小兔子点个赞,功能稳又香! 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add swap token component' clearly and accurately summarizes the main change in the pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dosubot dosubot bot added the feature Independent new features label Dec 10, 2025
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new SwapToken component, which is a significant feature addition. The implementation is comprehensive, covering token selection, input validation, and transaction simulation. My review focuses on improving code quality and maintainability. Key suggestions include removing leftover console.log statements, refactoring duplicated and overly complex logic into smaller functions, and addressing issues with React hooks like missing dependencies in useCallback. I've also pointed out some dead code and CSS practices that could be improved. Overall, this is a solid contribution, and addressing these points will make the new component more robust and easier to maintain.

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: 13

🧹 Nitpick comments (10)
packages/web3/src/swap-token/demos/fee-control.tsx (1)

62-72: 建议使用设计令牌替代硬编码颜色

硬编码的颜色值 #666 可能与 Ant Design 主题不一致。建议使用设计令牌以确保在不同主题下的一致性。

-            color: '#666',
+            color: 'var(--ant-color-text-secondary)',

基于 learnings,样式实现应使用 Ant Design 的 Design Tokens。

packages/web3/src/swap-token/__tests__/basic.test.tsx (2)

73-82: 建议使用 data-testid 替代 CSS 类选择器

使用 CSS 类选择器 .ant-web3-swap-token-swap-icon 进行元素查询较为脆弱,可能因样式重构而失效。建议在组件中添加 data-testid 属性以提高测试稳定性。

-    const swapIcon = container.querySelector('.ant-web3-swap-token-swap-icon');
-    expect(swapIcon).toBeTruthy();
-    fireEvent.click(swapIcon as Element);
+    const swapIcon = screen.getByTestId('swap-icon');
+    fireEvent.click(swapIcon);

注意:这需要在 SwapToken 组件的 swap icon 容器上添加相应的 data-testid="swap-icon" 属性。


84-102: 建议补充更多测试场景

当前测试覆盖了基本功能,建议考虑添加以下测试用例以提高覆盖率:

  1. onValueOutChange 回调测试
  2. switchToken 代币切换功能测试
  3. 边界值输入测试(如空值、负数、超大数值)

需要我帮助生成这些额外的测试用例吗?

packages/web3/src/swap-token/demos/mockData.tsx (1)

9-26: 演示用 TokenBadge 建议抽成可复用的小组件(可选)

这里在 mockData 里直接定义了一个带内联样式的 TokenBadge,用作多个代币的 icon

const TokenBadge: React.FC<TokenBadgeProps> = ({ text, background }) => (
  <span style={{ ... }}>{text}</span>
);

目前只在 demo 中使用完全没问题,不过如果后面其它 demo 也会复用类似标记器,建议:

  • 抽到 demos/components/TokenBadge.tsx 之类的公共演示组件;
  • 或至少把样式对象提到组件外部常量,避免每次渲染都新建对象。

纯属可读性/复用层面的优化,不影响当前功能。

packages/web3/src/swap-token/demos/quota.tsx (1)

21-59: 配额 demo 逻辑合理,switchToken 可加注释说明意图(可选)

整体交互(方向切换、手续费 loading、maxInputAmount / quota 配置等)都符合文档描述,作为示例够用。

这里:

tokens={[quotaToken]}
token={quotaToken}
switchToken={() => {}}

因为只有一个 token 组合,switchToken 做成空函数是可以的,但对阅读者不太直观。可以考虑:

  • 在上方加一行注释说明“本示例仅支持一个交易对,因此切换无效”;或
  • 直接省略 switchToken,如果组件实现里允许该属性为可选的话。

纯改进可读性的建议,非必改。

packages/web3/src/swap-token/style/index.tsx (1)

82-113: Use Design Tokens instead of hardcoded colors in shadow definitions

The shadow definitions contain hardcoded color values:

  • boxShadow: '0 1px 1px 0 rgba(0, 0, 0, 2%)'
  • boxShadow: '0 0 10px 0 rgba(0, 0, 0, 10%)'

Per the styling guidelines, these should utilize Ant Design's Design Tokens for custom styling support rather than hardcoded values. Consider using shadow-related tokens or defining custom tokens for shadow opacity to ensure consistency with the design system and support for theme customization.

packages/web3/src/swap-token/PrimaryButton/style/index.tsx (1)

14-24: 考虑将硬编码颜色值提取为 Design Tokens。

渐变背景和边框颜色(如 #676767#4d6aff#494848 等)目前是硬编码的。为了更好的主题化支持和一致性,可以考虑将这些颜色值提取为 Design Tokens 或组件级别的 token 变量。

packages/web3/src/swap-token/CryptoInput.tsx (2)

114-136: status useMemo 缺少 isGreaterThanGlobalRemainQuota 函数依赖。

isGreaterThanGlobalRemainQuota 函数在 useMemo 内部被调用,但该函数依赖于 isValidMaxInputAmountquota?.showremainQuotatoken?.decimals。虽然 remainQuota 已在依赖数组中,但为了确保正确性,建议将该函数移入 useMemo 内部或使用 useCallback 包装。


170-176: 自动聚焦使用 setTimeout 可能导致竞态条件。

edit 快速切换时,setTimeout 可能在组件卸载后执行。建议添加清理函数。

   React.useEffect(() => {
     if (edit) {
-      setTimeout(() => {
-        inputRef.current?.focus();
-      }, 100);
+      const timer = setTimeout(() => {
+        inputRef.current?.focus();
+      }, 100);
+      return () => clearTimeout(timer);
     }
   }, [edit]);
packages/web3/src/swap-token/TokenSelector.tsx (1)

40-91: 为组件添加 displayName 以便于调试。

当前默认导出是匿名箭头函数,在 React DevTools 中会显示为 Anonymous。建议为组件命名以便调试。

-export default <T,>({
+const TokenSelector = <T,>({
   tokens,
   token,
   switchToken,
   fundFlowDirection,
   disabled = false,
   customizePrefixCls = CUSTOMIZE_PREFIX_CLS,
   hashId = '',
-}: TokenSelectorProps<T>) => {
+}: TokenSelectorProps<T>) => {
   // ... component body
 };
+
+export default TokenSelector;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3a2a0dc and f532296.

⛔ Files ignored due to path filters (2)
  • packages/web3/src/swap-token/icons/swapBg.png is excluded by !**/*.png
  • packages/web3/src/swap-token/icons/swapBgNoAccount.png is excluded by !**/*.png
📒 Files selected for processing (18)
  • packages/web3/global.d.ts (1 hunks)
  • packages/web3/src/index.ts (1 hunks)
  • packages/web3/src/swap-token/CryptoInput.tsx (1 hunks)
  • packages/web3/src/swap-token/PrimaryButton/index.tsx (1 hunks)
  • packages/web3/src/swap-token/PrimaryButton/style/index.tsx (1 hunks)
  • packages/web3/src/swap-token/TokenSelector.tsx (1 hunks)
  • packages/web3/src/swap-token/__tests__/basic.test.tsx (1 hunks)
  • packages/web3/src/swap-token/constant.ts (1 hunks)
  • packages/web3/src/swap-token/demos/basic.tsx (1 hunks)
  • packages/web3/src/swap-token/demos/fee-control.tsx (1 hunks)
  • packages/web3/src/swap-token/demos/mockData.tsx (1 hunks)
  • packages/web3/src/swap-token/demos/quota.tsx (1 hunks)
  • packages/web3/src/swap-token/index.md (1 hunks)
  • packages/web3/src/swap-token/index.tsx (1 hunks)
  • packages/web3/src/swap-token/index.zh-CN.md (1 hunks)
  • packages/web3/src/swap-token/style/index.tsx (1 hunks)
  • packages/web3/src/swap-token/type.ts (1 hunks)
  • packages/web3/src/swap-token/utils/format.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/__tests__/**

📄 CodeRabbit inference engine (.cursor/rules/basic.mdc)

**/__tests__/**: Unit tests should be based on Vitest framework
Test code should be located in the __tests__ folder

Files:

  • packages/web3/src/swap-token/__tests__/basic.test.tsx
**/style/index.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/basic.mdc)

**/style/index.{ts,tsx}: Styles for each component should be located in style/index.ts or style/index.tsx directory within the component's folder
Styling implementation should be based on @ant-design/cssinjs and utilize Ant Design's Design Tokens for custom styling support

Files:

  • packages/web3/src/swap-token/style/index.tsx
  • packages/web3/src/swap-token/PrimaryButton/style/index.tsx
🧠 Learnings (6)
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: This is a multi-package React project built on Ant Design component library, designed to provide Web3 projects with wallet connection capabilities and DApp UI components

Applied to files:

  • packages/web3/src/swap-token/__tests__/basic.test.tsx
  • packages/web3/src/swap-token/demos/quota.tsx
  • packages/web3/src/swap-token/demos/mockData.tsx
  • packages/web3/src/swap-token/PrimaryButton/index.tsx
  • packages/web3/src/swap-token/index.md
  • packages/web3/src/swap-token/CryptoInput.tsx
  • packages/web3/src/index.ts
  • packages/web3/src/swap-token/demos/basic.tsx
  • packages/web3/src/swap-token/index.tsx
  • packages/web3/src/swap-token/demos/fee-control.tsx
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: Applies to **/style/index.{ts,tsx} : Styling implementation should be based on `ant-design/cssinjs` and utilize Ant Design's Design Tokens for custom styling support

Applied to files:

  • packages/web3/src/swap-token/PrimaryButton/index.tsx
  • packages/web3/src/swap-token/style/index.tsx
  • packages/web3/src/index.ts
  • packages/web3/src/swap-token/demos/basic.tsx
  • packages/web3/src/swap-token/index.tsx
  • packages/web3/src/swap-token/PrimaryButton/style/index.tsx
  • packages/web3/src/swap-token/TokenSelector.tsx
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: Applies to packages/web3/*/index.{md,zh-CN.md} : Documentation files should be available as `packages/web3/*/index.md` and `packages/web3/*/index.zh-CN.md` for component documentation and `packages/web3/ethereum` for wagmi package documentation

Applied to files:

  • packages/web3/src/swap-token/index.md
  • packages/web3/src/swap-token/index.zh-CN.md
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: Applies to **/style/index.{ts,tsx} : Styles for each component should be located in `style/index.ts` or `style/index.tsx` directory within the component's folder

Applied to files:

  • packages/web3/src/swap-token/style/index.tsx
  • packages/web3/src/swap-token/PrimaryButton/style/index.tsx
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: UI components are located under `packages/web3`, with other packages containing adapters for different blockchains or foundational packages

Applied to files:

  • packages/web3/src/index.ts
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: Applies to packages/web3/*/demos/** : Demo components should be located in `packages/web3/*/demos` directories

Applied to files:

  • packages/web3/src/swap-token/demos/basic.tsx
🧬 Code graph analysis (9)
packages/web3/src/swap-token/demos/quota.tsx (1)
packages/web3/src/swap-token/demos/mockData.tsx (1)
  • mockTokenPairs (32-77)
packages/web3/src/swap-token/demos/mockData.tsx (2)
packages/web3/src/index.ts (2)
  • SwapTokenConfig (15-15)
  • SwapTokenToken (16-16)
packages/web3/src/swap-token/style/index.tsx (1)
  • SwapTokenToken (8-11)
packages/web3/src/swap-token/PrimaryButton/index.tsx (2)
packages/web3/src/swap-token/PrimaryButton/style/index.tsx (1)
  • useStyle (52-60)
packages/web3/src/swap-token/style/index.tsx (1)
  • useStyle (191-199)
packages/web3/src/swap-token/CryptoInput.tsx (6)
packages/web3/src/swap-token/TokenSelector.tsx (2)
  • T (40-91)
  • TokenSelectorProps (8-23)
packages/web3/src/swap-token/index.tsx (2)
  • Token (437-437)
  • TokenConfig (437-437)
packages/web3/src/swap-token/type.ts (2)
  • Token (1-19)
  • TokenConfig (24-36)
packages/web3/src/swap-token/constant.ts (3)
  • CUSTOMIZE_PREFIX_CLS (7-7)
  • TOKEN_DECIMALS_DEFAULT (2-2)
  • AMOUNT_IN_DECIMALS (4-4)
packages/web3/src/index.ts (1)
  • FundFlowDirection (18-18)
packages/web3/src/swap-token/utils/format.ts (3)
  • formatAmount (70-82)
  • formatValue (42-63)
  • formatBalance (10-20)
packages/web3/src/swap-token/style/index.tsx (3)
packages/web3/src/index.ts (1)
  • SwapTokenToken (16-16)
packages/web3/src/theme/useStyle/index.ts (3)
  • Web3AliasToken (45-64)
  • GenerateStyle (35-38)
  • UseStyleResult (40-43)
packages/web3/src/swap-token/PrimaryButton/style/index.tsx (1)
  • useStyle (52-60)
packages/web3/src/swap-token/demos/basic.tsx (2)
packages/web3/src/swap-token/demos/mockData.tsx (1)
  • mockTokenPairs (32-77)
packages/web3/src/index.ts (1)
  • FundFlowDirection (18-18)
packages/web3/src/swap-token/PrimaryButton/style/index.tsx (2)
packages/web3/src/theme/useStyle/index.ts (2)
  • GenerateStyle (35-38)
  • UseStyleResult (40-43)
packages/web3/src/swap-token/style/index.tsx (1)
  • useStyle (191-199)
packages/web3/src/swap-token/demos/fee-control.tsx (2)
packages/web3/src/swap-token/demos/mockData.tsx (1)
  • mockTokenPairs (32-77)
packages/web3/src/index.ts (1)
  • FundFlowDirection (18-18)
packages/web3/src/swap-token/TokenSelector.tsx (3)
packages/web3/src/swap-token/type.ts (2)
  • TokenConfig (24-36)
  • Token (1-19)
packages/web3/src/index.ts (1)
  • FundFlowDirection (18-18)
packages/web3/src/swap-token/constant.ts (1)
  • CUSTOMIZE_PREFIX_CLS (7-7)
🪛 LanguageTool
packages/web3/src/swap-token/index.md

[style] ~42-~42: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...lance area of the upper / lower input | { upper?: (balance?: SwapTokenToken<T>, token?: SwapTokenConfig<T, SwapTokenToken<T>>) => React.ReactNode; under?: (balance?: SwapTokenToken<T>, token?: SwapTokenConfig<T, SwapTokenToken<T>>) => React.ReactNode } | - | - | | underButtonRender | Rend...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

packages/web3/src/swap-token/index.zh-CN.md

[grammar] ~12-~12: Ensure spelling is correct
Context: ...CryptoInput、代币选择器以及操作按钮的兑换面板,适合在 DApp 中快速集成。尤其适合跨链兑换业务中。 ## 基础用法 </co...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[style] ~41-~41: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... | | extraRenders | 自定义上下两组输入框右侧区域的渲染 | { upper?: (balance?: SwapTokenToken<T>, token?: SwapTokenConfig<T, SwapTokenToken<T>>) => React.ReactNode; under?: (balance?: SwapTokenToken<T>, token?: SwapTokenConfig<T, SwapTokenToken<T>>) => React.ReactNode } | - | - | | underButtonRender | 主按钮下...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: prepare preview
  • GitHub Check: ci
🔇 Additional comments (13)
packages/web3/global.d.ts (1)

13-17: LGTM!

PNG 模块声明符合 TypeScript 资源导入的标准模式,导出类型为 string(URL)是处理图片资源的正确方式,与现有的 SVG 声明保持一致的风格。

packages/web3/src/swap-token/type.ts (1)

21-47: 类型设计合理

TokenConfig 接口和 FundFlowDirection 枚举的设计清晰,支持成对的代币配置和资金流向控制。条件类型 T extends string ? (string extends T ? never : T) : never 有效地强制使用字面量字符串类型,这是一个很好的类型安全实践。

packages/web3/src/index.ts (1)

11-18: LGTM!

SwapToken 组件和相关类型的导出方式与文件中其他组件的导出模式保持一致。类型导出使用 SwapToken 前缀(如 SwapTokenConfigSwapTokenToken)有助于避免命名冲突,符合库的命名规范。

packages/web3/src/swap-token/demos/fee-control.tsx (1)

16-58: LGTM!

Demo 组件结构清晰,很好地展示了 SwapToken 的 API 用法,包括代币选择、资金流向切换、额外描述信息渲染以及数值变更回调等功能。

packages/web3/src/swap-token/__tests__/basic.test.tsx (1)

52-71: LGTM!

测试用例使用了正确的 Vitest 框架和 Testing Library 最佳实践,包括 vi.waitFor 进行异步断言和 vi.fn().mockResolvedValue() 进行 mock。符合编码规范中对单元测试的要求。

packages/web3/src/swap-token/demos/basic.tsx (1)

8-52: 基础用法 demo 逻辑清晰,没有明显问题

  • selectedToken / direction 状态管理简单直观;
  • switchTokenundefined 做了降级处理,避免内部回调传空值时崩溃;
  • extraunderButtonRender 的展示字段也与 mock 数据结构对应。

整体作为文档示例已经足够,当前实现可以保持。

packages/web3/src/swap-token/index.zh-CN.md (1)

10-89: 中文文档与 API 定义基本一致

阅读下来,SwapToken 的属性、SwapTokenConfig / SwapTokenToken / FundFlowDirection 等说明都与英文文档及类型定义对得上,目前没有看到名称、类型或默认值上的偏差。

如果后续实现侧对某些默认值(例如 btnTexttitleshowConnectButton 等)有调整,记得同步更新此表即可。

packages/web3/src/swap-token/index.md (1)

11-90: 英文文档与实现/中文文档对齐良好

SwapTokenSwapTokenConfigSwapTokenToken 以及 FundFlowDirection 各表格字段、类型和默认值与中文文档及组件行为一致,描述也比较清楚,没有明显歧义或遗漏。

目前可以按这个版本收录到站点,如后续 API 有新增/重命名,再一起补充即可。

packages/web3/src/swap-token/PrimaryButton/style/index.tsx (1)

1-59: 样式模块结构符合规范。

样式实现正确地基于 @ant-design/cssinjs,并使用了 Ant Design 的 Design Tokens(如 borderRadiusLGcolorWhite)。组件命名 SwapTokenPrimaryButton 和前缀类的使用与项目中其他样式模块保持一致。

packages/web3/src/swap-token/utils/format.ts (1)

84-96: decimalToBigInt 的 fallback 逻辑设计合理。

使用 viemparseUnits 作为主要实现,并在失败时回退到 Decimal.js 是一个稳健的设计。

packages/web3/src/swap-token/index.tsx (2)

97-435: 组件整体结构清晰,使用 forwardRef 暴露 reset 方法的设计合理。

主要功能包括双向输入、手续费计算、代币切换和交换方向切换,与其他子组件(CryptoInput、TokenSelector、PrimaryButton)的集成良好。


437-437: 缺少 FundFlowDirection 的类型导出。

根据 AI 摘要,FundFlowDirection 应该从该模块导出,但当前只导出了 TokenTokenConfig 类型。请验证该类型在 ./type 文件中的定义和导出状态。

packages/web3/src/swap-token/TokenSelector.tsx (1)

52-61: Handle potential undefined optionToken in options mapping.

The code selects between fromToken and toToken based on fundFlowDirection, but if either field is optional in TokenConfig, optionToken could be undefined when passed to renderTokenLabel. Either validate that the selected field exists before calling renderTokenLabel, or ensure the function handles undefined safely.

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

♻️ Duplicate comments (6)
packages/web3/src/swap-token/index.tsx (3)

159-167: 移除注释掉的代码。

大段注释代码会影响可读性和维护性。如果这些代码不再需要,应该删除;如果是待实现的功能,建议用简洁的 TODO 注释说明并引用 issue。

应用以下修改:

     }, [fundFlowDirection, token]);
 
-    // const invalidInput = React.useMemo(() => {
-    //   const tokenIn = tokenInfo?.find(
-    //     (item) => item?.symbol === tokenPair[0]?.symbol,
-    //   );
-
-    //   const amount = formatAmount({amount: valueIn, decimals: tokenIn?.decimals})
-
-    //   return buttonDisabled || amount.eq(0) || status === 'error';
-    // }, [buttonDisabled, valueIn, tokenInfo, tokenPair, status]);
-
     const invalidInput = React.useMemo(() => {

295-299: useEffect 依赖数组不完整。

handleCalculateFeevalueIn 在 effect 中被使用但未声明为依赖。由于 handleCalculateFee 不是用 useCallback 包装的,每次渲染都会创建新函数,可能导致问题。

在将 handleCalculateFee 包裹在 useCallback 后,应用以下修改:

     React.useEffect(() => {
       if (!token) return;
       // token发生变化时,重新计算手续费
       handleCalculateFee(valueIn);
-    }, [token]);
+    }, [token, handleCalculateFee, valueIn]);

注意:如果只希望在 token 变化时触发,可以保持当前依赖数组,但需要确保 handleCalculateFee 使用最新的 valueIn 值(例如通过 ref)。


266-278: 修复 handleSwapClick 中的重复状态重置。

setButtonLoading(false) 在 catch 块和函数末尾都被调用,导致在正常流程和错误流程中都会执行。应使用 finally 块确保只执行一次。

应用以下修改:

     const handleSwapClick = async () => {
       setButtonLoading(true);
       try {
         if (status === 'error') {
           message.error('Invalid input');
         } else {
           await onButtonClick?.(tokenPair, valueIn, valueOut);
         }
       } catch (error) {
+        console.error('Swap error:', error);
+      } finally {
         setButtonLoading(false);
       }
-      setButtonLoading(false);
     };
packages/web3/src/swap-token/CryptoInput.tsx (3)

138-144: useEffect 缺少依赖项 onStatusChange

根据 React Hooks 规则,onStatusChange 应该包含在依赖数组中。如果该回调可能变化,当前代码可能导致使用过期的回调引用。

应用以下修改:

   React.useEffect(() => {
     if (status === 'error') {
       onStatusChange?.('error');
     } else {
       onStatusChange?.('success');
     }
-  }, [status]);
+  }, [status, onStatusChange]);

注意:如果 onStatusChange 在每次渲染时都会重新创建,请在声明处使用 useCallback 包裹以避免不必要的重新渲染。


185-188: useEffect 缺少依赖项 onChangeValue

onChangeValue 被使用但未在依赖数组中声明。

应用以下修改:

   React.useEffect(() => {
     if (!!status) return;
     onChangeValue?.(inputValue);
-  }, [inputValue, status]);
+  }, [inputValue, status, onChangeValue]);

如果 onChangeValue 在每次渲染时都会重新创建,建议在其声明处使用 useCallback 包裹,或在 effect 内部通过 ref 稳定引用。


367-369: Decimal 构造函数不接受 bigint 类型。

remainQuotabigint 类型,但 Decimal() 构造函数不直接支持 bigint。应先转换为字符串。

应用以下修改:

             {formatAmount({ amount: inputValue, decimals: token?.decimals }).gt(
-              Decimal(remainQuota || 0n),
+              Decimal((remainQuota || 0n).toString()),
             ) && (
🧹 Nitpick comments (4)
packages/web3/src/swap-token/CryptoInput.tsx (2)

94-165: 提取公共验证逻辑以减少代码重复。

isGreaterThanGlobalRemainQuotaisGreaterThanMaxAmount 两个函数共享了大量相似的验证逻辑(长度检查、正则验证、Decimal 转换)。此外,正则验证是多余的,因为 Decimal 转换已经包裹在 try...catch 中,会自动处理无效的数字格式。

建议提取公共验证逻辑到一个辅助函数中:

+const validateAndConvertToDecimal = (
+  value: string,
+  decimals?: number
+): Decimal | null => {
+  if (!value?.length) return null;
+  try {
+    const result = Decimal(value?.replace(/,/g, '') ?? '0').mul(
+      Decimal.pow(10, decimals ?? TOKEN_DECIMALS_DEFAULT),
+    );
+    return result;
+  } catch (error) {
+    return null;
+  }
+};
+
 const isGreaterThanGlobalRemainQuota = (value: string) => {
   if (!isValidMaxInputAmount) return false;
-  try {
-    if (!value?.length) return false;
-    if (!quota?.show) return false;
-    // 验证是否是合法的 Decimal:允许整数、小数和千位分隔符,小数位中不能有千位分隔符
-    const regex = /^(\d{1,3}(,\d{3})*|\d+)(.\d+)?$/;
-    if (!regex.test(value?.replace(/,/g, ''))) {
-      return false;
-    }
-    if (!remainQuota || remainQuota === 0n) return true;
-    const result = Decimal(value?.replace(/,/g, '') ?? '0').mul(
-      Decimal.pow(10, token?.decimals ?? TOKEN_DECIMALS_DEFAULT),
-    );
-    return result.gt(remainQuota);
-  } catch (error) {
-    return false;
-  }
+  if (!quota?.show) return false;
+  if (!remainQuota || remainQuota === 0n) return true;
+  const result = validateAndConvertToDecimal(value, token?.decimals);
+  return result ? result.gt(remainQuota.toString()) : false;
 };

 const isGreaterThanMaxAmount = (value: string) => {
   if (!isValidMaxInputAmount) return false;
-  try {
-    if (!value?.length) return false;
-
-    // 验证是否是合法的 Decimal:允许整数、小数和千位分隔符,小数位中不能有千位分隔符
-    const regex = /^(\d{1,3}(,\d{3})*|\d+)(.\d+)?$/;
-    if (!regex.test(value?.replace(/,/g, ''))) {
-      return false;
-    }
-    if (!maxInputAmountValue) return false;
-    const result = Decimal(value?.replace(/,/g, '') ?? '0').mul(
-      Decimal.pow(10, token?.decimals ?? TOKEN_DECIMALS_DEFAULT),
-    );
-    return result.gt(maxInputAmountValue);
-  } catch (error) {
-    return false;
-  }
+  if (!maxInputAmountValue) return false;
+  const result = validateAndConvertToDecimal(value, token?.decimals);
+  return result ? result.gt(maxInputAmountValue.toString()) : false;
 };

265-330: 考虑重构复杂的 onChange 处理逻辑。

这个 onChange 事件处理器包含了大量复杂的输入验证和格式化逻辑(约 65 行)。为了提升可读性和可维护性,建议将其拆分为命名清晰的辅助函数,例如:

  • handleDecimalPoint - 处理小数点输入
  • handleLeadingZeros - 处理前导零
  • handleDecimalPrecision - 限制小数位数
  • clampToMaxValue - 处理最大值约束

示例重构:

const handleDecimalPoint = (value: string) => {
  if (value === '.') return '0.';
  if (value.split('.').length > 2) return inputValue ?? '';
  return value;
};

const sanitizeInput = (value: string) => {
  const newValue = value.replace(/[^\d,.]/g, '');
  return newValue.length === value.length ? newValue : inputValue ?? '';
};

// 在 onChange 中使用这些辅助函数
onChange={(e) => {
  const sanitized = sanitizeInput(e.target.value);
  const withDecimal = handleDecimalPoint(sanitized);
  // ... 其他验证逻辑
}}
packages/web3/src/swap-token/index.tsx (2)

222-256: handleValueOutChange 包裹在 useCallback 中以优化性能。

该函数作为 prop 传递给 CryptoInput 组件,但在每次渲染时都会重新创建,导致子组件不必要的重新渲染。

应用以下修改:

-    const handleValueOutChange = (value: string) => {
+    const handleValueOutChange = useCallback((value: string) => {
       if (value && !/[^\d,.]/g.test(value)) {
         if (['', ',', '.'].includes(value)) {
           setValueIn('');
           return;
         }
         try {
           const valueOutWithoutComma = value?.replace(/,/g, '') ?? '';
           if (Decimal(valueOutWithoutComma).eq(0) && value?.match(/^[\d.]+$/)) {
             setValueIn('0.00');
             return;
           }
           // 自定义计算
           if (calculateValueIn) {
             const valueIn = calculateValueIn(
               decimalToBigInt(valueOutWithoutComma, token?.decimals || 0),
             );
             if (Decimal(valueIn).lte(0)) {
               setValueIn('0.00');
               return;
             }
             setValueIn(formatValue(Decimal(valueIn).toFixed()) ?? '0.00');
             return;
           }
           // valueIn = valueOut + 跨链桥费用(按目标币种精度)
           const networkFee = Decimal(estFee).div(Decimal(10).pow(Decimal(token?.decimals || 0)));
           const inVal = Decimal(valueOutWithoutComma).add(networkFee);
           setValueIn(formatValue(inVal.toFixed()) ?? '0.00');
         } catch (error) {
           setValueIn('0.00');
         }
       } else {
         setValueIn('0.00');
       }
-    };
+    }, [calculateValueIn, estFee, token]);

282-293: handleCalculateFee 包裹在 useCallback 中。

该函数在 useEffect 中使用且作为 prop 传递给 CryptoInput。应该包裹在 useCallback 中以确保其引用稳定,避免不必要的 effect 重新执行和子组件重新渲染。

应用以下修改:

-    const handleCalculateFee = async (valueIn?: string) => {
+    const handleCalculateFee = useCallback(async (valueIn?: string) => {
       if (!onCalculateFee || !valueIn?.length) {
         return;
       }
       try {
         setIsCalculatingFee(true);
         await onCalculateFee?.(valueIn);
         setIsCalculatingFee(false);
       } catch (error) {
         setIsCalculatingFee(false);
       }
-    };
+    }, [onCalculateFee]);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f532296 and c94235c.

📒 Files selected for processing (2)
  • packages/web3/src/swap-token/CryptoInput.tsx (1 hunks)
  • packages/web3/src/swap-token/index.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: This is a multi-package React project built on Ant Design component library, designed to provide Web3 projects with wallet connection capabilities and DApp UI components

Applied to files:

  • packages/web3/src/swap-token/CryptoInput.tsx
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: Applies to **/style/index.{ts,tsx} : Styling implementation should be based on `ant-design/cssinjs` and utilize Ant Design's Design Tokens for custom styling support

Applied to files:

  • packages/web3/src/swap-token/index.tsx
🧬 Code graph analysis (2)
packages/web3/src/swap-token/CryptoInput.tsx (5)
packages/web3/src/swap-token/TokenSelector.tsx (2)
  • T (40-91)
  • TokenSelectorProps (8-23)
packages/web3/src/swap-token/type.ts (2)
  • Token (1-19)
  • TokenConfig (24-36)
packages/web3/src/swap-token/constant.ts (3)
  • CUSTOMIZE_PREFIX_CLS (7-7)
  • TOKEN_DECIMALS_DEFAULT (2-2)
  • AMOUNT_IN_DECIMALS (4-4)
packages/web3/src/index.ts (1)
  • FundFlowDirection (18-18)
packages/web3/src/swap-token/utils/format.ts (2)
  • formatAmount (70-82)
  • formatValue (42-63)
packages/web3/src/swap-token/index.tsx (6)
packages/web3/src/swap-token/TokenSelector.tsx (2)
  • T (40-91)
  • TokenSelectorProps (8-23)
packages/web3/src/swap-token/type.ts (2)
  • TokenConfig (24-36)
  • Token (1-19)
packages/web3/src/swap-token/constant.ts (1)
  • CUSTOMIZE_PREFIX_CLS (7-7)
packages/web3/src/swap-token/PrimaryButton/style/index.tsx (1)
  • useStyle (52-60)
packages/web3/src/swap-token/style/index.tsx (1)
  • useStyle (191-199)
packages/web3/src/swap-token/utils/format.ts (2)
  • decimalToBigInt (85-96)
  • formatValue (42-63)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: prepare preview
  • GitHub Check: ci
🔇 Additional comments (1)
packages/web3/src/swap-token/index.tsx (1)

181-220: 好的修复!依赖数组现已完整。

handleValueInChangeuseCallback 依赖数组现在已经包含了所有必需的依赖项(calculateValueOuttokenonValueOutChange),之前的问题已得到解决。

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

♻️ Duplicate comments (1)
packages/web3/src/swap-token/index.tsx (1)

269-281: handleSwapClick 中重复重置 loading 且静默吞掉错误,建议用 try/catch/finally 重构

当前实现中:

  • setButtonLoading(false)catch 和函数末尾都会被调用一次,虽然不会出大问题,但属于不必要的重复。
  • 捕获到异常后既不打日志也不向用户暴露任何信息,排查问题会比较困难。

建议改成:

   const handleSwapClick = async () => {
     setButtonLoading(true);
     try {
       if (status === 'error') {
         message.error('Invalid input');
       } else {
         await onButtonClick?.(tokenPair, valueIn, valueOut);
       }
-    } catch (error) {
-      setButtonLoading(false);
-    }
-    setButtonLoading(false);
+    } catch (error) {
+      // 可以按需换成 message.error 等用户提示
+      console.error('Swap error:', error);
+    } finally {
+      setButtonLoading(false);
+    }
   };

这样既避免了重复调用,又能在出错时至少留下可追踪的日志。

🧹 Nitpick comments (2)
packages/web3/src/swap-token/style/index.tsx (1)

14-188: 样式中大量硬编码颜色与固定尺寸,建议更多使用设计令牌和弹性布局

当前样式虽然功能上没问题,但有不少硬编码颜色与固定像素值,例如:

  • 颜色:'#e6ecf4', '#fbfcfd', '#f7f8fa', '#a8a8a8', '#f00' 等(如第 82、88、92、139、160、181、394 行附近)。
  • 尺寸与定位:width: 600, left: 273, top: 198, width: '100px', height: '40px' 等(如第 19、65–68、103–108 行附近)。

这会削弱主题定制(深色模式、品牌色等)和响应式布局的能力。建议:

  • 尽量用 Web3AliasToken / 主题中的设计令牌(例如 colorBorderSecondary, colorBgElevated, boxShadowSecondary 等)替代硬编码颜色和阴影。
  • 对宽度和定位优先使用百分比、maxWidthmargin/gap 等,更少依赖绝对像素和 magic number 坐标,以提升在小屏下的适配性。

可以先从按钮、选择器、错误提示这几处最容易暴露主题差异的区域逐步抽象。
As per coding guidelines, ...

packages/web3/src/swap-token/index.tsx (1)

58-61: onCalculateFee 类型与实际异步用法不一致,建议显式声明为可返回 Promise

SwapInputPropsonCalculateFee 的类型是:

onCalculateFee?: (valueIn?: string) => void;

但在 handleCalculateFee 里你是用 await onCalculateFee?.(valueIn); 来调用它(第 292 行),实际上是按“可能返回 Promise”来使用的。

虽然在 TS 中 await 任意值在类型层面是允许的,但为了让 props 的语义更清晰、更符合实际用法,建议把类型显式写成:

-  /** 开始预估费用 */
-  onCalculateFee?: (valueIn?: string) => void;
+  /** 开始预估费用,可同步也可异步 */
+  onCalculateFee?: (valueIn?: string) => void | Promise<void>;

这样调用方就能直观知道可以返回 Promise,也更容易在 IDE 中获得正确提示。

Also applies to: 283-299

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c94235c and e86c490.

📒 Files selected for processing (5)
  • packages/web3/src/swap-token/CryptoInput.tsx (1 hunks)
  • packages/web3/src/swap-token/PrimaryButton/style/index.tsx (1 hunks)
  • packages/web3/src/swap-token/constant.ts (1 hunks)
  • packages/web3/src/swap-token/index.tsx (1 hunks)
  • packages/web3/src/swap-token/style/index.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/web3/src/swap-token/PrimaryButton/style/index.tsx
  • packages/web3/src/swap-token/constant.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/style/index.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/basic.mdc)

**/style/index.{ts,tsx}: Styles for each component should be located in style/index.ts or style/index.tsx directory within the component's folder
Styling implementation should be based on @ant-design/cssinjs and utilize Ant Design's Design Tokens for custom styling support

Files:

  • packages/web3/src/swap-token/style/index.tsx
🧠 Learnings (3)
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: Applies to **/style/index.{ts,tsx} : Styling implementation should be based on `ant-design/cssinjs` and utilize Ant Design's Design Tokens for custom styling support

Applied to files:

  • packages/web3/src/swap-token/style/index.tsx
  • packages/web3/src/swap-token/index.tsx
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: Applies to **/style/index.{ts,tsx} : Styles for each component should be located in `style/index.ts` or `style/index.tsx` directory within the component's folder

Applied to files:

  • packages/web3/src/swap-token/style/index.tsx
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: This is a multi-package React project built on Ant Design component library, designed to provide Web3 projects with wallet connection capabilities and DApp UI components

Applied to files:

  • packages/web3/src/swap-token/index.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: prepare preview
  • GitHub Check: ci

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

♻️ Duplicate comments (2)
packages/web3/src/swap-token/index.tsx (2)

159-167: 移除注释代码

第 159-167 行仍包含注释掉的 invalidInput 计算逻辑。注释代码影响可读性,应该移除。如果这是待实现的功能,建议用简短的 TODO 注释说明或创建 issue 追踪。


302-306: useEffect 缺少 handleCalculateFee 依赖

第 306 行的 useEffect 在第 305 行调用了 handleCalculateFee,但依赖数组中未包含它。虽然 handleCalculateFee 通过 useCallback 保持稳定,但根据 React Hooks 规则,仍应将其添加到依赖数组中。

   React.useEffect(() => {
     if (!token) return;
     // token发生变化时,重新计算手续费
     handleCalculateFee(valueIn);
-  }, [token, valueIn]);
+  }, [token, valueIn, handleCalculateFee]);
🧹 Nitpick comments (1)
packages/web3/src/swap-token/CryptoInput.tsx (1)

215-311: 考虑提取输入验证辅助函数

输入处理逻辑非常完善,涵盖了各种边界情况(小数点、千位分隔符、前导零等)。当前实现功能正确,但为了提高可维护性和可测试性,可以考虑将 normalizeDotInputsanitizeAllowedCharactersnormalizeAllZeroInteger 等辅助函数提取到独立的 utils 文件中。

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e86c490 and 3080aba.

📒 Files selected for processing (5)
  • packages/web3/src/swap-token/CryptoInput.tsx (1 hunks)
  • packages/web3/src/swap-token/PrimaryButton/index.tsx (1 hunks)
  • packages/web3/src/swap-token/index.tsx (1 hunks)
  • packages/web3/src/swap-token/type.ts (1 hunks)
  • packages/web3/src/swap-token/utils/format.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/web3/src/swap-token/type.ts
  • packages/web3/src/swap-token/PrimaryButton/index.tsx
  • packages/web3/src/swap-token/utils/format.ts
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: This is a multi-package React project built on Ant Design component library, designed to provide Web3 projects with wallet connection capabilities and DApp UI components

Applied to files:

  • packages/web3/src/swap-token/index.tsx
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: Applies to **/style/index.{ts,tsx} : Styling implementation should be based on `ant-design/cssinjs` and utilize Ant Design's Design Tokens for custom styling support

Applied to files:

  • packages/web3/src/swap-token/index.tsx
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: UI components are located under `packages/web3`, with other packages containing adapters for different blockchains or foundational packages

Applied to files:

  • packages/web3/src/swap-token/index.tsx
🧬 Code graph analysis (1)
packages/web3/src/swap-token/CryptoInput.tsx (6)
packages/web3/src/swap-token/TokenSelector.tsx (2)
  • T (40-91)
  • TokenSelectorProps (8-23)
packages/web3/src/swap-token/index.tsx (2)
  • Token (396-396)
  • TokenConfig (396-396)
packages/web3/src/swap-token/type.ts (2)
  • Token (3-21)
  • TokenConfig (26-38)
packages/web3/src/swap-token/constant.ts (3)
  • CUSTOMIZE_PREFIX_CLS (7-7)
  • AMOUNT_IN_DECIMALS (4-4)
  • TOKEN_DECIMALS_DEFAULT (2-2)
packages/web3/src/index.ts (1)
  • FundFlowDirection (18-18)
packages/web3/src/swap-token/utils/format.ts (3)
  • formatAmount (70-82)
  • formatValue (42-63)
  • formatBalance (10-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: prepare preview
  • GitHub Check: ci
🔇 Additional comments (10)
packages/web3/src/swap-token/CryptoInput.tsx (5)

1-48: 类型定义和接口设计良好

导入和 Props 接口定义清晰完整,泛型 T 的使用保证了类型安全。特别是 maxInputAmountquota 的接口设计合理地处理了 bigint 类型。


130-189: bigint 类型转换已正确处理

第 138 行和第 185 行现在正确地使用 Decimal(remainQuota.toString())Decimal(maxInputAmountValue.toString()) 将 bigint 转换为字符串后再进行比较,避免了 Decimal.js 不支持 bigint 的问题。


144-174: 依赖数组已完善

status 的 useMemo(第 166 行)和 onStatusChange 的 useEffect(第 174 行)的依赖数组现在都已完整,包含了所有使用的外部变量,避免了过时闭包问题。


209-212: useEffect 依赖数组正确

第 212 行的依赖数组现在包含了 onChangeValue,确保回调变化时 effect 能正确响应。


371-472: 渲染逻辑结构清晰

组件的渲染部分组织良好,条件渲染逻辑清晰,正确集成了 TokenSelector 和余额显示功能。配额提示的显示逻辑(第 415-454 行)合理地处理了全局限额的 UI 反馈。

packages/web3/src/swap-token/index.tsx (5)

181-220: useCallback 依赖数组已完善

handleValueInChange 的依赖数组(第 219 行)现在包含了所有捕获的外部值:estFeeRateestFeetokencalculateValueOutonValueOutChange,避免了过时闭包问题。


222-259: handleValueOutChange 正确使用 useCallback

该函数现在正确地使用 useCallback 包装,依赖数组包含了 estFeetokencalculateValueIn,确保了稳定的引用以避免不必要的子组件重新渲染。


269-282: 错误处理逻辑正确

handleSwapClick 现在使用 try-catch-finally 模式,确保 setButtonLoading(false) 只在 finally 块中调用一次,并且错误被正确捕获和记录(第 278 行)。


308-393: 组件组合和渲染逻辑清晰

主渲染逻辑组织良好,两个 CryptoInput 组件的配置清晰,特别是第二个 CryptoInput 正确地反转了 fundFlowDirection(第 353-357 行)并禁用了最大值校验(第 349 行),符合"现金流出"的语义。


396-398: 类型导出使用别名是良好实践

使用 SwapTokenTokenSwapTokenConfig 别名重新导出类型是良好的实践,避免了命名冲突并提供了更清晰的公共 API。

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

♻️ Duplicate comments (1)
packages/web3/src/swap-token/index.tsx (1)

309-313: useEffect 依赖数组应包含 handleCalculateFee

虽然此问题在过往审查中被标记为已在提交 c94235c 中解决,但当前代码中 useEffect 的依赖数组仍只包含 [token, valueIn],而实际使用了 handleCalculateFee。根据 React Hooks 规则,所有在 effect 中使用的非稳定值都应声明为依赖。

由于 handleCalculateFee 已用 useCallback 包裹且仅依赖 onCalculateFee,它在大多数场景下是稳定的。但如果 onCalculateFeetokenvalueIn 未变化时发生更新,effect 将使用过期的回调。

建议将 handleCalculateFee 添加到依赖数组:

   React.useEffect(() => {
     if (!token) return;
     // token发生变化时,重新计算手续费
     handleCalculateFee(valueIn);
-  }, [token, valueIn]);
+  }, [token, valueIn, handleCalculateFee]);

这样可以确保在所有相关值变化时 effect 都能正确重新执行,符合 React Hooks 的最佳实践。

🧹 Nitpick comments (1)
packages/web3/src/swap-token/index.tsx (1)

162-171: 移除注释代码以提高可读性。

虽然此前的审查评论标记此问题已在提交 c94235c 中解决,但代码中仍保留了注释掉的 invalidInput 计算逻辑。即使是作为参考,保留注释代码也会降低代码可读性。建议完全删除这段注释,如需保留逻辑说明可改用简洁的 TODO 注释或在文档中记录。

-    // const invalidInput = React.useMemo(() => {
-    //   const tokenIn = tokenInfo?.find(
-    //     (item) => item?.symbol === tokenPair[0]?.symbol,
-    //   );
-
-    //   const amount = formatAmount({amount: valueIn, decimals: tokenIn?.decimals})
-
-    //   return buttonDisabled || amount.eq(0) || status === 'error';
-    // }, [buttonDisabled, valueIn, tokenInfo, tokenPair, status]);
-
     const invalidInput = React.useMemo(() => {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3080aba and c643810.

📒 Files selected for processing (4)
  • packages/web3/src/swap-token/CryptoInput.tsx (1 hunks)
  • packages/web3/src/swap-token/PrimaryButton/index.tsx (1 hunks)
  • packages/web3/src/swap-token/index.tsx (1 hunks)
  • packages/web3/src/swap-token/utils/format.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/web3/src/swap-token/PrimaryButton/index.tsx
  • packages/web3/src/swap-token/utils/format.ts
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: This is a multi-package React project built on Ant Design component library, designed to provide Web3 projects with wallet connection capabilities and DApp UI components

Applied to files:

  • packages/web3/src/swap-token/index.tsx
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: Applies to **/style/index.{ts,tsx} : Styling implementation should be based on `ant-design/cssinjs` and utilize Ant Design's Design Tokens for custom styling support

Applied to files:

  • packages/web3/src/swap-token/index.tsx
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: UI components are located under `packages/web3`, with other packages containing adapters for different blockchains or foundational packages

Applied to files:

  • packages/web3/src/swap-token/index.tsx
🧬 Code graph analysis (1)
packages/web3/src/swap-token/CryptoInput.tsx (6)
packages/web3/src/swap-token/index.tsx (2)
  • Token (403-403)
  • TokenConfig (403-403)
packages/web3/src/swap-token/type.ts (2)
  • Token (3-21)
  • TokenConfig (26-38)
packages/web3/src/crypto-input/index.tsx (1)
  • CryptoInput (52-183)
packages/web3/src/swap-token/constant.ts (1)
  • CUSTOMIZE_PREFIX_CLS (7-7)
packages/web3/src/index.ts (1)
  • FundFlowDirection (18-18)
packages/web3/src/swap-token/utils/format.ts (3)
  • formatAmount (71-83)
  • formatValue (43-64)
  • formatBalance (10-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: prepare preview
  • GitHub Check: ci
🔇 Additional comments (7)
packages/web3/src/swap-token/CryptoInput.tsx (4)

95-129: 输入校验逻辑完善。

isValidValue 函数正确处理了整数、小数和千分位分隔符的校验,逻辑清晰且覆盖了各种边界情况。


132-191: 校验函数实现正确,过往问题已修复。

isGreaterThanGlobalRemainQuotaisGreaterThanMaxAmount 正确地将 bigint 转换为字符串后再传给 Decimal,避免了类型错误。status 的依赖数组也已包含 isValidMaxInputAmount,确保配置变更时状态能正确更新。


217-314: 输入处理逻辑结构清晰。

通过将复杂的输入校验和格式化逻辑拆分为多个单一职责的辅助函数(normalizeDotInputsanitizeAllowedCharactersnormalizeAllZeroInteger 等),handleInputChange 的可读性和可维护性都得到了显著提升。这是处理复杂输入逻辑的良好实践。


316-474: 渲染逻辑清晰,状态处理得当。

组件正确处理了焦点、错误状态下的文本颜色变化,余额展示逻辑区分了登录和未登录状态,全局限额提示也能根据配置正确显示。整体渲染结构合理。

packages/web3/src/swap-token/index.tsx (3)

185-224: handleValueInChange 依赖数组完整。

该回调的依赖数组已包含所有捕获的外部变量(estFeeRateestFeetokencalculateValueOutonValueOutChange),过往审查中标记的依赖缺失问题已得到解决。


227-273: 输出值变化处理和币种切换逻辑正确。

handleValueOutChange 的依赖数组完整,handleSwap 函数正确处理了资金流向切换和输入输出值互换的逻辑。


315-405: 组件渲染结构合理,功能完整。

主渲染逻辑正确组合了两个 CryptoInput 组件,分别处理输入和输出。按钮的禁用逻辑全面(包括 invalidInputisCalculatingFeebuttonDisabledshowConnectButton),交换图标的交互行为也根据 swap 属性正确控制。类型导出清晰,组件整体实现完善。

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: 1

🧹 Nitpick comments (2)
packages/web3/src/swap-token/CryptoInput.tsx (2)

135-147: 提取重复的输入验证逻辑

isGreaterThanGlobalRemainQuotaisGreaterThanMaxAmount 两个函数包含大量相似的验证逻辑(检查长度、调用 isValidValue、格式化金额等)。建议提取共同的验证逻辑到独立的辅助函数中,提高代码可维护性。

参考实现:

// 通用的金额比较辅助函数
const isAmountGreaterThan = (value: string, compareTarget: bigint | undefined, enabled: boolean): boolean => {
  if (!enabled || !value?.length || !compareTarget) return false;
  if (!isValidValue(value)) return false;
  
  try {
    const result = formatAmount({ amount: value, decimals: token?.decimals });
    return result.gt(Decimal(compareTarget.toString()));
  } catch (error) {
    return false;
  }
};

const isGreaterThanGlobalRemainQuota = (value: string) => {
  if (!quota?.show || remainQuota === 0n) return !remainQuota;
  return isAmountGreaterThan(value, remainQuota, isValidMaxInputAmount);
};

const isGreaterThanMaxAmount = (value: string) => {
  return isAmountGreaterThan(value, maxInputAmountValue, isValidMaxInputAmount);
};

Also applies to: 190-202


276-325: 拆分过长的 handleInputChange 函数

handleInputChange 函数长达 50 行,包含多个职责:格式化处理、边界检查、小数位限制、前导零处理、最大值限制等。建议将其拆分为更小的、职责单一的辅助函数,以提高可读性和可维护性。

当前的实现虽然功能正确,但过于冗长,难以理解和测试。已有的辅助函数(normalizeDotInputhasMultipleDecimalPoints 等)是好的开始,但主函数仍然过于复杂。

建议进一步重构,将验证和格式化逻辑分离:

const handleInputChange = (value: string) => {
  // 1. 基本格式化
  const normalized = normalizeBasicInput(value);
  if (normalized === null) {
    setInputValue(inputValue ?? '');
    return;
  }
  
  // 2. 小数和整数部分处理
  const formatted = formatIntegerAndDecimal(normalized);
  
  // 3. 最大值检查
  const final = enforceMaxAmount(formatted);
  
  setInputValue(final);
};
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c643810 and a89e3c3.

📒 Files selected for processing (3)
  • packages/web3/src/swap-token/CryptoInput.tsx (1 hunks)
  • packages/web3/src/swap-token/TokenSelector.tsx (1 hunks)
  • packages/web3/src/swap-token/index.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: This is a multi-package React project built on Ant Design component library, designed to provide Web3 projects with wallet connection capabilities and DApp UI components

Applied to files:

  • packages/web3/src/swap-token/CryptoInput.tsx
  • packages/web3/src/swap-token/index.tsx
📚 Learning: 2025-11-25T09:58:18.233Z
Learnt from: CR
Repo: ant-design/ant-design-web3 PR: 0
File: .cursor/rules/basic.mdc:0-0
Timestamp: 2025-11-25T09:58:18.233Z
Learning: Applies to **/style/index.{ts,tsx} : Styling implementation should be based on `ant-design/cssinjs` and utilize Ant Design's Design Tokens for custom styling support

Applied to files:

  • packages/web3/src/swap-token/index.tsx
  • packages/web3/src/swap-token/TokenSelector.tsx
🧬 Code graph analysis (2)
packages/web3/src/swap-token/CryptoInput.tsx (6)
packages/web3/src/swap-token/TokenSelector.tsx (2)
  • T (41-92)
  • TokenSelectorProps (9-24)
packages/web3/src/swap-token/index.tsx (2)
  • Token (404-404)
  • TokenConfig (404-404)
packages/web3/src/swap-token/type.ts (2)
  • Token (3-21)
  • TokenConfig (26-38)
packages/web3/src/swap-token/constant.ts (1)
  • CUSTOMIZE_PREFIX_CLS (7-7)
packages/web3/src/index.ts (1)
  • FundFlowDirection (18-18)
packages/web3/src/swap-token/utils/format.ts (3)
  • formatAmount (71-83)
  • formatValue (43-64)
  • formatBalance (10-20)
packages/web3/src/swap-token/TokenSelector.tsx (3)
packages/web3/src/swap-token/type.ts (2)
  • TokenConfig (26-38)
  • Token (3-21)
packages/web3/src/index.ts (1)
  • FundFlowDirection (18-18)
packages/web3/src/swap-token/constant.ts (1)
  • CUSTOMIZE_PREFIX_CLS (7-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: prepare preview
  • GitHub Check: ci
🔇 Additional comments (7)
packages/web3/src/swap-token/CryptoInput.tsx (1)

1-488: 整体代码质量良好,核心功能实现完整

CryptoInput 组件整体架构合理,功能完善:

  • 输入验证逻辑严谨,支持整数、小数和千分位
  • 全局限额和最大值校验机制完善
  • 与 TokenSelector 集成良好
  • 状态管理和事件处理得当

已正确修复了之前评审中指出的关键问题(bigint 转字符串、useEffect 依赖等)。

packages/web3/src/swap-token/TokenSelector.tsx (1)

1-92: 代码实现简洁清晰,符合最佳实践

TokenSelector 组件设计合理:

  • 泛型类型参数使用得当,支持类型安全的 token 操作
  • useMemo 正确优化了 options 的计算,依赖数组完整
  • 根据 fundFlowDirection 正确选择 fromTokentoToken
  • 单个 token 时渲染静态标签,多个 token 时渲染下拉选择器,用户体验良好
  • renderTokenLabel 作为独立导出函数,便于复用
packages/web3/src/swap-token/index.tsx (5)

179-218: 输入值变化处理逻辑完善,依赖正确

handleValueInChange 回调函数:

  • 正确使用 useCallback 优化性能
  • 依赖数组完整,包含所有使用的外部值
  • 支持自定义计算函数 calculateValueOut 和默认的手续费计算
  • 异常处理得当,防止程序崩溃

221-258: 输出值变化处理逻辑完善

handleValueOutChange 回调函数实现合理:

  • 使用 useCallback 避免不必要的重渲染
  • 支持自定义 calculateValueIn 和默认的网络费用计算
  • 边界条件处理完善(零值、空值等)

287-301: 手续费计算函数实现正确

handleCalculateFee 使用 useCallback 包裹,依赖数组只包含 onCalculateFee,符合预期。Loading 状态管理完善,正确处理了成功和异常两种情况。


310-314: useEffect 依赖完整,副作用处理正确

Effect 在 token 或 valueIn 变化时重新计算手续费,依赖数组包含了所有使用的值(tokenvalueInhandleCalculateFee)。由于 handleCalculateFee 已经用 useCallback 包裹,不会导致无限循环。


1-406: SwapToken 组件架构优秀,功能完整

主组件设计亮点:

  • 完善的类型定义(SwapInputProps、SwapInputRef、SwapTokenComponent)
  • 使用 forwardRef 暴露 reset 方法,便于父组件控制
  • 双向输入联动逻辑清晰(handleValueInChange ↔ handleValueOutChange)
  • 支持自定义计算函数和默认计算逻辑
  • 手续费自动计算机制合理
  • 按钮状态管理完善(invalidInput、loading、disabled 等)
  • 良好的扩展性(extra、extraRenders、underButtonRender 等插槽)

之前评审中的关键问题均已修复:

  • useCallback 依赖完整
  • 异常处理使用 finally 块
  • 移除了注释代码

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 (2)
packages/web3/src/swap-token/CryptoInput.tsx (2)

91-96: maxInputAmountValue 的三元表达式嵌套较深,建议考虑简化。

当前逻辑正确,但嵌套三元表达式可读性较差。可考虑提取为独立函数或使用 if-else 结构。

-  const maxInputAmountValue =
-    maxInputAmount?.symbol === token?.symbol
-      ? (balance?.amount ?? 0n) > BigInt(maxInputAmount?.amount || 0n)
-        ? maxInputAmount?.amount || 0n
-        : balance?.amount
-      : balance?.amount;
+  const maxInputAmountValue = React.useMemo(() => {
+    if (maxInputAmount?.symbol !== token?.symbol) {
+      return balance?.amount;
+    }
+    const balanceAmt = balance?.amount ?? 0n;
+    const maxAmt = maxInputAmount?.amount ?? 0n;
+    return balanceAmt > maxAmt ? maxAmt : balanceAmt;
+  }, [maxInputAmount, token?.symbol, balance?.amount]);

320-328: 建议使用设计令牌替代硬编码颜色值。

#FF4D4F#326CFF 等硬编码颜色值可考虑使用 Ant Design 的主题令牌(如 token.colorErrortoken.colorPrimary),以保持与设计系统的一致性。

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a89e3c3 and ec95705.

📒 Files selected for processing (1)
  • packages/web3/src/swap-token/CryptoInput.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/web3/src/swap-token/CryptoInput.tsx (5)
packages/web3/src/swap-token/TokenSelector.tsx (2)
  • T (41-92)
  • TokenSelectorProps (9-24)
packages/web3/src/swap-token/type.ts (2)
  • Token (3-21)
  • TokenConfig (26-38)
packages/web3/src/swap-token/constant.ts (2)
  • CUSTOMIZE_PREFIX_CLS (7-7)
  • AMOUNT_IN_DECIMALS (4-4)
packages/web3/src/index.ts (1)
  • FundFlowDirection (18-18)
packages/web3/src/swap-token/utils/format.ts (2)
  • formatAmount (71-83)
  • formatValue (43-64)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: ci
  • GitHub Check: prepare preview
🔇 Additional comments (4)
packages/web3/src/swap-token/CryptoInput.tsx (4)

1-52: 接口定义和导入结构清晰。

接口文档完善,泛型约束合理,类型定义正确。


98-132: 金额校验逻辑完整。

isValidValue 函数正确处理了整数、小数和千分位分隔符的各种边界情况。


268-317: 输入处理逻辑重构良好。

handleInputChange 通过调用多个职责单一的辅助函数(normalizeDotInputsanitizeAllowedCharactersnormalizeLeadingZero 等)实现了清晰的验证流程,可读性和可维护性较好。


377-478: 组件渲染结构清晰。

JSX 布局合理,正确使用了 classNames 进行样式管理,全局限额提示区域的条件渲染逻辑正确。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Independent new features size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant