@somnia-chain/reactivity
v0.2.0
Published
Typescript SDK to build event-driven applications on the Somnia blockchain
Maintainers
Readme
🚀 Somnia Reactivity TypeScript SDK
The Somnia Reactivity TypeScript SDK enables applications within the Javascript and Typescript ecosystem (full stack) to immediately utilize reactivity tooling offered by Somnia chain with minimal boiler-plate code.
🔒 Key abstractions
The SDK uses viem to abstract away RPC calls, wallets, transaction creation and starting subscriptions.
- For read-only access, provide just a public client—the SDK handles contract setup for Somnia testnet or mainnet.
- For transactions, add any wallet client: private key-based, remote signer, ERC-4337 AA, etc.
🚀 Getting Started
📦 SDK Installation
Example with npm:
npm i @somnia-chain/reactivityHowever, feel free to use alternatives like pnpm
pnpm add @somnia-chain/reactivity🔌 Plugging into the SDK
You'll need viem installed for the public and or wallet client. Install it with npm i viem.
import { createPublicClient, createWalletClient, http, defineChain } from 'viem'
import { SDK } from '@somnia-chain/reactivity'
// Example: Public client (required for reading data)
const chain = defineChain() // see viem docs for defining a chain
const publicClient = createPublicClient({
chain,
transport: http(),
})
// Optional: Wallet client for writes
const walletClient = createWalletClient({
account,
chain,
transport: http(),
})
const sdk = new SDK({
public: publicClient,
wallet: walletClient, // Omit if not executing transactions on-chain
})📡 Activating Websocket Watch (off-chain)
Use WebSocket subscriptions for real-time updates to contract event and state updates atomically. Define params and subscribe — the SDK handles the rest via WebSockets.
import { SDK, WebsocketSubscriptionInitParams, SubscriptionCallback } from '@somnia-chain/reactivity'
// Example params
const initParams: WebsocketSubscriptionInitParams = {
ethCalls: [], // State to read when events are emitted
context: 'data', // Optional, e.g., 'topic0', 'data', 'address'
onData: (data: SubscriptionCallback) => console.log('Received:', data),
onError: (error: Error) => console.error('Error:', error), // Optional
eventContractSources: ['0xYourEmitterAddress'], // Optional, filter by emitter
topicOverrides: ['0xYourTopic0'], // Optional, filter by topics
onlyPushChanges: true, // Optional, push only if data changes
}
const subscription = await sdk.watch(initParams)
// Later, unsubscribe when done
await subscription.unsubscribe()⛓️ On-Chain Subscriptions (Solidity-Friendly Wrappers)
The SDK exposes wrapper params aligned with the Solidity SomniaExtensions ergonomics:
subscribe({ handlerContractAddress, filter, options })— subscribe to a contract eventscheduleSubscriptionAtTimestamp({ timestampMs, handlerContractAddress, options })— trigger at an absolute unix timestamp (ms)scheduleSubscriptionAtBlock({ blockNumber, handlerContractAddress, options })— trigger at a specific (or any future) blockscheduleSubscriptionAtEpoch({ epochNumber, handlerContractAddress, options })— trigger at a specific epochunsubscribe(subscriptionId)— cancel an active subscriptiongetSubscriptionInfo(subscriptionId)— fetch parameters and owner of a subscriptionsubscribeRaw(subscriptionData)— low-level wrapper that accepts a fully-assembledSoliditySubscriptionDatastruct
Low-level precompile fields are handled internally by the SDK and intentionally hidden from subscribe inputs:
callerisGuaranteedisCoalesced
import { SDK, SoliditySubscribeRequest } from '@somnia-chain/reactivity'
const request: SoliditySubscribeRequest = {
handlerContractAddress: '0xYourHandlerAddress',
filter: {
// eventTopics/origin/emitter are optional
eventTopics: ['0xYourTopic0'],
emitter: '0xYourEmitterAddress',
},
options: {
priorityFeePerGas: 1_000_000_000n,
maxFeePerGas: 10_000_000_000n,
gasLimit: 5_000_000n,
},
}
const txHash = await sdk.subscribe(request)Cancelling a subscription
import { SDK } from '@somnia-chain/reactivity'
const txHash = await sdk.unsubscribe(subscriptionId) // subscriptionId: bigint
if (txHash instanceof Error) throw txHash
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash })Querying subscription details
import { SDK, SoliditySubscriptionInfo } from '@somnia-chain/reactivity'
const info = await sdk.getSubscriptionInfo(subscriptionId) // subscriptionId: bigint
if (info instanceof Error) throw info
// info.subscriptionData — full SubscriptionData struct
// info.owner — address that owns the subscriptionLive SDK Test
A live end-to-end test runner is available at scripts/live-test-reactivity.mjs. It exercises all public methods in Reactivity.ts:
watchsubscribeRawsubscribescheduleSubscriptionAtTimestampscheduleSubscriptionAtBlockscheduleSubscriptionAtEpochgetSubscriptionInfounsubscribe
Run via shell wrapper (similar flow to Solidity live test scripts):
./scripts/LiveTestReactivitySdk.sh "https://rpc-url" "0xprivate-key"📋 Exported Types and Constants
| Export | Description |
|---|---|
| SoliditySubscribeRequest | Input type for sdk.subscribe() |
| SoliditySubscriptionData | Low-level precompile subscription struct (used by subscribeRaw) |
| SoliditySubscriptionInfo | Return type of sdk.getSubscriptionInfo() — { subscriptionData, owner } |
| SoliditySubscriptionFilter | { eventTopics?, origin?, emitter? } |
| SoliditySubscriptionOptions | { priorityFeePerGas, maxFeePerGas, gasLimit } |
| BlockTickSubscriptionRequest | Input type for sdk.scheduleSubscriptionAtBlock() |
| ScheduleRequest | Input type for sdk.scheduleSubscriptionAtTimestamp() |
| EpochTickSubscriptionRequest | Input type for sdk.scheduleSubscriptionAtEpoch() |
| WebsocketSubscriptionInitParams | Input type for sdk.watch() |
| SubscriptionCallback | Data shape passed to the onData callback in watch() |
| EthCall | Single ETH call entry used in WebsocketSubscriptionInitParams.ethCalls |
| defaultSubscriptionOptions | Constant with default fee/gas values (priorityFeePerGas: 0, maxFeePerGas: 20 gwei, gasLimit: 10_000_000) |
📚 Documentation
For detailed documentation, head over to our doc site here.
