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

Optimize: evm params #244

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Optimize: evm params #244

wants to merge 4 commits into from

Conversation

ByteZhang1024
Copy link
Contributor

@ByteZhang1024 ByteZhang1024 commented Nov 5, 2024

Summary by CodeRabbit

  • 新功能
    • 引入了多个新的组件,如 ApiButtonApiCheckboxApiComboboxApiFieldApiFormApiJsonEditApiSelectorApiSwitchApiTextAreaApiSeparator,增强了表单功能。
    • 新增了 WalletWatchAssetWalletWatchAssetERC721WalletWatchAssetERC1155 组件,用于管理以太坊资产。
    • 添加了命令面板 UI 组件,支持用户交互。
    • 引入了 ApiAutoTextAreaApiText 组件,提供动态文本区域和文本显示功能。
    • 新增了 TabCard 组件,支持创建选项卡界面。
    • 增强了对 TRC20 和 CRC20 资产的管理功能,提供更好的用户体验。
    • 新增了 ApiSwitchApiCheckbox 组件,提供更灵活的表单选项。
    • 新增了 Tooltip 组件,增强了用户界面的提示功能。
  • 依赖更新
    • 更新了多个依赖包的版本,确保兼容性和引入新特性。

Copy link

coderabbitai bot commented Nov 5, 2024

Walkthrough

此次更改引入了多个新的 React 组件和功能,主要集中在 API 表单的状态管理和用户交互上。新组件包括 ApiButtonApiCheckboxApiComboboxApiFieldApiForm 等,旨在增强表单的功能性和可用性。此外,状态管理也得到了改进,通过 Jotai 库实现了表单状态的集中管理。还新增了与以太坊相关的常量和 JSON 文件,支持区块链网络和合约交互。

Changes

文件路径 更改摘要
packages/example/components/ApiActuator/ApiPayloadProvider.tsx tryFormatJson 函数导出,使其可在其他模块中访问。
packages/example/components/ApiForm/ApiButton.tsx 新增组件 ApiButton,支持按钮点击和表单验证。
packages/example/components/ApiForm/ApiCheckbox.tsx 新增组件 ApiCheckbox,用于处理复选框状态。
packages/example/components/ApiForm/ApiCombobox.tsx 新增组件 ApiCombobox,实现可定制的组合框功能。
packages/example/components/ApiForm/ApiField.tsx 新增组件 ApiInputApiField,用于输入字段和标签的处理。
packages/example/components/ApiForm/ApiForm.tsx 新增组件 ApiForm,管理表单状态并提供上下文。
packages/example/components/ApiForm/ApiJsonEdit.tsx 新增组件 JsonEditApiJsonEdit,用于 JSON 编辑。
packages/example/components/ApiForm/ApiSelector.tsx 新增组件 ApiSelector,实现选择器功能。
packages/example/components/ApiForm/ApiSeparator.tsx 新增组件 ApiSeparator,用于分隔表单元素。
packages/example/components/ApiForm/ApiSwitch.tsx 新增组件 ApiSwitch,用于开关状态管理。
packages/example/components/ApiForm/ApiTextArea.tsx 新增组件 ApiTextArea,用于文本区域输入。
packages/example/components/ApiForm/hooks/useValidation.ts 新增自定义钩子 useValidation,处理表单验证逻辑。
packages/example/components/ApiForm/index.ts 新增 Form 组件,整合多个表单组件。
packages/example/components/ApiForm/store.ts 新增状态管理解决方案,定义 FormStore 接口和相关函数。
packages/example/components/ApiForm/types.ts 新增多个 TypeScript 接口,定义表单字段和状态。
packages/example/components/chains/ethereum/case/contract/SampleContracts.ts 新增常量,映射区块链网络和合约地址。
packages/example/components/chains/ethereum/case/contract/contract1155.json 新增 ERC-1155 合约的 ABI 和字节码。
packages/example/components/chains/ethereum/case/contract/contract721.json 新增 ERC-721 合约的 ABI 和字节码。
packages/example/components/chains/ethereum/case/transfer/malformed.ts 新增测试用例,模拟各种格式错误的交易场景。
packages/example/components/chains/ethereum/case/transfer/malicious.ts 新增模拟恶意交易的功能。
packages/example/components/chains/ethereum/example.tsx 新增与以太坊资产管理相关的组件。
packages/example/components/chains/ethereum/utils.ts parseChainId 函数导出,允许其他模块访问。
packages/example/components/context/ContextFactory.tsx 新增上下文管理系统,支持独立字段的状态管理。
packages/example/components/ui/command.tsx 新增命令面板组件,支持用户交互。
packages/example/components/ui/tabs.tsx 新增选项卡组件,基于 Radix UI 实现。
packages/example/package.json 更新多个依赖包的版本,确保兼容性。

🪧 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 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 or 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

socket-security bot commented Nov 6, 2024

🚨 Potential security issues detected. Learn more about Socket for GitHub ↗︎

To accept the risk, merge this PR and you will not be notified again.

Alert Package NoteSourceCI
Critical CVE npm/@babel/[email protected] ⚠︎

View full report↗︎

Next steps

What is a critical CVE?

Contains a Critical Common Vulnerability and Exposure (CVE).

Remove or replace dependencies that include known critical CVEs. Consumers can use dependency overrides or npm audit fix --force to remove vulnerable dependencies.

Take a deeper look at the dependency

Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support [AT] socket [DOT] dev.

Remove the package

If you happen to install a dependency that Socket reports as Known Malware you should immediately remove it and select a different dependency. For other alert types, you may may wish to investigate alternative packages or consider if there are other ways to mitigate the specific risk posed by the dependency.

Mark a package as acceptable risk

To ignore an alert, reply with a comment starting with @SocketSecurity ignore followed by a space separated list of ecosystem/package-name@version specifiers. e.g. @SocketSecurity ignore npm/[email protected] or ignore all packages with @SocketSecurity ignore-all

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.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

🛑 Comments failed to post (98)
packages/example/components/ApiForm/ApiSeparator.tsx (1)

4-6: 🧹 Nitpick (assertive)

建议添加 Props 类型定义

虽然目前组件没有接收任何属性,但为了未来的可扩展性和代码可维护性,建议添加 Props 接口定义。

建议按照以下方式修改:

+interface ApiSeparatorProps {}
-export const ApiSeparator = memo(() => {
+export const ApiSeparator = memo<ApiSeparatorProps>(() => {
    return <Separator />
});
📝 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.

interface ApiSeparatorProps {}
export const ApiSeparator = memo<ApiSeparatorProps>(() => {
    return <Separator />
});
packages/example/components/chains/ethereum/utils.ts (1)

1-2: 🧹 Nitpick (assertive)

建议使用 Number.parseInt 替代全局 parseInt

为了保持与 ES2015 的一致性,建议使用 Number 命名空间下的方法。

建议按如下方式修改代码:

export function parseChainId(chainId: string | undefined): number {
-  return parseInt(chainId?.startsWith('0x') ? chainId ?? '0' : `0x${chainId}`, 16);
+  return Number.parseInt(chainId?.startsWith('0x') ? chainId ?? '0' : `0x${chainId}`, 16);
}
📝 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.

export function parseChainId(chainId: string | undefined): number {
  return Number.parseInt(chainId?.startsWith('0x') ? chainId ?? '0' : `0x${chainId}`, 16);
🧰 Tools
🪛 Biome

[error] 2-2: Use Number.parseInt instead of the equivalent global.

ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.

(lint/style/useNumberNamespace)

packages/example/components/ApiForm/types.ts (3)

10-14: 🧹 Nitpick (assertive)

建议优化结果字段的类型定义

当前 result 字段使用 string 类型可能过于简单,建议使用更具体的类型来处理不同的结果状态。

建议修改如下:

-  result: string;
+  result: {
+    status: 'success' | 'error' | 'idle';
+    message: string;
+  };
📝 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.

export interface IApiFormState<T> {
  fields: Record<string, IFormField<T>>;
  loading: boolean;
  result: {
    status: 'success' | 'error' | 'idle';
    message: string;
  };
}

16-20: 🧹 Nitpick (assertive)

验证函数返回类型可以更明确

验证函数的返回类型可以更具体,建议使用专门的错误类型。

建议修改如下:

-  validator?: (values: Record<string, string>) => string | undefined;
+  validator?: (values: Record<string, string>) => {
+    field: string;
+    message: string;
+  } | undefined;
📝 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.

// 新增: 验证规则类型
export interface IValidationRule {
  fields: string[]; // 需要验证的字段
  validator?: (values: Record<string, string>) => {
    field: string;
    message: string;
  } | undefined; // 自定义验证函数
}

1-8: 🧹 Nitpick (assertive)

接口设计清晰简洁!

接口结构合理,泛型使用得当。不过建议考虑将 extra 字段的类型定义得更具体,避免使用 any

建议修改如下:

-  extra?: Record<string, any>;
+  extra?: Record<string, string | number | boolean>;
📝 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.

export interface IFormField<T> {
  value: T;
  name?: string;
  disabled?: boolean;
  error?: string;
  required?: boolean;
  extra?: Record<string, string | number | boolean>;
}
packages/example/components/chains/suiStandard/utils.ts (1)

7-7: 🧹 Nitpick (assertive)

导入的 CoinStruct 类型未被使用

代码中导入了 CoinStruct 类型,但在整个文件中都没有使用到这个类型。如果确实不需要,建议删除这个导入。

-import type { CoinStruct } from '@mysten/sui.js/client';
📝 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.


packages/example/components/ui/tooltip.tsx (2)

20-20: 🧹 Nitpick (assertive)

建议拆分长字符串类名

当前的类名字符串过长,不易维护。建议将其拆分为多个常量或使用配置对象。

建议重构为:

-      "z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
+      cn(
+        "z-50 overflow-hidden rounded-md border",
+        "bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md",
+        "animate-in fade-in-0 zoom-in-95",
+        "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
+        "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
+        "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2"
+      ),

Committable suggestion skipped: line range outside the PR's diff.


12-26: 🧹 Nitpick (assertive)

建议优化TooltipContent组件的类型定义

组件实现基本正确,但可以通过以下方式改进:

  1. 考虑为sideOffset添加类型注解
  2. 建议添加适当的JSDoc注释说明组件用途

建议按如下方式优化代码:

+/**
+ * 工具提示内容组件
+ * @param props - 组件属性
+ * @param ref - 转发的ref
+ */
 const TooltipContent = React.forwardRef<
   React.ElementRef<typeof TooltipPrimitive.Content>,
   React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
->(({ className, sideOffset = 4, ...props }, ref) => (
+>(({ className, sideOffset = 4 as number, ...props }, ref) => (
📝 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.

/**
 * 工具提示内容组件
 * @param props - 组件属性
 * @param ref - 转发的ref
 */
const TooltipContent = React.forwardRef<
  React.ElementRef<typeof TooltipPrimitive.Content>,
  React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
>(({ className, sideOffset = 4 as number, ...props }, ref) => (
  <TooltipPrimitive.Content
    ref={ref}
    sideOffset={sideOffset}
    className={cn(
      "z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
      className
    )}
    {...props}
  />
))
TooltipContent.displayName = TooltipPrimitive.Content.displayName
.github/workflows/deploy-dapp-example-web.yml (1)

28-28: 🧹 Nitpick (assertive)

建议添加环境变量用途说明

建议在工作流文件中添加注释,说明 OKLINK_API_KEY 的具体用途,以便其他开发者理解。

+          # OKLink API key for blockchain data queries
           echo "NEXT_PUBLIC_OKLINK_API_KEY=${{ secrets.OKLINK_API_KEY }}" >> ./packages/example/.env
📝 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.

          # OKLink API key for blockchain data queries
          echo "NEXT_PUBLIC_OKLINK_API_KEY=${{ secrets.OKLINK_API_KEY }}" >> ./packages/example/.env
packages/example/components/ApiForm/ApiSwitch.tsx (5)

50-52: 🧹 Nitpick (assertive)

改进错误信息展示

错误信息的样式可以更加突出,建议添加图标和更好的视觉反馈。

   {field.error && (
-      <div className="text-sm text-red-500">{field.error}</div>
+      <div className="flex items-center gap-1 text-sm text-red-500">
+        <span className="i-lucide-alert-circle" />
+        <span>{field.error}</span>
+      </div>
   )}
📝 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.

    {field.error && (
      <div className="flex items-center gap-1 text-sm text-red-500">
        <span className="i-lucide-alert-circle" />
        <span>{field.error}</span>
      </div>
    )}

6-10: 🧹 Nitpick (assertive)

接口定义清晰但缺少必要的文档注释

建议为接口及其属性添加 JSDoc 注释,以提供更好的开发体验。

+/**
+ * ApiSwitch 组件的属性接口
+ */
 export interface ApiSwitchProps {
+  /** 开关的唯一标识符 */
   id: string;
+  /** 开关的标签文本 */
   label?: string;
+  /** 开关的默认选中状态 */
   defaultChecked?: boolean;
 }
📝 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.

/**
 * ApiSwitch 组件的属性接口
 */
export interface ApiSwitchProps {
  /** 开关的唯一标识符 */
  id: string;
  /** 开关的标签文本 */
  label?: string;
  /** 开关的默认选中状态 */
  defaultChecked?: boolean;
}

39-39: ⚠️ Potential issue

修复类型安全问题

onCheckedChange 回调需要明确的类型定义。

-      onCheckedChange={(e) => setField({ ...field, value: e })}
+      onCheckedChange={(checked: boolean) => setField({ ...field, value: checked })}
📝 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.

      onCheckedChange={(checked: boolean) => setField({ ...field, value: checked })}
🧰 Tools
🪛 eslint

[error] 39-39: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)


23-31: 🛠️ Refactor suggestion

优化 useEffect 依赖项和逻辑

两个 useEffect 可以合并,并且需要添加正确的依赖项。

-  useEffect(() => {
-    field.name = label;
-  }, []);
-
-  useEffect(() => {
-    if (defaultChecked) {
-      setField({ ...field, value: defaultChecked });
-    }
-  }, []);
+  useEffect(() => {
+    const updates: Partial<typeof field> = { name: label };
+    if (defaultChecked) {
+      updates.value = defaultChecked;
+    }
+    setField(prev => ({ ...prev, ...updates }));
+  }, [label, defaultChecked, setField]);
📝 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.

  useEffect(() => {
    const updates: Partial<typeof field> = { name: label };
    if (defaultChecked) {
      updates.value = defaultChecked;
    }
    setField(prev => ({ ...prev, ...updates }));
  }, [label, defaultChecked, setField]);

33-53: 🛠️ Refactor suggestion

建议添加无障碍支持

组件缺少必要的 ARIA 属性,这对于屏幕阅读器用户来说可能不够友好。

-  return <div className="flex items-center gap-2">
+  return <div className="flex items-center gap-2" role="group" aria-labelledby={`${id}-label`}>
     <Switch
       id={id}
       defaultChecked={defaultChecked}
       required={field.required}
       checked={field.value}
       onCheckedChange={(e) => setField({ ...field, value: e })}
       disabled={field.disabled}
+      aria-describedby={field.error ? `${id}-error` : undefined}
     />

     <label
+      id={`${id}-label`}
       htmlFor={id}
       className="p-0 m-0 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
     >
       {label}
     </label>

     {field.error && (
-      <div className="text-sm text-red-500">{field.error}</div>
+      <div id={`${id}-error`} className="text-sm text-red-500" role="alert">{field.error}</div>
     )}
   </div>
📝 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.

  return <div className="flex items-center gap-2" role="group" aria-labelledby={`${id}-label`}>
    <Switch
      id={id}
      defaultChecked={defaultChecked}
      required={field.required}
      checked={field.value}
      onCheckedChange={(e) => setField({ ...field, value: e })}
      disabled={field.disabled}
      aria-describedby={field.error ? `${id}-error` : undefined}
    />

    <label
      id={`${id}-label`}
      htmlFor={id}
      className="p-0 m-0 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
    >
      {label}
    </label>

    {field.error && (
      <div id={`${id}-error`} className="text-sm text-red-500" role="alert">{field.error}</div>
    )}
  </div>
🧰 Tools
🪛 eslint

[error] 39-39: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/ApiForm/ApiCheckbox.tsx (5)

39-39: ⚠️ Potential issue

修复类型安全问题

onCheckedChange 回调中的 e 参数类型不安全。

建议明确指定类型:

-      onCheckedChange={(e) => setField({ ...field, value: e })}
+      onCheckedChange={(checked: boolean) => setField({ ...field, value: checked })}
📝 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.

      onCheckedChange={(checked: boolean) => setField({ ...field, value: checked })}
🧰 Tools
🪛 eslint

[error] 39-39: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)


50-52: 🧹 Nitpick (assertive)

改进错误信息展示样式

错误信息的展示可以更加友好,建议添加图标和更好的样式。

建议修改为:

-    {field.error && (
-      <div className="text-sm text-red-500">{field.error}</div>
-    )}
+    {field.error && (
+      <div className="flex items-center gap-1 text-sm text-red-500">
+        <span className="i-lucide-alert-circle h-4 w-4" />
+        <span>{field.error}</span>
+      </div>
+    )}
📝 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.

    {field.error && (
      <div className="flex items-center gap-1 text-sm text-red-500">
        <span className="i-lucide-alert-circle h-4 w-4" />
        <span>{field.error}</span>
      </div>
    )}

6-10: 🧹 Nitpick (assertive)

接口定义需要补充必要的文档注释

建议为 ApiCheckboxProps 接口添加 JSDoc 注释,说明各个属性的用途和约束条件。

添加如下注释:

+/**
+ * ApiCheckbox 组件的属性接口
+ * @interface ApiCheckboxProps
+ * @property {string} id - 复选框的唯一标识符
+ * @property {string} [label] - 复选框的标签文本
+ * @property {boolean} [defaultChecked] - 复选框的默认选中状态
+ */
export interface ApiCheckboxProps {
  id: string;
  label?: string;
  defaultChecked?: boolean;
}
📝 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.

/**
 * ApiCheckbox 组件的属性接口
 * @interface ApiCheckboxProps
 * @property {string} id - 复选框的唯一标识符
 * @property {string} [label] - 复选框的标签文本
 * @property {boolean} [defaultChecked] - 复选框的默认选中状态
 */
export interface ApiCheckboxProps {
  id: string;
  label?: string;
  defaultChecked?: boolean;
}

23-31: 🧹 Nitpick (assertive)

优化 useEffect 的依赖项设置

当前的两个 useEffect 钩子存在以下问题:

  1. 空依赖数组可能导致更新不及时
  2. 两个效果可以合并为一个

建议重构如下:

-  useEffect(() => {
-    field.name = label;
-  }, []);
-
-  useEffect(() => {
-    if (defaultChecked) {
-      setField({ ...field, value: defaultChecked });
-    }
-  }, []);
+  useEffect(() => {
+    const updates = { name: label };
+    if (defaultChecked) {
+      updates.value = defaultChecked;
+    }
+    setField(prev => ({ ...prev, ...updates }));
+  }, [label, defaultChecked, setField]);
📝 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.

  useEffect(() => {
    const updates = { name: label };
    if (defaultChecked) {
      updates.value = defaultChecked;
    }
    setField(prev => ({ ...prev, ...updates }));
  }, [label, defaultChecked, setField]);

33-53: 🛠️ Refactor suggestion

建议添加无障碍支持

组件缺少必要的 ARIA 属性支持。

建议添加以下属性:

   return <div className="flex items-center gap-2">
     <Checkbox
       id={id}
+      aria-label={label}
+      aria-invalid={!!field.error}
+      aria-describedby={field.error ? `${id}-error` : undefined}
       defaultChecked={defaultChecked}
       required={field.required}
       checked={field.value}
       onCheckedChange={(checked: boolean) => setField({ ...field, value: checked })}
       disabled={field.disabled}
     />

     <label
       htmlFor={id}
       className="p-0 m-0 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
     >
       {label}
     </label>

     {field.error && (
-      <div className="text-sm text-red-500">{field.error}</div>
+      <div id={`${id}-error`} className="text-sm text-red-500">{field.error}</div>
     )}
   </div>
📝 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.

  return <div className="flex items-center gap-2">
    <Checkbox
      id={id}
      aria-label={label}
      aria-invalid={!!field.error}
      aria-describedby={field.error ? `${id}-error` : undefined}
      defaultChecked={defaultChecked}
      required={field.required}
      checked={field.value}
      onCheckedChange={(checked: boolean) => setField({ ...field, value: checked })}
      disabled={field.disabled}
    />

    <label
      htmlFor={id}
      className="p-0 m-0 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
    >
      {label}
    </label>

    {field.error && (
      <div id={`${id}-error`} className="text-sm text-red-500">{field.error}</div>
    )}
  </div>
🧰 Tools
🪛 eslint

[error] 39-39: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/chains/ethereum/case/contract/SampleContracts.ts (4)

24-33: 🧹 Nitpick (assertive)

建议添加测试合约的用途说明

为了避免误解,建议:

  1. 添加注释说明这些是测试用的 NFT 合约
  2. 说明这些合约的具体用途
  3. 标注是否可以在生产环境使用

35-40: 🧹 Nitpick (assertive)

⚠️ Potential issue

⚠️ 恶意地址的安全风险提示

在代码中包含恶意地址存在潜在风险:

  1. 建议添加明确的警告注释
  2. 说明这些地址的用途(如测试、演示等)
  3. 考虑将这些地址移至专门的测试配置文件

建议重构为:

+// WARNING: These addresses are known malicious contracts used for testing purposes only
+// DO NOT send any real assets to these addresses
 export const MALICIOUS_CONTRACT_ADDRESSES = {
   mainnet: '0x000062Accd1a9d62eF428eC86cA3dD4f45120000',
   default: '0x00008F1149168C1D2fa1eBa1Ad3e9cD644510000',
 };

+// WARNING: Known malicious address - DO NOT USE with real assets
 export const MALICIOUS_ADDRESS = '0x5FbDB2315678afecb367f032d93F642f64180aa3';
📝 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.

// WARNING: These addresses are known malicious contracts used for testing purposes only
// DO NOT send any real assets to these addresses
export const MALICIOUS_CONTRACT_ADDRESSES = {
  mainnet: '0x000062Accd1a9d62eF428eC86cA3dD4f45120000',
  default: '0x00008F1149168C1D2fa1eBa1Ad3e9cD644510000',
};

// WARNING: Known malicious address - DO NOT USE with real assets
export const MALICIOUS_ADDRESS = '0x5FbDB2315678afecb367f032d93F642f64180aa3';

2-11: 🧹 Nitpick (assertive)

建议添加类型定义以增强类型安全性

建议为网络常量添加明确的类型定义,可以这样改进:

+type NetworkName = 'polygon' | 'optimism' | 'bsc' | 'avalanche' | 'arbitrum' | 'sepolia' | 'base' | 'opBnb';
+
-export const NETWORKS_BY_CHAIN_ID = {
+export const NETWORKS_BY_CHAIN_ID: Record<number, NetworkName> = {
   // ... rest of the definitions
};

Committable suggestion skipped: line range outside the PR's diff.


13-22: 💡 Codebase verification

USDC 合约地址需要额外的安全保障措施

代码分析显示:

  • 缺少地址来源文档
  • 没有实施地址校验机制
  • 同一文件中存在多组不同的地址,增加了出错风险

建议:

  1. 为每个网络的 USDC 地址添加官方来源链接注释
  2. 引入 ethereum-checksum-address 等工具进行地址格式校验
  3. 移除重复的地址声明,统一使用一个地址集
  4. 考虑添加单元测试验证地址的正确性
🔗 Analysis chain

请验证 USDC 合约地址的准确性

这些 USDC 合约地址直接关系到资金安全,建议:

  1. 确认这些是官方的 USDC 合约地址
  2. 添加来源文档链接
  3. 考虑添加地址校验机制
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 验证 USDC 合约地址
echo "正在检查合约地址格式..."
rg -e "0x[a-fA-F0-9]{40}" packages/example/components/chains/ethereum/case/contract/SampleContracts.ts

echo "建议与以下来源进行对比验证:"
echo "- Circle 官方文档"
echo "- Etherscan 验证合约"

Length of output: 1621


Script:

#!/bin/bash
# Search for any documentation or comments about these addresses
rg -i "usdc.*contract.*address" -g "!*.{json,lock}" -A 3 -B 3

# Look for any test files or configuration related to these addresses
fd -e test.ts -e spec.ts -e config.ts -X rg -l "0x2791bca1f2de4661ed88a30c99a7a9449aa84174|0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"

# Check if there are any validation utilities
fd -e ts -e js -X rg -l "validateAddress|checksum|isValidAddress"

# Look for any imports or references to address validation
ast-grep --pattern 'import $_ from "ethereum-checksum-address"'

Length of output: 381

packages/example/components/TabCard.tsx (3)

4-13: 🧹 Nitpick (assertive)

建议增加类型文档和灵活性

为了提高代码的可维护性和灵活性,建议做如下改进:

  1. 添加 JSDoc 注释说明类型用途
  2. 考虑将 title 设为可选属性,增加组件灵活性
+/**
+ * TabCard 组件的属性定义
+ * @property tabs - 标签页配置数组
+ * @property defaultValue - 默认选中的标签页值
+ */
 export type TabCardProps = {
     tabs: {
         label: string;
         value: string;
-        title: string;
+        title?: string;
         description?: string;
         content: React.ReactNode;
     }[];
     defaultValue?: string;
 }
📝 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.

/**
 * TabCard 组件的属性定义
 * @property tabs - 标签页配置数组
 * @property defaultValue - 默认选中的标签页值
 */
export type TabCardProps = {
    tabs: {
        label: string;
        value: string;
        title?: string;
        description?: string;
        content: React.ReactNode;
    }[];
    defaultValue?: string;
}

25-39: 🧹 Nitpick (assertive)

性能优化建议

建议使用 useMemo 缓存标签页内容渲染结果,避免不必要的重渲染:

+const memoizedTabContent = useMemo(() => 
+    tabs.map((tab) => (
         <TabsContent key={tab.value} value={tab.value}>
             <Card>
                 <CardHeader>
                     <CardTitle>{tab.title}</CardTitle>
                     {tab.description && (
                         <CardDescription>{tab.description}</CardDescription>
                     )}
                 </CardHeader>
                 <CardContent className="space-y-2">
                     {tab.content}
                 </CardContent>
             </Card>
         </TabsContent>
+    )), [tabs]
+);

Committable suggestion skipped: line range outside the PR's diff.


15-42: ⚠️ Potential issue

需要解决几个关键问题

代码存在以下需要优化的地方:

  1. 网格列数的动态计算可能存在问题:
-<TabsList className={`grid w-full grid-cols-${tabs.length}`}>
+<TabsList className="grid w-full" style={{ gridTemplateColumns: `repeat(${tabs.length}, 1fr)` }}>
  1. 缺少边界情况处理:
 export default function TabCard({ tabs, defaultValue }: TabCardProps) {
+    if (!tabs?.length) {
+        return null;
+    }
     return (
  1. 建议添加无障碍支持:
-<TabsList className={`grid w-full grid-cols-${tabs.length}`}>
+<TabsList className={`grid w-full grid-cols-${tabs.length}`} aria-label="标签页导航">
📝 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.

export default function TabCard({ tabs, defaultValue }: TabCardProps) {
    if (!tabs?.length) {
        return null;
    }
    return (
        <Tabs defaultValue={defaultValue || tabs[0]?.value}>
            <TabsList className="grid w-full" style={{ gridTemplateColumns: `repeat(${tabs.length}, 1fr)` }} aria-label="标签页导航">
                {tabs.map((tab) => (
                    <TabsTrigger key={tab.value} value={tab.value}>
                        {tab.label}
                    </TabsTrigger>
                ))}
            </TabsList>
            {tabs.map((tab) => (
                <TabsContent key={tab.value} value={tab.value}>
                    <Card>
                        <CardHeader>
                            <CardTitle>{tab.title}</CardTitle>
                            {tab.description && (
                                <CardDescription>{tab.description}</CardDescription>
                            )}
                        </CardHeader>
                        <CardContent className="space-y-2">
                            {tab.content}
                        </CardContent>
                    </Card>
                </TabsContent>
            ))}
        </Tabs>
    );
}
packages/example/components/ApiForm/ApiAutoTextArea.tsx (4)

25-26: ⚠️ Potential issue

需要修复类型安全问题

在处理表单值时存在类型安全隐患。建议添加适当的类型定义来解决 ESLint 警告。

- const [field, setField] = useAtom(store.fieldsAtom(id));
+ interface FieldState {
+   value: string;
+   error?: string;
+   disabled?: boolean;
+   name?: string;
+   required?: boolean;
+ }
+ const [field, setField] = useAtom<FieldState>(store.fieldsAtom(id));

Also applies to: 36-36


21-22: 🧹 Nitpick (assertive)

建议改进错误处理机制

目前的错误处理过于简单。建议实现错误边界(Error Boundary)来优雅地处理运行时错误。

建议:

  1. 创建专门的错误边界组件
  2. 添加错误重试机制
  3. 提供用户友好的错误提示

27-30: 🛠️ Refactor suggestion

优化 useEffect 依赖项

当前的 useEffect 缺少必要的依赖项,这可能导致更新不及时。建议添加所有必需的依赖。

  useEffect(() => {
    field.name = label;
    field.required = required;
-  }, []);
+  }, [field, label, required]);
📝 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.

  useEffect(() => {
    field.name = label;
    field.required = required;
  }, [field, label, required]);

46-48: 🧹 Nitpick (assertive)

移除冗余的接口属性定义

ApiAutoTextAreaProps 继承自 AutoTextAreaProps,无需重复定义 id 属性。

export interface ApiAutoTextAreaProps extends AutoTextAreaProps {
-  id: string;
}
📝 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.

export interface ApiAutoTextAreaProps extends AutoTextAreaProps {
}
packages/example/components/ApiForm/ApiTextArea.tsx (5)

39-39: 🧹 Nitpick (assertive)

避免使用内联样式

内联样式 style={{ overflow: 'hidden' }} 应该移至 CSS 文件中。

建议创建样式类:

- style={{ overflow: 'hidden' }}
+ className="textarea-hidden-overflow"

并在 CSS 文件中添加:

.textarea-hidden-overflow {
  overflow: hidden;
}

53-70: 🧹 Nitpick (assertive)

优化组件结构和性能

组件虽然使用了 memo,但可以进一步优化:

  1. Label 渲染逻辑可以提取为独立组件
  2. 可以使用 CSS 类代替条件渲染

建议重构如下:

+ const FormLabel = memo(({ id, label, required }: { id: string, label?: string, required?: boolean }) => {
+   if (!label) return null;
+   return (
+     <Label htmlFor={id}>
+       {label}
+       <span className={`required-mark ${required ? 'visible' : 'hidden'}`}>*</span>
+     </Label>
+   );
+ });

export const ApiTextArea = memo(({
  id,
  label,
  placeholder,
  required
}: ApiTextAreaProps) => {
  return (
    <div>
-     {label && (
-       <Label htmlFor={id}>
-         {label}
-         {required && <span className="text-red-500">*</span>}
-       </Label>
-     )}
+     <FormLabel id={id} label={label} required={required} />
      <TextArea id={id} placeholder={placeholder} />
    </div>
  );
});

并添加相应的 CSS:

.required-mark {
  color: #ef4444;
}
.required-mark.hidden {
  display: none;
}

27-30: ⚠️ Potential issue

添加 useEffect 依赖项

useEffect 中使用了 fieldrequired 等变量,但依赖数组为空,这可能导致更新不及时。

建议修改如下:

  useEffect(() => {
    field.name = label;
    field.required = required;
-  }, []);
+  }, [field, label, required]);
📝 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.

  useEffect(() => {
    field.name = label;
    field.required = required;
  }, [field, label, required]);

47-51: 🧹 Nitpick (assertive)

优化接口定义,避免重复属性

ApiTextAreaProps 继承了 TextAreaProps,但仍然重复声明了相同的属性。这是不必要的,应该移除重复的属性声明。

建议修改如下:

export interface ApiTextAreaProps extends TextAreaProps {
-  id: string;
-  label?: string;
-  required?: boolean;
}
📝 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.

export interface ApiTextAreaProps extends TextAreaProps {
}

35-36: ⚠️ Potential issue

增加类型安全性

field.value 的类型推断为 any,这可能导致运行时错误。

建议添加明确的类型定义:

- const [field, setField] = useAtom(store.fieldsAtom(id));
+ interface FieldState {
+   value: string;
+   name?: string;
+   required?: boolean;
+   disabled?: boolean;
+   error?: string;
+ }
+ const [field, setField] = useAtom<FieldState>(store.fieldsAtom(id));

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 36-36: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/ApiForm/hooks/useValidation.ts (3)

5-11: 🧹 Nitpick (assertive)

建议改进类型安全性

FormStore<any> 的使用降低了类型安全性。建议使用具体的类型参数来增强代码的可维护性和可靠性。

-  store: FormStore<any>;
+  store: FormStore<unknown>;
📝 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.

interface ValidationProps {
  store: FormStore<unknown>;
  validation?: {
    fields: string[];
    validator?: (values: Record<string, { id: string; value: string; required: boolean }>) => string | undefined;
  };
}

32-61: 🧹 Nitpick (assertive)

建议国际化错误消息

错误消息直接硬编码为中文字符串。建议使用国际化方案来支持多语言。

-        error: `请填写 ${validation.fields
+        error: `${i18n.t('form.required_fields')} ${validation.fields
           .filter((fieldId) => isEmpty(values[fieldId].value) && values[fieldId].required)
           .join(', ')} 字段`,

Committable suggestion skipped: line range outside the PR's diff.


15-29: 🛠️ Refactor suggestion

优化累加器性能

在 reduce 中使用展开运算符可能导致 O(n²) 的时间复杂度。对于大型数据集,这可能会影响性能。

建议重构为:

-    return validation.fields.reduce((acc, fieldId) => {
-      const field = store.scope.get(store.fieldsAtom(fieldId));
-      return {
-        ...acc,
-        [fieldId]: {
-          id: fieldId,
-          value: field.value,
-          required: field.required,
-        },
-      };
-    }, {} as Record<string, { id: string; value: string; required: boolean }>);
+    const result: Record<string, { id: string; value: string; required: boolean }> = {};
+    for (const fieldId of validation.fields) {
+      const field = store.scope.get(store.fieldsAtom(fieldId));
+      result[fieldId] = {
+        id: fieldId,
+        value: field.value,
+        required: field.required,
+      };
+    }
+    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.

  const getFieldValues = useCallback(() => {
    if (!validation) return {};

    const result: Record<string, { id: string; value: string; required: boolean }> = {};
    for (const fieldId of validation.fields) {
      const field = store.scope.get(store.fieldsAtom(fieldId));
      result[fieldId] = {
        id: fieldId,
        value: field.value,
        required: field.required,
      };
    }
    return result;
  }, [validation, store]);
🧰 Tools
🪛 Biome

[error] 22-23: Avoid the use of spread (...) syntax on accumulators.

Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.

(lint/performance/noAccumulatingSpread)

packages/example/components/ApiForm/ApiText.tsx (5)

64-70: 🧹 Nitpick (assertive)

建议优化渲染逻辑的可读性

当前的渲染逻辑正确,但可以更明确地表达意图。

-    if (field.value) {
+    if (!field.value) {
+        return null; // 当没有值时不渲染任何内容
+    }
+
     return <div className={cn(textSize, textColor, bgColor, 'p-2 rounded-md font-medium')}>{field.value}</div>
-    }
-    return null;
📝 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.

    if (!field.value) {
        return null; // 当没有值时不渲染任何内容
    }

    return <div className={cn(textSize, textColor, bgColor, 'p-2 rounded-md font-medium')}>{field.value}</div>

ApiText.displayName = 'ApiText';

27-38: 🧹 Nitpick (assertive)

建议简化尺寸样式逻辑

当前的 switch 语句可以用对象映射替代,使代码更简洁。

-    let textSize = '';
-    switch (size) {
-        case 'sm':
-            textSize = 'text-sm';
-            break;
-        case 'md':
-            textSize = 'text-base';
-            break;
-        case 'lg':
-            textSize = 'text-lg';
-            break;
-    }
+    const sizeClasses = {
+        sm: 'text-sm',
+        md: 'text-base',
+        lg: 'text-lg'
+    };
+    const textSize = sizeClasses[size];
📝 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.

    const sizeClasses = {
        sm: 'text-sm',
        md: 'text-base',
        lg: 'text-lg'
    };
    const textSize = sizeClasses[size];

40-62: ⚠️ Potential issue

修复默认样式和优化类型样式逻辑

发现以下问题:

  1. 默认情况下使用黑色背景配黑色文字,这会导致文字不可见
  2. 样式逻辑可以简化
-    let bgColor = '';
-    let textColor = '';
-    switch (type) {
-        case 'error':
-            textColor = 'text-black';
-            bgColor = 'bg-red-100';
-            break;
-        case 'warning':
-            textColor = 'text-black';
-            bgColor = 'bg-yellow-100';
-            break;
-        case 'success':
-            textColor = 'text-black';
-            bgColor = 'bg-green-100';
-            break;
-        case 'info':
-            textColor = 'text-black';
-            bgColor = 'bg-gray-100';
-            break;
-        default:
-            textColor = 'text-black';
-            bgColor = 'bg-black';
-    }
+    const typeStyles = {
+        error: 'bg-red-100',
+        warning: 'bg-yellow-100',
+        success: 'bg-green-100',
+        info: 'bg-gray-100',
+        text: 'bg-white'
+    };
+    const bgColor = typeStyles[type];
+    const textColor = 'text-black';
📝 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.

    const typeStyles = {
        error: 'bg-red-100',
        warning: 'bg-yellow-100',
        success: 'bg-green-100',
        info: 'bg-gray-100',
        text: 'bg-white'
    };
    const bgColor = typeStyles[type];
    const textColor = 'text-black';

13-25: 🧹 Nitpick (assertive)

组件声明合理,建议优化错误信息

使用 memo 和 context 的方式很好。建议改进错误信息,使其更具描述性。

-    if (!context) throw new Error('ApiField must be used within ApiForm');
+    if (!context) throw new Error('ApiText 组件必须在 ApiForm 组件内使用');
📝 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.

export const ApiText = memo(({
    id,
    size = 'md',
    type = 'text',
    hidden = false
}: ApiTextProps) => {
    const context = useContext(ApiFormContext);
    if (!context) throw new Error('ApiText 组件必须在 ApiForm 组件内使用');

    const { store } = context;
    const [field] = useAtom(store.fieldsAtom(id));

    if (hidden) return null;

1-11: 🧹 Nitpick (assertive)

接口定义清晰,建议添加属性文档

接口定义和导入都很规范。建议为 ApiTextProps 的每个属性添加 JSDoc 注释,以提供更好的开发体验。

 export interface ApiTextProps {
+    /** 文本字段的唯一标识符 */
     id: string
+    /** 文本大小,默认为 'md' */
     size?: 'sm' | 'md' | 'lg'
+    /** 文本类型,影响显示样式,默认为 'text' */
     type?: 'text' | 'error' | 'warning' | 'success' | 'info'
+    /** 是否隐藏文本,默认为 false */
     hidden?: boolean
 }
📝 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.

import React, { memo, useContext } from 'react';
import { useAtom } from 'jotai';
import { ApiFormContext } from './ApiForm';
import { cn } from '../../lib/utils';

export interface ApiTextProps {
    /** 文本字段的唯一标识符 */
    id: string
    /** 文本大小,默认为 'md' */
    size?: 'sm' | 'md' | 'lg'
    /** 文本类型,影响显示样式,默认为 'text' */
    type?: 'text' | 'error' | 'warning' | 'success' | 'info'
    /** 是否隐藏文本,默认为 false */
    hidden?: boolean
}
packages/example/components/ui/tabs.tsx (2)

8-21: 🧹 Nitpick (assertive)

建议添加组件类型文档

为了提高代码可维护性,建议为 TabsList 组件添加 JSDoc 注释,说明组件的用途和属性类型。

建议添加如下注释:

+/**
+ * TabsList 组件 - 用于呈现标签页列表容器
+ * @param className - 自定义类名
+ * @param props - 其他 TabsPrimitive.List 支持的属性
+ */
const TabsList = React.forwardRef<
📝 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.

/**
 * TabsList 组件 - 用于呈现标签页列表容器
 * @param className - 自定义类名
 * @param props - 其他 TabsPrimitive.List 支持的属性
 */
const TabsList = React.forwardRef<
  React.ElementRef<typeof TabsPrimitive.List>,
  React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => (
  <TabsPrimitive.List
    ref={ref}
    className={cn(
      "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
      className
    )}
    {...props}
  />
))
TabsList.displayName = TabsPrimitive.List.displayName

23-36: 🧹 Nitpick (assertive)

建议提取样式常量

当前的 className 字符串较长,建议将其提取为常量以提高可维护性。

建议重构为:

+const tabsTriggerStyles = {
+  base: "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all",
+  states: "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
+  active: "data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
+  disabled: "disabled:pointer-events-none disabled:opacity-50"
+}
+
const TabsTrigger = React.forwardRef<
  React.ElementRef<typeof TabsPrimitive.Trigger>,
  React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
>(({ className, ...props }, ref) => (
  <TabsPrimitive.Trigger
    ref={ref}
-    className={cn(
-      "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
-      className
-    )}
+    className={cn(tabsTriggerStyles.base, tabsTriggerStyles.states, tabsTriggerStyles.active, tabsTriggerStyles.disabled, className)}
    {...props}
  />
))
📝 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.

const tabsTriggerStyles = {
  base: "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all",
  states: "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
  active: "data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
  disabled: "disabled:pointer-events-none disabled:opacity-50"
}

const TabsTrigger = React.forwardRef<
  React.ElementRef<typeof TabsPrimitive.Trigger>,
  React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
>(({ className, ...props }, ref) => (
  <TabsPrimitive.Trigger
    ref={ref}
    className={cn(tabsTriggerStyles.base, tabsTriggerStyles.states, tabsTriggerStyles.active, tabsTriggerStyles.disabled, className)}
    {...props}
  />
))
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
packages/example/components/chains/utils/OkLink.ts (4)

76-76: 🧹 Nitpick (assertive)

建议使用懒加载模式

当前导出方式会在导入模块时立即创建实例。建议使用懒加载模式,只在首次使用时创建实例。

-export const okLinkRequest = new OKLinkRequest();
+let instance: OKLinkRequest | null = null;
+export const getOkLinkRequest = () => {
+  if (!instance) {
+    instance = new OKLinkRequest();
+  }
+  return instance;
+};
📝 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.

let instance: OKLinkRequest | null = null;
export const getOkLinkRequest = () => {
  if (!instance) {
    instance = new OKLinkRequest();
  }
  return instance;
};

1-4: 🧹 Nitpick (assertive)

建议处理 ESLint 警告而不是禁用它们

当前代码通过 ESLint 禁用指令忽略了多个类型安全相关的警告。建议通过proper类型定义来解决这些问题,而不是简单地禁用它们。这样可以提高代码的类型安全性。

-/* eslint-disable @typescript-eslint/no-unsafe-call */
-/* eslint-disable @typescript-eslint/no-unsafe-member-access */
-/* eslint-disable @typescript-eslint/no-unsafe-assignment */

Committable suggestion skipped: line range outside the PR's diff.


6-28: 🧹 Nitpick (assertive)

建议添加类型文档注释

类型定义结构清晰,但缺少文档注释。建议为每个类型添加 JSDoc 注释,说明其用途和字段含义。

+/**
+ * 分页信息类型
+ * @template T 列表项类型
+ */
 type PageInfo<T> = {
   page: number;
   limit: number;
   // ...
 };

+/**
+ * API 响应基础类型
+ * @template T 响应数据类型
+ */
 type BaseResponse<T> = {
   // ...
 };

+/**
+ * OKLink 代币信息类型
+ */
 export type OkLinkTokenInfo = {
   // ...
 };

Committable suggestion skipped: line range outside the PR's diff.


30-74: ⚠️ Potential issue

需要改进缓存机制和错误处理

当前实现存在以下问题:

  1. 缓存机制没有过期策略
  2. 错误处理过于简单,未区分不同类型的错误
  3. 缺少 API key 验证

建议进行如下改进:

 class OKLinkRequest {
   private axiosInstance: AxiosInstance;
-  private cache: Record<string, any> = {};
+  private cache: Map<string, { data: OkLinkTokenInfo[]; timestamp: number }> = new Map();
+  private readonly CACHE_DURATION = 5 * 60 * 1000; // 5分钟缓存
+
+  private validateApiKey() {
+    if (!process.env.NEXT_PUBLIC_OKLINK_API_KEY) {
+      throw new Error('OKLink API key is not configured');
+    }
+  }
+
+  private isCacheValid(key: string): boolean {
+    const cached = this.cache.get(key);
+    return cached ? Date.now() - cached.timestamp < this.CACHE_DURATION : false;
+  }

   constructor() {
+    this.validateApiKey();
     // ...
   }

   async getTokenList(
     chainName: 'TRON',
     tokenType: 'TRC20' | undefined,
   ): Promise<OkLinkTokenInfo[]> {
     const cacheKey = `${chainName}-${tokenType}`;
-    if (this.cache[cacheKey]) {
-      return this.cache[cacheKey];
+    if (this.isCacheValid(cacheKey)) {
+      return this.cache.get(cacheKey)!.data;
     }

     const res = await this.axiosInstance
       .get<BaseResponse<OkLinkTokenInfo>>(`/explorer/token/token-list?chainShortName=${chainName}&limit=50`)
       .catch((err) => {
-        console.error(err);
-        return { data: { data: [] } };
+        if (axios.isAxiosError(err)) {
+          if (err.response?.status === 401) {
+            throw new Error('Invalid API key');
+          }
+          if (err.response?.status === 429) {
+            throw new Error('Rate limit exceeded');
+          }
+        }
+        throw new Error(`Failed to fetch token list: ${err.message}`);
       });

     // ...

-    this.cache[cacheKey] = tokenList;
+    this.cache.set(cacheKey, { data: tokenList, timestamp: Date.now() });

     return tokenList;
   }
 }
📝 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.

class OKLinkRequest {
  private axiosInstance: AxiosInstance;
  private cache: Map<string, { data: OkLinkTokenInfo[]; timestamp: number }> = new Map();
  private readonly CACHE_DURATION = 5 * 60 * 1000; // 5分钟缓存

  private validateApiKey() {
    if (!process.env.NEXT_PUBLIC_OKLINK_API_KEY) {
      throw new Error('OKLink API key is not configured');
    }
  }

  private isCacheValid(key: string): boolean {
    const cached = this.cache.get(key);
    return cached ? Date.now() - cached.timestamp < this.CACHE_DURATION : false;
  }

  constructor() {
    this.validateApiKey();
    this.axiosInstance = axios.create({
      baseURL: 'https://www.oklink.com/api/v5/explorer',
      headers: {
        'Content-Type': 'application/json',
        'Ok-Access-Key': process.env.NEXT_PUBLIC_OKLINK_API_KEY,
      },
    });
  }

  async getTokenList(
    chainName: 'TRON',
    tokenType: 'TRC20' | undefined,
  ): Promise<OkLinkTokenInfo[]> {
    const cacheKey = `${chainName}-${tokenType}`;
    if (this.isCacheValid(cacheKey)) {
      return this.cache.get(cacheKey)!.data;
    }

    const res = await this.axiosInstance
      .get<BaseResponse<OkLinkTokenInfo>>(`/explorer/token/token-list?chainShortName=${chainName}&limit=50`)
      .catch((err) => {
        if (axios.isAxiosError(err)) {
          if (err.response?.status === 401) {
            throw new Error('Invalid API key');
          }
          if (err.response?.status === 429) {
            throw new Error('Rate limit exceeded');
          }
        }
        throw new Error(`Failed to fetch token list: ${err.message}`);
      });

    const tokenList =
      res.data?.data?.[0]?.tokenList?.filter((token: { protocolType: string }) => {
        if (tokenType) {
          return token.protocolType === tokenType;
        }
        return true;
      }) ?? [];

    this.cache.set(cacheKey, { data: tokenList, timestamp: Date.now() });

    return tokenList;
  }
}
packages/example/package.json (1)

64-64: 🧹 Nitpick (assertive)

新增依赖项的版本锁定建议

几点重要建议:

  1. ethers v5.7.2 是一个稳定版本,但建议考虑升级到 v6.x 以获得更好的性能和安全性。
  2. cmdk 使用了精确版本号 (1.0.0),这是个好习惯。
  3. jotai 使用了 ^2.10.1,建议也锁定具体版本以避免潜在的兼容性问题。

建议这样修改版本号:

-    "@uniswap/default-token-list": "^12.23.0",
+    "@uniswap/default-token-list": "12.23.0",
-    "ethers": "5.7.2",
+    "ethers": "^6.9.0",
-    "jotai": "^2.10.1",
+    "jotai": "2.10.1"

Also applies to: 80-80, 86-86, 89-89

packages/example/components/chains/ethereum/case/transfer/malformed.ts (3)

71-269: 🧹 Nitpick (assertive)

建议补充更多边界测试用例

当前的 signTypedData 测试用例覆盖了主要场景,建议添加以下测试用例以提高覆盖率:

  1. 测试 chainId 为负数的情况
  2. 测试 version 为空字符串的情况
  3. 测试嵌套数组类型的错误情况

需要我帮您生成这些测试用例的代码吗?


92-92: ⚠️ Potential issue

修复 OrderComponents 类型定义中的语法错误

在第 92 行,ConsiderationItem[+ 类型定义存在语法错误,可能导致类型验证失败。

建议修复为:

- OrderComponents: [{ name: 'consideration', type: 'ConsiderationItem[+' }],
+ OrderComponents: [{ name: 'consideration', type: 'ConsiderationItem[]' }],
📝 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.

            OrderComponents: [{ name: 'consideration', type: 'ConsiderationItem[]' }],

11-70: 🧹 Nitpick (assertive)

建议优化测试用例的可维护性

当前实现有以下几点可以改进:

  1. 建议将硬编码的 gas 值(如 '0x2540be400')提取为常量,提高可维护性
  2. 建议在测试用例中添加预期的错误信息,方便测试失败时快速定位问题

建议按如下方式重构:

+ const GAS_VALUES = {
+   MAX_FEE_PER_GAS: '0x2540be400',
+   MAX_PRIORITY_FEE_PER_GAS: '0x3b9aca00',
+   GAS_LIMIT: '0x5028'
+ };

  {
    'id': 'sendTransaction-malformed-invalid-gasLimit',
    'name': '1559 转账测试:错误的 gasLimit 类型',
    'description': '测试 1559 转账 错误的 gasLimit 类型',
+   'expectedError': 'Invalid gas limit: expected hex string',
    'value': JSON.stringify({
      from,
      to,
      value: '0x0',
      gasLimit: 'invalid',
-     maxFeePerGas: '0x2540be400',
-     maxPriorityFeePerGas: '0x3b9aca00',
+     maxFeePerGas: GAS_VALUES.MAX_FEE_PER_GAS,
+     maxPriorityFeePerGas: GAS_VALUES.MAX_PRIORITY_FEE_PER_GAS,
    }),
  }

Committable suggestion skipped: line range outside the PR's diff.

packages/example/components/chains/tron/example.tsx (2)

25-43: ⚠️ Potential issue

需要处理 useEffect 中的 Promise

当前的 useEffect 中存在未处理的 Promise,这可能导致内存泄漏。

建议使用 cleanup 函数来处理:

 useEffect(() => {
+  let isSubscribed = true;
+
   okLinkRequest.getTokenList('TRON', 'TRC20').then((tokens) => {
+    if (!isSubscribed) return;
+
     const tokenOptions = tokens.map((token) => ({
       value: token.tokenContractAddress,
       label: `${token.token} - ${token.tokenContractAddress}`,
       extra: {
         type: 'trc20',
         options: {
           address: token.tokenContractAddress,
           symbol: token.token,
           decimals: token.precision,
           image: token.logoUrl,
         }
       }
     }));

     apiFromComboboxRef.current?.setOptions(tokenOptions);
   })
+
+  return () => {
+    isSubscribed = 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.

  useEffect(() => {
    let isSubscribed = true;

    okLinkRequest.getTokenList('TRON', 'TRC20').then((tokens) => {
      if (!isSubscribed) return;

      const tokenOptions = tokens.map((token) => ({
        value: token.tokenContractAddress,
        label: `${token.token} - ${token.tokenContractAddress}`,
        extra: {
          type: 'trc20',
          options: {
            address: token.tokenContractAddress,
            symbol: token.token,
            decimals: token.precision,
            image: token.logoUrl,
          }
        }
      }));

      apiFromComboboxRef.current?.setOptions(tokenOptions);
    })

    return () => {
      isSubscribed = false;
    };
  }, []);
🧰 Tools
🪛 eslint

[error] 26-42: Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the void operator.

(@typescript-eslint/no-floating-promises)


19-88: 🧹 Nitpick (assertive)

建议增加错误处理和加载状态

当前实现存在以下可以改进的地方:

  1. Token 列表加载时缺少加载状态提示
  2. okLinkRequest 请求缺少错误处理
  3. 表单提交时缺少加载状态

建议添加以下改进:

 const WalletWatchAsset = memo(() => {
   const apiFromRef = useRef<ApiFormRef>(null);
   const apiFromComboboxRef = useRef<ApiComboboxRef>(null);
+  const [isLoading, setIsLoading] = useState(false);
 
   const { provider } = useWallet<IProviderApi>();
 
   useEffect(() => {
-    okLinkRequest.getTokenList('TRON', 'TRC20').then((tokens) => {
+    setIsLoading(true);
+    okLinkRequest.getTokenList('TRON', 'TRC20').then((tokens) => {
       const tokenOptions = tokens.map((token) => ({
         value: token.tokenContractAddress,
         label: `${token.token} - ${token.tokenContractAddress}`,
         extra: {
           type: 'trc20',
           options: {
             address: token.tokenContractAddress,
             symbol: token.token,
             decimals: token.precision,
             image: token.logoUrl,
           }
         }
       }));
 
       apiFromComboboxRef.current?.setOptions(tokenOptions);
-    })
+    }).catch((error) => {
+      console.error('Failed to fetch token list:', error);
+      // TODO: 添加错误提示 UI
+    }).finally(() => {
+      setIsLoading(false);
+    });
   }, []);

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 26-42: Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the void operator.

(@typescript-eslint/no-floating-promises)

packages/example/components/chains/conflux/example.tsx (2)

90-93: ⚠️ Potential issue

注意类型安全问题

在解析 JSON 时没有进行类型验证,可能导致运行时错误。建议添加类型检查。

+ interface WatchAssetParams {
+   type: string;
+   options: {
+     address: string;
+     symbol: string;
+     decimals: number;
+     image?: string;
+   };
+ }

- const res = await provider?.request({
+ const params = JSON.parse(apiFromRef.current?.getValue('request') ?? '') as WatchAssetParams;
+ const res = await provider?.request({
    'method': 'wallet_watchAsset',
-   'params': JSON.parse(apiFromRef.current?.getValue('request') ?? ''),
+   'params': params,
  });
📝 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.

        interface WatchAssetParams {
          type: string;
          options: {
            address: string;
            symbol: string;
            decimals: number;
            image?: string;
          };
        }

        const params = JSON.parse(apiFromRef.current?.getValue('request') ?? '') as WatchAssetParams;
        const res = await provider?.request({
          'method': 'wallet_watchAsset',
          'params': params,
        });
🧰 Tools
🪛 eslint

[error] 92-92: Unsafe argument of type any assigned to a parameter of type string.

(@typescript-eslint/no-unsafe-argument)


40-67: 🛠️ Refactor suggestion

建议增加错误处理和配置管理

  1. 建议添加错误处理逻辑,以应对 API 请求失败的情况
  2. 建议将 Token 列表的 URL 移至配置文件中,便于后期维护
+ const TOKEN_LIST_URL = process.env.TOKEN_LIST_URL || 'https://testingcf.jsdelivr.net/gh/conflux-fans/token-list@master/cfx.fluent.json';

  useEffect(() => {
-   axios.get('https://testingcf.jsdelivr.net/gh/conflux-fans/token-list@master/cfx.fluent.json').then((res) => {
+   axios.get(TOKEN_LIST_URL)
+     .then((res) => {
      const tokens = res.data.tokens as {
        // ... existing type definition
      }[];
      // ... existing code
-   })
+   })
+   .catch((error) => {
+     console.error('Failed to fetch token list:', error);
+     // 可以添加用户提示
+   });
  }, [chainId]);
📝 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.

  const TOKEN_LIST_URL = process.env.TOKEN_LIST_URL || 'https://testingcf.jsdelivr.net/gh/conflux-fans/token-list@master/cfx.fluent.json';

  useEffect(() => {
    axios.get(TOKEN_LIST_URL)
      .then((res) => {
        const tokens = res.data.tokens as {
          chainId: number;
          address: string;
          name: string;
          symbol: string;
          decimals: number;
          logoURI: string;
        }[]
        const tokenOptions = tokens.map((token) => ({
          value: token.address,
          label: `${token.name} - ${token.address}`,
          extra: {
            type: 'CRC20',
            options: {
              address: token.address,
              symbol: token.symbol,
              decimals: token.decimals,
              image: token.logoURI,
            }
          }
        }));

        apiFromComboboxRef.current?.setOptions(tokenOptions);
      })
      .catch((error) => {
        console.error('Failed to fetch token list:', error);
        // 可以添加用户提示
      });
  }, [chainId]);
packages/example/components/chains/ethereum/case/contract/contract721.json (1)

1-365: ⚠️ Potential issue

建议增加铸造函数的访问控制!

mintNFTs 函数缺少访问控制,建议:

  1. 添加 onlyOwner 或其他访问控制修饰符
  2. 考虑实现铸造数量限制

建议修改 mintNFTs 函数定义:

    {
      "inputs": [
        {
          "internalType": "uint256",
          "name": "numberOfTokens",
          "type": "uint256"
        }
      ],
      "name": "mintNFTs",
-     "outputs": [],
+     "outputs": [],
+     "stateMutability": "nonpayable",
-     "stateMutability": "nonpayable",
+     "stateMutability": "onlyOwner",
      "type": "function"
    }

Committable suggestion skipped: line range outside the PR's diff.

packages/example/components/ApiForm/store.ts (4)

42-42: 🧹 Nitpick (assertive)

确保 formId 类型一致

第42行中,formId 用于 formStores.set 方法。确保 formId 的类型为 string,以避免潜在的类型问题。

🧰 Tools
🪛 eslint

[error] 42-42: Unsafe argument of type any assigned to a parameter of type string.

(@typescript-eslint/no-unsafe-argument)


18-18: 🛠️ Refactor suggestion

显式声明 formId 的类型

第18行中,formId 的类型可能被推断为 any。为确保类型安全,建议显式将 formId 声明为 string 类型。

应用以下代码修改:

-  const formId = id || nanoid();
+  const formId: string = id || nanoid();
📝 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.

  const formId: string = id || nanoid();

15-15: 🛠️ Refactor suggestion

避免使用 any,提升类型安全

第15行的 formStores 类型定义为 FormStore<any>。使用 any 会降低类型安全性,建议改为 unknown 或使用泛型参数。

应用以下代码修改:

-const formStores = new Map<string, FormStore<any>>();
+const formStores = new Map<string, FormStore<unknown>>();
📝 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.

const formStores = new Map<string, FormStore<unknown>>();

29-33: 🛠️ Refactor suggestion

atomFamily 的返回值添加类型声明

第29-33行的匿名函数返回的 localAtom 类型可能被推断为 any。为了提高类型安全性,建议对返回值进行类型声明。

应用以下代码修改:

-      fieldsAtom: atomFamily((id: string) => {
+      fieldsAtom: atomFamily((id: string): Atom<IFormField<T>> => {
📝 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.

    fieldsAtom: atomFamily((id: string): Atom<IFormField<T>> => {
      const localAtom = atom<IFormField<T>>({ value: undefined });
      fieldsMap.set(id, { value: undefined });
      return localAtom;
    }),
🧰 Tools
🪛 eslint

[error] 32-32: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/ApiForm/ApiJsonEdit.tsx (3)

65-65: ⚠️ Potential issue

未将 labelrequired 属性传递给 JsonEdit 组件

ApiJsonEdit 组件中,labelrequired 属性未传递给 JsonEdit,可能导致其无法正确显示或校验必填项。

应用以下改动来修复:

-          <JsonEdit id={id} placeholder={placeholder} />
+          <JsonEdit id={id} placeholder={placeholder} label={label} required={required} />
📝 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.

      <JsonEdit id={id} placeholder={placeholder} label={label} required={required} />

28-31: ⚠️ Potential issue

避免直接修改 Atom 状态

直接修改 field 对象的属性可能不会触发组件更新。建议使用 setField 函数更新状态。

应用以下改动来修复:

-useEffect(() => {
-  field.name = label;
-  field.required = required;
-}, []);
+useEffect(() => {
+  setField({ ...field, name: label, required });
+}, [label, required]);
📝 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.

  useEffect(() => {
    setField({ ...field, name: label, required });
  }, [label, required]);

36-36: ⚠️ Potential issue

为回调函数参数添加类型注解

onChange 回调函数的参数 e 未指定类型,可能导致类型安全问题。建议为 e 添加类型注解。

应用以下改动来修复:

-          onChange={(e) => setField({ ...field, value: e })}
+          onChange={(e: any) => setField({ ...field, value: e })}

或者根据 JsonEditor 组件的 onChange 回调参数的实际类型进行精确的类型定义。

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 36-36: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/ApiForm/ApiField.tsx (3)

59-62: 🧹 Nitpick (assertive)

移除 ApiFieldProps 中的冗余属性

ApiFieldProps 已继承自 ApiInputProps,无需重复声明 idrequired 属性。

建议修改如下:

 export interface ApiFieldProps extends ApiInputProps {
-   id: string;
-   required?: boolean;
 }
📝 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.

export interface ApiFieldProps extends ApiInputProps {
}

47-47: ⚠️ Potential issue

为事件处理函数添加类型注解

onChange 事件处理函数的参数添加类型注解,避免类型不安全的问题。

建议修改如下:

-       onChange={(e) => setField({ ...field, value: e.target.value })}
+       onChange={(e: React.ChangeEvent<HTMLInputElement>) => setField({ ...field, value: e.target.value })}
📝 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.

      onChange={(e: React.ChangeEvent<HTMLInputElement>) => setField({ ...field, value: e.target.value })}
🧰 Tools
🪛 eslint

[error] 47-47: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)


38-39: ⚠️ Potential issue

避免直接修改状态,请使用状态更新函数

直接修改 field 对象可能导致状态不可预测。请使用 setField 方法更新状态。

建议修改如下:

-     field.name = label;
-     field.required = required;
+     setField({ ...field, name: label, required: required });

Committable suggestion skipped: line range outside the PR's diff.

packages/example/components/context/ContextFactory.tsx (3)

49-51: ⚠️ Potential issue

缺少 key 属性

遍历渲染元素时,每个元素都应提供唯一的 key 属性。这有助于 React 正确跟踪元素。

建议在 <Context.Provider> 中添加 key

-<Context.Provider value={state[key as keyof T]}>
+<Context.Provider key={String(key)} value={state[key as keyof T]}>
📝 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.

          <Context.Provider key={String(key)} value={state[key as keyof T]}>
            {acc}
          </Context.Provider>
🧰 Tools
🪛 Biome

[error] 49-51: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


20-20: ⚠️ Potential issue

请避免使用非空断言操作符 !

使用 ! 操作符可能隐藏潜在的 nullundefined 错误。建议添加空值检查,确保代码安全。

建议修改为:

-return FieldContexts.get(field)!;
+const context = FieldContexts.get(field);
+if (!context) {
+  throw new Error(`Context for field ${String(field)} not found`);
+}
+return context;
📝 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.

    const context = FieldContexts.get(field);
    if (!context) {
      throw new Error(`Context for field ${String(field)} not found`);
    }
    return context;
🧰 Tools
🪛 Biome

[error] 20-23: Forbidden non-null assertion.

(lint/style/noNonNullAssertion)


71-71: ⚠️ Potential issue

确保返回值的类型安全

直接返回 useContext(Context) 会导致返回类型为 any。建议明确返回值的类型,提升类型安全性。

可以修改为:

-const useFieldValue = <K extends keyof T>(field: K) => {
+const useFieldValue = <K extends keyof T>(field: K): T[K] => {

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 71-71: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/ApiForm/ApiButton.tsx (4)

55-55: ⚠️ Potential issue

确保返回值类型安全

第 55 行返回的值可能被推断为 any 类型。请确保返回值类型为 string,避免类型不安全。

可以通过显式声明返回类型或确保 field.namefield.id 具有正确的类型定义来解决。

🧰 Tools
🪛 eslint

[error] 55-55: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)


36-38: ⚠️ Potential issue

使用 setField 更新状态

useEffect 中直接修改 field.name 并不会触发组件更新。请使用 setField 来正确更新状态。

建议修改如下:

- useEffect(() => {
-     field.name = label;
- }, []);
+ useEffect(() => {
+     setField({ ...field, name: label });
+ }, []);
📝 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.

    useEffect(() => {
        setField({ ...field, name: label });
    }, []);

102-102: ⚠️ Potential issue

修复 onClick 的类型错误

handleClick 是一个异步函数,返回 Promise,但 onClick 属性期望一个返回 void 的函数。请修改以符合类型要求。

建议修改如下:

- onClick={handleClick}
+ onClick={() => {
+   handleClick().catch((error) => {
+     console.error(error);
+   });
+ }}
📝 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.

                onClick={() => {
                  handleClick().catch((error) => {
                    console.error(error);
                  });
                }}
🧰 Tools
🪛 eslint

[error] 102-102: Promise-returning function provided to attribute where a void return was expected.

(@typescript-eslint/no-misused-promises)


41-41: ⚠️ Potential issue

避免在回调中调用 useAtom

React Hooks(如 useAtom)不能在回调函数中调用。请将 useAtom 的调用移到组件或自定义 Hook 的顶层。

建议修改如下:

- const dependencyStates = availableDependencyFields?.map(fieldId => {
-   const [field] = useAtom(store.fieldsAtom(fieldId));
-   return {
-     id: fieldId,
-     value: field.value,
-     name: field.name
-   };
- }) ?? [];
+ const dependencyAtoms = availableDependencyFields?.map(fieldId => store.fieldsAtom(fieldId)) ?? [];
+ const dependencyFields = dependencyAtoms.map(atom => {
+   const [field] = useAtom(atom);
+   return field;
+ });
+ const dependencyStates = dependencyFields.map(field => ({
+   id: field.id,
+   value: field.value,
+   name: field.name,
+ }));

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 41-41: React Hook "useAtom" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function.

(react-hooks/rules-of-hooks)

packages/example/components/ApiForm/ApiForm.tsx (3)

121-121: 🧹 Nitpick (assertive)

按钮文本可能有拼写错误

第121行,按钮文本为“Rest 请求”。请确认是否应为“Reset 请求”或“重置请求”。如果是拼写错误,建议修改。

修改建议:

- Rest 请求
+ 重置请求
📝 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.

              重置请求

73-73: ⚠️ Potential issue

返回值类型未明确,可能导致类型安全问题

第73行的getValue方法返回了类型为any的值。这可能会引发类型安全问题。建议为返回值添加明确的类型注解。

修复建议:

- return store.scope.get(store.fieldsAtom(id)).value;
+ return store.scope.get(store.fieldsAtom(id)).value as YourValueType;

请将YourValueType替换为实际的类型。

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 73-73: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)


63-63: ⚠️ Potential issue

返回值类型未明确,可能导致类型安全问题

第63行的getField方法返回了类型为any的值。这可能会引发类型安全问题。建议为返回值添加明确的类型注解。

修复建议:

- return store.scope.get(store.fieldsAtom(id));
+ return store.scope.get(store.fieldsAtom(id)) as IFormField<any>;
📝 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.

      return store.scope.get(store.fieldsAtom(id)) as IFormField<any>;
🧰 Tools
🪛 eslint

[error] 63-63: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/ApiForm/ApiSelector.tsx (2)

88-92: 🧹 Nitpick (assertive)

重复的默认值处理逻辑

这个 useEffect 中的默认值处理逻辑与之前的 useEffect (第 66-72 行) 重复。建议移除这个重复的逻辑,以保持代码的简洁。

可以删除第 88-92 行的代码:

- useEffect(() => {
-   if (defaultValue) {
-     setField({ ...field, value: defaultValue });
-   }
- }, []);
📝 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.



58-64: 🛠️ Refactor suggestion

setOptions 函数的实现可以优化

setOptions 函数在设置新选项时,会覆盖字段的整个 extra 对象。这可能会导致 extra 中的其他属性丢失。建议只更新 extra.options,而不是整个 extra 对象。

可以这样优化 setOptions 函数:

const setOptions = useCallback((options: IOption<T>[]) => {
  setField({
    ...field,
-   extra: {
-     options
-   }
+   extra: {
+     ...field.extra,
+     options
+   }
  });
}, [setField]);
📝 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.

  const setOptions = useCallback((options: IOption<T>[]) => {
    setField({
      ...field,
      extra: {
        ...field.extra,
        options
      }
    });
  }, [setField]);
packages/example/components/ui/command.tsx (1)

24-24: 🛠️ Refactor suggestion

简化CommandDialogProps接口

CommandDialogProps接口未添加任何新成员,与DialogProps类型等效。建议直接使用DialogProps类型,移除空的CommandDialogProps接口。

可以按以下diff修改:

-interface CommandDialogProps extends DialogProps {}
+// 移除空的接口

并在CommandDialog组件中直接使用DialogProps类型:

-const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
+const CommandDialog = ({ children, ...props }: DialogProps) => {

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 24-24: An interface declaring no members is equivalent to its supertype.

(@typescript-eslint/no-empty-interface)

packages/example/components/ApiForm/ApiCombobox.tsx (4)

51-51: ⚠️ Potential issue

修正错误信息以匹配组件名称

当前错误信息为 'ApiField must be used within ApiForm',但组件实际是 ApiCombobox。请将错误信息修改为 'ApiCombobox must be used within ApiForm'


113-114: 🧹 Nitpick (assertive)

考虑使用语义化元素提高可访问性

Biome 提示您可以将具有 role="combobox" 的元素替换为原生的 <select> 元素,以增强无障碍性。建议评估是否适合改用 <select>

🧰 Tools
🪛 Biome

[error] 113-114: The elements with the following roles can be changed to the following elements:
For examples and more information, see WAI-ARIA Roles (lint/a11y/useSemanticElements) 119-121: 🧹 Nitpick (assertive) 简化代码直接使用 currentOption.label 您可以简化第 119-121 行的代码,直接使用 currentOption?.label: - {currentOption?.value - ? options.find((option) => option.value === currentOption?.value)?.label - : placeholder} + {currentOption?.label || placeholder} 📝 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. {currentOption?.label || placeholder} 74-76: ⚠️ Potential issue 正确处理 onRequestOptions 返回的 Promise 在第 74-76 行,您调用了 onRequestOptions(),但未处理其返回的 Promise。建议使用 async/await 语法并添加错误处理: useEffect(() => { if (onRequestOptions) { - onRequestOptions().then((options) => { - setOptions(options); - }); + (async () => { + try { + const options = await onRequestOptions(); + setOptions(options); + } catch (error) { + // 处理错误 + } + })(); } }, [onRequestOptions]); Committable suggestion skipped: line range outside the PR's diff. 🧰 Tools 🪛 eslint [error] 74-76: Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the void operator. (@typescript-eslint/no-floating-promises) packages/example/components/chains/ethereum/case/transfer/malicious.ts (5) 1-1: 🧹 Nitpick (assertive) 避免禁用 ESLint 规则 请尽量避免使用 /* eslint-disable @typescript-eslint/no-unsafe-assignment */,通过调整代码以满足 ESLint 规则,可以提高代码质量和可维护性。 50-51: 🛠️ Refactor suggestion 修复类型错误,避免使用 '@ts-expect-error' 在第50-51行和第58-59行,使用了 @ts-expect-error 来忽略 TypeScript 错误。建议修复这些类型错误,而不是忽略它们,以确保代码的类型安全性和可靠性。 Also applies to: 58-59 133-133: ⚠️ Potential issue 检查潜在的敏感信息泄露 静态分析工具检测到第133行和第140行可能存在敏感信息泄露。请检查代码,确保未泄露任何 API 密钥或敏感数据。 Also applies to: 140-140 🧰 Tools 🪛 Gitleaks 133-133: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key) 133-133: Detected a Generic API Key, potentially exposing access to various services and sensitive operations. (generic-api-key) 12-47: 🧹 Nitpick (assertive) 考虑提取重复的字符串 在 sendTransaction 方法中,多次使用了相似的字符串描述。为了提高代码的可维护性,建议将这些字符串提取到一个常量或配置文件中。 49-118: 🧹 Nitpick (assertive) 简化重复的代码片段 sendTransactionERC20 方法中,创建交易对象的过程存在重复。可以提取共用的代码片段为辅助函数,以减少冗余,提升代码清晰度。 packages/example/components/chains/suiStandard/example.tsx (1) 63-82: 🧹 Nitpick (assertive) **** AssetInfoView 组件目前没有渲染任何内容,只是一个空的片段 <></>。考虑添加一些 UI 元素来显示资产信息,或者如果该组件仅用于触发副作用,可以将其转换为自定义 hook。 🧰 Tools 🪛 eslint [error] 73-77: Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the void operator. (@typescript-eslint/no-floating-promises) [error] 75-75: Invalid type "any" of template literal expression. (@typescript-eslint/restrict-template-expressions) [error] 75-75: Invalid type "any" of template literal expression. (@typescript-eslint/restrict-template-expressions) [error] 75-75: Invalid type "any" of template literal expression. (@typescript-eslint/restrict-template-expressions) packages/example/components/chains/ethereum/example.tsx (7) 153-153: ⚠️ Potential issue 避免在模板字符串中使用类型为 'any' 的值 第153行中,nftsContract.address 和 nftsContract.deployTransaction.hash 的类型可能是 any,在模板字符串中使用时可能导致运行时错误。 建议为 nftsContract 的属性添加类型注解,或在使用前进行类型断言。 console.log( - `Contract mined! address: ${nftsContract.address} transactionHash: ${nftsContract.deployTransaction.hash}`, + `Contract mined! address: ${nftsContract.address as string} transactionHash: ${nftsContract.deployTransaction.hash as string}`, ); 📝 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. `Contract mined! address: ${nftsContract.address as string} transactionHash: ${nftsContract.deployTransaction.hash as string}`, 🧰 Tools 🪛 eslint [error] 153-153: Invalid type "any" of template literal expression. (@typescript-eslint/restrict-template-expressions) [error] 153-153: Invalid type "any" of template literal expression. (@typescript-eslint/restrict-template-expressions) 331-331: ⚠️ Potential issue 避免在模板字符串中使用类型为 'any' 的值 第331行中,erc1155Contract.address 和 erc1155Contract.deployTransaction.hash 的类型可能是 any,在模板字符串中使用时可能导致运行时错误。 建议为 erc1155Contract 的属性添加类型注解,或在使用前进行类型断言。 console.log( - `Contract mined! address: ${erc1155Contract.address} transactionHash: ${erc1155Contract.deployTransaction.hash}`, + `Contract mined! address: ${erc1155Contract.address as string} transactionHash: ${erc1155Contract.deployTransaction.hash as string}`, ); 📝 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. `Contract mined! address: ${erc1155Contract.address as string} transactionHash: ${erc1155Contract.deployTransaction.hash as string}`, 🧰 Tools 🪛 eslint [error] 331-331: Invalid type "any" of template literal expression. (@typescript-eslint/restrict-template-expressions) [error] 331-331: Invalid type "any" of template literal expression. (@typescript-eslint/restrict-template-expressions) 90-90: ⚠️ Potential issue 避免将类型为 'any' 的参数传递给 'params' 第90行中,JSON.parse(apiFromRef.current?.getValue('request') ?? '') 的返回值可能是 any,直接传递给 params 可能导致类型不安全。 建议确保解析后的对象具有明确的类型。 - 'params': JSON.parse(apiFromRef.current?.getValue('request') ?? ''), + const requestParams: YourRequestType = JSON.parse(apiFromRef.current?.getValue('request') ?? ''); + 'params': requestParams, 请将 YourRequestType 替换为实际的请求参数类型。 Committable suggestion skipped: line range outside the PR's diff. 🧰 Tools 🪛 eslint [error] 90-90: Unsafe argument of type any assigned to a parameter of type string. (@typescript-eslint/no-unsafe-argument) 732-735: 🛠️ Refactor suggestion 明确返回类型,避免返回 'any' 类型 当前函数返回一个类型为 any 的值,建议为函数指定明确的返回类型,以提高类型安全性。 建议如下: - const requestSendTransactionCommon = async (request: string) => { + const requestSendTransactionCommon = async (request: string): Promise<YourReturnType> => { 请将 YourReturnType 替换为实际的返回值类型。如果确实需要返回 any,也请显式声明。 Committable suggestion skipped: line range outside the PR's diff. 🧰 Tools 🪛 eslint [error] 732-735: Unsafe return of an any typed value. (@typescript-eslint/no-unsafe-return) 64-64: ⚠️ Potential issue 类型安全:确保传递正确类型的参数 第64行中,将 tokenOptions 传递给 setOptions 时,tokenOptions 的类型可能是 any,这可能导致类型不安全。 建议显式声明 tokenOptions 的类型,确保其符合 IOption<any>[] 接口。 - apiFromComboboxRef.current?.setOptions(tokenOptions); + apiFromComboboxRef.current?.setOptions(tokenOptions as IOption<any>[]); 📝 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. apiFromComboboxRef.current?.setOptions(tokenOptions as IOption<any>[]); 🧰 Tools 🪛 eslint [error] 64-64: Unsafe argument of type any assigned to a parameter of type IOption<any>[]. (@typescript-eslint/no-unsafe-argument) 1217-1220: 🛠️ Refactor suggestion 明确返回类型,避免返回 'any' 类型 在处理 eth_signTypedData_v4 的错误情况下,返回值类型为 any,应明确返回类型以提高类型安全性。 建议如下: - onExecute={async (request: string) => { + onExecute={async (request: string): Promise<string> => { 根据实际返回值类型进行修改。 Committable suggestion skipped: line range outside the PR's diff. 🧰 Tools 🪛 eslint [error] 1217-1220: Unsafe return of an any typed value. (@typescript-eslint/no-unsafe-return) 1193-1196: 🛠️ Refactor suggestion 明确返回类型,避免返回 'any' 类型 在 eth_signTypedData_v4 方法中,返回值类型为 any,建议为返回值指定明确的类型,提高类型安全性。 建议如下: - onExecute={async (request: string) => { + onExecute={async (request: string): Promise<string> => { 假设返回值为字符串类型,请根据实际情况修改返回类型。 Committable suggestion skipped: line range outside the PR's diff. 🧰 Tools 🪛 eslint [error] 1193-1196: Unsafe return of an any typed value. (@typescript-eslint/no-unsafe-return)

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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between 6c77d05 and 9843a1f.

⛔ Files ignored due to path filters (1)
  • packages/example/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (26)
  • .github/workflows/deploy-dapp-example-web.yml (1 hunks)
  • .github/workflows/publish-npm-package.yml (1 hunks)
  • packages/example/.env.simple (1 hunks)
  • packages/example/components/ApiForm/ApiAutoTextArea.tsx (1 hunks)
  • packages/example/components/ApiForm/ApiButton.tsx (1 hunks)
  • packages/example/components/ApiForm/ApiCheckbox.tsx (1 hunks)
  • packages/example/components/ApiForm/ApiCombobox.tsx (1 hunks)
  • packages/example/components/ApiForm/ApiField.tsx (1 hunks)
  • packages/example/components/ApiForm/ApiJsonEdit.tsx (1 hunks)
  • packages/example/components/ApiForm/ApiSelector.tsx (1 hunks)
  • packages/example/components/ApiForm/ApiSwitch.tsx (1 hunks)
  • packages/example/components/ApiForm/ApiText.tsx (1 hunks)
  • packages/example/components/ApiForm/ApiTextArea.tsx (1 hunks)
  • packages/example/components/ApiForm/index.ts (1 hunks)
  • packages/example/components/ApiForm/store.ts (1 hunks)
  • packages/example/components/ApiForm/types.ts (1 hunks)
  • packages/example/components/TabCard.tsx (1 hunks)
  • packages/example/components/chains/conflux/example.tsx (4 hunks)
  • packages/example/components/chains/ethereum/example.tsx (5 hunks)
  • packages/example/components/chains/nostr/params.ts (1 hunks)
  • packages/example/components/chains/suiStandard/example.tsx (3 hunks)
  • packages/example/components/chains/suiStandard/utils.ts (1 hunks)
  • packages/example/components/chains/tron/example.tsx (3 hunks)
  • packages/example/components/chains/utils/OkLink.ts (1 hunks)
  • packages/example/components/ui/tooltip.tsx (1 hunks)
  • packages/example/package.json (3 hunks)
🧰 Additional context used
🪛 eslint
packages/example/components/ApiForm/ApiAutoTextArea.tsx

[error] 36-36: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/ApiForm/ApiButton.tsx

[error] 41-41: React Hook "useAtom" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function.

(react-hooks/rules-of-hooks)


[error] 55-55: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)


[error] 102-102: Promise-returning function provided to attribute where a void return was expected.

(@typescript-eslint/no-misused-promises)

packages/example/components/ApiForm/ApiCheckbox.tsx

[error] 39-39: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/ApiForm/ApiCombobox.tsx

[error] 74-76: Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the void operator.

(@typescript-eslint/no-floating-promises)

packages/example/components/ApiForm/ApiField.tsx

[error] 47-47: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/ApiForm/ApiJsonEdit.tsx

[error] 36-36: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/ApiForm/ApiSelector.tsx

[error] 76-78: Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the void operator.

(@typescript-eslint/no-floating-promises)

packages/example/components/ApiForm/ApiSwitch.tsx

[error] 39-39: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/ApiForm/ApiTextArea.tsx

[error] 36-36: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/ApiForm/store.ts

[error] 20-20: Unsafe argument of type any assigned to a parameter of type string.

(@typescript-eslint/no-unsafe-argument)


[error] 21-21: Unsafe argument of type any assigned to a parameter of type string.

(@typescript-eslint/no-unsafe-argument)


[error] 32-32: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)


[error] 42-42: Unsafe argument of type any assigned to a parameter of type string.

(@typescript-eslint/no-unsafe-argument)

packages/example/components/chains/conflux/example.tsx

[error] 92-92: Unsafe argument of type any assigned to a parameter of type string.

(@typescript-eslint/no-unsafe-argument)

packages/example/components/chains/ethereum/example.tsx

[error] 53-53: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)


[error] 53-53: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)


[error] 64-64: Unsafe argument of type any assigned to a parameter of type IOption<any>[].

(@typescript-eslint/no-unsafe-argument)


[error] 90-90: Unsafe argument of type any assigned to a parameter of type string.

(@typescript-eslint/no-unsafe-argument)


[error] 153-153: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)


[error] 153-153: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)


[error] 331-331: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)


[error] 331-331: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)


[error] 732-735: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)


[error] 1193-1196: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)


[error] 1217-1220: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/chains/suiStandard/example.tsx

[error] 52-54: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)


[error] 73-77: Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the void operator.

(@typescript-eslint/no-floating-promises)


[error] 75-75: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)


[error] 75-75: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)


[error] 75-75: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)


[error] 104-104: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)


[error] 107-107: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)


[error] 113-122: Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the void operator.

(@typescript-eslint/no-floating-promises)


[error] 114-114: Unsafe argument of type any assigned to a parameter of type Iterable<unknown> | ArrayLike<unknown>.

(@typescript-eslint/no-unsafe-argument)


[error] 144-144: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)


[error] 154-154: Unsafe argument of type any assigned to a parameter of type string.

(@typescript-eslint/no-unsafe-argument)


[error] 165-165: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

packages/example/components/chains/tron/example.tsx

[error] 26-42: Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the void operator.

(@typescript-eslint/no-floating-promises)

🪛 Biome
packages/example/components/ApiForm/ApiCombobox.tsx

[error] 113-114: The elements with the following roles can be changed to the following elements:
For examples and more information, see WAI-ARIA Roles (lint/a11y/useSemanticElements) packages/example/components/chains/suiStandard/example.tsx [error] 111-111: Change to an optional chain. Unsafe fix: Change to an optional chain. (lint/complexity/useOptionalChain) [error] 152-152: Unsafe usage of optional chaining. If it short-circuits with 'undefined' the evaluation will throw TypeError here: (lint/correctness/noUnsafeOptionalChaining) 🔇 Additional comments (38) packages/example/.env.simple (1) 7-7: 提醒:验证 OKLINK_API_KEY 的使用情况 需要确认新添加的 OKLINK_API_KEY 在代码库中的使用方式是否安全合规。 packages/example/components/ApiForm/types.ts (1) 1-20: 接口设计清晰,结构合理 整体类型定义简洁明了,泛型使用恰当,能够很好地支持表单状态管理和验证功能。 packages/example/components/chains/nostr/params.ts (1) 21-24: ⚠️ Potential issue 测试用例值可能过短 当前测试值 '010203' 作为 Schnorr 签名测试用例可能过短: Schnorr 签名通常需要 64 字节(128 个十六进制字符) 建议添加一个更接近实际场景的测试值 建议添加标准长度的测试值: id: 'signSchnorr', name: 'Hex String - 硬件报错符合预期', - value: '010203', + value: '7d47a054e5dad6c1f4b55dc2653ec7c9734561ae15f9d59cc892118ad1d1edf96ed2a8ae437f5d4abd2c24e08bdc772d6f3f0e4b8b19509a015f2283c2e0b507', packages/example/components/chains/suiStandard/utils.ts (2) 5-5: 导入语句组织合理! 新增的导入语句与功能扩展相符,符合代码组织规范。 Also applies to: 7-7 Line range hint 15-30: 注意:需要验证非 SUI 代币的处理逻辑 当前实现可能无法正确处理非 SUI 代币的情况。getCoins 调用需要考虑 coinType 参数。 建议修改实现如下: - const coins = await client.getCoins({ owner: sender, limit: 1 }); + const coins = await client.getCoins({ + owner: sender, + coinType: coinType, + limit: 1 + }); 执行以下命令验证其他代码是否正确处理了不同的代币类型: packages/example/components/ui/tooltip.tsx (3) 1-4: 导入声明看起来很清晰! 导入了必要的依赖,包括React核心、Radix UI工具包和本地工具函数。代码结构简洁明了。 6-10: 组件别名定义简洁有效! 直接从Radix UI重新导出基础组件,便于维护和使用。这种方式可以在将来需要扩展组件功能时提供良好的灵活性。 28-28: 导出语句简洁明了! 命名导出方式清晰,便于使用方按需导入所需组件。 packages/example/components/ApiForm/ApiSwitch.tsx (1) 6-10: 🧹 Nitpick (assertive) 接口定义清晰但可以改进类型安全性 建议为 defaultChecked 明确指定布尔类型,增强类型安全。 export interface ApiSwitchProps { id: string; label?: string; - defaultChecked?: boolean; + defaultChecked?: boolean | undefined; } Likely invalid or redundant comment. packages/example/components/ApiForm/ApiCheckbox.tsx (1) 56-56: 组件命名设置正确 正确设置了组件的 displayName,这对开发工具和调试很有帮助。 packages/example/components/TabCard.tsx (1) 1-42: 验证组件使用情况 需要检查组件在代码库中的使用情况,确保接口变更不会影响现有代码。 ✅ Verification successful TabCard 组件接口变更安全可行 TabCard 组件仅在 example.tsx 中使用了两次,且用法与新接口完全匹配: 传入了正确的 tabs 数组属性,包含所需的 label、value、title、description 和 content 字段 没有传入 defaultValue 属性,符合可选参数设计 🏁 Scripts executed The following scripts were executed for the analysis: Script: #!/bin/bash # 搜索 TabCard 组件的使用情况 echo "查找 TabCard 组件的引用..." rg -l "TabCard" # 检查是否有类似的标签页组件 echo "检查是否存在类似组件..." rg -l "Tabs.*Card|Card.*Tabs" Length of output: 340 Script: #!/bin/bash # 查看 TabCard 的具体使用情况 echo "检查 TabCard 在 example.tsx 中的使用..." rg -A 10 "TabCard" packages/example/components/chains/ethereum/example.tsx # 检查 TabCard 的属性传递 echo "检查 TabCard 属性的使用方式..." ast-grep --pattern 'const $_ = &lt;TabCard $$$>' ast-grep --pattern '<TabCard $$$>' Length of output: 1107 packages/example/components/ApiForm/ApiAutoTextArea.tsx (2) 1-13: 代码结构清晰,接口定义合理! 导入语句简洁明了,接口定义包含了必要的属性。 69-69: 设置 displayName 是个好习惯! 为组件设置 displayName 有助于调试,这是一个很好的实践。 packages/example/components/ApiForm/index.ts (4) 1-12: 导入语句组织良好! 导入语句遵循了一致的模式,每个组件都单独导入,便于维护和阅读。 28-38: 组件分配结构清晰! 组件分配遵循了类型定义的顺序,结构清晰明了。 40-51: 导出设计规范合理! 特别赞赏将 IOption 重命名为 ComboboxOption 的做法,这样的命名更加直观和语义化。所有必要的类型都已正确导出。 14-26: 🧹 Nitpick (assertive) 建议考虑使用接口合并来简化类型定义 当前的类型断言方法虽然可行,但使用 TypeScript 的接口合并可能会更加优雅。 考虑使用以下方式重构: -const Form = ApiForm as typeof ApiForm & { - Field: typeof ApiField; - Button: typeof ApiButton; - // ... -}; +interface ApiForm { + Field: typeof ApiField; + Button: typeof ApiButton; + // ... +} +const Form = ApiForm; Likely invalid or redundant comment. packages/example/package.json (2) 37-38: Radix UI 组件库版本更新 所有 Radix UI 组件都更新到了最新的稳定版本,这是个好的实践。新增的 Tabs 和 Tooltip 组件能增强用户界面的交互性。 Also applies to: 40-42, 45-48 64-64: 区块链相关依赖的添加需要验证兼容性 新增了 Uniswap token list 和特定版本的 ethers(5.7.2),建议验证: ethers 5.7.2 是否与项目中其他区块链库兼容 token list 的使用场景是否合理 Also applies to: 86-86 ✅ Verification successful 区块链依赖兼容性验证已完成 经过验证,项目依赖配置合理: ethers 5.7.2 与其他区块链依赖(@ethersproject/bytes 5.0.6、ethereumjs-util 7.1.5)版本兼容 @uniswap/default-token-list 在 ethereum/example.tsx 中与 ethers 配合使用,用于处理以太坊代币列表,使用场景恰当 🏁 Scripts executed The following scripts were executed for the analysis: Script: #!/bin/bash # 检查是否存在其他版本的 ethers 相关依赖 rg '"ethers":|"@ethersproject/' 'package.json' # 检查 token list 的使用情况 rg -l '@uniswap/default-token-list' Length of output: 195 Script: #!/bin/bash # 检查 token list 的具体使用方式 rg -A 5 '@uniswap/default-token-list' packages/example/components/chains/ethereum/example.tsx # 检查项目中所有的区块链相关依赖 cat packages/example/package.json | jq '.dependencies + .devDependencies' | grep -i "eth\|web3\|chain" # 检查 ethers 的具体使用方式 ast-grep --pattern 'import $_ from "ethers"' Length of output: 806 packages/example/components/ApiForm/store.ts (1) 20-21: ⚠️ Potential issue 修复类型不安全的参数 在第 20 行和第 21 行,formId 可能不是字符串类型,导致类型不安全的赋值。请确保 formId 的类型为 string。 应用以下修改来确保 formId 的类型: -export const createFormStore = <T = string>(id?: string): FormStore<T> => { - const formId = id || nanoid(); +export const createFormStore = <T = string>(id?: string): FormStore<T> => { + const formId: string = id || nanoid(); Likely invalid or redundant comment. 🧰 Tools 🪛 eslint [error] 20-20: Unsafe argument of type any assigned to a parameter of type string. (@typescript-eslint/no-unsafe-argument) [error] 21-21: Unsafe argument of type any assigned to a parameter of type string. (@typescript-eslint/no-unsafe-argument) packages/example/components/ApiForm/ApiField.tsx (2) 18-57: ApiInput 组件的实现看起来不错! 使用 memo 进行了性能优化。 通过 useContext 获取表单上下文。 使用 Jotai 的 useAtom 管理表单字段的状态。 组件挂载时设置默认值。 根据 hidden 属性有条件地渲染错误信息。 总的来说,这个组件的实现是合理且优雅的。 🧰 Tools 🪛 eslint [error] 47-47: Unsafe return of an any typed value. (@typescript-eslint/no-unsafe-return) 64-84: ApiField 组件的实现看起来很棒! 使用 memo 进行了性能优化。 根据 hidden 和 label 属性有条件地渲染标签。 标签中使用 htmlFor 关联表单控件,提高了可访问性。 根据 required 属性添加红色星号,突出必填项。 组合使用 ApiInput 组件,减少了重复代码。 总的来说,这个组件的设计和实现都很优秀,没有明显的问题。 packages/example/components/chains/tron/example.tsx (3) 19-88: 新增的 WalletWatchAsset 组件看起来不错! 这个组件封装了观察 TRC20 资产的功能,使用了 React 的最佳实践,如 memo、useRef 和 useEffect 等。它还利用了 ApiForm 组件来管理表单状态和用户交互。总的来说,这个组件的设计和实现都很优秀。 🧰 Tools 🪛 eslint [error] 26-42: Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the void operator. (@typescript-eslint/no-floating-promises) 317-317: 很好地将 WalletWatchAsset 组件集成到了 Tron 示例中。 这样可以让用户方便地管理 TRC20 资产,提高了组件的可重用性和模块化。 26-42: ⚠️ Potential issue 修复 eslint 错误: 未处理的 Promise。 静态分析工具提示这里有一个未处理的 Promise,可能会导致潜在的错误。建议使用 .catch() 来处理可能的错误,或者如果你选择忽略这个错误,可以使用 void 操作符来显式地标记它。 useEffect(() => { okLinkRequest.getTokenList('TRON', 'TRC20').then((tokens) => { // ... - }) + }).catch((error) => { + console.error('获取 TRC20 代币列表失败:', error); + // 显示错误提示给用户 + }); }, []); 或者,如果你选择忽略这个错误: useEffect(() => { - okLinkRequest.getTokenList('TRON', 'TRC20').then((tokens) => { + void okLinkRequest.getTokenList('TRON', 'TRC20').then((tokens) => { // ... }) }, []); 🧰 Tools 🪛 eslint [error] 26-42: Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the void operator. (@typescript-eslint/no-floating-promises) packages/example/components/chains/suiStandard/example.tsx (4) 47-61: **** 函数 normalizeSuiCoinType 的实现看起来不错。它对 coinType 进行了标准化处理,并添加了错误处理。 🧰 Tools 🪛 eslint [error] 52-54: Invalid type "any" of template literal expression. (@typescript-eslint/restrict-template-expressions) 63-82: **** AssetInfoView 组件使用 useContext 和 useEffect 很好地获取和显示了资产的元数据信息。它还更新了表单字段,提高了用户体验。 🧰 Tools 🪛 eslint [error] 73-77: Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the void operator. (@typescript-eslint/no-floating-promises) [error] 75-75: Invalid type "any" of template literal expression. (@typescript-eslint/restrict-template-expressions) [error] 75-75: Invalid type "any" of template literal expression. (@typescript-eslint/restrict-template-expressions) [error] 75-75: Invalid type "any" of template literal expression. (@typescript-eslint/restrict-template-expressions) 444-446: **** 在 Example 组件中添加了 TransferForm,允许用户直接在应用程序中执行资产转账。这提高了应用的功能性和可用性。 143-150: ⚠️ Potential issue **** 在执行转账之前,应该先检查总余额是否足够。目前的实现可能会在余额不足时抛出错误。建议在构建交易之前添加余额检查: const totalBalance = coins.reduce((acc, coin) => { return acc.plus(new BigNumber(coin.balance)); }, new BigNumber(0)); + if (totalBalance.lt(amountBN)) { + apiFromRef.current?.setValue('result', '余额不足'); + throw new Error('Insufficient balance'); + } Likely invalid or redundant comment. 🧰 Tools 🪛 eslint [error] 144-144: Unsafe return of an any typed value. (@typescript-eslint/no-unsafe-return) packages/example/components/chains/conflux/example.tsx (3) 4-4: LGTM! 引入 axios 库以支持从指定 URL 获取 token 列表。 20-20: LGTM! 引入必要的 ApiComboboxRef、ApiForm 和 ApiFormRef 组件以支持新的 WalletWatchAsset 组件的功能。 545-547: 将新的 WalletWatchAsset 组件集成到现有的 API 结构中。 新组件被添加到一个名为 "wallet_watchAsset (EIP 747)" 的新 ApiGroup 中,与用于管理钱包资产的现有 API 结构很好地融合在一起。 packages/example/components/chains/ethereum/example.tsx (6) 5-6: LGTM! 新增的导入语句没有问题。 24-25: LGTM! 新增的导入语句没有问题。 26-41: LGTM! 导入合约 JSON 文件的语句没有问题。 1165-1169: LGTM! 新增的 ApiGroup 和相关组件没有问题。 1171-1203: LGTM! 新增的恶意交易签名测试相关的 ApiGroup 和 ApiPayload 没有问题。 🧰 Tools 🪛 eslint [error] 1193-1196: Unsafe return of an any typed value. (@typescript-eslint/no-unsafe-return) 1205-1227: LGTM! 新增的参数缺失或不正确的交易和签名测试相关的 ApiGroup 和 ApiPayload 没有问题。 🧰 Tools 🪛 eslint [error] 1217-1220: Unsafe return of an any typed value. (@typescript-eslint/no-unsafe-return)

Comment on lines +5 to +7
# oklink api key
NEXT_PUBLIC_OKLINK_API_KEY=xxxx
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

建议:改进环境变量的文档说明和安全性

建议对每个 API 密钥添加更详细的说明,包括:

  • 用途说明
  • 获取方式
  • 是否必填
  • 相关文档链接

同时建议:

  1. 添加一个示例 .env.example 文件用于版本控制
  2. 将实际的 .env 文件添加到 .gitignore
  3. 在 README 中说明环境变量的配置步骤
# wallet connect v2 project id
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=xxxx
NEXT_PUBLIC_WALLET_CONNECT_RELAY_URL=wss://relay.walletconnect.com

# Blockfrost API key for Cardano integration
# Required for Cardano network operations
# Get your key at: https://blockfrost.io
NEXT_PUBLIC_BLOCKFROST_CARDANO_PROJECT_ID=xxxx

# Oklink API key for blockchain data
# Required for asset management features
# Get your key at: https://www.oklink.com
NEXT_PUBLIC_OKLINK_API_KEY=xxxx
📝 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
NEXT_PUBLIC_BLOCKFROST_CARDANO_PROJECT_ID=xxxx
# oklink api key
NEXT_PUBLIC_OKLINK_API_KEY=xxxx
# wallet connect v2 project id
NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=xxxx
NEXT_PUBLIC_WALLET_CONNECT_RELAY_URL=wss://relay.walletconnect.com
# Blockfrost API key for Cardano integration
# Required for Cardano network operations
# Get your key at: https://blockfrost.io
NEXT_PUBLIC_BLOCKFROST_CARDANO_PROJECT_ID=xxxx
# Oklink API key for blockchain data
# Required for asset management features
# Get your key at: https://www.oklink.com
NEXT_PUBLIC_OKLINK_API_KEY=xxxx

Comment on lines +16 to +20
// 新增: 验证规则类型
export interface IValidationRule {
fields: string[]; // 需要验证的字段
validator?: (values: Record<string, string>) => string | undefined; // 自定义验证函数
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

建议改进验证器的返回类型

验证器函数返回 string | undefined 不够明确。建议使用专门的错误类型或者对象来提供更多的错误信息。

-  validator?: (values: Record<string, string>) => string | undefined;
+  validator?: (values: Record<string, string>) => {
+    message?: string;
+    code?: string;
+    field?: string;
+  } | undefined;
📝 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 interface IValidationRule {
fields: string[]; // 需要验证的字段
validator?: (values: Record<string, string>) => string | undefined; // 自定义验证函数
}
// 新增: 验证规则类型
export interface IValidationRule {
fields: string[]; // 需要验证的字段
validator?: (values: Record<string, string>) => {
message?: string;
code?: string;
field?: string;
} | undefined; // 自定义验证函数
}

Comment on lines +1 to +8
export interface IFormField<T> {
value: T;
name?: string;
disabled?: boolean;
error?: string;
required?: boolean;
extra?: Record<string, any>;
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

建议优化 extra 属性的类型安全性

extra 属性使用 Record<string, any> 可能会导致类型安全问题。建议定义一个更具体的接口来约束额外属性。

-  extra?: Record<string, any>;
+  extra?: {
+    placeholder?: string;
+    description?: string;
+    [key: string]: string | undefined;
+  };

Committable suggestion skipped: line range outside the PR's diff.

@@ -19,7 +19,7 @@ export default {
},
{
id: 'signSchnorr',
name: 'Hex String',
name: 'Hex String - 硬件报错符合预期',
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

参数名称需要更规范化

建议将参数名称调整为更专业的格式:

  • 避免在参数名中直接使用"硬件报错符合预期"这样的测试结果描述
  • 建议将测试预期结果移至注释或文档中

建议修改为:

-      name: 'Hex String - 硬件报错符合预期',
+      name: 'Invalid Hex String',
+      // 预期:硬件将报错
📝 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
name: 'Hex String - 硬件报错符合预期',
name: 'Invalid Hex String',
// 预期:硬件将报错

Comment on lines 8 to +12
export async function sponsorTransaction(
client: SuiClient,
sender: string,
transactionKindBytes: Uint8Array,
coinType: string = SUI_TYPE_ARG,
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

建议添加参数文档说明

函数签名的改动很好,但建议为新增的 coinType 参数添加 JSDoc 注释,说明其用途和可能的取值范围。

建议添加如下注释:

+/**
+ * @param coinType - 交易代币类型,默认为 SUI
+ */
export async function sponsorTransaction(
📝 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 async function sponsorTransaction(
client: SuiClient,
sender: string,
transactionKindBytes: Uint8Array,
coinType: string = SUI_TYPE_ARG,
/**
* @param coinType - 交易代币类型,默认为 SUI
*/
export async function sponsorTransaction(
client: SuiClient,
sender: string,
transactionKindBytes: Uint8Array,
coinType: string = SUI_TYPE_ARG,

Comment on lines +1217 to +1220
return await provider?.request({
'method': 'eth_signTypedData_v4',
'params': [account.address, request],
})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

修复 onExecute 回调函数的返回值类型。

[eslint] 报告了一个错误,指出该函数返回了 any 类型的不安全值。为了提高类型安全性,请明确指定返回值的类型。

-onExecute={async (request: string) => {
+onExecute={async (request: string): Promise<string> => {
   return await provider?.request({
     'method': 'eth_signTypedData_v4',
     'params': [account.address, request],
   })
 }}

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 1217-1220: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

Comment on lines +732 to 735
return await provider?.request({
'method': 'eth_sendTransaction',
'params': [JSON.parse(request)],
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

修复 requestSendTransactionCommon 函数的返回值类型。

[eslint] 报告了一个错误,指出该函数返回了 any 类型的不安全值。为了提高类型安全性,请明确指定返回值的类型。

-const requestSendTransactionCommon = async (request: string) => {
+const requestSendTransactionCommon = async (request: string): Promise<string> => {
   return await provider?.request({
     'method': 'eth_sendTransaction',
     'params': [JSON.parse(request)],
   });
 };

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 732-735: Unsafe return of an any typed value.

(@typescript-eslint/no-unsafe-return)

Comment on lines +289 to +488
availableDependencyFields={['mintTokenId', 'mintAmount']}
validation={{
fields: ['mintTokenId', 'mintAmount'],
validator: (values) => {
if (!values.mintTokenId.value) {
return '请输入铸造的 Token IDs';
}
if (!values.mintAmount.value) {
return '请输入铸造数量';
}

if (values.mintTokenId.value.split(',').length !== values.mintAmount.value.split(',').length) {
return '铸造的 Token IDs 和铸造数量数量不一致';
}

if (!account) {
return '请连接钱包';
}
if (!erc1155Contract) {
return '请部署 ERC1155 合约';
}
}
}}
/>

<ApiForm.TextArea
id="mintResponse"
label="铸造结果"
/></>,
},
{
label: '使用 ERC1155 合约',
value: 'use',
title: '使用 ERC1155 合约',
description: '使用当前帐户已经部署的 ERC1155 合约,测试 wallet_watchAsset ERC1155,在区块浏览器中查找 Owner 为当前帐户的 ERC1155 资产,填写 Contract Address 和 TokenId 进行观察',
content: <ApiForm.Field
id="watchContractAddress"
label="已经部署的 ERC1155 合约地址"
/>,
},
]} />

<ApiForm.Field
id="watchTokenId"
label="观察 TokenId"
defaultValue="1"
type="number"
required
/>

<ApiForm.Button
id="watchButton"
label="观察 Asset"
onClick={async () => {
const watchContractAddress = apiFromRef.current?.getValue('watchContractAddress');
const nftsContractAddress = erc1155Contract?.address ?? watchContractAddress;

const watchTokenId = apiFromRef.current?.getValue('watchTokenId');
let watchNftsResult;
try {
watchNftsResult = await provider?.request({
method: 'wallet_watchAsset',
params: {
type: 'ERC1155',
options: {
address: nftsContractAddress,
tokenId: watchTokenId,
},
},
}
);
} catch (error) {
console.error(error);
}

apiFromRef.current?.setValue('watchResponse', JSON.stringify(watchNftsResult, null, 2));
}}
availableDependencyFields={['watchTokenId']}
validation={{
fields: ['watchTokenId', 'watchContractAddress'],
validator: (values) => {
if (!values.watchTokenId.value) {
return '请输入观察 TokenId';
}
if (!account) {
return '请连接钱包';
}
if (!erc1155Contract && !values.watchContractAddress?.value) {
return '请部署 ERC1155 合约 或 填写已经部署的 ERC1155 合约地址';
}
}
}}
/>

<ApiForm.TextArea
id="watchResponse"
label="观察结果"
/>
</ApiForm>
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

优化 WalletWatchAssetERC1155 组件的代码结构。

考虑将部署合约和铸造 NFT 的逻辑提取到单独的函数中,以提高代码的可读性和可维护性。这样可以让组件更专注于渲染逻辑。

+const deployERC1155Contract = async (provider: any) => {
+  const ethersProvider = new ethers.providers.Web3Provider(provider, 'any');
+  erc1155Factory = new ethers.ContractFactory(
+    erc1155Abi,
+    erc1155Bytecode,
+    ethersProvider.getSigner(),
+  );
+  erc1155Contract = await erc1155Factory.deploy();
+  await erc1155Contract.deployTransaction.wait();
+  return erc1155Contract;
+};
+
+const mintERC1155NFTs = async (erc1155Contract: any, account: any, mintTokenIds: string, mintAmounts: string) => {
+  const params = [
+    account?.address,
+    mintTokenIds.split(',').map(Number),
+    mintAmounts.split(',').map(Number),
+    '0x',
+  ];
+  let result = await erc1155Contract.mintBatch(...params);
+  result = await result.wait();
+  return result;
+};
+
 const WalletWatchAssetERC1155 = ({ chainId }: { chainId: string | undefined }) => {
   // ...
   return (
     <ApiForm title="wallet_watchAsset ERC1155" description='添加 ERC1155 资产 尽量使用手续费低的链' ref={apiFromRef}>
       <TabCard tabs={[
         {
           label: '部署合约',
           value: 'deploy',
           title: '部署 ERC1155 合约',
           description: '部署 ERC1155 合约,用于测试 wallet_watchAsset ERC1155,尽量使用手续费低的链',
           content: (
             <>
               <ApiForm.Button
                 id="deployButton"
                 label="部署 ERC1155 合约"
                 onClick={async () => {
                   try {
-                    const ethersProvider = new ethers.providers.Web3Provider(provider, 'any');
-                    erc1155Factory = new ethers.ContractFactory(
-                      erc1155Abi,
-                      erc1155Bytecode,
-                      ethersProvider.getSigner(),
-                    );
-                    erc1155Contract = await erc1155Factory.deploy();
-                    await erc1155Contract.deployTransaction.wait();
+                    erc1155Contract = await deployERC1155Contract(provider);
                   } catch (error) {
                     // ...
                   }
                   // ...
                 }}
               />
               {/* ... */}
               <ApiForm.Button
                 id="mintButton"
                 label="铸造"
                 onClick={async () => {
                   const mintTokenIds = apiFromRef.current?.getValue('mintTokenId');
                   const mintAmounts = apiFromRef.current?.getValue('mintAmount');
                   try {
-                    const params = [
-                      account?.address,
-                      mintTokenIds.split(',').map(Number),
-                      mintAmounts.split(',').map(Number),
-                      '0x',
-                    ];
-                    let result = await erc1155Contract.mintBatch(...params);
-                    result = await result.wait();
+                    await mintERC1155NFTs(erc1155Contract, account, mintTokenIds, mintAmounts);
                   } catch (error) {
                     // ...
                   }
                   // ...
                 }}
                 // ...
               />
               {/* ... */}
             </>
           ),
         },
         // ...
       ]} />
       {/* ... */}
     </ApiForm>
   );
 };

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 331-331: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)


[error] 331-331: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)

Comment on lines +111 to +287
}

if (nftsContract.address === undefined) {
return;
}

apiFromRef.current?.setValue('mintResponse', nftsContract.address);
}}
availableDependencyFields={['mintAmount']}
validation={{
fields: ['mintAmount'],
validator: (values) => {
if (!values.mintAmount.value) {
return '请输入铸造数量';
}
if (!account) {
return '请连接钱包';
}
if (!nftsContract) {
return '请部署 ERC721 合约';
}
}
}}
/>

<ApiForm.TextArea
id="mintResponse"
label="铸造结果"
/></>,
},
{
label: '使用 ERC721 合约',
value: 'use',
title: '使用 ERC721 合约',
description: '使用当前帐户已经部署的 ERC721 合约,测试 wallet_watchAsset ERC721,在区块浏览器中查找 Owner 为当前帐户的 ERC721 资产,填写 Contract Address 和 TokenId 进行观察',
content: <ApiForm.Field
id="watchContractAddress"
label="已经部署的 ERC721 合约地址"
/>,
},
]} />

<ApiForm.Field
id="watchTokenId"
label="观察 TokenId"
defaultValue="1"
type="number"
required
/>

<ApiForm.Button
id="watchButton"
label="观察 Asset"
onClick={async () => {
const watchTokenId = apiFromRef.current?.getValue('watchTokenId');
const watchContractAddress = apiFromRef.current?.getValue('watchContractAddress');
const nftsContractAddress = nftsContract?.address ?? watchContractAddress;

let watchNftsResult;
try {
watchNftsResult = await provider?.request({
method: 'wallet_watchAsset',
params: {
type: 'ERC721',
options: {
address: nftsContractAddress,
tokenId: watchTokenId,
},
},
}
);
} catch (error) {
console.error(error);
}

apiFromRef.current?.setValue('watchResponse', JSON.stringify(watchNftsResult, null, 2));
}}
availableDependencyFields={['watchTokenId']}
validation={{
fields: ['watchTokenId', 'watchContractAddress'],
validator: (values) => {
if (!values.watchTokenId?.value) {
return '请输入观察 TokenId';
}
if (!account) {
return '请连接钱包';
}
if (!nftsContract && !values.watchContractAddress?.value) {
return '请部署 ERC721 合约 或 填写已经部署的 ERC721 合约地址';
}
}
}}
/>

<ApiForm.TextArea
id="watchResponse"
label="观察结果"
/>
</ApiForm>
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

优化 WalletWatchAssetERC721 组件的代码结构。

考虑将部署合约和铸造 NFT 的逻辑提取到单独的函数中,以提高代码的可读性和可维护性。这样可以让组件更专注于渲染逻辑。

+const deployERC721Contract = async (provider: any) => {
+  const ethersProvider = new ethers.providers.Web3Provider(provider, 'any');
+  nftsFactory = new ethers.ContractFactory(
+    nftsAbi,
+    nftsBytecode,
+    ethersProvider.getSigner(),
+  );
+  nftsContract = await nftsFactory.deploy();
+  await nftsContract.deployTransaction.wait();
+  return nftsContract;
+};
+
+const mintERC721NFTs = async (nftsContract: any, account: any, mintAmount: string) => {
+  let result = await nftsContract.mintNFTs(mintAmount, {
+    from: account?.address,
+  });
+  result = await result.wait();
+  return result;
+};
+
 const WalletWatchAssetERC721 = ({ chainId }: { chainId: string | undefined }) => {
   // ...
   return (
     <ApiForm title="wallet_watchAsset ERC721" description='添加 ERC721 资产' ref={apiFromRef}>
       <TabCard tabs={[
         {
           label: '部署合约',
           value: 'deploy',
           title: '部署 ERC721 合约',
           description: '部署 ERC721 合约,用于测试 wallet_watchAsset ERC721,尽量使用手续费低的链',
           content: (
             <>
               <ApiForm.Button
                 id="deployButton"
                 label="部署 ERC721 合约"
                 onClick={async () => {
                   try {
-                    const ethersProvider = new ethers.providers.Web3Provider(provider, 'any');
-                    nftsFactory = new ethers.ContractFactory(
-                      nftsAbi,
-                      nftsBytecode,
-                      ethersProvider.getSigner(),
-                    );
-                    nftsContract = await nftsFactory.deploy();
-                    await nftsContract.deployTransaction.wait();
+                    nftsContract = await deployERC721Contract(provider);
                   } catch (error) {
                     // ...
                   }
                   // ...
                 }}
               />
               {/* ... */}
               <ApiForm.Button
                 id="mintButton"
                 label="铸造"
                 onClick={async () => {
                   const mintAmount = apiFromRef.current?.getValue('mintAmount');
                   try {
-                    let result = await nftsContract.mintNFTs(mintAmount, {
-                      from: account?.address,
-                    });
-                    result = await result.wait();
+                    await mintERC721NFTs(nftsContract, account, mintAmount);
                   } catch (error) {
                     // ...
                   }
                   // ...
                 }}
                 // ...
               />
               {/* ... */}
             </>
           ),
         },
         // ...
       ]} />
       {/* ... */}
     </ApiForm>
   );
 };

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 153-153: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)


[error] 153-153: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)

Comment on lines +43 to +109
const WalletWatchAsset = ({ chainId }: { chainId: string | undefined }) => {
const apiFromRef = useRef<ApiFormRef>(null);
const apiFromComboboxRef = useRef<ApiComboboxRef>(null);

const { provider } = useWallet<IEthereumProvider>();

useEffect(() => {
const tokens = TokenList.tokens.filter((token) => parseChainId(chainId) === token.chainId);
const tokenOptions = tokens.map((token) => ({
value: token.address,
label: `${token.name} - ${token.address}`,
extra: {
type: 'ERC20',
options: {
address: token.address,
symbol: token.symbol,
decimals: token.decimals,
image: token.logoURI,
}
}
}));
apiFromComboboxRef.current?.setOptions(tokenOptions);
}, [chainId]);

return <ApiForm title="wallet_watchAsset ERC20" description='添加 ERC20 资产' ref={apiFromRef}>
<ApiForm.Combobox
ref={apiFromComboboxRef}
id="tokenSelector"
label="预设参数"
placeholder="请选择 ERC20 Token"
onOptionChange={(option) => {
apiFromRef.current?.setJsonValue('request', option?.extra);
}}
/>

<ApiForm.JsonEdit
id="request"
label="请求(可以手动编辑)"
required
/>

<ApiForm.Button
id="watchButton"
label="观察 Asset"
onClick={async () => {
const res = await provider?.request({
'method': 'wallet_watchAsset',
'params': JSON.parse(apiFromRef.current?.getValue('request') ?? ''),
});
apiFromRef.current?.setValue('response', JSON.stringify(res, null, 2));
}}
validation={{
fields: ['request'],
validator: (values) => {
if (!values.request) {
return '请选择 ERC20 Token';
}
}
}}
/>

<ApiForm.TextArea
id="response"
label="执行结果"
/>
</ApiForm>
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

优化 WalletWatchAsset 组件的代码结构。

考虑将获取 token 列表的逻辑提取到一个单独的函数中,以提高代码的可读性和可维护性。这样可以让组件更专注于渲染逻辑。

+const getTokenOptions = (chainId: string | undefined) => {
+  const tokens = TokenList.tokens.filter((token) => parseChainId(chainId) === token.chainId);
+  return tokens.map((token) => ({
+    value: token.address,
+    label: `${token.name} - ${token.address}`,
+    extra: {
+      type: 'ERC20',
+      options: {
+        address: token.address,
+        symbol: token.symbol,
+        decimals: token.decimals,
+        image: token.logoURI,
+      }
+    }
+  }));
+};
+
 const WalletWatchAsset = ({ chainId }: { chainId: string | undefined }) => {
   // ...
   useEffect(() => {
-    const tokens = TokenList.tokens.filter((token) => parseChainId(chainId) === token.chainId);
-    const tokenOptions = tokens.map((token) => ({
-      value: token.address,
-      label: `${token.name} - ${token.address}`,
-      extra: {
-        type: 'ERC20',
-        options: {
-          address: token.address,
-          symbol: token.symbol,
-          decimals: token.decimals,
-          image: token.logoURI,
-        }
-      }
-    }));
+    const tokenOptions = getTokenOptions(chainId);
     apiFromComboboxRef.current?.setOptions(tokenOptions);
   }, [chainId]);
   // ...
 };
📝 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 WalletWatchAsset = ({ chainId }: { chainId: string | undefined }) => {
const apiFromRef = useRef<ApiFormRef>(null);
const apiFromComboboxRef = useRef<ApiComboboxRef>(null);
const { provider } = useWallet<IEthereumProvider>();
useEffect(() => {
const tokens = TokenList.tokens.filter((token) => parseChainId(chainId) === token.chainId);
const tokenOptions = tokens.map((token) => ({
value: token.address,
label: `${token.name} - ${token.address}`,
extra: {
type: 'ERC20',
options: {
address: token.address,
symbol: token.symbol,
decimals: token.decimals,
image: token.logoURI,
}
}
}));
apiFromComboboxRef.current?.setOptions(tokenOptions);
}, [chainId]);
return <ApiForm title="wallet_watchAsset ERC20" description='添加 ERC20 资产' ref={apiFromRef}>
<ApiForm.Combobox
ref={apiFromComboboxRef}
id="tokenSelector"
label="预设参数"
placeholder="请选择 ERC20 Token"
onOptionChange={(option) => {
apiFromRef.current?.setJsonValue('request', option?.extra);
}}
/>
<ApiForm.JsonEdit
id="request"
label="请求(可以手动编辑)"
required
/>
<ApiForm.Button
id="watchButton"
label="观察 Asset"
onClick={async () => {
const res = await provider?.request({
'method': 'wallet_watchAsset',
'params': JSON.parse(apiFromRef.current?.getValue('request') ?? ''),
});
apiFromRef.current?.setValue('response', JSON.stringify(res, null, 2));
}}
validation={{
fields: ['request'],
validator: (values) => {
if (!values.request) {
return '请选择 ERC20 Token';
}
}
}}
/>
<ApiForm.TextArea
id="response"
label="执行结果"
/>
</ApiForm>
}
const getTokenOptions = (chainId: string | undefined) => {
const tokens = TokenList.tokens.filter((token) => parseChainId(chainId) === token.chainId);
return tokens.map((token) => ({
value: token.address,
label: `${token.name} - ${token.address}`,
extra: {
type: 'ERC20',
options: {
address: token.address,
symbol: token.symbol,
decimals: token.decimals,
image: token.logoURI,
}
}
}));
};
const WalletWatchAsset = ({ chainId }: { chainId: string | undefined }) => {
const apiFromRef = useRef<ApiFormRef>(null);
const apiFromComboboxRef = useRef<ApiComboboxRef>(null);
const { provider } = useWallet<IEthereumProvider>();
useEffect(() => {
const tokenOptions = getTokenOptions(chainId);
apiFromComboboxRef.current?.setOptions(tokenOptions);
}, [chainId]);
return <ApiForm title="wallet_watchAsset ERC20" description='添加 ERC20 资产' ref={apiFromRef}>
<ApiForm.Combobox
ref={apiFromComboboxRef}
id="tokenSelector"
label="预设参数"
placeholder="请选择 ERC20 Token"
onOptionChange={(option) => {
apiFromRef.current?.setJsonValue('request', option?.extra);
}}
/>
<ApiForm.JsonEdit
id="request"
label="请求(可以手动编辑)"
required
/>
<ApiForm.Button
id="watchButton"
label="观察 Asset"
onClick={async () => {
const res = await provider?.request({
'method': 'wallet_watchAsset',
'params': JSON.parse(apiFromRef.current?.getValue('request') ?? ''),
});
apiFromRef.current?.setValue('response', JSON.stringify(res, null, 2));
}}
validation={{
fields: ['request'],
validator: (values) => {
if (!values.request) {
return '请选择 ERC20 Token';
}
}
}}
/>
<ApiForm.TextArea
id="response"
label="执行结果"
/>
</ApiForm>
}
🧰 Tools
🪛 eslint

[error] 53-53: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)


[error] 53-53: Invalid type "any" of template literal expression.

(@typescript-eslint/restrict-template-expressions)


[error] 64-64: Unsafe argument of type any assigned to a parameter of type IOption<any>[].

(@typescript-eslint/no-unsafe-argument)


[error] 90-90: Unsafe argument of type any assigned to a parameter of type string.

(@typescript-eslint/no-unsafe-argument)

Copy link

New and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/@babel/[email protected] None 0 50 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 16.8 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 3.05 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 6.58 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 2.53 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 3.44 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 16.3 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 39.8 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 5 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 4.32 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 19 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 4.57 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 86.9 kB nicolo-ribaudo
npm/@babel/[email protected] Transitive: environment +7 89.9 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 2.52 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 2.42 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 2.68 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 2.56 kB jlhwung
npm/@babel/[email protected] None 0 2.58 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 2.74 kB jlhwung
npm/@babel/[email protected] None 0 2.63 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 2.75 kB jlhwung
npm/@babel/[email protected] None 0 2.53 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 2.57 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 2.52 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 2.74 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 3.91 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 148 kB nicolo-ribaudo
npm/@babel/[email protected] None 0 21.4 kB nicolo-ribaudo
npm/@bcoe/[email protected] None 0 277 kB bcoe
npm/@eslint/[email protected] filesystem, unsafe +4 782 kB eslintbot
npm/@gar/[email protected] None 0 4.2 kB gar
npm/@humanwhocodes/[email protected] None 0 43.1 kB nzakas
npm/@humanwhocodes/[email protected] None 0 49.4 kB nzakas
npm/@hutson/[email protected] None 0 20.6 kB hutson
npm/@isaacs/[email protected] None 0 3.16 kB isaacs
npm/@istanbuljs/[email protected] environment, filesystem Transitive: eval +4 438 kB coreyfarrell
npm/@istanbuljs/[email protected] None 0 17.2 kB coreyfarrell
npm/@jest/[email protected] None 0 21.7 kB simenb
npm/@jest/[email protected] unsafe 0 174 kB simenb
npm/@jest/[email protected] None 0 12.4 kB simenb
npm/@jest/[email protected] None 0 26.5 kB simenb
npm/@jest/[email protected] None 0 3.56 kB simenb
npm/@jest/[email protected] environment, unsafe +1 909 kB simenb
npm/@jest/[email protected] None 0 5.71 kB simenb

View full report↗︎

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)
packages/example/components/chains/aptosMartian/example.tsx (1)

Line range hint 1-450: 建议优化错误处理和 Promise 链式调用

代码中存在以下可以改进的地方:

  1. API 调用缺少统一的错误处理机制
  2. Promise 链式调用可以使用 async/await 简化
  3. 建议添加更严格的类型检查

建议参考以下示例进行改进:

- onExecute={async (request: string) => {
-   const obj = JSON.parse(request);
-   const tx = await provider?.generateTransaction(account?.address, obj);
-   return await provider?.signTransaction(tx);
- }}
+ onExecute={async (request: string) => {
+   try {
+     const obj = JSON.parse(request);
+     if (!account?.address) {
+       throw new Error('地址不能为空');
+     }
+     const tx = await provider?.generateTransaction(account.address, obj);
+     if (!tx) {
+       throw new Error('生成交易失败');
+     }
+     return await provider?.signTransaction(tx);
+   } catch (error) {
+     console.error('交易签名失败:', error);
+     throw error;
+   }
+ }}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE

📥 Commits

Reviewing files that changed from the base of the PR and between 9843a1f and 15b4f50.

📒 Files selected for processing (1)
  • packages/example/components/chains/aptosMartian/example.tsx (1 hunks)
🔇 Additional comments (1)
packages/example/components/chains/aptosMartian/example.tsx (1)

200-202: 签名验证逻辑优化完善!

在验证签名时添加了 stripHexPrefix 处理,确保了签名和公钥格式的正确性,这是一个很好的安全性改进。

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

Successfully merging this pull request may close these issues.

1 participant