Somnia On-Chain 反应性
Source: Dev.to

1. 引言
作为 Web3 开发者,我们经常构建需要自动响应的系统。
真实项目中的例子包括链上游戏、PotWar 池、预测市场:
- 计时结束时最后一位玩家获胜
- 开箱后自动奖励
- 池子自动支付
- NFT 在获得 XP 后升级
- DAO 提案自动执行
使用传统智能合约,这需要:
- 后端服务器
- 事件索引器
- 定时任务(Cron jobs)
- 额外的用户交易
这会增加复杂性、成本和中心化风险。
Somnia 链上响应性 通过允许智能合约在链上完全自动响应事件来解决这些问题。
2. 什么是 Somnia 链上响应性?
Somnia 让智能合约在订阅的事件发生时自动执行逻辑。
传统流程
User Action → Event → Backend Listener → New Tx → State Update
Somnia 响应式流程
User Action → Event → Validator Detect → _onEvent() → State Update
- 无后端。
- 无额外用户 gas。
- 完全去中心化。
3. 为什么这对 Web3 开发者很重要
对于从事游戏、DeFi 或自动化的构建者:
- 无服务器基础设施
- 更低延迟
- 更简洁的架构
- 更好的用户体验
- 更快的黑客松构建
例如,在 Last Player Standing 中我们不需要后端计时器;合约逻辑可以自动响应。
4. 示例:Magic Chest Reactive Game
让我们构建一个小型游戏。
游戏规则
- Common chest → +10 金币
- Rare chest → +50 金币
- Legendary chest → NFT 剑
玩家打开箱子 → 奖励自动发放。
5. Solidity 合约示例
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import { SomniaEventHandler }
from "@somnia-chain/reactivity-contracts/contracts/SomniaEventHandler.sol";
contract MagicChestReactiveGame is SomniaEventHandler {
event ChestOpened(address indexed player, uint256 chestType);
mapping(address => uint256) public coins;
mapping(address => bool) public hasSword;
bytes32 constant CHEST_SIG =
keccak256("ChestOpened(address,uint256)");
uint256 constant COMMON = 1;
uint256 constant RARE = 2;
uint256 constant LEGENDARY = 3;
function openChest(uint256 chestType) external {
emit ChestOpened(msg.sender, chestType);
}
function _onEvent(
address,
bytes32[] calldata topics,
bytes calldata data
) internal override {
require(topics[0] == CHEST_SIG, "Wrong event");
address player =
address(uint160(uint256(topics[1])));
uint256 chestType =
abi.decode(data, (uint256));
if (chestType == COMMON)
coins[player] += 10;
else if (chestType == RARE)
coins[player] += 50;
else if (chestType == LEGENDARY)
hasSword[player] = true;
}
}
6. Reactivity 工作原理(内部)
- 玩家调用
openChest() - 事件被触发
- Somnia 验证者检测到订阅
_onEvent()自动执行- 状态已更新
- 无需额外交易
Reactive transaction is executed by validator address:
0x0000000000000000000000000000000000000100
7. 为事件创建订阅
import { SDK } from "@somnia-chain/reactivity";
import { privateKeyToAccount } from "viem/accounts";
import { createPublicClient, createWalletClient, http } from "viem";
import { somniaTestnet } from "viem/chains";
import { keccak256, toBytes } from "viem";
const CONTRACT = "0xYourContractAddress";
async function main() {
const account = privateKeyToAccount(
process.env.PRIVATE_KEY as `0x${string}`
);
const publicClient = createPublicClient({
chain: somniaTestnet,
transport: http(),
});
const walletClient = createWalletClient({
account,
chain: somniaTestnet,
transport: http(),
});
const sdk = new SDK({
public: publicClient,
wallet: walletClient,
});
const EVENT_SIG = keccak256(
toBytes("ChestOpened(address,uint256)")
);
const txHash = await sdk.createSoliditySubscription({
handlerContractAddress: CONTRACT,
emitter: CONTRACT,
eventTopics: [EVENT_SIG],
gasLimit: 3_000_000n,
});
const receipt = await publicClient.waitForTransactionReceipt({
hash: txHash,
});
// 👉 Extract subscriptionId
const log = receipt.logs[0];
const subscriptionId = BigInt(log.topics[2]);
console.log("Subscription ID:", subscriptionId.toString());
}
main();
重要说明
- 需要 32 STT 余额。
- 保存订阅 ID。
- 事件签名必须完全匹配。
8. 测试响应性
import { ethers } from "hardhat";
const CONTRACT = "0xYourContractAddress";
async function main() {
const [user] = await ethers.getSigners();
const game = await ethers.getContractAt(
"MagicChestReactiveGame",
CONTRACT
);
const before = await game.coins(user.address);
console.log("Coins before:", before.toString());
const tx = await game.openChest(1); // 1 = COMMON
await tx.wait();
console.log("Waiting for Somnia reactivity...");
await new Promise(r => setTimeout(r, 5000)); // adjust as needed
const after = await game.coins(user.address);
console.log("Coins after:", after.toString());
if (after > before) {
console.log("✅ Reactivity Working");
} else {
console.log("❌ No Reactivity");
}
}
main();
9. 实际使用案例
游戏
- 最后存活玩家
- PotWar 自动支付
- 掠夺奖励
- NFT 升级
预测市场
- 自动奖励分配
- 分数更新
去中心化金融 (DeFi)
- 清算
- 收益分配
DAO
- 提案自动执行
10. 结论
Somnia On‑Chain Reactivity 消除了对后端的依赖,使智能合约能够完全自治。
对于构建自动化游戏逻辑、预测市场或 DeFi 自动化的开发者而言,这开启了全新的可扩展性和简易性。
Web3 应用的未来是响应式的。
Neeraj Choubisa(Nikku.Dev)— 全栈区块链工程师,专注于智能合约开发、Web3 集成以及面向消费者的去中心化应用。
