@bsv/overlay-express
Version:
BSV Blockchain Overlay Express
78 lines • 3.17 kB
JavaScript
import { PushDrop, Utils } from '@bsv/sdk';
/**
* Wraps a SHIP or SLAP LookupService to intercept outputAdmittedByTopic calls
* and block outputs whose domain or outpoint appears in the persistent ban list.
*
* This prevents GASP from re-syncing stale or banned tokens that were previously
* removed by the Janitor or an admin.
*/
export class BanAwareLookupWrapper {
wrapped;
banService;
protocol;
logger;
admissionMode;
spendNotificationMode;
constructor(wrapped, banService, protocol, logger = console) {
this.wrapped = wrapped;
this.banService = banService;
this.protocol = protocol;
this.logger = logger;
this.admissionMode = wrapped.admissionMode;
this.spendNotificationMode = wrapped.spendNotificationMode;
}
/**
* Intercepts admission to check the ban list before delegating to the wrapped service.
* If the output's domain or outpoint is banned, the admission is silently blocked.
*/
async outputAdmittedByTopic(payload) {
if (payload.mode === 'locking-script') {
const { txid, outputIndex, lockingScript } = payload;
// Check if the specific outpoint is banned
if (await this.banService.isOutpointBanned(txid, outputIndex)) {
this.logger.log(`[BAN] Blocked banned outpoint ${txid}.${outputIndex} from ${this.protocol}`);
return;
}
// Try to parse the domain from PushDrop fields and check domain ban
try {
const result = PushDrop.decode(lockingScript);
if (result.fields.length >= 3) {
const domain = Utils.toUTF8(result.fields[2]);
if (await this.banService.isDomainBanned(domain)) {
this.logger.log(`[BAN] Blocked banned domain ${domain} from ${this.protocol} (${txid}.${outputIndex})`);
return;
}
}
}
catch {
// If we can't parse PushDrop fields, let it through to the wrapped service
// which will apply its own validation
}
}
// Delegate to the wrapped service
return await this.wrapped.outputAdmittedByTopic(payload);
}
async outputSpent(payload) {
if (typeof this.wrapped.outputSpent === 'function') {
return await this.wrapped.outputSpent(payload);
}
}
async outputNoLongerRetainedInHistory(txid, outputIndex, topic) {
if (typeof this.wrapped.outputNoLongerRetainedInHistory === 'function') {
return await this.wrapped.outputNoLongerRetainedInHistory(txid, outputIndex, topic);
}
}
async outputEvicted(txid, outputIndex) {
return await this.wrapped.outputEvicted(txid, outputIndex);
}
async lookup(question) {
return await this.wrapped.lookup(question);
}
async getDocumentation() {
return await this.wrapped.getDocumentation();
}
async getMetaData() {
return await this.wrapped.getMetaData();
}
}
//# sourceMappingURL=BanAwareLookupWrapper.js.map