Skip to content

This guide targets the Tiramisu testnet. Check Networks for current testnets and faucets.

The watchEntityEvents method on the public client lets you listen for entity changes in real time. It polls the chain for new events. When an entity is created, patched, deleted, extended, or handed to a new owner, it calls the handlers you pass.

import { createPublicClient } from "@arkiv-network/sdk"
import { tiramisu } from "@arkiv-network/sdk/chains"
import { http } from "viem"
const client = createPublicClient({
chain: tiramisu,
transport: http(),
})
const unwatch = client.watchEntityEvents({
onEntityCreated: (event) => {
console.log("Entity created:", event.entityKey)
},
onEntityPatched: (event) => {
console.log("Entity patched:", event.entityKey)
},
onEntityDeleted: (event) => {
console.log("Entity deleted:", event.entityKey)
},
onExpiryExtended: (event) => {
console.log("Expiry extended:", event.entityKey)
},
onOwnershipTransferred: (event) => {
console.log("Ownership transferred:", event.entityKey)
},
onError: (error) => {
console.error("Watch error:", error)
},
})
// Later, stop listening:
unwatch()

watchEntityEvents takes one object with the event handlers plus a couple of optional settings:

ParameterTypeDescription
Event handlerssee belowOne callback per event type, all optional
onEvent(event: EntityEvent) => voidEvery event, whatever its type, runs before the per-event handler
onError(error: Error) => voidTransport failures, undecodable logs, or a handler that throws. Defaults to console.error.
fromBlockbigintReplay from this block before following the head. Defaults to the head.
pollingIntervalnumberHow often to poll, in milliseconds. Defaults to half a block.
HandlerEvent TypeFires When
onEntityCreatedEntityCreatedEventA new entity is created
onEntityPatchedEntityPatchedEventAn entity’s attributes or payload change
onExpiryExtendedExpiryExtendedEventAn entity’s expiry moves further out
onOwnershipTransferredOwnershipTransferredEventAn entity changes owner
onEntityDeletedEntityDeletedEventAn entity is deleted by its owner, before its expiry

Every event carries blockNumber, transactionHash and logIndex, which together give you the order the operations were applied in.

{
type: "EntityCreated"
entityKey: Hex
owner: Address
expiresAt: bigint // block the entity is set to expire at
creationFlags: { readonly: boolean; permissionlessExtension: boolean }
blockNumber: bigint
transactionHash: Hex
logIndex: number
}
{
type: "EntityPatched"
entityKey: Hex
owner: Address
blockNumber: bigint
transactionHash: Hex
logIndex: number
}

The event only says an entity’s attributes or payload changed, not what changed. Call getEntity() to read the new state.

{
type: "ExpiryExtended"
entityKey: Hex
owner: Address // the entity's owner, not necessarily who extended it
expiresAt: bigint // the new expiry block
blockNumber: bigint
transactionHash: Hex
logIndex: number
}
{
type: "OwnershipTransferred"
entityKey: Hex
previousOwner: Address
newOwner: Address
blockNumber: bigint
transactionHash: Hex
logIndex: number
}
{
type: "EntityDeleted"
entityKey: Hex
owner: Address
blockNumber: bigint
transactionHash: Hex
logIndex: number
}

Use fromBlock to replay events. The replay starts from a past block:

const unwatch = client.watchEntityEvents({
onEntityCreated: (event) => {
console.log("Created:", event.entityKey, "at block", event.blockNumber)
},
fromBlock: 100n,
pollingInterval: 5000, // poll every 5 seconds
})

Listen for changes to your own entities and log a summary:

import { createPublicClient } from "@arkiv-network/sdk"
import { tiramisu } from "@arkiv-network/sdk/chains"
import { http } from "viem"
const client = createPublicClient({
chain: tiramisu,
transport: http(),
})
const MY_ADDRESS = "0xYourAddress..."
const unwatch = client.watchEntityEvents({
onEntityCreated: (event) => {
if (event.owner === MY_ADDRESS) {
console.log(`New entity ${event.entityKey} expires at block ${event.expiresAt}`)
}
},
onEntityDeleted: (event) => {
if (event.owner === MY_ADDRESS) {
console.log(`Entity ${event.entityKey} was deleted`)
}
},
onError: (error) => {
console.error("Event stream error:", error)
},
})
// Clean up on exit
process.on("SIGINT", () => {
unwatch()
process.exit()
})