Skip to content

Commit 9f88759

Browse files
authored
Merge pull request #3 from bsv-blockchain/fix/slackthread
[ FIX ] slackthread
2 parents 680fc43 + 5449d2f commit 9f88759

File tree

6 files changed

+77
-15
lines changed

6 files changed

+77
-15
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "overlay-express-examples",
3-
"version": "0.4.0",
3+
"version": "0.4.1",
44
"description": "Run the overlay infrastructure for distributed applications.",
55
"homepage": "https://github.com/bsv-blockchain/overlay-express-examples#readme",
66
"bugs": {
Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,34 @@
11
export default `
22
# SlackThread Lookup Service Documentation
33
4-
The **SlackThread Lookup Service** (service ID: \`ls_slackthreads\`) lets clients search the on-chain *SlackThread* messages that are indexed by the **SlackThread Topic Manager**. Each record represents a Pay-to-Push-Drop output whose single field is a UTF-8 message of at least two characters.
4+
The **SlackThread Lookup Service** (service ID: \`ls_slackthread\`) lets clients search the on-chain *SlackThread* messages that are indexed by the **SlackThread Topic Manager**. Each record represents a Pay-to-Push-Drop output whose single field is a UTF-8 message of at least two characters.
55
66
## Example
77
\`\`\`typescript
88
import { LookupResolver } from '@bsv/sdk'
99
1010
const overlay = new LookupResolver()
1111
12+
// find all
13+
const response2 = await overlay.query({
14+
service: 'ls_slackthread',
15+
query: {}
16+
}, 10000)
17+
18+
// find by thread hash
1219
const response = await overlay.query({
13-
service: 'ls_slackthreads',
20+
service: 'ls_slackthread',
1421
query: {
1522
threadHash: 'some 32 byte hash of a thread'
1623
}
1724
}, 10000)
25+
26+
// find by txid
27+
const response3 = await overlay.query({
28+
service: 'ls_slackthread',
29+
query: {
30+
txid: 'some txid'
31+
}
32+
}, 10000)
1833
\`\`\`
1934
`

src/services/slackthreads/SlackThreadsLookupServiceFactory.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import {
99
OutputSpent
1010
} from '@bsv/overlay'
1111
import { SlackThreadsStorage } from './SlackThreadsStorage.js'
12-
import { PushDrop, Utils } from '@bsv/sdk'
12+
import { Utils } from '@bsv/sdk'
1313
import { Db } from 'mongodb'
1414

1515
export interface SlackThreadQuery {
1616
threadHash?: string
17+
txid?: string
1718
limit?: number
1819
skip?: number
1920
startDate?: Date
@@ -39,18 +40,15 @@ export class SlackThreadLookupService implements LookupService {
3940
async outputAdmittedByTopic(payload: OutputAdmittedByTopic): Promise<void> {
4041
if (payload.mode !== 'locking-script') throw new Error('Invalid mode')
4142
const { topic, lockingScript, txid, outputIndex } = payload
42-
if (payload.topic !== 'tm_slackthread') return
43+
if (topic !== 'tm_slackthread') return
4344

4445
try {
45-
// Decode the PushDrop token
46-
const result = PushDrop.decode(lockingScript)
47-
if (!result.fields || result.fields.length < 1) throw new Error('Invalid SlackThread token: wrong field count')
48-
49-
const threadHash = Utils.toUTF8(result.fields[0])
50-
if (threadHash.length < 2) throw new Error('Invalid SlackThread token: thread hash too short')
46+
const threadHash = lockingScript.chunks[1].data
47+
if (threadHash.length !== 32) throw new Error('Invalid SlackThread token: thread hash must be exactly 32 bytes')
48+
const threadHashString = Utils.toHex(threadHash)
5149

5250
// Persist for future lookup
53-
await this.storage.storeRecord(txid, outputIndex, threadHash)
51+
await this.storage.storeRecord(txid, outputIndex, threadHashString)
5452
} catch (err) {
5553
console.error(`SlackThreadLookupService: failed to index ${txid}.${outputIndex}`, err)
5654
}
@@ -88,6 +86,7 @@ export class SlackThreadLookupService implements LookupService {
8886

8987
const {
9088
threadHash,
89+
txid,
9190
limit = 50,
9291
skip = 0,
9392
startDate,
@@ -108,6 +107,10 @@ export class SlackThreadLookupService implements LookupService {
108107
return this.storage.findByThreadHash(threadHash, limit, skip, sortOrder)
109108
}
110109

110+
if (txid) {
111+
return this.storage.findByTxid(txid, limit, skip, sortOrder)
112+
}
113+
111114
return this.storage.findAll(limit, skip, from, to, sortOrder)
112115
}
113116

src/services/slackthreads/SlackThreadsStorage.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ export class SlackThreadsStorage {
1111
*/
1212
constructor(private readonly db: Db) {
1313
this.records = db.collection<SlackThreadRecord>('slackThreadRecords')
14+
this.createSearchableIndex() // Initialize the searchable index
15+
}
16+
17+
/* Ensures a text index exists for the `threadHash` field, enabling efficient searches.
18+
* The index is named `threadHashIndex`.
19+
*/
20+
private async createSearchableIndex(): Promise<void> {
21+
await this.records.createIndex({ threadHash: 1 }, { name: 'threadHashIndex' })
1422
}
1523

1624
/**
@@ -75,6 +83,42 @@ export class SlackThreadsStorage {
7583
)
7684
}
7785

86+
/**
87+
* Finds SlackThread records containing the specified transaction ID (case-insensitive).
88+
*
89+
* @param txid Partial or full transaction ID to search for
90+
* @param limit Max number of results to return (default = 50)
91+
* @param skip Number of results to skip for pagination (default = 0)
92+
* @param sortOrder 'asc' | 'desc' – sort by createdAt (default = 'desc')
93+
*/
94+
async findByTxid(
95+
txid: string,
96+
limit: number = 50,
97+
skip: number = 0,
98+
sortOrder: 'asc' | 'desc' = 'desc'
99+
): Promise<UTXOReference[]> {
100+
if (!txid) return []
101+
102+
// Map text value → numeric MongoDB sort direction
103+
const direction = sortOrder === 'asc' ? 1 : -1
104+
105+
return this.records
106+
.find(
107+
{ txid },
108+
{ projection: { txid: 1, outputIndex: 1, createdAt: 1 } }
109+
)
110+
.sort({ createdAt: direction })
111+
.skip(skip)
112+
.limit(limit)
113+
.toArray()
114+
.then(results =>
115+
results.map(r => ({
116+
txid: r.txid,
117+
outputIndex: r.outputIndex
118+
}))
119+
)
120+
}
121+
78122
/**
79123
* Retrieves all SlackThread records, optionally filtered by date range and sorted by creation time.
80124
* @param {number} [limit=50] - The maximum number of results to return

src/services/slackthreads/SlackThreadsTopicDocs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
export default `
22
# SlackThread Topic Manager Documentation
33
4-
The **SlackThread Topic Manager** (topic ID: \`tm_slackthreads\`) lets clients Push hashes to chain and remove them by revealing the preimage.
4+
The **SlackThread Topic Manager** (topic ID: \`tm_slackthread\`) lets clients Push hashes to chain and remove them by revealing the preimage.
55
66
Either there is a locking script of the form:
77

0 commit comments

Comments
 (0)