frontend-apps

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Sui Frontend / dApp Kit

Sui 前端 / dApp Kit

MCP tool: When available in your environment, also query the Sui documentation MCP server (
https://sui.mcp.kapa.ai
) for up-to-date answers. Use it for verification and for details not covered by these reference files.
Browser Sui apps fail for a consistent set of reasons:
  1. Wrong package.
    @mysten/dapp-kit
    (no suffix) is the legacy JSON-RPC-only package — deprecated. New code uses
    @mysten/dapp-kit-react
    or
    @mysten/dapp-kit-core
    .
  2. Wrong client. dApp Kit takes a
    SuiGrpcClient
    (recommended) in
    createDAppKit
    's
    createClient
    . Passing a
    SuiJsonRpcClient
    defeats the point of the new package.
  3. Old provider stack. Code often tries the v1 pattern:
    QueryClientProvider
    SuiClientProvider
    WalletProvider
    . That's gone. New pattern:
    createDAppKit
    factory +
    DAppKitProvider
    (or a non-React equivalent).
  4. Dead hooks.
    useSuiClientQuery
    ,
    useSuiClientInfiniteQuery
    ,
    useSignAndExecuteTransaction
    (mutation hook),
    useConnectWallet
    ,
    useDisconnectWallet
    ,
    useSuiClient
    ,
    useSuiClientContext
    removed. Replaced by
    useCurrentClient
    /
    useCurrentNetwork
    /
    useDAppKit()
    (imperative methods) + your own TanStack Query wrappers.
  5. Skipping
    waitForTransaction
    between execute and refetch.
    Fullnodes index transactions asynchronously — invalidating TanStack caches immediately after
    signAndExecuteTransaction
    refetches stale data.
  6. Building PTBs in app code with
    tx.build()
    before handing to the wallet.
    Defeats the wallet's gas selection. Always pass the
    Transaction
    instance (or
    tx.serialize()
    ) to the wallet.
All patterns in this skill are derived from:
If unsure about any API, fetch from the relevant page — do not extrapolate from the legacy
@mysten/dapp-kit
or the pre-v2 hook surface. Many outdated tutorials exist.

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
    会失去新版包的优势。
  3. 过时的提供者栈:代码常尝试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
    实例(或
    tx.serialize()
    )交给钱包。
本技能中的所有模式均源自:
若对任何API存疑,请从相关页面获取信息——不要从旧版
@mysten/dapp-kit
或v2之前的钩子接口推断。目前存在许多过时教程。

Reference files

参考文件

setup — Install, factory, provider

setup — 安装、工厂函数、提供者

Path:
setup.md
Load when: starting a new dApp project, scaffolding React/Next.js/Vue setup, or migrating from the old three-provider pattern. Covers package choice,
createDAppKit({ networks, createClient })
,
DAppKitProvider
(React), and the
declare module
TypeScript augmentation.
路径:
setup.md
加载时机: 启动新的dApp项目、搭建React/Next.js/Vue环境,或从旧的三提供者模式迁移时。涵盖包选择、
createDAppKit({ networks, createClient })
DAppKitProvider
(React),以及TypeScript的
declare module
扩展。

react — React hooks & patterns

react — React钩子与模式

Path:
react.md
Load when: writing React components. Covers every current hook (
useCurrentAccount
,
useCurrentWallet
,
useCurrentNetwork
,
useCurrentClient
,
useDAppKit
,
useWallets
,
useWalletConnection
), standard components (
ConnectButton
), and wallet-gated UI idioms.
路径:
react.md
加载时机: 编写React组件时。涵盖所有当前钩子(
useCurrentAccount
useCurrentWallet
useCurrentNetwork
useCurrentClient
useDAppKit
useWallets
useWalletConnection
)、标准组件(
ConnectButton
),以及钱包 gated UI的惯用写法。

non-react — Vue, vanilla JS, Web Components

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

Path:
non-react.md
Load when: building Vue / Svelte / vanilla JS dApps. Covers
@mysten/dapp-kit-core
, nanostores reactive state (
dAppKit.stores.$connection
etc.), Web Components registration, Vue bindings via
@nanostores/vue
.
路径:
non-react.md
加载时机: 构建Vue/Svelte/原生JS dApp时。涵盖
@mysten/dapp-kit-core
、nanostores响应式状态(
dAppKit.stores.$connection
等)、Web Components注册、通过
@nanostores/vue
实现Vue绑定。

queries — TanStack Query patterns

queries — TanStack Query模式

Path:
queries.md
Load when: fetching on-chain data (balances, owned objects, coins, dynamic fields, transactions) in a dApp. Covers
useQuery
+
useCurrentClient
,
useInfiniteQuery
for paginated results,
enabled
guards, and cache invalidation after writes.
路径:
queries.md
加载时机: 在dApp中获取链上数据(余额、拥有的对象、代币、动态字段、交易)时。涵盖
useQuery
+
useCurrentClient
、用于分页结果的
useInfiniteQuery
enabled
守卫,以及写入后的缓存失效。

transactions — Signing and executing

transactions — 签名与执行

Path:
transactions.md
Load when: submitting any transaction from a dApp. Covers
dAppKit.signAndExecuteTransaction
, the
$kind
-based result discriminant,
signTransaction
(wallet signs but doesn't execute — for sponsored flows),
signPersonalMessage
, the
waitForTransaction
+
invalidateQueries
sequence, and common wallet UX failures.
路径:
transactions.md
加载时机: 从dApp提交任何交易时。涵盖
dAppKit.signAndExecuteTransaction
、基于
$kind
的结果判别、
signTransaction
(钱包签名但不执行——用于赞助流程)、
signPersonalMessage
waitForTransaction
+
invalidateQueries
序列,以及常见的钱包UX失败场景。

limitations — What frontends can't or shouldn't do

limitations — 前端不能或不应做的事

Path:
limitations.md
Load when: a user is designing something that feels like it crosses a browser-environment boundary. Covers: no backend-only features (gas station internals, validator keys), browser/SSR caveats, auto-connect reliability, JSON-RPC-specific features that don't have gRPC equivalents yet, and the "don't put secrets in the browser" rules.
路径:
limitations.md
加载时机: 用户设计的内容似乎跨越浏览器环境边界时。涵盖:无后端专属功能(加油站内部逻辑、验证器密钥)、浏览器/SSR注意事项、自动连接的可靠性、尚未有gRPC等效实现的JSON-RPC专属功能,以及“不要在浏览器中存储密钥”规则。

Routing guide

路由指南

TaskLoad
New React dApp from scratchsetup + react + queries + transactions
New Vue / vanilla / Svelte dAppsetup + non-react
"How do I connect a wallet?"react (or non-react)
"How do I query a balance / owned objects?"queries
"How do I send a transaction?"transactions + (sui-sdks for PTB construction)
Sponsored tx flowtransactions (front-end side) + ptbs (PTB side)
Migrating from
@mysten/dapp-kit
(no suffix)
setup + limitations + all as needed
Why is my UI stale after a tx?transactions + queries
Dealing with SSR / Next.jssetup + limitations
Full code review of a dAppall reference files + the code-review checklist below
"Review this code" / "what's wrong with this snippet"the code-review checklist below + relevant reference files
任务加载内容
从零开始创建新React dAppsetup + react + queries + transactions
创建新Vue/原生/Svelte dAppsetup + non-react
“如何连接钱包?”react(或non-react)
“如何查询余额/拥有的对象?”queries
“如何发送交易?”transactions +(sui-sdks用于PTB构建)
赞助交易流程transactions(前端侧) + ptbs(PTB侧)
@mysten/dapp-kit
(无后缀)迁移
setup + limitations + 按需加载其他内容
为什么交易后我的UI显示过期数据?transactions + queries
处理SSR/Next.jssetup + limitations
dApp代码全面审查所有参考文件 + 下方的代码审查清单
“审查这段代码” / “这段代码有什么问题?”下方的代码审查清单 + 相关参考文件

Skill Content

技能内容

Key concepts

核心概念

  • Two packages, one API.
    @mysten/dapp-kit-react
    wraps
    @mysten/dapp-kit-core
    .
    createDAppKit
    exists in both; actions (
    signAndExecuteTransaction
    ,
    signTransaction
    ,
    switchNetwork
    ,
    connectWallet
    ,
    disconnectWallet
    ) are identical. What differs is how you read reactive state: React uses hooks; non-React reads nanostores stores.
  • One instance, many networks.
    createDAppKit({ networks: [...], createClient })
    creates one dApp Kit instance that knows about multiple networks.
    dAppKit.switchNetwork(name)
    changes the active one. The
    createClient
    factory is called once per network, lazily.
  • gRPC by default. The new dApp Kit is built for
    SuiGrpcClient
    . JSON-RPC is legacy; don't pass
    SuiJsonRpcClient
    to
    createClient
    .
  • Wallets are browser-only. Wallet detection uses
    window.navigator.wallets
    and CustomEvents. Any component that touches wallet state must be client-side rendered. In Next.js / SSR frameworks this means
    'use client'
    on wallet-aware components.
  • The wallet owns gas. Apps build the
    Transaction
    and pass it to the wallet. The wallet picks gas coins, sets budget (via dry-run), and signs. Never call
    tx.build()
    + pass bytes unless it's a sponsored flow — see
    transactions.md
    .
  • Fullnodes are eventually consistent.
    signAndExecuteTransaction
    returns a digest before the data is queryable. Always
    waitForTransaction
    before refetching.
  • 两个包,一套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为旧版;不要将
    SuiJsonRpcClient
    传入
    createClient
  • 钱包仅支持浏览器环境:钱包检测使用
    window.navigator.wallets
    和CustomEvents。任何涉及钱包状态的组件都必须在客户端渲染。在Next.js/SSR框架中,这意味着钱包相关组件需要添加
    'use client'
    指令。
  • 钱包管理gas:应用构建
    Transaction
    并将其交给钱包。钱包选择gas代币、设置预算(通过预执行)并签名。除非是赞助流程,否则绝不要调用
    tx.build()
    并传递字节——详见
    transactions.md
  • 全节点最终一致性
    signAndExecuteTransaction
    在数据可查询前就会返回交易摘要。重新查询前必须调用
    waitForTransaction

Rules

规则

  1. Use
    @mysten/dapp-kit-react
    or
    @mysten/dapp-kit-core
    — never the bare
    @mysten/dapp-kit
    in new code. That package is JSON-RPC-only and deprecated.
  2. Use
    SuiGrpcClient
    in
    createClient
    .
    Not
    SuiJsonRpcClient
    . Not
    SuiClient
    SuiClient
    is removed in v2; use
    SuiGrpcClient
    from
    @mysten/sui/grpc
    .
  3. Use
    createDAppKit
    +
    DAppKitProvider
    .
    Not the three-provider stack (
    QueryClientProvider
    +
    SuiClientProvider
    +
    WalletProvider
    ). You still wrap with
    QueryClientProvider
    if you use TanStack Query for data fetching, but dApp Kit itself doesn't need it.
  4. Include the
    declare module
    TypeScript augmentation
    so hooks get proper types without passing the instance manually.
  5. Do not use the removed hooks.
    useSuiClientQuery
    /
    useSuiClientInfiniteQuery
    /
    useSuiClientContext
    /
    useSuiClient
    /
    useSignAndExecuteTransaction
    (mutation hook) /
    useConnectWallet
    /
    useDisconnectWallet
    — gone. Use
    useCurrentClient
    +
    useQuery
    /
    useInfiniteQuery
    +
    useDAppKit()
    imperative methods.
  6. Null-check the current account.
    useCurrentAccount()
    returns
    null
    before connection. Always
    if (!account) return
    / gate with
    enabled: !!account
    in queries.
  7. waitForTransaction
    before cache invalidation.
    await client.waitForTransaction({ digest: result.Transaction.digest })
    then
    queryClient.invalidateQueries(...)
    . Reversing this fetches stale data.
  8. Pass the
    Transaction
    instance (or
    tx.serialize()
    ) to the wallet, not
    await tx.build(...)
    bytes.
    The wallet needs to own gas selection. Exception: sponsored flows that use
    tx.build({ client, onlyTransactionKind: true })
    — see
    ptbs
    skill.
  9. Check
    result.$kind === 'FailedTransaction'
    (or
    result.FailedTransaction
    ).
    Don't assume success. Don't use v1's
    result.effects?.status?.status
    .
  10. Wallet-gated UI must client-render. SSR without a client-side guard renders wallet buttons before wallets are detectable. Use
    'use client'
    / dynamic imports / effect-based hydration.
  11. Vue:
    useStore
    returns a Vue ref — use
    .value
    in script code.
    const connection = useStore(dAppKit.stores.$connection)
    returns a ref. Access state as
    connection.value.account
    in
    <script setup>
    . Vue auto-unwraps refs in templates, but always show the
    .value
    pattern in script examples.
  1. 使用
    @mysten/dapp-kit-react
    @mysten/dapp-kit-core
    ——新代码绝不要使用无后缀的
    @mysten/dapp-kit
    。该包仅支持JSON-RPC且已废弃。
  2. createClient
    中使用
    SuiGrpcClient
    。不要使用
    SuiJsonRpcClient
    。不要使用
    SuiClient
    ——v2中已移除
    SuiClient
    ;请使用
    @mysten/sui/grpc
    中的
    SuiGrpcClient
  3. 使用
    createDAppKit
    +
    DAppKitProvider
    。不要使用三提供者栈(
    QueryClientProvider
    +
    SuiClientProvider
    +
    WalletProvider
    )。如果使用TanStack Query进行数据获取,仍然需要包裹
    QueryClientProvider
    ,但dApp Kit本身不需要它。
  4. 添加TypeScript的
    declare module
    扩展
    ,这样钩子无需手动传递实例即可获得正确类型。
  5. 不要使用已移除的钩子
    useSuiClientQuery
    /
    useSuiClientInfiniteQuery
    /
    useSuiClientContext
    /
    useSuiClient
    /
    useSignAndExecuteTransaction
    (mutation钩子) /
    useConnectWallet
    /
    useDisconnectWallet
    ——已移除。使用
    useCurrentClient
    +
    useQuery
    /
    useInfiniteQuery
    +
    useDAppKit()
    命令式方法替代。
  6. 空值检查当前账户
    useCurrentAccount()
    在连接前返回
    null
    。必须添加
    if (!account) return
    / 在查询中设置
    enabled: !!account
  7. 缓存失效前调用
    waitForTransaction
    。先执行
    await client.waitForTransaction({ digest: result.Transaction.digest })
    ,再执行
    queryClient.invalidateQueries(...)
    。颠倒顺序会获取到过期数据。
  8. Transaction
    实例(或
    tx.serialize()
    )交给钱包,而非
    await tx.build(...)
    的字节
    。钱包需要掌控gas选择。例外情况:使用
    tx.build({ client, onlyTransactionKind: true })
    的赞助流程——详见
    ptbs
    技能。
  9. 检查
    result.$kind === 'FailedTransaction'
    (或
    result.FailedTransaction
    。不要假设交易成功。不要使用v1的
    result.effects?.status?.status
  10. 钱包 gated UI必须在客户端渲染。无客户端守卫的SSR会在钱包可检测前渲染钱包按钮。使用
    'use client'
    / 动态导入 / 基于effect的hydration。
  11. Vue:
    useStore
    返回Vue ref——在脚本代码中使用
    .value
    const connection = useStore(dAppKit.stores.$connection)
    返回一个ref。在
    <script setup>
    中通过
    connection.value.account
    访问状态。Vue会在模板中自动解包ref,但脚本示例中必须显示
    .value
    的用法。

Code-review checklist

代码审查清单

When the user asks you to review a code snippet, do not stop at the first 2–3 issues you spot. Walk this checklist explicitly and call out every match. Browser Sui code typically has 5–10 issues stacked in a single component because it was copied from a v1 tutorial.
Imports / packages
  • @mysten/sui.js
    (anywhere) — frozen v1 package; replace with
    @mysten/sui
    .
  • @mysten/dapp-kit
    (no suffix) — deprecated JSON-RPC-only package; replace with
    @mysten/dapp-kit-react
    (React) or
    @mysten/dapp-kit-core
    (other frameworks).
  • import { ConnectButton } from '@mysten/dapp-kit-react'
    — wrong path;
    ConnectButton
    and
    ConnectModal
    are exported from
    @mysten/dapp-kit-react/ui
    . Using the wrong path causes a silent white screen.
  • import { SuiClient }
    SuiClient
    is removed in v2 — use
    SuiGrpcClient
    from
    @mysten/sui/grpc
    (or
    useCurrentClient()
    inside components).
  • import { TransactionBlock }
    — renamed to
    Transaction
    in v2.
Removed hooks (any of these = bug)
  • useSuiClientQuery
    ,
    useSuiClientInfiniteQuery
    ,
    useSuiClientContext
    ,
    useSuiClient
    — replace with
    useCurrentClient()
    + TanStack
    useQuery
    /
    useInfiniteQuery
    .
  • useSignAndExecuteTransaction
    (mutation hook) — replace with
    useDAppKit().signAndExecuteTransaction(...)
    called imperatively in event handlers.
  • useConnectWallet
    ,
    useDisconnectWallet
    — replace with
    useDAppKit().connectWallet()
    /
    disconnectWallet()
    .
Provider stack
  • SuiClientProvider
    +
    WalletProvider
    (the v1 three-provider stack) — replace with
    createDAppKit(...)
    +
    <DAppKitProvider>
    .
    QueryClientProvider
    from TanStack is still allowed.
Client construction inside components
  • new SuiClient(...)
    /
    new SuiGrpcClient(...)
    inside a component body — breaks network switching and re-creates a client per render. Use
    useCurrentClient()
    .
  • Missing
    enabled: !!account
    on queries that need a connected wallet — fires on undefined owner and errors.
Transaction construction
  • tx.pure(value)
    (untyped) — replace with the typed helper matching the Move type:
    tx.pure.u64(n)
    ,
    tx.pure.address(addr)
    ,
    tx.pure.string(s)
    , etc.
  • tx.build()
    before handing to the wallet — defeats wallet gas selection. Pass the
    Transaction
    instance (or
    tx.serialize()
    ).
Execute / wait / status
  • signAndExecuteTransactionBlock(...)
    (v1 method) — replace with
    signAndExecuteTransaction(...)
    .
  • { transactionBlock: tx }
    parameter shape — replace with
    { transaction: tx }
    .
  • result.effects?.status?.status === 'success'
    — v1 shape; replace with
    result.$kind !== 'FailedTransaction'
    (or check
    result.FailedTransaction
    ).
  • result.digest
    direct access — on success the digest is at
    result.Transaction.digest
    ; on failure there's no digest.
  • Cache invalidation immediately after execute — must
    await client.waitForTransaction({ digest })
    first, then
    queryClient.invalidateQueries(...)
    .
SSR / Next.js
  • Wallet-aware component without
    'use client'
    — wallet detection uses browser-only APIs.
After walking the list, count the distinct issues you found. If it's fewer than 5 on a typical multi-line snippet pulled from an outdated tutorial, re-read the snippet — you almost certainly missed something.
当用户要求你审查代码片段时,不要停留在发现的前2-3个问题。请明确按照此清单检查,并指出所有匹配的问题。由于代码可能复制自v1教程,Sui浏览器代码通常在单个组件中存在5-10个问题。
导入/包
  • @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 }
    ——v2中已移除
    SuiClient
    ——使用
    @mysten/sui/grpc
    中的
    SuiGrpcClient
    (或在组件内使用
    useCurrentClient()
    )。
  • import { TransactionBlock }
    ——v2中已重命名为
    Transaction
已移除的钩子(出现任何一个均为bug)
  • useSuiClientQuery
    useSuiClientInfiniteQuery
    useSuiClientContext
    useSuiClient
    ——替换为
    useCurrentClient()
    + TanStack
    useQuery
    /
    useInfiniteQuery
  • useSignAndExecuteTransaction
    (mutation钩子)——替换为在事件处理函数中命令式调用
    useDAppKit().signAndExecuteTransaction(...)
  • useConnectWallet
    useDisconnectWallet
    ——替换为
    useDAppKit().connectWallet()
    /
    disconnectWallet()
提供者栈
  • SuiClientProvider
    +
    WalletProvider
    (v1三提供者栈)——替换为
    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
    实例(或
    tx.serialize()
    )。
执行/等待/状态
  • signAndExecuteTransactionBlock(...)
    (v1方法)——替换为
    signAndExecuteTransaction(...)
  • 参数格式为
    { transactionBlock: tx }
    ——替换为
    { transaction: tx }
  • result.effects?.status?.status === 'success'
    ——v1格式;替换为
    result.$kind !== 'FailedTransaction'
    (或检查
    result.FailedTransaction
    )。
  • 直接访问
    result.digest
    ——成功时摘要位于
    result.Transaction.digest
    ;失败时无摘要。
  • 执行后立即失效缓存——必须先
    await client.waitForTransaction({ digest })
    ,再执行
    queryClient.invalidateQueries(...)
SSR/Next.js
  • 钱包相关组件未添加
    'use client'
    ——钱包检测使用浏览器专属API。
检查完清单后,统计发现的不同问题数量。如果从过时教程复制的多行代码片段中发现的问题少于5个,请重新阅读代码片段——你几乎肯定遗漏了某些内容。

Common mistakes

常见错误

  • Using
    @tanstack/react-query
    's
    useQuery
    without
    enabled: !!account
    for queries that require a connected wallet. The query fires with undefined owner and errors.
  • Returning a
    Transaction
    from a React-Query
    queryFn
    .
    Transactions aren't queries — use them in mutations or event handlers via
    useDAppKit()
    .
  • dAppKit.signAndExecuteTransaction({ transactionBlock: tx })
    .
    It's
    { transaction: tx }
    in the new API.
  • Reading
    result.digest
    directly.
    On success the digest is at
    result.Transaction.digest
    . On failure there's no digest — check
    result.FailedTransaction
    first.
  • Invalidating queries before
    waitForTransaction
    .
    Classic stale-UI bug. Always wait first.
  • Calling
    new SuiGrpcClient(...)
    inside components.
    Breaks network switching. Use
    useCurrentClient()
    .
  • Instantiating
    SuinsClient
    /
    DeepBookClient
    directly.
    Use
    client.$extend(suins(), deepbook({ address }))
    on the client returned from
    createClient
    .
  • Leaving
    autoConnect: true
    with a confusing UX.
    Auto-reconnect restores the last wallet on load. If the app handles permissions/nonces, account for the async nature of that restore (pending / reconnecting states).
  • Hardcoding testnet / mainnet URLs in multiple places. Keep them in a single
    GRPC_URLS
    map keyed by network name and reference from
    createClient
    .
  • Using wallet-standard APIs directly. dApp Kit wraps the wallet standard — don't call
    window.navigator.wallets
    yourself; use
    useWallets()
    /
    dAppKit.stores.$wallets
    .
  • Storing private keys or secrets in the browser. Never. dApps sign via wallets; backends hold keys.
  • 对需要连接钱包的查询,使用@tanstack/react-query的
    useQuery
    但未设置
    enabled: !!account
    ——查询会在owner未定义时触发并报错。
  • 从React-Query的
    queryFn
    返回
    Transaction
    ——交易不属于查询范畴——应在mutation或事件处理函数中通过
    useDAppKit()
    使用。
  • dAppKit.signAndExecuteTransaction({ transactionBlock: tx })
    ——新版API中应为
    { transaction: tx }
  • 直接读取
    result.digest
    ——成功时摘要位于
    result.Transaction.digest
    。失败时无摘要——需先检查
    result.FailedTransaction
  • waitForTransaction
    前失效缓存
    ——典型的过期UI bug。必须先等待。
  • 在组件内调用
    new SuiGrpcClient(...)
    ——破坏网络切换。使用
    useCurrentClient()
  • 直接实例化
    SuinsClient
    /
    DeepBookClient
    ——应在
    createClient
    返回的客户端上调用
    client.$extend(suins(), deepbook({ address }))
  • 保留
    autoConnect: true
    但未处理好UX
    ——自动连接会在加载时恢复上次的钱包。如果应用处理权限/随机数,需考虑恢复操作的异步性(pending/重新连接状态)。
  • 在多个位置硬编码testnet/mainnet URL——应将URL保存在按网络名称键控的单个
    GRPC_URLS
    映射中,并从
    createClient
    中引用。
  • 直接使用wallet-standard API——dApp Kit已封装钱包标准——不要自行调用
    window.navigator.wallets
    ;使用
    useWallets()
    /
    dAppKit.stores.$wallets
  • 在浏览器中存储私钥或密钥——绝对不要这样做。dApp通过钱包签名;后端保存密钥。