This source candidate declares SDK peer ^2.1.6 || ^3.0.0. SDK3 remains
a coordinated proposal; see the qualification and migration limits
before adopting it.
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' }
})The package exports an additive AdmissionStorage capability, semantic identity
helpers and recovery fence/cursor predicates. storageHasAdmission reports
whether the optional Storage.admission field is present; getAdmissionStorage
additionally requires the v1 protocol and both commit and reconciliation
methods. These define the local durable receipt and pending index/propagation
boundary for future adapters. Current Engine.submit, its early STEAK callback
and Knex storage do not use the capability. See the persistence v1
specification
for the shared fixtures and explicit limits. No consumer migration is required.
The package also contains an opt-in MongoDB foundation for schema bootstrap,
content-addressed payload publication, reference guards, and payload collection.
It is not an Engine integration, an AdmissionStorage implementation, or a
default storage selection; importing @bsv/overlay does not load MongoDB.
Applications using a Mongo deep entry point install the optional peer first:
npm install @bsv/overlay mongodb@^7.5.0The initial entry points are @bsv/overlay/storage/mongo/MongoSchema and
@bsv/overlay/storage/mongo/MongoPayloadStore. They require an explicitly
operated unsharded replica set; the supported deployment profile is three
members. See the Mongo v1
foundation.
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')SHIP tracker responses are untrusted discovery hints. The Engine authenticates the canonical identity-linked advertisement signature and binds its one-satoshi output, BEEF/TXID, and requested topic before using the endpoint for GASP; the connection still requires the normal public-HTTPS and DNS-pinning controls.
tm_*, lookup services ls_* by default in discovery