news 2026/10/13 4:53:50

Web3Modal AppKit Pay 与多链适配器演进实录:从 0.1.1 到 0.1.23 的 CHANGELOG 深度解读

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Web3Modal AppKit Pay 与多链适配器演进实录:从 0.1.1 到 0.1.23 的 CHANGELOG 深度解读
  • 区块链
  • 前端
  • 认证鉴权

【免费下载链接】web3modal

The full stack toolkit to build onchain app UX

项目地址:https://gitcode.com/gh_mirrors/we/web3modal
点击查看免费下载

本文以仓库中 apps/pay-test-exchange/CHANGELOG.md 为主线,系统梳理 Reown Web3Modal 生态中 AppKit Pay(支付与存款)功能、多链钱包适配器(Stellar、TRON、Bitcoin、Solana、EVM)以及 SIWX 签名体系的版本演进脉络。通过逐条对照仓库源码(packages/pay、packages/adapters、packages/siwx 等),读者将理解:支付流程如何从"单一代币直接转账"升级为"任意代币支付 + 自动兑换桥接 + 交易所出金入金"的完整闭环,Stellar 适配器如何接入 WalletConnect 协议族,以及连接事件、签名弹窗、网络切换等 UX 细节背后的实现原理。

一、CHANGELOG 文档背景:一个支付测试交易所的迭代记录

该 CHANGELOG 隶属于pay-test-exchange应用,它是 AppKit Pay 生态中的一个测试用交易所页面:通过模拟"支付成功 / 触发错误"两种场景,帮助 DApp 开发者验证接入 AppKit Pay 后的完整回调链路。其核心交互见 apps/pay-test-exchange/components/exchange-actions.tsx:页面渲染 Reown 品牌信息后,提供Complete Successfully与Trigger Error两个按钮,分别调用markSessionSuccess/markSessionError更新 Cloudflare KV 存储中的会话状态,再跳转到/success或/error页面。

会话状态机定义在 apps/pay-test-exchange/lib/types.ts:

export type Session = { status: 'pending' | 'success' | 'error' createdAt: string txid?: string }

写入逻辑见 apps/pay-test-exchange/app/api/update/route.ts:会话通过 Cloudflare KV(SESSIONID_STORAGE)持久化,默认 TTL 为 72 小时(EXPIRY_SECONDS = 60 * 60 * 72);标记成功时会写入一个模拟txid,供 DApp 端轮询getBuyStatus或getQuoteStatus后展示交易结果。这个"测试交易所"恰好是理解 AppKit Pay 服务端回调用例的缩影——CHANGELOG 中大量条目(token 选择、入金流程、余额校验)都能在 packages/pay 的控制器实现中找到对应。

二、AppKit Pay 核心能力演进:从转账到支付闭环

2.1 支付方式矩阵:钱包直付与交易所出金

AppKit Pay 的支付模型经历了三次大的形态跃迁,全部反映在 CHANGELOG 中:

版本能力变化源码佐证
0.1.10允许用户手动编辑从交易所入金的存款金额(PR #5004)PayController.getPayUrl 中金额以字符串传递并做Number归一化
0.1.13改进 send 流程设计,为余额不足用户增加充值(top-up)选项(PR #4959)fetchTokens同时支持 EOA 余额与交易所资产两种来源
0.1.20任意代币支付:付款方可用任意代币,收款方始终收到其偏好代币(自动兑换+桥接);实现 Reown 与合作方手续费分账(PR #5423)引入quote与quoteStatus状态,见PayControllerState

PayControllerState(packages/pay/src/controllers/PayController.ts)完整定义了这一演进的状态空间:paymentAsset、recipient、amount描述支付请求;exchanges描述可用交易所;quote/quoteStatus/quoteError描述兑换报价;currentPayment以type: 'wallet' | 'exchange'区分两种支付通道。

在 0.1.20 之前,支付是"指定代币、直接转账";之后,系统会先通过getQuote拉取兑换报价(packages/pay/src/utils/ApiUtil.ts),再根据quote.transactionStep决定执行路径:EVM 侧走ConnectionController.sendTransaction发送from/to/data/value,Solana 侧走ConnectionController.writeSolanaTransaction提交instructions。若当前网络与目标资产网络不一致,PayController.onSendTransaction会先调用ChainController.switchActiveNetwork切换网络,再发起交易——这正是 0.1.9 修复"open带 send 参数切换网络不抛错导致状态不一致"的延续。

2.2 支付资产处理的三条路径

packages/pay/src/utils/PaymentUtil.ts 将支付执行收敛为三个函数,与 CHANGELOG 的修复条目一一对应:

  • processEvmNativePayment:EVM 原生币转账。使用ConnectionController.parseUnits按资产精度换算金额,再经sendTransaction发送value(data: '0x')。对应 0.1.12 修复的"用户拒绝交易时误记SEND_ERROR,改为记录SEND_REJECTED"。
  • processEvmErc20Payment:ERC20 代币转账。通过ConnectionController.writeContract调用 ERC20transfer(recipient, amount),ABI 由ContractUtil.getERC20Abi提供。
  • processSolanaPayment:Solana 转账。传入tokenMint时构造 SPL Token 转账指令;本地(native SOL)与 SPL 代币分派逻辑在 PayController.onTransfer 中由paymentAsset.asset是否为'native'决定。

Solana 路径背后有一段值得关注的修复史(0.1.7 与 0.1.8 均提及):Token-2022 代币转账失败,原因是 send 流程使用了 legacy 转账指令。仓库当前实现 createSPLTokenTransactionKit.ts 中可见保护逻辑:

if (mint.programAddress !== TOKEN_PROGRAM_ADDRESS) { throw new Error('Token-2022 mints are not yet supported') }

也就是说,SPL Token 标准程序地址(TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA)之外的 Token-2022 Mint 会被显式拒绝而非产生错误指令;同时该文件用字符串大数运算(toTokenBaseUnits)取代 IEEE-754 浮点乘法,避免0.29 * 100 === 28.999...这类精度陷阱——对应 CHANGELOG 中"高精度大额代币兑换失败"(0.1.21)与"SPL 代币无法发送"(0.1.5)的根治方案。

2.3 交易所入金(deposit from exchange)流程

CHANGELOG 中反复出现"deposit from exchange / fund from exchange"相关条目,这是 AppKit Pay 区别于普通转账的独特能力:用户从中心化交易所向链上地址入金。

  • 0.1.5:为 fund from exchange 流程增加代币选择,解决部分交易所不支持特定代币的问题(PR #4890);
  • 0.1.8:修复"从交易所入金首次尝试不生效"(PR #4941);将文案从 "deposit from an exchange" 统一为 "deposit from exchange"(PR #4957);
  • 0.1.10:允许手动编辑入金金额(PR #5004);
  • 0.1.13:为"从交易所入金"视图的代币按钮增加链图标(PR #5078)。

入金流程的 API 侧实现集中在 packages/pay/src/utils/ApiUtil.ts:

  • getExchanges(RPCreown_getExchanges)拉取可用交易所列表,PayController.fetchExchanges 目前截取前两家以兼容现有 UI;
  • getAssetsForExchange(exchangeId)拉取该交易所支持的资产清单,随后fetchTokensFromExchange逐一代币补齐图标 URL(AssetUtil.getImageByToken),并将 CAIP 地址解析为裸地址;
  • getPayUrl({ exchangeId, asset, amount, recipient })生成交易所付款 URL 与会话 ID(sessionId),PayController.openPayUrl按openInNewTab决定以_blank/_self打开。

quote 驱动的入金是 0.1.20 的进阶形态:fetchQuote拿到报价后,如果存在transferStep,会以transferStep.deposit.receiver作为入金接收地址、transferStep.deposit.amount作为金额,调用generateExchangeUrlForQuote生成交易所链接,并用DIRECT_TRANSFER_REQUEST_ID标识"直接转账式入金"的轮询请求。

2.4 支付结果轮询与客户端 API

packages/pay/src/client.ts 暴露了编程式支付入口:

  • openPay(options):打开支付弹窗;
  • pay(options, timeoutMs):打开弹窗并返回 Promise,默认5 分钟(PAYMENT_TIMEOUT_MS = 300000)超时;通过订阅currentPayment、error、isPaymentInProgress三个状态键,在SUCCESS/FAILED/ 超时三种情况下 settle;
  • getPayUrl/openPayUrl/getAvailableExchanges/getPayResult/getPayError/getIsPaymentInProgress:headless 模式下的组件化调用;
  • subscribeStateKey:事件监听接口,返回取消订阅函数——这正是 0.1.21 新增的"AppKit 事件监听器 unsubscribe 能力"(PR #5447)的落地。

三、新增 Stellar 适配器:WalletConnect 协议族的新成员(0.1.23)

0.1.23 中最具里程碑意义的一条:通过新的@reown/appkit-adapter-stellar包接入 Stellar 网络,支持stellar:pubnet与stellar:testnet两条网络,以及stellar_signXDR、stellar_signAndSubmitXDR、stellar_signMessage、stellar_signAuthEntry四个签名方法,并附带针对 SEP-53 签名的 SIWX 验证器。Stellar 钱包仅通过 WalletConnect 连接,不支持扩展钱包。

3.1 适配器骨架:扩展钱包的"无操作"实现

packages/adapters/stellar/src/adapter.ts 中,StellarAdapter extends AdapterBlueprint<StellarConnector>,其设计要点:

  • syncConnectors()被刻意留空——因为 Stellar 没有注入式钱包可发现,WalletConnect 连接器在setUniversalProvider中注册;
  • 其余 EVM 形态的蓝图方法(sendTransaction、writeContract、estimateGas、grantPermissions、getCapabilities等)全部以满足接口但不假装做事的方式实现为 no-op。这是因为 Stellar 交易是 DApp 侧构建的 XDR 信封,签名应走连接器的signXDR/signAndSubmitXDR,而非通用 EVM 方法;
  • getBalance直接请求HorizonRPC({horizonUrl}/accounts/{address})读取原生 XLM 余额;对"从未被注资(404)"的账户返回零余额而非报错——注释明确说明 Blockchain API 目前尚无 Stellar 支持。

3.2 连接器:四类 stellar_* 方法的统一路由

packages/adapters/stellar/src/connectors/StellarWalletConnectConnector.ts 实现 Stellar WalletConnect 规范的方法集。核心机制是私有的requestStellarMethod:每个请求都通过ChainController.getCaipNetworkByNamespace(ConstantsUtil.CHAIN.STELLAR)取当前激活网络,并把chain与account(形如stellar:pubnet:ADDRESS)附加到 payload 上:

return await this.provider.request<T>( { method, params: { ...rest, chain: chain.caipNetworkId, account: `${chain.caipNetworkId}:${address}` } }, chain.caipNetworkId )

这把网络解析绑定到会话链 ID 而非调用方传入的参数——钱包据此路由到正确的密钥。signAndSubmitXDR会把钱包返回的tx_hash映射为txHash,并仅在调用方提供时才透传waitForInclusion。配套测试 packages/adapters/stellar/tests/connectors/StellarWalletConnectConnector.test.ts 逐一验证了四个方法的请求形状与stellar:pubnet网络绑定。

3.3 SIWX 验证器:SEP-53 域分隔签名

packages/siwx/src/verifiers/StellarVerifier.ts 是配套的会话验证器。Stellar 与 Solana 一样使用 Ed25519 签名,但钱包签署的是 SEP-53 规定的域分隔载荷sha256("StellarMessage" || 0x00 || message),而非消息本身;地址使用 StrKey 编码而非 base58。验证流程:

const payload = new Uint8Array(prefix.length + 1 + message.length) payload.set(prefix, 0) payload[prefix.length] = 0 payload.set(message, prefix.length + 1) const digest = sha256(payload, 'bytes') return nacl.sign.detached.verify(digest, signature, publicKey)

该验证器已默认注册进 packages/siwx/src/configs/DefaultSIWX.ts 的默认配置(new StellarVerifier()),与 EIP155、Solana、BIP122、TRON 验证器并列。

四、SIWX 签名与连接恢复的修复纵深

4.1 SIWX 签名弹窗不出现的修复(0.1.23)

CHANGELOG 0.1.23 修复了"连接后 SIWX 签名弹窗不出现,需刷新页面才生效"的问题,复现场景覆盖 Solana 适配器 + 邮箱登录、Farcaster 登录以及浏览器注入钱包连接。根因在于 packages/siwx/src/signers/DefaultSigner.ts 的签名链路依赖实时状态:signMessage依次从ChainController取当前网络、从AdapterController取适配器、从ChainController.getAccountData取地址、从ConnectorController取连接器 ID,任一环节在连接事件完成前未就绪,签名就无法发起。该文件还包含一个细节:当连接器是AUTH(邮箱/社交登录)时,会先RouterController.pushTransactionStack({})压入交易栈,为弹窗导航做准备。

4.2 多链钱包的签名竞态修复(0.1.23, PR #5736)

Trust Wallet、SafePal 等多链钱包的 SIWX 签名在"消息创建与签名之间活跃 namespace 发生变化"时会失败。从架构上看,SIWX 的签名委派链是SIWXConfig.signMessage → signer.signMessage(message, chainId)(packages/siwx/src/core/SIWXConfig.ts),而DefaultSigner在未显式传chainId时回退到ChainController.getActiveCaipNetwork()——这就是竞态窗口:若用户在弹窗中切换了网络,签名请求携带的 namespace 与消息创建时不一致,适配器便找不到对应签名者。该修复思路与 0.1.4 修复的"取消 SIWX 签名未恢复原网络状态"一脉相承,都是围绕 namespace 一致性问题做状态收敛。

4.3 TRON 连接在重载时被静默清空(0.1.23, PR #5746)

这是 0.1.23 中另一个教科书级的引导同步(boot sync)竞态修复:当 TronLink 等钱包适配器在引导同步运行时仍处于readyState解析中,已存储的 TRON 连接会被静默抹掉。修复方式体现在 packages/adapters/tron/src/adapter.ts 的syncConnectors与 packages/adapters/tron/src/utils/TronConnectUtil.ts 中:

  • syncConnectors先启动watchWalletAdapters(监听readyStateChanged事件),再await waitForLoadingAdapters(...);
  • waitForLoadingAdapters通过withRetry轮询(间隔 200ms、上限 3000ms),但只等待存在实际存储的 TRON 连接(hasConnected && !hasDisconnected)且处于Loading的适配器——未安装的钱包或仅通过 WalletConnect 连接的会话不会阻塞引导,从而避免了"每次页面加载都延迟数秒"的副作用;
  • 配套测试 packages/adapters/tron/src/tests/adapter.test.ts 断言syncConnectors在解析前确实 await 了waitForLoadingAdapters。

TronConnectUtil还包含一个"防冒名"校验:isGenuineAdapter通过检查window.tron.isTronLink === true或window.tronLink.ready === true,过滤掉为兼容性注入window.tronLink的仿冒钱包(如 Klever),避免 TronLinkAdapter 误报 "Found"。

五、连接、账户与钱包发现层的 UX 修复

5.1 Coinbase 连接器偏好回归修复(0.1.22)

0.1.22 修复了coinbasePreference配置被忽略的回归(源自 PR #5269):'all'与'eoaOnly'现在正确使用coinbaseWallet连接器(含 QR 码支持),'smartWalletOnly'使用baseAccount。底层实现见 packages/adapters/wagmi/src/client.ts 的addThirdPartyConnectors:从OptionsController.state读取enableCoinbase/enableBaseAccount/coinbasePreference,分别通过getBaseAccountConnector与getCoinbaseConnector(this.wagmiConfig.connectors, coinbasePreference)组装连接器。测试 packages/adapters/wagmi/src/tests/client.test.ts 对三种偏好分支(all/eoaOnly/smartWalletOnly)均有断言。

5.2 事件语义与钱包排名(0.1.11 / 0.1.10 / 0.1.12)

事件体系的演进体现了产品对"失败原因"的精细化管理:

  • 0.1.10:用户拒绝连接不再记CONNECT_ERROR,改记新事件USER_REJECTED(PR #4992);
  • 0.1.11:CONNECT_SUCCESS事件新增walletRank属性,并创建@appkit/recent_walletlocalStorage 键记录最近连接的 wallet(PR #5030);
  • 0.1.12:用户拒绝交易不再记SEND_ERROR,改记SEND_REJECTED(PR #5021)。

这些事件常量与载荷定义在 packages/controllers/src/utils/TypeUtil.ts(CONNECT_SUCCESS、USER_REJECTED、DISCONNECT_SUCCESS等),而walletRank的取值来自连接器在钱包榜单中的排序connector?.explorerWallet?.order,见 packages/controllers/src/controllers/ConnectionController.ts。结合 packages/controllers/src/controllers/ApiController.ts 中的walletRanks预取,可以推断walletRank用于在事件分析中衡量钱包发现效率。

5.3 钱包发现与展示的细节修正

  • 0.1.18:改进钱包搜索,按平台与 SDK 类型过滤掉不匹配的钱包(PR #5296)——对应 ApiController 的过滤逻辑在 0.1.8 中已允许 webapp 钱包在移动端出现;
  • 0.1.19:修复 ProfileWallets 标签页顺序(PR #5378),以及应用内钱包浏览器中钱包按钮失效(PR #5364);
  • 0.1.21:修复折叠钱包按钮显示复制图标而非钱包图标(PR #5450)、iOS 设备勾选图标不显示(PR #5449);
  • 0.1.23:wui-button作为 flex 子项可收缩,标签以省略号截断,避免 Sign 弹窗的 Cancel/Sign 按钮在同时处于 loading 时溢出弹窗边界(PR #5758)。该样式位于 packages/ui/src/composites/wui-button/styles.ts:button设white-space: nowrap,内部wui-text设min-width: 0; overflow: hidden; text-overflow: ellipsis,图标与 spinner 设flex-shrink: 0——正是"按钮可收缩 + 文本省略号截断"的实现。弹窗消费方见 packages/scaffold-ui/src/views/w3m-siwx-sign-message-view/index.ts,两个wui-button(neutral-secondary的 Cancel 与neutral-primary的 Sign)在isCancelling/isSigning时为?loading并切换文案 "Cancelling..." / "Signing..."。

六、转账、余额与网络细节:Bitcoin 与 Solana 专项

  • 0.1.2:修复 WalletConnect 连接在CONNECT_SUCCESS事件中缺少address(PR #4744);Bitcoin 连接新增 Binance Web3 Wallet deeplink 支持(PR #4748);
  • 0.1.4:引入连接钱包时的校验和地址(checksum)转换(PR #4821);修复移动钱包拒绝连接后无法返回上一屏重新发起(PR #4819);
  • 0.1.5:修复 Bitcoin WalletConnect 签名请求不含正确用户地址(PR #4886);修复 SPL Solana 代币无法通过 send 流程发送(PR #4877);
  • 0.1.6:新增 Bitcoinsignet网络(PR #4891);修复邮箱与社交登录禁用时authConnector仍被注入 wagmi 配置(PR #4892);
  • 0.1.12:修复 OKX Bitcoin 钱包连接时publicKey返回undefined(PR #5048);
  • 0.1.13:修复通用提供器在钱包拒绝连接时抛出随机对象错误(PR #5079);
  • 0.1.21:修复 Bitcoin 钱包返回的账户缺少 purpose 类型(PR #5452);Solana 转账失败时展示非友好错误消息的问题(PR #5444)。

这些条目大多对应 packages/adapters/bitcoin、packages/adapters/solana 与 packages/adapters/wagmi 的控制器/连接器实现,其中 "purpose 类型" 与 Bitcoin 多签名(multisig)账户体系相关,"publicKey 缺失"则与 OKX 注入式 Bitcoin 钱包的账户枚举实现相关。

七、网络标识与资产展示的细节

  • 0.1.9:修复 SIWX 屏幕钱包图标在 Safari 上渲染异常(PR #4965)、头部问号图标显示异常(PR #4982)、send 输入框缺少数字格式校验(PR #4968),并新增open函数的send 参数(token、amount、chain、recipient 预配置,PR #4962);
  • 0.1.14:新增getDisabledCaipNetworksAPI 用于获取被禁用的 CAIP 网络(PR #5098);
  • 0.1.16:AppKit 新增用量上限 UI,超限时展示(PR #5225);
  • 0.1.23:修复带损坏图片 URL 的代币显示裂图(PR #5747);修复 Rootstock 网络 logo 未在网络选择器中显示(PR #5723);Sign In 消息请求中默认钱包图标加大(PR #5755);"Don't have X?" 下载 CTA 不再硬截断钱包全名(PR #5756)。

其中 send 参数预配置能力与 packages/pay/src/client.ts 的openPay(options)互为表里:PaymentOptions中的paymentAsset(含network、asset、metadata)、recipient、amount会被写入PayController状态,并在handleOpenPay中通过PAY_MODAL_OPEN事件上报配置快照。getDisabledCaipNetworks则可从 packages/controllers/src/controllers/ChainController.ts 的网络状态中推断,用于在 UI 层灰显不可用网络。

八、版本维护与依赖治理

CHANGELOG 也记录了工程化层面的例行升级:

  • 0.1.14 / 0.1.16 / 0.1.23:多次将 viem、wagmi、WalletConnect、Solana 等依赖升级到最新版本;0.1.23 明确"Upgraded viem to latest version";
  • 0.1.16:修复打包时包版本注入问题(PR #5247)——对应仓库根目录 scripts/inject-version.js 的职责;
  • 0.1.17:修复使用 appkit core 时仍调用远程配置端点的问题(PR #5274);
  • 0.1.3:将ReownAuthentication类迁入@reown/appkit-controllers包,并通过 AppKit features 与 remote features 简化集成(PR #4750)——这是认证能力从应用层下沉到控制器层的关键重构。

pay-test-exchange应用本身基于 Next.js 15(Turbopack dev,端口 4001)与 OpenNext Cloudflare 部署,部署脚本opennextjs-cloudflare build && opennextjs-cloudflare deploy见 apps/pay-test-exchange/package.json。

九、总结:从 CHANGELOG 看 AppKit Pay 的设计哲学

回看 apps/pay-test-exchange/CHANGELOG.md 从 0.1.1 到 0.1.23 的 23 个补丁版本,可以提炼出三条清晰的设计主线:

  1. 支付通道的多元化:从"钱包直接转账"单一通道,演进为"钱包直付 + 交易所出金 + 报价驱动的自动兑换桥接"三条通道并存,PayController的状态机与quote体系是这一演进的载体;
  2. 多链适配器的可插拔范式:AdapterBlueprint抽象让 Stellar(纯 WalletConnect)、TRON(扩展 + WalletConnect 混合)、Solana、Bitcoin 等异构链以统一接口接入,扩展钱包不存在的链用显式 no-op 满足接口而非硬造实现;
  3. 状态一致性的执念:从 SIWX 竞态、TRON 引导同步、钱包切换后的 stale provider,到 Cancel/Sign 按钮溢出,绝大多数 Patch 都在对抗"异步状态在何时以何种顺序收敛"这一核心复杂度。

对于正在接入 AppKit Pay 或扩展多链支持的开发者,这份 CHANGELOG 既是"已知问题与规避方式"的索引,也是理解 packages/pay、packages/adapters、packages/siwx 源码架构的最佳导读。

  • 区块链
  • 前端
  • 认证鉴权

【免费下载链接】web3modal

The full stack toolkit to build onchain app UX

项目地址:https://gitcode.com/gh_mirrors/we/web3modal
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/13 4:53:35

ThreadPoolTaskExecutor为何默认LinkedBlockingQueue?与ArrayBlockingQueue全面对比

这道题我在不少面试场合见过&#xff0c;也在几轮内部候选人评估里把它当"进阶题"来用。表面问的是两个队列的差异&#xff0c;实际上考察的是三件事&#xff1a;对线程池执行流程的理解、对并发容器实现细节的了解、以及有没有真实处理过生产环境线程池问题。如果只…

作者头像 李华
网站建设 2026/10/13 4:53:31

从概念到工程落地:agent-skills 技能体系设计指南

agent-skills 这个词最近频繁出现在各类智能体讨论里。第一次看到时可能觉得就是个普通项目名&#xff0c;其实背后的思想是把智能体拆成“会干一件明确事情的技能集合”。我在这块摸爬滚打了一段时间&#xff0c;发现很多团队卡住的地方不是模型能力不够&#xff0c;而是技能定…

作者头像 李华
网站建设 2026/10/13 4:52:43

联邦学习分布式训练MNIST:FedAvg与客户端聚合实战解析

简介&#xff1a;这份联邦学习分布式训练资源以MNIST手写数字识别为示例&#xff0c;面向希望掌握联邦学习、分布式训练与隐私保护技术的开发者、学生或研究人员。压缩包内共17个文件&#xff0c;总大小约56.29MB&#xff0c;主要包括Python脚本、模型权重文件、MNIST原始数据及…

作者头像 李华
网站建设 2026/10/13 4:52:43

基于OpenCV的SUSAN边缘检测与米粒计数实践:从原理到代码

简介&#xff1a;面向计算机视觉与OpenCV入门学习者的实验工程&#xff0c;在Visual Studio中演示Susan算子边缘检测与米粒图像处理任务。工程覆盖中值滤波去噪、灰度直方图统计、大津法与经验阈值分割、Susan边缘检测、连通区域分析与米粒计数等步骤&#xff0c;并以实际米粒图…

作者头像 李华
网站建设 2026/10/13 4:51:31

LiteLLM实战:统一多模型API接入的网关方案与避坑指南

说实话&#xff0c;在真正用上 LiteLLM 之前&#xff0c;我一度觉得这类“模型中间层”是多余的东西——多一层封装&#xff0c;就多一层故障点&#xff0c;出了问题反而不好排查。直到我自己接了一个需要同时对接多家模型服务商的内部工具&#xff0c;才彻底改观。那段时间&am…

作者头像 李华
网站建设 2026/10/13 4:51:20

macOS上搭建learnOpenGL环境:GLFW+GLAD+CMake完整指南

1. 先说思路&#xff1a;macOS 上跑 learnOpenGL 到底在忙活什么1.1 三个组件各管哪一摊很多人第一次翻开 learnOpenGL 教程&#xff0c;看到 GLFW、GLAD、CMake 这一堆词直接蒙了。实际上在 macOS 上搭环境&#xff0c;本质上就是解决三件事&#xff1a;谁负责创建窗口、谁负责…

作者头像 李华