Loading…
Core library defining the Overlay Services Engine for UTXO-based systems on BSV.
npm install @bsv/overlay @bsv/overlay-topicsimport { Engine } from '@bsv/overlay'
import { KnexStorage } from '@bsv/overlay'
import { HelloWorldTopicManager, createHelloWorldLookupService } from '@bsv/overlay-topics'
import { WhatsOnChain } from '@bsv/sdk'
import type { Knex } from 'knex'
import type { Db } from 'mongodb'
declare const knex: Knex
declare const mongoDb: Db
declare const req: { headers: { 'x-topics'?: string }; body: number[] }
declare const res: { status: (code: number) => { json: (body: unknown) => void } }
const lookupService = await createHelloWorldLookupService(mongoDb)
// Create and configure an Engine
const engine = new Engine(
{ tm_helloworld: new HelloWorldTopicManager() },
{ ls_helloworld: lookupService },
new KnexStorage(knex),
new WhatsOnChain('main'),
'https://example.com'
)
// Submit transactions with topics
const topicsHeader = req.headers['x-topics'] ?? ''
const topics = topicsHeader.trim().startsWith('[')
? JSON.parse(topicsHeader)
: topicsHeader.split(',').map(topic => topic.trim())
const taggedBEEF = { beef: Array.from(req.body), topics }
await engine.submit(taggedBEEF, steak => res.status(200).json(steak))
// Perform lookups
const result = await engine.lookup({
service: 'ls_helloworld',
query: { message: 'hello world' }
})import type { TopicManager } from '@bsv/overlay'
import { Transaction } from '@bsv/sdk'
class CustomTopicManager implements TopicManager {
async identifyAdmissibleOutputs(beef, previousCoins) {
const tx = Transaction.fromBEEF(beef)
return { outputsToAdmit: [0], coinsToRetain: [] }
}
async getDocumentation() {
return 'Custom topic documentation'
}
async getMetaData() {
return {
name: 'custom',
shortDescription: 'A custom topic'
}
}
}import type { LookupService } from '@bsv/overlay'
class CustomLookupService implements LookupService {
readonly admissionMode = 'locking-script' as const
readonly spendNotificationMode = 'none' as const
async outputAdmittedByTopic(payload) {
if (payload.mode === 'locking-script') {
// Index the output
}
}
async lookup(question) {
// Return a LookupFormula: outpoints that the Engine should hydrate.
return []
}
async outputEvicted(txid, outputIndex) {
// Remove the UTXO from any service-specific index.
}
async getDocumentation() {
return 'Custom lookup service documentation'
}
async getMetaData() {
return {
name: 'custom lookup',
shortDescription: 'A custom lookup service'
}
}
}const storage = new KnexStorage(knex)
// Run the standard KnexStorageMigrations before first use.BASM-capable deployments need a chain tracker that can validate Merkle roots and resolve canonical block headers. The Engine exposes maintenance operations used by Overlay Express and monitor processes:
await engine.startBASMSync()
await engine.refreshUnprovenTransactionProofs({
thresholdBlocks: 144,
proofProvider: async txid => await lookupProof(txid)
})
await engine.maintainUnprovenTransactions({
thresholdBlocks: 144,
proofProvider: async txid => await lookupProof(txid)
})maintainUnprovenTransactions first tries to prove old unproven rows, then
evicts rows that remain unproven past the configured threshold. Provider-level
terminal invalidation can also call evictAppliedTransaction so double-spent or
invalid transactions stop appearing in lookup results immediately.
'locking-script') or whole transaction ('whole-tx')'none', 'txid', 'script', or 'whole-tx')tm_*, lookup services ls_* by default in discovery