@bsv/overlay 0.1.28 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/cjs/package.json +2 -2
  2. package/dist/cjs/src/Engine.js +91 -12
  3. package/dist/cjs/src/Engine.js.map +1 -1
  4. package/dist/cjs/src/GASP/OverlayGASPRemote.js.map +1 -1
  5. package/dist/cjs/src/GASP/OverlayGASPStorage.js +1 -1
  6. package/dist/cjs/src/GASP/OverlayGASPStorage.js.map +1 -1
  7. package/dist/cjs/src/storage/knex/KnexStorage.js.map +1 -1
  8. package/dist/cjs/src/storage/knex/migrations/2024-05-18-001-initial.js.map +1 -1
  9. package/dist/cjs/src/storage/knex/migrations/2024-07-10-001-block-height.js.map +1 -1
  10. package/dist/cjs/src/storage/knex/migrations/2024-07-17-001-transactions.js.map +1 -1
  11. package/dist/cjs/src/storage/knex/migrations/2024-07-18-001-indexes.js.map +1 -1
  12. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  13. package/dist/esm/src/Engine.js +89 -11
  14. package/dist/esm/src/Engine.js.map +1 -1
  15. package/dist/esm/src/GASP/OverlayGASPRemote.js.map +1 -1
  16. package/dist/esm/src/GASP/OverlayGASPStorage.js +1 -1
  17. package/dist/esm/src/GASP/OverlayGASPStorage.js.map +1 -1
  18. package/dist/esm/src/storage/knex/KnexStorage.js.map +1 -1
  19. package/dist/esm/src/storage/knex/migrations/2024-05-18-001-initial.js.map +1 -1
  20. package/dist/esm/src/storage/knex/migrations/2024-07-10-001-block-height.js.map +1 -1
  21. package/dist/esm/src/storage/knex/migrations/2024-07-17-001-transactions.js.map +1 -1
  22. package/dist/esm/src/storage/knex/migrations/2024-07-18-001-indexes.js.map +1 -1
  23. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  24. package/dist/types/src/Engine.d.ts.map +1 -1
  25. package/dist/types/src/GASP/OverlayGASPRemote.d.ts +1 -1
  26. package/dist/types/src/GASP/OverlayGASPRemote.d.ts.map +1 -1
  27. package/dist/types/src/GASP/OverlayGASPStorage.d.ts.map +1 -1
  28. package/dist/types/src/LookupService.d.ts +67 -48
  29. package/dist/types/src/LookupService.d.ts.map +1 -1
  30. package/dist/types/src/Output.d.ts +2 -2
  31. package/dist/types/src/Output.d.ts.map +1 -1
  32. package/dist/types/src/storage/Storage.d.ts.map +1 -1
  33. package/dist/types/src/storage/knex/KnexStorage.d.ts.map +1 -1
  34. package/dist/types/src/storage/knex/all-migrations.d.ts +2 -2
  35. package/dist/types/src/storage/knex/all-migrations.d.ts.map +1 -1
  36. package/dist/types/src/storage/knex/migrations/2024-05-18-001-initial.d.ts.map +1 -1
  37. package/dist/types/src/storage/knex/migrations/2024-07-10-001-block-height.d.ts.map +1 -1
  38. package/dist/types/src/storage/knex/migrations/2024-07-17-001-transactions.d.ts.map +1 -1
  39. package/dist/types/src/storage/knex/migrations/2024-07-18-001-indexes.d.ts.map +1 -1
  40. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  41. package/package.json +2 -2
  42. package/src/Engine.ts +133 -60
  43. package/src/GASP/OverlayGASPRemote.ts +6 -6
  44. package/src/GASP/OverlayGASPStorage.ts +17 -17
  45. package/src/LookupService.ts +112 -49
  46. package/src/Output.ts +1 -1
  47. package/src/__tests/Engine.test.ts +38 -29
  48. package/src/storage/Storage.ts +0 -1
  49. package/src/storage/knex/KnexStorage.ts +12 -12
  50. package/src/storage/knex/all-migrations.ts +1 -1
  51. package/src/storage/knex/migrations/2024-05-18-001-initial.ts +2 -2
  52. package/src/storage/knex/migrations/2024-07-10-001-block-height.ts +2 -2
  53. package/src/storage/knex/migrations/2024-07-17-001-transactions.ts +2 -2
  54. package/src/storage/knex/migrations/2024-07-18-001-indexes.ts +2 -2
@@ -1,68 +1,131 @@
1
1
  import { LookupFormula } from './LookupFormula.js'
2
- import { LookupQuestion, LookupAnswer, Script } from '@bsv/sdk'
2
+ import { Script, LookupQuestion, LookupAnswer } from '@bsv/sdk'
3
3
 
4
- /**
5
- * Defines a Lookup Service interface to be implemented for specific use-cases
6
- */
4
+ /* ---------------------------------------------------------------------------
5
+ * Modes a Lookup Service may request from the Overlay Services Engine
6
+ * -------------------------------------------------------------------------- */
7
+ export type AdmissionMode = 'locking-script' | 'whole-tx'
8
+ export type SpendNotificationMode = 'none' | 'txid' | 'script' | 'whole-tx'
9
+
10
+ /* ---------------------------------------------------------------------------
11
+ * Admission-Notification payloads
12
+ * -------------------------------------------------------------------------- */
13
+ export type OutputAdmittedByTopic =
14
+ | { // «locking-script» mode
15
+ mode: 'locking-script'
16
+ txid: string // ID of the *admitted* transaction
17
+ outputIndex: number // index of admitted output
18
+ topic: string // topic into which it was admitted
19
+ satoshis: number // value of the output
20
+ lockingScript: Script // script in this output
21
+ }
22
+ | { // «whole-tx» mode
23
+ mode: 'whole-tx'
24
+ atomicBEEF: number[] // whole transaction (Atomic BEEF)
25
+ outputIndex: number
26
+ topic: string
27
+ }
28
+
29
+ /* ---------------------------------------------------------------------------
30
+ * Spend-Notification payloads
31
+ * -------------------------------------------------------------------------- */
32
+ export type OutputSpent =
33
+ | { // «none» – “it was spent”
34
+ mode: 'none'
35
+ txid: string
36
+ outputIndex: number
37
+ topic: string
38
+ }
39
+ | { // «txid» – pointer only
40
+ mode: 'txid'
41
+ txid: string
42
+ outputIndex: number
43
+ topic: string
44
+ spendingTxid: string
45
+ }
46
+ | { // «script» – granular input data
47
+ mode: 'script'
48
+ txid: string
49
+ outputIndex: number
50
+ topic: string
51
+ spendingTxid: string
52
+ inputIndex: number
53
+ unlockingScript: Script
54
+ sequenceNumber: number
55
+ }
56
+ | { // «whole-tx» – full spending TX
57
+ mode: 'whole-tx'
58
+ txid: string
59
+ outputIndex: number
60
+ topic: string
61
+ spendingAtomicBEEF: number[]
62
+ }
63
+
64
+ /* ---------------------------------------------------------------------------
65
+ * Metadata structure returned by getMetaData()
66
+ * -------------------------------------------------------------------------- */
67
+ export interface LookupServiceMetaData {
68
+ name: string
69
+ shortDescription: string
70
+ iconURL?: string
71
+ version?: string
72
+ informationURL?: string
73
+ }
74
+
75
+ /* ---------------------------------------------------------------------------
76
+ * Lookup Service Interface
77
+ * -------------------------------------------------------------------------- */
7
78
  export interface LookupService {
79
+ /* -------------------------------------------------------------------------
80
+ * REQUIRED static declarations
81
+ * ----------------------------------------------------------------------- */
82
+ readonly admissionMode: AdmissionMode
83
+ readonly spendNotificationMode: SpendNotificationMode
8
84
 
85
+ /* -------------------------------------------------------------------------
86
+ * REQUIRED lifecycle hooks
87
+ * ----------------------------------------------------------------------- */
9
88
  /**
10
- * Process the event when a new UTXO is let into a topic
11
- * @param txid - The transaction ID (TXID) of the transaction where the new UTXO resides.
12
- * @param outputIndex - The index of the transaction output (UTXO) within the transaction.
13
- * @param outputScript - The script associated with the transaction output.
14
- * @param topic - The topic to which the new UTXO is being added.
15
- * @returns A promise that resolves when the processing of the new UTXO is complete.
89
+ * Invoked when a Topic Manager admits a new UTXO.
90
+ * The payload shape depends on this.admissionMode.
16
91
  */
17
- outputAdded?: (txid: string, outputIndex: number, outputScript: Script, topic: string) => Promise<void>
92
+ outputAdmittedByTopic: (payload: OutputAdmittedByTopic) => Promise<void> | void
18
93
 
19
94
  /**
20
- * Processes the spend event for a UTXO.
21
- *
22
- * @param txid - The transaction ID of the spent UTXO.
23
- * @param outputIndex - The index of the transaction output that was spent.
24
- * @param topic - The topic from which the UTXO was spent.
25
- *
26
- * @returns A promise that resolves when processing is complete.
95
+ * Invoked when a previously-admitted UTXO is spent.
96
+ * The payload shape depends on this.spendNotificationMode.
27
97
  */
28
- outputSpent?: (txid: string, outputIndex: number, topic: string) => Promise<void>
98
+ outputSpent?: (payload: OutputSpent) => Promise<void> | void
29
99
 
30
100
  /**
31
- * Processes the deletion event for a UTXO.
32
- *
33
- * @param txid - The transaction ID of the deleted UTXO.
34
- * @param outputIndex - The index of the transaction output that was deleted.
35
- * @param topic - The topic from which the UTXO was deleted.
36
- *
37
- * @returns A promise that resolves when processing is complete.
101
+ * Called when a Topic Manager decides that **historical retention** of the
102
+ * specified UTXO is no longer required.
38
103
  */
39
- outputDeleted?: (txid: string, outputIndex: number, topic: string) => Promise<void>
104
+ outputNoLongerRetainedInHistory?: (
105
+ txid: string,
106
+ outputIndex: number,
107
+ topic: string
108
+ ) => Promise<void> | void
40
109
 
41
110
  /**
42
- * Queries the lookup service for information
43
- * @param question — The question to be answered by the lookup service
44
- * @returns — The Lookup Answer or Lookup Formula used to answer the question
111
+ * LEGAL EVICTION:
112
+ * Permanently remove the referenced UTXO from all indices maintained by the
113
+ * Lookup Service. After eviction the service MUST NOT reference the output
114
+ * in any future lookup answer.
45
115
  */
116
+ outputEvicted: (
117
+ txid: string,
118
+ outputIndex: number
119
+ ) => Promise<void> | void
120
+
121
+ /* -------------------------------------------------------------------------
122
+ * Query API
123
+ * ----------------------------------------------------------------------- */
46
124
  lookup: (question: LookupQuestion) => Promise<LookupAnswer | LookupFormula>
47
125
 
48
- /**
49
- * Returns a Markdown-formatted documentation string for the lookup service.
50
- *
51
- * @returns A promise that resolves to a documentation string.
52
- */
126
+ /* -------------------------------------------------------------------------
127
+ * Documentation helpers
128
+ * ----------------------------------------------------------------------- */
53
129
  getDocumentation: () => Promise<string>
54
-
55
- /**
56
- * Returns a metadata object that can be used to identify the lookup service.
57
- *
58
- * @returns A promise that resolves to a metadata object containing the name, short description,
59
- * and optional properties such as icon URL, version, and information URL.
60
- */
61
- getMetaData: () => Promise<{
62
- name: string
63
- shortDescription: string
64
- iconURL?: string
65
- version?: string
66
- informationURL?: string
67
- }>
130
+ getMetaData: () => Promise<LookupServiceMetaData>
68
131
  }
package/src/Output.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Represents an output to be tracked by the Overlay Services Engine
3
3
  */
4
- export type Output = {
4
+ export interface Output {
5
5
  /** TXID of the output */
6
6
  txid: string
7
7
  /** index of the output */
@@ -25,7 +25,7 @@ const mockOutput: Output = {
25
25
  outputIndex: 0,
26
26
  outputScript: exampleTX.outputs[0].lockingScript.toBinary(),
27
27
  topic: 'hello',
28
- satoshis: exampleTX.outputs[0].satoshis as number,
28
+ satoshis: exampleTX.outputs[0].satoshis,
29
29
  beef: exampleBeef,
30
30
  spent: false,
31
31
  outputsConsumed: [],
@@ -33,20 +33,19 @@ const mockOutput: Output = {
33
33
  }
34
34
 
35
35
  const invalidHostingUrls = [
36
- "http://example.com", // Invalid: http
37
- "https://localhost:3000", // Invalid: localhost
38
- "https://192.168.1.1", // Invalid: internal private IP
39
- "https://127.0.0.1", // Invalid: loopback IP
40
- "https://0.0.0.0", // Invalid: non-routable IP
41
- "http://172.16.0.1", // Invalid: private IP
42
- "[::1]"
36
+ 'http://example.com', // Invalid: http
37
+ 'https://localhost:3000', // Invalid: localhost
38
+ 'https://192.168.1.1', // Invalid: internal private IP
39
+ 'https://127.0.0.1', // Invalid: loopback IP
40
+ 'https://0.0.0.0', // Invalid: non-routable IP
41
+ 'http://172.16.0.1', // Invalid: private IP
42
+ '[::1]'
43
43
  ]
44
44
 
45
-
46
45
  const validHostingUrls = [
47
- "https://example.com", // Valid: public URL
48
- "https://8.8.8.8", // Valid: public routable IP
49
- "https://255.255.255.255", // Valid: public routable IP
46
+ 'https://example.com', // Valid: public URL
47
+ 'https://8.8.8.8', // Valid: public routable IP
48
+ 'https://255.255.255.255' // Valid: public routable IP
50
49
  ]
51
50
 
52
51
  const mockAdvertiser: Advertiser = {
@@ -70,10 +69,13 @@ describe('BSV Overlay Services Engine', () => {
70
69
  }
71
70
 
72
71
  mockLookupService = {
73
- outputAdded: jest.fn(),
72
+ outputAdmittedByTopic: jest.fn(),
74
73
  outputSpent: jest.fn(),
75
74
  lookup: jest.fn(),
76
- outputDeleted: jest.fn(),
75
+ outputNoLongerRetainedInHistory: jest.fn(),
76
+ outputEvicted: jest.fn(),
77
+ admissionMode: 'locking-script',
78
+ spendNotificationMode: 'none',
77
79
  getDocumentation: async () => 'Service Documentation',
78
80
  getMetaData: async () => ({ name: 'Mock Service', shortDescription: 'Mock Short Service Description' })
79
81
  }
@@ -107,7 +109,7 @@ describe('BSV Overlay Services Engine', () => {
107
109
  undefined
108
110
  )
109
111
 
110
- engine.submit = jest.fn(async (taggedBEEF: TaggedBEEF, onSteakReady: any, mode?: string) => ({ 'tm_helloworld': { outputsToAdmit: [], coinsToRetain: [], coinsRemoved: [] } } as STEAK))
112
+ engine.submit = jest.fn(async (taggedBEEF: TaggedBEEF, onSteakReady: any, mode?: string) => ({ tm_helloworld: { outputsToAdmit: [], coinsToRetain: [], coinsRemoved: [] } } as STEAK))
111
113
 
112
114
  // Call the method that would normally trigger syncAdvertisements
113
115
  const result = await engine.syncAdvertisements()
@@ -128,8 +130,8 @@ describe('BSV Overlay Services Engine', () => {
128
130
  parseAdvertisement: jest.fn().mockReturnValue({
129
131
  protocol: 'SHIP',
130
132
  topicOrServiceName: 'mock-topic',
131
- timestamp: Date.now(),
132
- }),
133
+ timestamp: Date.now()
134
+ })
133
135
  }
134
136
 
135
137
  for (const url of validHostingUrls) {
@@ -147,7 +149,7 @@ describe('BSV Overlay Services Engine', () => {
147
149
  )
148
150
 
149
151
  // Call the method that would normally trigger syncAdvertisements
150
- engine.submit = jest.fn(async (taggedBEEF: TaggedBEEF, onSteakReady: any, mode?: string) => ({ 'tm_helloworld': { outputsToAdmit: [], coinsToRetain: [], coinsRemoved: [] } } as STEAK))
152
+ engine.submit = jest.fn(async (taggedBEEF: TaggedBEEF, onSteakReady: any, mode?: string) => ({ tm_helloworld: { outputsToAdmit: [], coinsToRetain: [], coinsRemoved: [] } } as STEAK))
151
153
  const result = await engine.syncAdvertisements()
152
154
  expect(engine.submit).toHaveBeenCalled()
153
155
 
@@ -240,7 +242,7 @@ describe('BSV Overlay Services Engine', () => {
240
242
  outputIndex: 0,
241
243
  outputScript: exampleTX.outputs[0].lockingScript.toBinary(),
242
244
  topic: 'hello',
243
- satoshis: exampleTX.outputs[0].satoshis as number,
245
+ satoshis: exampleTX.outputs[0].satoshis,
244
246
  beef: exampleBeef,
245
247
  spent: false,
246
248
  outputsConsumed: [],
@@ -305,7 +307,7 @@ describe('BSV Overlay Services Engine', () => {
305
307
  outputIndex,
306
308
  outputScript: tx.outputs[outputIndex].lockingScript.toBinary(),
307
309
  topic: 'hello',
308
- satoshis: tx.outputs[outputIndex].satoshis as number,
310
+ satoshis: tx.outputs[outputIndex].satoshis,
309
311
  beef: tx.toBEEF(),
310
312
  spent: false,
311
313
  outputsConsumed: [],
@@ -554,7 +556,12 @@ describe('BSV Overlay Services Engine', () => {
554
556
  beef: exampleBeef,
555
557
  topics: ['Hello']
556
558
  })
557
- expect(engine.lookupServices.Hello.outputSpent).toHaveBeenCalledWith(exampleTXID, 0, 'Hello')
559
+ expect(engine.lookupServices.Hello.outputSpent).toHaveBeenCalledWith({
560
+ mode: 'none',
561
+ txid: exampleTXID,
562
+ outputIndex: 0,
563
+ topic: 'Hello'
564
+ })
558
565
  })
559
566
  })
560
567
  describe('When previous UTXOs were not retained by the topic manager', () => {
@@ -579,7 +586,7 @@ describe('BSV Overlay Services Engine', () => {
579
586
  })
580
587
  // Test that previous UTXOs are deleted
581
588
  expect(mockStorageEngine.deleteOutput).toHaveBeenCalledWith(exampleTXID, 0, 'hello')
582
- expect(mockLookupService.outputDeleted).toHaveBeenCalledWith(exampleTXID, 0, 'hello')
589
+ expect(mockLookupService.outputNoLongerRetainedInHistory).toHaveBeenCalledWith(exampleTXID, 0, 'hello')
583
590
  })
584
591
  it('Notifies all lookup services about the output being spent (the notification about the actual deletion will come from deleteUTXODeep)', async () => {
585
592
  // Mock findUTXO to return a UTXO
@@ -601,7 +608,7 @@ describe('BSV Overlay Services Engine', () => {
601
608
  topics: ['Hello']
602
609
  })
603
610
  // Was the lookup service notified of the output deletion?
604
- expect(mockLookupService.outputDeleted).toHaveBeenCalledWith(exampleTXID, 0, 'hello')
611
+ expect(mockLookupService.outputNoLongerRetainedInHistory).toHaveBeenCalledWith(exampleTXID, 0, 'hello')
605
612
  })
606
613
  })
607
614
  it('Adds admissible UTXOs to the storage engine', async () => {
@@ -646,12 +653,14 @@ describe('BSV Overlay Services Engine', () => {
646
653
  topics: ['Hello']
647
654
  })
648
655
  // Test the lookup service was notified of the new UTXO
649
- expect(mockLookupService.outputAdded).toHaveBeenCalledWith(
650
- exampleTXID,
651
- 0,
652
- exampleTX.outputs[0].lockingScript,
653
- 'Hello'
654
- )
656
+ expect(mockLookupService.outputAdmittedByTopic).toHaveBeenCalledWith({
657
+ mode: 'locking-script',
658
+ txid: exampleTXID,
659
+ satoshis: 26172,
660
+ outputIndex: 0,
661
+ lockingScript: exampleTX.outputs[0].lockingScript,
662
+ topic: 'Hello'
663
+ })
655
664
  })
656
665
  describe('For each consumed UTXO', () => {
657
666
  it('Finds the UTXO', async () => {
@@ -78,7 +78,6 @@ export interface Storage {
78
78
  */
79
79
  updateTransactionBEEF: (txid: string, beef: number[]) => Promise<void>
80
80
 
81
-
82
81
  /**
83
82
  * Updates the block height on an output
84
83
  * @param txid — TXID of the output to update
@@ -5,11 +5,11 @@ import type { Output } from '../../Output.js'
5
5
  export class KnexStorage implements Storage {
6
6
  knex: Knex
7
7
 
8
- constructor(knex: Knex) {
8
+ constructor (knex: Knex) {
9
9
  this.knex = knex
10
10
  }
11
11
 
12
- async findOutput(txid: string, outputIndex: number, topic?: string, spent?: boolean, includeBEEF: boolean = false): Promise<Output | null> {
12
+ async findOutput (txid: string, outputIndex: number, topic?: string, spent?: boolean, includeBEEF: boolean = false): Promise<Output | null> {
13
13
  const search: {
14
14
  'outputs.txid': string
15
15
  'outputs.outputIndex': number
@@ -59,7 +59,7 @@ export class KnexStorage implements Storage {
59
59
  }
60
60
  }
61
61
 
62
- async findOutputsForTransaction(txid: string, includeBEEF: boolean = false): Promise<Output[]> {
62
+ async findOutputsForTransaction (txid: string, includeBEEF: boolean = false): Promise<Output[]> {
63
63
  // Base query to get outputs
64
64
  const query = this.knex('outputs').where({ 'outputs.txid': txid })
65
65
 
@@ -97,7 +97,7 @@ export class KnexStorage implements Storage {
97
97
  }))
98
98
  }
99
99
 
100
- async findUTXOsForTopic(topic: string, since?: number, includeBEEF: boolean = false): Promise<Output[]> {
100
+ async findUTXOsForTopic (topic: string, since?: number, includeBEEF: boolean = false): Promise<Output[]> {
101
101
  // Base query to get outputs
102
102
  const query = this.knex('outputs').where({ 'outputs.topic': topic, 'outputs.spent': false })
103
103
 
@@ -141,7 +141,7 @@ export class KnexStorage implements Storage {
141
141
  }))
142
142
  }
143
143
 
144
- async deleteOutput(txid: string, outputIndex: number, topic: string): Promise<void> {
144
+ async deleteOutput (txid: string, outputIndex: number, topic: string): Promise<void> {
145
145
  await this.knex.transaction(async trx => {
146
146
  // Delete the specific output
147
147
  await trx('outputs').where({ txid, outputIndex }).del()
@@ -156,7 +156,7 @@ export class KnexStorage implements Storage {
156
156
  })
157
157
  }
158
158
 
159
- async insertOutput(output: Output): Promise<void> {
159
+ async insertOutput (output: Output): Promise<void> {
160
160
  const insertPromises = [this.knex('outputs').insert({
161
161
  txid: output.txid,
162
162
  outputIndex: Number(output.outputIndex),
@@ -181,7 +181,7 @@ export class KnexStorage implements Storage {
181
181
  })
182
182
  }
183
183
 
184
- async markUTXOAsSpent(txid: string, outputIndex: number, topic?: string): Promise<void> {
184
+ async markUTXOAsSpent (txid: string, outputIndex: number, topic?: string): Promise<void> {
185
185
  await this.knex('outputs').where({
186
186
  txid,
187
187
  outputIndex,
@@ -189,7 +189,7 @@ export class KnexStorage implements Storage {
189
189
  }).update('spent', true)
190
190
  }
191
191
 
192
- async updateConsumedBy(txid: string, outputIndex: number, topic: string, consumedBy: Array<{ txid: string, outputIndex: number }>): Promise<void> {
192
+ async updateConsumedBy (txid: string, outputIndex: number, topic: string, consumedBy: Array<{ txid: string, outputIndex: number }>): Promise<void> {
193
193
  await this.knex('outputs').where({
194
194
  txid,
195
195
  outputIndex,
@@ -197,13 +197,13 @@ export class KnexStorage implements Storage {
197
197
  }).update('consumedBy', JSON.stringify(consumedBy))
198
198
  }
199
199
 
200
- async updateTransactionBEEF(txid: string, beef: number[]): Promise<void> {
200
+ async updateTransactionBEEF (txid: string, beef: number[]): Promise<void> {
201
201
  await this.knex('transactions').where({
202
202
  txid
203
203
  }).update('beef', Buffer.from(beef))
204
204
  }
205
205
 
206
- async updateOutputBlockHeight(txid: string, outputIndex: number, topic: string, blockHeight: number): Promise<void> {
206
+ async updateOutputBlockHeight (txid: string, outputIndex: number, topic: string, blockHeight: number): Promise<void> {
207
207
  await this.knex('outputs').where({
208
208
  txid,
209
209
  outputIndex,
@@ -211,14 +211,14 @@ export class KnexStorage implements Storage {
211
211
  }).update('blockHeight', blockHeight)
212
212
  }
213
213
 
214
- async insertAppliedTransaction(tx: { txid: string, topic: string }): Promise<void> {
214
+ async insertAppliedTransaction (tx: { txid: string, topic: string }): Promise<void> {
215
215
  await this.knex('applied_transactions').insert({
216
216
  txid: tx.txid,
217
217
  topic: tx.topic
218
218
  })
219
219
  }
220
220
 
221
- async doesAppliedTransactionExist(tx: { txid: string, topic: string }): Promise<boolean> {
221
+ async doesAppliedTransactionExist (tx: { txid: string, topic: string }): Promise<boolean> {
222
222
  const result = await this.knex('applied_transactions')
223
223
  .where({ txid: tx.txid, topic: tx.topic })
224
224
  .select(this.knex.raw('1'))
@@ -7,7 +7,7 @@ import { up as addedIndexesUp, down as addedIndexesDown } from './migrations/202
7
7
  /**
8
8
  * An array of all migrations, in order.
9
9
  */
10
- type Migration = {
10
+ interface Migration {
11
11
  up: (knex: Knex) => Promise<void>
12
12
  down: (knex: Knex) => Promise<void>
13
13
  }
@@ -1,6 +1,6 @@
1
1
  import type { Knex } from 'knex'
2
2
 
3
- export async function up(knex: Knex): Promise<void> {
3
+ export async function up (knex: Knex): Promise<void> {
4
4
  await knex.schema.createTable('outputs', table => {
5
5
  table.increments()
6
6
  table.string('txid', 64)
@@ -24,7 +24,7 @@ export async function up(knex: Knex): Promise<void> {
24
24
  })
25
25
  }
26
26
 
27
- export async function down(knex: Knex): Promise<void> {
27
+ export async function down (knex: Knex): Promise<void> {
28
28
  await knex.schema.dropTable('applied_transactions')
29
29
  await knex.schema.dropTable('outputs')
30
30
  }
@@ -1,13 +1,13 @@
1
1
  import type { Knex } from 'knex'
2
2
 
3
- export async function up(knex: Knex): Promise<void> {
3
+ export async function up (knex: Knex): Promise<void> {
4
4
  // Add new column for blockHeight associated with outputs
5
5
  await knex.schema.table('outputs', table => {
6
6
  table.integer('blockHeight').unsigned().nullable()
7
7
  })
8
8
  }
9
9
 
10
- export async function down(knex: Knex): Promise<void> {
10
+ export async function down (knex: Knex): Promise<void> {
11
11
  // Remove the blockHeight column (rollback operation)
12
12
  await knex.schema.table('outputs', table => {
13
13
  table.dropColumn('blockHeight')
@@ -1,6 +1,6 @@
1
1
  import type { Knex } from 'knex'
2
2
 
3
- export async function up(knex: Knex): Promise<void> {
3
+ export async function up (knex: Knex): Promise<void> {
4
4
  // Create the new transactions table
5
5
  await knex.schema.createTable('transactions', table => {
6
6
  table.increments()
@@ -22,7 +22,7 @@ export async function up(knex: Knex): Promise<void> {
22
22
  })
23
23
  }
24
24
 
25
- export async function down(knex: Knex): Promise<void> {
25
+ export async function down (knex: Knex): Promise<void> {
26
26
  // Add the beef column back to the outputs table
27
27
  await knex.schema.table('outputs', table => {
28
28
  table.binary('beef')
@@ -1,5 +1,5 @@
1
1
  import type { Knex } from 'knex'
2
- export async function up(knex: Knex): Promise<void> {
2
+ export async function up (knex: Knex): Promise<void> {
3
3
  // Add index for applied_transactions table
4
4
  await knex.schema.table('applied_transactions', function (table) {
5
5
  table.index(['txid', 'topic'], 'idx_applied_transactions_txid_topic')
@@ -14,7 +14,7 @@ export async function up(knex: Knex): Promise<void> {
14
14
  })
15
15
  }
16
16
 
17
- export async function down(knex: Knex): Promise<void> {
17
+ export async function down (knex: Knex): Promise<void> {
18
18
  // Drop index for applied_transactions table
19
19
  await knex.schema.table('applied_transactions', function (table) {
20
20
  table.dropIndex(['txid', 'topic'], 'idx_applied_transactions_txid_topic')