Loading…
This source candidate declares SDK peer ^2.4.0 || ^3.0.0. SDK3 remains
a coordinated proposal; see the qualification and migration limits
before adopting it.
Implements SHIP and SLAP protocols for peer discovery and service advertisement in overlay networks.
npm install @bsv/overlay-discovery-servicesimport { Engine, type LookupService, type Storage, type TopicManager } from '@bsv/overlay'
import {
SHIPLookupService,
SHIPStorage,
SHIPTopicManager,
SLAPLookupService,
SLAPStorage,
SLAPTopicManager,
isAdvertisableURI,
isValidTopicOrServiceName
} from '@bsv/overlay-discovery-services'
import { WhatsOnChain } from '@bsv/sdk'
import type { Db } from 'mongodb'
declare const managers: Record<string, TopicManager>
declare const lookupServices: Record<string, LookupService>
declare const storage: Storage
declare const db: Db
const shipStorage = new SHIPStorage(db)
const slapStorage = new SLAPStorage(db)
await shipStorage.ensureIndexes()
await slapStorage.ensureIndexes()
const engine = new Engine(
{
...managers,
tm_ship: new SHIPTopicManager(),
tm_slap: new SLAPTopicManager()
},
{
...lookupServices,
ls_ship: new SHIPLookupService(shipStorage),
ls_slap: new SLAPLookupService(slapStorage)
},
storage,
new WhatsOnChain('main'),
'https://mynode.example.com',
['https://ship.example.com'], // SHIP trackers
['https://slap.example.com'] // SLAP trackers
)
// Query SHIP for topic hosts
const shipResults = await engine.lookup({
service: 'ls_ship',
query: {
topics: ['tm_hello'],
limit: 25
}
})
// Query SLAP for lookup services
const slapResults = await engine.lookup({
service: 'ls_slap',
query: {
service: 'ls_hello',
limit: 25
}
})isAdvertisableURI(), isValidTopicOrServiceName(), isTokenSignatureCorrectlyLinked()import { isAdvertisableURI, isValidTopicOrServiceName } from '@bsv/overlay-discovery-services'
const valid = isAdvertisableURI('https://node.example.com')
const validName = isValidTopicOrServiceName('tm_custom_topic')import { WalletAdvertiser } from '@bsv/overlay-discovery-services'
const advertiser = new WalletAdvertiser(
'main',
process.env.SERVER_PRIVATE_KEY!, // dedicated root secret; never expose the instance
'https://store-us-1.bsvb.tech',
'https://mynode.example.com'
)
await advertiser.init()
const taggedBEEF = await advertiser.createAdvertisements([
{ protocol: 'SHIP', topicOrServiceName: 'tm_hello' },
{ protocol: 'SLAP', topicOrServiceName: 'ls_hello' }
])
await engine.submit(taggedBEEF)// After Engine is initialized with tracker URLs
const hostDiscovery = await engine.lookup({
service: 'ls_ship',
query: {
topics: ['tm_btms']
}
})
// Returns a LookupFormula for matching SHIP advertisement outputs.
const serviceDiscovery = await engine.lookup({
service: 'ls_slap',
query: {
service: 'ls_kvstore'
}
})
// Returns a LookupFormula for matching SLAP advertisement outputs.tm_* (e.g., tm_hello, tm_ship, tm_btms)ls_* (e.g., ls_hello, ls_slap, ls_btms)WalletAdvertiser.findAllAdvertisements() returns only canonical,
cryptographically authenticated advertisements owned by its wallet identity.
Use ls_ship or ls_slap lookups to discover advertisements from other
identities.WalletAdvertiser.privateKey remains public only for compatibility and is a
root wallet secret. Never serialize, log, return, or share an advertiser
instance with plugins or untrusted code; use a dedicated key.parseAdvertisement() is a synchronous structural parser, not a signature
verdict. Topic admission and the advertiser's create/find/revoke flows perform
the cryptographic check.limit is an integer
from 0 through 1,000, defaults to 1,000, and zero returns no rows. skip is
bounded to 1,000,000. Paginate explicitly.tm_ship/tm_slap and their lookup services. OverlayExpress has separate host setup; neither implies automatic BRC189 identity-overlay installation.tm_* or ls_* pattern; invalid names rejected by validators