@bsv/overlay 0.1.13 → 0.1.15

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.
@@ -7,6 +7,8 @@ import { Storage } from '../storage/Storage'
7
7
  import { Transaction, Utils } from '@bsv/sdk'
8
8
  import { Output } from '../Output'
9
9
  import { SyncConfiguration } from '../SyncConfiguration'
10
+ import { TaggedBEEF } from '../TaggedBEEF.js'
11
+ import { Advertiser } from '../Advertiser.js'
10
12
 
11
13
  const mockChainTracker = {
12
14
  isValidRootForHeight: jest.fn(async () => true)
@@ -24,13 +26,37 @@ const mockOutput: Output = {
24
26
  outputIndex: 0,
25
27
  outputScript: exampleTX.outputs[0].lockingScript.toBinary(),
26
28
  topic: 'hello',
27
- satoshis: exampleTX.outputs[0].satoshis,
29
+ satoshis: exampleTX.outputs[0].satoshis as number,
28
30
  beef: exampleBeef,
29
31
  spent: false,
30
32
  outputsConsumed: [],
31
33
  consumedBy: []
32
34
  }
33
35
 
36
+ const invalidHostingUrls = [
37
+ "http://example.com", // Invalid: http
38
+ "https://localhost:3000", // Invalid: localhost
39
+ "https://192.168.1.1", // Invalid: internal private IP
40
+ "https://127.0.0.1", // Invalid: loopback IP
41
+ "https://0.0.0.0", // Invalid: non-routable IP
42
+ "http://172.16.0.1", // Invalid: private IP
43
+ "[::1]"
44
+ ]
45
+
46
+
47
+ const validHostingUrls = [
48
+ "https://example.com", // Valid: public URL
49
+ "https://8.8.8.8", // Valid: public routable IP
50
+ "https://255.255.255.255", // Valid: public routable IP
51
+ ]
52
+
53
+ const mockAdvertiser: Advertiser = {
54
+ createAdvertisements: jest.fn(async (): Promise<TaggedBEEF> => ({ beef: [0, 1, 2], topics: [] })),
55
+ revokeAdvertisements: jest.fn(async (): Promise<TaggedBEEF> => ({ beef: [0, 1, 2], topics: [] })),
56
+ findAllAdvertisements: jest.fn(async () => []),
57
+ parseAdvertisement: jest.fn()
58
+ }
59
+
34
60
  describe('BSV Overlay Services Engine', () => {
35
61
  beforeEach(() => {
36
62
  jest.clearAllMocks()
@@ -66,6 +92,74 @@ describe('BSV Overlay Services Engine', () => {
66
92
  findUTXOsForTopic: jest.fn()
67
93
  }
68
94
  })
95
+
96
+ it('engine.syncAdvertisements should return void when invalid hostingURL is provided', async () => {
97
+ for (const url of invalidHostingUrls) {
98
+ const engine = new Engine(
99
+ { tm_helloworld: mockTopicManager },
100
+ { ls_helloworld: mockLookupService },
101
+ mockStorageEngine,
102
+ mockChainTracker,
103
+ url, // Invalid hostingURL
104
+ ['tracker1'], // shipTrackers
105
+ ['tracker2'], // slapTrackers
106
+ undefined,
107
+ mockAdvertiser,
108
+ undefined
109
+ )
110
+
111
+ engine.submit = jest.fn(async (taggedBEEF: TaggedBEEF, onSteakReady: any, mode?: string) => ({ outputsToAdmit: [] }))
112
+
113
+ // Call the method that would normally trigger syncAdvertisements
114
+ const result = await engine.syncAdvertisements()
115
+
116
+ expect(result).toBeUndefined()
117
+
118
+ // Verify that Advertiser methods are NOT called
119
+ expect(mockAdvertiser.createAdvertisements).not.toHaveBeenCalled()
120
+ expect(mockAdvertiser.findAllAdvertisements).not.toHaveBeenCalledWith('SHIP') // Assuming 'SHIP' is expected
121
+
122
+ console.log('Got past', url)
123
+ }
124
+ })
125
+
126
+ it('should allow engine.syncAdvertisements to proceed with valid hostingURLs', async () => {
127
+ const mockAdvertiser: Advertiser = {
128
+ createAdvertisements: jest.fn().mockResolvedValue({ tag: 'MOCK_TAG', data: Buffer.from('mock data') }),
129
+ findAllAdvertisements: jest.fn().mockResolvedValue([]),
130
+ revokeAdvertisements: jest.fn().mockResolvedValue({ tag: 'MOCK_REVOKE_TAG', data: Buffer.from('revocation data') }),
131
+ parseAdvertisement: jest.fn().mockReturnValue({
132
+ protocol: 'SHIP',
133
+ topicOrServiceName: 'mock-topic',
134
+ timestamp: Date.now(),
135
+ }),
136
+ }
137
+
138
+ for (const url of validHostingUrls) {
139
+ const engine = new Engine(
140
+ { tm_helloworld: mockTopicManager },
141
+ { ls_helloworld: mockLookupService },
142
+ mockStorageEngine,
143
+ mockChainTracker,
144
+ url, // Valid hostingURL
145
+ ['tracker1'], // shipTrackers
146
+ ['tracker2'], // slapTrackers
147
+ undefined,
148
+ mockAdvertiser, // Pass the mock Advertiser
149
+ undefined
150
+ )
151
+
152
+ // Call the method that would normally trigger syncAdvertisements
153
+ engine.submit = jest.fn(async (taggedBEEF: TaggedBEEF, onSteakReady: any, mode?: string) => ({ outputsToAdmit: [] }))
154
+ const result = await engine.syncAdvertisements()
155
+ expect(engine.submit).toHaveBeenCalled()
156
+
157
+ // Verify that Advertiser methods are called
158
+ expect(mockAdvertiser.createAdvertisements).toHaveBeenCalled()
159
+ expect(mockAdvertiser.findAllAdvertisements).toHaveBeenCalledWith('SHIP') // Assuming 'SHIP' is expected
160
+ }
161
+ })
162
+
69
163
  it('Uses SHIP sync configuration by default if no syncConfiguration was provided', () => {
70
164
  const engine = new Engine(
71
165
  { tm_helloworld: mockTopicManager },