跳到主要内容

在 Chia 上构建一个 dapp

每个 DIG 基础原语都有各自独立的文档 —— 脚手架、页内钱包、读取路径、支出、部署。本页则是将它们串联成一个完整已发布 dapp 的那条唯一线索。 你将从一个空文件夹开始,最终得到一个具备钱包能力的 React 应用,并在自己的域名下于链上正式上线。

从头到发布之前的整个流程都是免费的 —— 搭建脚手架、开发和预览都不花一分钱。你只在部署这一步才需要支付以 $DIG 计价的统一 capsule 价格

new ──▶ dev ──▶ wire wallet (dig-sdk) ──▶ build a spend (chip35) ──▶ deploy ──▶ custom domain
free free free free capsule price free

你需要准备什么

  • 已安装 digstore CLI
  • Node 18+ 和 npm
  • 一个已充值的 Chia 钱包 —— 仅在部署这一步需要(以 $DIG 计价的统一 capsule 价格 + 少量 XCH 手续费)。在此之前的一切都是免费的。

1. 搭建一个 React 应用 —— 免费,不上链

digstore new 会写入一个可运行的、已接入钱包的项目。选择 React 模板:

digstore new vite-react my-dapp
cd my-dapp

你会得到一个 Vite + React 应用、一个 dig.tomloutput-dir = "dist"build-command = "npm install && npm run build"),以及一个已经接入页内钱包的 App.jsx。此时没有任何 store 被铸造,也没有任何花费 —— new 完全是本地操作。

更喜欢 npm?使用 npm create dig-app

npm create dig-app@latest my-dapp -- --template vite-react 可以直接从 npm 搭建同样的模板 —— 这是 JS 入口,无需先安装 digstore 即可开始。查看搭建应用脚手架了解全部五种模板,以及这两个入口之间的比较。

2. 在真实读取路径上开发 —— 免费

digstore dev

dev 会运行你的构建流程,通过真实的 chia:// 读取路径(编译 → 验证 → 解密)提供输出内容的服务,并注入一个 window.chia 开发模拟器(dev shim),让你无需真实钱包即可开发钱包相关流程。编辑 src/App.jsx 并保存,页面会热重载 —— 这正是访客最终会看到的效果,且不涉及任何链上交互,也不会有任何花费。

3. 用 SDK 接入钱包 —— window.chia + WalletConnect 回退

脚手架直接与 window.chia 通信,这在 DIG Browser 内部效果完美。为了同时支持其他浏览器的用户,可以添加 SDK —— 它会优先使用注入的 window.chia 钱包,回退到 WalletConnect → Sage,两者被统一封装在同一个规范化接口之下,因此钱包相关逻辑只需编写一次。

npm i @dignetwork/dig-sdk
npm i @walletconnect/sign-client # optional: only for the WalletConnect fallback
// src/App.jsx
import { useState } from "react";
import { ChiaProvider } from "@dignetwork/dig-sdk";

export default function App() {
const [address, setAddress] = useState(null);

async function login() {
// "auto" prefers the injected DIG Browser wallet, else WalletConnect → Sage.
const provider = await ChiaProvider.connect({
mode: "auto",
walletConnect: {
projectId: import.meta.env.VITE_WC_PROJECT_ID, // a PUBLIC build-time value
metadata: {
name: "My DIG dapp",
description: "Built with @dignetwork/dig-sdk",
url: "https://my-dapp.example",
icons: ["https://my-dapp.example/icon.png"],
},
onUri: (uri) => console.log("Scan to connect:", uri), // render a QR
},
});
setAddress(await provider.getAddress());
}

return (
<main>
<h1>My DIG dapp</h1>
<button onClick={login}>Connect wallet</button>
{address && <p>Connected: {address}</p>}
</main>
);
}

同一个 connect() 调用既能在 DIG Browser 中工作(无需二维码,无需中继),也能在其他任何地方工作(通过 WalletConnect)。provider.backend 会告诉你实际连接使用的是哪种传输方式。无论哪种情况,方法名称和返回结果的结构都完全一致 —— 完整的集成指南参见使用 window.chia,或者查看规范性的 window.chia provider 规范文档以获取确切的方法/参数/返回值/错误约定。

WalletConnect 项目 ID 是一个公开的构建期取值

VITE_WC_PROJECT_ID 会被编译进你的构建产物中,是全世界都可读的 —— 对于一个 WalletConnect 云端 ID 来说,这是正确的做法。切勿将钱包助记词、部署密钥或任何机密信息放入构建产物中:capsule 是一个没有服务器端机密信息的盲态静态制品

4. 构建并签名一笔支出 —— 通过 SDK 使用 chip35 wasm

当你的 dapp 需要在链上执行某些操作时(铸造一个 store、更新元数据、构建一笔 CAT 支付),它会使用规范的 CHIP-0035 支出构建器来构建这笔支出,并交给钱包签名。SDK 在 /spend 子路径下重新导出了该构建器 —— 你永远不需要手工拼装一个支出包

import { ChiaProvider } from "@dignetwork/dig-sdk";
import * as spend from "@dignetwork/dig-sdk/spend"; // the chip35 wasm builder

async function doSpend() {
spend.init();

// Build coin spends with the wasm builder, e.g. spend.mintStore(...) /
// spend.updateStoreMetadata(...) / spend.buildDigPayment(...). The builder is
// offline and pure — no keys, no network.
const coinSpends = /* spend.mintStore({ ... }) */ [];

// Hand them to the wallet to sign (the wallet holds the keys, not your dapp).
const provider = await ChiaProvider.connect({ mode: "auto" });
const aggregatedSignature = await provider.signCoinSpends(coinSpends);
// → combine into a spend bundle and broadcast.
}

这正是 hub 所使用的精确模式:在浏览器中用 wasm 构建支出包,用钱包为其签名。 该支出构建器是整个生态系统中支出包的唯一规范来源,因此你的 dapp 产生的支出与 hub 和 CLI 产生的支出在字节层面完全一致。

读取已验证的加密内容(例如,在你的 dapp 中渲染另一个 store 的数据),可以使用 SDK 的 DigClient

import { DigClient } from "@dignetwork/dig-sdk";

const dig = new DigClient(); // defaults to https://rpc.dig.net
const html = await dig.readText({
urn: "urn:dig:chia:<storeId>/index.html",
root: "<onchain-root-hex>", // the trust anchor, read from the chain
});

DigClient 会在浏览器中推导出 URN 对应的密钥,对照链上根哈希验证包含性,然后解密 —— 服务端的主机始终保持盲态。参见什么是 dig RPC?

想要收费访问?使用 Paywall

若要实现变现 —— 付费解锁内容,或将访问权限限定为持有某个 NFT —— SDK 提供了一个高级的 Paywall 辅助工具,它将一个已连接的 ChiaProvider 与支出构建器组合起来,让你无需手动接入支付逻辑:paywall.requestPayment({ amount, owner }) 会向 dapp 所有者付款并返回一个凭证,而 paywall.verifyReceipt(...) / paywall.proveAccess({ nft | collection }) 则用于门控访问权限。

import { ChiaProvider, Paywall } from "@dignetwork/dig-sdk";

const provider = await ChiaProvider.connect({ mode: "auto" });
const paywall = new Paywall({ provider });
const receipt = await paywall.requestPayment({ amount: 5, owner: "<your-address>" });
if (await paywall.verifyReceipt(receipt)) { /* unlock the content */ }

5. 部署上链

构建和预览都是免费的;这一步是唯一会花费的步骤。首先一次性创建 store:

digstore init my-dapp --dir dist      # mint the store's first capsule (uniform capsule price + XCH fee)

init 会在主网上铸造一个 Chia singleton —— launcher id 即成为你的 store id。将它复制进 dig.tomlstore-id = "<64-hex>")。此后,一条命令即可构建并发布一个新的 capsule:

digstore deploy --json                # runs build-command, stages dist/, advances the root

每一次 deploy 都会以统一的 capsule 价格发布一个新的不可变 capsule。一经确认,你的 dapp 就可以通过 dig RPC 读取,通过它的 URN / chia:// 地址访问 —— 加密、已验证,且无法被下线,无需注册,也无需额外付费。(一个友好的 *.on.dig.net 网址是一个单独的可选步骤 —— 参见下一节。)若要在每次提交时都实现 push-to-deploy,请接入从 GitHub Actions 部署

6. 部署到你自己的域名

你的 store 已经可以通过它的 URN / dig:// 地址访问 —— 但如果想要一个友好的网址,你需要注册一个名字。当你在 DIGHUb 中为 store 注册一个 handle 时,它就会获得一个 *.on.dig.net 子域名:这是一项单独的付费注册,用于将该 store 固定到那个名称上(不注册 → 就没有 *.on.dig.net 地址)。如果想改用你自己拥有的域名提供服务,可以在 DIGHUb ↗ 中添加一个带 TLS 的自定义域名 —— 将你的域名指向该 store,DIGHUb 会自动处理证书。无论哪种方式,你的 dapp 都会从一个人类友好的网址加载,同时底层依然完全去中心化。

当 CHIP-54 的 .dig handle 落地后,一个 store 也将可以通过人类可读的 .dig 名称被寻址;在那之前,通过 DIGHUb 使用自定义域名是为一次部署打上品牌标识的方式。


你已经发布了一个 dapp

你从一个空文件夹出发,最终得到了一个具备钱包能力的 React 应用,并在 Chia 主网上通过你自己的域名正式上线 —— 沿途接触了每一个基础原语:脚手架搭建页内钱包SDK支出构建器读取路径,以及部署。你也可以从示例画廊中克隆一个已完成的版本。