Skip to main content
Handle blockchain forks by tracking unfinalized blocks and rolling back when forks occur.
let recentUnfinalizedBlocks: BlockCursor[] = []

const target = createTarget({
  write: async ({read}) => {
    for await (const {data, ctx} of read(recentUnfinalizedBlocks[recentUnfinalizedBlocks.length-1])) {
      // Track unfinalized blocks from the batch
      ctx.state.rollbackChain.forEach((bc) => {
        recentUnfinalizedBlocks.push(bc)
      })
      
      // Prune finalized blocks
      if (ctx.head.finalized) {
        recentUnfinalizedBlocks = recentUnfinalizedBlocks.filter(
          b => b.number >= ctx.head.finalized!.number
        )
      }
    }
  },
  fork: async (previousBlocks) => {
    const rollbackIndex = findCommonAncestor(recentUnfinalizedBlocks, previousBlocks)
    if (rollbackIndex >= 0) {
      recentUnfinalizedBlocks.length = rollbackIndex + 1
      return recentUnfinalizedBlocks[rollbackIndex]
    }
    return null
  }
})
When the source detects a fork, it calls the fork() handler with blocks from the new consensus chain. The handler finds the common ancestor between your stored blocks and the new chain, then returns the cursor to resume from. Track unfinalized blocks in ctx.state.rollbackChain and prune them as blocks become finalized.

View full example on GitHub

Complete working code with fork handling