mcpField
F
frontend-apps

frontend-apps

github.com/mystenlabs开发19431 次安装今天更新
代码仓库

关于 frontend-apps

面向构建 Sui 前端 dApp 的开发者,提供基于当前 dApp Kit 的实现与迁移指南,涵盖 React、Vue 及其他非 React 框架,并强调避免过时 API 和常见交易问题。

主要功能

  1. 01dApp Kit 安装与初始化
  2. 02React 钱包连接与状态管理
  3. 03Vue、Svelte 和原生 JS 模式
  4. 04TanStack Query 链上数据查询
  5. 05交易签名、执行与状态检查
  6. 06旧版 API 迁移及代码审查

适用场景

  1. 01搭建新的 Sui React dApp
  2. 02实现 Vue 或 Svelte 钱包界面
  3. 03查询余额并提交链上交易
  4. 04检查旧教程代码并排查过时 API

MCP 相关

建议在可用时查询 Sui 文档 MCP 服务,以核实最新信息并补充参考文件未涵盖的细节。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mystenlabs/skills --skill frontend-apps

安装后在 Claude Code 中输入/frontend-apps确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

limitations.md
non-react.md
queries.md
react.md
setup.md
transactions.md
evals/
code-evals.json
evals.json

详细介绍

Sui 前端 / dApp 工具包

**MCP 工具:**如果你的环境支持,请同时查询 Sui 文档 MCP 服务(https://sui.mcp.kapa.ai)以获取最新答案。请用它核验信息,并了解这些参考文件未涵盖的细节。

浏览器中的 Sui 应用常因以下原因出错:

  1. 使用了错误的包。@mysten/dapp-kit(不带后缀)是仅支持旧版 JSON-RPC 的包——已弃用。新代码使用 @mysten/dapp-kit-react 或 @mysten/dapp-kit-core。
  2. **使用了错误的客户端。**dApp Kit 在 createDAppKit 的 createClient 中使用 SuiGrpcClient(推荐)。不要传入 SuiJsonRpcClient——JSON-RPC 已弃用。
  3. **使用了旧版 Provider 堆栈。**代码经常尝试使用 v1 模式:QueryClientProvider → SuiClientProvider → WalletProvider。这种模式已淘汰。新模式:createDAppKit 工厂 + DAppKitProvider(或非 React 等效方案)。
  4. 使用了已移除的钩子。useSuiClientQuery、useSuiClientInfiniteQuery、useSignAndExecuteTransaction(mutation 钩子)、useConnectWallet、useDisconnectWallet、useSuiClient、useSuiClientContext——均已移除。现在使用 useCurrentClient / useCurrentNetwork / useDAppKit()(命令式方法)+ 自行封装的 TanStack Query。
  5. **在执行交易和重新获取数据之间跳过 waitForTransaction。**全节点会异步索引交易——在 signAndExecuteTransaction 后立即使 TanStack 缓存失效,会重新获取过期数据。
  6. **在应用代码中调用 tx.build() 构建 PTB,再交给钱包。**这会妨碍钱包选择 Gas。始终将 Transaction 实例传给钱包。

此技能中的所有模式均基于以下资料:

如果不确定某个 API,请从相关页面获取信息——不要根据旧版 @mysten/dapp-kit 或 v2 之前的钩子接口进行推断。网上有很多过时的教程。


参考文件

setup — 安装、工厂、Provider

路径: setup.md **适用场景:**开始新的 dApp 项目、搭建 React/Next.js/Vue 项目,或从旧的三 Provider 模式迁移时。涵盖包的选择、createDAppKit({ networks, createClient })、DAppKitProvider(React)以及 declare module TypeScript 扩展。

react — React 钩子与模式

路径: react.md **适用场景:**编写 React 组件时。涵盖所有当前钩子(useCurrentAccount、useCurrentWallet、useCurrentNetwork、useCurrentClient、useDAppKit、useWallets、useWalletConnection)、标准组件(ConnectButton)以及需要连接钱包才能使用的界面惯用模式。

non-react — Vue、原生 JS、Web Components

路径: non-react.md **适用场景:**构建 Vue / Svelte / 原生 JS dApp 时。涵盖 @mysten/dapp-kit-core、nanostores 响应式状态(如 dAppKit.stores.$connection)、Web Components 注册,以及通过 @nanostores/vue 绑定到 Vue。

queries — TanStack Query 模式

路径: queries.md **适用场景:**在 dApp 中获取链上数据(余额、自有对象、代币、动态字段、交易)时。涵盖 useQuery + useCurrentClient、用于分页结果的 useInfiniteQuery、enabled 条件判断,以及写入后的缓存失效。

transactions — 签名与执行

路径: transactions.md **适用场景:**从 dApp 提交任何交易时。涵盖 dAppKit.signAndExecuteTransaction、基于 $kind 的结果判别、signTransaction(钱包只签名、不执行——用于赞助交易流程)、signPersonalMessage、waitForTransaction + invalidateQueries 顺序,以及常见的钱包 UX 故障。

限制——前端不能做或不应做的事

路径: limitations.md 在以下情况下加载: 用户正在设计的功能似乎会越过浏览器环境的边界。涵盖:仅限后端的功能(加油站内部信息、验证者密钥)、浏览器/SSR 注意事项、自动连接的可靠性,以及“不要在浏览器中放置机密信息”的规则。

路由指南

任务加载内容
从头开始构建新的 React dAppsetup + react + queries + transactions
构建新的 Vue/原生 JavaScript/Svelte dAppsetup + non-react
“如何连接钱包?”react(或 non-react)
“如何查询余额/拥有的对象?”queries
“如何发送交易?”transactions +(用于构建 PTB 的 sui-sdks)
赞助交易流程transactions(前端部分)+ ptbs(PTB 部分)
从 @mysten/dapp-kit(无后缀)迁移setup + limitations + 按需加载其他内容
为什么我的 UI 在交易后没有更新?transactions + queries
处理 SSR/Next.jssetup + limitations
对 dApp 进行完整代码审查所有参考文件 + 以下代码审查清单
“审查这段代码”/“这段代码有什么问题?”以下代码审查清单 + 相关参考文件

技能内容

关键概念
  • 两个包,一个 API。 @mysten/dapp-kit-react 封装了 @mysten/dapp-kit-core。两者都有 createDAppKit;操作(signAndExecuteTransaction、signTransaction、switchNetwork、connectWallet、disconnectWallet)完全相同。不同之处在于如何读取响应式状态:React 使用钩子;非 React 则读取 nanostores 存储。
  • 一个实例,多个网络。 createDAppKit({ networks: [...], createClient }) 会创建一个了解多个网络的 dApp Kit 实例。dAppKit.switchNetwork(name) 会切换当前活动网络。createClient 工厂会为每个网络延迟调用一次。
  • 默认使用 gRPC。 新版 dApp Kit 基于 SuiGrpcClient 构建。JSON-RPC 已弃用;请在 createClient 中使用 SuiGrpcClient。
  • 钱包仅限浏览器环境。 钱包检测使用 window.navigator.wallets 和 CustomEvents。任何涉及钱包状态的组件都必须在客户端渲染。在 Next.js/SSR 框架中,这意味着要在涉及钱包的组件上添加 'use client'。
  • Gas 由钱包负责。 应用构建 Transaction 并将其传递给钱包。钱包会选择 Gas 币、设置预算(通过 dry-run)并签名。除非是赞助交易流程,否则绝不要调用 tx.build() 并传递字节——请参阅 transactions.md。
  • 全节点的数据最终一致。 signAndExecuteTransaction 会在数据可查询之前返回摘要。重新获取数据前,务必先调用 waitForTransaction。
规则
  1. 使用 @mysten/dapp-kit-react 或 @mysten/dapp-kit-core——新代码中不要使用裸包 @mysten/dapp-kit。该包仅支持 JSON-RPC,且已弃用。
  2. 在 createClient 中使用 SuiGrpcClient。 不要使用 SuiClient——SuiClient 已在 v2 中移除;请使用来自 @mysten/sui/grpc 的 SuiGrpcClient。
  3. 使用 createDAppKit + DAppKitProvider。 不要使用三个 Provider 组成的堆栈(QueryClientProvider + SuiClientProvider + WalletProvider)。如果使用 TanStack Query 获取数据,仍需用 QueryClientProvider 包裹,但 dApp Kit 本身不需要它。
  4. 加入 declare module TypeScript 扩展声明, 这样 Hooks 无需手动传入实例也能获得正确类型。
  5. 不要使用已移除的 Hooks。 useSuiClientQuery / useSuiClientInfiniteQuery / useSuiClientContext / useSuiClient / useSignAndExecuteTransaction(mutation Hook)/ useConnectWallet / useDisconnectWallet 均已移除。请使用 useCurrentClient + useQuery/useInfiniteQuery + useDAppKit() 命令式方法。
  6. 检查当前账户是否为 null。 连接前,useCurrentAccount() 会返回 null。始终使用 if (!account) return,或在查询中通过 enabled: !!account 设置执行条件。
  7. 使缓存失效前先调用 waitForTransaction。 先执行 await client.waitForTransaction({ digest: result.Transaction.digest }),再执行 queryClient.invalidateQueries(...)。反过来会获取到过期数据。
  8. 将 Transaction 实例传给钱包,而不是传入 await tx.build(...) 得到的字节。 钱包需要负责选择 gas。例外:使用 tx.build({ client, onlyTransactionKind: true }) 的赞助交易流程——请参见 ptbs skill。
  9. 检查 result.$kind === 'FailedTransaction'(或 result.FailedTransaction)。 不要假定交易成功。不要使用 v1 的 result.effects?.status?.status。
  10. 钱包相关 UI 必须在客户端渲染。 如果 SSR 时没有客户端保护,钱包按钮会在检测到钱包前渲染。请使用 'use client' / 动态导入 / 基于 effect 的水合。
  11. Vue:useStore 返回 Vue ref——在脚本代码中使用 .value。 const connection = useStore(dAppKit.stores.$connection) 会返回一个 ref。在 <script setup> 中,通过 connection.value.account 访问状态。Vue 会在模板中自动解包 ref,但脚本示例中始终展示 .value 的用法。
代码审查清单

当用户要求你审查代码片段时,不要只指出最先发现的 2–3 个问题。请逐项检查此清单,并指出所有匹配项。Browser Sui 代码通常在单个组件中堆叠了 5–10 个问题,因为它是从 v1 教程中复制而来的。

导入 / 软件包

  • @mysten/sui.js(出现在任何位置)——已冻结的 v1 软件包;替换为 @mysten/sui。
  • @mysten/dapp-kit(无后缀)——已弃用的仅支持 JSON-RPC 的软件包;替换为 @mysten/dapp-kit-react(React)或 @mysten/dapp-kit-core(其他框架)。
  • import { ConnectButton } from '@mysten/dapp-kit-react'——路径错误;ConnectButton 和 ConnectModal 从 @mysten/dapp-kit-react/ui 导出。使用错误路径会导致白屏,且不会显示任何错误。
  • import { SuiClient }——SuiClient 已在 v2 中移除——使用 @mysten/sui/grpc 中的 SuiGrpcClient(或在组件内使用 useCurrentClient())。
  • import { TransactionBlock }——在 v2 中已重命名为 Transaction。

已移除的钩子(出现任何一个都属于错误)

  • useSuiClientQuery、useSuiClientInfiniteQuery、useSuiClientContext、useSuiClient——替换为 useCurrentClient() + TanStack 的 useQuery / useInfiniteQuery。
  • useSignAndExecuteTransaction(变更钩子)——替换为在事件处理程序中命令式调用 useDAppKit().signAndExecuteTransaction(...)。
  • useConnectWallet、useDisconnectWallet——替换为 useDAppKit().connectWallet() / disconnectWallet()。

Provider 组合

  • SuiClientProvider + WalletProvider(v1 的三 Provider 组合)——替换为 createDAppKit(...) + <DAppKitProvider>。仍可使用 TanStack 的 QueryClientProvider。

在组件内构造客户端

  • 在组件主体内调用 new SuiClient(...) / new SuiGrpcClient(...)——会导致网络切换失效,并在每次渲染时重新创建客户端。请使用 useCurrentClient()。
  • 需要已连接钱包的查询缺少 enabled: !!account——会在 owner 未定义时触发查询并报错。

构造交易

  • tx.pure(value)(未指定类型)——替换为与 Move 类型匹配的类型化辅助方法:tx.pure.u64(n)、tx.pure.address(addr)、tx.pure.string(s) 等。
  • 将交易传给钱包之前先调用 tx.build()——这会使钱包无法选择 gas。请直接传入 Transaction 实例。

执行 / 等待 / 状态

  • signAndExecuteTransactionBlock(...)(v1 方法)——替换为 signAndExecuteTransaction(...)。
  • { transactionBlock: tx } 参数形式——替换为 { transaction: tx }。
  • result.effects?.status?.status === 'success'——这是 v1 的形式;替换为 result.$kind !== 'FailedTransaction'(或检查 result.FailedTransaction)。
  • 直接访问 result.digest——成功时,digest 位于 result.Transaction.digest;失败时没有 digest。
  • 执行后立即使缓存失效——必须先 await client.waitForTransaction({ digest }),然后再调用 queryClient.invalidateQueries(...)。

SSR / Next.js

  • 未添加 'use client' 的钱包感知组件——钱包检测会使用仅限浏览器的 API。

完成清单检查后,统计发现的不同问题数量。如果从典型的旧教程多行代码片段中找到的问题少于 5 个,请重新检查代码片段——你几乎肯定漏掉了问题。

常见错误
  • 对需要连接钱包的查询使用 @tanstack/react-query 的 useQuery,却未设置 enabled: !!account。 查询会在所有者未定义时触发并报错。
  • 从 React-Query 的 queryFn 返回 Transaction。 交易不是查询;请通过 useDAppKit() 在变更或事件处理器中使用交易。
  • 使用 dAppKit.signAndExecuteTransaction({ transactionBlock: tx })。 新 API 中应使用 { transaction: tx }。
  • 直接读取 result.digest。 成功时,摘要位于 result.Transaction.digest。失败时没有摘要——请先检查 result.FailedTransaction。
  • 在 waitForTransaction 之前使查询失效。 这是经典的 UI 过时问题。务必先等待。
  • 在组件中调用 new SuiGrpcClient(...)。 这会导致网络切换失效。请使用 useCurrentClient()。
  • 直接实例化 SuinsClient / DeepBookClient。 请在 createClient 返回的客户端上使用 client.$extend(suins(), deepbook({ address }))。
  • 保留 autoConnect: true,却未提供清晰的用户体验。 自动重连会在加载时恢复上次使用的钱包。如果应用会处理权限或 nonce,请考虑恢复过程的异步特性(待处理/正在重连状态)。
  • 在多个地方硬编码 testnet / mainnet URL。 请将它们集中放在按网络名称索引的 GRPC_URLS 映射中,并在 createClient 中引用。
  • 直接使用 wallet-standard API。 dApp Kit 封装了 wallet standard——请勿自行调用 window.navigator.wallets;应使用 useWallets() / dAppKit.stores.$wallets。
  • 在浏览器中存储私钥或机密。 绝对不要这样做。dApp 通过钱包签名;密钥由后端持有。

评论

支持 Markdown