状态管理Skill midnight-dapp:state-management

Midnight DApp状态管理技能专注于区块链去中心化应用中的状态处理,包括读取链上公共状态、管理本地私有状态、实现状态同步与缓存优化。关键词:Midnight DApp、状态管理、双状态模型、链同步、隐私缓存、智能合约状态、区块链开发、Web3应用。

DApp开发 0 次安装 0 次浏览 更新于 2/26/2026

name: midnight-dapp:state-management description: 用于读取公共账本状态、实现与链状态同步的响应式UI、缓存状态以优化性能,或理解Midnight DApp中的公共与私有状态。

状态管理

在Midnight DApp中读取、同步和缓存合约状态,并正确处理双状态模型。

使用场景

  • 从已部署合约中读取公共账本状态
  • 实现与链状态同步更新的响应式UI
  • 缓存状态以优化性能
  • 理解何时使用公共状态与私有状态
  • 跨多个组件同步状态

核心概念

双状态模型

Midnight合约拥有两种状态类型:

状态类型 存储位置 访问方式 可见性
公共账本状态 链上(索引器) contract.state.* 任何人都可读取
私有本地状态 浏览器(LevelDB) WitnessContext.privateState 仅本地用户

这与以太坊所有状态都公开在链上的模式有根本不同。

状态访问模式

// 公共状态 - 任何人都可读取
const totalSupply = await contract.state.total_supply();
const balance = await contract.state.balances.get(address);

// 私有状态 - 仅在见证中访问
const witnesses = {
  get_secret: ({ privateState }) => privateState.secretKey,
};

链同步

链上状态可能因其他交易而改变。DApp必须处理:

  1. 初始加载 - 组件挂载时获取当前状态
  2. 轮询 - 定期检查更新
  3. WebSocket - 订阅实时更新
  4. 乐观更新 - 在确认前更新UI

参考资料

文档 描述
contract-state.md 读取公共和私有合约状态
chain-sync.md 同步模式和订阅
privacy-aware-caching.md Midnight的安全缓存策略
web3-comparison.md 以太坊状态模式与Midnight对比

示例

示例 描述
use-contract-state/ 读取合约状态的React钩子
state-sync-provider/ 状态同步的上下文提供者
cache-manager/ 隐私感知缓存工具

快速开始

1. 读取简单状态值

// 部署合约后,读取公共状态
const contract = await deployedContract();

// 简单值
const totalSupply: bigint = await contract.state.total_supply();

// 映射查找
const balance: bigint | undefined = await contract.state.balances.get(userAddress);

// 集合成员检查
const isMember: boolean = await contract.state.members.has(userAddress);

2. 创建状态钩子

function useContractState<T>(
  contract: Contract,
  accessor: (state: ContractState) => Promise<T>
) {
  const [value, setValue] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;

    async function fetchState() {
      setLoading(true);
      const result = await accessor(contract.state);
      if (!cancelled) {
        setValue(result);
        setLoading(false);
      }
    }

    fetchState();
    return () => { cancelled = true; };
  }, [contract, accessor]);

  return { value, loading };
}

3. 订阅更新

// 轮询状态变化
useEffect(() => {
  const interval = setInterval(async () => {
    const newBalance = await contract.state.balances.get(address);
    setBalance(newBalance);
  }, 5000); // 每5秒轮询一次

  return () => clearInterval(interval);
}, [contract, address]);

常用模式

类型安全的状态读取

interface ContractState {
  total_supply(): Promise<bigint>;
  balances: {
    get(address: string): Promise<bigint | undefined>;
  };
  members: {
    has(address: string): Promise<boolean>;
  };
}

// 编译器从你的Compact合约生成这些类型

错误处理

async function safeStateRead<T>(
  accessor: () => Promise<T>,
  fallback: T
): Promise<T> {
  try {
    return await accessor();
  } catch (error) {
    console.error('状态读取失败:', error);
    return fallback;
  }
}

const balance = await safeStateRead(
  () => contract.state.balances.get(address),
  0n
);

乐观更新

// 立即更新UI,然后与链同步
const [balance, setBalance] = useState<bigint>(0n);

async function transfer(to: string, amount: bigint) {
  // 乐观更新
  setBalance(prev => prev - amount);

  try {
    await contract.callTx.transfer(to, amount, witnesses);
    // 状态将在下次轮询时同步
  } catch (error) {
    // 回滚乐观更新
    setBalance(prev => prev + amount);
    throw error;
  }
}

相关技能

  • wallet-integration - 设置提供者所需
  • proof-handling - 访问私有状态的见证实现
  • transaction-flows - 提交状态变更交易
  • error-handling - 处理状态读取错误

相关命令

  • /dapp-check - 验证提供者配置
  • /dapp-debug state - 调试状态同步问题