Somnia On-Chain Reactivity

Published: (February 16, 2026 at 09:06 AM EST)
4 min read
Source: Dev.to

Source: Dev.to

Cover image for Somnia On-Chain Reactivity

Neeraj Choubisa

1. Introduction

As Web3 developers, we often build systems that require automatic reactions.
Examples from real projects like on‑chain games, PotWar pools, prediction markets:

  • Last player wins when timer ends
  • Auto reward after chest open
  • Pool auto payout
  • NFT level‑up after XP
  • DAO proposal auto‑execute

With traditional smart contracts, this requires:

  • Backend server
  • Event indexer
  • Cron jobs
  • Extra user transactions

This increases complexity, cost, and centralization.

Somnia On‑Chain Reactivity solves this by allowing smart contracts to automatically react to events fully on‑chain.

2. What is Somnia On‑Chain Reactivity?

Somnia lets smart contracts execute logic automatically when subscribed events occur.

Traditional Flow

User Action → Event → Backend Listener → New Tx → State Update

Somnia Reactive Flow

User Action → Event → Validator Detect → _onEvent() → State Update
  • No backend.
  • No extra user gas.
  • Fully decentralized.

3. Why This Matters for Web3 Devs

For builders working on gaming, DeFi, or automation:

  • No server infra
  • Less latency
  • Cleaner architecture
  • Better UX
  • Faster hackathon builds

For example, in Last Player Standing we don’t need a backend timer; contract logic can react automatically.

4. Example: Magic Chest Reactive Game

Let’s build a small game.

Game Rules

  • Common chest → +10 coins
  • Rare chest → +50 coins
  • Legendary chest → NFT sword

Player opens chest → reward auto‑given.

5. Solidity Contract Example

// 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. How Reactivity Works Internally

  1. Player calls openChest()
  2. Event emitted
  3. Somnia validators detect subscription
  4. _onEvent() executes automatically
  5. State updated
  6. No extra transaction required

Reactive transaction is executed by validator address:

0x0000000000000000000000000000000000000100

7. Creating a Subscription for the Event

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();

Important Notes

  • Need 32 STT balance.
  • Save subscription ID.
  • Event signature must match exactly.

8. Testing Reactivity

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. Real Use Cases

Gaming

  • Last Player Standing
  • PotWar auto payout
  • Loot rewards
  • NFT upgrades

Prediction Markets

  • Auto reward distribution
  • Score updates

DeFi

  • Liquidations
  • Yield distribution

DAO

  • Proposal auto‑execute

10. Conclusion

Somnia On‑Chain Reactivity removes backend dependency and enables fully autonomous smart contracts.

For developers building automated gaming logic, prediction markets, or DeFi automation, this unlocks a new level of scalability and simplicity.

The future of Web3 apps is reactive.

Neeraj Choubisa (Nikku.Dev) – Full‑Stack Blockchain Engineer specializing in smart contract development, Web3 integrations, and consumer‑focused decentralized applications.

0 views
Back to Blog

Related posts

Read more »