frontend-apps
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSui Frontend / dApp Kit
Sui 前端 / dApp Kit
MCP tool: When available in your environment, also query the Sui documentation MCP server () for up-to-date answers. Use it for verification and for details not covered by these reference files.https://sui.mcp.kapa.ai
Browser Sui apps fail for a consistent set of reasons:
- Wrong package. (no suffix) is the legacy JSON-RPC-only package — deprecated. New code uses
@mysten/dapp-kitor@mysten/dapp-kit-react.@mysten/dapp-kit-core - Wrong client. dApp Kit takes a (recommended) in
SuiGrpcClient'screateDAppKit. Passing acreateClientdefeats the point of the new package.SuiJsonRpcClient - Old provider stack. Code often tries the v1 pattern: →
QueryClientProvider→SuiClientProvider. That's gone. New pattern:WalletProviderfactory +createDAppKit(or a non-React equivalent).DAppKitProvider - Dead hooks. ,
useSuiClientQuery,useSuiClientInfiniteQuery(mutation hook),useSignAndExecuteTransaction,useConnectWallet,useDisconnectWallet,useSuiClient— removed. Replaced byuseSuiClientContext/useCurrentClient/useCurrentNetwork(imperative methods) + your own TanStack Query wrappers.useDAppKit() - Skipping between execute and refetch. Fullnodes index transactions asynchronously — invalidating TanStack caches immediately after
waitForTransactionrefetches stale data.signAndExecuteTransaction - Building PTBs in app code with before handing to the wallet. Defeats the wallet's gas selection. Always pass the
tx.build()instance (orTransaction) to the wallet.tx.serialize()
All patterns in this skill are derived from:
- https://sdk.mystenlabs.com/dapp-kit (landing)
- https://sdk.mystenlabs.com/dapp-kit/getting-started/react
- https://sdk.mystenlabs.com/dapp-kit/getting-started/next-js
- https://sdk.mystenlabs.com/dapp-kit/getting-started/vue
- https://docs.sui.io/standards/wallet-standard
If unsure about any API, fetch from the relevant page — do not extrapolate from the legacy or the pre-v2 hook surface. Many outdated tutorials exist.
@mysten/dapp-kitMCP工具: 如果你的环境支持,也可以查询Sui文档MCP服务器()获取最新答案。可用于验证内容及获取本参考文件未覆盖的细节。https://sui.mcp.kapa.ai
Sui浏览器应用失败通常有以下几种固定原因:
- 错误的包:(无后缀)是仅支持JSON-RPC的旧版包——已废弃。新代码应使用
@mysten/dapp-kit或@mysten/dapp-kit-react。@mysten/dapp-kit-core - 错误的客户端:dApp Kit在的
createDAppKit中推荐使用createClient。传入SuiGrpcClient会失去新版包的优势。SuiJsonRpcClient - 过时的提供者栈:代码常尝试v1模式:→
QueryClientProvider→SuiClientProvider。该模式已被移除。新模式为:WalletProvider工厂函数 +createDAppKit(或非React等效组件)。DAppKitProvider - 已废弃的钩子:、
useSuiClientQuery、useSuiClientInfiniteQuery(mutation钩子)、useSignAndExecuteTransaction、useConnectWallet、useDisconnectWallet、useSuiClient——已移除。替换为useSuiClientContext/useCurrentClient/useCurrentNetwork(命令式方法) + 自定义的TanStack Query封装。useDAppKit() - 执行交易与重新查询之间未调用:全节点会异步索引交易——在
waitForTransaction后立即失效TanStack缓存会导致重新查询到过期数据。signAndExecuteTransaction - 在应用代码中用构建PTB后再交给钱包:这会破坏钱包的gas选择逻辑。应始终将
tx.build()实例(或Transaction)交给钱包。tx.serialize()
本技能中的所有模式均源自:
- https://sdk.mystenlabs.com/dapp-kit(首页)
- https://sdk.mystenlabs.com/dapp-kit/getting-started/react
- https://sdk.mystenlabs.com/dapp-kit/getting-started/next-js
- https://sdk.mystenlabs.com/dapp-kit/getting-started/vue
- https://docs.sui.io/standards/wallet-standard
若对任何API存疑,请从相关页面获取信息——不要从旧版或v2之前的钩子接口推断。目前存在许多过时教程。
@mysten/dapp-kitReference files
参考文件
setup — Install, factory, provider
setup — 安装、工厂函数、提供者
Path:
Load when: starting a new dApp project, scaffolding React/Next.js/Vue setup, or migrating from the old three-provider pattern. Covers package choice, , (React), and the TypeScript augmentation.
setup.mdcreateDAppKit({ networks, createClient })DAppKitProviderdeclare module路径:
加载时机: 启动新的dApp项目、搭建React/Next.js/Vue环境,或从旧的三提供者模式迁移时。涵盖包选择、、(React),以及TypeScript的扩展。
setup.mdcreateDAppKit({ networks, createClient })DAppKitProviderdeclare modulereact — React hooks & patterns
react — React钩子与模式
Path:
Load when: writing React components. Covers every current hook (, , , , , , ), standard components (), and wallet-gated UI idioms.
react.mduseCurrentAccountuseCurrentWalletuseCurrentNetworkuseCurrentClientuseDAppKituseWalletsuseWalletConnectionConnectButton路径:
加载时机: 编写React组件时。涵盖所有当前钩子(、、、、、、)、标准组件(),以及钱包 gated UI的惯用写法。
react.mduseCurrentAccountuseCurrentWalletuseCurrentNetworkuseCurrentClientuseDAppKituseWalletsuseWalletConnectionConnectButtonnon-react — Vue, vanilla JS, Web Components
non-react — Vue、原生JS、Web Components
Path:
Load when: building Vue / Svelte / vanilla JS dApps. Covers , nanostores reactive state ( etc.), Web Components registration, Vue bindings via .
non-react.md@mysten/dapp-kit-coredAppKit.stores.$connection@nanostores/vue路径:
加载时机: 构建Vue/Svelte/原生JS dApp时。涵盖、nanostores响应式状态(等)、Web Components注册、通过实现Vue绑定。
non-react.md@mysten/dapp-kit-coredAppKit.stores.$connection@nanostores/vuequeries — TanStack Query patterns
queries — TanStack Query模式
Path:
Load when: fetching on-chain data (balances, owned objects, coins, dynamic fields, transactions) in a dApp. Covers + , for paginated results, guards, and cache invalidation after writes.
queries.mduseQueryuseCurrentClientuseInfiniteQueryenabled路径:
加载时机: 在dApp中获取链上数据(余额、拥有的对象、代币、动态字段、交易)时。涵盖 + 、用于分页结果的、守卫,以及写入后的缓存失效。
queries.mduseQueryuseCurrentClientuseInfiniteQueryenabledtransactions — Signing and executing
transactions — 签名与执行
Path:
Load when: submitting any transaction from a dApp. Covers , the -based result discriminant, (wallet signs but doesn't execute — for sponsored flows), , the + sequence, and common wallet UX failures.
transactions.mddAppKit.signAndExecuteTransaction$kindsignTransactionsignPersonalMessagewaitForTransactioninvalidateQueries路径:
加载时机: 从dApp提交任何交易时。涵盖、基于的结果判别、(钱包签名但不执行——用于赞助流程)、、 + 序列,以及常见的钱包UX失败场景。
transactions.mddAppKit.signAndExecuteTransaction$kindsignTransactionsignPersonalMessagewaitForTransactioninvalidateQuerieslimitations — What frontends can't or shouldn't do
limitations — 前端不能或不应做的事
Path:
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专属功能,以及“不要在浏览器中存储密钥”规则。
limitations.mdRouting guide
路由指南
| Task | Load |
|---|---|
| New React dApp from scratch | setup + react + queries + transactions |
| New Vue / vanilla / Svelte dApp | setup + 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 flow | transactions (front-end side) + ptbs (PTB side) |
Migrating from | setup + limitations + all as needed |
| Why is my UI stale after a tx? | transactions + queries |
| Dealing with SSR / Next.js | setup + limitations |
| Full code review of a dApp | all 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 dApp | setup + react + queries + transactions |
| 创建新Vue/原生/Svelte dApp | setup + non-react |
| “如何连接钱包?” | react(或non-react) |
| “如何查询余额/拥有的对象?” | queries |
| “如何发送交易?” | transactions +(sui-sdks用于PTB构建) |
| 赞助交易流程 | transactions(前端侧) + ptbs(PTB侧) |
从 | setup + limitations + 按需加载其他内容 |
| 为什么交易后我的UI显示过期数据? | transactions + queries |
| 处理SSR/Next.js | setup + limitations |
| dApp代码全面审查 | 所有参考文件 + 下方的代码审查清单 |
| “审查这段代码” / “这段代码有什么问题?” | 下方的代码审查清单 + 相关参考文件 |
Skill Content
技能内容
Key concepts
核心概念
- Two packages, one API. wraps
@mysten/dapp-kit-react.@mysten/dapp-kit-coreexists in both; actions (createDAppKit,signAndExecuteTransaction,signTransaction,switchNetwork,connectWallet) are identical. What differs is how you read reactive state: React uses hooks; non-React reads nanostores stores.disconnectWallet - One instance, many networks. creates one dApp Kit instance that knows about multiple networks.
createDAppKit({ networks: [...], createClient })changes the active one. ThedAppKit.switchNetwork(name)factory is called once per network, lazily.createClient - gRPC by default. The new dApp Kit is built for . JSON-RPC is legacy; don't pass
SuiGrpcClienttoSuiJsonRpcClient.createClient - Wallets are browser-only. Wallet detection uses and CustomEvents. Any component that touches wallet state must be client-side rendered. In Next.js / SSR frameworks this means
window.navigator.walletson wallet-aware components.'use client' - The wallet owns gas. Apps build the and pass it to the wallet. The wallet picks gas coins, sets budget (via dry-run), and signs. Never call
Transaction+ pass bytes unless it's a sponsored flow — seetx.build().transactions.md - Fullnodes are eventually consistent. returns a digest before the data is queryable. Always
signAndExecuteTransactionbefore refetching.waitForTransaction
- 两个包,一套API:封装了
@mysten/dapp-kit-react。@mysten/dapp-kit-core在两个包中都存在;操作(createDAppKit、signAndExecuteTransaction、signTransaction、switchNetwork、connectWallet)完全相同。区别在于读取响应式状态的方式:React使用钩子;非React读取nanostores存储。disconnectWallet - 一个实例,多网络支持:创建一个支持多网络的dApp Kit实例。
createDAppKit({ networks: [...], createClient })可切换当前活跃网络。dAppKit.switchNetwork(name)工厂函数会按网络惰性调用,每个网络调用一次。createClient - 默认使用gRPC:新版dApp Kit基于构建。JSON-RPC为旧版;不要将
SuiGrpcClient传入SuiJsonRpcClient。createClient - 钱包仅支持浏览器环境:钱包检测使用和CustomEvents。任何涉及钱包状态的组件都必须在客户端渲染。在Next.js/SSR框架中,这意味着钱包相关组件需要添加
window.navigator.wallets指令。'use client' - 钱包管理gas:应用构建并将其交给钱包。钱包选择gas代币、设置预算(通过预执行)并签名。除非是赞助流程,否则绝不要调用
Transaction并传递字节——详见tx.build()。transactions.md - 全节点最终一致性:在数据可查询前就会返回交易摘要。重新查询前必须调用
signAndExecuteTransaction。waitForTransaction
Rules
规则
- Use or
@mysten/dapp-kit-react— never the bare@mysten/dapp-kit-corein new code. That package is JSON-RPC-only and deprecated.@mysten/dapp-kit - Use in
SuiGrpcClient. NotcreateClient. NotSuiJsonRpcClient—SuiClientis removed in v2; useSuiClientfromSuiGrpcClient.@mysten/sui/grpc - Use +
createDAppKit. Not the three-provider stack (DAppKitProvider+QueryClientProvider+SuiClientProvider). You still wrap withWalletProviderif you use TanStack Query for data fetching, but dApp Kit itself doesn't need it.QueryClientProvider - Include the TypeScript augmentation so hooks get proper types without passing the instance manually.
declare module - Do not use the removed hooks. /
useSuiClientQuery/useSuiClientInfiniteQuery/useSuiClientContext/useSuiClient(mutation hook) /useSignAndExecuteTransaction/useConnectWallet— gone. UseuseDisconnectWallet+useCurrentClient/useQuery+useInfiniteQueryimperative methods.useDAppKit() - Null-check the current account. returns
useCurrentAccount()before connection. Alwaysnull/ gate withif (!account) returnin queries.enabled: !!account - before cache invalidation.
waitForTransactionthenawait client.waitForTransaction({ digest: result.Transaction.digest }). Reversing this fetches stale data.queryClient.invalidateQueries(...) - Pass the instance (or
Transaction) to the wallet, nottx.serialize()bytes. The wallet needs to own gas selection. Exception: sponsored flows that useawait tx.build(...)— seetx.build({ client, onlyTransactionKind: true })skill.ptbs - Check (or
result.$kind === 'FailedTransaction'). Don't assume success. Don't use v1'sresult.FailedTransaction.result.effects?.status?.status - Wallet-gated UI must client-render. SSR without a client-side guard renders wallet buttons before wallets are detectable. Use / dynamic imports / effect-based hydration.
'use client' - Vue: returns a Vue ref — use
useStorein script code..valuereturns a ref. Access state asconst connection = useStore(dAppKit.stores.$connection)inconnection.value.account. Vue auto-unwraps refs in templates, but always show the<script setup>pattern in script examples..value
- 使用或
@mysten/dapp-kit-react——新代码绝不要使用无后缀的@mysten/dapp-kit-core。该包仅支持JSON-RPC且已废弃。@mysten/dapp-kit - 在中使用
createClient。不要使用SuiGrpcClient。不要使用SuiJsonRpcClient——v2中已移除SuiClient;请使用SuiClient中的@mysten/sui/grpc。SuiGrpcClient - 使用+
createDAppKit。不要使用三提供者栈(DAppKitProvider+QueryClientProvider+SuiClientProvider)。如果使用TanStack Query进行数据获取,仍然需要包裹WalletProvider,但dApp Kit本身不需要它。QueryClientProvider - 添加TypeScript的扩展,这样钩子无需手动传递实例即可获得正确类型。
declare module - 不要使用已移除的钩子。/
useSuiClientQuery/useSuiClientInfiniteQuery/useSuiClientContext/useSuiClient(mutation钩子) /useSignAndExecuteTransaction/useConnectWallet——已移除。使用useDisconnectWallet+useCurrentClient/useQuery+useInfiniteQuery命令式方法替代。useDAppKit() - 空值检查当前账户。在连接前返回
useCurrentAccount()。必须添加null/ 在查询中设置if (!account) return。enabled: !!account - 缓存失效前调用。先执行
waitForTransaction,再执行await client.waitForTransaction({ digest: result.Transaction.digest })。颠倒顺序会获取到过期数据。queryClient.invalidateQueries(...) - 将实例(或
Transaction)交给钱包,而非tx.serialize()的字节。钱包需要掌控gas选择。例外情况:使用await tx.build(...)的赞助流程——详见tx.build({ client, onlyTransactionKind: true })技能。ptbs - 检查(或
result.$kind === 'FailedTransaction')。不要假设交易成功。不要使用v1的result.FailedTransaction。result.effects?.status?.status - 钱包 gated UI必须在客户端渲染。无客户端守卫的SSR会在钱包可检测前渲染钱包按钮。使用/ 动态导入 / 基于effect的hydration。
'use client' - Vue:返回Vue ref——在脚本代码中使用
useStore。.value返回一个ref。在const connection = useStore(dAppKit.stores.$connection)中通过<script setup>访问状态。Vue会在模板中自动解包ref,但脚本示例中必须显示connection.value.account的用法。.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
- (anywhere) — frozen v1 package; replace with
@mysten/sui.js.@mysten/sui - (no suffix) — deprecated JSON-RPC-only package; replace with
@mysten/dapp-kit(React) or@mysten/dapp-kit-react(other frameworks).@mysten/dapp-kit-core - — wrong path;
import { ConnectButton } from '@mysten/dapp-kit-react'andConnectButtonare exported fromConnectModal. Using the wrong path causes a silent white screen.@mysten/dapp-kit-react/ui - —
import { SuiClient }is removed in v2 — useSuiClientfromSuiGrpcClient(or@mysten/sui/grpcinside components).useCurrentClient() - — renamed to
import { TransactionBlock }in v2.Transaction
Removed hooks (any of these = bug)
- ,
useSuiClientQuery,useSuiClientInfiniteQuery,useSuiClientContext— replace withuseSuiClient+ TanStackuseCurrentClient()/useQuery.useInfiniteQuery - (mutation hook) — replace with
useSignAndExecuteTransactioncalled imperatively in event handlers.useDAppKit().signAndExecuteTransaction(...) - ,
useConnectWallet— replace withuseDisconnectWallet/useDAppKit().connectWallet().disconnectWallet()
Provider stack
- +
SuiClientProvider(the v1 three-provider stack) — replace withWalletProvider+createDAppKit(...).<DAppKitProvider>from TanStack is still allowed.QueryClientProvider
Client construction inside components
- /
new SuiClient(...)inside a component body — breaks network switching and re-creates a client per render. Usenew SuiGrpcClient(...).useCurrentClient() - Missing on queries that need a connected wallet — fires on undefined owner and errors.
enabled: !!account
Transaction construction
- (untyped) — replace with the typed helper matching the Move type:
tx.pure(value),tx.pure.u64(n),tx.pure.address(addr), etc.tx.pure.string(s) - before handing to the wallet — defeats wallet gas selection. Pass the
tx.build()instance (orTransaction).tx.serialize()
Execute / wait / status
- (v1 method) — replace with
signAndExecuteTransactionBlock(...).signAndExecuteTransaction(...) - parameter shape — replace with
{ transactionBlock: tx }.{ transaction: tx } - — v1 shape; replace with
result.effects?.status?.status === 'success'(or checkresult.$kind !== 'FailedTransaction').result.FailedTransaction - direct access — on success the digest is at
result.digest; on failure there's no digest.result.Transaction.digest - Cache invalidation immediately after execute — must first, then
await client.waitForTransaction({ digest }).queryClient.invalidateQueries(...)
SSR / Next.js
- Wallet-aware component without — wallet detection uses browser-only APIs.
'use client'
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个问题。
导入/包
- (任何位置)——已冻结的v1包;替换为
@mysten/sui.js。@mysten/sui - (无后缀)——已废弃的仅支持JSON-RPC的包;替换为
@mysten/dapp-kit(React)或@mysten/dapp-kit-react(其他框架)。@mysten/dapp-kit-core - ——错误路径;
import { ConnectButton } from '@mysten/dapp-kit-react'和ConnectButton从ConnectModal导出。使用错误路径会导致静默白屏。@mysten/dapp-kit-react/ui - ——v2中已移除
import { SuiClient }——使用SuiClient中的@mysten/sui/grpc(或在组件内使用SuiGrpcClient)。useCurrentClient() - ——v2中已重命名为
import { TransactionBlock }。Transaction
已移除的钩子(出现任何一个均为bug)
- 、
useSuiClientQuery、useSuiClientInfiniteQuery、useSuiClientContext——替换为useSuiClient+ TanStackuseCurrentClient()/useQuery。useInfiniteQuery - (mutation钩子)——替换为在事件处理函数中命令式调用
useSignAndExecuteTransaction。useDAppKit().signAndExecuteTransaction(...) - 、
useConnectWallet——替换为useDisconnectWallet/useDAppKit().connectWallet()。disconnectWallet()
提供者栈
- +
SuiClientProvider(v1三提供者栈)——替换为WalletProvider+createDAppKit(...)。TanStack的<DAppKitProvider>仍可使用。QueryClientProvider
组件内的客户端构建
- 在组件体内创建/
new SuiClient(...)——会破坏网络切换,且每次渲染都会重新创建客户端。使用new SuiGrpcClient(...)。useCurrentClient() - 需要连接钱包的查询缺少——会在owner未定义时触发并报错。
enabled: !!account
交易构建
- (无类型)——替换为与Move类型匹配的类型化辅助函数:
tx.pure(value)、tx.pure.u64(n)、tx.pure.address(addr)等。tx.pure.string(s) - 交给钱包前调用——破坏钱包的gas选择逻辑。应传递
tx.build()实例(或Transaction)。tx.serialize()
执行/等待/状态
- (v1方法)——替换为
signAndExecuteTransactionBlock(...)。signAndExecuteTransaction(...) - 参数格式为——替换为
{ transactionBlock: tx }。{ transaction: tx } - ——v1格式;替换为
result.effects?.status?.status === 'success'(或检查result.$kind !== 'FailedTransaction')。result.FailedTransaction - 直接访问——成功时摘要位于
result.digest;失败时无摘要。result.Transaction.digest - 执行后立即失效缓存——必须先,再执行
await client.waitForTransaction({ digest })。queryClient.invalidateQueries(...)
SSR/Next.js
- 钱包相关组件未添加——钱包检测使用浏览器专属API。
'use client'
检查完清单后,统计发现的不同问题数量。如果从过时教程复制的多行代码片段中发现的问题少于5个,请重新阅读代码片段——你几乎肯定遗漏了某些内容。
Common mistakes
常见错误
- Using 's
@tanstack/react-querywithoutuseQueryfor queries that require a connected wallet. The query fires with undefined owner and errors.enabled: !!account - Returning a from a React-Query
Transaction. Transactions aren't queries — use them in mutations or event handlers viaqueryFn.useDAppKit() - . It's
dAppKit.signAndExecuteTransaction({ transactionBlock: tx })in the new API.{ transaction: tx } - Reading directly. On success the digest is at
result.digest. On failure there's no digest — checkresult.Transaction.digestfirst.result.FailedTransaction - Invalidating queries before . Classic stale-UI bug. Always wait first.
waitForTransaction - Calling inside components. Breaks network switching. Use
new SuiGrpcClient(...).useCurrentClient() - Instantiating /
SuinsClientdirectly. UseDeepBookClienton the client returned fromclient.$extend(suins(), deepbook({ address })).createClient - Leaving 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).
autoConnect: true - Hardcoding testnet / mainnet URLs in multiple places. Keep them in a single map keyed by network name and reference from
GRPC_URLS.createClient - Using wallet-standard APIs directly. dApp Kit wraps the wallet standard — don't call yourself; use
window.navigator.wallets/useWallets().dAppKit.stores.$wallets - Storing private keys or secrets in the browser. Never. dApps sign via wallets; backends hold keys.
- 对需要连接钱包的查询,使用@tanstack/react-query的但未设置
useQuery——查询会在owner未定义时触发并报错。enabled: !!account - 从React-Query的返回
queryFn——交易不属于查询范畴——应在mutation或事件处理函数中通过Transaction使用。useDAppKit() - ——新版API中应为
dAppKit.signAndExecuteTransaction({ transactionBlock: tx })。{ transaction: tx } - 直接读取——成功时摘要位于
result.digest。失败时无摘要——需先检查result.Transaction.digest。result.FailedTransaction - 在前失效缓存——典型的过期UI bug。必须先等待。
waitForTransaction - 在组件内调用——破坏网络切换。使用
new SuiGrpcClient(...)。useCurrentClient() - 直接实例化/
SuinsClient——应在DeepBookClient返回的客户端上调用createClient。client.$extend(suins(), deepbook({ address })) - 保留但未处理好UX——自动连接会在加载时恢复上次的钱包。如果应用处理权限/随机数,需考虑恢复操作的异步性(pending/重新连接状态)。
autoConnect: true - 在多个位置硬编码testnet/mainnet URL——应将URL保存在按网络名称键控的单个映射中,并从
GRPC_URLS中引用。createClient - 直接使用wallet-standard API——dApp Kit已封装钱包标准——不要自行调用;使用
window.navigator.wallets/useWallets()。dAppKit.stores.$wallets - 在浏览器中存储私钥或密钥——绝对不要这样做。dApp通过钱包签名;后端保存密钥。