@bsv/overlay 2.2.1 → 2.2.7

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 (151) hide show
  1. package/LICENSE.txt +57 -27
  2. package/README.md +102 -269
  3. package/dist/cjs/mod.d.ts +15 -0
  4. package/dist/cjs/mod.d.ts.map +1 -0
  5. package/dist/cjs/mod.js +4 -1
  6. package/dist/cjs/mod.js.map +1 -1
  7. package/dist/cjs/package.json +41 -13
  8. package/dist/cjs/src/Advertisement.d.ts +9 -0
  9. package/dist/cjs/src/Advertisement.d.ts.map +1 -0
  10. package/dist/cjs/src/Advertiser.d.ts +36 -0
  11. package/dist/cjs/src/Advertiser.d.ts.map +1 -0
  12. package/dist/cjs/src/BASM.d.ts +110 -0
  13. package/dist/cjs/src/BASM.d.ts.map +1 -0
  14. package/dist/cjs/src/BASM.js.map +1 -1
  15. package/dist/cjs/src/BASMRemote.d.ts +14 -0
  16. package/dist/cjs/src/BASMRemote.d.ts.map +1 -0
  17. package/dist/cjs/src/BASMRemote.js.map +1 -1
  18. package/dist/cjs/src/Engine.d.ts +377 -0
  19. package/dist/cjs/src/Engine.d.ts.map +1 -0
  20. package/dist/cjs/src/Engine.js +416 -417
  21. package/dist/cjs/src/Engine.js.map +1 -1
  22. package/dist/cjs/src/GASP/OverlayGASPRemote.d.ts +24 -0
  23. package/dist/cjs/src/GASP/OverlayGASPRemote.d.ts.map +1 -0
  24. package/dist/cjs/src/GASP/OverlayGASPRemote.js +7 -10
  25. package/dist/cjs/src/GASP/OverlayGASPRemote.js.map +1 -1
  26. package/dist/cjs/src/GASP/OverlayGASPStorage.d.ts +103 -0
  27. package/dist/cjs/src/GASP/OverlayGASPStorage.d.ts.map +1 -0
  28. package/dist/cjs/src/GASP/OverlayGASPStorage.js +32 -30
  29. package/dist/cjs/src/GASP/OverlayGASPStorage.js.map +1 -1
  30. package/dist/cjs/src/LookupFormula.d.ts +29 -0
  31. package/dist/cjs/src/LookupFormula.d.ts.map +1 -0
  32. package/dist/cjs/src/LookupService.d.ts +85 -0
  33. package/dist/cjs/src/LookupService.d.ts.map +1 -0
  34. package/dist/cjs/src/Output.d.ts +32 -0
  35. package/dist/cjs/src/Output.d.ts.map +1 -0
  36. package/dist/cjs/src/SafeLog.d.ts +14 -0
  37. package/dist/cjs/src/SafeLog.d.ts.map +1 -0
  38. package/dist/cjs/src/SafeLog.js +44 -0
  39. package/dist/cjs/src/SafeLog.js.map +1 -0
  40. package/{src/SyncConfiguration.ts → dist/cjs/src/SyncConfiguration.d.ts} +2 -1
  41. package/dist/cjs/src/SyncConfiguration.d.ts.map +1 -0
  42. package/dist/cjs/src/TopicManager.d.ts +35 -0
  43. package/dist/cjs/src/TopicManager.d.ts.map +1 -0
  44. package/dist/cjs/src/storage/Storage.d.ts +237 -0
  45. package/dist/cjs/src/storage/Storage.d.ts.map +1 -0
  46. package/dist/cjs/src/storage/knex/KnexStorage.d.ts +69 -0
  47. package/dist/cjs/src/storage/knex/KnexStorage.d.ts.map +1 -0
  48. package/dist/cjs/src/storage/knex/KnexStorage.js +7 -10
  49. package/dist/cjs/src/storage/knex/KnexStorage.js.map +1 -1
  50. package/dist/cjs/src/storage/knex/all-migrations.d.ts +11 -0
  51. package/dist/cjs/src/storage/knex/all-migrations.d.ts.map +1 -0
  52. package/dist/cjs/src/storage/knex/all-migrations.js.map +1 -1
  53. package/dist/cjs/src/storage/knex/migrations/2024-05-18-001-initial.d.ts +4 -0
  54. package/dist/cjs/src/storage/knex/migrations/2024-05-18-001-initial.d.ts.map +1 -0
  55. package/dist/cjs/src/storage/knex/migrations/2024-05-18-001-initial.js.map +1 -1
  56. package/dist/cjs/src/storage/knex/migrations/2024-07-10-001-block-height.d.ts +4 -0
  57. package/dist/cjs/src/storage/knex/migrations/2024-07-10-001-block-height.d.ts.map +1 -0
  58. package/dist/cjs/src/storage/knex/migrations/2024-07-10-001-block-height.js.map +1 -1
  59. package/dist/cjs/src/storage/knex/migrations/2024-07-17-001-transactions.d.ts +4 -0
  60. package/dist/cjs/src/storage/knex/migrations/2024-07-17-001-transactions.d.ts.map +1 -0
  61. package/dist/cjs/src/storage/knex/migrations/2024-07-17-001-transactions.js.map +1 -1
  62. package/dist/cjs/src/storage/knex/migrations/2024-07-18-001-indexes.d.ts +4 -0
  63. package/dist/cjs/src/storage/knex/migrations/2024-07-18-001-indexes.d.ts.map +1 -0
  64. package/dist/cjs/src/storage/knex/migrations/2024-07-18-001-indexes.js.map +1 -1
  65. package/dist/cjs/src/storage/knex/migrations/2025-05-28-001-enlarge.d.ts +4 -0
  66. package/dist/cjs/src/storage/knex/migrations/2025-05-28-001-enlarge.d.ts.map +1 -0
  67. package/dist/cjs/src/storage/knex/migrations/2025-05-28-001-enlarge.js.map +1 -1
  68. package/dist/cjs/src/storage/knex/migrations/2025-06-25-001-gasp-pagination-support.d.ts +4 -0
  69. package/dist/cjs/src/storage/knex/migrations/2025-06-25-001-gasp-pagination-support.d.ts.map +1 -0
  70. package/dist/cjs/src/storage/knex/migrations/2025-06-25-001-gasp-pagination-support.js.map +1 -1
  71. package/dist/cjs/src/storage/knex/migrations/2025-07-22-001-fix-score-column-type.d.ts +4 -0
  72. package/dist/cjs/src/storage/knex/migrations/2025-07-22-001-fix-score-column-type.d.ts.map +1 -0
  73. package/dist/cjs/src/storage/knex/migrations/2025-07-22-001-fix-score-column-type.js.map +1 -1
  74. package/dist/cjs/src/storage/knex/migrations/2025-11-11-001-utxo-lookup-index.d.ts +9 -0
  75. package/dist/cjs/src/storage/knex/migrations/2025-11-11-001-utxo-lookup-index.d.ts.map +1 -0
  76. package/dist/cjs/src/storage/knex/migrations/2025-11-11-001-utxo-lookup-index.js.map +1 -1
  77. package/dist/cjs/src/storage/knex/migrations/2026-05-29-001-brc136-basm.d.ts +4 -0
  78. package/dist/cjs/src/storage/knex/migrations/2026-05-29-001-brc136-basm.d.ts.map +1 -0
  79. package/dist/cjs/src/storage/knex/migrations/2026-05-29-001-brc136-basm.js.map +1 -1
  80. package/dist/esm/mod.js +2 -1
  81. package/dist/esm/mod.js.map +1 -1
  82. package/dist/esm/src/BASMRemote.js.map +1 -1
  83. package/dist/esm/src/Engine.js +394 -395
  84. package/dist/esm/src/Engine.js.map +1 -1
  85. package/dist/esm/src/GASP/OverlayGASPRemote.js +2 -2
  86. package/dist/esm/src/GASP/OverlayGASPRemote.js.map +1 -1
  87. package/dist/esm/src/GASP/OverlayGASPStorage.js +21 -18
  88. package/dist/esm/src/GASP/OverlayGASPStorage.js.map +1 -1
  89. package/dist/esm/src/SafeLog.js +40 -0
  90. package/dist/esm/src/SafeLog.js.map +1 -0
  91. package/dist/esm/src/storage/knex/KnexStorage.js.map +1 -1
  92. package/dist/types/mod.d.ts +5 -4
  93. package/dist/types/mod.d.ts.map +1 -1
  94. package/dist/types/src/BASMRemote.d.ts.map +1 -1
  95. package/dist/types/src/Engine.d.ts +15 -0
  96. package/dist/types/src/Engine.d.ts.map +1 -1
  97. package/dist/types/src/GASP/OverlayGASPRemote.d.ts +2 -2
  98. package/dist/types/src/GASP/OverlayGASPRemote.d.ts.map +1 -1
  99. package/dist/types/src/GASP/OverlayGASPStorage.d.ts +3 -1
  100. package/dist/types/src/GASP/OverlayGASPStorage.d.ts.map +1 -1
  101. package/dist/types/src/SafeLog.d.ts +14 -0
  102. package/dist/types/src/SafeLog.d.ts.map +1 -0
  103. package/dist/types/src/storage/knex/KnexStorage.d.ts.map +1 -1
  104. package/dist/types/src/storage/knex/all-migrations.d.ts.map +1 -1
  105. package/package.json +85 -28
  106. package/dist/cjs/tsconfig.cjs.tsbuildinfo +0 -1
  107. package/dist/esm/tsconfig.esm.tsbuildinfo +0 -1
  108. package/dist/types/tsconfig.types.tsbuildinfo +0 -1
  109. package/docs/API.md +0 -944
  110. package/docs/BRC-136-BASM.md +0 -327
  111. package/docs/README.md +0 -16
  112. package/docs/Synchronization.md +0 -212
  113. package/docs/concepts/00-overview.md +0 -85
  114. package/docs/concepts/01-best-practices.md +0 -202
  115. package/docs/concepts/02-query-performance.md +0 -345
  116. package/docs/concepts/03-database-monitoring.md +0 -211
  117. package/docs/concepts/04-pagination-example.md +0 -186
  118. package/docs/concepts/05-recommendations-summary.md +0 -158
  119. package/docs/concepts/README.md +0 -20
  120. package/docs/examples/README.md +0 -15
  121. package/docs/examples/gs-wip.md +0 -111
  122. package/docs/internal/README.md +0 -11
  123. package/mod.ts +0 -40
  124. package/src/Advertisement.ts +0 -8
  125. package/src/Advertiser.ts +0 -41
  126. package/src/BASM.ts +0 -208
  127. package/src/BASMRemote.ts +0 -54
  128. package/src/Engine.ts +0 -2194
  129. package/src/GASP/OverlayGASPRemote.ts +0 -108
  130. package/src/GASP/OverlayGASPStorage.ts +0 -384
  131. package/src/LookupFormula.ts +0 -31
  132. package/src/LookupService.ts +0 -136
  133. package/src/Output.ts +0 -31
  134. package/src/TopicManager.ts +0 -40
  135. package/src/__tests/BASM.test.ts +0 -44
  136. package/src/__tests/BASMChain.test.ts +0 -295
  137. package/src/__tests/Engine.test.ts +0 -1381
  138. package/src/__tests/OverlayGASPRemote.test.ts +0 -135
  139. package/src/__tests/OverlayGASPStorage.test.ts +0 -205
  140. package/src/storage/Storage.ts +0 -260
  141. package/src/storage/knex/KnexStorage.ts +0 -651
  142. package/src/storage/knex/all-migrations.ts +0 -32
  143. package/src/storage/knex/migrations/2024-05-18-001-initial.ts +0 -30
  144. package/src/storage/knex/migrations/2024-07-10-001-block-height.ts +0 -15
  145. package/src/storage/knex/migrations/2024-07-17-001-transactions.ts +0 -64
  146. package/src/storage/knex/migrations/2024-07-18-001-indexes.ts +0 -30
  147. package/src/storage/knex/migrations/2025-05-28-001-enlarge.ts +0 -42
  148. package/src/storage/knex/migrations/2025-06-25-001-gasp-pagination-support.ts +0 -46
  149. package/src/storage/knex/migrations/2025-07-22-001-fix-score-column-type.ts +0 -24
  150. package/src/storage/knex/migrations/2025-11-11-001-utxo-lookup-index.ts +0 -18
  151. package/src/storage/knex/migrations/2026-05-29-001-brc136-basm.ts +0 -123
@@ -1,135 +0,0 @@
1
- import { OverlayGASPRemote } from '../GASP/OverlayGASPRemote'
2
- import { GASPInitialRequest, GASPInitialResponse, GASPNode } from '@bsv/gasp'
3
-
4
- global.fetch = jest.fn(async () => {
5
- await Promise.resolve({
6
- ok: true,
7
- status: 200,
8
- json: async () => await Promise.resolve({})
9
- })
10
- }
11
- ) as jest.Mock
12
-
13
- describe('OverlayGASPRemote', () => {
14
- let overlayRemote: OverlayGASPRemote
15
-
16
- beforeEach(() => {
17
- overlayRemote = new OverlayGASPRemote('http://example.com', 'tm_test');
18
- (fetch as jest.Mock).mockClear()
19
- })
20
-
21
- describe('getInitialResponse', () => {
22
- it('should send a request and return a valid response', async () => {
23
- const mockRequest: GASPInitialRequest = { version: 1, since: 0 }
24
- const mockResponse: GASPInitialResponse = {
25
- UTXOList: [{ txid: 'txid1', outputIndex: 0, score: 0 }],
26
- since: 1234567890
27
- };
28
-
29
- (fetch as jest.Mock).mockResolvedValue({
30
- ok: true,
31
- status: 200,
32
- json: jest.fn().mockResolvedValue(mockResponse)
33
- })
34
-
35
- const response = await overlayRemote.getInitialResponse(mockRequest)
36
-
37
- expect(fetch).toHaveBeenCalledWith('http://example.com/requestSyncResponse', {
38
- method: 'POST',
39
- headers: {
40
- 'Content-Type': 'application/json',
41
- 'X-BSV-Topic': 'tm_test'
42
- },
43
- body: JSON.stringify(mockRequest)
44
- })
45
- expect(response).toEqual(mockResponse)
46
- })
47
-
48
- it('should throw an error if the response status is not OK', async () => {
49
- const mockRequest: GASPInitialRequest = { version: 1, since: 0 };
50
-
51
- (fetch as jest.Mock).mockResolvedValue({
52
- ok: false,
53
- status: 500
54
- })
55
-
56
- await expect(overlayRemote.getInitialResponse(mockRequest)).rejects.toThrow('HTTP error! Status: 500')
57
- })
58
-
59
- it('should throw an error if the response format is invalid', async () => {
60
- const mockRequest: GASPInitialRequest = { version: 1, since: 0 }
61
- const invalidResponse = { invalid: 'data' };
62
-
63
- (fetch as jest.Mock).mockResolvedValue({
64
- ok: true,
65
- status: 200,
66
- json: jest.fn().mockResolvedValue(invalidResponse)
67
- })
68
-
69
- await expect(overlayRemote.getInitialResponse(mockRequest)).rejects.toThrow('Invalid response format')
70
- })
71
- })
72
-
73
- describe('requestNode', () => {
74
- it('should send a request and return a valid GASPNode', async () => {
75
- const graphID = 'graphID1'
76
- const txid = 'txid1'
77
- const outputIndex = 0
78
- const metadata = true
79
- const mockResponse: GASPNode = {
80
- graphID,
81
- rawTx: 'rawTxData',
82
- outputIndex,
83
- proof: 'proofData',
84
- txMetadata: 'txMetadata',
85
- outputMetadata: 'outputMetadata',
86
- inputs: {}
87
- };
88
-
89
- (fetch as jest.Mock).mockResolvedValue({
90
- ok: true,
91
- status: 200,
92
- json: jest.fn().mockResolvedValue(mockResponse)
93
- })
94
-
95
- const response = await overlayRemote.requestNode(graphID, txid, outputIndex, metadata)
96
-
97
- expect(fetch).toHaveBeenCalledWith('http://example.com/requestForeignGASPNode', {
98
- method: 'POST',
99
- headers: { 'Content-Type': 'application/json' },
100
- body: JSON.stringify({ graphID, txid, outputIndex, metadata })
101
- })
102
- expect(response).toEqual(mockResponse)
103
- })
104
-
105
- it('should throw an error if the response status is not OK', async () => {
106
- const graphID = 'graphID1'
107
- const txid = 'txid1'
108
- const outputIndex = 0
109
- const metadata = true;
110
-
111
- (fetch as jest.Mock).mockResolvedValue({
112
- ok: false,
113
- status: 500
114
- })
115
-
116
- await expect(overlayRemote.requestNode(graphID, txid, outputIndex, metadata)).rejects.toThrow('HTTP error! Status: 500')
117
- })
118
-
119
- it('should throw an error if the response format is invalid', async () => {
120
- const graphID = 'graphID1'
121
- const txid = 'txid1'
122
- const outputIndex = 0
123
- const metadata = true
124
- const invalidResponse = { invalid: 'data' };
125
-
126
- (fetch as jest.Mock).mockResolvedValue({
127
- ok: true,
128
- status: 200,
129
- json: jest.fn().mockResolvedValue(invalidResponse)
130
- })
131
-
132
- await expect(overlayRemote.requestNode(graphID, txid, outputIndex, metadata)).rejects.toThrow('Invalid response format')
133
- })
134
- })
135
- })
@@ -1,205 +0,0 @@
1
- import { GraphNode, OverlayGASPStorage } from '../GASP/OverlayGASPStorage'
2
- import { Transaction, MerklePath } from '@bsv/sdk'
3
- import { GASPNode } from '@bsv/gasp'
4
-
5
- describe('OverlayGASPStorage', () => {
6
- let overlayStorage: OverlayGASPStorage
7
- let mockEngine: any
8
-
9
- beforeEach(() => {
10
- mockEngine = { storage: { findOutput: jest.fn(() => undefined), findUTXOsForTopic: jest.fn() }, managers: {} }
11
- overlayStorage = new OverlayGASPStorage('test-topic', mockEngine)
12
- })
13
-
14
- describe('appendToGraph', () => {
15
- it('should append a new node to an empty graph', async () => {
16
- const mockTx = {
17
- rawTx: '001122',
18
- outputIndex: 0,
19
- graphID: 'txid123.0'
20
- }
21
-
22
- // Use actual Transaction implementation
23
- const parsedTx = Transaction.fromHex(mockTx.rawTx)
24
-
25
- await overlayStorage.appendToGraph(mockTx)
26
-
27
- expect(Object.keys(overlayStorage.temporaryGraphNodeRefs).length).toBe(1)
28
- expect(overlayStorage.temporaryGraphNodeRefs['txid123.0'].txid).toBe(parsedTx.id('hex'))
29
- })
30
-
31
- it('throws error when max nodes are exceeded', async () => {
32
- overlayStorage.maxNodesInGraph = 1
33
- const graphNode: GraphNode = { txid: 'txid123', children: [], rawTx: '', graphID: 'txid4321.2', outputIndex: 0 }
34
- overlayStorage.temporaryGraphNodeRefs['txid123.0'] = graphNode
35
-
36
- const mockTx = {
37
- rawTx: '334455',
38
- outputIndex: 1,
39
- graphID: 'txid234.1'
40
- }
41
-
42
- await expect(overlayStorage.appendToGraph(mockTx)).rejects.toThrow('The max number of nodes in transaction graph has been reached!')
43
- })
44
- })
45
-
46
- describe('findKnownUTXOs', () => {
47
- it('should return known UTXOs since a given timestamp', async () => {
48
- const mockUTXOs = [{ txid: 'txid1', outputIndex: 0, score: 0 }, { txid: 'txid2', outputIndex: 1, score: 0 }]
49
- mockEngine.storage.findUTXOsForTopic.mockResolvedValue(mockUTXOs)
50
-
51
- const result = await overlayStorage.findKnownUTXOs(1234567890)
52
-
53
- expect(result).toEqual([
54
- { txid: 'txid1', outputIndex: 0, score: 0 },
55
- { txid: 'txid2', outputIndex: 1, score: 0 }
56
- ])
57
- expect(mockEngine.storage.findUTXOsForTopic).toHaveBeenCalledWith('test-topic', 1234567890)
58
- })
59
-
60
- it('should handle errors correctly', async () => {
61
- mockEngine.storage.findUTXOsForTopic.mockRejectedValue(new Error('Database error'))
62
-
63
- await expect(overlayStorage.findKnownUTXOs(1234567890)).rejects.toThrow('Database error')
64
- })
65
- })
66
-
67
- describe('hydrateGASPNode', () => {
68
- it('should throw an error if no output is found', async () => {
69
- await expect(overlayStorage.hydrateGASPNode('graphID', 'txid', 0, false)).rejects.toThrow('No matching output found!')
70
- })
71
- // TODO: Further test coverage
72
- })
73
-
74
- describe('findNeededInputs', () => {
75
- // TODO: Write more complicated test cases
76
- it('should return inputs needed for further verification when no proof is present', async () => {
77
- const mockTx: GASPNode = {
78
- rawTx: '001122',
79
- proof: undefined,
80
- graphID: 'txid123.0',
81
- outputIndex: 0
82
- }
83
-
84
- const parsedTx = {
85
- inputs: [{ sourceTXID: 'inputTxid1', sourceOutputIndex: 0 }],
86
- toBEEF: jest.fn(),
87
- id: jest.fn().mockReturnValue('txid123')
88
- }
89
- Transaction.fromHex = jest.fn().mockReturnValue(parsedTx)
90
-
91
- const result = await overlayStorage.findNeededInputs(mockTx)
92
-
93
- expect(result).toEqual({
94
- requestedInputs: { 'inputTxid1.0': { metadata: false } }
95
- })
96
- })
97
-
98
- it('should return inputs needed for further verification when proof is present', async () => {
99
- const mockTx: GASPNode = {
100
- rawTx: '001122',
101
- proof: 'someproof',
102
- graphID: 'txid123.0',
103
- outputIndex: 0
104
- }
105
-
106
- const parsedTx = {
107
- inputs: [{ sourceTXID: 'neededTxid', sourceOutputIndex: 1 }],
108
- toBEEF: jest.fn(),
109
- id: jest.fn().mockReturnValue('txid123'),
110
- merklePath: {}
111
- }
112
- Transaction.fromHex = jest.fn().mockReturnValue(parsedTx)
113
- MerklePath.fromHex = jest.fn().mockReturnValue(parsedTx.merklePath)
114
-
115
- mockEngine.managers['test-topic'] = {
116
- identifyAdmissibleOutputs: jest.fn().mockResolvedValue({
117
- outputsToAdmit: []
118
- }),
119
- identifyNeededInputs: jest.fn().mockResolvedValue([{ txid: 'neededTxid', outputIndex: 1 }])
120
- }
121
-
122
- const result = await overlayStorage.findNeededInputs(mockTx)
123
-
124
- expect(result).toEqual({
125
- requestedInputs: { 'neededTxid.1': { metadata: false } }
126
- })
127
- })
128
-
129
- it.each([
130
- [new Error('manager failed'), 'manager failed'],
131
- ['manager failed as a string', 'manager failed as a string']
132
- ])('terminates the graph and logs normalized identifyNeededInputs errors', async (failure, message) => {
133
- const mockTx: GASPNode = {
134
- rawTx: '001122',
135
- proof: 'someproof',
136
- graphID: 'txid123.0',
137
- outputIndex: 0
138
- }
139
- const parsedTx = {
140
- inputs: [],
141
- toBEEF: jest.fn().mockReturnValue([1, 2, 3]),
142
- id: jest.fn().mockReturnValue('txid123'),
143
- merklePath: {}
144
- }
145
- Transaction.fromHex = jest.fn().mockReturnValue(parsedTx)
146
- MerklePath.fromHex = jest.fn().mockReturnValue(parsedTx.merklePath)
147
- mockEngine.managers['test-topic'] = {
148
- identifyAdmissibleOutputs: jest.fn().mockResolvedValue({
149
- outputsToAdmit: []
150
- }),
151
- identifyNeededInputs: jest.fn().mockRejectedValue(failure)
152
- }
153
- const consoleError = jest.spyOn(console, 'error').mockImplementation(() => {})
154
-
155
- await expect(overlayStorage.findNeededInputs(mockTx)).resolves.toBeUndefined()
156
-
157
- expect(consoleError).toHaveBeenCalledWith(
158
- `An error occurred when identifying needed inputs for transaction: txid123.0: ${message}`
159
- )
160
- consoleError.mockRestore()
161
- })
162
- })
163
-
164
- describe('discardGraph', () => {
165
- it('should discard the graph and its nodes', async () => {
166
- const graphNode1: GraphNode = {
167
- txid: 'txid123',
168
- graphID: 'txid123.0',
169
- rawTx: 'rawTxData',
170
- outputIndex: 0,
171
- children: [],
172
- parent: undefined
173
- }
174
- overlayStorage.temporaryGraphNodeRefs['txid123.0'] = graphNode1
175
-
176
- const parentNode: GraphNode = {
177
- txid: 'txid123',
178
- graphID: 'txid123.0',
179
- rawTx: 'rawTxData',
180
- outputIndex: 0,
181
- children: []
182
- }
183
- const graphNode2: GraphNode = {
184
- txid: 'txid124',
185
- graphID: 'txid123.0',
186
- rawTx: 'rawTxData',
187
- outputIndex: 1,
188
- children: [],
189
- parent: parentNode
190
- }
191
- overlayStorage.temporaryGraphNodeRefs['txid124.0'] = graphNode2
192
-
193
- await overlayStorage.discardGraph('txid123.0')
194
-
195
- expect(overlayStorage.temporaryGraphNodeRefs['txid123.0']).toBeUndefined()
196
- expect(overlayStorage.temporaryGraphNodeRefs['txid124.0']).toBeUndefined()
197
- })
198
- })
199
-
200
- it('should handle non-existent graphID', async () => {
201
- await overlayStorage.discardGraph('nonexistent.0')
202
-
203
- expect(Object.keys(overlayStorage.temporaryGraphNodeRefs).length).toBe(0)
204
- })
205
- })
@@ -1,260 +0,0 @@
1
- import type { Output } from '../Output.js'
2
- import type {
3
- AdmittedTxRef,
4
- RawTransactionRecord,
5
- TopicAnchorTip,
6
- TopicBlockAnchor
7
- } from '../BASM.js'
8
-
9
- /**
10
- * Represents a transaction that has been applied to a topic.
11
- */
12
- export interface AppliedTransaction {
13
- /** TXID of the applied transaction */
14
- txid: string
15
- /** Output index of the applied transaction */
16
- topic: string
17
- /** Block height of the transaction proof, when known */
18
- blockHeight?: number
19
- /** Block hash for the proven transaction's block, when known */
20
- blockHash?: string
21
- /** Transaction's canonical in-block index, when known */
22
- blockIndex?: number
23
- /** Merkle root computed from the direct proof, when known */
24
- merkleRoot?: string
25
- /** Chain height when this transaction was first seen by this overlay */
26
- firstSeenHeight?: number
27
- /** Whether this applied transaction has a direct proof of inclusion */
28
- proven?: boolean
29
- }
30
-
31
- export interface StoredTransactionRecord {
32
- txid: string
33
- beef?: number[]
34
- rawTx?: number[]
35
- merklePath?: number[]
36
- blockHeight?: number
37
- blockHash?: string
38
- blockIndex?: number
39
- merkleRoot?: string
40
- }
41
-
42
- export interface AppliedTransactionProofUpdate {
43
- txid: string
44
- topic: string
45
- blockHeight: number
46
- blockHash?: string
47
- blockIndex?: number
48
- merkleRoot?: string
49
- }
50
-
51
- export interface UnprovenAppliedTransactionCandidate {
52
- txid: string
53
- topic: string
54
- firstSeenHeight?: number
55
- outputs: Array<{ txid: string, outputIndex: number }>
56
- }
57
-
58
- /**
59
- * Defines the Storage Engine interface used internally by the Overlay Services Engine.
60
- */
61
- export interface Storage {
62
- /**
63
- * Adds a new output to storage
64
- * @param utxo — The output to add
65
- */
66
- insertOutput: (utxo: Output) => Promise<void>
67
-
68
- /**
69
- * Finds an output from storage
70
- * @param txid — TXID of hte output to find
71
- * @param outputIndex — Output index for the output to find
72
- * @param topic — The topic in which the output is stored (optional)
73
- * @param spent — Whether the output must be spent to be returned (optional)
74
- * @param includeBEEF — Whether to include the BEEF data for the output (optional)
75
- */
76
- findOutput: (txid: string, outputIndex: number, topic?: string, spent?: boolean, includeBEEF?: boolean) => Promise<Output | null>
77
-
78
- /**
79
- * Finds multiple outputs from storage by txid/output index pairs.
80
- * Implementations can use this to collapse many point lookups into a single query.
81
- * @param outpoints — txid/output index pairs to find
82
- * @param includeBEEF — Whether to include the BEEF data for the outputs (optional)
83
- */
84
- findOutputsByOutpoints?: (
85
- outpoints: Array<{ txid: string, outputIndex: number }>,
86
- includeBEEF?: boolean
87
- ) => Promise<Output[]>
88
-
89
- /**
90
- * Finds outputs with a matching transaction ID from storage
91
- * @param txid — TXID of the outputs to find
92
- * @param includeBEEF — Whether to include the BEEF data for the outputs (optional)
93
- */
94
- findOutputsForTransaction: (txid: string, includeBEEF?: boolean) => Promise<Output[]>
95
-
96
- /**
97
- * Finds current UTXOs that have been admitted into a given topic
98
- * @param topic - The topic for which we want to find Unspent Transaction Outputs (UTXOs).
99
- * @param since - Optional parameter indicating the minimum score value to retrieve matching UTXOs from. This is used for score-based filtering.
100
- * @param limit - Optional parameter to limit the number of results returned
101
- * @param includeBEEF — Whether to include the BEEF data for the outputs (optional)
102
- * @returns A promise that resolves to an array of matching UTXOs.
103
- */
104
- findUTXOsForTopic: (topic: string, since?: number, limit?: number, includeBEEF?: boolean) => Promise<Output[]>
105
-
106
- /**
107
- * Deletes an output from storage
108
- * @param txid — The TXID of the output to delete
109
- * @param outputIndex — The index of the output to delete
110
- * @param topic — The topic where the output should be deleted
111
- */
112
- deleteOutput: (txid: string, outputIndex: number, topic: string) => Promise<void>
113
-
114
- /**
115
- * Updates a UTXO as spent
116
- * @param txid — TXID of the output to update
117
- * @param outputIndex — Index of the output to update
118
- * @param topic — Topic in which the output should be updated
119
- */
120
- markUTXOAsSpent: (txid: string, outputIndex: number, topic: string) => Promise<void>
121
-
122
- /**
123
- * Updates which outputs are consumed by this output
124
- * @param txid — TXID of the output to update
125
- * @param outputIndex — Index of the output to update
126
- * @param topic — Topic in which the output should be updated
127
- * @param consumedBy — The new set of outputs consumed by this output
128
- */
129
- updateConsumedBy: (txid: string, outputIndex: number, topic: string, consumedBy: Array<{
130
- txid: string
131
- outputIndex: number
132
- }>) => Promise<void>
133
-
134
- /**
135
- * Updates the beef data for a transaction
136
- * @param txid — TXID of the transaction to update
137
- * @param beef - BEEF data to update
138
- */
139
- updateTransactionBEEF: (txid: string, beef: number[]) => Promise<void>
140
-
141
- /**
142
- * Updates the block height on an output
143
- * @param txid — TXID of the output to update
144
- * @param outputIndex — Index of the output to update
145
- * @param topic— Topic in which the output should be updated
146
- * @param blockHeight - height of the block the transaction associated with this output was included in
147
- */
148
- updateOutputBlockHeight?: (txid: string, outputIndex: number, topic: string, blockHeight: number) => Promise<void>
149
-
150
- /**
151
- * Upserts transaction-level data used for compact BEEF, raw-tx BASM fetches,
152
- * and direct proof retrieval.
153
- */
154
- upsertTransactionRecord?: (record: StoredTransactionRecord) => Promise<void>
155
-
156
- /**
157
- * Updates direct proof metadata for an applied topic transaction.
158
- */
159
- updateAppliedTransactionProof?: (record: AppliedTransactionProofUpdate) => Promise<void>
160
-
161
- /**
162
- * Inserts record of the applied transaction
163
- * @param tx — The transaction to insert
164
- */
165
- insertAppliedTransaction: (tx: AppliedTransaction) => Promise<void>
166
-
167
- /**
168
- * Checks if a duplicate transaction exists
169
- * @param tx — Transaction to check
170
- * @returns Whether the transaction is already applied
171
- */
172
- doesAppliedTransactionExist: (tx: AppliedTransaction) => Promise<boolean>
173
-
174
- /**
175
- * Returns proven topic transactions admitted in one block, in canonical block order.
176
- */
177
- findAdmittedTransactionsForBlock?: (topic: string, blockHeight: number, blockHash?: string) => Promise<AdmittedTxRef[]>
178
-
179
- /**
180
- * Persists or replaces a topic block anchor for one height.
181
- */
182
- upsertTopicBlockAnchor?: (anchor: TopicBlockAnchor) => Promise<void>
183
-
184
- /**
185
- * Returns one topic block anchor.
186
- */
187
- findTopicBlockAnchor?: (topic: string, blockHeight: number, blockHash?: string) => Promise<TopicBlockAnchor | undefined>
188
-
189
- /**
190
- * Returns topic block anchors across a closed height range.
191
- */
192
- findTopicBlockAnchors?: (topic: string, fromHeight: number, toHeight: number) => Promise<TopicBlockAnchor[]>
193
-
194
- /**
195
- * Returns the latest known topic anchor tip.
196
- */
197
- findTopicAnchorTip?: (topic: string) => Promise<TopicAnchorTip | undefined>
198
-
199
- /**
200
- * Returns raw transactions for the requested txids.
201
- */
202
- findRawTransactions?: (txids: string[]) => Promise<RawTransactionRecord[]>
203
-
204
- /**
205
- * Returns direct Merkle paths for the requested txids.
206
- */
207
- findTransactionMerklePaths?: (txids: string[]) => Promise<Array<{
208
- txid: string
209
- merklePath: string
210
- blockHeight?: number
211
- blockHash?: string
212
- blockIndex?: number
213
- merkleRoot?: string
214
- }>>
215
-
216
- /**
217
- * Finds topic-applied transactions with no direct proof old enough to evict.
218
- */
219
- findUnprovenAppliedTransactions?: (cutoffHeight: number, topic?: string) => Promise<UnprovenAppliedTransactionCandidate[]>
220
-
221
- /**
222
- * Deletes a topic-applied transaction record.
223
- */
224
- deleteAppliedTransaction?: (txid: string, topic: string) => Promise<void>
225
-
226
- /**
227
- * Returns proven topic-applied transactions whose proof anchors to the given
228
- * block hash. Used to demote admissions when that block is reorged out.
229
- */
230
- findProvenAppliedTransactionsByBlockHash?: (blockHash: string) => Promise<Array<{ txid: string, topic: string, blockHeight: number }>>
231
-
232
- /**
233
- * Returns proven topic-applied transactions in a closed block-height range,
234
- * including the proof's block hash and merkle root for revalidation sweeps.
235
- */
236
- findProvenAppliedTransactionsInRange?: (fromHeight: number, toHeight: number, topic?: string) => Promise<Array<{ txid: string, topic: string, blockHeight: number, blockHash?: string, merkleRoot?: string }>>
237
-
238
- /**
239
- * Demotes a proven applied transaction back to unproven: clears the block
240
- * proof metadata and `proven` flag while retaining `firstSeenHeight`, so the
241
- * "received" record survives until re-proof or unproven eviction.
242
- */
243
- demoteAppliedTransactionToUnproven?: (txid: string, topic: string) => Promise<void>
244
-
245
- /**
246
- * Updates the last interaction score for a given host and topic
247
- * @param host — The host identifier
248
- * @param topic — The topic for which to update the interaction score
249
- * @param since — The score value to store
250
- */
251
- updateLastInteraction: (host: string, topic: string, since: number) => Promise<void>
252
-
253
- /**
254
- * Retrieves the last interaction score for a given host and topic
255
- * @param host — The host identifier
256
- * @param topic — The topic to query
257
- * @returns The last interaction score, or 0 if not found
258
- */
259
- getLastInteraction: (host: string, topic: string) => Promise<number>
260
- }